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.
Files changed (102) hide show
  1. package/LICENSE +21 -0
  2. package/assets/scripts/404.ts +353 -0
  3. package/assets/scripts/_article.ts +290 -0
  4. package/assets/scripts/_base.ts +65 -0
  5. package/assets/scripts/_pagefind.d.ts +424 -0
  6. package/assets/scripts/_search.ts +88 -0
  7. package/assets/scripts/_utils.ts +74 -0
  8. package/assets/scripts/archive.ts +143 -0
  9. package/assets/scripts/article.ts +18 -0
  10. package/assets/scripts/category.ts +4 -0
  11. package/assets/scripts/home.ts +73 -0
  12. package/assets/scripts/links.ts +14 -0
  13. package/assets/scripts/main.ts +11 -0
  14. package/assets/scripts/page.ts +11 -0
  15. package/assets/scripts/tag.ts +4 -0
  16. package/assets/scripts/tsconfig.json +10 -0
  17. package/assets/styles/404.styl +31 -0
  18. package/assets/styles/_article/fold.styl +15 -0
  19. package/assets/styles/_article/footnote.styl +12 -0
  20. package/assets/styles/_article/heading.styl +29 -0
  21. package/assets/styles/_article/image.styl +30 -0
  22. package/assets/styles/_article/kbd.styl +10 -0
  23. package/assets/styles/_article/links.styl +31 -0
  24. package/assets/styles/_article/list.styl +19 -0
  25. package/assets/styles/_article/note.styl +18 -0
  26. package/assets/styles/_article/other.styl +44 -0
  27. package/assets/styles/_article/table.styl +29 -0
  28. package/assets/styles/_article/tabs.styl +25 -0
  29. package/assets/styles/_code.styl +83 -0
  30. package/assets/styles/_index/contact.styl +20 -0
  31. package/assets/styles/_index/footer.styl +5 -0
  32. package/assets/styles/_index/header.styl +40 -0
  33. package/assets/styles/_index/nav.styl +59 -0
  34. package/assets/styles/_index/search.styl +64 -0
  35. package/assets/styles/_index.styl +91 -0
  36. package/assets/styles/_var.styl +96 -0
  37. package/assets/styles/archive.styl +35 -0
  38. package/assets/styles/article.styl +138 -0
  39. package/assets/styles/category.styl +4 -0
  40. package/assets/styles/home.styl +124 -0
  41. package/assets/styles/links.styl +121 -0
  42. package/assets/styles/page.styl +12 -0
  43. package/assets/styles/tag.styl +4 -0
  44. package/dist/config.d.ts +128 -0
  45. package/dist/feed.d.ts +4 -0
  46. package/dist/image/asset.d.ts +22 -0
  47. package/dist/image/db.d.ts +18 -0
  48. package/dist/image/index.d.ts +10 -0
  49. package/dist/image/metadata.d.ts +2 -0
  50. package/dist/image/utils.d.ts +1 -0
  51. package/dist/index-now.d.ts +1 -0
  52. package/dist/index.d.ts +3 -0
  53. package/dist/index.js +2066 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/layout.d.ts +2 -0
  56. package/dist/markdown/codeblock/data.d.ts +1 -0
  57. package/dist/markdown/codeblock/index.d.ts +6 -0
  58. package/dist/markdown/codeblock/style.d.ts +2 -0
  59. package/dist/markdown/fold.d.ts +6 -0
  60. package/dist/markdown/footnote.d.ts +15 -0
  61. package/dist/markdown/image.d.ts +12 -0
  62. package/dist/markdown/index.d.ts +2 -0
  63. package/dist/markdown/kbd.d.ts +6 -0
  64. package/dist/markdown/link.d.ts +2 -0
  65. package/dist/markdown/links.d.ts +12 -0
  66. package/dist/markdown/note.d.ts +8 -0
  67. package/dist/markdown/table.d.ts +3 -0
  68. package/dist/markdown/tabs.d.ts +7 -0
  69. package/dist/markdown/tex.d.ts +9 -0
  70. package/dist/page/404.d.ts +1 -0
  71. package/dist/page/archive.d.ts +1 -0
  72. package/dist/page/category.d.ts +1 -0
  73. package/dist/page/home.d.ts +2 -0
  74. package/dist/page/tag.d.ts +1 -0
  75. package/dist/pagefind.d.ts +20 -0
  76. package/dist/sitemap.d.ts +2 -0
  77. package/dist/transform/script.d.ts +2 -0
  78. package/dist/transform/stylus.d.ts +2 -0
  79. package/dist/utils.d.ts +2 -0
  80. package/layouts/404.tsx +8 -0
  81. package/layouts/archive.tsx +81 -0
  82. package/layouts/article.tsx +145 -0
  83. package/layouts/base.tsx +20 -0
  84. package/layouts/category.tsx +18 -0
  85. package/layouts/components/ArchiveArticleList.tsx +14 -0
  86. package/layouts/components/Article.tsx +46 -0
  87. package/layouts/components/Contact.tsx +14 -0
  88. package/layouts/components/Footer.tsx +44 -0
  89. package/layouts/components/Head.tsx +119 -0
  90. package/layouts/components/Image.tsx +42 -0
  91. package/layouts/components/Nav.tsx +33 -0
  92. package/layouts/components/Search.tsx +20 -0
  93. package/layouts/components/Waline.tsx +22 -0
  94. package/layouts/context.d.ts +54 -0
  95. package/layouts/home.tsx +74 -0
  96. package/layouts/links.tsx +53 -0
  97. package/layouts/page.tsx +19 -0
  98. package/layouts/tag.tsx +18 -0
  99. package/layouts/tsconfig.json +11 -0
  100. package/package.json +47 -0
  101. package/readme.md +17 -0
  102. 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