@lumeland/core 1.0.0-beta-7 → 1.0.0-beta-9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +7 -0
  2. package/build/deps/cli.d.ts +1 -1
  3. package/build/deps/cli.js +1 -1
  4. package/build/deps/front-matter.d.ts +2 -0
  5. package/build/deps/front-matter.js +2 -0
  6. package/build/deps/media-types.d.ts +2 -0
  7. package/build/deps/media-types.js +2 -0
  8. package/build/deps/path.d.ts +1 -1
  9. package/build/deps/path.js +1 -1
  10. package/build/src/archetypes.d.ts +13 -3
  11. package/build/src/archetypes.js +39 -4
  12. package/build/src/components.js +1 -1
  13. package/build/src/{data_loader.js → data-loader.js} +1 -1
  14. package/build/src/loaders/text.js +1 -1
  15. package/build/src/path.d.ts +20 -0
  16. package/build/src/path.js +101 -0
  17. package/build/src/processors.js +0 -1
  18. package/build/src/renderer.d.ts +0 -3
  19. package/build/src/renderer.js +11 -19
  20. package/build/src/searcher.d.ts +1 -1
  21. package/build/src/searcher.js +7 -5
  22. package/build/src/server.d.ts +1 -1
  23. package/build/src/server.js +5 -6
  24. package/build/src/services/fs.js +2 -2
  25. package/build/src/site.d.ts +4 -12
  26. package/build/src/site.js +24 -31
  27. package/build/src/source.d.ts +1 -1
  28. package/build/src/source.js +8 -7
  29. package/build/src/types.d.ts +1 -1
  30. package/build/src/utils/cdn.js +5 -4
  31. package/build/src/utils/{data_values.d.ts → data-values.d.ts} +1 -1
  32. package/build/src/utils/{data_values.js → data-values.js} +0 -1
  33. package/build/src/utils/includes.d.ts +2 -0
  34. package/build/src/utils/includes.js +13 -0
  35. package/build/src/utils/{page_url.js → page-url.js} +3 -6
  36. package/build/src/utils/path.d.ts +0 -13
  37. package/build/src/utils/path.js +1 -48
  38. package/build/src/utils/{serve_file.js → serve-file.js} +1 -1
  39. package/build/src/watcher.js +15 -15
  40. package/build/src/writer.js +1 -3
  41. package/package.json +4 -4
  42. package/build/deps/front_matter.d.ts +0 -2
  43. package/build/deps/front_matter.js +0 -2
  44. package/build/deps/media_types.d.ts +0 -2
  45. package/build/deps/media_types.js +0 -2
  46. /package/build/src/{data_loader.d.ts → data-loader.d.ts} +0 -0
  47. /package/build/src/utils/{css_urls.d.ts → css-urls.d.ts} +0 -0
  48. /package/build/src/utils/{css_urls.js → css-urls.js} +0 -0
  49. /package/build/src/utils/{dom_links.d.ts → dom-links.d.ts} +0 -0
  50. /package/build/src/utils/{dom_links.js → dom-links.js} +0 -0
  51. /package/build/src/utils/{lume_config.d.ts → lume-config.d.ts} +0 -0
  52. /package/build/src/utils/{lume_config.js → lume-config.js} +0 -0
  53. /package/build/src/utils/{merge_data.d.ts → merge-data.d.ts} +0 -0
  54. /package/build/src/utils/{merge_data.js → merge-data.js} +0 -0
  55. /package/build/src/utils/{page_content.d.ts → page-content.d.ts} +0 -0
  56. /package/build/src/utils/{page_content.js → page-content.js} +0 -0
  57. /package/build/src/utils/{page_date.d.ts → page-date.d.ts} +0 -0
  58. /package/build/src/utils/{page_date.js → page-date.js} +0 -0
  59. /package/build/src/utils/{page_url.d.ts → page-url.d.ts} +0 -0
  60. /package/build/src/utils/{serve_file.d.ts → serve-file.d.ts} +0 -0
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @lumeland/core
2
+
3
+ The core of Lume SSG
4
+
5
+ ---
6
+
7
+ Please see [CHANGELOG](CHANGELOG.md) for information about the recent changes.
@@ -1 +1 @@
1
- export { parseArgs } from "deno-std/cli/parse_args.js";
1
+ export { parseArgs } from "deno-std/cli/parse-args.js";
package/build/deps/cli.js CHANGED
@@ -1 +1 @@
1
- export { parseArgs } from "deno-std/cli/parse_args.js";
1
+ export { parseArgs } from "deno-std/cli/parse-args.js";
@@ -0,0 +1,2 @@
1
+ export * from "deno-std/front-matter/any.js";
2
+ export { test } from "deno-std/front-matter/test.js";
@@ -0,0 +1,2 @@
1
+ export * from "deno-std/front-matter/any.js";
2
+ export { test } from "deno-std/front-matter/test.js";
@@ -0,0 +1,2 @@
1
+ export { contentType } from "deno-std/media-types/content-type.js";
2
+ export { typeByExtension } from "deno-std/media-types/type-by-extension.js";
@@ -0,0 +1,2 @@
1
+ export { contentType } from "deno-std/media-types/content-type.js";
2
+ export { typeByExtension } from "deno-std/media-types/type-by-extension.js";
@@ -1,4 +1,4 @@
1
1
  export { posix, sep as SEPARATOR } from "node:path";
2
2
  export { basename, dirname, extname, join, relative } from "node:path";
3
- export { globToRegExp } from "deno-std/path/glob_to_regexp.js";
3
+ export { globToRegExp } from "deno-std/path/glob-to-regexp.js";
4
4
  export { fileURLToPath as fromFileUrl, pathToFileURL as toFileUrl } from "node:url";
@@ -1,6 +1,6 @@
1
1
  export { posix, sep as SEPARATOR } from "node:path";
2
2
  export { basename, dirname, extname, join, relative } from "node:path";
3
- export { globToRegExp } from "deno-std/path/glob_to_regexp.js";
3
+ export { globToRegExp } from "deno-std/path/glob-to-regexp.js";
4
4
  export { fileURLToPath as fromFileUrl, pathToFileURL as toFileUrl } from "node:url";
5
5
  // posix.dirname
6
6
  // posix.join
@@ -9,12 +9,22 @@ export default class Archetypes {
9
9
  constructor(options: Options);
10
10
  register(name: string, archetype: string | Archetype): void;
11
11
  run(name: string, args?: string[]): Promise<void>;
12
- save(file: ArchetypeFile): Promise<void>;
12
+ save(file: ArchetypeFile | ArchetypeRemote): Promise<void>;
13
13
  load(name: string): Promise<Archetype>;
14
14
  }
15
- export type Archetype = (...args: string[]) => void | ArchetypeFile | Generator<ArchetypeFile> | AsyncGenerator<ArchetypeFile>;
15
+ export type Archetype = (...args: string[]) => void | ArchetypeFile | ArchetypeRemote | Generator<ArchetypeFile | ArchetypeRemote> | AsyncGenerator<ArchetypeFile | ArchetypeRemote>;
16
+ /** To generate files dynamically */
16
17
  export interface ArchetypeFile<T = unknown> {
17
18
  base?: "src" | "root";
18
19
  path: string;
19
- content: T | ((prev?: T) => T | Promise<T>);
20
+ overwrite?: boolean;
21
+ content: T | URL | ((prev?: T) => T | Promise<T>);
22
+ url?: string;
23
+ }
24
+ /** Allow to download files */
25
+ export interface ArchetypeRemote {
26
+ url: string | URL;
27
+ path?: string;
28
+ files: string[];
29
+ overwrite?: boolean;
20
30
  }
@@ -7,7 +7,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
7
7
  return path;
8
8
  };
9
9
  import { parse, stringify } from "../deps/yaml.js";
10
- import { extract, test } from "../deps/front_matter.js";
10
+ import { extract, test } from "../deps/front-matter.js";
11
11
  import { ensureDir } from "./utils/fs.js";
12
12
  import { dirname, join, toFileUrl } from "../deps/path.js";
13
13
  import { isGenerator } from "./utils/generator.js";
@@ -15,6 +15,8 @@ import { log } from "./utils/log.js";
15
15
  import { isUrl } from "./utils/path.js";
16
16
  import { cwd } from "./services/process.js";
17
17
  import { readTextFile, writeFile, writeTextFile } from "./services/fs.js";
18
+ import { read } from "./utils/read.js";
19
+ import { getFiles, isFromCdn } from "./utils/cdn.js";
18
20
  export default class Archetypes {
19
21
  archetypes = new Map();
20
22
  src;
@@ -52,16 +54,26 @@ export default class Archetypes {
52
54
  }
53
55
  }
54
56
  async save(file) {
55
- const { path, base = "src", content } = file;
57
+ if (isRemote(file)) {
58
+ const files = await remoteToFile(file);
59
+ for (const file of files) {
60
+ await this.save(file);
61
+ }
62
+ return;
63
+ }
64
+ const { path, base = "src", content, overwrite } = file;
56
65
  if (!path) {
57
66
  throw new Error("Archetype path is required.");
58
67
  }
59
- if (!content) {
68
+ if (content === undefined || content === null) {
60
69
  throw new Error("Archetype content is required.");
61
70
  }
62
71
  const fullPath = join(base === "root" ? this.root : this.src, path);
72
+ if (content instanceof URL) {
73
+ return await saveFile(fullPath, await read(content.href), overwrite);
74
+ }
63
75
  if (typeof content === "string" || content instanceof Uint8Array) {
64
- return await saveFile(fullPath, content);
76
+ return await saveFile(fullPath, content, overwrite);
65
77
  }
66
78
  if (path.endsWith(".json")) {
67
79
  return await runObjectArchetype(fullPath, content, JSON.parse, (o) => JSON.stringify(o, null, 2));
@@ -150,3 +162,26 @@ async function readFile(path) {
150
162
  throw error;
151
163
  }
152
164
  }
165
+ function isRemote(arch) {
166
+ return !!arch.url;
167
+ }
168
+ async function remoteToFile(remote) {
169
+ const overwrite = remote.overwrite;
170
+ const url = remote.url.toString();
171
+ if (isFromCdn(url) || url.startsWith("file:")) {
172
+ const files = await getFiles(url, remote.files);
173
+ return Array.from(files).map(([file, url]) => ({
174
+ path: join(remote.path ?? "/", file),
175
+ overwrite,
176
+ content: new URL(url),
177
+ }));
178
+ }
179
+ if (isUrl(url)) {
180
+ return remote.files.map((file) => ({
181
+ path: join(remote.path ?? "/", file),
182
+ overwrite,
183
+ content: new URL(url),
184
+ }));
185
+ }
186
+ throw new Error(`Invalid archifact's url "${url}"`);
187
+ }
@@ -12,7 +12,7 @@ export class ComponentLoader {
12
12
  if (!components) {
13
13
  components = new Map();
14
14
  }
15
- for await (const entry of dirEntry.children.values()) {
15
+ for (const entry of dirEntry.children.values()) {
16
16
  if (entry.name.startsWith(".") || entry.name.startsWith("_")) {
17
17
  continue;
18
18
  }
@@ -26,7 +26,7 @@ export default class DataLoader {
26
26
  /** Load a _data directory */
27
27
  async #loadDirectory(entry) {
28
28
  const data = {};
29
- for await (const child of entry.children.values()) {
29
+ for (const child of entry.children.values()) {
30
30
  await this.loadEntry(child, data);
31
31
  }
32
32
  return data;
@@ -1,4 +1,4 @@
1
- import { extract, test } from "../../deps/front_matter.js";
1
+ import { extract, test } from "../../deps/front-matter.js";
2
2
  import { read } from "../utils/read.js";
3
3
  /** Load a text file. Detect and parse the front matter */
4
4
  export default async function text(path) {
@@ -0,0 +1,20 @@
1
+ export default class Path {
2
+ #private;
3
+ static create(path: string | Path): Path;
4
+ static createDecoded(path: string): Path;
5
+ private constructor();
6
+ clone(): Path;
7
+ get dirname(): string;
8
+ toString(): string;
9
+ valueOf(): string;
10
+ get full(): string;
11
+ get url(): URL;
12
+ get basename(): string;
13
+ get extension(): string;
14
+ set extension(ext: string);
15
+ join(...paths: string[]): this;
16
+ removeBase(base: string | Path): this;
17
+ addBase(base: string | Path): this;
18
+ belongsTo(base: string | Path): boolean;
19
+ contains(base: string | Path): boolean;
20
+ }
@@ -0,0 +1,101 @@
1
+ import { fromFileUrl, toFileUrl, posix, SEPARATOR } from "../deps/path.js";
2
+ import { decodeURIComponentSafe } from "./utils/path.js";
3
+ const WINDOWS_ABSOLUTE = /^\w:[\\/]/;
4
+ const EXTENSION = /\.\w+$/;
5
+ export default class Path {
6
+ #drive;
7
+ #path;
8
+ static create(path) {
9
+ if (typeof path === "string") {
10
+ const [d, p] = parse(path);
11
+ return new Path(d, p);
12
+ }
13
+ return path;
14
+ }
15
+ static createDecoded(path) {
16
+ return Path.create(decodeURIComponentSafe(path));
17
+ }
18
+ constructor(drive, path) {
19
+ this.#drive = drive;
20
+ this.#path = path;
21
+ }
22
+ clone() {
23
+ return new Path(this.#drive, this.#path);
24
+ }
25
+ get dirname() {
26
+ return posix.dirname(this.#path);
27
+ }
28
+ toString() {
29
+ return this.#path;
30
+ }
31
+ valueOf() {
32
+ return this.#path;
33
+ }
34
+ get full() {
35
+ return this.#drive ? `${this.#drive}:${this.#path}` : this.#path;
36
+ }
37
+ get url() {
38
+ return toFileUrl(this.full);
39
+ }
40
+ get basename() {
41
+ return posix.basename(this.#path, this.extension);
42
+ }
43
+ get extension() {
44
+ const match = this.#path.match(EXTENSION);
45
+ return match ? match[0].toLowerCase() : "";
46
+ }
47
+ set extension(ext) {
48
+ const length = this.extension.length;
49
+ this.#path = `${length ? this.#path.slice(0, -length) : this.#path}${ext}`;
50
+ }
51
+ join(...paths) {
52
+ this.#path = posix.join(this.#path, ...paths);
53
+ return this;
54
+ }
55
+ removeBase(base) {
56
+ this.#drive = undefined;
57
+ base = Path.create(base).toString();
58
+ if (base.length > 1 && base.endsWith("/")) {
59
+ base = base.slice(0, -1);
60
+ }
61
+ if (this.#path === base || this.#path.startsWith(base)) {
62
+ this.#path = posix.join("/", this.#path.slice(base.length));
63
+ }
64
+ return this;
65
+ }
66
+ addBase(base) {
67
+ if (base instanceof Path) {
68
+ this.#drive = base.#drive;
69
+ }
70
+ base = Path.create(base).toString();
71
+ if (!this.#path.startsWith(base)) {
72
+ this.#path = posix.join(base, this.#path);
73
+ }
74
+ return this;
75
+ }
76
+ belongsTo(base) {
77
+ base = Path.create(base).toString();
78
+ if (base.length > 1 && base.endsWith("/")) {
79
+ base = base.slice(0, -1);
80
+ }
81
+ return this.#path === base || this.#path.startsWith(base);
82
+ }
83
+ contains(base) {
84
+ return Path.create(base).belongsTo(this);
85
+ }
86
+ }
87
+ function parse(path) {
88
+ let drive;
89
+ if (path.startsWith("file://")) {
90
+ path = fromFileUrl(path);
91
+ }
92
+ if (path.match(WINDOWS_ABSOLUTE)) {
93
+ drive = path[0];
94
+ path = path.slice(2).replaceAll("\\", "/");
95
+ }
96
+ else if (SEPARATOR !== "/") {
97
+ path = path.replaceAll("\\", "/");
98
+ }
99
+ path = posix.join("/", path);
100
+ return [drive, path];
101
+ }
@@ -8,7 +8,6 @@ export default class Processors {
8
8
  /** Loaded extensions cache */
9
9
  loadedExtensions = new Set();
10
10
  /** Assign a processor to some extensions */
11
- // deno-lint-ignore no-explicit-any
12
11
  set(extensions, processor) {
13
12
  if (Array.isArray(extensions)) {
14
13
  extensions.forEach((extension) => {
@@ -5,7 +5,6 @@ import type Formats from "./formats.ts";
5
5
  import type FS from "./fs.ts";
6
6
  import type DebugBar from "./debugbar.ts";
7
7
  export interface Options {
8
- includes: string;
9
8
  prettyUrls: boolean;
10
9
  preprocessors: Processors;
11
10
  formats: Formats;
@@ -17,8 +16,6 @@ export interface Options {
17
16
  */
18
17
  export default class Renderer {
19
18
  #private;
20
- /** The default folder to include the layouts */
21
- includes: string;
22
19
  /** The filesystem instance used to read the layouts */
23
20
  fs: FS;
24
21
  /** To convert the urls to pretty /example.html => /example/ */
@@ -1,18 +1,16 @@
1
- import { resolveInclude } from "./utils/path.js";
2
1
  import { isGenerator } from "./utils/generator.js";
3
2
  import { concurrent } from "./utils/concurrent.js";
4
- import { mergeData } from "./utils/merge_data.js";
5
- import { getBasename, getPageUrl } from "./utils/page_url.js";
6
- import { getPageDate } from "./utils/page_date.js";
3
+ import { mergeData } from "./utils/merge-data.js";
4
+ import { getBasename, getPageUrl } from "./utils/page-url.js";
5
+ import { getPageDate } from "./utils/page-date.js";
7
6
  import { posix } from "../deps/path.js";
8
7
  import { log } from "./utils/log.js";
8
+ import { getInclude } from "./utils/includes.js";
9
9
  /**
10
10
  * The renderer is responsible for rendering the site pages
11
11
  * in the right order and using the right template engine.
12
12
  */
13
13
  export default class Renderer {
14
- /** The default folder to include the layouts */
15
- includes;
16
14
  /** The filesystem instance used to read the layouts */
17
15
  fs;
18
16
  /** To convert the urls to pretty /example.html => /example/ */
@@ -24,7 +22,6 @@ export default class Renderer {
24
22
  /** The registered helpers */
25
23
  helpers = new Map();
26
24
  constructor(options) {
27
- this.includes = options.includes;
28
25
  this.prettyUrls = options.prettyUrls;
29
26
  this.preprocessors = options.preprocessors;
30
27
  this.formats = options.formats;
@@ -164,7 +161,7 @@ export default class Renderer {
164
161
  /** Render the page layout */
165
162
  async #renderLayout(page, content) {
166
163
  let data = { ...page.data };
167
- let path = page.src.path + page.src.ext;
164
+ let path = posix.dirname(page.src.path + page.src.ext);
168
165
  let layout = data.layout;
169
166
  // Render the layouts recursively
170
167
  while (layout) {
@@ -172,22 +169,17 @@ export default class Renderer {
172
169
  if (!format || !format.loader) {
173
170
  throw new Error(`The layout format "${layout}" doesn't exist`);
174
171
  }
175
- const includesPath = format.engines?.[0].includes;
176
- if (!includesPath) {
177
- throw new Error(`The layout format "${layout}" doesn't support includes`);
172
+ const layoutEntry = getInclude(path, layout, this.fs);
173
+ if (!layoutEntry) {
174
+ throw new Error(`The layout file "${layout}" for the file "${path}" doesn't exist`);
178
175
  }
179
- const layoutPath = resolveInclude(layout, includesPath, posix.dirname(path));
180
- const entry = this.fs.entries.get(layoutPath);
181
- if (!entry) {
182
- throw new Error(`The layout file "${layoutPath}" doesn't exist`);
183
- }
184
- const layoutData = await entry.getContent(format.loader);
176
+ const layoutData = await layoutEntry.getContent(format.loader);
185
177
  delete data.layout;
186
178
  delete data.templateEngine;
187
179
  data = mergeData(layoutData, data, { content });
188
- content = await this.render(layoutData.content, data, layoutPath, true);
180
+ content = await this.render(layoutData.content, data, layoutEntry.path, true);
189
181
  layout = layoutData.layout;
190
- path = layoutPath;
182
+ path = layoutEntry.path.split("/_includes/")[0];
191
183
  }
192
184
  return content;
193
185
  }
@@ -20,7 +20,7 @@ export default class Searcher {
20
20
  /**
21
21
  * Return the data in the scope of a path (file or folder)
22
22
  */
23
- data<T>(path?: string): Data<T> | DirectoryData<T> | undefined;
23
+ data<T>(rawPath?: string): Data<T> | DirectoryData<T> | undefined;
24
24
  /** Search pages */
25
25
  pages<T>(query?: string, sort?: string, limit?: number): Data<T>[];
26
26
  /** Search and return the first page */
@@ -1,5 +1,5 @@
1
1
  import { globToRegExp } from "../deps/path.js";
2
- import { normalizePath } from "./utils/path.js";
2
+ import Path from "./path.js";
3
3
  /** Search helper */
4
4
  export default class Searcher {
5
5
  #pages;
@@ -22,13 +22,13 @@ export default class Searcher {
22
22
  /**
23
23
  * Return the data in the scope of a path (file or folder)
24
24
  */
25
- data(path = "/") {
26
- const normalized = normalizePath(path);
27
- const dirData = this.#sourceData.get(normalized);
25
+ data(rawPath = "/") {
26
+ const path = Path.create(rawPath).toString();
27
+ const dirData = this.#sourceData.get(path);
28
28
  if (dirData) {
29
29
  return dirData;
30
30
  }
31
- const result = this.#pages.find((page) => page.data.url === normalized || page.data.sourcePath === normalized);
31
+ const result = this.#pages.find((page) => page.data.url === path || page.data.sourcePath === path);
32
32
  if (result) {
33
33
  return result.data;
34
34
  }
@@ -159,6 +159,7 @@ function compileFilter(conditions) {
159
159
  values.push(value);
160
160
  });
161
161
  args.push(`return (data) => ${filters.join(" && ")};`);
162
+ // oxlint-disable-next-line typescript/no-implied-eval
162
163
  const factory = new Function(...args);
163
164
  return factory(...values);
164
165
  }
@@ -330,5 +331,6 @@ export function buildSort(sort) {
330
331
  break;
331
332
  }
332
333
  });
334
+ // oxlint-disable-next-line typescript/no-implied-eval
333
335
  return new Function(`${init} return function (a, b) { return ${fn}; }`)();
334
336
  }
@@ -1,5 +1,5 @@
1
1
  import Events from "./events.ts";
2
- import { serveFile } from "./utils/serve_file.ts";
2
+ import { serveFile } from "./utils/serve-file.ts";
3
3
  import type { Event, EventListener, EventOptions } from "./events.ts";
4
4
  import type { HTTPHandlerInfo, NetAddress } from "./services/net.ts";
5
5
  import type { Merge } from "./utils/object.ts";
@@ -1,5 +1,5 @@
1
1
  import Events from "./events.js";
2
- import { serveFile } from "./utils/serve_file.js";
2
+ import { serveFile } from "./utils/serve-file.js";
3
3
  import { cwd } from "./services/process.js";
4
4
  import { merge } from "./utils/object.js";
5
5
  import { serve } from "./services/net.js";
@@ -9,7 +9,6 @@ export const defaults = {
9
9
  serveFile,
10
10
  };
11
11
  export default class Server {
12
- // deno-lint-ignore no-explicit-any
13
12
  events = new Events();
14
13
  options;
15
14
  middlewares = [];
@@ -74,17 +73,17 @@ export default class Server {
74
73
  signal,
75
74
  onListen: () => {
76
75
  if (!this.#waiting) {
77
- this.dispatchEvent({ type: "start" });
76
+ void this.dispatchEvent({ type: "start" });
78
77
  }
79
78
  },
80
79
  onUpgradeWebSocket: (socket) => {
81
- this.dispatchEvent({ type: "upgrade", socket });
80
+ void this.dispatchEvent({ type: "upgrade", socket });
82
81
  },
83
82
  });
84
83
  }
85
84
  else if (this.#waiting) {
86
85
  this.#waiting = false;
87
- this.dispatchEvent({ type: "start" });
86
+ void this.dispatchEvent({ type: "start" });
88
87
  }
89
88
  }
90
89
  /** Stops the server */
@@ -93,7 +92,7 @@ export default class Server {
93
92
  this.#server?.shutdown();
94
93
  }
95
94
  catch (err) {
96
- this.dispatchEvent({
95
+ void this.dispatchEvent({
97
96
  type: "error",
98
97
  error: err,
99
98
  });
@@ -99,8 +99,8 @@ export class FsError extends Error {
99
99
  get code() {
100
100
  if (this.cause.code === "ENOENT")
101
101
  return "not-found";
102
- console.log(this.cause);
103
- // if (this.cause instanceof Deno.errors.AlreadyExists) return "exists";
102
+ if (this.cause.code === "EEXIST")
103
+ return "exists";
104
104
  return "other";
105
105
  }
106
106
  }
@@ -1,6 +1,7 @@
1
+ import Path from "./path.ts";
1
2
  import FS from "./fs.ts";
2
3
  import { ComponentLoader } from "./components.ts";
3
- import DataLoader from "./data_loader.ts";
4
+ import DataLoader from "./data-loader.ts";
4
5
  import Source from "./source.ts";
5
6
  import Scopes from "./scopes.ts";
6
7
  import Processors from "./processors.ts";
@@ -28,7 +29,7 @@ import type { Middleware } from "./server.ts";
28
29
  import type { ScopeFilter } from "./scopes.ts";
29
30
  import type { ScriptOrFunction } from "./scripts.ts";
30
31
  import type { Merge } from "./utils/object.ts";
31
- import type { MergeStrategy } from "./utils/merge_data.ts";
32
+ import type { MergeStrategy } from "./utils/merge-data.ts";
32
33
  import type { Data, DefaultType } from "./types.ts";
33
34
  import type { HTTPHandlerInfo } from "./services/net.ts";
34
35
  /** Default options of the site */
@@ -38,7 +39,6 @@ declare const defaults: {
38
39
  dest: string;
39
40
  emptyDest: true;
40
41
  caseSensitiveUrls: false;
41
- includes: string;
42
42
  cssFile: string;
43
43
  jsFile: string;
44
44
  fontsFolder: string;
@@ -66,6 +66,7 @@ declare const defaults: {
66
66
  export default class Site {
67
67
  #private;
68
68
  options: Merge<SiteOptions, typeof defaults>;
69
+ rootPath: Path;
69
70
  /** Internal data. Used to save arbitrary data by plugins and processors */
70
71
  _data: Record<string, unknown>;
71
72
  /** To register and run archetypes */
@@ -237,13 +238,6 @@ export default class Site {
237
238
  /** Returns a Web server of the site */
238
239
  getServer(): Server;
239
240
  }
240
- /** The options for the resolve function */
241
- export interface ResolveOptions {
242
- /** Whether search in the includes folder or not */
243
- includes?: boolean;
244
- /** Default loader */
245
- loader?: Loader;
246
- }
247
241
  /** The options to configure the site build */
248
242
  export interface SiteOptions {
249
243
  /** The path of the current working directory */
@@ -254,8 +248,6 @@ export interface SiteOptions {
254
248
  dest?: string;
255
249
  /** Whether the empty folder should be emptied before the build */
256
250
  emptyDest?: boolean;
257
- /** The default includes path */
258
- includes?: string;
259
251
  /** The default css file */
260
252
  cssFile?: string;
261
253
  /** The default js file */
package/build/src/site.js CHANGED
@@ -1,15 +1,16 @@
1
- import { fromFileUrl, join, posix } from "../deps/path.js";
1
+ import { fromFileUrl, posix } from "../deps/path.js";
2
2
  import { merge } from "./utils/object.js";
3
- import { isUrl, normalizePath } from "./utils/path.js";
3
+ import { isUrl } from "./utils/path.js";
4
4
  import { envBoolean, setEnv } from "./utils/env.js";
5
5
  import { log } from "./utils/log.js";
6
- import { filter404page } from "./utils/page_url.js";
7
- import { insertContent } from "./utils/page_content.js";
6
+ import { filter404page } from "./utils/page-url.js";
7
+ import { insertContent } from "./utils/page-content.js";
8
8
  import { getFile, getFiles, isFromCdn } from "./utils/cdn.js";
9
9
  import { setCache } from "./utils/read.js";
10
+ import Path from "./path.js";
10
11
  import FS from "./fs.js";
11
12
  import { ComponentLoader } from "./components.js";
12
- import DataLoader from "./data_loader.js";
13
+ import DataLoader from "./data-loader.js";
13
14
  import Source from "./source.js";
14
15
  import Scopes from "./scopes.js";
15
16
  import Processors from "./processors.js";
@@ -37,7 +38,6 @@ const defaults = {
37
38
  dest: "./_site",
38
39
  emptyDest: true,
39
40
  caseSensitiveUrls: false,
40
- includes: "_includes",
41
41
  cssFile: "/style.css",
42
42
  jsFile: "/script.js",
43
43
  fontsFolder: "/fonts",
@@ -64,6 +64,7 @@ const defaults = {
64
64
  */
65
65
  export default class Site {
66
66
  options;
67
+ rootPath;
67
68
  /** Internal data. Used to save arbitrary data by plugins and processors */
68
69
  _data = {};
69
70
  /** To register and run archetypes */
@@ -87,7 +88,6 @@ export default class Site {
87
88
  /** To render the pages using any template engine */
88
89
  renderer;
89
90
  /** To listen and dispatch events */
90
- // deno-lint-ignore no-explicit-any
91
91
  events;
92
92
  /** To run scripts */
93
93
  scripts;
@@ -104,7 +104,6 @@ export default class Site {
104
104
  /** Components created with site.component() */
105
105
  scopedComponents = new Map();
106
106
  /** Hooks installed by the plugins */
107
- // deno-lint-ignore no-explicit-any
108
107
  hooks = {};
109
108
  /** The debug bar data */
110
109
  debugBar;
@@ -120,10 +119,11 @@ export default class Site {
120
119
  if (this.options.cwd.startsWith("file:")) {
121
120
  this.options.cwd = fromFileUrl(this.options.cwd);
122
121
  }
122
+ this.rootPath = Path.create(this.options.cwd);
123
123
  const root = this.root();
124
124
  const src = this.src();
125
125
  const dest = this.dest();
126
- const { includes, cwd, prettyUrls, components, server, caseSensitiveUrls } = this.options;
126
+ const { cwd, prettyUrls, components, server, caseSensitiveUrls } = this.options;
127
127
  // To load source files
128
128
  const fs = new FS({ root: src });
129
129
  const formats = new Formats();
@@ -153,7 +153,6 @@ export default class Site {
153
153
  preprocessors,
154
154
  formats,
155
155
  fs,
156
- includes,
157
156
  });
158
157
  // Other stuff
159
158
  const archetypes = new Archetypes({ src, root });
@@ -188,12 +187,10 @@ export default class Site {
188
187
  if (this.dest().startsWith(this.src())) {
189
188
  this.ignore(this.options.dest);
190
189
  }
191
- // Ignore the includes folder
192
- this.ignore(this.options.includes);
193
190
  // Normalize the ignored paths
194
- this.options.watcher.ignore = this.options.watcher.ignore.map((path) => typeof path === "string" ? normalizePath(path) : path);
191
+ this.options.watcher.ignore = this.options.watcher.ignore.map((path) => typeof path === "string" ? Path.create(path).toString() : path);
195
192
  // Ignore the dest folder by the watcher
196
- this.options.watcher.ignore.push(normalizePath(this.options.dest));
193
+ this.options.watcher.ignore.push(Path.create(this.options.dest).toString());
197
194
  this.fs.options.ignore = this.options.watcher.ignore;
198
195
  // Initialize the cache if LUME_NOCACHE is not enabled
199
196
  if (envBoolean("LUME_NOCACHE") !== true) {
@@ -225,7 +222,7 @@ export default class Site {
225
222
  debugBar.addEventListener("lume:drafts", (event) => {
226
223
  const showDrafts = event.data.value ?? "false";
227
224
  setEnv("LUME_DRAFTS", String(showDrafts));
228
- this.update();
225
+ void this.update();
229
226
  });
230
227
  return this;
231
228
  }
@@ -234,7 +231,7 @@ export default class Site {
234
231
  * Use the arguments to return a subpath
235
232
  */
236
233
  root(...path) {
237
- return normalizePath(join(this.options.cwd, ...path));
234
+ return this.rootPath.clone().join(...path).full;
238
235
  }
239
236
  /**
240
237
  * Returns the full path to the src directory.
@@ -469,7 +466,7 @@ export default class Site {
469
466
  if (from.startsWith("../")) {
470
467
  throw new Error(`It's not possible to copy files outsite the src directory ("${from}")`);
471
468
  }
472
- this.source.addFile(normalizePath(from), to ?? ((str) => str), copy);
469
+ this.source.addFile(Path.create(from).toString(), to ?? ((str) => str), copy);
473
470
  }
474
471
  /** Ignore one or several files or directories */
475
472
  ignore(...paths) {
@@ -528,7 +525,7 @@ export default class Site {
528
525
  this.debugBar?.startMeasure("build");
529
526
  if ((await this.dispatchEvent({ type: "beforeBuild" })) === false) {
530
527
  this.debugBar?.endMeasure("build", "Build cancelled");
531
- this.dispatchEvent({ type: "idle" });
528
+ await this.dispatchEvent({ type: "idle" });
532
529
  return;
533
530
  }
534
531
  if (this.options.emptyDest) {
@@ -540,7 +537,7 @@ export default class Site {
540
537
  this.debugBar?.endMeasure("scan", "[Loading] Scan source folder");
541
538
  if ((await this.dispatchEvent({ type: "afterLoad" })) === false) {
542
539
  this.debugBar?.endMeasure("build", "Build cancelled");
543
- this.dispatchEvent({ type: "idle" });
540
+ await this.dispatchEvent({ type: "idle" });
544
541
  return;
545
542
  }
546
543
  // Get the site content
@@ -550,7 +547,7 @@ export default class Site {
550
547
  // Stop if the build is cancelled
551
548
  if ((await this.#buildPages(_pages)) === false) {
552
549
  this.debugBar?.endMeasure("build", "Build cancelled");
553
- this.dispatchEvent({ type: "idle" });
550
+ await this.dispatchEvent({ type: "idle" });
554
551
  return;
555
552
  }
556
553
  // Save the pages and copy static files in the dest folder
@@ -560,7 +557,7 @@ export default class Site {
560
557
  this.debugBar?.endMeasure("save", `[Write] ${pages.length + staticFiles.length} files`);
561
558
  await this.dispatchEvent({ type: "afterBuild", pages, staticFiles });
562
559
  this.debugBar?.endMeasure("build", "Site generated");
563
- this.dispatchEvent({ type: "idle" });
560
+ await this.dispatchEvent({ type: "idle" });
564
561
  }
565
562
  /** Reload some files that might be changed */
566
563
  async update(files) {
@@ -568,7 +565,7 @@ export default class Site {
568
565
  this.debugBar?.startMeasure("build");
569
566
  if ((await this.dispatchEvent({ type: "beforeUpdate", files })) === false) {
570
567
  this.debugBar?.endMeasure("build", "Update cancelled");
571
- this.dispatchEvent({ type: "idle" });
568
+ await this.dispatchEvent({ type: "idle" });
572
569
  return;
573
570
  }
574
571
  this.search.deleteCache();
@@ -593,7 +590,7 @@ export default class Site {
593
590
  this.debugBar?.endMeasure("reload", `[Loading] Updated ${files?.size ?? 0} files`);
594
591
  if ((await this.dispatchEvent({ type: "afterLoad" })) === false) {
595
592
  this.debugBar?.endMeasure("build", "Update cancelled");
596
- this.dispatchEvent({ type: "idle" });
593
+ await this.dispatchEvent({ type: "idle" });
597
594
  return;
598
595
  }
599
596
  // Get the site content
@@ -603,7 +600,7 @@ export default class Site {
603
600
  this.files.splice(0, this.files.length, ..._staticFiles);
604
601
  if ((await this.#buildPages(_pages)) === false) {
605
602
  this.debugBar?.endMeasure("build", "Update cancelled");
606
- this.dispatchEvent({ type: "idle" });
603
+ await this.dispatchEvent({ type: "idle" });
607
604
  return;
608
605
  }
609
606
  // Save the pages and copy static files in the dest folder
@@ -618,7 +615,7 @@ export default class Site {
618
615
  pages,
619
616
  staticFiles,
620
617
  });
621
- this.dispatchEvent({ type: "idle" });
618
+ await this.dispatchEvent({ type: "idle" });
622
619
  }
623
620
  /**
624
621
  * Internal function to load pages
@@ -786,7 +783,7 @@ export default class Site {
786
783
  }
787
784
  }
788
785
  async getOrCreatePage(url) {
789
- url = normalizePath(url);
786
+ url = Path.create(url).toString();
790
787
  // It's a page
791
788
  const page = this.pages.find((page) => page.data.url === url);
792
789
  if (page) {
@@ -814,11 +811,7 @@ export default class Site {
814
811
  return newPage;
815
812
  }
816
813
  async getContent(file, binary) {
817
- file = normalizePath(file);
818
- const basePath = this.src();
819
- if (file.startsWith(basePath)) {
820
- file = normalizePath(file.slice(basePath.length));
821
- }
814
+ file = Path.create(file).removeBase(this.src()).toString();
822
815
  file = decodeURI(file);
823
816
  const url = encodeURI(file);
824
817
  // It's a page
@@ -2,7 +2,7 @@ import { Page, StaticFile } from "./file.ts";
2
2
  import type { DirectoryData, RawData } from "./types.ts";
3
3
  import type { default as FS, Entry } from "./fs.ts";
4
4
  import type { default as Formats } from "./formats.ts";
5
- import type DataLoader from "./data_loader.ts";
5
+ import type DataLoader from "./data-loader.ts";
6
6
  import type { ScopeFilter } from "./scopes.ts";
7
7
  import type { ComponentLoader, Components } from "./components.ts";
8
8
  export interface Options {
@@ -1,10 +1,11 @@
1
1
  import { posix } from "../deps/path.js";
2
- import { getExtension, normalizePath } from "./utils/path.js";
3
- import { mergeData } from "./utils/merge_data.js";
4
- import { getBasename, getPageUrl } from "./utils/page_url.js";
5
- import { getPageDate } from "./utils/page_date.js";
2
+ import { getExtension } from "./utils/path.js";
3
+ import { mergeData } from "./utils/merge-data.js";
4
+ import { getBasename, getPageUrl } from "./utils/page-url.js";
5
+ import { getPageDate } from "./utils/page-date.js";
6
6
  import { Page, StaticFile } from "./file.js";
7
7
  import { toProxy } from "./components.js";
8
+ import Path from "./path.js";
8
9
  import { log } from "./utils/log.js";
9
10
  /**
10
11
  * Scan and load files from the source folder
@@ -53,7 +54,7 @@ export default class Source {
53
54
  this.basenameParsers = options.basenameParsers;
54
55
  }
55
56
  addIgnoredPath(path) {
56
- this.ignored.add(normalizePath(path));
57
+ this.ignored.add(Path.create(path).toString());
57
58
  }
58
59
  addIgnoreFilter(filter) {
59
60
  this.filters.push(filter);
@@ -65,13 +66,13 @@ export default class Source {
65
66
  }
66
67
  }
67
68
  else {
68
- from = normalizePath(from);
69
+ from = Path.create(from).toString();
69
70
  }
70
71
  if (typeof to === "string") {
71
72
  if (to.endsWith("/")) {
72
73
  to = to.slice(0, -1);
73
74
  }
74
- to = normalizePath(to);
75
+ to = Path.create(to).toString();
75
76
  }
76
77
  this.addedFiles.set(from, [to, isCopy]);
77
78
  }
@@ -4,7 +4,7 @@ import type { Loader } from "./fs.ts";
4
4
  import type { default as Site, Plugin } from "./site.ts";
5
5
  import type { Archetype, ArchetypeFile } from "./archetypes.ts";
6
6
  import type { Middleware, RequestHandler } from "./server.ts";
7
- import type { MergeStrategy } from "./utils/merge_data.ts";
7
+ import type { MergeStrategy } from "./utils/merge-data.ts";
8
8
  import type { ProxyComponents } from "./components.ts";
9
9
  /** Raw data defined for pages or _data files */
10
10
  export type RawData<D = unknown> = D & {
@@ -1,6 +1,7 @@
1
1
  import { canParse, format, maxSatisfying, parse, parseRange } from "../../deps/semver.js";
2
- import { fromFileUrl, globToRegExp, join, posix, toFileUrl } from "../../deps/path.js";
2
+ import { fromFileUrl, globToRegExp, join, posix } from "../../deps/path.js";
3
3
  import { readDirSync } from "../services/fs.js";
4
+ import Path from "../path.js";
4
5
  export async function getFiles(specifier, patterns = ["/**"]) {
5
6
  if (specifier.startsWith("file:")) {
6
7
  return getFsFiles(specifier, patterns);
@@ -40,11 +41,11 @@ function getFsFiles(specifier, patterns) {
40
41
  const fileMap = new Map();
41
42
  const regexps = patterns.map((pattern) => globToRegExp(posix.join("/", pattern), { globstar: true, extended: true }));
42
43
  for (const path of walk(basePath)) {
43
- const filename = join("/", path.slice(basePath.length));
44
- if (!regexps.some((regexp) => regexp.test(filename))) {
44
+ const filename = Path.create(path).removeBase(basePath);
45
+ if (!regexps.some((regexp) => regexp.test(filename.toString()))) {
45
46
  continue;
46
47
  }
47
- fileMap.set(filename, toFileUrl(path).href);
48
+ fileMap.set(filename.toString(), filename.url.href);
48
49
  }
49
50
  return fileMap;
50
51
  }
@@ -1,4 +1,4 @@
1
- import { RemoveMarkdownOptions } from "../../deps/remove-markdown.ts";
1
+ import type { RemoveMarkdownOptions } from "../../deps/remove-markdown.ts";
2
2
  import type { Data } from "../types.ts";
3
3
  /**
4
4
  * Get the value of a page data
@@ -32,7 +32,6 @@ function searchValue(data, value) {
32
32
  return data[key] ?? searchValue(data, value);
33
33
  }
34
34
  const keys = key.split(".");
35
- // deno-lint-ignore no-explicit-any
36
35
  let val = data;
37
36
  for (const key of keys) {
38
37
  val = val?.[key];
@@ -0,0 +1,2 @@
1
+ import type { default as FS, Entry } from "../fs.ts";
2
+ export declare function getInclude(fromDir: string, to: string, fs: FS): Entry | undefined;
@@ -0,0 +1,13 @@
1
+ import { posix } from "../../deps/path.js";
2
+ export function getInclude(fromDir, to, fs) {
3
+ // Absolute path
4
+ if (to.startsWith("/_includes/")) {
5
+ return fs.entries.get(to);
6
+ }
7
+ // Relative path
8
+ if (to.startsWith(".")) {
9
+ return fs.entries.get(posix.join("/", fromDir, to));
10
+ }
11
+ // Get from _includes folder
12
+ return fs.entries.get(posix.join("/_includes", to));
13
+ }
@@ -1,8 +1,8 @@
1
1
  import { posix } from "../../deps/path.js";
2
- import { decodeURIComponentSafe, getExtension, normalizePath } from "./path.js";
2
+ import Path from "../path.js";
3
3
  /** Returns a function to filter the 404 page */
4
4
  export function filter404page(page404) {
5
- const url404 = page404 ? normalizePath(page404) : undefined;
5
+ const url404 = page404 ? Path.create(page404).toString() : undefined;
6
6
  return url404 ? (data) => data.url !== url404 : () => true;
7
7
  }
8
8
  /** Returns the final part of a url */
@@ -10,10 +10,7 @@ export function getBasename(url) {
10
10
  if (url === "/") {
11
11
  return "";
12
12
  }
13
- if (url.endsWith("/")) {
14
- return decodeURIComponentSafe(posix.basename(url));
15
- }
16
- return decodeURIComponentSafe(posix.basename(url, getExtension(url)));
13
+ return Path.createDecoded(url).basename;
17
14
  }
18
15
  /** Returns the final URL assigned to a page */
19
16
  export function getPageUrl(page, prettyUrls, parentPath, destination) {
@@ -1,26 +1,13 @@
1
- /**
2
- * Convert the Windows paths (that use the separator "\")
3
- * to Posix paths (with the separator "/")
4
- * and ensure it starts with "/".
5
- */
6
- export declare function normalizePath(path: string, rootToRemove?: string): string;
7
1
  /** Check if the path is an URL */
8
2
  export declare function isUrl(path: string): boolean;
9
3
  /** Check if the path is absolute */
10
4
  export declare function isAbsolutePath(path: string): boolean;
11
- /** Replace the extension of a path */
12
- export declare function replaceExtension(path: string, ext: string): string;
13
5
  /** Split a path to path + extension */
14
6
  export declare function getPathAndExtension(path: string): [string, string];
15
7
  /** Get the extension of a path (this works better than std/path) */
16
8
  export declare function getExtension(path: string): string;
17
9
  export type Extensions = string[] | "*";
18
10
  export declare function matchExtension(exts: Extensions, path: string): boolean;
19
- /**
20
- * Resolve the path of an included file
21
- * Used in the template engines and processors
22
- */
23
- export declare function resolveInclude(path: string, includesDir: string, fromDir?: string, rootToRemove?: string): string;
24
11
  /**
25
12
  * decodeURI() can't decode the `%` character, as it is used in any encoded character
26
13
  * @author [Why does decodeURIComponent('%') lock up my browser?](https://stackoverflow.com/a/54310080/3416774)
@@ -1,28 +1,4 @@
1
- import { posix, SEPARATOR } from "../../deps/path.js";
2
- /**
3
- * Convert the Windows paths (that use the separator "\")
4
- * to Posix paths (with the separator "/")
5
- * and ensure it starts with "/".
6
- */
7
- export function normalizePath(path, rootToRemove) {
8
- if (rootToRemove) {
9
- path = path.replace(rootToRemove, "");
10
- }
11
- if (SEPARATOR !== "/") {
12
- path = path.replaceAll(SEPARATOR, "/");
13
- // Is absolute Windows path (C:/...)
14
- if (path.includes(":/")) {
15
- if (rootToRemove && path.startsWith(rootToRemove)) {
16
- return posix.join("/", path.replace(rootToRemove, ""));
17
- }
18
- return path;
19
- }
20
- }
21
- const absolute = posix.join("/", path);
22
- return rootToRemove && absolute.startsWith(rootToRemove)
23
- ? posix.join("/", absolute.replace(rootToRemove, ""))
24
- : absolute;
25
- }
1
+ import { SEPARATOR } from "../../deps/path.js";
26
2
  /** Check if the path is an URL */
27
3
  export function isUrl(path) {
28
4
  return !!path.match(/^(https?|file):\/\//);
@@ -31,10 +7,6 @@ export function isUrl(path) {
31
7
  export function isAbsolutePath(path) {
32
8
  return SEPARATOR !== "/" ? /^\w:[/\\]/.test(path) : path.startsWith("/");
33
9
  }
34
- /** Replace the extension of a path */
35
- export function replaceExtension(path, ext) {
36
- return path.replace(/\.\w+$/, ext);
37
- }
38
10
  /** Split a path to path + extension */
39
11
  export function getPathAndExtension(path) {
40
12
  const extension = getExtension(path);
@@ -55,25 +27,6 @@ export function matchExtension(exts, path) {
55
27
  }
56
28
  return exts.some((ext) => path.endsWith(ext));
57
29
  }
58
- /**
59
- * Resolve the path of an included file
60
- * Used in the template engines and processors
61
- */
62
- export function resolveInclude(path, includesDir, fromDir, rootToRemove) {
63
- if (isUrl(path)) {
64
- return path;
65
- }
66
- if (path.startsWith(".")) {
67
- if (!fromDir) {
68
- throw new Error(`Cannot load "${path}" without a base directory`);
69
- }
70
- return normalizePath(posix.join(fromDir, path), rootToRemove);
71
- }
72
- const normalized = normalizePath(path, rootToRemove);
73
- return normalized.startsWith(normalizePath(posix.join(includesDir, "/")))
74
- ? normalized
75
- : normalizePath(posix.join(includesDir, normalized));
76
- }
77
30
  /**
78
31
  * decodeURI() can't decode the `%` character, as it is used in any encoded character
79
32
  * @author [Why does decodeURIComponent('%') lock up my browser?](https://stackoverflow.com/a/54310080/3416774)
@@ -1,4 +1,4 @@
1
- import { contentType } from "../../deps/media_types.js";
1
+ import { contentType } from "../../deps/media-types.js";
2
2
  import { decodeURIComponentSafe } from "./path.js";
3
3
  import { extname, posix } from "../../deps/path.js";
4
4
  import { readStream, statSync } from "../services/fs.js";
@@ -1,6 +1,6 @@
1
- import { fromFileUrl, join, relative, toFileUrl } from "../deps/path.js";
2
- import { normalizePath } from "./utils/path.js";
1
+ import { relative } from "../deps/path.js";
3
2
  import Events from "./events.js";
3
+ import Path from "./path.js";
4
4
  import { updateDependencies, updateVersion } from "./services/hmr.js";
5
5
  import { watchFiles } from "./services/fs.js";
6
6
  export default class FSWatcher {
@@ -22,7 +22,8 @@ export default class FSWatcher {
22
22
  /** Start the file watcher */
23
23
  async start() {
24
24
  const { root, ignore, debounce, dependencies } = this.options;
25
- const watcher = watchFiles(root);
25
+ const rootPath = Path.create(root);
26
+ const watcher = watchFiles(rootPath.toString());
26
27
  const changes = new Set();
27
28
  let timer = undefined;
28
29
  let runningCallback = false;
@@ -59,36 +60,35 @@ export default class FSWatcher {
59
60
  }
60
61
  // New changes detected while running the callback
61
62
  if (changes.size) {
62
- callback();
63
+ void callback();
63
64
  }
64
65
  };
65
66
  for await (const changedPaths of watcher) {
66
67
  const paths = new Set();
67
68
  updateVersion();
68
- for (const path of changedPaths.map((p) => normalizePath(p))) {
69
+ for (const path of changedPaths.map((p) => Path.create(p))) {
69
70
  // Filter ignored paths
70
71
  const isIgnored = ignore?.some((condition) => typeof condition === "string"
71
- ? path.startsWith(normalizePath(join(root, condition, "/"))) ||
72
- path === normalizePath(join(root, condition))
73
- : condition(path));
72
+ ? path.belongsTo(rootPath.clone().join(condition))
73
+ : condition(path.toString()));
74
74
  if (isIgnored)
75
75
  continue;
76
- paths.add(path);
77
- for (const dep of updateDependencies(toFileUrl(path).href)) {
78
- paths.add(normalizePath(fromFileUrl(dep)));
76
+ paths.add(path.toString());
77
+ for (const dep of updateDependencies(path.url.href)) {
78
+ paths.add(Path.create(dep).toString());
79
79
  }
80
80
  }
81
81
  if (!paths.size) {
82
82
  continue;
83
83
  }
84
84
  paths.forEach((path) => {
85
- const normalized = normalizePath(relative(root, path));
85
+ const normalized = Path.create(relative(root, path)).toString();
86
86
  changes.add(normalized);
87
87
  // The file has dependencies
88
88
  for (const [file, deps] of Object.entries(dependencies ?? {})) {
89
- const isDependent = deps.some((dep) => normalizePath(dep) === normalized);
89
+ const isDependent = deps.some((dep) => Path.create(dep).toString() === normalized);
90
90
  if (isDependent) {
91
- changes.add(normalizePath(file));
91
+ changes.add(Path.create(file).toString());
92
92
  }
93
93
  }
94
94
  });
@@ -124,7 +124,7 @@ export class SiteWatcher {
124
124
  ...event.pages.map((page) => page.outputPath),
125
125
  ...event.staticFiles.map((file) => file.outputPath),
126
126
  ]);
127
- this.dispatchEvent({ type: "change", files });
127
+ void this.dispatchEvent({ type: "change", files });
128
128
  });
129
129
  }
130
130
  }
@@ -104,9 +104,7 @@ export class FSWriter {
104
104
  return true;
105
105
  }
106
106
  catch (error) {
107
- log.error(
108
- // deno-lint-ignore no-explicit-any
109
- `Failed to copy file: ${file.outputPath}: ${error.message}`);
107
+ log.error(`Failed to copy file: ${file.outputPath}: ${error.message}`);
110
108
  }
111
109
  return false;
112
110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumeland/core",
3
- "version": "1.0.0-beta-7",
3
+ "version": "1.0.0-beta-9",
4
4
  "description": "The core of Lume SSG",
5
5
  "license": "MIT",
6
6
  "author": "Óscar Otero",
@@ -21,9 +21,9 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@lumeland/dom": "^0.1.56",
24
- "@lumeland/plugin-esbuild": "^1.0.0-beta-5",
25
- "@lumeland/plugin-lightningcss": "^1.0.0-beta-5",
26
- "deno-std": "1.5.1",
24
+ "@lumeland/plugin-esbuild": "^1.0.0-beta-9",
25
+ "@lumeland/plugin-lightningcss": "^1.0.0-beta-9",
26
+ "deno-std": "^1.6.0",
27
27
  "remove-markdown": "0.8.0",
28
28
  "temporal-polyfill": "^1.0.6",
29
29
  "ws": "^8.22.0"
@@ -1,2 +0,0 @@
1
- export * from "deno-std/front_matter/any.js";
2
- export { test } from "deno-std/front_matter/test.js";
@@ -1,2 +0,0 @@
1
- export * from "deno-std/front_matter/any.js";
2
- export { test } from "deno-std/front_matter/test.js";
@@ -1,2 +0,0 @@
1
- export { contentType } from "deno-std/media_types/content_type.js";
2
- export { typeByExtension } from "deno-std/media_types/type_by_extension.js";
@@ -1,2 +0,0 @@
1
- export { contentType } from "deno-std/media_types/content_type.js";
2
- export { typeByExtension } from "deno-std/media_types/type_by_extension.js";
File without changes
File without changes
File without changes