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/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); + }); + }); }); 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); + }); +}); 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 -%}