diff --git a/.obsidian/plugins/webinar-dash/main.js b/.obsidian/plugins/webinar-dash/main.js index 9977e06..23e0c79 100644 --- a/.obsidian/plugins/webinar-dash/main.js +++ b/.obsidian/plugins/webinar-dash/main.js @@ -49,10 +49,15 @@ function derivePipeline({ rawFiles, sourcePages }) { else unprocessed.push(file); } + // One pass over sourcePages, so a page appears in `orphaned` at most once no + // matter how many of the three reasons apply to it. Concatenating a separate + // duplicates array here would double-count a losing claimant whose shared raw + // path is also missing from disk. const rawPaths = new Set(rawFiles.map((f) => f.path)); - const orphaned = sourcePages - .filter((p) => !p.rawPath || !rawPaths.has(p.rawPath)) - .concat(duplicates); + const duplicateSet = new Set(duplicates); + const orphaned = sourcePages.filter( + (p) => duplicateSet.has(p) || !p.rawPath || !rawPaths.has(p.rawPath) + ); unprocessed.sort((a, b) => a.name.localeCompare(b.name)); processed.sort((a, b) => b.page.name.localeCompare(a.page.name)); diff --git a/.obsidian/plugins/webinar-dash/test/pipeline.test.js b/.obsidian/plugins/webinar-dash/test/pipeline.test.js index b5e95f9..61b39cb 100644 --- a/.obsidian/plugins/webinar-dash/test/pipeline.test.js +++ b/.obsidian/plugins/webinar-dash/test/pipeline.test.js @@ -82,6 +82,17 @@ test("derivePipeline routes a duplicate raw-path claim to orphaned", () => { assert.deepEqual(out.orphaned.map((p) => p.name), ["second.md"]); }); +test("derivePipeline lists a page once when it is both a duplicate claim and missing its raw file", () => { + const out = derivePipeline({ + rawFiles: [{ path: "raw/sources/other.md", name: "other.md", size: 10 }], + sourcePages: [ + { path: "wiki/sources/first.md", name: "first.md", rawPath: "raw/sources/gone.md" }, + { path: "wiki/sources/second.md", name: "second.md", rawPath: "raw/sources/gone.md" }, + ], + }); + assert.deepEqual(out.orphaned.map((p) => p.name), ["first.md", "second.md"]); +}); + test("derivePipeline sorts unprocessed by name and processed newest first", () => { const out = derivePipeline({ rawFiles: [