ezal-theme-example 0.0.1
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/LICENSE +21 -0
- package/assets/scripts/404.ts +353 -0
- package/assets/scripts/_article.ts +290 -0
- package/assets/scripts/_base.ts +65 -0
- package/assets/scripts/_pagefind.d.ts +424 -0
- package/assets/scripts/_search.ts +88 -0
- package/assets/scripts/_utils.ts +74 -0
- package/assets/scripts/archive.ts +143 -0
- package/assets/scripts/article.ts +18 -0
- package/assets/scripts/category.ts +4 -0
- package/assets/scripts/home.ts +73 -0
- package/assets/scripts/links.ts +14 -0
- package/assets/scripts/main.ts +11 -0
- package/assets/scripts/page.ts +11 -0
- package/assets/scripts/tag.ts +4 -0
- package/assets/scripts/tsconfig.json +10 -0
- package/assets/styles/404.styl +31 -0
- package/assets/styles/_article/fold.styl +15 -0
- package/assets/styles/_article/footnote.styl +12 -0
- package/assets/styles/_article/heading.styl +29 -0
- package/assets/styles/_article/image.styl +30 -0
- package/assets/styles/_article/kbd.styl +10 -0
- package/assets/styles/_article/links.styl +31 -0
- package/assets/styles/_article/list.styl +19 -0
- package/assets/styles/_article/note.styl +18 -0
- package/assets/styles/_article/other.styl +44 -0
- package/assets/styles/_article/table.styl +29 -0
- package/assets/styles/_article/tabs.styl +25 -0
- package/assets/styles/_code.styl +83 -0
- package/assets/styles/_index/contact.styl +20 -0
- package/assets/styles/_index/footer.styl +5 -0
- package/assets/styles/_index/header.styl +40 -0
- package/assets/styles/_index/nav.styl +59 -0
- package/assets/styles/_index/search.styl +64 -0
- package/assets/styles/_index.styl +91 -0
- package/assets/styles/_var.styl +96 -0
- package/assets/styles/archive.styl +35 -0
- package/assets/styles/article.styl +138 -0
- package/assets/styles/category.styl +4 -0
- package/assets/styles/home.styl +124 -0
- package/assets/styles/links.styl +121 -0
- package/assets/styles/page.styl +12 -0
- package/assets/styles/tag.styl +4 -0
- package/dist/config.d.ts +128 -0
- package/dist/feed.d.ts +4 -0
- package/dist/image/asset.d.ts +22 -0
- package/dist/image/db.d.ts +18 -0
- package/dist/image/index.d.ts +10 -0
- package/dist/image/metadata.d.ts +2 -0
- package/dist/image/utils.d.ts +1 -0
- package/dist/index-now.d.ts +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2066 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +2 -0
- package/dist/markdown/codeblock/data.d.ts +1 -0
- package/dist/markdown/codeblock/index.d.ts +6 -0
- package/dist/markdown/codeblock/style.d.ts +2 -0
- package/dist/markdown/fold.d.ts +6 -0
- package/dist/markdown/footnote.d.ts +15 -0
- package/dist/markdown/image.d.ts +12 -0
- package/dist/markdown/index.d.ts +2 -0
- package/dist/markdown/kbd.d.ts +6 -0
- package/dist/markdown/link.d.ts +2 -0
- package/dist/markdown/links.d.ts +12 -0
- package/dist/markdown/note.d.ts +8 -0
- package/dist/markdown/table.d.ts +3 -0
- package/dist/markdown/tabs.d.ts +7 -0
- package/dist/markdown/tex.d.ts +9 -0
- package/dist/page/404.d.ts +1 -0
- package/dist/page/archive.d.ts +1 -0
- package/dist/page/category.d.ts +1 -0
- package/dist/page/home.d.ts +2 -0
- package/dist/page/tag.d.ts +1 -0
- package/dist/pagefind.d.ts +20 -0
- package/dist/sitemap.d.ts +2 -0
- package/dist/transform/script.d.ts +2 -0
- package/dist/transform/stylus.d.ts +2 -0
- package/dist/utils.d.ts +2 -0
- package/layouts/404.tsx +8 -0
- package/layouts/archive.tsx +81 -0
- package/layouts/article.tsx +145 -0
- package/layouts/base.tsx +20 -0
- package/layouts/category.tsx +18 -0
- package/layouts/components/ArchiveArticleList.tsx +14 -0
- package/layouts/components/Article.tsx +46 -0
- package/layouts/components/Contact.tsx +14 -0
- package/layouts/components/Footer.tsx +44 -0
- package/layouts/components/Head.tsx +119 -0
- package/layouts/components/Image.tsx +42 -0
- package/layouts/components/Nav.tsx +33 -0
- package/layouts/components/Search.tsx +20 -0
- package/layouts/components/Waline.tsx +22 -0
- package/layouts/context.d.ts +54 -0
- package/layouts/home.tsx +74 -0
- package/layouts/links.tsx +53 -0
- package/layouts/page.tsx +19 -0
- package/layouts/tag.tsx +18 -0
- package/layouts/tsconfig.json +11 -0
- package/package.json +47 -0
- package/readme.md +17 -0
- package/readme_zh.md +17 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2066 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
let node_path = require("node:path");
|
|
25
|
+
node_path = __toESM(node_path);
|
|
26
|
+
let ezal = require("ezal");
|
|
27
|
+
let feed = require("feed");
|
|
28
|
+
let node_path_posix = require("node:path/posix");
|
|
29
|
+
node_path_posix = __toESM(node_path_posix);
|
|
30
|
+
let node_fs = require("node:fs");
|
|
31
|
+
let sharp = require("sharp");
|
|
32
|
+
sharp = __toESM(sharp);
|
|
33
|
+
let better_sqlite3 = require("better-sqlite3");
|
|
34
|
+
better_sqlite3 = __toESM(better_sqlite3);
|
|
35
|
+
let node_crypto = require("node:crypto");
|
|
36
|
+
let node_fs_promises = require("node:fs/promises");
|
|
37
|
+
let node_vibrant_node = require("node-vibrant/node");
|
|
38
|
+
let indexnow = require("indexnow");
|
|
39
|
+
indexnow = __toESM(indexnow);
|
|
40
|
+
let ezal_layout = require("ezal-layout");
|
|
41
|
+
let mime_types = require("mime-types");
|
|
42
|
+
mime_types = __toESM(mime_types);
|
|
43
|
+
let ezal_markdown = require("ezal-markdown");
|
|
44
|
+
let __shikijs_colorized_brackets = require("@shikijs/colorized-brackets");
|
|
45
|
+
let __shikijs_transformers = require("@shikijs/transformers");
|
|
46
|
+
let __vscode_vscode_languagedetection = require("@vscode/vscode-languagedetection");
|
|
47
|
+
let shiki = require("shiki");
|
|
48
|
+
let clean_css = require("clean-css");
|
|
49
|
+
clean_css = __toESM(clean_css);
|
|
50
|
+
let stylus = require("stylus");
|
|
51
|
+
stylus = __toESM(stylus);
|
|
52
|
+
let katex = require("katex");
|
|
53
|
+
katex = __toESM(katex);
|
|
54
|
+
let sitemap = require("sitemap");
|
|
55
|
+
let esbuild = require("esbuild");
|
|
56
|
+
esbuild = __toESM(esbuild);
|
|
57
|
+
|
|
58
|
+
//#region packages/ezal-theme-example/src/config.ts
|
|
59
|
+
let config$1;
|
|
60
|
+
function setThemeConfig(cfg) {
|
|
61
|
+
config$1 = cfg ?? {};
|
|
62
|
+
}
|
|
63
|
+
function getThemeConfig() {
|
|
64
|
+
return config$1;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region packages/ezal-theme-example/src/utils.ts
|
|
69
|
+
function compareByDate(a, b) {
|
|
70
|
+
return b.date.epochMilliseconds - a.date.epochMilliseconds;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region packages/ezal-theme-example/src/feed.ts
|
|
75
|
+
const FEED_TYPE_URL = {
|
|
76
|
+
rss: "/rss.xml",
|
|
77
|
+
atom: "/atom.xml",
|
|
78
|
+
feed: "/feed.json"
|
|
79
|
+
};
|
|
80
|
+
let author;
|
|
81
|
+
let feed$1;
|
|
82
|
+
let assets$1;
|
|
83
|
+
var FeedAsset = class extends ezal.VirtualAssets {
|
|
84
|
+
#type;
|
|
85
|
+
constructor(type) {
|
|
86
|
+
super(FEED_TYPE_URL[type]);
|
|
87
|
+
this.#type = type;
|
|
88
|
+
}
|
|
89
|
+
build() {
|
|
90
|
+
switch (this.#type) {
|
|
91
|
+
case "rss": return feed$1.rss2();
|
|
92
|
+
case "atom": return feed$1.atom1();
|
|
93
|
+
case "feed": return feed$1.json1();
|
|
94
|
+
default: return "";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
onDependenciesChanged() {}
|
|
98
|
+
};
|
|
99
|
+
function initFeed() {
|
|
100
|
+
const { site } = (0, ezal.getConfig)();
|
|
101
|
+
const theme$1 = getThemeConfig();
|
|
102
|
+
const since = theme$1.since?.year;
|
|
103
|
+
author = {
|
|
104
|
+
name: site.author,
|
|
105
|
+
link: site.domain
|
|
106
|
+
};
|
|
107
|
+
feed$1 = new feed.Feed({
|
|
108
|
+
title: site.title,
|
|
109
|
+
description: site.description,
|
|
110
|
+
id: site.domain,
|
|
111
|
+
language: site.language,
|
|
112
|
+
favicon: theme$1.favicon?.[0],
|
|
113
|
+
copyright: `© ${since ? `${since}-` : ""}${(/* @__PURE__ */ new Date()).getFullYear()} ${site.author}`,
|
|
114
|
+
author,
|
|
115
|
+
updated: /* @__PURE__ */ new Date(),
|
|
116
|
+
feedLinks: {
|
|
117
|
+
rss: `${site.domain}/rss.xml`,
|
|
118
|
+
atom: `${site.domain}/atom.xml`,
|
|
119
|
+
json: `${site.domain}/feed.json`
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
assets$1 = {
|
|
123
|
+
rss: new FeedAsset("rss"),
|
|
124
|
+
atom: new FeedAsset("atom"),
|
|
125
|
+
feed: new FeedAsset("feed")
|
|
126
|
+
};
|
|
127
|
+
for (const article of ezal.Article.getAll().sort(compareByDate)) updateFeedItem(article);
|
|
128
|
+
for (const category of ezal.Category.getAll()) updateFeedCategory(category);
|
|
129
|
+
}
|
|
130
|
+
function refreshAsset() {
|
|
131
|
+
if (!assets$1) return;
|
|
132
|
+
assets$1.rss.invalidated();
|
|
133
|
+
assets$1.atom.invalidated();
|
|
134
|
+
assets$1.feed.invalidated();
|
|
135
|
+
}
|
|
136
|
+
function updateFeedItem(article) {
|
|
137
|
+
if (!feed$1) return;
|
|
138
|
+
const i = feed$1.items.findIndex((item$1) => item$1.id === article.id);
|
|
139
|
+
if (article.destroyed) {
|
|
140
|
+
if (i === -1) return;
|
|
141
|
+
feed$1.items.splice(i, 1);
|
|
142
|
+
return refreshAsset();
|
|
143
|
+
}
|
|
144
|
+
const { site } = (0, ezal.getConfig)();
|
|
145
|
+
let image$1 = article.data?.cover ? ezal.URL.resolve(article.url, article.data.cover) : void 0;
|
|
146
|
+
if (image$1) image$1 = site.domain + image$1;
|
|
147
|
+
const item = {
|
|
148
|
+
title: article.title,
|
|
149
|
+
id: article.id,
|
|
150
|
+
link: site.domain + article.url,
|
|
151
|
+
description: article.description,
|
|
152
|
+
content: article.content,
|
|
153
|
+
author: [author],
|
|
154
|
+
date: new Date(article.date.toInstant().epochMilliseconds),
|
|
155
|
+
image: image$1,
|
|
156
|
+
category: article.categories.values().toArray().map((category) => ({ name: category.path.join("/") }))
|
|
157
|
+
};
|
|
158
|
+
if (i === -1) feed$1.addItem(item);
|
|
159
|
+
else feed$1.items[i] = item;
|
|
160
|
+
refreshAsset();
|
|
161
|
+
}
|
|
162
|
+
function updateFeedCategory(category) {
|
|
163
|
+
if (!feed$1) return;
|
|
164
|
+
const name = category.path.join("/");
|
|
165
|
+
const i = feed$1.categories.indexOf(name);
|
|
166
|
+
if (category.destroyed) {
|
|
167
|
+
if (i === -1) return;
|
|
168
|
+
feed$1.categories.splice(i, 1);
|
|
169
|
+
return refreshAsset();
|
|
170
|
+
}
|
|
171
|
+
if (i !== -1) return;
|
|
172
|
+
feed$1.addCategory(name);
|
|
173
|
+
refreshAsset();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region packages/ezal-theme-example/src/image/utils.ts
|
|
178
|
+
let dir;
|
|
179
|
+
function getCacheDir() {
|
|
180
|
+
if (dir) return dir;
|
|
181
|
+
dir = getThemeConfig().imageCache?.optimized ?? "cache";
|
|
182
|
+
if (!node_path.default.isAbsolute(dir)) dir = node_path.default.resolve(dir);
|
|
183
|
+
return dir;
|
|
184
|
+
}
|
|
185
|
+
function getOptimizedPath(filepath, ext) {
|
|
186
|
+
const dir$1 = getCacheDir();
|
|
187
|
+
const cachePath = node_path.default.relative(process.cwd(), filepath);
|
|
188
|
+
return `${node_path.default.join(dir$1, cachePath)}.opt${ext}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region packages/ezal-theme-example/src/image/asset.ts
|
|
193
|
+
const OPTIMIZE = {
|
|
194
|
+
".avif": (sharp$1) => sharp$1.avif().toBuffer(),
|
|
195
|
+
".webp": (sharp$1) => sharp$1.webp().toBuffer(),
|
|
196
|
+
".jxl": (sharp$1) => sharp$1.jxl().toBuffer(),
|
|
197
|
+
".jpg": (sharp$1) => sharp$1.jpeg({
|
|
198
|
+
trellisQuantisation: true,
|
|
199
|
+
overshootDeringing: true,
|
|
200
|
+
progressive: true,
|
|
201
|
+
optimiseScans: true
|
|
202
|
+
}).toBuffer(),
|
|
203
|
+
".png": (sharp$1) => sharp$1.png({
|
|
204
|
+
progressive: true,
|
|
205
|
+
adaptiveFiltering: true
|
|
206
|
+
}).toBuffer(),
|
|
207
|
+
".gif": (sharp$1) => sharp$1.gif().toBuffer()
|
|
208
|
+
};
|
|
209
|
+
var OptimizedImage = class extends ezal.VirtualAssets {
|
|
210
|
+
#optimizedPath;
|
|
211
|
+
#filepath;
|
|
212
|
+
#ext;
|
|
213
|
+
/**
|
|
214
|
+
* @param asset 源资源
|
|
215
|
+
* @param target 目标优化格式
|
|
216
|
+
*/
|
|
217
|
+
constructor(asset$2, ext) {
|
|
218
|
+
super(ezal.URL.extname(asset$2.url, `.opt${ext}`));
|
|
219
|
+
this.#filepath = asset$2.filepath;
|
|
220
|
+
this.#ext = ext;
|
|
221
|
+
this.#optimizedPath = getOptimizedPath(this.#filepath, ext);
|
|
222
|
+
}
|
|
223
|
+
async build() {
|
|
224
|
+
if (await ezal.fs.isFile(this.#optimizedPath)) return (0, node_fs.createReadStream)(this.#optimizedPath);
|
|
225
|
+
const sharp$1 = (0, sharp.default)(this.#filepath);
|
|
226
|
+
const buffer = await OPTIMIZE[this.#ext](sharp$1);
|
|
227
|
+
ezal.fs.writeFile(this.#optimizedPath, buffer);
|
|
228
|
+
return buffer;
|
|
229
|
+
}
|
|
230
|
+
onDependenciesChanged() {}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region packages/ezal-theme-example/src/image/db.ts
|
|
235
|
+
let db;
|
|
236
|
+
let statements;
|
|
237
|
+
function getMetadata(url) {
|
|
238
|
+
return statements.get.get(url);
|
|
239
|
+
}
|
|
240
|
+
function updateMetadata(data) {
|
|
241
|
+
return statements.update.run(data.path, data.hash, data.width, data.height, data.color).changes !== 0;
|
|
242
|
+
}
|
|
243
|
+
function deleteMetadata(url) {
|
|
244
|
+
return statements.delete.run(url).changes !== 0;
|
|
245
|
+
}
|
|
246
|
+
function initImageMetadataDB() {
|
|
247
|
+
let filename = getThemeConfig().imageCache?.metadata ?? "image-metadata.sqlite";
|
|
248
|
+
if (!node_path.default.isAbsolute(filename)) filename = node_path.default.resolve(filename);
|
|
249
|
+
db = new better_sqlite3.default(filename);
|
|
250
|
+
db.exec(`CREATE TABLE IF NOT EXISTS image_metadata (
|
|
251
|
+
path TEXT PRIMARY KEY,
|
|
252
|
+
hash TEXT NOT NULL,
|
|
253
|
+
width INTEGER NOT NULL,
|
|
254
|
+
height INTEGER NOT NULL,
|
|
255
|
+
color TEXT(8)
|
|
256
|
+
)`);
|
|
257
|
+
statements = {
|
|
258
|
+
get: db.prepare("SELECT * FROM image_metadata WHERE path = ?"),
|
|
259
|
+
delete: db.prepare("DELETE FROM image_metadata WHERE path = ?"),
|
|
260
|
+
update: db.prepare(`INSERT OR REPLACE INTO image_metadata
|
|
261
|
+
(path, hash, width, height, color)
|
|
262
|
+
VALUES (?, ?, ?, ?, ?)
|
|
263
|
+
`)
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
const imageDB = {
|
|
267
|
+
init: initImageMetadataDB,
|
|
268
|
+
get: getMetadata,
|
|
269
|
+
update: updateMetadata,
|
|
270
|
+
delete: deleteMetadata
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region packages/ezal-theme-example/src/image/metadata.ts
|
|
275
|
+
async function updateImageMetadata(asset$2) {
|
|
276
|
+
const buffer = await (0, node_fs_promises.readFile)(asset$2.filepath);
|
|
277
|
+
const hash = (0, node_crypto.createHash)("sha256").update(buffer).digest("hex");
|
|
278
|
+
if (imageDB.get(asset$2.url)?.hash === hash) return false;
|
|
279
|
+
const { width, height, format } = await (0, sharp.default)(buffer).metadata();
|
|
280
|
+
let color = null;
|
|
281
|
+
if (format !== "svg") try {
|
|
282
|
+
color = (await node_vibrant_node.Vibrant.from(buffer).getPalette()).Muted?.hex ?? null;
|
|
283
|
+
} catch {}
|
|
284
|
+
const metadata = {
|
|
285
|
+
path: asset$2.url,
|
|
286
|
+
hash,
|
|
287
|
+
width,
|
|
288
|
+
height,
|
|
289
|
+
color
|
|
290
|
+
};
|
|
291
|
+
imageDB.update(metadata);
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region packages/ezal-theme-example/src/image/index.ts
|
|
297
|
+
const INFO = {
|
|
298
|
+
ADD: "Add image file:",
|
|
299
|
+
UPDATE: "Update image file:",
|
|
300
|
+
REMOVE: "Remove image file:",
|
|
301
|
+
OPTIMIZE: (path$8) => `The image "${path$8}" will be generated in this format:`
|
|
302
|
+
};
|
|
303
|
+
const ERR = { METADATA: (path$8) => `Unable to update metadata for "${path$8}"` };
|
|
304
|
+
const SUPPORT_EXTS = new Set([
|
|
305
|
+
".jpeg",
|
|
306
|
+
".jpg",
|
|
307
|
+
".png",
|
|
308
|
+
".gif",
|
|
309
|
+
".webp",
|
|
310
|
+
".svg",
|
|
311
|
+
".tiff",
|
|
312
|
+
".tif",
|
|
313
|
+
".avif",
|
|
314
|
+
".heif",
|
|
315
|
+
".jxl"
|
|
316
|
+
]);
|
|
317
|
+
const OPTIMIZE_RULES = new Map([
|
|
318
|
+
[".jpeg", [
|
|
319
|
+
".avif",
|
|
320
|
+
".webp",
|
|
321
|
+
".jxl",
|
|
322
|
+
".jpg"
|
|
323
|
+
]],
|
|
324
|
+
[".jpg", [
|
|
325
|
+
".avif",
|
|
326
|
+
".webp",
|
|
327
|
+
".jpg"
|
|
328
|
+
]],
|
|
329
|
+
[".png", [
|
|
330
|
+
".avif",
|
|
331
|
+
".webp",
|
|
332
|
+
".png"
|
|
333
|
+
]],
|
|
334
|
+
[".webp", [
|
|
335
|
+
".avif",
|
|
336
|
+
".webp",
|
|
337
|
+
".png"
|
|
338
|
+
]],
|
|
339
|
+
[".avif", [
|
|
340
|
+
".avif",
|
|
341
|
+
".webp",
|
|
342
|
+
".png"
|
|
343
|
+
]]
|
|
344
|
+
]);
|
|
345
|
+
const logger$3 = new ezal.Logger("theme:image");
|
|
346
|
+
const assetsMap = /* @__PURE__ */ new Map();
|
|
347
|
+
function getImageInfo(url) {
|
|
348
|
+
const ext = node_path_posix.default.extname(url).toLowerCase();
|
|
349
|
+
if (!SUPPORT_EXTS.has(ext)) return null;
|
|
350
|
+
return {
|
|
351
|
+
metadata: imageDB.get(url),
|
|
352
|
+
rule: OPTIMIZE_RULES.get(ext)
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
async function cleanOptimized(asset$2) {
|
|
356
|
+
const ext = node_path_posix.default.extname(asset$2.filepath).toLowerCase();
|
|
357
|
+
const rule = OPTIMIZE_RULES.get(ext);
|
|
358
|
+
if (!rule) return;
|
|
359
|
+
await Promise.all(rule.map((ext$1) => getOptimizedPath(asset$2.filepath, ext$1)).map((filepath) => ezal.fs.remove(filepath)));
|
|
360
|
+
}
|
|
361
|
+
async function imageAddHook(asset$2) {
|
|
362
|
+
if (asset$2.level !== "user") return;
|
|
363
|
+
const ext = node_path_posix.default.extname(asset$2.filepath).toLowerCase();
|
|
364
|
+
if (!SUPPORT_EXTS.has(ext)) return;
|
|
365
|
+
logger$3.debug(INFO.ADD, asset$2.filepath);
|
|
366
|
+
let updated = false;
|
|
367
|
+
try {
|
|
368
|
+
updated = await updateImageMetadata(asset$2);
|
|
369
|
+
} catch (error) {
|
|
370
|
+
logger$3.error(ERR.METADATA(asset$2.filepath), error);
|
|
371
|
+
}
|
|
372
|
+
if (updated) await cleanOptimized(asset$2);
|
|
373
|
+
const rule = OPTIMIZE_RULES.get(ext);
|
|
374
|
+
if (!rule) return;
|
|
375
|
+
logger$3.debug(INFO.OPTIMIZE(asset$2.filepath), rule);
|
|
376
|
+
const assets$2 = rule.map((ext$1) => {
|
|
377
|
+
try {
|
|
378
|
+
return new OptimizedImage(asset$2, ext$1);
|
|
379
|
+
} catch (error) {
|
|
380
|
+
logger$3.warn(error);
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}).filter((v) => v);
|
|
384
|
+
assetsMap.set(asset$2.url, assets$2);
|
|
385
|
+
}
|
|
386
|
+
async function imageUpdateHook(asset$2) {
|
|
387
|
+
if (asset$2.level !== "user") return;
|
|
388
|
+
const ext = node_path_posix.default.extname(asset$2.filepath).toLowerCase();
|
|
389
|
+
if (!SUPPORT_EXTS.has(ext)) return;
|
|
390
|
+
logger$3.debug(INFO.UPDATE, asset$2.filepath);
|
|
391
|
+
let updated = false;
|
|
392
|
+
try {
|
|
393
|
+
updated = await updateImageMetadata(asset$2);
|
|
394
|
+
} catch (error) {
|
|
395
|
+
logger$3.error(ERR.METADATA(asset$2.filepath), error);
|
|
396
|
+
}
|
|
397
|
+
if (updated) await cleanOptimized(asset$2);
|
|
398
|
+
const assets$2 = assetsMap.get(asset$2.url);
|
|
399
|
+
if (!assets$2) return;
|
|
400
|
+
for (const asset$3 of assets$2) asset$3.invalidated();
|
|
401
|
+
}
|
|
402
|
+
function imageRemoveHook(asset$2) {
|
|
403
|
+
if (asset$2.level !== "user") return;
|
|
404
|
+
const ext = node_path_posix.default.extname(asset$2.filepath).toLowerCase();
|
|
405
|
+
if (!SUPPORT_EXTS.has(ext)) return;
|
|
406
|
+
logger$3.debug(INFO.REMOVE, asset$2.filepath);
|
|
407
|
+
imageDB.delete(asset$2.filepath);
|
|
408
|
+
const assets$2 = assetsMap.get(asset$2.url);
|
|
409
|
+
if (!assets$2) return;
|
|
410
|
+
assetsMap.delete(asset$2.url);
|
|
411
|
+
for (const asset$3 of assets$2) asset$3.destroy();
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
//#endregion
|
|
415
|
+
//#region packages/ezal-theme-example/src/index-now.ts
|
|
416
|
+
const logger$2 = new ezal.Logger("theme:index-now");
|
|
417
|
+
async function exeIndexNow() {
|
|
418
|
+
const { site } = (0, ezal.getConfig)();
|
|
419
|
+
const { indexNow } = getThemeConfig();
|
|
420
|
+
if (!indexNow) return;
|
|
421
|
+
logger$2.log("Collecting data...");
|
|
422
|
+
const urls = [];
|
|
423
|
+
for (const article of ezal.Article.getAll()) {
|
|
424
|
+
if (article.data?.robots === false) continue;
|
|
425
|
+
urls.push(site.domain + article.url);
|
|
426
|
+
}
|
|
427
|
+
for (const page of ezal.Page.getAll()) {
|
|
428
|
+
if (!page.data?.robots) continue;
|
|
429
|
+
urls.push(site.domain + page.url);
|
|
430
|
+
}
|
|
431
|
+
if (indexNow.bing) {
|
|
432
|
+
logger$2.log("Submitting urls to Bing...");
|
|
433
|
+
await new indexnow.default(indexnow.SEARCH_ENGINES.BING, indexNow.bing).submitUrls(site.domain, urls);
|
|
434
|
+
}
|
|
435
|
+
if (indexNow.yandex) {
|
|
436
|
+
logger$2.log("Submitting urls to Yandex...");
|
|
437
|
+
await new indexnow.default(indexnow.SEARCH_ENGINES.YANDEX, indexNow.yandex).submitUrls(site.domain, urls);
|
|
438
|
+
}
|
|
439
|
+
logger$2.log("Finished");
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region packages/ezal-theme-example/src/layout.ts
|
|
444
|
+
const EXTERNAL_MODULES = Object.fromEntries([
|
|
445
|
+
"mime-types",
|
|
446
|
+
"ezal",
|
|
447
|
+
"@js-temporal/polyfill"
|
|
448
|
+
].map((name) => [name, require(name)]));
|
|
449
|
+
function createRenderer(template) {
|
|
450
|
+
return (page) => {
|
|
451
|
+
const { site } = (0, ezal.getConfig)();
|
|
452
|
+
const context = {
|
|
453
|
+
page,
|
|
454
|
+
site,
|
|
455
|
+
theme: getThemeConfig(),
|
|
456
|
+
getImageInfo,
|
|
457
|
+
mime: mime_types.default,
|
|
458
|
+
compareByDate
|
|
459
|
+
};
|
|
460
|
+
try {
|
|
461
|
+
return template(context);
|
|
462
|
+
} catch (error) {
|
|
463
|
+
return (0, ezal.normalizeError)(error);
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
async function compiler(src) {
|
|
468
|
+
try {
|
|
469
|
+
const { renderer: template, dependencies } = await (0, ezal_layout.compile)(src, EXTERNAL_MODULES);
|
|
470
|
+
return {
|
|
471
|
+
renderer: createRenderer(template),
|
|
472
|
+
dependencies
|
|
473
|
+
};
|
|
474
|
+
} catch (error) {
|
|
475
|
+
return (0, ezal.normalizeError)(error);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
const layoutConfig = {
|
|
479
|
+
root: node_path.default.join(__dirname, "../layouts"),
|
|
480
|
+
compiler
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
//#endregion
|
|
484
|
+
//#region packages/ezal-theme-example/src/markdown/codeblock/data.ts
|
|
485
|
+
const LANGUAGE_MAP = new Map([
|
|
486
|
+
["markup", "Markup"],
|
|
487
|
+
["html", "HTML"],
|
|
488
|
+
["xml", "XML"],
|
|
489
|
+
["svg", "SVG"],
|
|
490
|
+
["mathml", "MathML"],
|
|
491
|
+
["ssml", "SSML"],
|
|
492
|
+
["atom", "Atom"],
|
|
493
|
+
["rss", "RSS"],
|
|
494
|
+
["css", "CSS"],
|
|
495
|
+
["clike", "C-like"],
|
|
496
|
+
["javascript", "JavaScript"],
|
|
497
|
+
["js", "JavaScript"],
|
|
498
|
+
["abap", "ABAP"],
|
|
499
|
+
["abnf", "ABNF"],
|
|
500
|
+
["actionscript", "ActionScript"],
|
|
501
|
+
["ada", "Ada"],
|
|
502
|
+
["agda", "Agda"],
|
|
503
|
+
["al", "AL"],
|
|
504
|
+
["antlr4", "ANTLR4"],
|
|
505
|
+
["g4", "ANTLR4"],
|
|
506
|
+
["apacheconf", "Apache Configuration"],
|
|
507
|
+
["apex", "Apex"],
|
|
508
|
+
["apl", "APL"],
|
|
509
|
+
["applescript", "AppleScript"],
|
|
510
|
+
["aql", "AQL"],
|
|
511
|
+
["arduino", "Arduino"],
|
|
512
|
+
["ino", "Arduino"],
|
|
513
|
+
["arff", "ARFF"],
|
|
514
|
+
["armasm", "ARM Assembly"],
|
|
515
|
+
["arm-asm", "ARM Assembly"],
|
|
516
|
+
["arturo", "Arturo"],
|
|
517
|
+
["art", "Arturo"],
|
|
518
|
+
["asciidoc", "AsciiDoc"],
|
|
519
|
+
["adoc", "AsciiDoc"],
|
|
520
|
+
["aspnet", "ASP.NET (C#)"],
|
|
521
|
+
["asm6502", "6502 Assembly"],
|
|
522
|
+
["asmatmel", "Atmel AVR Assembly"],
|
|
523
|
+
["autohotkey", "AutoHotkey"],
|
|
524
|
+
["autoit", "AutoIt"],
|
|
525
|
+
["avisynth", "AviSynth"],
|
|
526
|
+
["avs", "AviSynth"],
|
|
527
|
+
["avro-idl", "Avro IDL"],
|
|
528
|
+
["avdl", "Avro IDL"],
|
|
529
|
+
["awk", "AWK"],
|
|
530
|
+
["gawk", "AWK"],
|
|
531
|
+
["bash", "Bash"],
|
|
532
|
+
["sh", "Bash"],
|
|
533
|
+
["shell", "Bash"],
|
|
534
|
+
["basic", "BASIC"],
|
|
535
|
+
["batch", "Batch"],
|
|
536
|
+
["bbcode", "BBcode"],
|
|
537
|
+
["shortcode", "BBcode"],
|
|
538
|
+
["bbj", "BBj"],
|
|
539
|
+
["bicep", "Bicep"],
|
|
540
|
+
["birb", "Birb"],
|
|
541
|
+
["bison", "Bison"],
|
|
542
|
+
["bnf", "BNF"],
|
|
543
|
+
["rbnf", "BNF"],
|
|
544
|
+
["bqn", "BQN"],
|
|
545
|
+
["brainfuck", "Brainfuck"],
|
|
546
|
+
["brightscript", "BrightScript"],
|
|
547
|
+
["bro", "Bro"],
|
|
548
|
+
["bsl", "BSL (1C:Enterprise)"],
|
|
549
|
+
["oscript", "BSL (1C:Enterprise)"],
|
|
550
|
+
["c", "C"],
|
|
551
|
+
["csharp", "C#"],
|
|
552
|
+
["cs", "C#"],
|
|
553
|
+
["dotnet", "C#"],
|
|
554
|
+
["cpp", "C++"],
|
|
555
|
+
["cfscript", "CFScript"],
|
|
556
|
+
["cfc", "CFScript"],
|
|
557
|
+
["chaiscript", "ChaiScript"],
|
|
558
|
+
["cil", "CIL"],
|
|
559
|
+
["cilkc", "Cilk/C"],
|
|
560
|
+
["cilk-c", "Cilk/C"],
|
|
561
|
+
["cilkcpp", "Cilk/C++"],
|
|
562
|
+
["cilk-cpp", "Cilk/C++"],
|
|
563
|
+
["cilk", "Cilk/C++"],
|
|
564
|
+
["clojure", "Clojure"],
|
|
565
|
+
["cmake", "CMake"],
|
|
566
|
+
["cobol", "COBOL"],
|
|
567
|
+
["coffeescript", "CoffeeScript"],
|
|
568
|
+
["coffee", "CoffeeScript"],
|
|
569
|
+
["concurnas", "Concurnas"],
|
|
570
|
+
["conc", "Concurnas"],
|
|
571
|
+
["csp", "Content-Security-Policy"],
|
|
572
|
+
["cooklang", "Cooklang"],
|
|
573
|
+
["coq", "Coq"],
|
|
574
|
+
["crystal", "Crystal"],
|
|
575
|
+
["css-extras", "CSS Extras"],
|
|
576
|
+
["csv", "CSV"],
|
|
577
|
+
["cue", "CUE"],
|
|
578
|
+
["cypher", "Cypher"],
|
|
579
|
+
["d", "D"],
|
|
580
|
+
["dart", "Dart"],
|
|
581
|
+
["dataweave", "DataWeave"],
|
|
582
|
+
["dax", "DAX"],
|
|
583
|
+
["dhall", "Dhall"],
|
|
584
|
+
["diff", "Diff"],
|
|
585
|
+
["django", "Django/Jinja2"],
|
|
586
|
+
["jinja2", "Django/Jinja2"],
|
|
587
|
+
["dns-zone-file", "DNS zone file"],
|
|
588
|
+
["dns-zone", "DNS zone file"],
|
|
589
|
+
["docker", "Docker"],
|
|
590
|
+
["dockerfile", "Docker"],
|
|
591
|
+
["dot", "DOT (Graphviz)"],
|
|
592
|
+
["gv", "DOT (Graphviz)"],
|
|
593
|
+
["ebnf", "EBNF"],
|
|
594
|
+
["editorconfig", "EditorConfig"],
|
|
595
|
+
["eiffel", "Eiffel"],
|
|
596
|
+
["ejs", "EJS"],
|
|
597
|
+
["eta", "EJS"],
|
|
598
|
+
["elixir", "Elixir"],
|
|
599
|
+
["elm", "Elm"],
|
|
600
|
+
["etlua", "Embedded Lua templating"],
|
|
601
|
+
["erb", "ERB"],
|
|
602
|
+
["erlang", "Erlang"],
|
|
603
|
+
["excel-formula", "Excel Formula"],
|
|
604
|
+
["xlsx", "Excel Formula"],
|
|
605
|
+
["xls", "Excel Formula"],
|
|
606
|
+
["fsharp", "F#"],
|
|
607
|
+
["factor", "Factor"],
|
|
608
|
+
["false", "False"],
|
|
609
|
+
["firestore-security-rules", "Firestore security rules"],
|
|
610
|
+
["flow", "Flow"],
|
|
611
|
+
["fortran", "Fortran"],
|
|
612
|
+
["ftl", "FreeMarker Template Language"],
|
|
613
|
+
["gml", "GameMaker Language"],
|
|
614
|
+
["gamemakerlanguage", "GameMaker Language"],
|
|
615
|
+
["gap", "GAP (CAS)"],
|
|
616
|
+
["gcode", "G-code"],
|
|
617
|
+
["gdscript", "GDScript"],
|
|
618
|
+
["gedcom", "GEDCOM"],
|
|
619
|
+
["gettext", "gettext"],
|
|
620
|
+
["po", "gettext"],
|
|
621
|
+
["gherkin", "Gherkin"],
|
|
622
|
+
["git", "Git"],
|
|
623
|
+
["glsl", "GLSL"],
|
|
624
|
+
["gn", "GN"],
|
|
625
|
+
["gni", "GN"],
|
|
626
|
+
["linker-script", "GNU Linker Script"],
|
|
627
|
+
["ld", "GNU Linker Script"],
|
|
628
|
+
["go", "Go"],
|
|
629
|
+
["go-module", "Go module"],
|
|
630
|
+
["go-mod", "Go module"],
|
|
631
|
+
["gradle", "Gradle"],
|
|
632
|
+
["graphql", "GraphQL"],
|
|
633
|
+
["groovy", "Groovy"],
|
|
634
|
+
["haml", "Haml"],
|
|
635
|
+
["handlebars", "Handlebars"],
|
|
636
|
+
["hbs", "Handlebars"],
|
|
637
|
+
["mustache", "Handlebars"],
|
|
638
|
+
["haskell", "Haskell"],
|
|
639
|
+
["hs", "Haskell"],
|
|
640
|
+
["haxe", "Haxe"],
|
|
641
|
+
["hcl", "HCL"],
|
|
642
|
+
["hlsl", "HLSL"],
|
|
643
|
+
["hoon", "Hoon"],
|
|
644
|
+
["http", "HTTP"],
|
|
645
|
+
["hpkp", "HTTP Public-Key-Pins"],
|
|
646
|
+
["hsts", "HTTP Strict-Transport-Security"],
|
|
647
|
+
["ichigojam", "IchigoJam"],
|
|
648
|
+
["icon", "Icon"],
|
|
649
|
+
["icu-message-format", "ICU Message Format"],
|
|
650
|
+
["idris", "Idris"],
|
|
651
|
+
["idr", "Idris"],
|
|
652
|
+
["ignore", ".ignore"],
|
|
653
|
+
["gitignore", ".ignore"],
|
|
654
|
+
["hgignore", ".ignore"],
|
|
655
|
+
["npmignore", ".ignore"],
|
|
656
|
+
["inform7", "Inform 7"],
|
|
657
|
+
["ini", "Ini"],
|
|
658
|
+
["io", "Io"],
|
|
659
|
+
["j", "J"],
|
|
660
|
+
["java", "Java"],
|
|
661
|
+
["javadoc", "JavaDoc"],
|
|
662
|
+
["javadoclike", "JavaDoc-like"],
|
|
663
|
+
["javastacktrace", "Java stack trace"],
|
|
664
|
+
["jexl", "Jexl"],
|
|
665
|
+
["jolie", "Jolie"],
|
|
666
|
+
["jq", "JQ"],
|
|
667
|
+
["jsdoc", "JSDoc"],
|
|
668
|
+
["js-extras", "JS Extras"],
|
|
669
|
+
["json", "JSON"],
|
|
670
|
+
["webmanifest", "JSON"],
|
|
671
|
+
["json5", "JSON5"],
|
|
672
|
+
["jsonp", "JSONP"],
|
|
673
|
+
["jsstacktrace", "JS stack trace"],
|
|
674
|
+
["js-templates", "JS Templates"],
|
|
675
|
+
["julia", "Julia"],
|
|
676
|
+
["keepalived", "Keepalived Configure"],
|
|
677
|
+
["keyman", "Keyman"],
|
|
678
|
+
["kotlin", "Kotlin"],
|
|
679
|
+
["kt", "Kotlin"],
|
|
680
|
+
["kts", "Kotlin"],
|
|
681
|
+
["kumir", "KuMir (КуМир)"],
|
|
682
|
+
["kum", "KuMir (КуМир)"],
|
|
683
|
+
["kusto", "Kusto"],
|
|
684
|
+
["latex", "LaTeX"],
|
|
685
|
+
["tex", "LaTeX"],
|
|
686
|
+
["context", "LaTeX"],
|
|
687
|
+
["latte", "Latte"],
|
|
688
|
+
["less", "Less"],
|
|
689
|
+
["lilypond", "LilyPond"],
|
|
690
|
+
["ly", "LilyPond"],
|
|
691
|
+
["liquid", "Liquid"],
|
|
692
|
+
["lisp", "Lisp"],
|
|
693
|
+
["emacs", "Lisp"],
|
|
694
|
+
["elisp", "Lisp"],
|
|
695
|
+
["emacs-lisp", "Lisp"],
|
|
696
|
+
["livescript", "LiveScript"],
|
|
697
|
+
["llvm", "LLVM IR"],
|
|
698
|
+
["log", "Log file"],
|
|
699
|
+
["lolcode", "LOLCODE"],
|
|
700
|
+
["lua", "Lua"],
|
|
701
|
+
["magma", "Magma (CAS)"],
|
|
702
|
+
["makefile", "Makefile"],
|
|
703
|
+
["markdown", "Markdown"],
|
|
704
|
+
["md", "Markdown"],
|
|
705
|
+
["markup-templating", "Markup templating"],
|
|
706
|
+
["mata", "Mata"],
|
|
707
|
+
["matlab", "MATLAB"],
|
|
708
|
+
["maxscript", "MAXScript"],
|
|
709
|
+
["mel", "MEL"],
|
|
710
|
+
["mermaid", "Mermaid"],
|
|
711
|
+
["metafont", "METAFONT"],
|
|
712
|
+
["mizar", "Mizar"],
|
|
713
|
+
["mongodb", "MongoDB"],
|
|
714
|
+
["monkey", "Monkey"],
|
|
715
|
+
["moonscript", "MoonScript"],
|
|
716
|
+
["moon", "MoonScript"],
|
|
717
|
+
["n1ql", "N1QL"],
|
|
718
|
+
["n4js", "N4JS"],
|
|
719
|
+
["n4jsd", "N4JS"],
|
|
720
|
+
["nand2tetris-hdl", "Nand To Tetris HDL"],
|
|
721
|
+
["naniscript", "Naninovel Script"],
|
|
722
|
+
["nani", "Naninovel Script"],
|
|
723
|
+
["nasm", "NASM"],
|
|
724
|
+
["neon", "NEON"],
|
|
725
|
+
["nevod", "Nevod"],
|
|
726
|
+
["nginx", "nginx"],
|
|
727
|
+
["nim", "Nim"],
|
|
728
|
+
["nix", "Nix"],
|
|
729
|
+
["nsis", "NSIS"],
|
|
730
|
+
["objectivec", "Objective-C"],
|
|
731
|
+
["objc", "Objective-C"],
|
|
732
|
+
["ocaml", "OCaml"],
|
|
733
|
+
["odin", "Odin"],
|
|
734
|
+
["opencl", "OpenCL"],
|
|
735
|
+
["openqasm", "OpenQasm"],
|
|
736
|
+
["qasm", "OpenQasm"],
|
|
737
|
+
["oz", "Oz"],
|
|
738
|
+
["parigp", "PARI/GP"],
|
|
739
|
+
["parser", "Parser"],
|
|
740
|
+
["pascal", "Pascal"],
|
|
741
|
+
["objectpascal", "Pascal"],
|
|
742
|
+
["pascaligo", "Pascaligo"],
|
|
743
|
+
["psl", "PATROL Scripting Language"],
|
|
744
|
+
["pcaxis", "PC-Axis"],
|
|
745
|
+
["px", "PC-Axis"],
|
|
746
|
+
["peoplecode", "PeopleCode"],
|
|
747
|
+
["pcode", "PeopleCode"],
|
|
748
|
+
["perl", "Perl"],
|
|
749
|
+
["php", "PHP"],
|
|
750
|
+
["phpdoc", "PHPDoc"],
|
|
751
|
+
["php-extras", "PHP Extras"],
|
|
752
|
+
["plant-uml", "PlantUML"],
|
|
753
|
+
["plantuml", "PlantUML"],
|
|
754
|
+
["plsql", "PL/SQL"],
|
|
755
|
+
["powerquery", "PowerQuery"],
|
|
756
|
+
["pq", "PowerQuery"],
|
|
757
|
+
["mscript", "PowerQuery"],
|
|
758
|
+
["powershell", "PowerShell"],
|
|
759
|
+
["processing", "Processing"],
|
|
760
|
+
["prolog", "Prolog"],
|
|
761
|
+
["promql", "PromQL"],
|
|
762
|
+
["properties", ".properties"],
|
|
763
|
+
["protobuf", "Protocol Buffers"],
|
|
764
|
+
["pug", "Pug"],
|
|
765
|
+
["puppet", "Puppet"],
|
|
766
|
+
["pure", "Pure"],
|
|
767
|
+
["purebasic", "PureBasic"],
|
|
768
|
+
["pbfasm", "PureBasic"],
|
|
769
|
+
["purescript", "PureScript"],
|
|
770
|
+
["purs", "PureScript"],
|
|
771
|
+
["python", "Python"],
|
|
772
|
+
["py", "Python"],
|
|
773
|
+
["qsharp", "Q#"],
|
|
774
|
+
["qs", "Q#"],
|
|
775
|
+
["q", "Q (kdb+ database)"],
|
|
776
|
+
["qml", "QML"],
|
|
777
|
+
["qore", "Qore"],
|
|
778
|
+
["r", "R"],
|
|
779
|
+
["racket", "Racket"],
|
|
780
|
+
["rkt", "Racket"],
|
|
781
|
+
["cshtml", "Razor C#"],
|
|
782
|
+
["razor", "Razor C#"],
|
|
783
|
+
["jsx", "React JSX"],
|
|
784
|
+
["tsx", "React TSX"],
|
|
785
|
+
["reason", "Reason"],
|
|
786
|
+
["regex", "Regex"],
|
|
787
|
+
["rego", "Rego"],
|
|
788
|
+
["renpy", "Ren'py"],
|
|
789
|
+
["rpy", "Ren'py"],
|
|
790
|
+
["rescript", "ReScript"],
|
|
791
|
+
["res", "ReScript"],
|
|
792
|
+
["rest", "reST (reStructuredText)"],
|
|
793
|
+
["rip", "Rip"],
|
|
794
|
+
["roboconf", "Roboconf"],
|
|
795
|
+
["robotframework", "Robot Framework"],
|
|
796
|
+
["robot", "Robot Framework"],
|
|
797
|
+
["ruby", "Ruby"],
|
|
798
|
+
["rb", "Ruby"],
|
|
799
|
+
["rust", "Rust"],
|
|
800
|
+
["sas", "SAS"],
|
|
801
|
+
["sass", "Sass (Sass)"],
|
|
802
|
+
["scss", "Sass (SCSS)"],
|
|
803
|
+
["scala", "Scala"],
|
|
804
|
+
["scheme", "Scheme"],
|
|
805
|
+
["shell-session", "Shell session"],
|
|
806
|
+
["sh-session", "Shell session"],
|
|
807
|
+
["shellsession", "Shell session"],
|
|
808
|
+
["smali", "Smali"],
|
|
809
|
+
["smalltalk", "Smalltalk"],
|
|
810
|
+
["smarty", "Smarty"],
|
|
811
|
+
["sml", "SML"],
|
|
812
|
+
["smlnj", "SML"],
|
|
813
|
+
["solidity", "Solidity (Ethereum)"],
|
|
814
|
+
["sol", "Solidity (Ethereum)"],
|
|
815
|
+
["solution-file", "Solution file"],
|
|
816
|
+
["sln", "Solution file"],
|
|
817
|
+
["soy", "Soy (Closure Template)"],
|
|
818
|
+
["sparql", "SPARQL"],
|
|
819
|
+
["rq", "SPARQL"],
|
|
820
|
+
["splunk-spl", "Splunk SPL"],
|
|
821
|
+
["sqf", "SQF: Status Quo Function (Arma 3)"],
|
|
822
|
+
["sql", "SQL"],
|
|
823
|
+
["squirrel", "Squirrel"],
|
|
824
|
+
["stan", "Stan"],
|
|
825
|
+
["stata", "Stata Ado"],
|
|
826
|
+
["iecst", "Structured Text (IEC 61131-3)"],
|
|
827
|
+
["stylus", "Stylus"],
|
|
828
|
+
["supercollider", "SuperCollider"],
|
|
829
|
+
["sclang", "SuperCollider"],
|
|
830
|
+
["swift", "Swift"],
|
|
831
|
+
["systemd", "Systemd configuration file"],
|
|
832
|
+
["t4-templating", "T4 templating"],
|
|
833
|
+
["t4-cs", "T4 Text Templates (C#)"],
|
|
834
|
+
["t4", "T4 Text Templates (C#)"],
|
|
835
|
+
["t4-vb", "T4 Text Templates (VB)"],
|
|
836
|
+
["tap", "TAP"],
|
|
837
|
+
["tcl", "Tcl"],
|
|
838
|
+
["tt2", "Template Toolkit 2"],
|
|
839
|
+
["textile", "Textile"],
|
|
840
|
+
["toml", "TOML"],
|
|
841
|
+
["tremor", "Tremor"],
|
|
842
|
+
["trickle", "Tremor"],
|
|
843
|
+
["troy", "Tremor"],
|
|
844
|
+
["turtle", "Turtle"],
|
|
845
|
+
["trig", "Turtle"],
|
|
846
|
+
["twig", "Twig"],
|
|
847
|
+
["typescript", "TypeScript"],
|
|
848
|
+
["ts", "TypeScript"],
|
|
849
|
+
["typoscript", "TypoScript"],
|
|
850
|
+
["tsconfig", "TypoScript"],
|
|
851
|
+
["unrealscript", "UnrealScript"],
|
|
852
|
+
["uscript", "UnrealScript"],
|
|
853
|
+
["uc", "UnrealScript"],
|
|
854
|
+
["uorazor", "UO Razor Script"],
|
|
855
|
+
["uri", "URI"],
|
|
856
|
+
["url", "URI"],
|
|
857
|
+
["v", "V"],
|
|
858
|
+
["vala", "Vala"],
|
|
859
|
+
["vbnet", "VB.Net"],
|
|
860
|
+
["velocity", "Velocity"],
|
|
861
|
+
["verilog", "Verilog"],
|
|
862
|
+
["vhdl", "VHDL"],
|
|
863
|
+
["vim", "vim"],
|
|
864
|
+
["visual-basic", "Visual Basic"],
|
|
865
|
+
["vb", "Visual Basic"],
|
|
866
|
+
["vba", "Visual Basic"],
|
|
867
|
+
["warpscript", "WarpScript"],
|
|
868
|
+
["wasm", "WebAssembly"],
|
|
869
|
+
["web-idl", "Web IDL"],
|
|
870
|
+
["webidl", "Web IDL"],
|
|
871
|
+
["wgsl", "WGSL"],
|
|
872
|
+
["wiki", "Wiki markup"],
|
|
873
|
+
["wolfram", "Wolfram language"],
|
|
874
|
+
["mathematica", "Wolfram language"],
|
|
875
|
+
["nb", "Wolfram language"],
|
|
876
|
+
["wl", "Wolfram language"],
|
|
877
|
+
["wren", "Wren"],
|
|
878
|
+
["xeora", "Xeora"],
|
|
879
|
+
["xeoracube", "Xeora"],
|
|
880
|
+
["xml-doc", "XML doc (.net)"],
|
|
881
|
+
["xojo", "Xojo (REALbasic)"],
|
|
882
|
+
["xquery", "XQuery"],
|
|
883
|
+
["yaml", "YAML"],
|
|
884
|
+
["yml", "YAML"],
|
|
885
|
+
["yang", "YANG"],
|
|
886
|
+
["zig", "Zig"]
|
|
887
|
+
]);
|
|
888
|
+
|
|
889
|
+
//#endregion
|
|
890
|
+
//#region packages/ezal-theme-example/src/markdown/codeblock/style.ts
|
|
891
|
+
const base = node_path.default.join(__dirname, "../assets/styles/_code.styl");
|
|
892
|
+
const cleaner$1 = new clean_css.default();
|
|
893
|
+
var CodeblockStyle = class extends ezal.VirtualAssets {
|
|
894
|
+
#baseCache = new ezal.Cache();
|
|
895
|
+
extra = "";
|
|
896
|
+
constructor() {
|
|
897
|
+
super("/styles/code.css");
|
|
898
|
+
super.updateDependencies([base]);
|
|
899
|
+
}
|
|
900
|
+
async build() {
|
|
901
|
+
let cache = this.#baseCache.get();
|
|
902
|
+
if (!cache) {
|
|
903
|
+
const file = await (0, node_fs_promises.readFile)(base, "utf8");
|
|
904
|
+
cache = stylus.default.render(file);
|
|
905
|
+
this.#baseCache.set(cache);
|
|
906
|
+
}
|
|
907
|
+
const result = this.extra + cache;
|
|
908
|
+
if ((0, ezal.getMode)() !== "build") return result;
|
|
909
|
+
return cleaner$1.minify(result).styles;
|
|
910
|
+
}
|
|
911
|
+
onDependenciesChanged() {
|
|
912
|
+
super.invalidated();
|
|
913
|
+
this.#baseCache.clean();
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
let asset$1;
|
|
917
|
+
function updateStyles(css) {
|
|
918
|
+
if (css === asset$1.extra) return;
|
|
919
|
+
asset$1.extra = css;
|
|
920
|
+
asset$1.invalidated();
|
|
921
|
+
}
|
|
922
|
+
function initCodeblockStyle() {
|
|
923
|
+
asset$1 = new CodeblockStyle();
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
//#endregion
|
|
927
|
+
//#region packages/ezal-theme-example/src/markdown/codeblock/index.ts
|
|
928
|
+
const PATTERN_CLASS = /class="([A-Za-z0-9 -]+)"/;
|
|
929
|
+
const PATTERN_EMPTY_LINE = /\n<span class="line">(<span class="mtk-\d+"><\/span>)?<\/span><\/code><\/pre>$/;
|
|
930
|
+
const modelOperations = new __vscode_vscode_languagedetection.ModelOperations();
|
|
931
|
+
async function getLang(code, lang) {
|
|
932
|
+
if (lang) return lang;
|
|
933
|
+
return (await modelOperations.runModel(code)).toSorted((a, b) => b.confidence - a.confidence)[0].languageId;
|
|
934
|
+
}
|
|
935
|
+
let shiki$1;
|
|
936
|
+
const shikiClassName = [];
|
|
937
|
+
const toClass = (0, __shikijs_transformers.transformerStyleToClass)({ classReplacer(name) {
|
|
938
|
+
let i = shikiClassName.indexOf(name);
|
|
939
|
+
if (i === -1) {
|
|
940
|
+
i = shikiClassName.length;
|
|
941
|
+
shikiClassName.push(name);
|
|
942
|
+
}
|
|
943
|
+
return `mtk-${i}`;
|
|
944
|
+
} });
|
|
945
|
+
const transformers = [
|
|
946
|
+
(0, __shikijs_transformers.transformerNotationDiff)(),
|
|
947
|
+
(0, __shikijs_transformers.transformerNotationHighlight)(),
|
|
948
|
+
(0, __shikijs_transformers.transformerNotationWordHighlight)(),
|
|
949
|
+
(0, __shikijs_transformers.transformerNotationFocus)(),
|
|
950
|
+
(0, __shikijs_transformers.transformerNotationErrorLevel)(),
|
|
951
|
+
(0, __shikijs_colorized_brackets.transformerColorizedBrackets)(),
|
|
952
|
+
toClass
|
|
953
|
+
];
|
|
954
|
+
async function highlighter(code, lang) {
|
|
955
|
+
lang = await getLang(code, lang);
|
|
956
|
+
let loadedLanguage = lang;
|
|
957
|
+
try {
|
|
958
|
+
await shiki$1.loadLanguage(lang);
|
|
959
|
+
} catch {
|
|
960
|
+
loadedLanguage = "plain";
|
|
961
|
+
}
|
|
962
|
+
const theme$1 = getThemeConfig().markdown?.codeBlockTheme;
|
|
963
|
+
const html = await shiki$1.codeToHtml(code, {
|
|
964
|
+
lang: loadedLanguage,
|
|
965
|
+
themes: {
|
|
966
|
+
light: theme$1?.light.name ?? "light-plus",
|
|
967
|
+
dark: theme$1?.dark.name ?? "dark-plus"
|
|
968
|
+
},
|
|
969
|
+
transformers
|
|
970
|
+
});
|
|
971
|
+
if ((0, ezal.getMode)() === "serve") updateStyles(toClass.getCSS());
|
|
972
|
+
return [html, lang];
|
|
973
|
+
}
|
|
974
|
+
const { $: $$9 } = ezal_markdown.utils;
|
|
975
|
+
function packager(html, lang, extra) {
|
|
976
|
+
const name = LANGUAGE_MAP.get(lang) ?? lang;
|
|
977
|
+
let mtk = "";
|
|
978
|
+
html = html.replace(PATTERN_CLASS, (_, className) => {
|
|
979
|
+
const classes = className.split(" ");
|
|
980
|
+
const result = ["shiki"];
|
|
981
|
+
for (const name$1 of classes) if (name$1.startsWith("has-")) result.push(name$1);
|
|
982
|
+
else if (name$1.startsWith("mtk-")) mtk = name$1;
|
|
983
|
+
return `class="${result.join(" ")}"`;
|
|
984
|
+
}).replace(PATTERN_EMPTY_LINE, "</code></pre>");
|
|
985
|
+
return $$9("figure", {
|
|
986
|
+
class: [
|
|
987
|
+
"code",
|
|
988
|
+
"rounded",
|
|
989
|
+
mtk
|
|
990
|
+
],
|
|
991
|
+
html: [$$9("figcaption", {
|
|
992
|
+
class: ["sticky", "rounded"],
|
|
993
|
+
html: [
|
|
994
|
+
$$9("code", name),
|
|
995
|
+
extra,
|
|
996
|
+
$$9("button", {
|
|
997
|
+
class: ["link", "icon-copy"],
|
|
998
|
+
attr: { title: "复制代码" }
|
|
999
|
+
})
|
|
1000
|
+
]
|
|
1001
|
+
}), html]
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
const origin$1 = ezal_markdown.plugins.codeblock();
|
|
1005
|
+
async function render$1({ code, lang, children }, { shared, counter }) {
|
|
1006
|
+
counter.count(code);
|
|
1007
|
+
shared.codeblock = true;
|
|
1008
|
+
const result = await highlighter(code, lang);
|
|
1009
|
+
return packager(result[0], result[1], children?.html ?? "");
|
|
1010
|
+
}
|
|
1011
|
+
const indented = {
|
|
1012
|
+
...origin$1.indentedCodeblock,
|
|
1013
|
+
render: render$1
|
|
1014
|
+
};
|
|
1015
|
+
const fenced = {
|
|
1016
|
+
...origin$1.fencedCodeblock,
|
|
1017
|
+
render: render$1
|
|
1018
|
+
};
|
|
1019
|
+
async function codeblock() {
|
|
1020
|
+
const theme$1 = getThemeConfig().markdown?.codeBlockTheme;
|
|
1021
|
+
shiki$1 = await (0, shiki.createHighlighter)({
|
|
1022
|
+
themes: theme$1 ? [theme$1.light, theme$1.dark] : ["light-plus", "dark-plus"],
|
|
1023
|
+
langs: []
|
|
1024
|
+
});
|
|
1025
|
+
return {
|
|
1026
|
+
indented,
|
|
1027
|
+
fenced
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
function setupCodeblockStyle() {
|
|
1031
|
+
updateStyles(toClass.getCSS());
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
//#endregion
|
|
1035
|
+
//#region packages/ezal-theme-example/src/markdown/fold.ts
|
|
1036
|
+
const PATTERN_START$2 = /(?<=^|\n) {0,3}(\+{3,}) {0,3}(\S.*)\n/;
|
|
1037
|
+
const { $: $$8 } = ezal_markdown.utils;
|
|
1038
|
+
const fold = {
|
|
1039
|
+
name: "fold",
|
|
1040
|
+
type: "block",
|
|
1041
|
+
order: 0,
|
|
1042
|
+
priority: 0,
|
|
1043
|
+
start: PATTERN_START$2,
|
|
1044
|
+
parse(source$1, { md }) {
|
|
1045
|
+
const matched = source$1.match(PATTERN_START$2);
|
|
1046
|
+
if (!matched) return;
|
|
1047
|
+
const size = matched[1].length;
|
|
1048
|
+
const summary = matched[2];
|
|
1049
|
+
const pattern = /* @__PURE__ */ new RegExp(`(?<=^|\\n) {0,3}\\+{${size}}\\s*(\\n|$)`);
|
|
1050
|
+
const endMatched = source$1.match(pattern);
|
|
1051
|
+
const end = endMatched?.index ?? Infinity;
|
|
1052
|
+
const rawEnd = end + (endMatched?.[0].length ?? 0);
|
|
1053
|
+
const raw = source$1.slice(0, rawEnd);
|
|
1054
|
+
const details = raw.slice(matched[0].length, end);
|
|
1055
|
+
return {
|
|
1056
|
+
raw,
|
|
1057
|
+
children: [md(summary, "inline"), md(details, "block")]
|
|
1058
|
+
};
|
|
1059
|
+
},
|
|
1060
|
+
render({ children: [summary, details] }) {
|
|
1061
|
+
return $$8("details", {
|
|
1062
|
+
class: "rounded",
|
|
1063
|
+
html: [$$8("summary", {
|
|
1064
|
+
class: ["rounded", "sticky"],
|
|
1065
|
+
html: summary.html
|
|
1066
|
+
}), $$8("div", {
|
|
1067
|
+
class: "sticky-content",
|
|
1068
|
+
html: details.html
|
|
1069
|
+
})]
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
|
|
1074
|
+
//#endregion
|
|
1075
|
+
//#region packages/ezal-theme-example/src/markdown/footnote.ts
|
|
1076
|
+
const { eachLine, $: $$7 } = ezal_markdown.utils;
|
|
1077
|
+
const PATTERN_SOURCE_START = /(?<=^|\n)\[\^.*?\]:/;
|
|
1078
|
+
const PATTERN_SOURCE_BEGIN = /^\[(.*?)\]:/;
|
|
1079
|
+
const PATTERN_SOURCE_INDENT = /^(\t| {1,4})/;
|
|
1080
|
+
const render = {
|
|
1081
|
+
name: "footnote",
|
|
1082
|
+
type: "inline",
|
|
1083
|
+
render({ id, label }, { counter }) {
|
|
1084
|
+
counter.count(label);
|
|
1085
|
+
return $$7("sup", $$7("a", {
|
|
1086
|
+
class: "footnote",
|
|
1087
|
+
attr: { href: id },
|
|
1088
|
+
content: label
|
|
1089
|
+
}));
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
const ast = {
|
|
1093
|
+
name: "footnote-ast",
|
|
1094
|
+
type: "inline",
|
|
1095
|
+
phase: "post",
|
|
1096
|
+
priority: -1,
|
|
1097
|
+
parse(root) {
|
|
1098
|
+
for (const child of root.entires().toArray()) {
|
|
1099
|
+
if (!(child instanceof ezal_markdown.LinkNode)) continue;
|
|
1100
|
+
if (child.label?.[0] !== "^") continue;
|
|
1101
|
+
if (child.raw?.length !== child.label.length + 2) continue;
|
|
1102
|
+
const id = child.destination;
|
|
1103
|
+
const label = child.raw.slice(2, -1);
|
|
1104
|
+
child.before(new ezal_markdown.ParsedNode("footnote", "inline", {
|
|
1105
|
+
id,
|
|
1106
|
+
label
|
|
1107
|
+
}));
|
|
1108
|
+
child.remove();
|
|
1109
|
+
}
|
|
1110
|
+
},
|
|
1111
|
+
verifyNode: (_) => false,
|
|
1112
|
+
render: () => ""
|
|
1113
|
+
};
|
|
1114
|
+
const source = {
|
|
1115
|
+
name: "footnote-source",
|
|
1116
|
+
type: "block",
|
|
1117
|
+
order: 0,
|
|
1118
|
+
priority: 0,
|
|
1119
|
+
start: PATTERN_SOURCE_START,
|
|
1120
|
+
parse(source$1, { anchors, refMap, md }) {
|
|
1121
|
+
const contents = [];
|
|
1122
|
+
const id = [];
|
|
1123
|
+
let current = "";
|
|
1124
|
+
let raw = "";
|
|
1125
|
+
let indentState = null;
|
|
1126
|
+
for (const [line] of eachLine(source$1)) {
|
|
1127
|
+
const matched = line.match(PATTERN_SOURCE_BEGIN);
|
|
1128
|
+
if (matched) {
|
|
1129
|
+
if (matched[1][0] !== "^") break;
|
|
1130
|
+
if (raw) contents.push(current);
|
|
1131
|
+
const label = matched[1].slice(1);
|
|
1132
|
+
const hash = anchors.register(label);
|
|
1133
|
+
id.push([label, hash]);
|
|
1134
|
+
refMap.set(matched[1], { destination: `#${hash}` });
|
|
1135
|
+
current = line.slice(matched[0].length);
|
|
1136
|
+
raw += line;
|
|
1137
|
+
indentState = null;
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
const indent = PATTERN_SOURCE_INDENT.test(line);
|
|
1141
|
+
const empty = line.trim().length === 0;
|
|
1142
|
+
if (indentState === null) indentState = indent || empty;
|
|
1143
|
+
if (!indentState && empty) break;
|
|
1144
|
+
if (indentState && !indent) break;
|
|
1145
|
+
if (!(empty || indent)) indentState = false;
|
|
1146
|
+
current += line;
|
|
1147
|
+
raw += line;
|
|
1148
|
+
}
|
|
1149
|
+
if (id.length !== contents.length) contents.push(current);
|
|
1150
|
+
const children = contents.map((content) => md(content, {
|
|
1151
|
+
skipParagraphWrapping: true,
|
|
1152
|
+
maxLevel: "block"
|
|
1153
|
+
}));
|
|
1154
|
+
return {
|
|
1155
|
+
raw,
|
|
1156
|
+
id,
|
|
1157
|
+
children
|
|
1158
|
+
};
|
|
1159
|
+
},
|
|
1160
|
+
render({ id, children }, { counter }) {
|
|
1161
|
+
for (const [label] of id) counter.count(label);
|
|
1162
|
+
for (const child of children) counter.count(child.raw);
|
|
1163
|
+
return $$7("dl", children.flatMap((child, i) => [$$7("dt", {
|
|
1164
|
+
content: id[i][0],
|
|
1165
|
+
id: id[i][1]
|
|
1166
|
+
}), $$7("dd", child.html)]));
|
|
1167
|
+
}
|
|
1168
|
+
};
|
|
1169
|
+
const footnote = {
|
|
1170
|
+
source,
|
|
1171
|
+
ast,
|
|
1172
|
+
render
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
//#endregion
|
|
1176
|
+
//#region packages/ezal-theme-example/src/markdown/image.ts
|
|
1177
|
+
const { $: $$6 } = ezal_markdown.utils;
|
|
1178
|
+
function img(info, src, alt, title) {
|
|
1179
|
+
return $$6("img", {
|
|
1180
|
+
attr: {
|
|
1181
|
+
src: ezal.URL.for(src),
|
|
1182
|
+
alt,
|
|
1183
|
+
width: info?.metadata?.width,
|
|
1184
|
+
height: info?.metadata?.height,
|
|
1185
|
+
loading: "lazy",
|
|
1186
|
+
title
|
|
1187
|
+
},
|
|
1188
|
+
style: { $imgColor: info?.metadata?.color }
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
function renderImage(url, alt, title, page) {
|
|
1192
|
+
const info = getImageInfo(ezal.URL.resolve(page.url, url));
|
|
1193
|
+
if (!info?.rule) return img(info, url, alt, title);
|
|
1194
|
+
const html = info.rule.slice(0, -1).map((ext) => $$6("source", { attr: {
|
|
1195
|
+
srcset: ezal.URL.extname(url, `.opt${ext}`),
|
|
1196
|
+
type: mime_types.default.lookup(ext)
|
|
1197
|
+
} }));
|
|
1198
|
+
html.push(img(info, ezal.URL.extname(url, info.rule.at(-1)), alt, title));
|
|
1199
|
+
return $$6("picture", html);
|
|
1200
|
+
}
|
|
1201
|
+
const blockRender = {
|
|
1202
|
+
name: "image",
|
|
1203
|
+
type: "block",
|
|
1204
|
+
render({ title, url, alt }, { shared, counter }) {
|
|
1205
|
+
const page = shared.page;
|
|
1206
|
+
const html = [renderImage(url, alt, title, page)];
|
|
1207
|
+
html.push($$6("figcaption", { content: alt }));
|
|
1208
|
+
counter.count(alt);
|
|
1209
|
+
return $$6("figure", {
|
|
1210
|
+
class: "image",
|
|
1211
|
+
html
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
const block$1 = {
|
|
1216
|
+
name: "image-post",
|
|
1217
|
+
type: "inline",
|
|
1218
|
+
phase: "post",
|
|
1219
|
+
priority: -1,
|
|
1220
|
+
parse(root) {
|
|
1221
|
+
if (!(root instanceof ezal_markdown.Paragraph)) return;
|
|
1222
|
+
if (root.size !== 1) return;
|
|
1223
|
+
const child = root.child(0);
|
|
1224
|
+
if (!(child instanceof ezal_markdown.ImageNode)) return;
|
|
1225
|
+
const alt = child.entires().map((node) => node.raw ?? "").toArray().join("");
|
|
1226
|
+
const image$1 = new ezal_markdown.ParsedNode("image", "block", {
|
|
1227
|
+
raw: child.raw ?? "",
|
|
1228
|
+
title: child.title,
|
|
1229
|
+
alt: (0, ezal.escapeHTML)(alt),
|
|
1230
|
+
url: child.destination
|
|
1231
|
+
});
|
|
1232
|
+
root.before(image$1);
|
|
1233
|
+
root.remove();
|
|
1234
|
+
},
|
|
1235
|
+
verifyNode: (_node) => false,
|
|
1236
|
+
render: () => ""
|
|
1237
|
+
};
|
|
1238
|
+
const inline$1 = {
|
|
1239
|
+
name: "image",
|
|
1240
|
+
type: "inline",
|
|
1241
|
+
phase: "post",
|
|
1242
|
+
priority: 1,
|
|
1243
|
+
parse() {},
|
|
1244
|
+
verifyNode(node) {
|
|
1245
|
+
return node instanceof ezal_markdown.ImageNode;
|
|
1246
|
+
},
|
|
1247
|
+
render(node, { shared }) {
|
|
1248
|
+
const page = shared.page;
|
|
1249
|
+
const { destination, title } = node;
|
|
1250
|
+
return renderImage(destination, (0, ezal.escapeHTML)(node.entires().map((node$1) => node$1.html).toArray().join("")), title, page);
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
const image = {
|
|
1254
|
+
block: block$1,
|
|
1255
|
+
blockRender,
|
|
1256
|
+
inline: inline$1
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
//#endregion
|
|
1260
|
+
//#region packages/ezal-theme-example/src/markdown/kbd.ts
|
|
1261
|
+
const PATTERN = /{{\S+?}}/;
|
|
1262
|
+
const { $: $$5 } = ezal_markdown.utils;
|
|
1263
|
+
const kbd = {
|
|
1264
|
+
name: "kbd",
|
|
1265
|
+
type: "inline",
|
|
1266
|
+
order: 0,
|
|
1267
|
+
priority: 0,
|
|
1268
|
+
start: PATTERN,
|
|
1269
|
+
parse(source$1) {
|
|
1270
|
+
const matched = source$1.match(PATTERN);
|
|
1271
|
+
if (!matched) return;
|
|
1272
|
+
return {
|
|
1273
|
+
raw: matched[0],
|
|
1274
|
+
key: matched[0].slice(2, -2)
|
|
1275
|
+
};
|
|
1276
|
+
},
|
|
1277
|
+
render({ key }, { counter }) {
|
|
1278
|
+
counter.count(key);
|
|
1279
|
+
return $$5("kbd", { content: key });
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1283
|
+
//#endregion
|
|
1284
|
+
//#region packages/ezal-theme-example/src/markdown/link.ts
|
|
1285
|
+
const PATTERN_ABSOLUTE_LINK = /^[a-z][a-z0-9+.-]*:|^\/\//;
|
|
1286
|
+
const { $: $$4 } = ezal_markdown.utils;
|
|
1287
|
+
const link = {
|
|
1288
|
+
name: "link",
|
|
1289
|
+
type: "inline",
|
|
1290
|
+
phase: "post",
|
|
1291
|
+
priority: 1,
|
|
1292
|
+
parse() {},
|
|
1293
|
+
verifyNode(node) {
|
|
1294
|
+
return node instanceof ezal_markdown.LinkNode;
|
|
1295
|
+
},
|
|
1296
|
+
render(node) {
|
|
1297
|
+
const html = [...node.entires().map((node$1) => node$1.html)];
|
|
1298
|
+
const target = PATTERN_ABSOLUTE_LINK.test(node.destination) ? "_blank" : void 0;
|
|
1299
|
+
return $$4("a", {
|
|
1300
|
+
attr: {
|
|
1301
|
+
href: ezal.URL.for(node.destination),
|
|
1302
|
+
target,
|
|
1303
|
+
title: node.title
|
|
1304
|
+
},
|
|
1305
|
+
html
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
};
|
|
1309
|
+
|
|
1310
|
+
//#endregion
|
|
1311
|
+
//#region packages/ezal-theme-example/src/markdown/links.ts
|
|
1312
|
+
const PATTERN_ALL = /(?<=^|\n)@@\n.*?\n@@(\n|$)/s;
|
|
1313
|
+
const PATTERN_EACH = /(?<=^|\n)@ ?([^@\n].*\n){2,3}/g;
|
|
1314
|
+
const PATTERN_WHITESPACE = /\s+/;
|
|
1315
|
+
const { $: $$3 } = ezal_markdown.utils;
|
|
1316
|
+
const links = {
|
|
1317
|
+
name: "links",
|
|
1318
|
+
type: "block",
|
|
1319
|
+
order: 0,
|
|
1320
|
+
priority: 0,
|
|
1321
|
+
start: PATTERN_ALL,
|
|
1322
|
+
parse(source$1) {
|
|
1323
|
+
const matched = source$1.match(PATTERN_ALL);
|
|
1324
|
+
if (!matched) return;
|
|
1325
|
+
const raw = matched[0];
|
|
1326
|
+
return {
|
|
1327
|
+
raw,
|
|
1328
|
+
links: [...raw.matchAll(PATTERN_EACH).map((matched$1) => {
|
|
1329
|
+
const lines = matched$1[0].split("\n");
|
|
1330
|
+
const args = lines[0].slice(1).trim().split(PATTERN_WHITESPACE);
|
|
1331
|
+
return {
|
|
1332
|
+
href: args[0],
|
|
1333
|
+
icon: args[1],
|
|
1334
|
+
title: lines[1],
|
|
1335
|
+
subtitle: lines[2]
|
|
1336
|
+
};
|
|
1337
|
+
})]
|
|
1338
|
+
};
|
|
1339
|
+
},
|
|
1340
|
+
render({ links: links$1 }, { counter }) {
|
|
1341
|
+
return $$3("div", {
|
|
1342
|
+
class: "links",
|
|
1343
|
+
html: links$1.map(({ href, icon, title, subtitle }) => {
|
|
1344
|
+
const html = [$$3("i", { class: ["icon-link"] })];
|
|
1345
|
+
if (icon) html.push($$3("img", {
|
|
1346
|
+
class: "rounded",
|
|
1347
|
+
attr: {
|
|
1348
|
+
src: ezal.URL.for(icon),
|
|
1349
|
+
alt: title
|
|
1350
|
+
}
|
|
1351
|
+
}));
|
|
1352
|
+
html.push($$3("div", {
|
|
1353
|
+
class: "link-title",
|
|
1354
|
+
content: title
|
|
1355
|
+
}));
|
|
1356
|
+
counter.count(title);
|
|
1357
|
+
if (subtitle) {
|
|
1358
|
+
html.push($$3("div", { content: subtitle }));
|
|
1359
|
+
counter.count(subtitle);
|
|
1360
|
+
}
|
|
1361
|
+
return $$3("a", {
|
|
1362
|
+
class: "rounded",
|
|
1363
|
+
html,
|
|
1364
|
+
attr: { href: ezal.URL.for(href) }
|
|
1365
|
+
});
|
|
1366
|
+
})
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
};
|
|
1370
|
+
|
|
1371
|
+
//#endregion
|
|
1372
|
+
//#region packages/ezal-theme-example/src/markdown/note.ts
|
|
1373
|
+
const PATTERN_START$1 = /(?<=^|\n) {0,3}(!{3,}) ?(info|tip|warn|danger)(.*)\n/;
|
|
1374
|
+
const { $: $$2 } = ezal_markdown.utils;
|
|
1375
|
+
const NOTE_TITLE = {
|
|
1376
|
+
info: "注意",
|
|
1377
|
+
tip: "提示",
|
|
1378
|
+
warn: "警告",
|
|
1379
|
+
danger: "危险"
|
|
1380
|
+
};
|
|
1381
|
+
const note = {
|
|
1382
|
+
name: "note",
|
|
1383
|
+
type: "block",
|
|
1384
|
+
order: 0,
|
|
1385
|
+
priority: 0,
|
|
1386
|
+
start: PATTERN_START$1,
|
|
1387
|
+
parse(source$1, { md }) {
|
|
1388
|
+
const matched = source$1.match(PATTERN_START$1);
|
|
1389
|
+
if (!matched) return;
|
|
1390
|
+
const size = matched[1].length;
|
|
1391
|
+
const type = matched[2];
|
|
1392
|
+
let title = matched[3]?.trim();
|
|
1393
|
+
if (!title) title = NOTE_TITLE[type];
|
|
1394
|
+
const pattern = /* @__PURE__ */ new RegExp(`(?<=^|\\n) {0,3}!{${size}}\\s*(\\n|$)`);
|
|
1395
|
+
const endMatched = source$1.match(pattern);
|
|
1396
|
+
const end = endMatched?.index ?? Infinity;
|
|
1397
|
+
const rawEnd = end + (endMatched?.[0].length ?? 0);
|
|
1398
|
+
const raw = source$1.slice(0, rawEnd);
|
|
1399
|
+
const content = raw.slice(matched[0].length, end);
|
|
1400
|
+
return {
|
|
1401
|
+
raw,
|
|
1402
|
+
type,
|
|
1403
|
+
title,
|
|
1404
|
+
children: md(content, "block")
|
|
1405
|
+
};
|
|
1406
|
+
},
|
|
1407
|
+
render({ type, title, children }) {
|
|
1408
|
+
return $$2("div", {
|
|
1409
|
+
class: ["note", `note-${type}`],
|
|
1410
|
+
html: [$$2("p", [$$2("i", { class: `icon-${type}` }), title]), children.html]
|
|
1411
|
+
});
|
|
1412
|
+
}
|
|
1413
|
+
};
|
|
1414
|
+
|
|
1415
|
+
//#endregion
|
|
1416
|
+
//#region packages/ezal-theme-example/src/markdown/table.ts
|
|
1417
|
+
const { $: $$1 } = ezal_markdown.utils;
|
|
1418
|
+
const origin = ezal_markdown.plugins.table();
|
|
1419
|
+
const table = {
|
|
1420
|
+
...origin,
|
|
1421
|
+
render(source$1, context, options) {
|
|
1422
|
+
return $$1("div", {
|
|
1423
|
+
class: ["table", "rounded"],
|
|
1424
|
+
attr: { tabindex: "0" },
|
|
1425
|
+
html: origin.render(source$1, context, options)
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
//#endregion
|
|
1431
|
+
//#region packages/ezal-theme-example/src/markdown/tabs.ts
|
|
1432
|
+
const PATTERN_START = /(?<=^|\n) {0,3}(:{3,}) {0,3}\S/;
|
|
1433
|
+
const { $ } = ezal_markdown.utils;
|
|
1434
|
+
const tabs = {
|
|
1435
|
+
name: "tabs",
|
|
1436
|
+
type: "block",
|
|
1437
|
+
order: 0,
|
|
1438
|
+
priority: 0,
|
|
1439
|
+
start: PATTERN_START,
|
|
1440
|
+
parse(source$1, { anchors, md }) {
|
|
1441
|
+
const size = source$1.match(PATTERN_START)?.[1].length ?? 0;
|
|
1442
|
+
if (!size) return;
|
|
1443
|
+
const pattern = /* @__PURE__ */ new RegExp(`(?<=^|\\n) {0,3}:{${size}}(.*)(\\n|$)`);
|
|
1444
|
+
const children = [];
|
|
1445
|
+
const id = [];
|
|
1446
|
+
let matched = source$1.match(pattern);
|
|
1447
|
+
let offset = 0;
|
|
1448
|
+
while (matched) {
|
|
1449
|
+
offset += matched[0].length;
|
|
1450
|
+
if (matched[1].trim().length === 0) break;
|
|
1451
|
+
const tab = md(matched[1], "inline");
|
|
1452
|
+
matched = source$1.slice(offset).match(pattern);
|
|
1453
|
+
const next = (matched?.index ?? Infinity) + offset;
|
|
1454
|
+
const content = md(source$1.slice(offset, next), "block");
|
|
1455
|
+
offset = next;
|
|
1456
|
+
id.push(anchors.register("tab"));
|
|
1457
|
+
children.push([tab, content]);
|
|
1458
|
+
}
|
|
1459
|
+
if (children.length === 0) return;
|
|
1460
|
+
return {
|
|
1461
|
+
raw: source$1.slice(0, offset),
|
|
1462
|
+
children,
|
|
1463
|
+
id
|
|
1464
|
+
};
|
|
1465
|
+
},
|
|
1466
|
+
render({ children, id }, context) {
|
|
1467
|
+
const name = `tabs-${context.self}`;
|
|
1468
|
+
context.self++;
|
|
1469
|
+
const nav = children.map(([tab], i) => $("label", {
|
|
1470
|
+
attr: { for: id[i] },
|
|
1471
|
+
html: [$("input", {
|
|
1472
|
+
attr: {
|
|
1473
|
+
type: "radio",
|
|
1474
|
+
name,
|
|
1475
|
+
checked: i === 0
|
|
1476
|
+
},
|
|
1477
|
+
id: id[i]
|
|
1478
|
+
}), tab.html]
|
|
1479
|
+
}));
|
|
1480
|
+
const content = children.map(([_, content$1], i) => $("div", {
|
|
1481
|
+
class: i === 0 ? "active" : void 0,
|
|
1482
|
+
html: content$1.html
|
|
1483
|
+
}));
|
|
1484
|
+
return $("div", {
|
|
1485
|
+
class: ["tabs", "rounded"],
|
|
1486
|
+
html: [$("div", {
|
|
1487
|
+
class: [
|
|
1488
|
+
"tab-nav",
|
|
1489
|
+
"rounded",
|
|
1490
|
+
"sticky"
|
|
1491
|
+
],
|
|
1492
|
+
html: nav
|
|
1493
|
+
}), $("div", {
|
|
1494
|
+
class: ["tab-content", "sticky-content"],
|
|
1495
|
+
html: content
|
|
1496
|
+
})]
|
|
1497
|
+
});
|
|
1498
|
+
},
|
|
1499
|
+
context: () => 0
|
|
1500
|
+
};
|
|
1501
|
+
|
|
1502
|
+
//#endregion
|
|
1503
|
+
//#region packages/ezal-theme-example/src/markdown/tex.ts
|
|
1504
|
+
const PATTERN_INLINE = /(?<=\s|\W|^)(?<!\$)(\$\$?)(.+?)(\1)(?!\$)(?=\s|\W|$)/;
|
|
1505
|
+
const PATTERN_BLOCK = /(?<=^|\n) {0,3}\$\$.*?\$\$\s*(\n|$)/s;
|
|
1506
|
+
const katexErrorHandler = (logger$4) => (errorCode, errorMsg, token) => {
|
|
1507
|
+
switch (errorCode) {
|
|
1508
|
+
case "unknownSymbol":
|
|
1509
|
+
case "unicodeTextInMathMode":
|
|
1510
|
+
case "mathVsTextUnits":
|
|
1511
|
+
case "newLineInDisplayMode":
|
|
1512
|
+
case "htmlExtension":
|
|
1513
|
+
logger$4.warn(`${errorCode}: ${errorMsg}`, token);
|
|
1514
|
+
break;
|
|
1515
|
+
case "commentAtEnd":
|
|
1516
|
+
logger$4.error(`${errorCode}: ${errorMsg}`, token);
|
|
1517
|
+
break;
|
|
1518
|
+
}
|
|
1519
|
+
return false;
|
|
1520
|
+
};
|
|
1521
|
+
const inline = {
|
|
1522
|
+
name: "tex",
|
|
1523
|
+
type: "inline",
|
|
1524
|
+
order: 0,
|
|
1525
|
+
priority: 0,
|
|
1526
|
+
start: PATTERN_INLINE,
|
|
1527
|
+
parse(source$1) {
|
|
1528
|
+
const matched = source$1.match(PATTERN_INLINE);
|
|
1529
|
+
if (!matched) return;
|
|
1530
|
+
return {
|
|
1531
|
+
raw: matched[0],
|
|
1532
|
+
tex: matched[2]
|
|
1533
|
+
};
|
|
1534
|
+
},
|
|
1535
|
+
render({ tex: tex$1 }, { logger: logger$4, shared, counter }) {
|
|
1536
|
+
shared.tex = true;
|
|
1537
|
+
counter.count(tex$1);
|
|
1538
|
+
return katex.default.renderToString(tex$1, {
|
|
1539
|
+
output: "html",
|
|
1540
|
+
throwOnError: false,
|
|
1541
|
+
strict: katexErrorHandler(logger$4)
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
const block = {
|
|
1546
|
+
name: "tex",
|
|
1547
|
+
type: "block",
|
|
1548
|
+
order: 0,
|
|
1549
|
+
priority: 0,
|
|
1550
|
+
start: PATTERN_BLOCK,
|
|
1551
|
+
parse(source$1) {
|
|
1552
|
+
const matched = source$1.match(PATTERN_BLOCK);
|
|
1553
|
+
if (!matched) return;
|
|
1554
|
+
const raw = matched[0];
|
|
1555
|
+
const start = raw.indexOf("$$");
|
|
1556
|
+
const end = raw.lastIndexOf("$$");
|
|
1557
|
+
return {
|
|
1558
|
+
raw,
|
|
1559
|
+
tex: raw.slice(start + 2, end).trim()
|
|
1560
|
+
};
|
|
1561
|
+
},
|
|
1562
|
+
render({ tex: tex$1 }, { logger: logger$4, shared, counter }) {
|
|
1563
|
+
shared.tex = true;
|
|
1564
|
+
counter.count(tex$1);
|
|
1565
|
+
return katex.default.renderToString(tex$1, {
|
|
1566
|
+
displayMode: true,
|
|
1567
|
+
output: "html",
|
|
1568
|
+
throwOnError: false,
|
|
1569
|
+
strict: katexErrorHandler(logger$4)
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
};
|
|
1573
|
+
const tex = {
|
|
1574
|
+
inline,
|
|
1575
|
+
block
|
|
1576
|
+
};
|
|
1577
|
+
|
|
1578
|
+
//#endregion
|
|
1579
|
+
//#region packages/ezal-theme-example/src/markdown/index.ts
|
|
1580
|
+
const logger$1 = new ezal.Logger("markdown");
|
|
1581
|
+
const renderer = new ezal_markdown.EzalMarkdown();
|
|
1582
|
+
renderer.logger = {
|
|
1583
|
+
debug(data) {
|
|
1584
|
+
logger$1.debug(`[${data.name}]`, data.message, data.errObj);
|
|
1585
|
+
},
|
|
1586
|
+
info(data) {
|
|
1587
|
+
logger$1.log(`[${data.name}]`, data.message, data.errObj);
|
|
1588
|
+
},
|
|
1589
|
+
warn(data) {
|
|
1590
|
+
if (data.name === "link-reference-define" && data.message.includes("label ^")) return;
|
|
1591
|
+
logger$1.warn(`[${data.name}]`, data.message, data.errObj);
|
|
1592
|
+
},
|
|
1593
|
+
error(data) {
|
|
1594
|
+
logger$1.error(`[${data.name}]`, data.message, data.errObj);
|
|
1595
|
+
}
|
|
1596
|
+
};
|
|
1597
|
+
const setext = {
|
|
1598
|
+
name: "setext-heading",
|
|
1599
|
+
type: "block",
|
|
1600
|
+
order: 0,
|
|
1601
|
+
priority: 0,
|
|
1602
|
+
start: () => null,
|
|
1603
|
+
parse: () => null,
|
|
1604
|
+
render: () => ""
|
|
1605
|
+
};
|
|
1606
|
+
async function markdownPageHandler() {
|
|
1607
|
+
renderer.set(ezal_markdown.plugins.heading({ shiftLevels: true }), image, table, await codeblock(), footnote, tex, tabs, note, fold, kbd, links, setext, link);
|
|
1608
|
+
return {
|
|
1609
|
+
exts: ".md",
|
|
1610
|
+
async parser(src) {
|
|
1611
|
+
const file = await ezal.fs.readFile(src);
|
|
1612
|
+
if (file instanceof Error) return file;
|
|
1613
|
+
const frontmatter = await (0, ezal_markdown.extractFrontmatter)(file);
|
|
1614
|
+
let data = frontmatter?.data;
|
|
1615
|
+
if (typeof data !== "object") data = {};
|
|
1616
|
+
return {
|
|
1617
|
+
content: file.slice(frontmatter?.raw.length ?? 0),
|
|
1618
|
+
data
|
|
1619
|
+
};
|
|
1620
|
+
},
|
|
1621
|
+
async renderer(content, page) {
|
|
1622
|
+
const config$2 = getThemeConfig();
|
|
1623
|
+
const result = await renderer.renderHTML(content, {
|
|
1624
|
+
lineBreak: config$2.markdown?.lineBreak,
|
|
1625
|
+
shared: { page }
|
|
1626
|
+
});
|
|
1627
|
+
return {
|
|
1628
|
+
html: result.html,
|
|
1629
|
+
data: result.context
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
//#endregion
|
|
1636
|
+
//#region packages/ezal-theme-example/src/page/404.ts
|
|
1637
|
+
function init404Page() {
|
|
1638
|
+
new ezal.VirtualPage({
|
|
1639
|
+
id: "404",
|
|
1640
|
+
src: "/404.html",
|
|
1641
|
+
layout: "404"
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
//#endregion
|
|
1646
|
+
//#region packages/ezal-theme-example/src/page/archive.ts
|
|
1647
|
+
let indexPage;
|
|
1648
|
+
const years = /* @__PURE__ */ new Map();
|
|
1649
|
+
function getArticles$1(year) {
|
|
1650
|
+
return ezal.Article.getAll().filter((article) => article.date.year === year).toSorted(compareByDate);
|
|
1651
|
+
}
|
|
1652
|
+
function createIndex() {
|
|
1653
|
+
indexPage = new ezal.VirtualPage({
|
|
1654
|
+
id: "archive",
|
|
1655
|
+
src: "/archive/",
|
|
1656
|
+
layout: "archive",
|
|
1657
|
+
title: "归档",
|
|
1658
|
+
data: {
|
|
1659
|
+
years,
|
|
1660
|
+
getArticles: getArticles$1
|
|
1661
|
+
}
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
let scanned$3 = false;
|
|
1665
|
+
function updateArchivePage(_any) {
|
|
1666
|
+
if (!scanned$3 && _any) return;
|
|
1667
|
+
scanned$3 = true;
|
|
1668
|
+
if (!indexPage) createIndex();
|
|
1669
|
+
const newYears = /* @__PURE__ */ new Map();
|
|
1670
|
+
for (const article of ezal.Article.getAll()) {
|
|
1671
|
+
const year = article.date.year;
|
|
1672
|
+
let count = newYears.get(year);
|
|
1673
|
+
if (count === void 0) count = 0;
|
|
1674
|
+
count++;
|
|
1675
|
+
newYears.set(year, count);
|
|
1676
|
+
}
|
|
1677
|
+
years.clear();
|
|
1678
|
+
for (const [year, count] of newYears) years.set(year, count);
|
|
1679
|
+
indexPage.invalidated();
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
//#endregion
|
|
1683
|
+
//#region packages/ezal-theme-example/src/page/category.ts
|
|
1684
|
+
const categories = /* @__PURE__ */ new Map();
|
|
1685
|
+
function createPage$2(category) {
|
|
1686
|
+
const id = `category/${category.path.join("/")}`;
|
|
1687
|
+
const data = { category };
|
|
1688
|
+
return new ezal.VirtualPage({
|
|
1689
|
+
id,
|
|
1690
|
+
src: `/${id}/`,
|
|
1691
|
+
title: `分类:${category.name}`,
|
|
1692
|
+
layout: "category",
|
|
1693
|
+
data
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
let scanned$2 = false;
|
|
1697
|
+
function updateCategoryPage(_any) {
|
|
1698
|
+
if (!scanned$2 && _any) return;
|
|
1699
|
+
scanned$2 = true;
|
|
1700
|
+
for (const [category, page] of categories.entries().toArray()) {
|
|
1701
|
+
if (!category.destroyed) continue;
|
|
1702
|
+
page.destroy();
|
|
1703
|
+
categories.delete(category);
|
|
1704
|
+
}
|
|
1705
|
+
for (const category of ezal.Category.getAll()) {
|
|
1706
|
+
if (categories.has(category)) continue;
|
|
1707
|
+
categories.set(category, createPage$2(category));
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
//#endregion
|
|
1712
|
+
//#region packages/ezal-theme-example/src/page/home.ts
|
|
1713
|
+
const pages = [];
|
|
1714
|
+
function getArticles(index$1) {
|
|
1715
|
+
const pre = getThemeConfig().home?.articlesPrePage ?? 10;
|
|
1716
|
+
const offset = index$1 * pre;
|
|
1717
|
+
return ezal.Article.getAll().toSorted(compareByDate).slice(offset, offset + pre);
|
|
1718
|
+
}
|
|
1719
|
+
function getPages() {
|
|
1720
|
+
return pages;
|
|
1721
|
+
}
|
|
1722
|
+
function createPage$1(index$1) {
|
|
1723
|
+
const i = String(index$1 + 1);
|
|
1724
|
+
const data = {
|
|
1725
|
+
index: index$1,
|
|
1726
|
+
getPages,
|
|
1727
|
+
getArticles
|
|
1728
|
+
};
|
|
1729
|
+
return new ezal.VirtualPage({
|
|
1730
|
+
id: index$1 ? `${i}/` : "",
|
|
1731
|
+
src: `/${index$1 ? `${i}/` : ""}`,
|
|
1732
|
+
layout: "home",
|
|
1733
|
+
data
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
let scanned$1 = false;
|
|
1737
|
+
function updateHomePage(article) {
|
|
1738
|
+
if (!scanned$1 && article) return;
|
|
1739
|
+
scanned$1 = true;
|
|
1740
|
+
const pre = getThemeConfig().home?.articlesPrePage ?? 10;
|
|
1741
|
+
const count = Math.ceil(Math.max(ezal.Article.getAll().length / pre, 1));
|
|
1742
|
+
if (count > pages.length) for (let i = pages.length; i < count; i++) pages.push(createPage$1(i));
|
|
1743
|
+
else if (count < pages.length) for (const page of pages.splice(count)) page.destroy();
|
|
1744
|
+
for (const page of pages) page.invalidated();
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
//#endregion
|
|
1748
|
+
//#region packages/ezal-theme-example/src/page/tag.ts
|
|
1749
|
+
const tags = /* @__PURE__ */ new Map();
|
|
1750
|
+
function createPage(tag) {
|
|
1751
|
+
const id = `tag/${tag.name}`;
|
|
1752
|
+
const data = { tag };
|
|
1753
|
+
return new ezal.VirtualPage({
|
|
1754
|
+
id,
|
|
1755
|
+
src: `/${id}/`,
|
|
1756
|
+
title: `标签:${tag.name}`,
|
|
1757
|
+
layout: "tag",
|
|
1758
|
+
data
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1761
|
+
let scanned = false;
|
|
1762
|
+
function updateTagPage(_any) {
|
|
1763
|
+
if (!scanned && _any) return;
|
|
1764
|
+
scanned = true;
|
|
1765
|
+
for (const [tag, page] of tags.entries().toArray()) {
|
|
1766
|
+
if (!tag.destroyed) continue;
|
|
1767
|
+
page.destroy();
|
|
1768
|
+
tags.delete(tag);
|
|
1769
|
+
}
|
|
1770
|
+
for (const tag of ezal.Tag.getAll()) {
|
|
1771
|
+
if (tags.has(tag)) continue;
|
|
1772
|
+
tags.set(tag, createPage(tag));
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
//#endregion
|
|
1777
|
+
//#region packages/ezal-theme-example/src/pagefind.ts
|
|
1778
|
+
const logger = new ezal.Logger("theme:index");
|
|
1779
|
+
let index;
|
|
1780
|
+
const assets = /* @__PURE__ */ new Map();
|
|
1781
|
+
var PagefindIndex = class extends ezal.VirtualAssets {
|
|
1782
|
+
buffer;
|
|
1783
|
+
constructor(url, buffer) {
|
|
1784
|
+
super(url);
|
|
1785
|
+
this.buffer = buffer;
|
|
1786
|
+
}
|
|
1787
|
+
build() {
|
|
1788
|
+
return this.buffer;
|
|
1789
|
+
}
|
|
1790
|
+
onDependenciesChanged() {}
|
|
1791
|
+
};
|
|
1792
|
+
/** 重建索引文件虚拟资源 */
|
|
1793
|
+
async function rebuildIndexFile() {
|
|
1794
|
+
if (!index) return;
|
|
1795
|
+
const { errors, files } = await index.getFiles();
|
|
1796
|
+
if (errors.length > 0) {
|
|
1797
|
+
if ((0, ezal.getMode)() === "build") logger.fatal(errors);
|
|
1798
|
+
else logger.error(errors);
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
const fileMap = new Map(files.map(({ path: path$8, content }) => [path$8, Buffer.from(content)]));
|
|
1802
|
+
for (const [path$8, asset$2] of assets.entries().toArray()) {
|
|
1803
|
+
if (fileMap.has(path$8)) continue;
|
|
1804
|
+
asset$2.destroy();
|
|
1805
|
+
assets.delete(path$8);
|
|
1806
|
+
}
|
|
1807
|
+
for (const [path$8, buffer] of fileMap) {
|
|
1808
|
+
let asset$2 = assets.get(path$8);
|
|
1809
|
+
if (asset$2) {
|
|
1810
|
+
asset$2.buffer = buffer;
|
|
1811
|
+
asset$2.invalidated();
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1814
|
+
asset$2 = new PagefindIndex(path$8, buffer);
|
|
1815
|
+
assets.set(path$8, asset$2);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
/**
|
|
1819
|
+
* 添加页面
|
|
1820
|
+
* @description 构建模式下需启用强制才能添加索引
|
|
1821
|
+
*/
|
|
1822
|
+
async function addPage(page, force) {
|
|
1823
|
+
if (!index) return [];
|
|
1824
|
+
if ((0, ezal.getMode)() === "build" && !force) return [];
|
|
1825
|
+
const allowIndex = page.data?.index;
|
|
1826
|
+
if (page instanceof ezal.Article) {
|
|
1827
|
+
if (allowIndex === false) return [];
|
|
1828
|
+
} else if (!allowIndex) return [];
|
|
1829
|
+
const { errors } = await index.addCustomRecord({
|
|
1830
|
+
url: page.url,
|
|
1831
|
+
content: page.content ?? page.markdownContent ?? "",
|
|
1832
|
+
language: (0, ezal.getConfig)().site.language,
|
|
1833
|
+
meta: { title: page.title }
|
|
1834
|
+
});
|
|
1835
|
+
if (errors.length > 0) logger.error(errors);
|
|
1836
|
+
if (!force) await rebuildIndexFile();
|
|
1837
|
+
return errors;
|
|
1838
|
+
}
|
|
1839
|
+
/** 创建所有页面索引 */
|
|
1840
|
+
async function buildAllIndex() {
|
|
1841
|
+
const errors = [];
|
|
1842
|
+
for (const article of ezal.Article.getAll()) errors.push(...await addPage(article, true));
|
|
1843
|
+
for (const page of ezal.Page.getAll()) errors.push(...await addPage(page, true));
|
|
1844
|
+
return errors;
|
|
1845
|
+
}
|
|
1846
|
+
/**
|
|
1847
|
+
* 清除并重建索引
|
|
1848
|
+
* @description 构建模式下无效
|
|
1849
|
+
*/
|
|
1850
|
+
async function rebuildPagefind() {
|
|
1851
|
+
if (!index) return;
|
|
1852
|
+
if ((0, ezal.getMode)() === "build") return;
|
|
1853
|
+
await index.deleteIndex();
|
|
1854
|
+
const response = await (await import("pagefind")).createIndex();
|
|
1855
|
+
if (!response.index) throw response.errors;
|
|
1856
|
+
index = response.index;
|
|
1857
|
+
await buildAllIndex();
|
|
1858
|
+
await rebuildIndexFile();
|
|
1859
|
+
}
|
|
1860
|
+
/** 构建 Pagefind */
|
|
1861
|
+
async function buildPagefind() {
|
|
1862
|
+
if (!index) throw new Error("Pagefind not initialized");
|
|
1863
|
+
await buildAllIndex();
|
|
1864
|
+
await rebuildIndexFile();
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* 初始化 PageFind
|
|
1868
|
+
* @description 构建模式下不会构建索引
|
|
1869
|
+
*/
|
|
1870
|
+
async function initPagefind() {
|
|
1871
|
+
if (index) return;
|
|
1872
|
+
const response = await (await import("pagefind")).createIndex();
|
|
1873
|
+
if (!response.index) throw response.errors;
|
|
1874
|
+
index = response.index;
|
|
1875
|
+
if ((0, ezal.getMode)() === "build") return;
|
|
1876
|
+
await rebuildPagefind();
|
|
1877
|
+
}
|
|
1878
|
+
/** 停止 PageFind */
|
|
1879
|
+
async function stopPagefind() {
|
|
1880
|
+
await (await import("pagefind")).close();
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
//#endregion
|
|
1884
|
+
//#region packages/ezal-theme-example/src/sitemap.ts
|
|
1885
|
+
function getInfo(page) {
|
|
1886
|
+
let img$1 = page.data?.cover;
|
|
1887
|
+
if (img$1) img$1 = ezal.URL.resolve(page.url, img$1);
|
|
1888
|
+
return {
|
|
1889
|
+
url: page.url,
|
|
1890
|
+
changefreq: "weekly",
|
|
1891
|
+
img: img$1
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
var Sitemap = class extends ezal.VirtualAssets {
|
|
1895
|
+
constructor() {
|
|
1896
|
+
super("/sitemap.xml");
|
|
1897
|
+
}
|
|
1898
|
+
build() {
|
|
1899
|
+
const { site } = (0, ezal.getConfig)();
|
|
1900
|
+
const stream = new sitemap.SitemapStream({ hostname: site.domain });
|
|
1901
|
+
stream.write({ url: "/" });
|
|
1902
|
+
const pre = getThemeConfig().home?.articlesPrePage ?? 10;
|
|
1903
|
+
const count = Math.ceil(Math.max(ezal.Article.getAll().length / pre, 1));
|
|
1904
|
+
for (let i = 2; i <= count; i++) stream.write({ url: `/${i}/` });
|
|
1905
|
+
for (const article of ezal.Article.getAll()) {
|
|
1906
|
+
if (article.data?.sitemap === false) continue;
|
|
1907
|
+
stream.write(getInfo(article));
|
|
1908
|
+
}
|
|
1909
|
+
for (const page of ezal.Page.getAll()) {
|
|
1910
|
+
if (!page.data?.sitemap) continue;
|
|
1911
|
+
stream.write(getInfo(page));
|
|
1912
|
+
}
|
|
1913
|
+
stream.end();
|
|
1914
|
+
return stream;
|
|
1915
|
+
}
|
|
1916
|
+
onDependenciesChanged() {}
|
|
1917
|
+
};
|
|
1918
|
+
let asset;
|
|
1919
|
+
function initSitemap() {
|
|
1920
|
+
asset = new Sitemap();
|
|
1921
|
+
}
|
|
1922
|
+
function updateSitemap() {
|
|
1923
|
+
asset?.invalidated();
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
//#endregion
|
|
1927
|
+
//#region packages/ezal-theme-example/src/transform/script.ts
|
|
1928
|
+
const scriptTransformRule = {
|
|
1929
|
+
from: ".ts",
|
|
1930
|
+
to: ".js",
|
|
1931
|
+
async transformer(src) {
|
|
1932
|
+
const buildMode = (0, ezal.getMode)() === "build";
|
|
1933
|
+
const { outputFiles, metafile: { inputs } } = await esbuild.default.build({
|
|
1934
|
+
entryPoints: [src],
|
|
1935
|
+
loader: { ".ts": "ts" },
|
|
1936
|
+
external: ["../pagefind.js"],
|
|
1937
|
+
bundle: true,
|
|
1938
|
+
platform: "browser",
|
|
1939
|
+
format: "iife",
|
|
1940
|
+
target: "es2024",
|
|
1941
|
+
write: false,
|
|
1942
|
+
metafile: true,
|
|
1943
|
+
sourcemap: buildMode ? false : "inline",
|
|
1944
|
+
treeShaking: buildMode,
|
|
1945
|
+
minify: buildMode
|
|
1946
|
+
});
|
|
1947
|
+
const cwd = process.cwd();
|
|
1948
|
+
return {
|
|
1949
|
+
result: outputFiles[0].text,
|
|
1950
|
+
dependencies: Object.keys(inputs).map((src$1) => node_path.default.join(cwd, src$1))
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
};
|
|
1954
|
+
|
|
1955
|
+
//#endregion
|
|
1956
|
+
//#region packages/ezal-theme-example/src/transform/stylus.ts
|
|
1957
|
+
const STYLE_CONFIGS = {
|
|
1958
|
+
"color.light": () => getThemeConfig().color?.light,
|
|
1959
|
+
"color.dark": () => getThemeConfig().color?.dark,
|
|
1960
|
+
waline: () => !!getThemeConfig().waline
|
|
1961
|
+
};
|
|
1962
|
+
function config({ val }) {
|
|
1963
|
+
if (val in STYLE_CONFIGS) return STYLE_CONFIGS[val]();
|
|
1964
|
+
}
|
|
1965
|
+
function linksStyle({ val }) {
|
|
1966
|
+
const styles = getThemeConfig().linkPageStyles;
|
|
1967
|
+
if (!styles) return true;
|
|
1968
|
+
return styles.includes(val);
|
|
1969
|
+
}
|
|
1970
|
+
const cleaner = new clean_css.default();
|
|
1971
|
+
const styleTransformRule = {
|
|
1972
|
+
from: ".styl",
|
|
1973
|
+
to: ".css",
|
|
1974
|
+
async transformer(src) {
|
|
1975
|
+
const file = await ezal.fs.readFile(src);
|
|
1976
|
+
if (file instanceof Error) return file;
|
|
1977
|
+
try {
|
|
1978
|
+
const renderer$1 = (0, stylus.default)(file, {
|
|
1979
|
+
paths: [node_path.default.join(src, "..")],
|
|
1980
|
+
filename: node_path.default.basename(src),
|
|
1981
|
+
functions: {
|
|
1982
|
+
config,
|
|
1983
|
+
linksStyle
|
|
1984
|
+
},
|
|
1985
|
+
"include css": true
|
|
1986
|
+
});
|
|
1987
|
+
const dependencies = renderer$1.deps().map((dep) => {
|
|
1988
|
+
if (!dep.startsWith("//?/")) return dep;
|
|
1989
|
+
return node_path.default.normalize(dep.slice(4));
|
|
1990
|
+
});
|
|
1991
|
+
let result = renderer$1.render();
|
|
1992
|
+
if ((0, ezal.getMode)() === "build") result = cleaner.minify(result).styles;
|
|
1993
|
+
return {
|
|
1994
|
+
result,
|
|
1995
|
+
dependencies
|
|
1996
|
+
};
|
|
1997
|
+
} catch (error) {
|
|
1998
|
+
return (0, ezal.normalizeError)(error);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
|
|
2003
|
+
//#endregion
|
|
2004
|
+
//#region packages/ezal-theme-example/src/index.ts
|
|
2005
|
+
async function theme(config$2) {
|
|
2006
|
+
setThemeConfig(config$2);
|
|
2007
|
+
imageDB.init();
|
|
2008
|
+
return {
|
|
2009
|
+
assetsRoot: node_path.default.join(__dirname, "../assets"),
|
|
2010
|
+
transformRules: [styleTransformRule, scriptTransformRule],
|
|
2011
|
+
layout: layoutConfig,
|
|
2012
|
+
pageHandlers: [await markdownPageHandler()],
|
|
2013
|
+
hooks: {
|
|
2014
|
+
"config:after": [initCodeblockStyle],
|
|
2015
|
+
"scan:after": [
|
|
2016
|
+
updateHomePage,
|
|
2017
|
+
updateArchivePage,
|
|
2018
|
+
updateCategoryPage,
|
|
2019
|
+
updateTagPage,
|
|
2020
|
+
init404Page,
|
|
2021
|
+
initPagefind,
|
|
2022
|
+
initSitemap,
|
|
2023
|
+
initFeed
|
|
2024
|
+
],
|
|
2025
|
+
"asset:add": [imageAddHook],
|
|
2026
|
+
"asset:update": [imageUpdateHook],
|
|
2027
|
+
"asset:remove": [imageRemoveHook],
|
|
2028
|
+
"build:before:assets-virtual": [
|
|
2029
|
+
setupCodeblockStyle,
|
|
2030
|
+
buildPagefind,
|
|
2031
|
+
updateSitemap
|
|
2032
|
+
],
|
|
2033
|
+
"build:after": [stopPagefind, exeIndexNow],
|
|
2034
|
+
"article:add": [updateHomePage, updateArchivePage],
|
|
2035
|
+
"article:update": [
|
|
2036
|
+
updateHomePage,
|
|
2037
|
+
updateArchivePage,
|
|
2038
|
+
addPage,
|
|
2039
|
+
updateSitemap,
|
|
2040
|
+
updateFeedItem
|
|
2041
|
+
],
|
|
2042
|
+
"article:remove": [
|
|
2043
|
+
updateHomePage,
|
|
2044
|
+
updateArchivePage,
|
|
2045
|
+
rebuildPagefind,
|
|
2046
|
+
updateSitemap,
|
|
2047
|
+
updateFeedItem
|
|
2048
|
+
],
|
|
2049
|
+
"article:build:after": [addPage, updateFeedItem],
|
|
2050
|
+
"page:update": [addPage, updateSitemap],
|
|
2051
|
+
"page:remove": [rebuildPagefind, updateSitemap],
|
|
2052
|
+
"page:build:after": [addPage],
|
|
2053
|
+
"category:add": [updateCategoryPage],
|
|
2054
|
+
"category:update": [updateCategoryPage, updateFeedCategory],
|
|
2055
|
+
"category:remove": [updateCategoryPage, updateFeedCategory],
|
|
2056
|
+
"tag:add": [updateTagPage],
|
|
2057
|
+
"tag:update": [updateTagPage],
|
|
2058
|
+
"tag:remove": [updateTagPage],
|
|
2059
|
+
"preview:stop": [stopPagefind]
|
|
2060
|
+
}
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
//#endregion
|
|
2065
|
+
exports.theme = theme;
|
|
2066
|
+
//# sourceMappingURL=index.js.map
|