From 19ad1c880f3e7f257a0d5e90628a9a4154499b59 Mon Sep 17 00:00:00 2001 From: Ole Eskild Steensen <6201338+oleeskild@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:10:59 +0200 Subject: [PATCH 1/4] feat(filetree): hide notes flagged dg-hide or dg-hide-in-filetree Co-Authored-By: Claude Opus 4.8 (1M context) --- src/helpers/filetreeUtils.js | 4 ++-- src/helpers/filetreeUtils.test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/helpers/filetreeUtils.js b/src/helpers/filetreeUtils.js index 493dd92e8..6350378b1 100644 --- a/src/helpers/filetreeUtils.js +++ b/src/helpers/filetreeUtils.js @@ -113,8 +113,8 @@ function getPermalinkMeta(note, key) { } // Reason for adding the hide flag instead of removing completely from file tree is to // allow users to use the filetree data elsewhere without the fear of losing any data. - if (note.data.hide) { - hide = note.data.hide; + if (note.data.hide || note.data.hideInFiletree) { + hide = true; } if (note.data.pinned) { pinned = note.data.pinned; diff --git a/src/helpers/filetreeUtils.test.js b/src/helpers/filetreeUtils.test.js index 03329044d..493e92a3e 100644 --- a/src/helpers/filetreeUtils.test.js +++ b/src/helpers/filetreeUtils.test.js @@ -231,4 +231,30 @@ describe("filetreeUtils", () => { expect(keys[1]).toBe("zebra.md"); }); }); + + describe("hide flags", () => { + it("does not hide a normal note", () => { + const data = { collections: { note: [makeNote("/normal")] } }; + const tree = getFileTree(data); + expect(tree["normal.md"].hide).toBeFalsy(); + }); + + it("hides a note with hide:true (dg-hide)", () => { + const data = { + collections: { note: [makeNote("/secret", { hide: true })] }, + }; + const tree = getFileTree(data); + expect(tree["secret.md"].hide).toBe(true); + }); + + it("hides a note with hideInFiletree:true (dg-hide-in-filetree)", () => { + const data = { + collections: { + note: [makeNote("/treeonly", { hideInFiletree: true })], + }, + }; + const tree = getFileTree(data); + expect(tree["treeonly.md"].hide).toBe(true); + }); + }); }); From 607261b05d5fb5309b59d24766c56ac50b9d4348 Mon Sep 17 00:00:00 2001 From: Ole Eskild Steensen <6201338+oleeskild@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:12:17 +0200 Subject: [PATCH 2/4] feat(graph): hide dg-hide notes from graph; tag them private for backlinks Co-Authored-By: Claude Opus 4.8 (1M context) --- src/helpers/linkUtils.js | 3 ++- src/helpers/linkUtils.test.js | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/helpers/linkUtils.test.js diff --git a/src/helpers/linkUtils.js b/src/helpers/linkUtils.js index 2753c5582..0a827f39c 100644 --- a/src/helpers/linkUtils.js +++ b/src/helpers/linkUtils.js @@ -131,7 +131,8 @@ async function getGraph(data) { neighbors: new Set(), backLinks: new Set(), noteIcon: v.data.noteIcon || process.env.NOTE_ICON_DEFAULT, - hide: v.data.hideInGraph || false, + hide: v.data.hide || v.data.hideInGraph || false, + private: v.data.hide || false, }; stemURLs[fpath] = v.url; if ( diff --git a/src/helpers/linkUtils.test.js b/src/helpers/linkUtils.test.js new file mode 100644 index 000000000..bd66cbf06 --- /dev/null +++ b/src/helpers/linkUtils.test.js @@ -0,0 +1,47 @@ +import { describe, it, expect } from "vitest"; +import { getGraph } from "./linkUtils.js"; + +// Minimal note stub matching what getGraph reads. +function makeNote(slug, data = {}) { + return { + filePathStem: `/notes/${slug}`, + url: `/${slug}/`, + fileSlug: slug, + data: { title: slug, ...data }, + template: { read: async () => ({ content: "" }) }, + }; +} + +async function buildGraph(notes) { + return getGraph({ collections: { note: notes } }); +} + +describe("linkUtils getGraph hide flags", () => { + it("does not hide or privatize a normal note", async () => { + const graph = await buildGraph([makeNote("normal")]); + expect(graph.nodes["/normal/"].hide).toBe(false); + expect(graph.nodes["/normal/"].private).toBe(false); + }); + + it("hides and privatizes a note with hide:true (dg-hide)", async () => { + const graph = await buildGraph([makeNote("secret", { hide: true })]); + expect(graph.nodes["/secret/"].hide).toBe(true); + expect(graph.nodes["/secret/"].private).toBe(true); + }); + + it("hides but does not privatize a note with hideInGraph:true", async () => { + const graph = await buildGraph([ + makeNote("graphonly", { hideInGraph: true }), + ]); + expect(graph.nodes["/graphonly/"].hide).toBe(true); + expect(graph.nodes["/graphonly/"].private).toBe(false); + }); + + it("does not hide a filetree-only note from the graph", async () => { + const graph = await buildGraph([ + makeNote("treeonly", { hideInFiletree: true }), + ]); + expect(graph.nodes["/treeonly/"].hide).toBe(false); + expect(graph.nodes["/treeonly/"].private).toBe(false); + }); +}); From 2be2b6f8105264dbcb42304357e0a3be2ea4cbff Mon Sep 17 00:00:00 2001 From: Ole Eskild Steensen <6201338+oleeskild@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:12:52 +0200 Subject: [PATCH 3/4] feat(backlinks): omit dg-hide notes from backlinks on other pages Co-Authored-By: Claude Opus 4.8 (1M context) --- src/site/_includes/components/sidebar.njk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/_includes/components/sidebar.njk b/src/site/_includes/components/sidebar.njk index c2b5e06f9..517d4a8d4 100644 --- a/src/site/_includes/components/sidebar.njk +++ b/src/site/_includes/components/sidebar.njk @@ -63,7 +63,7 @@ {%- endif -%} {%- for backlink in currentNode.backLinks -%} - {%- if graph.nodes[backlink].url != page.url -%} + {%- if graph.nodes[backlink].url != page.url and not graph.nodes[backlink].private -%} From 41e3e654249a21b3dcaf87a148ca96f20c3e9030 Mon Sep 17 00:00:00 2001 From: Ole Eskild Steensen <6201338+oleeskild@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:14:29 +0200 Subject: [PATCH 4/4] feat(hide): exclude dg-hide notes from search, feed, and sitemap Co-Authored-By: Claude Opus 4.8 (1M context) --- .eleventy.js | 4 ++++ src/site/feed.njk | 2 +- src/site/search-index.njk | 2 +- src/site/sitemap.njk | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.eleventy.js b/.eleventy.js index c725eee3d..90f2aadc7 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -755,6 +755,10 @@ module.exports = function(eleventyConfig) { return JSON.stringify(variable) || '""'; }); + eleventyConfig.addFilter("notHidden", function (arr) { + return (arr || []).filter((item) => !item.data.hide); + }); + eleventyConfig.addFilter("validJson", function(variable) { if (Array.isArray(variable)) { return variable.map((x) => x.replaceAll("\\", "\\\\")).join(","); diff --git a/src/site/feed.njk b/src/site/feed.njk index a5bd7666b..54fbe3d2e 100644 --- a/src/site/feed.njk +++ b/src/site/feed.njk @@ -12,7 +12,7 @@ {{ collections.notes | getNewestCollectionItemDate | dateToRfc3339 }} {{ meta.siteBaseUrl }} - {%- for note in collections.note | reverse -%} + {%- for note in (collections.note | notHidden) | reverse -%} {%- if note.url != "/" -%} {%- if note.title -%}{{ note.title }}{%- else -%}{{ note.fileSlug }}{%- endif -%} diff --git a/src/site/search-index.njk b/src/site/search-index.njk index 4b89987a5..dbca7ada3 100644 --- a/src/site/search-index.njk +++ b/src/site/search-index.njk @@ -2,7 +2,7 @@ permalink: /searchIndex.json eleventyExcludeFromCollections: true --- -[{% for post in collections.note %} +[{% for post in collections.note | notHidden %} { "title": {% if post.data.title %}{{post.data.title | jsonify | safe }}{% else %}{{post.fileSlug | jsonify | safe }}{% endif %}, "date":"{{ post.date }}", diff --git a/src/site/sitemap.njk b/src/site/sitemap.njk index 3f170d894..eaaf911dc 100644 --- a/src/site/sitemap.njk +++ b/src/site/sitemap.njk @@ -5,9 +5,11 @@ eleventyExcludeFromCollections: true {% for page in collections.all %} + {% if not page.data.hide %} {{ meta.siteBaseUrl }}{{ page.url | url }} {%if page.data.updated %}{{ page.data.updated | dateToZulu }}{%else%}{{ page.date | dateToZulu }}{%endif%} + {% endif %} {% endfor %} \ No newline at end of file