Name

Tags

description

Collects all used tags and inserts them into a note you specify.

instructions

Install the plugin. Set an "Output Note Title" (without this, the plugin will fail).
If you choose an existing note title, the contents of that note will be overwritten, so be careful. If the note doesn't exist, it will be created.
If you leave the "Create Links" setting blank, tags will be output in plain text. If you enter 'y' or 'yes' , then each tag will be rendered as a search link to notes with that tag.
Output includes an H1 header: "All Tags (#)" where the # contains the count of tags found.
Note: this plugin can only count tags that are in use (applied to a note). I don't think there's a way to retrieve tags directly without getting them from an existing note.

setting

Output Note Title

setting

Create Links

{
noteOption: {
"List All Tags": async function(app, noteUUID) {
// 1) Read setting (required). If missing, alert & bail.
const outputTitle = (app.settings["Output Note Title"] || "").trim();
if (!outputTitle) {
await app.alert(
"No output note is set.\n\nPlease open plugin settings and provide an 'Output Note Title'."
);
return;
}
 
// read Create Links setting (defaults to "yes")
const createLinks = ((app.settings["Create Links"] || "no").trim().toLowerCase().startsWith("y"));
// 2) Fetch all notes (note handles include .tags)
const handles = await app.filterNotes({}); // no filters => all notes
 
// 3) Collect all tags (plus ancestor prefixes) into a Set
const tagSet = new Set();
for (const h of handles) {
const tags = Array.isArray(h.tags) ? h.tags : []; // safe default
for (const tag of tags) {
const clean = (tag || "").trim();
if (!clean) continue;
 
tagSet.add(clean);
 
// Add ancestors so "fruit/apple/red" implies "fruit" and "fruit/apple"
const parts = clean.split("/").filter(Boolean);
for (let i = 1; i < parts.length; i++) {
tagSet.add(parts.slice(0, i).join("/"));
}
}
}
 
// 4) Sort for natural parent→child grouping
const allTags = Array.from(tagSet).sort((a, b) => a.localeCompare(b));
 
// 5) Build Markdown: one link per line (keep "/" readable)
const toParam = (t) => encodeURIComponent(t).replace(/%2F/g, "/");
 
// Toggle between links or plain text
const lines = allTags.map(t =>
createLinks ? `[${t}](https://www.amplenote.com/notes/?tag=${toParam(t)})` : t
);
//const lines = allTags.map(t => `[${t}](https://www.amplenote.com/notes/?tag=${toParam(t)})`);
//const content = `# All Tags (${allTags.length})\n\n${lines.join("\n")}`;
 
// 6) Find/create destination note
let target = await app.findNote({ name: outputTitle });
let targetUUID;
if (!target) {
targetUUID = await app.createNote(outputTitle);
} else {
targetUUID = target.uuid;
}
 
// 7) Write a small header first (safe size)
const header = `# All Tags (${allTags.length})\n\n`;
await app.replaceNoteContent(targetUUID, header);
 
// 8) Append lines in chunks to avoid "markdownContent is too long"
// Keep each chunk under ~60k characters to be well below the sandbox limit.
const MAX_CHARS = 60000;
let buffer = "";
for (let i = 0; i < lines.length; i++) {
const line = lines[i] + "\n";
// If adding this line would exceed our chunk size, flush the buffer first
if (buffer.length + line.length > MAX_CHARS) {
await app.insertNoteContent({ uuid: targetUUID }, buffer, { atEnd: true });
buffer = "";
}
buffer += line;
}
// Flush any remaining lines
if (buffer.length > 0) {
await app.insertNoteContent({ uuid: targetUUID }, buffer, { atEnd: true });
}
}
}
}