@lumeland/core 1.0.0-beta-8 → 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.
- package/README.md +7 -0
- package/build/deps/cli.d.ts +1 -1
- package/build/deps/cli.js +1 -1
- package/build/deps/front-matter.d.ts +2 -0
- package/build/deps/front-matter.js +2 -0
- package/build/deps/media-types.d.ts +2 -0
- package/build/deps/media-types.js +2 -0
- package/build/deps/path.d.ts +1 -1
- package/build/deps/path.js +1 -1
- package/build/src/archetypes.d.ts +11 -2
- package/build/src/archetypes.js +32 -1
- package/build/src/components.js +1 -1
- package/build/src/{data_loader.js → data-loader.js} +1 -1
- package/build/src/loaders/text.js +1 -1
- package/build/src/path.d.ts +20 -0
- package/build/src/path.js +101 -0
- package/build/src/processors.js +0 -1
- package/build/src/renderer.d.ts +0 -3
- package/build/src/renderer.js +11 -19
- package/build/src/searcher.d.ts +1 -1
- package/build/src/searcher.js +7 -5
- package/build/src/server.d.ts +1 -1
- package/build/src/server.js +5 -6
- package/build/src/site.d.ts +4 -12
- package/build/src/site.js +24 -31
- package/build/src/source.d.ts +1 -1
- package/build/src/source.js +8 -7
- package/build/src/types.d.ts +1 -1
- package/build/src/utils/cdn.js +5 -4
- package/build/src/utils/{data_values.js → data-values.js} +0 -1
- package/build/src/utils/includes.d.ts +2 -0
- package/build/src/utils/includes.js +13 -0
- package/build/src/utils/{page_url.js → page-url.js} +3 -6
- package/build/src/utils/path.d.ts +0 -13
- package/build/src/utils/path.js +1 -48
- package/build/src/utils/{serve_file.js → serve-file.js} +1 -1
- package/build/src/watcher.js +15 -15
- package/build/src/writer.js +1 -3
- package/package.json +4 -4
- package/build/deps/front_matter.d.ts +0 -2
- package/build/deps/front_matter.js +0 -2
- package/build/deps/media_types.d.ts +0 -2
- package/build/deps/media_types.js +0 -2
- /package/build/src/{data_loader.d.ts → data-loader.d.ts} +0 -0
- /package/build/src/utils/{css_urls.d.ts → css-urls.d.ts} +0 -0
- /package/build/src/utils/{css_urls.js → css-urls.js} +0 -0
- /package/build/src/utils/{data_values.d.ts → data-values.d.ts} +0 -0
- /package/build/src/utils/{dom_links.d.ts → dom-links.d.ts} +0 -0
- /package/build/src/utils/{dom_links.js → dom-links.js} +0 -0
- /package/build/src/utils/{lume_config.d.ts → lume-config.d.ts} +0 -0
- /package/build/src/utils/{lume_config.js → lume-config.js} +0 -0
- /package/build/src/utils/{merge_data.d.ts → merge-data.d.ts} +0 -0
- /package/build/src/utils/{merge_data.js → merge-data.js} +0 -0
- /package/build/src/utils/{page_content.d.ts → page-content.d.ts} +0 -0
- /package/build/src/utils/{page_content.js → page-content.js} +0 -0
- /package/build/src/utils/{page_date.d.ts → page-date.d.ts} +0 -0
- /package/build/src/utils/{page_date.js → page-date.js} +0 -0
- /package/build/src/utils/{page_url.d.ts → page-url.d.ts} +0 -0
- /package/build/src/utils/{serve_file.d.ts → serve-file.d.ts} +0 -0
package/README.md
ADDED
package/build/deps/cli.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { parseArgs } from "deno-std/cli/
|
|
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/
|
|
1
|
+
export { parseArgs } from "deno-std/cli/parse-args.js";
|
package/build/deps/path.d.ts
CHANGED
|
@@ -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/
|
|
3
|
+
export { globToRegExp } from "deno-std/path/glob-to-regexp.js";
|
|
4
4
|
export { fileURLToPath as fromFileUrl, pathToFileURL as toFileUrl } from "node:url";
|
package/build/deps/path.js
CHANGED
|
@@ -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/
|
|
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,13 +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
20
|
overwrite?: boolean;
|
|
20
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;
|
|
21
30
|
}
|
package/build/src/archetypes.js
CHANGED
|
@@ -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/
|
|
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";
|
|
@@ -16,6 +16,7 @@ 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
18
|
import { read } from "./utils/read.js";
|
|
19
|
+
import { getFiles, isFromCdn } from "./utils/cdn.js";
|
|
19
20
|
export default class Archetypes {
|
|
20
21
|
archetypes = new Map();
|
|
21
22
|
src;
|
|
@@ -53,6 +54,13 @@ export default class Archetypes {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
async save(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
|
+
}
|
|
56
64
|
const { path, base = "src", content, overwrite } = file;
|
|
57
65
|
if (!path) {
|
|
58
66
|
throw new Error("Archetype path is required.");
|
|
@@ -154,3 +162,26 @@ async function readFile(path) {
|
|
|
154
162
|
throw error;
|
|
155
163
|
}
|
|
156
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
|
+
}
|
package/build/src/components.js
CHANGED
|
@@ -12,7 +12,7 @@ export class ComponentLoader {
|
|
|
12
12
|
if (!components) {
|
|
13
13
|
components = new Map();
|
|
14
14
|
}
|
|
15
|
-
for
|
|
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
|
|
29
|
+
for (const child of entry.children.values()) {
|
|
30
30
|
await this.loadEntry(child, data);
|
|
31
31
|
}
|
|
32
32
|
return data;
|
|
@@ -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
|
+
}
|
package/build/src/processors.js
CHANGED
|
@@ -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) => {
|
package/build/src/renderer.d.ts
CHANGED
|
@@ -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/ */
|
package/build/src/renderer.js
CHANGED
|
@@ -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/
|
|
5
|
-
import { getBasename, getPageUrl } from "./utils/
|
|
6
|
-
import { getPageDate } from "./utils/
|
|
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
|
|
176
|
-
if (!
|
|
177
|
-
throw new Error(`The layout
|
|
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
|
|
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,
|
|
180
|
+
content = await this.render(layoutData.content, data, layoutEntry.path, true);
|
|
189
181
|
layout = layoutData.layout;
|
|
190
|
-
path =
|
|
182
|
+
path = layoutEntry.path.split("/_includes/")[0];
|
|
191
183
|
}
|
|
192
184
|
return content;
|
|
193
185
|
}
|
package/build/src/searcher.d.ts
CHANGED
|
@@ -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>(
|
|
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 */
|
package/build/src/searcher.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { globToRegExp } from "../deps/path.js";
|
|
2
|
-
import
|
|
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(
|
|
26
|
-
const
|
|
27
|
-
const dirData = this.#sourceData.get(
|
|
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 ===
|
|
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
|
}
|
package/build/src/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Events from "./events.ts";
|
|
2
|
-
import { serveFile } from "./utils/
|
|
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";
|
package/build/src/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Events from "./events.js";
|
|
2
|
-
import { serveFile } from "./utils/
|
|
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
|
});
|
package/build/src/site.d.ts
CHANGED
|
@@ -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 "./
|
|
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/
|
|
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,
|
|
1
|
+
import { fromFileUrl, posix } from "../deps/path.js";
|
|
2
2
|
import { merge } from "./utils/object.js";
|
|
3
|
-
import { isUrl
|
|
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/
|
|
7
|
-
import { insertContent } from "./utils/
|
|
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 "./
|
|
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 {
|
|
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" ?
|
|
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(
|
|
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
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
package/build/src/source.d.ts
CHANGED
|
@@ -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 "./
|
|
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 {
|
package/build/src/source.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { posix } from "../deps/path.js";
|
|
2
|
-
import { getExtension
|
|
3
|
-
import { mergeData } from "./utils/
|
|
4
|
-
import { getBasename, getPageUrl } from "./utils/
|
|
5
|
-
import { getPageDate } from "./utils/
|
|
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(
|
|
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 =
|
|
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 =
|
|
75
|
+
to = Path.create(to).toString();
|
|
75
76
|
}
|
|
76
77
|
this.addedFiles.set(from, [to, isCopy]);
|
|
77
78
|
}
|
package/build/src/types.d.ts
CHANGED
|
@@ -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/
|
|
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 & {
|
package/build/src/utils/cdn.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { canParse, format, maxSatisfying, parse, parseRange } from "../../deps/semver.js";
|
|
2
|
-
import { fromFileUrl, globToRegExp, join, posix
|
|
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 =
|
|
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,
|
|
48
|
+
fileMap.set(filename.toString(), filename.url.href);
|
|
48
49
|
}
|
|
49
50
|
return fileMap;
|
|
50
51
|
}
|
|
@@ -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
|
|
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 ?
|
|
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
|
-
|
|
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)
|
package/build/src/utils/path.js
CHANGED
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
import {
|
|
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/
|
|
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";
|
package/build/src/watcher.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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) =>
|
|
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.
|
|
72
|
-
|
|
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(
|
|
78
|
-
paths.add(
|
|
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 =
|
|
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) =>
|
|
89
|
+
const isDependent = deps.some((dep) => Path.create(dep).toString() === normalized);
|
|
90
90
|
if (isDependent) {
|
|
91
|
-
changes.add(
|
|
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
|
}
|
package/build/src/writer.js
CHANGED
|
@@ -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-
|
|
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-
|
|
25
|
-
"@lumeland/plugin-lightningcss": "^1.0.0-beta-
|
|
26
|
-
"deno-std": "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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|