From da9b70dedd3e864c0710e8903187881f873ffe40 Mon Sep 17 00:00:00 2001 From: Oscar Otero Date: Thu, 4 May 2023 21:14:27 +0200 Subject: [PATCH] fix scope --- core/scopes.ts | 15 +++++---- core/site.ts | 8 +++-- core/source.ts | 23 +++++++++++--- tests/core/scopes.test.ts | 64 +++++++++++++++++++++------------------ 4 files changed, 67 insertions(+), 43 deletions(-) diff --git a/core/scopes.ts b/core/scopes.ts index 8fbd449b..d66f94c1 100644 --- a/core/scopes.ts +++ b/core/scopes.ts @@ -1,4 +1,4 @@ -import type { Page } from "../core.ts"; +import type { Entry } from "../core.ts"; /** * Define independent updates scopes @@ -8,7 +8,7 @@ export default class Scopes { scopes = new Set(); /** Returns a function to filter the pages that must be rebuild */ - getFilter(changedFiles: Iterable): (page: Page) => boolean { + getFilter(changedFiles: Iterable): (entry: Entry) => boolean { // There's no any scope, so rebuild all pages if (this.scopes.size === 0) { return () => true; @@ -42,18 +42,21 @@ export default class Scopes { } // Generate the filter function - return function (page) { - const path = page.src.path + page.src.ext; + return function (entry) { + // Ignore directories + if (entry.type === "directory") { + return false; + } // It matches with any scope that has changed for (const scopeFn of changed) { - if (scopeFn(path)) { + if (scopeFn(entry.path)) { return true; } } // It's not scoped - return noScoped && notChanged.every((scopeFn) => !scopeFn(path)); + return noScoped && notChanged.every((scopeFn) => !scopeFn(entry.path)); }; } } diff --git a/core/site.ts b/core/site.ts index 91ebfa64..a99308dc 100644 --- a/core/site.ts +++ b/core/site.ts @@ -512,7 +512,7 @@ export default class Site { const [_pages, _staticFiles] = await this.source.build( this.globalComponents, [ - (page) => !page.data.draft || this.options.dev, + (_, page) => !page?.data.draft || this.options.dev, ], ); @@ -558,7 +558,7 @@ export default class Site { const [_pages, _staticFiles] = await this.source.build( this.globalComponents, [ - (page) => !page.data.draft || this.options.dev, + (_, page) => !page?.data.draft || this.options.dev, this.scopes.getFilter(files), ], ); @@ -664,7 +664,9 @@ export default class Site { const [pages] = await this.source.build( this.globalComponents, [ - (page) => page.src.path + page.src.ext === file, + (entry) => + (entry.type === "directory" && file.startsWith(entry.path)) || + entry.path === file, ], ); diff --git a/core/source.ts b/core/source.ts index 0d7210bf..aaeeebb3 100644 --- a/core/source.ts +++ b/core/source.ts @@ -110,12 +110,13 @@ export default class Source { async build( globalComponents: Components, - pageFilters: ((page: Page) => boolean)[], + buildFilters: BuildFilter[], ): Promise<[Page[], StaticFile[]]> { const pages: Page[] = []; const staticFiles: StaticFile[] = []; await this.#build( + buildFilters, this.fs.entries.get("/")!, "/", globalComponents, @@ -125,14 +126,13 @@ export default class Source { ); return [ - pages.filter(( - page, - ) => pageFilters.every((filter) => filter(page))), + pages, staticFiles, ]; } async #build( + buildFilters: BuildFilter[], dir: Entry, path: string, parentComponents: Components, @@ -140,6 +140,10 @@ export default class Source { pages: Page[], staticFiles: StaticFile[], ) { + if (buildFilters.some((filter) => !filter(dir))) { + return; + } + // Parse the date/time in the folder name const [name, date] = parseDate(dir.name); path = posix.join(path, name); @@ -180,6 +184,10 @@ export default class Source { // Load the pages and static files for (const entry of dir.children.values()) { + if (buildFilters.some((filter) => !filter(entry))) { + continue; + } + // Static files if (this.staticPaths.has(entry.path)) { const dest = this.staticPaths.get(entry.path); @@ -280,6 +288,10 @@ export default class Source { page.data.date = getDate(page.data.date, entry); page.data.page = page; + if (buildFilters.some((filter) => !filter(entry, page))) { + continue; + } + pages.push(page); continue; } @@ -288,6 +300,7 @@ export default class Source { // Load recursively the directory if (entry.type === "directory") { await this.#build( + buildFilters, entry, path, parentComponents, @@ -413,6 +426,8 @@ function toProxy( }) as unknown as ProxyComponents; } +export type BuildFilter = (entry: Entry, page?: Page) => boolean; + export type ComponentFunction = (props: Record) => string; export interface ProxyComponents { diff --git a/tests/core/scopes.test.ts b/tests/core/scopes.test.ts index 881d3a9d..31b91ce2 100644 --- a/tests/core/scopes.test.ts +++ b/tests/core/scopes.test.ts @@ -1,18 +1,22 @@ import { assertStrictEquals as equals } from "../../deps/assert.ts"; import Scopes from "../../core/scopes.ts"; -import { Page } from "../../core/filesystem.ts"; +import FS from "../../core/fs.ts"; Deno.test("Scripts", async (t) => { const scopes = new Scopes(); equals(scopes.scopes.size, 0); - const pages: Page[] = [ - new Page({ path: "file1", ext: ".foo" }), - new Page({ path: "file2", ext: ".bar" }), - new Page({ path: "file3", ext: ".css" }), - new Page({ path: "file4", ext: ".html" }), - ]; + const fs = new FS({ + root: "/", + }); + + fs.addEntry({ path: "/file1.foo", type: "file" }); + fs.addEntry({ path: "/file2.bar", type: "file" }); + fs.addEntry({ path: "/file3.css", type: "file" }); + fs.addEntry({ path: "/file4.html", type: "file" }); + + const entries = Array.from(fs.entries.values()); await t.step("Add scopes", () => { scopes.scopes.add((path: string) => path.endsWith(".foo")); @@ -24,48 +28,48 @@ Deno.test("Scripts", async (t) => { await t.step("Check scoped changes", () => { const filter = scopes.getFilter([ - "file1.foo", - "file3.foo", + "/file1.foo", + "/file3.foo", ]); - const filteredPages = pages.filter(filter); - equals(filteredPages.length, 1); - equals(filteredPages[0].src.path, "file1"); + const filteredEntries = entries.filter(filter); + equals(filteredEntries.length, 1); + equals(filteredEntries[0].path, "/file1.foo"); }); await t.step("Check 2 scoped changes", () => { const filter = scopes.getFilter([ - "file1.foo", - "file2.bar", + "/file1.foo", + "/file2.bar", ]); - const filteredPages = pages.filter(filter); - equals(filteredPages.length, 2); - equals(filteredPages[0].src.path, "file1"); - equals(filteredPages[1].src.path, "file2"); + const filteredEntries = entries.filter(filter); + equals(filteredEntries.length, 2); + equals(filteredEntries[0].path, "/file1.foo"); + equals(filteredEntries[1].path, "/file2.bar"); }); await t.step("Check unscoped changes", () => { const filter = scopes.getFilter([ - "file3.css", + "/file3.css", ]); - const filteredPages = pages.filter(filter); - equals(filteredPages.length, 2); - equals(filteredPages[0].src.path, "file3"); - equals(filteredPages[1].src.path, "file4"); + const filteredEntries = entries.filter(filter); + equals(filteredEntries.length, 2); + equals(filteredEntries[0].path, "/file3.css"); + equals(filteredEntries[1].path, "/file4.html"); }); await t.step("Check scoped and unscoped changes", () => { const filter = scopes.getFilter([ - "file3.css", - "file1.foo", + "/file3.css", + "/file1.foo", ]); - const filteredPages = pages.filter(filter); - equals(filteredPages.length, 3); - equals(filteredPages[0].src.path, "file1"); - equals(filteredPages[1].src.path, "file3"); - equals(filteredPages[2].src.path, "file4"); + const filteredEntries = entries.filter(filter); + equals(filteredEntries.length, 3); + equals(filteredEntries[0].path, "/file1.foo"); + equals(filteredEntries[1].path, "/file3.css"); + equals(filteredEntries[2].path, "/file4.html"); }); });