volute 0.54.0 → 0.56.0

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 (204) hide show
  1. package/dist/{activity-events-LQII6PZS.js → activity-events-YASF46HS.js} +3 -3
  2. package/dist/{ai-service-YW5SWCSB.js → ai-service-3UFNG6GI.js} +3 -5
  3. package/dist/{archive-FOHGXHPT.js → archive-L2OFBGDQ.js} +2 -2
  4. package/dist/{auth-KRDSM55Q.js → auth-N2F5ASAB.js} +4 -4
  5. package/dist/auto-upgrade-O4MQPYQF.js +46 -0
  6. package/dist/{avatar-image-52WGXLHV.js → avatar-image-QEKKUFDF.js} +3 -3
  7. package/dist/{backup-QRNX6RK7.js → backup-TPM7QQBQ.js} +13 -13
  8. package/dist/{channels-CKCY64TD.js → channels-JP3GYTPX.js} +18 -18
  9. package/dist/{chat-ZUGNL5GS.js → chat-7YCF4ZU5.js} +3 -3
  10. package/dist/{chunk-QUSMYGNQ.js → chunk-2674KIGI.js} +1 -0
  11. package/dist/{chunk-444RR3YF.js → chunk-2B4E6SL7.js} +14 -14
  12. package/dist/chunk-2GATCSZK.js +520 -0
  13. package/dist/{chunk-I7U5EEZC.js → chunk-2LFTJNVH.js} +2 -2
  14. package/dist/{chunk-L7BKTZ5U.js → chunk-2QLWAYIU.js} +2 -2
  15. package/dist/{chunk-F6D766VQ.js → chunk-45MCH4G4.js} +2 -2
  16. package/dist/{chunk-OGPVJ53N.js → chunk-4RZS7XCV.js} +5 -5
  17. package/dist/{chunk-HKGYZVWN.js → chunk-6LICEQGP.js} +38 -4
  18. package/dist/{chunk-LAUCO2HC.js → chunk-APDEUAIE.js} +1 -1
  19. package/dist/{chunk-5Y54AE3L.js → chunk-CLH357FI.js} +2 -2
  20. package/dist/{chunk-OAYY3WF3.js → chunk-CVPCRWWC.js} +1 -12
  21. package/dist/{chunk-EGV6R6UF.js → chunk-E2SN3ZOJ.js} +5 -40
  22. package/dist/{chunk-LGXVGIWN.js → chunk-ELQU2GBT.js} +193 -69
  23. package/dist/{chunk-OT5SXF7L.js → chunk-EPRLTYJR.js} +28 -14
  24. package/dist/{chunk-ATZF2RNJ.js → chunk-EYFBT2KP.js} +15 -15
  25. package/dist/{chunk-U54PJPTB.js → chunk-FYMIGUJ5.js} +2 -2
  26. package/dist/{chunk-7XKPG66D.js → chunk-G7A5LEVI.js} +5 -5
  27. package/dist/{chunk-RGHF3OK5.js → chunk-GAAATVTM.js} +17 -17
  28. package/dist/{chunk-7LT3YZUR.js → chunk-I3OJ342S.js} +2 -2
  29. package/dist/{chunk-3LHUXY3E.js → chunk-IABDYN4N.js} +4 -4
  30. package/dist/{chunk-VDUCLVZI.js → chunk-IOMBP2T5.js} +28 -26
  31. package/dist/{chunk-YSRYCS3N.js → chunk-IQROTVBG.js} +2 -2
  32. package/dist/{chunk-PPSN2MLC.js → chunk-IRNM4LSF.js} +9 -6
  33. package/dist/{chunk-ZNHL5KQJ.js → chunk-KN3UHV7O.js} +8 -3
  34. package/dist/{chunk-CV6BNGFK.js → chunk-KXM4K46T.js} +4 -4
  35. package/dist/{chunk-Z4Q6TQWL.js → chunk-LRRPKZBD.js} +2 -2
  36. package/dist/{chunk-LNNI3MS4.js → chunk-MNKPAAQF.js} +9 -2
  37. package/dist/{chunk-OIOW3FPT.js → chunk-NA2NJXY4.js} +1 -1
  38. package/dist/{chunk-GLM7TVWP.js → chunk-OHHS5PSI.js} +1 -1
  39. package/dist/{chunk-CKPAVQNK.js → chunk-OPTA3BJ4.js} +36 -24
  40. package/dist/{chunk-X67BDDZR.js → chunk-P3GXOT2X.js} +48 -2
  41. package/dist/{chunk-WHL6PKYP.js → chunk-PAO7JZNW.js} +52 -48
  42. package/dist/{chunk-TPX6E6PL.js → chunk-Q5M5QFKY.js} +3 -3
  43. package/dist/{chunk-OYF25B62.js → chunk-T7UMSTH2.js} +3 -3
  44. package/dist/{chunk-H6X6CKDN.js → chunk-TAVIVN2I.js} +2 -32
  45. package/dist/{chunk-56IT2ZXF.js → chunk-TGYKFUCF.js} +9 -15
  46. package/dist/{chunk-5U5GLZSD.js → chunk-TZ7OHGNL.js} +2 -2
  47. package/dist/{chunk-UFTDRTCP.js → chunk-UMQP5TC5.js} +2 -2
  48. package/dist/{chunk-LKUGUQUW.js → chunk-UNTDRIV2.js} +5 -5
  49. package/dist/{chunk-CLCHOXLR.js → chunk-V2M6PNLE.js} +5 -5
  50. package/dist/{chunk-ICXY54ZC.js → chunk-WTZD6LFW.js} +2 -2
  51. package/dist/{chunk-FLIEXG2T.js → chunk-XZP3FJ7Q.js} +1 -1
  52. package/dist/{chunk-HTRSSOHY.js → chunk-YU5EYQAE.js} +1 -1
  53. package/dist/cli.js +26 -23
  54. package/dist/{clock-X7V3C7NL.js → clock-ZT5YT6HA.js} +2 -2
  55. package/dist/{cloud-sync-52YNJRMR.js → cloud-sync-RTUXMYU2.js} +23 -23
  56. package/dist/{conversations-ZL6PHROD.js → conversations-ERMMPMOS.js} +4 -4
  57. package/dist/{create-G2RIKQYK.js → create-IUCFJXCE.js} +1 -1
  58. package/dist/{daemon-restart-QWHN5VMU.js → daemon-restart-N2YOISNJ.js} +11 -6
  59. package/dist/daemon.js +230 -279
  60. package/dist/{db-BONH4SUG.js → db-BQFYIONA.js} +1 -1
  61. package/dist/{db-I4EH5SLF.js → db-JH3NTERX.js} +17 -3
  62. package/dist/delivery-manager-5EGCFN4K.js +41 -0
  63. package/dist/{delivery-notices-RZQ6GONP.js → delivery-notices-LZKZXWTX.js} +6 -6
  64. package/dist/{delivery-router-QS4NLJR6.js → delivery-router-U6Q22ZYU.js} +3 -3
  65. package/dist/doctor-225FYBAQ.js +454 -0
  66. package/dist/{down-UN2EDX2Y.js → down-3BQSPUAZ.js} +4 -4
  67. package/dist/echo-text-Y2DFTD7L.js +40 -0
  68. package/dist/{env-SQFCWW52.js → env-4YX5YNWZ.js} +2 -2
  69. package/dist/{exec-Z34TTUO3.js → exec-Y5VMDAVA.js} +2 -2
  70. package/dist/{export-VBNWM7I4.js → export-ASRHBMRG.js} +2 -2
  71. package/dist/{extensions-QT65JGV6.js → extensions-YEPEWURN.js} +27 -23
  72. package/dist/{files-PCKBQHAY.js → files-FASUDSZQ.js} +3 -3
  73. package/dist/{import-DB2KULRO.js → import-O35Y7DSF.js} +6 -6
  74. package/dist/{isolation-UQPDO34R.js → isolation-ZOAUXYXA.js} +2 -2
  75. package/dist/{login-57MMYILL.js → login-54TZQQP4.js} +5 -5
  76. package/dist/{logout-YFZAJRPY.js → logout-4G46Z4RU.js} +1 -1
  77. package/dist/message-delivery-HBTMGWFU.js +46 -0
  78. package/dist/{mind-CT6ANXK4.js → mind-IKMX7K7G.js} +8 -24
  79. package/dist/{mind-activity-tracker-QF6DCX2X.js → mind-activity-tracker-ABAEIMA3.js} +4 -4
  80. package/dist/mind-service-LRVOQG2T.js +48 -0
  81. package/dist/{mind-sleep-24HV4RCA.js → mind-sleep-LZAFBDZD.js} +2 -2
  82. package/dist/{package-F6S5NHY2.js → package-X5O7OD2E.js} +12 -13
  83. package/dist/{prompts-JECJIFPQ.js → prompts-ZNOE3KN3.js} +2 -2
  84. package/dist/{registry-TRC2HJXR.js → registry-BTQXLDW6.js} +1 -1
  85. package/dist/{sandbox-NNWCTHRI.js → sandbox-OUFAGN45.js} +3 -3
  86. package/dist/scheduler-G6BCIVGP.js +27 -0
  87. package/dist/{seed-cmd-6IMTO3LG.js → seed-cmd-BGAW3WDY.js} +2 -2
  88. package/dist/{seed-create-VNLDYRFK.js → seed-create-SMCPEUFQ.js} +3 -3
  89. package/dist/{seed-readiness-H5TTPAQH.js → seed-readiness-RBANMSWW.js} +3 -3
  90. package/dist/{seed-sprout-PPGYGK4G.js → seed-sprout-CSHV36N3.js} +9 -9
  91. package/dist/{send-UXUQKO4N.js → send-D3ADUBR5.js} +6 -6
  92. package/dist/{service-T4P5W6RS.js → service-SWEEBOOY.js} +3 -24
  93. package/dist/{service-install-R4SNYUVO.js → service-install-RCC26KDV.js} +4 -4
  94. package/dist/{setup-YUAQMDVZ.js → setup-L5NZG2U3.js} +5 -5
  95. package/dist/{setup-WZSXHHRJ.js → setup-R7Q4HFJP.js} +1 -5
  96. package/dist/skills/volute-mind/SKILL.md +8 -0
  97. package/dist/{skills-GMQ5UIIW.js → skills-BCCU4OJW.js} +4 -4
  98. package/dist/sleep-manager-25P44HAO.js +42 -0
  99. package/dist/{spirit-Q5VGFWUI.js → spirit-YPG2MU6W.js} +7 -7
  100. package/dist/spirit-availability-ZQM5IH4C.js +43 -0
  101. package/dist/{src-H3UCOP6B.js → src-246GSX7A.js} +5 -2
  102. package/dist/src-LOUB3WPR.js +4189 -0
  103. package/dist/{status-LCKTTIWS.js → status-BYPCJU6H.js} +4 -4
  104. package/dist/{system-events-Q7IVZ5T4.js → system-events-CWC7CBKP.js} +6 -4
  105. package/dist/{systems-HL7SGSW7.js → systems-VDRUZXNF.js} +2 -2
  106. package/dist/{tailscale-KHNZFC7L.js → tailscale-4XY7B5A2.js} +2 -2
  107. package/dist/{template-hash-YKWMVYMM.js → template-hash-RJRMF6DT.js} +2 -2
  108. package/dist/{template-staleness-PY2CULH6.js → template-staleness-CL4V7BT7.js} +5 -5
  109. package/dist/{turn-tracker-HZDPMSCC.js → turn-tracker-LZP5X6GZ.js} +8 -8
  110. package/dist/{up-XZDSJVMU.js → up-3AAN4GYY.js} +4 -4
  111. package/dist/{update-ILCPVNDD.js → update-2MWXRE2S.js} +4 -4
  112. package/dist/{update-check-SZ7B5IFI.js → update-check-PJOZXZYJ.js} +2 -2
  113. package/dist/variant-cleanup-K7RFMSH7.js +24 -0
  114. package/dist/{version-notify-VNVFX6UP.js → version-notify-QIDHR6WO.js} +12 -12
  115. package/dist/web-assets/assets/{index-CwtxGwe_.js → index-Bfvls20e.js} +17 -17
  116. package/dist/web-assets/assets/index-hPn_fkz3.css +1 -0
  117. package/dist/web-assets/index.html +2 -2
  118. package/drizzle/0000_crazy_epoch.sql +232 -0
  119. package/drizzle/README.md +42 -0
  120. package/drizzle/meta/0000_snapshot.json +1420 -3
  121. package/drizzle/meta/_journal.json +2 -128
  122. package/package.json +12 -13
  123. package/packages/extensions/intentions/dist/ui/assets/index-Bl5KEcli.js +67 -0
  124. package/packages/extensions/intentions/dist/ui/index.html +1 -1
  125. package/packages/extensions/pages/dist/ui/assets/index-BKxVQkA9.css +1 -0
  126. package/packages/extensions/pages/dist/ui/assets/index-BMt6sStP.js +68 -0
  127. package/packages/extensions/pages/dist/ui/index.html +2 -2
  128. package/packages/extensions/pages/skills/pages/SKILL.md +123 -4
  129. package/templates/_base/.init/.config/prompts.json +0 -1
  130. package/templates/_base/.init/.local/hooks/pre-prompt/turn-context.ts +30 -0
  131. package/templates/_base/src/lib/codex-session-seed.ts +6 -55
  132. package/templates/_base/src/lib/pi-session-seed.ts +8 -57
  133. package/templates/_base/src/lib/seed-note.ts +4 -4
  134. package/templates/_base/src/lib/session-seed.ts +8 -53
  135. package/templates/_base/src/lib/startup.ts +0 -20
  136. package/templates/claude/package.json +2 -2
  137. package/templates/claude/src/agent.ts +34 -102
  138. package/templates/claude/src/lib/hooks/pre-compact.ts +6 -6
  139. package/templates/claude/src/server.ts +0 -1
  140. package/templates/codex/package.json +2 -2
  141. package/templates/codex/src/agent.ts +23 -89
  142. package/templates/pi/package.json +1 -1
  143. package/templates/pi/src/agent.ts +26 -93
  144. package/templates/pi/src/server.ts +0 -1
  145. package/dist/auto-upgrade-HEVZKPTF.js +0 -46
  146. package/dist/chunk-AAPNU7GA.js +0 -168
  147. package/dist/delivery-manager-7R2YIQ2W.js +0 -41
  148. package/dist/echo-text-73CYQRL7.js +0 -40
  149. package/dist/message-delivery-TRKT4T2P.js +0 -46
  150. package/dist/migrate-name-placeholder-C7NCNLWF.js +0 -37
  151. package/dist/migrate-thread-config-EQSEP2XG.js +0 -90
  152. package/dist/mind-service-7EFIJ3ZA.js +0 -48
  153. package/dist/scheduler-73Q4MQ7Y.js +0 -27
  154. package/dist/seed-DRKAP3XV.js +0 -11
  155. package/dist/sleep-manager-KHI65FEX.js +0 -42
  156. package/dist/spirit-availability-G5FMWKRH.js +0 -43
  157. package/dist/sprout-PMTRL7QN.js +0 -11
  158. package/dist/src-3FIW7DLH.js +0 -2376
  159. package/dist/src-LTTQVN2Z.js +0 -832
  160. package/dist/variant-HHDTW74J.js +0 -62
  161. package/dist/variant-cleanup-QHGGY7ND.js +0 -24
  162. package/dist/web-assets/assets/index-DhM1yYRN.css +0 -1
  163. package/drizzle/0000_baseline.sql +0 -152
  164. package/drizzle/0001_add_conversation_private.sql +0 -1
  165. package/drizzle/0002_turns.sql +0 -21
  166. package/drizzle/0003_turn_feed_links.sql +0 -11
  167. package/drizzle/0004_spirits.sql +0 -5
  168. package/drizzle/0005_meta_summaries.sql +0 -15
  169. package/drizzle/0006_channels.sql +0 -17
  170. package/drizzle/0007_drop_conversation_name_title.sql +0 -11
  171. package/drizzle/0008_performance_indexes.sql +0 -6
  172. package/drizzle/0009_mind_notices.sql +0 -14
  173. package/drizzle/0010_delivery_queue_redrive.sql +0 -10
  174. package/drizzle/0011_drop_turn_summary_event_id.sql +0 -3
  175. package/drizzle/0012_channel_gates.sql +0 -17
  176. package/drizzle/0013_variant_purpose.sql +0 -3
  177. package/drizzle/0014_system_events.sql +0 -26
  178. package/drizzle/0015_rename_session_to_thread.sql +0 -12
  179. package/drizzle/0016_brain_to_human.sql +0 -4
  180. package/drizzle/0017_event_history_rows.sql +0 -9
  181. package/drizzle/0018_api_tokens.sql +0 -20
  182. package/drizzle/meta/0001_snapshot.json +0 -7
  183. package/drizzle/meta/0002_snapshot.json +0 -7
  184. package/drizzle/meta/0003_snapshot.json +0 -7
  185. package/drizzle/meta/0004_snapshot.json +0 -7
  186. package/drizzle/meta/0005_snapshot.json +0 -7
  187. package/drizzle/meta/0006_snapshot.json +0 -7
  188. package/drizzle/meta/0007_snapshot.json +0 -7
  189. package/packages/extensions/intentions/dist/ui/assets/index-CQz4aceM.js +0 -67
  190. package/packages/extensions/notes/dist/ui/assets/index-BBs8pyel.js +0 -67
  191. package/packages/extensions/notes/dist/ui/assets/index-D3cdui42.css +0 -1
  192. package/packages/extensions/notes/dist/ui/index.html +0 -14
  193. package/packages/extensions/notes/skills/notes/SKILL.md +0 -90
  194. package/packages/extensions/pages/dist/ui/assets/index-B589e8Xe.js +0 -2
  195. package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +0 -1
  196. package/dist/{env-7AZFBPWX.js → env-IBW2QI6K.js} +5 -5
  197. package/dist/{login-4NUS72Z5.js → login-RJJTCVR3.js} +3 -3
  198. package/dist/{mind-contacts-PEXCDRXA.js → mind-contacts-KV64UDJS.js} +6 -6
  199. package/dist/{mind-history-RZMMCHMX.js → mind-history-H45GM2M2.js} +6 -6
  200. package/dist/{register-WNCSOTAU.js → register-OX4HRSGC.js} +3 -3
  201. package/dist/{restart-B4GNMVF2.js → restart-AGEGNSYQ.js} +4 -4
  202. package/dist/{skill-QYTBUDNQ.js → skill-B5OJEQUA.js} +4 -4
  203. package/dist/{start-BDHJVOVX.js → start-MUMNFR52.js} +3 -3
  204. package/dist/{stop-45QYSGYS.js → stop-EKERNYTX.js} +4 -4
@@ -1,2376 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- createExtension
4
- } from "./chunk-RG5TOL4O.js";
5
- import {
6
- getAllSites,
7
- getMindsWithSites,
8
- getPublishedPages,
9
- getRecentPages,
10
- getSystemPages,
11
- initDb,
12
- syncPublishedPages,
13
- syncSystemPages
14
- } from "./chunk-AAPNU7GA.js";
15
- import "./chunk-K3NQKI34.js";
16
-
17
- // packages/extensions/pages/src/index.ts
18
- import { resolve as resolve6 } from "path";
19
-
20
- // packages/extensions/pages/src/commands.ts
21
- import { cpSync, existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, rmSync as rmSync2, statSync as statSync2 } from "fs";
22
- import { relative as relative2, resolve as resolve3 } from "path";
23
-
24
- // packages/extensions/pages/src/commons.ts
25
- import { existsSync, readFileSync, writeFileSync } from "fs";
26
- import { resolve } from "path";
27
- function commonsReport(repoDir, systemFiles, mindsWithSites) {
28
- const index = systemFiles.find((f) => f === "index.md" || f === "index.html");
29
- if (!index) {
30
- return { hasIndex: false, orphanPages: [...systemFiles], unlinkedMinds: [...mindsWithSites] };
31
- }
32
- const contentOf = (f) => {
33
- try {
34
- return readFileSync(resolve(repoDir, f), "utf-8");
35
- } catch {
36
- return "";
37
- }
38
- };
39
- const reached = /* @__PURE__ */ new Set([index]);
40
- const queue = [index];
41
- while (queue.length > 0) {
42
- const content = contentOf(queue.shift());
43
- for (const f of systemFiles) {
44
- if (!reached.has(f) && content.includes(f)) {
45
- reached.add(f);
46
- queue.push(f);
47
- }
48
- }
49
- }
50
- const orphanPages = systemFiles.filter((f) => !reached.has(f));
51
- const reachableText = [...reached].map(contentOf).join("\n");
52
- const unlinkedMinds = mindsWithSites.filter(
53
- (m2) => !reachableText.includes(`../${m2}/`) && !reachableText.includes(`/ext/pages/public/${m2}/`)
54
- );
55
- return { hasIndex: true, orphanPages, unlinkedMinds };
56
- }
57
- async function maybeSendCommonsCue(ctx, repoDir) {
58
- const cueFlag = resolve(ctx.dataDir, ".commons-cue-sent");
59
- const hasIndex = existsSync(resolve(repoDir, "index.md")) || existsSync(resolve(repoDir, "index.html"));
60
- if (hasIndex || existsSync(cueFlag)) return;
61
- const spirit = ctx.getSpiritName();
62
- if (!spirit) return;
63
- try {
64
- if (!await ctx.getMindDir(spirit)) return;
65
- await ctx.recordNotice(
66
- spirit,
67
- "The commons \u2014 the shared pages at pages/_system/ that every mind here can edit \u2014 has no index yet. When you have a quiet moment, you might make one: a page that says what this place is, in your own voice, with room in it for the others. The commons-gardening skill describes the craft."
68
- );
69
- writeFileSync(cueFlag, (/* @__PURE__ */ new Date()).toISOString());
70
- } catch (err) {
71
- console.warn(`[pages] commons cue failed: ${err.message}`);
72
- }
73
- }
74
-
75
- // packages/extensions/pages/src/shared-pages.ts
76
- import { execFile as execFileCb } from "child_process";
77
- import { createHash } from "crypto";
78
- import {
79
- chmodSync,
80
- existsSync as existsSync2,
81
- mkdirSync,
82
- readdirSync,
83
- readFileSync as readFileSync2,
84
- rmSync,
85
- statSync,
86
- writeFileSync as writeFileSync2
87
- } from "fs";
88
- import { relative, resolve as resolve2 } from "path";
89
- function isolationFrom(ctx) {
90
- return { isIsolationEnabled: ctx.isIsolationEnabled, getMindUser: ctx.getMindUser };
91
- }
92
- function execAsync(cmd, args) {
93
- return new Promise((resolve7, reject) => {
94
- execFileCb(cmd, args, (err) => {
95
- if (err) reject(err);
96
- else resolve7();
97
- });
98
- });
99
- }
100
- var IDENTITY_ARGS = ["-c", "user.name=volute", "-c", "user.email=volute@localhost"];
101
- function gitExec(args, opts, isolation) {
102
- const prefix = [];
103
- if (isolation?.isIsolationEnabled()) prefix.push("-c", "safe.directory=*");
104
- if (args[0] === "commit") prefix.push(...IDENTITY_ARGS);
105
- const fullArgs = prefix.length ? [...prefix, ...args] : args;
106
- return new Promise((resolve7, reject) => {
107
- execFileCb("git", fullArgs, { cwd: opts.cwd }, (err, stdout, stderr) => {
108
- if (err) {
109
- const e = err;
110
- e.stderr = stderr;
111
- e.stdout = stdout;
112
- reject(err);
113
- } else {
114
- resolve7(stdout);
115
- }
116
- });
117
- });
118
- }
119
- function readWorktreeGitDir(worktreePath2) {
120
- const dotGit = resolve2(worktreePath2, ".git");
121
- if (!existsSync2(dotGit)) return null;
122
- try {
123
- const content = readFileSync2(dotGit, "utf-8").trim();
124
- const match = content.match(/^gitdir:\s*(.+)$/);
125
- return match ? match[1] : null;
126
- } catch (err) {
127
- console.warn(`[pages] failed to read .git file at ${dotGit}: ${err.message}`);
128
- return null;
129
- }
130
- }
131
- function pagesRepoDir(dataDir) {
132
- return resolve2(dataDir, "repo");
133
- }
134
- function worktreePath(mindDir) {
135
- return resolve2(mindDir, "home", "pages", "_system");
136
- }
137
- function pagesIsolationChownPaths(mindDir, wtGitDir) {
138
- const paths = [resolve2(mindDir, "home", "pages")];
139
- if (wtGitDir) paths.push(wtGitDir);
140
- return paths;
141
- }
142
- async function isRepoValid(dir, isolation) {
143
- try {
144
- await gitExec(["rev-parse", "HEAD"], { cwd: dir }, isolation);
145
- return true;
146
- } catch {
147
- return false;
148
- }
149
- }
150
- async function ensurePagesRepo(dataDir, isolation) {
151
- const dir = pagesRepoDir(dataDir);
152
- mkdirSync(dir, { recursive: true });
153
- if (existsSync2(resolve2(dir, ".git"))) {
154
- if (await isRepoValid(dir, isolation)) return;
155
- console.warn("[pages] repo invalid or incomplete, re-initializing");
156
- rmSync(resolve2(dir, ".git"), { recursive: true, force: true });
157
- }
158
- const isIso = isolation?.isIsolationEnabled() ?? false;
159
- const initArgs = isIso ? ["init", "--shared=group"] : ["init"];
160
- await gitExec(initArgs, { cwd: dir }, isolation);
161
- await gitExec(["checkout", "-b", "main"], { cwd: dir }, isolation);
162
- writeFileSync2(resolve2(dir, ".gitkeep"), "");
163
- await gitExec(["add", "-A"], { cwd: dir }, isolation);
164
- await gitExec(["commit", "-m", "init pages repo"], { cwd: dir }, isolation);
165
- if (isIso) {
166
- try {
167
- await execAsync("chgrp", ["-R", "volute", dir]);
168
- } catch {
169
- console.warn("[pages] failed to chgrp pages repo to volute group");
170
- }
171
- chmodSync(dir, 1533);
172
- }
173
- }
174
- async function addPagesWorktree(mindName, mindDir, dataDir, isolation) {
175
- const dir = pagesRepoDir(dataDir);
176
- if (!await isRepoValid(dir, isolation)) {
177
- console.warn(`[pages] repo not usable, skipping worktree for ${mindName}`);
178
- return;
179
- }
180
- const wt = worktreePath(mindDir);
181
- if (existsSync2(wt)) {
182
- if (!existsSync2(resolve2(wt, ".git"))) {
183
- console.warn(
184
- `[pages] ${wt} exists but is not a worktree \u2014 shared publishing will fail for ${mindName}. Move it aside and restart the mind to provision one.`
185
- );
186
- }
187
- return;
188
- }
189
- mkdirSync(resolve2(mindDir, "home", "pages"), { recursive: true });
190
- let branchExists = false;
191
- try {
192
- await gitExec(["rev-parse", "--verify", mindName], { cwd: dir }, isolation);
193
- branchExists = true;
194
- } catch {
195
- }
196
- if (branchExists) {
197
- await gitExec(["worktree", "add", wt, mindName], { cwd: dir }, isolation);
198
- } else {
199
- await gitExec(["worktree", "add", "-b", mindName, wt], { cwd: dir }, isolation);
200
- }
201
- if (isolation?.isIsolationEnabled()) {
202
- const user = isolation.getMindUser(mindName);
203
- const wtGitDir = readWorktreeGitDir(wt);
204
- for (const target of pagesIsolationChownPaths(mindDir, wtGitDir)) {
205
- try {
206
- await execAsync("chown", ["-R", `${user}:volute`, target]);
207
- } catch {
208
- console.warn(`[pages] failed to chown ${target} for ${mindName}`);
209
- }
210
- }
211
- }
212
- }
213
- var pagesLock = Promise.resolve();
214
- async function withPagesLock(fn) {
215
- const prev = pagesLock;
216
- let resolve_;
217
- pagesLock = new Promise((r) => {
218
- resolve_ = r;
219
- });
220
- await prev;
221
- try {
222
- return await fn();
223
- } finally {
224
- resolve_();
225
- }
226
- }
227
- async function pagesPull(mindName, mindDir, isolation) {
228
- return withPagesLock(async () => {
229
- const wt = worktreePath(mindDir);
230
- const status = (await gitExec(["status", "--porcelain"], { cwd: wt }, isolation)).trim();
231
- if (status) {
232
- await gitExec(["add", "-A"], { cwd: wt }, isolation);
233
- await gitExec(
234
- ["commit", "--author", `${mindName} <${mindName}@volute>`, "-m", `wip: ${mindName}`],
235
- { cwd: wt },
236
- isolation
237
- );
238
- }
239
- try {
240
- await gitExec(["rebase", "main"], { cwd: wt }, isolation);
241
- } catch (err) {
242
- const errMsg = err instanceof Error ? err.message : String(err);
243
- const isConflict = errMsg.includes("CONFLICT") || errMsg.includes("could not apply") || errMsg.includes("merge conflict");
244
- try {
245
- await gitExec(["rebase", "--abort"], { cwd: wt }, isolation);
246
- } catch (abortErr) {
247
- console.error("[pages] rebase abort failed", abortErr);
248
- }
249
- if (isConflict) {
250
- return {
251
- ok: false,
252
- conflicts: true,
253
- message: "Pull conflicts detected \u2014 your changes conflict with main. Reconcile the conflicting files, commit, and pull again."
254
- };
255
- }
256
- console.error("[pages] pull rebase failed", err);
257
- return { ok: false, message: `Pull failed: ${errMsg}` };
258
- }
259
- if (isolation?.isIsolationEnabled()) {
260
- try {
261
- await execAsync("chown", ["-R", `${isolation.getMindUser(mindName)}:volute`, wt]);
262
- } catch {
263
- }
264
- }
265
- return { ok: true, message: "Pulled latest shared changes." };
266
- });
267
- }
268
- async function pagesPullAndMerge(mindName, mindDir, dataDir, message, isolation) {
269
- return withPagesLock(async () => {
270
- const wt = worktreePath(mindDir);
271
- const dir = pagesRepoDir(dataDir);
272
- const status = (await gitExec(["status", "--porcelain"], { cwd: wt }, isolation)).trim();
273
- if (status) {
274
- await gitExec(["add", "-A"], { cwd: wt }, isolation);
275
- await gitExec(
276
- ["commit", "--author", `${mindName} <${mindName}@volute>`, "-m", `wip: ${mindName}`],
277
- { cwd: wt },
278
- isolation
279
- );
280
- }
281
- try {
282
- await gitExec(["rebase", "main"], { cwd: wt }, isolation);
283
- } catch (err) {
284
- const errMsg = err instanceof Error ? err.message : String(err);
285
- const isConflict = errMsg.includes("CONFLICT") || errMsg.includes("could not apply") || errMsg.includes("merge conflict");
286
- try {
287
- await gitExec(["rebase", "--abort"], { cwd: wt }, isolation);
288
- } catch (abortErr) {
289
- console.error("[pages] rebase abort failed", abortErr);
290
- }
291
- if (isConflict) {
292
- return {
293
- ok: false,
294
- conflicts: true,
295
- message: "Pull conflicts detected \u2014 your changes conflict with main. Reconcile the conflicting files, commit, and try again."
296
- };
297
- }
298
- return { ok: false, message: `Pull failed: ${errMsg}` };
299
- }
300
- const diff = (await gitExec(["diff", `main...${mindName}`, "--stat"], { cwd: dir }, isolation)).trim();
301
- if (!diff) {
302
- return { ok: true, message: "Nothing to publish" };
303
- }
304
- try {
305
- await gitExec(["merge", "--squash", mindName], { cwd: dir }, isolation);
306
- } catch (err) {
307
- const errOutput = [
308
- err.message,
309
- err.stderr ?? "",
310
- err.stdout ?? ""
311
- ].join("\n");
312
- const isConflict = errOutput.includes("CONFLICT") || errOutput.includes("could not apply");
313
- try {
314
- await gitExec(["reset", "--hard", "HEAD"], { cwd: dir }, isolation);
315
- } catch (resetErr) {
316
- console.error("[pages] reset after squash conflict failed", resetErr);
317
- }
318
- if (isConflict) {
319
- return { ok: false, conflicts: true, message: "Merge conflicts detected" };
320
- }
321
- return { ok: false, message: `Merge failed: ${err.message}` };
322
- }
323
- await gitExec(
324
- ["commit", "--author", `${mindName} <${mindName}@volute>`, "-m", message],
325
- { cwd: dir },
326
- isolation
327
- );
328
- let changedFiles = [];
329
- const priorAuthors = {};
330
- try {
331
- changedFiles = (await gitExec(["diff", "--name-only", "HEAD^", "HEAD"], { cwd: dir }, isolation)).trim().split("\n").filter(Boolean);
332
- for (const file of changedFiles) {
333
- const names = (await gitExec(["log", "--format=%an", "HEAD^", "--", file], { cwd: dir }, isolation)).trim().split("\n").filter(Boolean);
334
- const unique = [...new Set(names)].filter((n) => n !== mindName && n !== "volute");
335
- if (unique.length > 0) priorAuthors[file] = unique;
336
- }
337
- } catch (err) {
338
- console.warn(`[pages] contributor lookup failed: ${err.message}`);
339
- }
340
- try {
341
- await gitExec(["reset", "--hard", "main"], { cwd: wt }, isolation);
342
- } catch (err) {
343
- console.error(`[pages] branch reset failed for ${mindName}`, err);
344
- return {
345
- ok: true,
346
- message: "Published to main, but branch reset failed \u2014 run 'volute pages pull' to sync",
347
- changedFiles,
348
- priorAuthors
349
- };
350
- }
351
- if (isolation?.isIsolationEnabled()) {
352
- try {
353
- await execAsync("chown", ["-R", `${isolation.getMindUser(mindName)}:volute`, wt]);
354
- } catch {
355
- }
356
- }
357
- return { ok: true, changedFiles, priorAuthors };
358
- });
359
- }
360
- function collectPageFiles(dir) {
361
- const files = [];
362
- function walk(d2) {
363
- let items;
364
- try {
365
- items = readdirSync(d2);
366
- } catch (err) {
367
- if (err?.code === "ENOENT") return;
368
- throw err;
369
- }
370
- for (const item of items) {
371
- if (item.startsWith(".")) continue;
372
- const full = resolve2(d2, item);
373
- try {
374
- const s = statSync(full);
375
- if (s.isFile() && (item.endsWith(".html") || item.endsWith(".md"))) {
376
- files.push(relative(dir, full));
377
- } else if (s.isDirectory()) {
378
- walk(full);
379
- }
380
- } catch (err) {
381
- if (err?.code === "ENOENT" || err?.code === "EACCES") continue;
382
- throw err;
383
- }
384
- }
385
- }
386
- walk(dir);
387
- return files.sort();
388
- }
389
- function hashFiles(baseDir, files) {
390
- return files.map((file) => ({
391
- file,
392
- hash: createHash("sha256").update(readFileSync2(resolve2(baseDir, file))).digest("hex")
393
- }));
394
- }
395
- function isPageFile(f) {
396
- return f.endsWith(".html") || f.endsWith(".md");
397
- }
398
- async function pagesStatus(mindDir, isolation) {
399
- const wt = worktreePath(mindDir);
400
- const errors = [];
401
- const [mainFiles, branchFiles, uncommitted] = await Promise.all([
402
- gitExec(["ls-tree", "-r", "--name-only", "main"], { cwd: wt }, isolation).then((s) => s.trim().split("\n").filter(Boolean)).catch((err) => {
403
- errors.push(err);
404
- return [];
405
- }),
406
- gitExec(["ls-tree", "-r", "--name-only", "HEAD"], { cwd: wt }, isolation).then((s) => s.trim().split("\n").filter(Boolean)).catch((err) => {
407
- errors.push(err);
408
- return [];
409
- }),
410
- gitExec(["status", "--porcelain"], { cwd: wt }, isolation).then((s) => s.trim()).catch((err) => {
411
- errors.push(err);
412
- return "";
413
- })
414
- ]);
415
- if (errors.length === 3) {
416
- throw new Error(`Shared pages git error: ${errors[0].message}`);
417
- }
418
- const uncommittedFiles = /* @__PURE__ */ new Set();
419
- if (uncommitted) {
420
- for (const line of uncommitted.split("\n")) {
421
- const match = line.match(/^.{2}\s+(.+)$/);
422
- if (match) uncommittedFiles.add(match[1]);
423
- }
424
- }
425
- const mainSet = new Set(mainFiles.filter(isPageFile));
426
- const allPageFiles = /* @__PURE__ */ new Set([
427
- ...mainFiles.filter(isPageFile),
428
- ...branchFiles.filter(isPageFile),
429
- ...[...uncommittedFiles].filter(isPageFile)
430
- ]);
431
- if (allPageFiles.size === 0) return "No shared pages found.";
432
- const lines = [...allPageFiles].sort().map((file) => {
433
- const onMain = mainSet.has(file);
434
- const isUncommitted = uncommittedFiles.has(file);
435
- let status;
436
- if (isUncommitted) {
437
- status = "uncommitted";
438
- } else if (onMain) {
439
- status = "published";
440
- } else {
441
- status = "draft";
442
- }
443
- return `${status.padEnd(13)} ${file}`;
444
- });
445
- return lines.join("\n");
446
- }
447
- async function pagesLog(mindDir, limit = 20, isolation) {
448
- const wt = worktreePath(mindDir);
449
- const output = (await gitExec(["log", "--oneline", "main", `-${limit}`], { cwd: wt }, isolation)).trim();
450
- return output || "No history.";
451
- }
452
-
453
- // packages/extensions/pages/src/commands.ts
454
- function createCommands() {
455
- return {
456
- publish: {
457
- description: "Publish all pages (copy to public snapshot)",
458
- args: [{ name: "message", description: "Commit message for shared publish" }],
459
- flags: {
460
- remote: { type: "boolean", description: "Also publish to volute.systems" },
461
- shared: { type: "boolean", description: "Publish to shared pages repository" }
462
- },
463
- handler: async ({ args, flags }, ctx) => {
464
- const mindName = ctx.mindName;
465
- if (!mindName) return { error: "No mind specified (use --mind or VOLUTE_MIND)" };
466
- if (flags.shared) {
467
- const mindDir2 = await ctx.getMindDir(mindName);
468
- if (!mindDir2) return { error: `Mind not found: ${mindName}` };
469
- const message = args.message?.trim();
470
- if (!message)
471
- return { error: 'Usage: volute pages publish --shared "description of changes"' };
472
- try {
473
- const result = await pagesPullAndMerge(
474
- mindName,
475
- mindDir2,
476
- ctx.dataDir,
477
- message,
478
- isolationFrom(ctx)
479
- );
480
- if (!result.ok) {
481
- return {
482
- error: result.message || "Merge conflicts detected \u2014 pull, reconcile, and try again."
483
- };
484
- }
485
- let syncWarning = "";
486
- if (result.ok && ctx.db) {
487
- const repoDir = resolve3(ctx.dataDir, "repo");
488
- try {
489
- syncSystemPages(ctx.db, hashFiles(repoDir, collectPageFiles(repoDir)), mindName);
490
- } catch (err) {
491
- console.error("[pages] failed to sync system pages to DB:", err);
492
- syncWarning = "\nWarning: failed to sync pages to dashboard \u2014 they may not appear in the UI until the next daemon restart.";
493
- }
494
- }
495
- const files = result.changedFiles ?? [];
496
- if (files.length > 0) {
497
- const fileList = files.join(", ");
498
- const pageFile = files.find(isPageFile);
499
- ctx.publishActivity({
500
- type: "page_published",
501
- mind: mindName,
502
- summary: `${mindName} tended the commons: ${fileList}`,
503
- metadata: {
504
- shared: true,
505
- files,
506
- message,
507
- ...pageFile ? { iframeUrl: `/ext/pages/public/_system/${pageFile}` } : {}
508
- }
509
- });
510
- try {
511
- await ctx.announceToSystem(
512
- `${mindName} tended the commons: ${fileList} \u2014 "${message}"`
513
- );
514
- const authorFiles = /* @__PURE__ */ new Map();
515
- for (const [file, authors] of Object.entries(result.priorAuthors ?? {})) {
516
- for (const a of authors)
517
- authorFiles.set(a, [...authorFiles.get(a) ?? [], file]);
518
- }
519
- for (const [author, theirs] of authorFiles) {
520
- await ctx.recordNotice(
521
- author,
522
- `${mindName} built on ${theirs.join(", ")} in the commons \u2014 ${theirs.length > 1 ? "pages" : "a page"} you helped write ("${message}"). \`volute pages log\` shows the trail.`
523
- );
524
- }
525
- } catch (err) {
526
- console.warn(
527
- `[pages] shared publish notification failed: ${err.message}`
528
- );
529
- }
530
- }
531
- return { output: (result.message || "Published shared pages.") + syncWarning };
532
- } catch (err) {
533
- return { error: `Shared publish failed: ${err.message}` };
534
- }
535
- }
536
- const remote = flags.remote;
537
- const mindDir = await ctx.getMindDir(mindName);
538
- if (!mindDir) return { error: `Mind not found: ${mindName}` };
539
- const sourceDir = resolve3(mindDir, "home", "pages");
540
- if (!existsSync3(sourceDir)) return { error: "No pages directory found (home/pages/)" };
541
- const db = ctx.db;
542
- if (!db) return { error: "Database not available" };
543
- const snapshotDir = resolve3(ctx.dataDir, "sites", mindName);
544
- try {
545
- if (existsSync3(snapshotDir)) rmSync2(snapshotDir, { recursive: true });
546
- cpSync(sourceDir, snapshotDir, {
547
- recursive: true,
548
- filter: (src) => !src.endsWith("/_system") && !src.includes("/_system/")
549
- });
550
- } catch (err) {
551
- return { error: `Failed to publish snapshot: ${err.message}` };
552
- }
553
- const pageFiles = collectFiles(snapshotDir, snapshotDir, [".html", ".md"]);
554
- let diff;
555
- try {
556
- diff = syncPublishedPages(db, mindName, hashFiles(snapshotDir, pageFiles));
557
- } catch (err) {
558
- return { error: `Failed to update page database: ${err.message}` };
559
- }
560
- for (const file of diff.added) {
561
- ctx.publishActivity({
562
- type: "page_published",
563
- mind: mindName,
564
- summary: `${mindName} published ${file}`,
565
- metadata: {
566
- file,
567
- url: `/minds/${mindName}/pages/${file}`,
568
- iframeUrl: `/ext/pages/public/${mindName}/${file}`
569
- }
570
- });
571
- }
572
- for (const file of diff.removed) {
573
- ctx.publishActivity({
574
- type: "page_removed",
575
- mind: mindName,
576
- summary: `${mindName} removed ${file}`,
577
- metadata: { file }
578
- });
579
- }
580
- let output = `Published ${pageFiles.length} files`;
581
- const parts = [];
582
- if (diff.added.length > 0) parts.push(`${diff.added.length} new`);
583
- if (diff.updated.length > 0) parts.push(`${diff.updated.length} updated`);
584
- if (diff.removed.length > 0) parts.push(`${diff.removed.length} removed`);
585
- if (parts.length > 0) output += ` (${parts.join(", ")})`;
586
- if (remote) {
587
- const config = ctx.getSystemsConfig();
588
- if (!config)
589
- return {
590
- error: "Not connected to volute.systems. Run volute systems register or login first."
591
- };
592
- const allFiles = collectFiles(snapshotDir, snapshotDir);
593
- const files = {};
594
- for (const f of allFiles) {
595
- const fp = resolve3(snapshotDir, f);
596
- files[f] = readFileSync3(fp).toString("base64");
597
- }
598
- try {
599
- const res = await fetch(`${config.apiUrl}/api/pages/publish/${mindName}`, {
600
- method: "PUT",
601
- headers: {
602
- "Content-Type": "application/json",
603
- Authorization: `Bearer ${config.apiKey}`
604
- },
605
- body: JSON.stringify({ files })
606
- });
607
- const data = await res.json().catch(() => ({}));
608
- if (!res.ok) {
609
- const errMsg = data.error || `HTTP ${res.status}`;
610
- output += `
611
- Warning: remote publish failed: ${errMsg}`;
612
- } else if (data.url) {
613
- output += `
614
- Remote: ${data.url}`;
615
- }
616
- } catch (err) {
617
- output += `
618
- Warning: remote publish failed: ${err.message}`;
619
- }
620
- }
621
- return { output };
622
- }
623
- },
624
- list: {
625
- description: "List pages with publish status",
626
- flags: {
627
- all: { type: "boolean", description: "Show pages from all minds" },
628
- shared: { type: "boolean", description: "Show shared pages status" }
629
- },
630
- handler: async ({ flags }, ctx) => {
631
- const db = ctx.db;
632
- if (!db) return { error: "Database not available" };
633
- const allFlag = flags.all;
634
- const port = process.env.VOLUTE_DAEMON_PORT || "1618";
635
- if (allFlag) {
636
- const { getAllSites: getAllSites2, getSystemPages: getSystemPages2 } = await import("./db-I4EH5SLF.js");
637
- const sites = getAllSites2(db);
638
- const system = getSystemPages2(db);
639
- const lines2 = [];
640
- if (system) {
641
- for (const f of system.files) {
642
- const url = `http://localhost:${port}/ext/pages/public/_system/${f.file}`;
643
- const author = f.author ? ` (${f.author})` : "";
644
- lines2.push(`_system${author.padStart(10)} ${f.file.padEnd(25)} ${url}`);
645
- }
646
- }
647
- for (const site of sites) {
648
- for (const f of site.files) {
649
- const url = `http://localhost:${port}/ext/pages/public/${site.mind}/${f.file}`;
650
- lines2.push(`${site.mind.padEnd(15)} ${f.file.padEnd(25)} ${url}`);
651
- }
652
- }
653
- return { output: lines2.length > 0 ? lines2.join("\n") : "No published pages found." };
654
- }
655
- const mindName = ctx.mindName;
656
- if (!mindName) return { error: "No mind specified (use --mind or VOLUTE_MIND)" };
657
- if (flags.shared) {
658
- const mindDir2 = await ctx.getMindDir(mindName);
659
- if (!mindDir2) return { error: `Mind not found: ${mindName}` };
660
- try {
661
- const status = await pagesStatus(mindDir2, isolationFrom(ctx));
662
- return { output: status };
663
- } catch (err) {
664
- return { error: `Failed to check shared status: ${err.message}` };
665
- }
666
- }
667
- const mindDir = await ctx.getMindDir(mindName);
668
- if (!mindDir) return { error: `Mind not found: ${mindName}` };
669
- const sourceDir = resolve3(mindDir, "home", "pages");
670
- const published = new Set(getPublishedPages(db, mindName).map((p) => p.file));
671
- const draftFiles = existsSync3(sourceDir) ? collectFiles(sourceDir, sourceDir, [".html", ".md"]) : [];
672
- const allFiles = /* @__PURE__ */ new Set([...published, ...draftFiles]);
673
- if (allFiles.size === 0) return { output: "No pages found." };
674
- const lines = [...allFiles].sort().map((file) => {
675
- const isPublished = published.has(file);
676
- const status = isPublished ? "published" : "draft";
677
- const url = isPublished ? `http://localhost:${port}/ext/pages/public/${mindName}/${file}` : "";
678
- return `${status.padEnd(11)} ${file.padEnd(25)} ${url}`;
679
- });
680
- return { output: lines.join("\n") };
681
- }
682
- },
683
- pull: {
684
- description: "Pull latest shared page changes from other minds",
685
- handler: async (_parsed, ctx) => {
686
- const mindName = ctx.mindName;
687
- if (!mindName) return { error: "No mind specified (use --mind or VOLUTE_MIND)" };
688
- const mindDir = await ctx.getMindDir(mindName);
689
- if (!mindDir) return { error: `Mind not found: ${mindName}` };
690
- try {
691
- const result = await pagesPull(mindName, mindDir, isolationFrom(ctx));
692
- if (!result.ok) {
693
- return { error: result.message || "Pull failed." };
694
- }
695
- return { output: result.message || "Pulled latest shared changes." };
696
- } catch (err) {
697
- return { error: `Pull failed: ${err.message}` };
698
- }
699
- }
700
- },
701
- log: {
702
- description: "View shared pages commit history",
703
- flags: {
704
- limit: { type: "number", description: "Max number of entries to show (default: 20)" }
705
- },
706
- handler: async ({ flags }, ctx) => {
707
- const mindName = ctx.mindName;
708
- if (!mindName) return { error: "No mind specified (use --mind or VOLUTE_MIND)" };
709
- const mindDir = await ctx.getMindDir(mindName);
710
- if (!mindDir) return { error: `Mind not found: ${mindName}` };
711
- const limit = flags.limit ?? 20;
712
- try {
713
- const output = await pagesLog(mindDir, limit, isolationFrom(ctx));
714
- return { output };
715
- } catch (err) {
716
- return { error: `Failed to read shared log: ${err.message}` };
717
- }
718
- }
719
- },
720
- commons: {
721
- description: "Curation report for the commons: index, orphaned pages, unrepresented minds",
722
- handler: async (_parsed, ctx) => {
723
- const db = ctx.db;
724
- if (!db) return { error: "Database not available" };
725
- const repoDir = resolve3(ctx.dataDir, "repo");
726
- const files = collectPageFiles(repoDir);
727
- const report = commonsReport(repoDir, files, getMindsWithSites(db));
728
- const lines = [];
729
- if (!report.hasIndex) {
730
- lines.push("The commons has no index page yet (index.md or index.html).");
731
- } else {
732
- lines.push(`Index: ok (${files.length} pages in the commons)`);
733
- }
734
- lines.push(
735
- report.orphanPages.length > 0 ? `Orphaned pages (not reachable from the index): ${report.orphanPages.join(", ")}` : "Orphaned pages: none"
736
- );
737
- lines.push(
738
- report.unlinkedMinds.length > 0 ? `Minds with sites not linked from the commons: ${report.unlinkedMinds.join(", ")}` : "Resident sites: all linked"
739
- );
740
- return { output: lines.join("\n") };
741
- }
742
- }
743
- };
744
- }
745
- function collectFiles(dir, baseDir, ext) {
746
- const files = [];
747
- let items;
748
- try {
749
- items = readdirSync2(dir);
750
- } catch (err) {
751
- console.error(`[pages] failed to read directory ${dir}: ${err.message}`);
752
- return files;
753
- }
754
- for (const item of items) {
755
- if (item.startsWith(".")) continue;
756
- const fullPath = resolve3(dir, item);
757
- try {
758
- const s = statSync2(fullPath);
759
- const matchesExt = !ext || (Array.isArray(ext) ? ext.some((e) => item.endsWith(e)) : item.endsWith(ext));
760
- if (s.isFile() && matchesExt) {
761
- files.push(relative2(baseDir, fullPath));
762
- } else if (s.isDirectory()) {
763
- files.push(...collectFiles(fullPath, baseDir, ext));
764
- }
765
- } catch (err) {
766
- console.error(`[pages] failed to stat ${fullPath}: ${err.message}`);
767
- }
768
- }
769
- return files.sort();
770
- }
771
-
772
- // packages/extensions/pages/src/routes.ts
773
- import { readFile, stat } from "fs/promises";
774
- import { extname, resolve as resolve5 } from "path";
775
- import { Hono } from "hono";
776
-
777
- // packages/extensions/pages/src/cache.ts
778
- function mapFiles(mind, files) {
779
- return files.map((f) => ({
780
- file: f.file,
781
- modified: f.updated_at,
782
- url: `/ext/pages/public/${mind}/${f.file}`,
783
- author: f.author
784
- }));
785
- }
786
- function getSites(db) {
787
- const sites = getAllSites(db).map((site) => ({
788
- name: site.mind,
789
- label: site.mind,
790
- pages: mapFiles(site.mind, site.files)
791
- }));
792
- const system = getSystemPages(db);
793
- const systemSite = system ? { name: "_system", label: "Shared Pages", pages: mapFiles("_system", system.files) } : null;
794
- return { sites, systemSite };
795
- }
796
- function getRecentPagesList(db, opts) {
797
- const rows = getRecentPages(db, opts);
798
- return rows.map((r) => ({
799
- mind: r.mind,
800
- file: r.file,
801
- modified: r.updated_at,
802
- url: `/ext/pages/public/${r.mind}/${r.file}`,
803
- author: r.author
804
- }));
805
- }
806
-
807
- // packages/extensions/pages/src/markdown.ts
808
- import { existsSync as existsSync4 } from "fs";
809
- import { dirname, relative as relative3, resolve as resolve4 } from "path";
810
- import DOMPurify from "isomorphic-dompurify";
811
-
812
- // node_modules/marked/lib/marked.esm.js
813
- function M() {
814
- return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
815
- }
816
- var T = M();
817
- function N(l3) {
818
- T = l3;
819
- }
820
- var _ = { exec: () => null };
821
- function E(l3) {
822
- let e = [];
823
- return (t) => {
824
- let n = Math.max(0, Math.min(3, t - 1)), s = e[n];
825
- return s || (s = l3(n), e[n] = s), s;
826
- };
827
- }
828
- function d(l3, e = "") {
829
- let t = typeof l3 == "string" ? l3 : l3.source, n = { replace: (s, r) => {
830
- let i = typeof r == "string" ? r : r.source;
831
- return i = i.replace(m.caret, "$1"), t = t.replace(s, i), n;
832
- }, getRegex: () => new RegExp(t, e) };
833
- return n;
834
- }
835
- var Te = ((l3 = "") => {
836
- try {
837
- return !!new RegExp("(?<=1)(?<!1)" + l3);
838
- } catch {
839
- return false;
840
- }
841
- })();
842
- var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] +\S/, listReplaceTask: /^\[[ xX]\] +/, listTaskCheckbox: /\[[ xX]\]/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^<a /i, endATag: /^<\/a>/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^</, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (l3) => new RegExp(`^( {0,3}${l3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: E((l3) => new RegExp(`^ {0,${l3}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)), hrRegex: E((l3) => new RegExp(`^ {0,${l3}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`)), fencesBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}(?:\`\`\`|~~~)`)), headingBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}#`)), htmlBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}<(?:[a-z].*>|!--)`, "i")), blockquoteBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}>`)) };
843
- var Oe = /^(?:[ \t]*(?:\n|$))+/;
844
- var we = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
845
- var ye = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
846
- var B = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
847
- var Pe = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
848
- var j = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
849
- var oe = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
850
- var ae = d(oe).replace(/bull/g, j).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
851
- var Se = d(oe).replace(/bull/g, j).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
852
- var F = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
853
- var $e = /^[^\n]+/;
854
- var U = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
855
- var Le = d(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", U).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
856
- var _e = d(/^(bull)([ \t][^\n]*?)?(?:\n|$)/).replace(/bull/g, j).getRegex();
857
- var H = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
858
- var K = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
859
- var ze = d("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>[^\\n]*\\n+|$)|<![A-Z][\\s\\S]*?(?:>[^\\n]*\\n+|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>[^\\n]*\\n+|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", K).replace("tag", H).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
860
- var le = (l3) => d(F).replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", l3).replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex();
861
- var Me = le(/ {0,3}(?:[*+-]|1[.)])[ \t]+[^ \t\n]/);
862
- var Ee = le(/ {0,3}(?:[*+-]|\d{1,9}[.)])[ \t]+[^ \t\n]/);
863
- var Ie = d(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", Ee).getRegex();
864
- var W = { blockquote: Ie, code: we, def: Le, fences: ye, heading: Pe, hr: B, html: ze, lheading: ae, list: _e, newline: Oe, paragraph: Me, table: _, text: $e };
865
- var se = d("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex();
866
- var Ae = { ...W, lheading: Se, table: se, paragraph: d(F).replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex() };
867
- var Ce = { ...W, html: d(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", K).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: _, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: d(F).replace("hr", B).replace("heading", ` *#{1,6} *[^
868
- ]`).replace("lheading", ae).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
869
- var Be = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
870
- var qe = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
871
- var ue = /^( {2,}|\\)\n(?!\s*$)/;
872
- var De = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
873
- var I = /[\p{P}\p{S}]/u;
874
- var Z = /[\s\p{P}\p{S}]/u;
875
- var X = /[^\s\p{P}\p{S}]/u;
876
- var ve = d(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, Z).getRegex();
877
- var pe = /(?!~)[\p{P}\p{S}]/u;
878
- var He = /(?!~)[\s\p{P}\p{S}]/u;
879
- var Ze = /(?:[^\s\p{P}\p{S}]|~)/u;
880
- var Ge = d(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", Te ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
881
- var ce = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
882
- var Ne = d(ce, "u").replace(/punct/g, I).getRegex();
883
- var Qe = d(ce, "u").replace(/punct/g, pe).getRegex();
884
- var he = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
885
- var je = d(he, "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
886
- var Fe = d(he, "gu").replace(/notPunctSpace/g, Ze).replace(/punctSpace/g, He).replace(/punct/g, pe).getRegex();
887
- var Ue = d("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
888
- var Ke = d(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, I).getRegex();
889
- var We = "^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)";
890
- var Xe = d(We, "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
891
- var Je = d(/\\(punct)/, "gu").replace(/punct/g, I).getRegex();
892
- var Ve = d(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
893
- var Ye = d(K).replace("(?:-->|$)", "-->").getRegex();
894
- var et = d("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", Ye).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
895
- var v = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/;
896
- var tt = d(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", v).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]+|(?=\))/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
897
- var ke = d(/^!?\[(label)\]\[(ref)\]/).replace("label", v).replace("ref", U).getRegex();
898
- var de = d(/^!?\[(ref)\](?:\[\])?/).replace("ref", U).getRegex();
899
- var nt = d("reflink|nolink(?!\\()", "g").replace("reflink", ke).replace("nolink", de).getRegex();
900
- var ie = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
901
- var J = { _backpedal: _, anyPunctuation: Je, autolink: Ve, blockSkip: Ge, br: ue, code: qe, del: _, delLDelim: _, delRDelim: _, emStrongLDelim: Ne, emStrongRDelimAst: je, emStrongRDelimUnd: Ue, escape: Be, link: tt, nolink: de, punctuation: ve, reflink: ke, reflinkSearch: nt, tag: et, text: De, url: _ };
902
- var rt = { ...J, link: d(/^!?\[(label)\]\((.*?)\)/).replace("label", v).getRegex(), reflink: d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", v).getRegex() };
903
- var Q = { ...J, emStrongRDelimAst: Fe, emStrongLDelim: Qe, delLDelim: Ke, delRDelim: Xe, url: d(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", ie).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: d(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", ie).getRegex() };
904
- var st = { ...Q, br: d(ue).replace("{2,}", "*").getRegex(), text: d(Q.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
905
- var q = { normal: W, gfm: Ae, pedantic: Ce };
906
- var A = { normal: J, gfm: Q, breaks: st, pedantic: rt };
907
- var it = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
908
- var ge = (l3) => it[l3];
909
- function O(l3, e) {
910
- if (e) {
911
- if (m.escapeTest.test(l3)) return l3.replace(m.escapeReplace, ge);
912
- } else if (m.escapeTestNoEncode.test(l3)) return l3.replace(m.escapeReplaceNoEncode, ge);
913
- return l3;
914
- }
915
- function V(l3) {
916
- try {
917
- l3 = encodeURI(l3).replace(m.percentDecode, "%");
918
- } catch {
919
- return null;
920
- }
921
- return l3;
922
- }
923
- function Y(l3, e) {
924
- let t = l3.replace(m.findPipe, (r, i, o) => {
925
- let u = false, a = i;
926
- for (; --a >= 0 && o[a] === "\\"; ) u = !u;
927
- return u ? "|" : " |";
928
- }), n = t.split(m.splitPipe), s = 0;
929
- if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
930
- else for (; n.length < e; ) n.push("");
931
- for (; s < n.length; s++) n[s] = n[s].trim().replace(m.slashPipe, "|");
932
- return n;
933
- }
934
- function $(l3, e, t) {
935
- let n = l3.length;
936
- if (n === 0) return "";
937
- let s = 0;
938
- for (; s < n; ) {
939
- let r = l3.charAt(n - s - 1);
940
- if (r === e && !t) s++;
941
- else if (r !== e && t) s++;
942
- else break;
943
- }
944
- return l3.slice(0, n - s);
945
- }
946
- function ee(l3) {
947
- let e = l3.split(`
948
- `), t = e.length - 1;
949
- for (; t >= 0 && m.blankLine.test(e[t]); ) t--;
950
- return e.length - t <= 2 ? l3 : e.slice(0, t + 1).join(`
951
- `);
952
- }
953
- function fe(l3, e) {
954
- if (l3.indexOf(e[1]) === -1) return -1;
955
- let t = 0;
956
- for (let n = 0; n < l3.length; n++) if (l3[n] === "\\") n++;
957
- else if (l3[n] === e[0]) t++;
958
- else if (l3[n] === e[1] && (t--, t < 0)) return n;
959
- return t > 0 ? -2 : -1;
960
- }
961
- function me(l3, e = 0) {
962
- let t = e, n = "";
963
- for (let s of l3) if (s === " ") {
964
- let r = 4 - t % 4;
965
- n += " ".repeat(r), t += r;
966
- } else n += s, t++;
967
- return n;
968
- }
969
- function xe(l3, e, t, n, s) {
970
- let r = e.href, i = e.title || null, o = l3[1].replace(s.other.outputLinkReplace, "$1");
971
- n.state.inLink = true;
972
- let u = { type: l3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: r, title: i, text: o, tokens: n.inlineTokens(o) };
973
- return n.state.inLink = false, u;
974
- }
975
- function ot(l3, e, t) {
976
- let n = l3.match(t.other.indentCodeCompensation);
977
- if (n === null) return e;
978
- let s = n[1];
979
- return e.split(`
980
- `).map((r) => {
981
- let i = r.match(t.other.beginningSpace);
982
- if (i === null) return r;
983
- let [o] = i;
984
- return o.length >= s.length ? r.slice(s.length) : r;
985
- }).join(`
986
- `);
987
- }
988
- var w = class {
989
- options;
990
- rules;
991
- lexer;
992
- constructor(e) {
993
- this.options = e || T;
994
- }
995
- space(e) {
996
- let t = this.rules.block.newline.exec(e);
997
- if (t && t[0].length > 0) return { type: "space", raw: t[0] };
998
- }
999
- code(e) {
1000
- let t = this.rules.block.code.exec(e);
1001
- if (t) {
1002
- let n = this.options.pedantic ? t[0] : ee(t[0]), s = n.replace(this.rules.other.codeRemoveIndent, "");
1003
- return { type: "code", raw: n, codeBlockStyle: "indented", text: s };
1004
- }
1005
- }
1006
- fences(e) {
1007
- let t = this.rules.block.fences.exec(e);
1008
- if (t) {
1009
- let n = t[0], s = ot(n, t[3] || "", this.rules);
1010
- return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: s };
1011
- }
1012
- }
1013
- heading(e) {
1014
- let t = this.rules.block.heading.exec(e);
1015
- if (t) {
1016
- let n = t[2].trim();
1017
- if (this.rules.other.endingHash.test(n)) {
1018
- let s = $(n, "#");
1019
- (this.options.pedantic || !s || this.rules.other.endingSpaceChar.test(s)) && (n = s.trim());
1020
- }
1021
- return { type: "heading", raw: $(t[0], `
1022
- `), depth: t[1].length, text: n, tokens: this.lexer.inline(n) };
1023
- }
1024
- }
1025
- hr(e) {
1026
- let t = this.rules.block.hr.exec(e);
1027
- if (t) return { type: "hr", raw: $(t[0], `
1028
- `) };
1029
- }
1030
- blockquote(e) {
1031
- let t = this.rules.block.blockquote.exec(e);
1032
- if (t) {
1033
- let n = $(t[0], `
1034
- `).split(`
1035
- `), s = "", r = "", i = [];
1036
- for (; n.length > 0; ) {
1037
- let o = false, u = [], a;
1038
- for (a = 0; a < n.length; a++) if (this.rules.other.blockquoteStart.test(n[a])) u.push(n[a]), o = true;
1039
- else if (!o) u.push(n[a]);
1040
- else break;
1041
- n = n.slice(a);
1042
- let c = u.join(`
1043
- `), p = c.replace(this.rules.other.blockquoteSetextReplace, `
1044
- $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
1045
- s = s ? `${s}
1046
- ${c}` : c, r = r ? `${r}
1047
- ${p}` : p;
1048
- let k = this.lexer.state.top;
1049
- if (this.lexer.state.top = true, this.lexer.blockTokens(p, i, true), this.lexer.state.top = k, n.length === 0) break;
1050
- let h = i.at(-1);
1051
- if (h?.type === "code") break;
1052
- if (h?.type === "blockquote") {
1053
- let R = h, f = R.raw + `
1054
- ` + n.join(`
1055
- `), S = this.blockquote(f);
1056
- i[i.length - 1] = S, s = s.substring(0, s.length - R.raw.length) + S.raw, r = r.substring(0, r.length - R.text.length) + S.text;
1057
- break;
1058
- } else if (h?.type === "list") {
1059
- let R = h, f = R.raw + `
1060
- ` + n.join(`
1061
- `), S = this.list(f);
1062
- i[i.length - 1] = S, s = s.substring(0, s.length - h.raw.length) + S.raw, r = r.substring(0, r.length - R.raw.length) + S.raw, n = f.substring(i.at(-1).raw.length).split(`
1063
- `);
1064
- continue;
1065
- }
1066
- }
1067
- return { type: "blockquote", raw: s, tokens: i, text: r };
1068
- }
1069
- }
1070
- list(e) {
1071
- let t = this.rules.block.list.exec(e);
1072
- if (t) {
1073
- let n = t[1].trim(), s = n.length > 1, r = { type: "list", raw: "", ordered: s, start: s ? +n.slice(0, -1) : "", loose: false, items: [] };
1074
- n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]");
1075
- let i = this.rules.other.listItemRegex(n), o = false;
1076
- for (; e; ) {
1077
- let a = false, c = "", p = "";
1078
- if (!(t = i.exec(e)) || this.rules.block.hr.test(e)) break;
1079
- c = t[0], e = e.substring(c.length);
1080
- let k = me(t[2].split(`
1081
- `, 1)[0], t[1].length), h = e.split(`
1082
- `, 1)[0], R = !k.trim(), f = 0;
1083
- if (this.options.pedantic ? (f = 2, p = k.trimStart()) : R ? f = t[1].length + 1 : (f = k.search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, p = k.slice(f), f += t[1].length), R && this.rules.other.blankLine.test(h) && (c += h + `
1084
- `, e = e.substring(h.length + 1), a = true), !a) {
1085
- let S = this.rules.other.nextBulletRegex(f), te = this.rules.other.hrRegex(f), ne = this.rules.other.fencesBeginRegex(f), re = this.rules.other.headingBeginRegex(f), be = this.rules.other.htmlBeginRegex(f), Re = this.rules.other.blockquoteBeginRegex(f);
1086
- for (; e; ) {
1087
- let G = e.split(`
1088
- `, 1)[0], C;
1089
- if (h = G, this.options.pedantic ? (h = h.replace(this.rules.other.listReplaceNesting, " "), C = h) : C = h.replace(this.rules.other.tabCharGlobal, " "), ne.test(h) || re.test(h) || be.test(h) || Re.test(h) || S.test(h) || te.test(h)) break;
1090
- if (C.search(this.rules.other.nonSpaceChar) >= f || !h.trim()) p += `
1091
- ` + C.slice(f);
1092
- else {
1093
- if (R || k.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || ne.test(k) || re.test(k) || te.test(k)) break;
1094
- p += `
1095
- ` + h;
1096
- }
1097
- R = !h.trim(), c += G + `
1098
- `, e = e.substring(G.length + 1), k = C.slice(f);
1099
- }
1100
- }
1101
- r.loose || (o ? r.loose = true : this.rules.other.doubleBlankLine.test(c) && (o = true)), r.items.push({ type: "list_item", raw: c, task: !!this.options.gfm && this.rules.other.listIsTask.test(p), loose: false, text: p, tokens: [] }), r.raw += c;
1102
- }
1103
- let u = r.items.at(-1);
1104
- if (u) u.raw = u.raw.trimEnd(), u.text = u.text.trimEnd();
1105
- else return;
1106
- r.raw = r.raw.trimEnd();
1107
- for (let a of r.items) {
1108
- this.lexer.state.top = false, a.tokens = this.lexer.blockTokens(a.text, []);
1109
- let c = a.tokens[0];
1110
- if (a.task && (c?.type === "text" || c?.type === "paragraph")) {
1111
- a.text = a.text.replace(this.rules.other.listReplaceTask, ""), c.raw = c.raw.replace(this.rules.other.listReplaceTask, ""), c.text = c.text.replace(this.rules.other.listReplaceTask, "");
1112
- for (let k = this.lexer.inlineQueue.length - 1; k >= 0; k--) if (this.rules.other.listIsTask.test(this.lexer.inlineQueue[k].src)) {
1113
- this.lexer.inlineQueue[k].src = this.lexer.inlineQueue[k].src.replace(this.rules.other.listReplaceTask, "");
1114
- break;
1115
- }
1116
- let p = this.rules.other.listTaskCheckbox.exec(a.raw);
1117
- if (p) {
1118
- let k = { type: "checkbox", raw: p[0] + " ", checked: p[0] !== "[ ]" };
1119
- a.checked = k.checked, r.loose ? a.tokens[0] && ["paragraph", "text"].includes(a.tokens[0].type) && "tokens" in a.tokens[0] && a.tokens[0].tokens ? (a.tokens[0].raw = k.raw + a.tokens[0].raw, a.tokens[0].text = k.raw + a.tokens[0].text, a.tokens[0].tokens.unshift(k)) : a.tokens.unshift({ type: "paragraph", raw: k.raw, text: k.raw, tokens: [k] }) : a.tokens.unshift(k);
1120
- }
1121
- } else a.task && (a.task = false);
1122
- if (!r.loose) {
1123
- let p = a.tokens.filter((h) => h.type === "space"), k = p.length > 0 && p.some((h) => this.rules.other.anyLine.test(h.raw));
1124
- r.loose = k;
1125
- }
1126
- }
1127
- if (r.loose) for (let a of r.items) {
1128
- a.loose = true;
1129
- for (let c of a.tokens) c.type === "text" && (c.type = "paragraph");
1130
- }
1131
- return r;
1132
- }
1133
- }
1134
- html(e) {
1135
- let t = this.rules.block.html.exec(e);
1136
- if (t) {
1137
- let n = ee(t[0]);
1138
- return { type: "html", block: true, raw: n, pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: n };
1139
- }
1140
- }
1141
- def(e) {
1142
- let t = this.rules.block.def.exec(e);
1143
- if (t) {
1144
- let n = t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), s = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", r = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3];
1145
- return { type: "def", tag: n, raw: $(t[0], `
1146
- `), href: s, title: r };
1147
- }
1148
- }
1149
- table(e) {
1150
- let t = this.rules.block.table.exec(e);
1151
- if (!t || !this.rules.other.tableDelimiter.test(t[2])) return;
1152
- let n = Y(t[1]), s = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), r = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
1153
- `) : [], i = { type: "table", raw: $(t[0], `
1154
- `), header: [], align: [], rows: [] };
1155
- if (n.length === s.length) {
1156
- for (let o of s) this.rules.other.tableAlignRight.test(o) ? i.align.push("right") : this.rules.other.tableAlignCenter.test(o) ? i.align.push("center") : this.rules.other.tableAlignLeft.test(o) ? i.align.push("left") : i.align.push(null);
1157
- for (let o = 0; o < n.length; o++) i.header.push({ text: n[o], tokens: this.lexer.inline(n[o]), header: true, align: i.align[o] });
1158
- for (let o of r) i.rows.push(Y(o, i.header.length).map((u, a) => ({ text: u, tokens: this.lexer.inline(u), header: false, align: i.align[a] })));
1159
- return i;
1160
- }
1161
- }
1162
- lheading(e) {
1163
- let t = this.rules.block.lheading.exec(e);
1164
- if (t) {
1165
- let n = t[1].trim();
1166
- return { type: "heading", raw: $(t[0], `
1167
- `), depth: t[2].charAt(0) === "=" ? 1 : 2, text: n, tokens: this.lexer.inline(n) };
1168
- }
1169
- }
1170
- paragraph(e) {
1171
- let t = this.rules.block.paragraph.exec(e);
1172
- if (t) {
1173
- let n = t[1].charAt(t[1].length - 1) === `
1174
- ` ? t[1].slice(0, -1) : t[1];
1175
- return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) };
1176
- }
1177
- }
1178
- text(e) {
1179
- let t = this.rules.block.text.exec(e);
1180
- if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) };
1181
- }
1182
- escape(e) {
1183
- let t = this.rules.inline.escape.exec(e);
1184
- if (t) return { type: "escape", raw: t[0], text: t[1] };
1185
- }
1186
- tag(e) {
1187
- let t = this.rules.inline.tag.exec(e);
1188
- if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] };
1189
- }
1190
- link(e) {
1191
- let t = this.rules.inline.link.exec(e);
1192
- if (t) {
1193
- let n = t[2].trim();
1194
- if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) {
1195
- if (!this.rules.other.endAngleBracket.test(n)) return;
1196
- let i = $(n.slice(0, -1), "\\");
1197
- if ((n.length - i.length) % 2 === 0) return;
1198
- } else {
1199
- let i = fe(t[2], "()");
1200
- if (i === -2) return;
1201
- if (i > -1) {
1202
- let u = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + i;
1203
- t[2] = t[2].substring(0, i), t[0] = t[0].substring(0, u).trim(), t[3] = "";
1204
- }
1205
- }
1206
- let s = t[2], r = "";
1207
- if (this.options.pedantic) {
1208
- let i = this.rules.other.pedanticHrefTitle.exec(s);
1209
- i && (s = i[1], r = i[3]);
1210
- } else r = t[3] ? t[3].slice(1, -1) : "";
1211
- return s = s.trim(), this.rules.other.startAngleBracket.test(s) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n) ? s = s.slice(1) : s = s.slice(1, -1)), xe(t, { href: s && s.replace(this.rules.inline.anyPunctuation, "$1"), title: r && r.replace(this.rules.inline.anyPunctuation, "$1") }, t[0], this.lexer, this.rules);
1212
- }
1213
- }
1214
- reflink(e, t) {
1215
- let n;
1216
- if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) {
1217
- let s = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), r = t[s.toLowerCase()];
1218
- if (!r) {
1219
- let i = n[0].charAt(0);
1220
- return { type: "text", raw: i, text: i };
1221
- }
1222
- return xe(n, r, n[0], this.lexer, this.rules);
1223
- }
1224
- }
1225
- emStrong(e, t, n = "") {
1226
- let s = this.rules.inline.emStrongLDelim.exec(e);
1227
- if (!s || !s[1] && !s[2] && !s[3] && !s[4] || s[4] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
1228
- if (!(s[1] || s[3] || "") || !n || this.rules.inline.punctuation.exec(n)) {
1229
- let i = [...s[0]].length - 1, o, u, a = i, c = 0, p = s[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
1230
- for (p.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = p.exec(t)) !== null; ) {
1231
- if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) continue;
1232
- if (u = [...o].length, s[3] || s[4]) {
1233
- a += u;
1234
- continue;
1235
- } else if ((s[5] || s[6]) && i % 3 && !((i + u) % 3)) {
1236
- c += u;
1237
- continue;
1238
- }
1239
- if (a -= u, a > 0) continue;
1240
- u = Math.min(u, u + a + c);
1241
- let k = [...s[0]][0].length, h = e.slice(0, i + s.index + k + u);
1242
- if (Math.min(i, u) % 2) {
1243
- let f = h.slice(1, -1);
1244
- return { type: "em", raw: h, text: f, tokens: this.lexer.inlineTokens(f) };
1245
- }
1246
- let R = h.slice(2, -2);
1247
- return { type: "strong", raw: h, text: R, tokens: this.lexer.inlineTokens(R) };
1248
- }
1249
- }
1250
- }
1251
- codespan(e) {
1252
- let t = this.rules.inline.code.exec(e);
1253
- if (t) {
1254
- let n = t[2].replace(this.rules.other.newLineCharGlobal, " "), s = this.rules.other.nonSpaceChar.test(n), r = this.rules.other.startingSpaceChar.test(n) && this.rules.other.endingSpaceChar.test(n);
1255
- return s && r && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n };
1256
- }
1257
- }
1258
- br(e) {
1259
- let t = this.rules.inline.br.exec(e);
1260
- if (t) return { type: "br", raw: t[0] };
1261
- }
1262
- del(e, t, n = "") {
1263
- let s = this.rules.inline.delLDelim.exec(e);
1264
- if (!s) return;
1265
- if (!(s[1] || "") || !n || this.rules.inline.punctuation.exec(n)) {
1266
- let i = [...s[0]].length - 1, o, u, a = i, c = this.rules.inline.delRDelim;
1267
- for (c.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = c.exec(t)) !== null; ) {
1268
- if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o || (u = [...o].length, u !== i)) continue;
1269
- if (s[3] || s[4]) {
1270
- a += u;
1271
- continue;
1272
- }
1273
- if (a -= u, a > 0) continue;
1274
- u = Math.min(u, u + a);
1275
- let p = [...s[0]][0].length, k = e.slice(0, i + s.index + p + u), h = k.slice(i, -i);
1276
- return { type: "del", raw: k, text: h, tokens: this.lexer.inlineTokens(h) };
1277
- }
1278
- }
1279
- }
1280
- autolink(e) {
1281
- let t = this.rules.inline.autolink.exec(e);
1282
- if (t) {
1283
- let n, s;
1284
- return t[2] === "@" ? (n = t[1], s = "mailto:" + n) : (n = t[1], s = n), { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
1285
- }
1286
- }
1287
- url(e) {
1288
- let t;
1289
- if (t = this.rules.inline.url.exec(e)) {
1290
- let n, s;
1291
- if (t[2] === "@") n = t[0], s = "mailto:" + n;
1292
- else {
1293
- let r;
1294
- do
1295
- r = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? "";
1296
- while (r !== t[0]);
1297
- n = t[0], t[1] === "www." ? s = "http://" + t[0] : s = t[0];
1298
- }
1299
- return { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
1300
- }
1301
- }
1302
- inlineText(e) {
1303
- let t = this.rules.inline.text.exec(e);
1304
- if (t) {
1305
- let n = this.lexer.state.inRawBlock;
1306
- return { type: "text", raw: t[0], text: t[0], escaped: n };
1307
- }
1308
- }
1309
- };
1310
- var x = class l {
1311
- tokens;
1312
- options;
1313
- state;
1314
- inlineQueue;
1315
- tokenizer;
1316
- constructor(e) {
1317
- this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || T, this.options.tokenizer = this.options.tokenizer || new w(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, top: true };
1318
- let t = { other: m, block: q.normal, inline: A.normal };
1319
- this.options.pedantic ? (t.block = q.pedantic, t.inline = A.pedantic) : this.options.gfm && (t.block = q.gfm, this.options.breaks ? t.inline = A.breaks : t.inline = A.gfm), this.tokenizer.rules = t;
1320
- }
1321
- static get rules() {
1322
- return { block: q, inline: A };
1323
- }
1324
- static lex(e, t) {
1325
- return new l(t).lex(e);
1326
- }
1327
- static lexInline(e, t) {
1328
- return new l(t).inlineTokens(e);
1329
- }
1330
- lex(e) {
1331
- e = e.replace(m.carriageReturn, `
1332
- `), this.blockTokens(e, this.tokens);
1333
- for (let t = 0; t < this.inlineQueue.length; t++) {
1334
- let n = this.inlineQueue[t];
1335
- this.inlineTokens(n.src, n.tokens);
1336
- }
1337
- return this.inlineQueue = [], this.tokens;
1338
- }
1339
- blockTokens(e, t = [], n = false) {
1340
- this.tokenizer.lexer = this, this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, ""));
1341
- let s = 1 / 0;
1342
- for (; e; ) {
1343
- if (e.length < s) s = e.length;
1344
- else {
1345
- this.infiniteLoopError(e.charCodeAt(0));
1346
- break;
1347
- }
1348
- let r;
1349
- if (this.options.extensions?.block?.some((o) => (r = o.call({ lexer: this }, e, t)) ? (e = e.substring(r.raw.length), t.push(r), true) : false)) continue;
1350
- if (r = this.tokenizer.space(e)) {
1351
- e = e.substring(r.raw.length);
1352
- let o = t.at(-1);
1353
- r.raw.length === 1 && o !== void 0 ? o.raw += `
1354
- ` : t.push(r);
1355
- continue;
1356
- }
1357
- if (r = this.tokenizer.code(e)) {
1358
- e = e.substring(r.raw.length);
1359
- let o = t.at(-1);
1360
- o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
1361
- `) ? "" : `
1362
- `) + r.raw, o.text += `
1363
- ` + r.text, this.inlineQueue.at(-1).src = o.text) : t.push(r);
1364
- continue;
1365
- }
1366
- if (r = this.tokenizer.fences(e)) {
1367
- e = e.substring(r.raw.length), t.push(r);
1368
- continue;
1369
- }
1370
- if (r = this.tokenizer.heading(e)) {
1371
- e = e.substring(r.raw.length), t.push(r);
1372
- continue;
1373
- }
1374
- if (r = this.tokenizer.hr(e)) {
1375
- e = e.substring(r.raw.length), t.push(r);
1376
- continue;
1377
- }
1378
- if (r = this.tokenizer.blockquote(e)) {
1379
- e = e.substring(r.raw.length), t.push(r);
1380
- continue;
1381
- }
1382
- if (r = this.tokenizer.list(e)) {
1383
- e = e.substring(r.raw.length), t.push(r);
1384
- continue;
1385
- }
1386
- if (r = this.tokenizer.html(e)) {
1387
- e = e.substring(r.raw.length), t.push(r);
1388
- continue;
1389
- }
1390
- if (r = this.tokenizer.def(e)) {
1391
- e = e.substring(r.raw.length);
1392
- let o = t.at(-1);
1393
- o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
1394
- `) ? "" : `
1395
- `) + r.raw, o.text += `
1396
- ` + r.raw, this.inlineQueue.at(-1).src = o.text) : this.tokens.links[r.tag] || (this.tokens.links[r.tag] = { href: r.href, title: r.title }, t.push(r));
1397
- continue;
1398
- }
1399
- if (r = this.tokenizer.table(e)) {
1400
- e = e.substring(r.raw.length), t.push(r);
1401
- continue;
1402
- }
1403
- if (r = this.tokenizer.lheading(e)) {
1404
- e = e.substring(r.raw.length), t.push(r);
1405
- continue;
1406
- }
1407
- let i = e;
1408
- if (this.options.extensions?.startBlock) {
1409
- let o = 1 / 0, u = e.slice(1), a;
1410
- this.options.extensions.startBlock.forEach((c) => {
1411
- a = c.call({ lexer: this }, u), typeof a == "number" && a >= 0 && (o = Math.min(o, a));
1412
- }), o < 1 / 0 && o >= 0 && (i = e.substring(0, o + 1));
1413
- }
1414
- if (this.state.top && (r = this.tokenizer.paragraph(i))) {
1415
- let o = t.at(-1);
1416
- n && o?.type === "paragraph" ? (o.raw += (o.raw.endsWith(`
1417
- `) ? "" : `
1418
- `) + r.raw, o.text += `
1419
- ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r), n = i.length !== e.length, e = e.substring(r.raw.length);
1420
- continue;
1421
- }
1422
- if (r = this.tokenizer.text(e)) {
1423
- e = e.substring(r.raw.length);
1424
- let o = t.at(-1);
1425
- o?.type === "text" ? (o.raw += (o.raw.endsWith(`
1426
- `) ? "" : `
1427
- `) + r.raw, o.text += `
1428
- ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r);
1429
- continue;
1430
- }
1431
- if (e) {
1432
- this.infiniteLoopError(e.charCodeAt(0));
1433
- break;
1434
- }
1435
- }
1436
- return this.state.top = true, t;
1437
- }
1438
- inline(e, t = []) {
1439
- return this.inlineQueue.push({ src: e, tokens: t }), t;
1440
- }
1441
- inlineTokens(e, t = []) {
1442
- this.tokenizer.lexer = this;
1443
- let n = e, s = null;
1444
- if (this.tokens.links) {
1445
- let a = Object.keys(this.tokens.links);
1446
- if (a.length > 0) for (; (s = this.tokenizer.rules.inline.reflinkSearch.exec(n)) !== null; ) a.includes(s[0].slice(s[0].lastIndexOf("[") + 1, -1)) && (n = n.slice(0, s.index) + "[" + "a".repeat(s[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));
1447
- }
1448
- for (; (s = this.tokenizer.rules.inline.anyPunctuation.exec(n)) !== null; ) n = n.slice(0, s.index) + "++" + n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
1449
- let r;
1450
- for (; (s = this.tokenizer.rules.inline.blockSkip.exec(n)) !== null; ) r = s[2] ? s[2].length : 0, n = n.slice(0, s.index + r) + "[" + "a".repeat(s[0].length - r - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1451
- n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
1452
- let i = false, o = "", u = 1 / 0;
1453
- for (; e; ) {
1454
- if (e.length < u) u = e.length;
1455
- else {
1456
- this.infiniteLoopError(e.charCodeAt(0));
1457
- break;
1458
- }
1459
- i || (o = ""), i = false;
1460
- let a;
1461
- if (this.options.extensions?.inline?.some((p) => (a = p.call({ lexer: this }, e, t)) ? (e = e.substring(a.raw.length), t.push(a), true) : false)) continue;
1462
- if (a = this.tokenizer.escape(e)) {
1463
- e = e.substring(a.raw.length), t.push(a);
1464
- continue;
1465
- }
1466
- if (a = this.tokenizer.tag(e)) {
1467
- e = e.substring(a.raw.length), t.push(a);
1468
- continue;
1469
- }
1470
- if (a = this.tokenizer.link(e)) {
1471
- e = e.substring(a.raw.length), t.push(a);
1472
- continue;
1473
- }
1474
- if (a = this.tokenizer.reflink(e, this.tokens.links)) {
1475
- e = e.substring(a.raw.length);
1476
- let p = t.at(-1);
1477
- a.type === "text" && p?.type === "text" ? (p.raw += a.raw, p.text += a.text) : t.push(a);
1478
- continue;
1479
- }
1480
- if (a = this.tokenizer.emStrong(e, n, o)) {
1481
- e = e.substring(a.raw.length), t.push(a);
1482
- continue;
1483
- }
1484
- if (a = this.tokenizer.codespan(e)) {
1485
- e = e.substring(a.raw.length), t.push(a);
1486
- continue;
1487
- }
1488
- if (a = this.tokenizer.br(e)) {
1489
- e = e.substring(a.raw.length), t.push(a);
1490
- continue;
1491
- }
1492
- if (a = this.tokenizer.del(e, n, o)) {
1493
- e = e.substring(a.raw.length), t.push(a);
1494
- continue;
1495
- }
1496
- if (a = this.tokenizer.autolink(e)) {
1497
- e = e.substring(a.raw.length), t.push(a);
1498
- continue;
1499
- }
1500
- if (!this.state.inLink && (a = this.tokenizer.url(e))) {
1501
- e = e.substring(a.raw.length), t.push(a);
1502
- continue;
1503
- }
1504
- let c = e;
1505
- if (this.options.extensions?.startInline) {
1506
- let p = 1 / 0, k = e.slice(1), h;
1507
- this.options.extensions.startInline.forEach((R) => {
1508
- h = R.call({ lexer: this }, k), typeof h == "number" && h >= 0 && (p = Math.min(p, h));
1509
- }), p < 1 / 0 && p >= 0 && (c = e.substring(0, p + 1));
1510
- }
1511
- if (a = this.tokenizer.inlineText(c)) {
1512
- e = e.substring(a.raw.length), a.raw.slice(-1) !== "_" && (o = a.raw.slice(-1)), i = true;
1513
- let p = t.at(-1);
1514
- p?.type === "text" ? (p.raw += a.raw, p.text += a.text) : t.push(a);
1515
- continue;
1516
- }
1517
- if (e) {
1518
- this.infiniteLoopError(e.charCodeAt(0));
1519
- break;
1520
- }
1521
- }
1522
- return t;
1523
- }
1524
- infiniteLoopError(e) {
1525
- let t = "Infinite loop on byte: " + e;
1526
- if (this.options.silent) console.error(t);
1527
- else throw new Error(t);
1528
- }
1529
- };
1530
- var y = class {
1531
- options;
1532
- parser;
1533
- constructor(e) {
1534
- this.options = e || T;
1535
- }
1536
- space(e) {
1537
- return "";
1538
- }
1539
- code({ text: e, lang: t, escaped: n }) {
1540
- let s = (t || "").match(m.notSpaceStart)?.[0], r = e.replace(m.endingNewline, "") + `
1541
- `;
1542
- return s ? '<pre><code class="language-' + O(s) + '">' + (n ? r : O(r, true)) + `</code></pre>
1543
- ` : "<pre><code>" + (n ? r : O(r, true)) + `</code></pre>
1544
- `;
1545
- }
1546
- blockquote({ tokens: e }) {
1547
- return `<blockquote>
1548
- ${this.parser.parse(e)}</blockquote>
1549
- `;
1550
- }
1551
- html({ text: e }) {
1552
- return e;
1553
- }
1554
- def(e) {
1555
- return "";
1556
- }
1557
- heading({ tokens: e, depth: t }) {
1558
- return `<h${t}>${this.parser.parseInline(e)}</h${t}>
1559
- `;
1560
- }
1561
- hr(e) {
1562
- return `<hr>
1563
- `;
1564
- }
1565
- list(e) {
1566
- let t = e.ordered, n = e.start, s = "";
1567
- for (let o = 0; o < e.items.length; o++) {
1568
- let u = e.items[o];
1569
- s += this.listitem(u);
1570
- }
1571
- let r = t ? "ol" : "ul", i = t && n !== 1 ? ' start="' + n + '"' : "";
1572
- return "<" + r + i + `>
1573
- ` + s + "</" + r + `>
1574
- `;
1575
- }
1576
- listitem(e) {
1577
- return `<li>${this.parser.parse(e.tokens)}</li>
1578
- `;
1579
- }
1580
- checkbox({ checked: e }) {
1581
- return "<input " + (e ? 'checked="" ' : "") + 'disabled="" type="checkbox"> ';
1582
- }
1583
- paragraph({ tokens: e }) {
1584
- return `<p>${this.parser.parseInline(e)}</p>
1585
- `;
1586
- }
1587
- table(e) {
1588
- let t = "", n = "";
1589
- for (let r = 0; r < e.header.length; r++) n += this.tablecell(e.header[r]);
1590
- t += this.tablerow({ text: n });
1591
- let s = "";
1592
- for (let r = 0; r < e.rows.length; r++) {
1593
- let i = e.rows[r];
1594
- n = "";
1595
- for (let o = 0; o < i.length; o++) n += this.tablecell(i[o]);
1596
- s += this.tablerow({ text: n });
1597
- }
1598
- return s && (s = `<tbody>${s}</tbody>`), `<table>
1599
- <thead>
1600
- ` + t + `</thead>
1601
- ` + s + `</table>
1602
- `;
1603
- }
1604
- tablerow({ text: e }) {
1605
- return `<tr>
1606
- ${e}</tr>
1607
- `;
1608
- }
1609
- tablecell(e) {
1610
- let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td";
1611
- return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + `</${n}>
1612
- `;
1613
- }
1614
- strong({ tokens: e }) {
1615
- return `<strong>${this.parser.parseInline(e)}</strong>`;
1616
- }
1617
- em({ tokens: e }) {
1618
- return `<em>${this.parser.parseInline(e)}</em>`;
1619
- }
1620
- codespan({ text: e }) {
1621
- return `<code>${O(e, true)}</code>`;
1622
- }
1623
- br(e) {
1624
- return "<br>";
1625
- }
1626
- del({ tokens: e }) {
1627
- return `<del>${this.parser.parseInline(e)}</del>`;
1628
- }
1629
- link({ href: e, title: t, tokens: n }) {
1630
- let s = this.parser.parseInline(n), r = V(e);
1631
- if (r === null) return s;
1632
- e = r;
1633
- let i = '<a href="' + e + '"';
1634
- return t && (i += ' title="' + O(t) + '"'), i += ">" + s + "</a>", i;
1635
- }
1636
- image({ href: e, title: t, text: n, tokens: s }) {
1637
- s && (n = this.parser.parseInline(s, this.parser.textRenderer));
1638
- let r = V(e);
1639
- if (r === null) return O(n);
1640
- e = r;
1641
- let i = `<img src="${e}" alt="${O(n)}"`;
1642
- return t && (i += ` title="${O(t)}"`), i += ">", i;
1643
- }
1644
- text(e) {
1645
- return "tokens" in e && e.tokens ? this.parser.parseInline(e.tokens) : "escaped" in e && e.escaped ? e.text : O(e.text);
1646
- }
1647
- };
1648
- var L = class {
1649
- strong({ text: e }) {
1650
- return e;
1651
- }
1652
- em({ text: e }) {
1653
- return e;
1654
- }
1655
- codespan({ text: e }) {
1656
- return e;
1657
- }
1658
- del({ text: e }) {
1659
- return e;
1660
- }
1661
- html({ text: e }) {
1662
- return e;
1663
- }
1664
- text({ text: e }) {
1665
- return e;
1666
- }
1667
- link({ text: e }) {
1668
- return "" + e;
1669
- }
1670
- image({ text: e }) {
1671
- return "" + e;
1672
- }
1673
- br() {
1674
- return "";
1675
- }
1676
- checkbox({ raw: e }) {
1677
- return e;
1678
- }
1679
- };
1680
- var b = class l2 {
1681
- options;
1682
- renderer;
1683
- textRenderer;
1684
- constructor(e) {
1685
- this.options = e || T, this.options.renderer = this.options.renderer || new y(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new L();
1686
- }
1687
- static parse(e, t) {
1688
- return new l2(t).parse(e);
1689
- }
1690
- static parseInline(e, t) {
1691
- return new l2(t).parseInline(e);
1692
- }
1693
- parse(e) {
1694
- this.renderer.parser = this;
1695
- let t = "";
1696
- for (let n = 0; n < e.length; n++) {
1697
- let s = e[n];
1698
- if (this.options.extensions?.renderers?.[s.type]) {
1699
- let i = s, o = this.options.extensions.renderers[i.type].call({ parser: this }, i);
1700
- if (o !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "def", "paragraph", "text"].includes(i.type)) {
1701
- t += o || "";
1702
- continue;
1703
- }
1704
- }
1705
- let r = s;
1706
- switch (r.type) {
1707
- case "space": {
1708
- t += this.renderer.space(r);
1709
- break;
1710
- }
1711
- case "hr": {
1712
- t += this.renderer.hr(r);
1713
- break;
1714
- }
1715
- case "heading": {
1716
- t += this.renderer.heading(r);
1717
- break;
1718
- }
1719
- case "code": {
1720
- t += this.renderer.code(r);
1721
- break;
1722
- }
1723
- case "table": {
1724
- t += this.renderer.table(r);
1725
- break;
1726
- }
1727
- case "blockquote": {
1728
- t += this.renderer.blockquote(r);
1729
- break;
1730
- }
1731
- case "list": {
1732
- t += this.renderer.list(r);
1733
- break;
1734
- }
1735
- case "checkbox": {
1736
- t += this.renderer.checkbox(r);
1737
- break;
1738
- }
1739
- case "html": {
1740
- t += this.renderer.html(r);
1741
- break;
1742
- }
1743
- case "def": {
1744
- t += this.renderer.def(r);
1745
- break;
1746
- }
1747
- case "paragraph": {
1748
- t += this.renderer.paragraph(r);
1749
- break;
1750
- }
1751
- case "text": {
1752
- t += this.renderer.text(r);
1753
- break;
1754
- }
1755
- default: {
1756
- let i = 'Token with "' + r.type + '" type was not found.';
1757
- if (this.options.silent) return console.error(i), "";
1758
- throw new Error(i);
1759
- }
1760
- }
1761
- }
1762
- return t;
1763
- }
1764
- parseInline(e, t = this.renderer) {
1765
- this.renderer.parser = this;
1766
- let n = "";
1767
- for (let s = 0; s < e.length; s++) {
1768
- let r = e[s];
1769
- if (this.options.extensions?.renderers?.[r.type]) {
1770
- let o = this.options.extensions.renderers[r.type].call({ parser: this }, r);
1771
- if (o !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(r.type)) {
1772
- n += o || "";
1773
- continue;
1774
- }
1775
- }
1776
- let i = r;
1777
- switch (i.type) {
1778
- case "escape": {
1779
- n += t.text(i);
1780
- break;
1781
- }
1782
- case "html": {
1783
- n += t.html(i);
1784
- break;
1785
- }
1786
- case "link": {
1787
- n += t.link(i);
1788
- break;
1789
- }
1790
- case "image": {
1791
- n += t.image(i);
1792
- break;
1793
- }
1794
- case "checkbox": {
1795
- n += t.checkbox(i);
1796
- break;
1797
- }
1798
- case "strong": {
1799
- n += t.strong(i);
1800
- break;
1801
- }
1802
- case "em": {
1803
- n += t.em(i);
1804
- break;
1805
- }
1806
- case "codespan": {
1807
- n += t.codespan(i);
1808
- break;
1809
- }
1810
- case "br": {
1811
- n += t.br(i);
1812
- break;
1813
- }
1814
- case "del": {
1815
- n += t.del(i);
1816
- break;
1817
- }
1818
- case "text": {
1819
- n += t.text(i);
1820
- break;
1821
- }
1822
- default: {
1823
- let o = 'Token with "' + i.type + '" type was not found.';
1824
- if (this.options.silent) return console.error(o), "";
1825
- throw new Error(o);
1826
- }
1827
- }
1828
- }
1829
- return n;
1830
- }
1831
- };
1832
- var P = class {
1833
- options;
1834
- block;
1835
- constructor(e) {
1836
- this.options = e || T;
1837
- }
1838
- static passThroughHooks = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"]);
1839
- static passThroughHooksRespectAsync = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"]);
1840
- preprocess(e) {
1841
- return e;
1842
- }
1843
- postprocess(e) {
1844
- return e;
1845
- }
1846
- processAllTokens(e) {
1847
- return e;
1848
- }
1849
- emStrongMask(e) {
1850
- return e;
1851
- }
1852
- provideLexer(e = this.block) {
1853
- return e ? x.lex : x.lexInline;
1854
- }
1855
- provideParser(e = this.block) {
1856
- return e ? b.parse : b.parseInline;
1857
- }
1858
- };
1859
- var D = class {
1860
- defaults = M();
1861
- options = this.setOptions;
1862
- parse = this.parseMarkdown(true);
1863
- parseInline = this.parseMarkdown(false);
1864
- Parser = b;
1865
- Renderer = y;
1866
- TextRenderer = L;
1867
- Lexer = x;
1868
- Tokenizer = w;
1869
- Hooks = P;
1870
- constructor(...e) {
1871
- this.use(...e);
1872
- }
1873
- walkTokens(e, t) {
1874
- let n = [];
1875
- for (let s of e) switch (n = n.concat(t.call(this, s)), s.type) {
1876
- case "table": {
1877
- let r = s;
1878
- for (let i of r.header) n = n.concat(this.walkTokens(i.tokens, t));
1879
- for (let i of r.rows) for (let o of i) n = n.concat(this.walkTokens(o.tokens, t));
1880
- break;
1881
- }
1882
- case "list": {
1883
- let r = s;
1884
- n = n.concat(this.walkTokens(r.items, t));
1885
- break;
1886
- }
1887
- default: {
1888
- let r = s;
1889
- this.defaults.extensions?.childTokens?.[r.type] ? this.defaults.extensions.childTokens[r.type].forEach((i) => {
1890
- let o = r[i].flat(1 / 0);
1891
- n = n.concat(this.walkTokens(o, t));
1892
- }) : r.tokens && (n = n.concat(this.walkTokens(r.tokens, t)));
1893
- }
1894
- }
1895
- return n;
1896
- }
1897
- use(...e) {
1898
- let t = this.defaults.extensions || { renderers: {}, childTokens: {} };
1899
- return e.forEach((n) => {
1900
- let s = { ...n };
1901
- if (s.async = this.defaults.async || s.async || false, n.extensions && (n.extensions.forEach((r) => {
1902
- if (!r.name) throw new Error("extension name required");
1903
- if ("renderer" in r) {
1904
- let i = t.renderers[r.name];
1905
- i ? t.renderers[r.name] = function(...o) {
1906
- let u = r.renderer.apply(this, o);
1907
- return u === false && (u = i.apply(this, o)), u;
1908
- } : t.renderers[r.name] = r.renderer;
1909
- }
1910
- if ("tokenizer" in r) {
1911
- if (!r.level || r.level !== "block" && r.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
1912
- let i = t[r.level];
1913
- i ? i.unshift(r.tokenizer) : t[r.level] = [r.tokenizer], r.start && (r.level === "block" ? t.startBlock ? t.startBlock.push(r.start) : t.startBlock = [r.start] : r.level === "inline" && (t.startInline ? t.startInline.push(r.start) : t.startInline = [r.start]));
1914
- }
1915
- "childTokens" in r && r.childTokens && (t.childTokens[r.name] = r.childTokens);
1916
- }), s.extensions = t), n.renderer) {
1917
- let r = this.defaults.renderer || new y(this.defaults);
1918
- for (let i in n.renderer) {
1919
- if (!(i in r)) throw new Error(`renderer '${i}' does not exist`);
1920
- if (["options", "parser"].includes(i)) continue;
1921
- let o = i, u = n.renderer[o], a = r[o];
1922
- r[o] = (...c) => {
1923
- let p = u.apply(r, c);
1924
- return p === false && (p = a.apply(r, c)), p || "";
1925
- };
1926
- }
1927
- s.renderer = r;
1928
- }
1929
- if (n.tokenizer) {
1930
- let r = this.defaults.tokenizer || new w(this.defaults);
1931
- for (let i in n.tokenizer) {
1932
- if (!(i in r)) throw new Error(`tokenizer '${i}' does not exist`);
1933
- if (["options", "rules", "lexer"].includes(i)) continue;
1934
- let o = i, u = n.tokenizer[o], a = r[o];
1935
- r[o] = (...c) => {
1936
- let p = u.apply(r, c);
1937
- return p === false && (p = a.apply(r, c)), p;
1938
- };
1939
- }
1940
- s.tokenizer = r;
1941
- }
1942
- if (n.hooks) {
1943
- let r = this.defaults.hooks || new P();
1944
- for (let i in n.hooks) {
1945
- if (!(i in r)) throw new Error(`hook '${i}' does not exist`);
1946
- if (["options", "block"].includes(i)) continue;
1947
- let o = i, u = n.hooks[o], a = r[o];
1948
- P.passThroughHooks.has(i) ? r[o] = (c) => {
1949
- if (this.defaults.async && P.passThroughHooksRespectAsync.has(i)) return (async () => {
1950
- let k = await u.call(r, c);
1951
- return a.call(r, k);
1952
- })();
1953
- let p = u.call(r, c);
1954
- return a.call(r, p);
1955
- } : r[o] = (...c) => {
1956
- if (this.defaults.async) return (async () => {
1957
- let k = await u.apply(r, c);
1958
- return k === false && (k = await a.apply(r, c)), k;
1959
- })();
1960
- let p = u.apply(r, c);
1961
- return p === false && (p = a.apply(r, c)), p;
1962
- };
1963
- }
1964
- s.hooks = r;
1965
- }
1966
- if (n.walkTokens) {
1967
- let r = this.defaults.walkTokens, i = n.walkTokens;
1968
- s.walkTokens = function(o) {
1969
- let u = [];
1970
- return u.push(i.call(this, o)), r && (u = u.concat(r.call(this, o))), u;
1971
- };
1972
- }
1973
- this.defaults = { ...this.defaults, ...s };
1974
- }), this;
1975
- }
1976
- setOptions(e) {
1977
- return this.defaults = { ...this.defaults, ...e }, this;
1978
- }
1979
- lexer(e, t) {
1980
- return x.lex(e, t ?? this.defaults);
1981
- }
1982
- parser(e, t) {
1983
- return b.parse(e, t ?? this.defaults);
1984
- }
1985
- parseMarkdown(e) {
1986
- return (n, s) => {
1987
- let r = { ...s }, i = { ...this.defaults, ...r }, o = this.onError(!!i.silent, !!i.async);
1988
- if (this.defaults.async === true && r.async === false) return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
1989
- if (typeof n > "u" || n === null) return o(new Error("marked(): input parameter is undefined or null"));
1990
- if (typeof n != "string") return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
1991
- if (i.hooks && (i.hooks.options = i, i.hooks.block = e), i.async) return (async () => {
1992
- let u = i.hooks ? await i.hooks.preprocess(n) : n, c = await (i.hooks ? await i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(u, i), p = i.hooks ? await i.hooks.processAllTokens(c) : c;
1993
- i.walkTokens && await Promise.all(this.walkTokens(p, i.walkTokens));
1994
- let h = await (i.hooks ? await i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(p, i);
1995
- return i.hooks ? await i.hooks.postprocess(h) : h;
1996
- })().catch(o);
1997
- try {
1998
- i.hooks && (n = i.hooks.preprocess(n));
1999
- let a = (i.hooks ? i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(n, i);
2000
- i.hooks && (a = i.hooks.processAllTokens(a)), i.walkTokens && this.walkTokens(a, i.walkTokens);
2001
- let p = (i.hooks ? i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(a, i);
2002
- return i.hooks && (p = i.hooks.postprocess(p)), p;
2003
- } catch (u) {
2004
- return o(u);
2005
- }
2006
- };
2007
- }
2008
- onError(e, t) {
2009
- return (n) => {
2010
- if (n.message += `
2011
- Please report this to https://github.com/markedjs/marked.`, e) {
2012
- let s = "<p>An error occurred:</p><pre>" + O(n.message + "", true) + "</pre>";
2013
- return t ? Promise.resolve(s) : s;
2014
- }
2015
- if (t) return Promise.reject(n);
2016
- throw n;
2017
- };
2018
- }
2019
- };
2020
- var z = new D();
2021
- function g(l3, e) {
2022
- return z.parse(l3, e);
2023
- }
2024
- g.options = g.setOptions = function(l3) {
2025
- return z.setOptions(l3), g.defaults = z.defaults, N(g.defaults), g;
2026
- };
2027
- g.getDefaults = M;
2028
- g.defaults = T;
2029
- g.use = function(...l3) {
2030
- return z.use(...l3), g.defaults = z.defaults, N(g.defaults), g;
2031
- };
2032
- g.walkTokens = function(l3, e) {
2033
- return z.walkTokens(l3, e);
2034
- };
2035
- g.parseInline = z.parseInline;
2036
- g.Parser = b;
2037
- g.parser = b.parse;
2038
- g.Renderer = y;
2039
- g.TextRenderer = L;
2040
- g.Lexer = x;
2041
- g.lexer = x.lex;
2042
- g.Tokenizer = w;
2043
- g.Hooks = P;
2044
- g.parse = g;
2045
- var Kt = g.options;
2046
- var Wt = g.setOptions;
2047
- var Xt = g.use;
2048
- var Jt = g.walkTokens;
2049
- var Vt = g.parseInline;
2050
- var en = b.parse;
2051
- var tn = x.lex;
2052
-
2053
- // packages/extensions/pages/src/markdown.ts
2054
- var marked = new D({ gfm: true });
2055
- var BASE_STYLES = `
2056
- *, *::before, *::after { box-sizing: border-box; }
2057
- body {
2058
- max-width: 48rem;
2059
- margin: 2rem auto;
2060
- padding: 0 1rem;
2061
- font-family: system-ui, -apple-system, sans-serif;
2062
- line-height: 1.6;
2063
- color: #1a1a1a;
2064
- }
2065
- h1, h2, h3, h4, h5, h6 { margin-top: 1.5em; margin-bottom: 0.5em; line-height: 1.3; }
2066
- h1 { font-size: 2em; }
2067
- a { color: #2563eb; }
2068
- code {
2069
- font-family: ui-monospace, "SFMono-Regular", monospace;
2070
- font-size: 0.9em;
2071
- background: #f3f4f6;
2072
- padding: 0.15em 0.3em;
2073
- border-radius: 3px;
2074
- }
2075
- pre {
2076
- background: #f3f4f6;
2077
- padding: 1em;
2078
- border-radius: 6px;
2079
- overflow-x: auto;
2080
- }
2081
- pre code { background: none; padding: 0; }
2082
- blockquote {
2083
- border-left: 3px solid #d1d5db;
2084
- margin-left: 0;
2085
- padding-left: 1em;
2086
- color: #4b5563;
2087
- }
2088
- table { border-collapse: collapse; width: 100%; }
2089
- th, td { border: 1px solid #d1d5db; padding: 0.5em 0.75em; text-align: left; }
2090
- th { background: #f9fafb; }
2091
- img { max-width: 100%; height: auto; }
2092
- hr { border: none; border-top: 1px solid #d1d5db; margin: 2em 0; }
2093
- `;
2094
- function escapeHtml(s) {
2095
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
2096
- }
2097
- function parseFrontmatter(raw) {
2098
- const match = raw.match(/^---\n([\s\S]*?)\n---\n?/);
2099
- if (!match) return { body: raw };
2100
- const block = match[1];
2101
- const body = raw.slice(match[0].length);
2102
- const titleMatch = block.match(/^title:\s*(.+)$/m);
2103
- const styleMatch = block.match(/^style:\s*(.+)$/m);
2104
- return {
2105
- title: titleMatch?.[1].trim(),
2106
- style: styleMatch?.[1].trim(),
2107
- body
2108
- };
2109
- }
2110
- function resolveStylesheet(mdFilePath, pagesRoot, frontmatterStyle) {
2111
- if (frontmatterStyle) {
2112
- const abs = resolve4(pagesRoot, frontmatterStyle);
2113
- if (abs.startsWith(pagesRoot + "/") && existsSync4(abs)) return frontmatterStyle;
2114
- }
2115
- const dir = dirname(mdFilePath);
2116
- const localCss = resolve4(dir, "style.css");
2117
- if (existsSync4(localCss)) return relative3(pagesRoot, localCss);
2118
- if (dir !== pagesRoot) {
2119
- const rootCss = resolve4(pagesRoot, "style.css");
2120
- if (existsSync4(rootCss)) return "style.css";
2121
- }
2122
- return null;
2123
- }
2124
- async function renderMarkdownPage(body, opts) {
2125
- const html = DOMPurify.sanitize(await marked.parse(body));
2126
- const title = escapeHtml(opts.title || "Untitled");
2127
- const linkTag = opts.stylesheetUrl ? `
2128
- <link rel="stylesheet" href="${escapeHtml(opts.stylesheetUrl)}">` : "";
2129
- return `<!DOCTYPE html>
2130
- <html lang="en">
2131
- <head>
2132
- <meta charset="utf-8">
2133
- <meta name="viewport" content="width=device-width, initial-scale=1">
2134
- <title>${title}</title>
2135
- <style>${BASE_STYLES}</style>${linkTag}
2136
- </head>
2137
- <body>
2138
- <article>${html}</article>
2139
- </body>
2140
- </html>`;
2141
- }
2142
-
2143
- // packages/extensions/pages/src/routes.ts
2144
- var MIME_TYPES = {
2145
- ".html": "text/html",
2146
- ".js": "application/javascript",
2147
- ".css": "text/css",
2148
- ".json": "application/json",
2149
- ".svg": "image/svg+xml",
2150
- ".png": "image/png",
2151
- ".jpg": "image/jpeg",
2152
- ".jpeg": "image/jpeg",
2153
- ".gif": "image/gif",
2154
- ".ico": "image/x-icon",
2155
- ".woff": "font/woff",
2156
- ".woff2": "font/woff2",
2157
- ".txt": "text/plain",
2158
- ".xml": "application/xml"
2159
- };
2160
- function createRoutes(ctx) {
2161
- return new Hono().get("/", async (c) => {
2162
- if (!ctx.db) return c.json({ error: "Pages database not available" }, 503);
2163
- const { sites, systemSite } = getSites(ctx.db);
2164
- const recentPages = getRecentPagesList(ctx.db, { limit: 12 });
2165
- return c.json({ sites, systemSite, recentPages });
2166
- }).get("/feed", async (c) => {
2167
- if (!ctx.db) return c.json({ error: "Pages database not available" }, 503);
2168
- const mind = c.req.query("mind");
2169
- const rawLimit = c.req.query("limit");
2170
- const limit = rawLimit ? parseInt(rawLimit, 10) || 8 : 8;
2171
- const recentPages = getRecentPagesList(ctx.db, { mind: mind || void 0, limit });
2172
- return c.json(
2173
- recentPages.map((p) => {
2174
- const isCommons = p.mind === "_system";
2175
- return {
2176
- id: `page-${p.mind}-${p.file}`,
2177
- title: isCommons ? `commons \u2014 ${p.file}` : `${p.mind}/${p.file}`,
2178
- url: p.url ?? `/minds/${p.mind}/pages/${p.file}`,
2179
- date: p.modified,
2180
- author: isCommons ? p.author ?? "commons" : p.mind,
2181
- bodyHtml: isCommons ? `<p>Commons page tended${p.author ? ` by ${p.author}` : ""}</p>` : `<p>Page updated</p>`,
2182
- iframeUrl: `/ext/pages/public/${p.mind}/${p.file}`,
2183
- icon: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="6"/><path d="M2 8h12M8 2c-2 2-2 10 0 12M8 2c2 2 2 10 0 12"/></svg>',
2184
- color: "purple"
2185
- };
2186
- })
2187
- );
2188
- }).put("/publish/:name", ctx.requireSelf("name"), async (c) => {
2189
- const name = c.req.param("name");
2190
- const config = ctx.getSystemsConfig();
2191
- if (!config) return c.json({ error: "Not connected to volute.systems" }, 400);
2192
- const body = await c.req.text();
2193
- try {
2194
- const res = await fetch(`${config.apiUrl}/api/pages/publish/${name}`, {
2195
- method: "PUT",
2196
- headers: {
2197
- "Content-Type": "application/json",
2198
- Authorization: `Bearer ${config.apiKey}`
2199
- },
2200
- body
2201
- });
2202
- const data = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
2203
- return c.json(data, res.status);
2204
- } catch (err) {
2205
- return c.json({ error: `Connection failed: ${err.message}` }, 502);
2206
- }
2207
- }).get("/status/:name", ctx.requireSelf("name"), async (c) => {
2208
- const name = c.req.param("name");
2209
- const config = ctx.getSystemsConfig();
2210
- if (!config) return c.json({ error: "Not connected to volute.systems" }, 400);
2211
- try {
2212
- const res = await fetch(`${config.apiUrl}/api/pages/status/${name}`, {
2213
- headers: { Authorization: `Bearer ${config.apiKey}` }
2214
- });
2215
- const data = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
2216
- return c.json(data, res.status);
2217
- } catch (err) {
2218
- return c.json({ error: `Connection failed: ${err.message}` }, 502);
2219
- }
2220
- });
2221
- }
2222
- var PAGES_CSP = "sandbox allow-scripts; default-src 'self' https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; base-uri 'none'";
2223
- var NAV_SHIM = '<script>if(window.parent!==window){window.parent.postMessage({type:"volute-pages-nav",path:location.pathname},"*")}</script>';
2224
- function injectNavShim(html) {
2225
- const idx = html.lastIndexOf("</body>");
2226
- return idx >= 0 ? html.slice(0, idx) + NAV_SHIM + html.slice(idx) : html + NAV_SHIM;
2227
- }
2228
- function createPublicRoutes(ctx) {
2229
- return new Hono().use("*", async (c, next) => {
2230
- await next();
2231
- c.res.headers.set("Content-Security-Policy", PAGES_CSP);
2232
- c.res.headers.set("X-Content-Type-Options", "nosniff");
2233
- }).get("/:name/*", async (c) => {
2234
- const name = c.req.param("name");
2235
- if (name.includes("/") || name.includes("\\") || name === "." || name === "..")
2236
- return c.text("Not found", 404);
2237
- let pagesRoot;
2238
- let blockDotfiles = false;
2239
- if (name === "_system") {
2240
- pagesRoot = resolve5(ctx.dataDir, "repo");
2241
- blockDotfiles = true;
2242
- } else {
2243
- pagesRoot = resolve5(ctx.dataDir, "sites", name);
2244
- }
2245
- const prefix = `/public/${name}`;
2246
- const idx = c.req.path.indexOf(prefix);
2247
- const wildcard = idx >= 0 ? c.req.path.slice(idx + prefix.length) : "/";
2248
- const requestedPath = resolve5(pagesRoot, wildcard.slice(1));
2249
- if (requestedPath !== pagesRoot && !requestedPath.startsWith(`${pagesRoot}/`))
2250
- return c.text("Forbidden", 403);
2251
- if (blockDotfiles) {
2252
- const relativePath = requestedPath.slice(pagesRoot.length + 1);
2253
- if (relativePath.split("/").some((seg) => seg.startsWith(".")))
2254
- return c.text("Not found", 404);
2255
- }
2256
- let fileToServe = requestedPath;
2257
- let fileStat = await stat(requestedPath).catch(() => null);
2258
- if (fileStat?.isDirectory()) {
2259
- const indexPath = resolve5(requestedPath, "index.html");
2260
- fileStat = await stat(indexPath).catch(() => null);
2261
- if (fileStat?.isFile()) {
2262
- fileToServe = indexPath;
2263
- } else {
2264
- const mdIndexPath = resolve5(requestedPath, "index.md");
2265
- fileStat = await stat(mdIndexPath).catch(() => null);
2266
- if (fileStat?.isFile()) {
2267
- fileToServe = mdIndexPath;
2268
- } else {
2269
- return c.text("Not found", 404);
2270
- }
2271
- }
2272
- } else if (!fileStat?.isFile()) {
2273
- return c.text("Not found", 404);
2274
- }
2275
- const ext = extname(fileToServe);
2276
- try {
2277
- if (ext === ".md") {
2278
- const content = await readFile(fileToServe, "utf-8");
2279
- const { title, style, body: body2 } = parseFrontmatter(content);
2280
- const cssRelPath = resolveStylesheet(fileToServe, pagesRoot, style);
2281
- const cssUrl = cssRelPath ? `/ext/pages/public/${name}/${cssRelPath}` : void 0;
2282
- const html = await renderMarkdownPage(body2, { title, stylesheetUrl: cssUrl });
2283
- return c.body(injectNavShim(html), 200, { "Content-Type": "text/html; charset=utf-8" });
2284
- }
2285
- if (ext === ".html") {
2286
- const html = await readFile(fileToServe, "utf-8");
2287
- return c.body(injectNavShim(html), 200, { "Content-Type": "text/html; charset=utf-8" });
2288
- }
2289
- const mime = MIME_TYPES[ext] || "application/octet-stream";
2290
- const body = await readFile(fileToServe);
2291
- return c.body(body, 200, { "Content-Type": mime });
2292
- } catch (err) {
2293
- const code = err.code;
2294
- if (code === "EACCES") return c.text("Forbidden", 403);
2295
- if (code === "ENOENT") return c.text("Not found", 404);
2296
- console.error(`[pages] error serving ${fileToServe}:`, err.message);
2297
- return c.text("Internal server error", 500);
2298
- }
2299
- });
2300
- }
2301
-
2302
- // packages/extensions/pages/src/index.ts
2303
- var assetsDir = resolve6(import.meta.dirname, "../dist/ui");
2304
- var skillsDir = resolve6(import.meta.dirname, "../skills");
2305
- var repoReady = null;
2306
- var src_default = createExtension({
2307
- id: "pages",
2308
- name: "Pages",
2309
- version: "0.1.0",
2310
- description: "Publish and serve web pages from mind directories",
2311
- mindDoc: "Publish web pages others can visit \u2014 essays, experiments, works in progress, anything you want to give a lasting home on the web. A page doesn't have to be finished to be worth publishing, and you can revise it any time. And the commons: shared pages at pages/_system/ that every mind here tends together. Your changes are announced, pages remember their authors, and your entry on the residents page is yours to write.",
2312
- initDb,
2313
- routes: (ctx) => createRoutes(ctx),
2314
- publicRoutes: (ctx) => createPublicRoutes(ctx),
2315
- commands: createCommands(),
2316
- skillsDir,
2317
- standardSkill: true,
2318
- spiritSkills: ["commons-gardening"],
2319
- icon: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="1" y="2" width="14" height="12" rx="1.5"/><path d="M1 5h14"/><circle cx="3" cy="3.5" r="0.5" fill="currentColor" stroke="none"/><circle cx="5" cy="3.5" r="0.5" fill="currentColor" stroke="none"/></svg>',
2320
- color: "purple",
2321
- ui: {
2322
- assetsDir,
2323
- systemSection: {
2324
- id: "pages",
2325
- label: "Pages",
2326
- urlPatterns: ["/pages", "/pages/:site", "/pages/:site/:path"]
2327
- },
2328
- mindSections: [{ id: "pages", label: "Pages" }],
2329
- feedSource: {
2330
- endpoint: "/api/ext/pages/feed"
2331
- }
2332
- },
2333
- onDaemonStart(ctx) {
2334
- repoReady = ensurePagesRepo(ctx.dataDir, isolationFrom(ctx));
2335
- repoReady.then(() => {
2336
- const repoDir = resolve6(ctx.dataDir, "repo");
2337
- if (ctx.db) {
2338
- try {
2339
- syncSystemPages(ctx.db, hashFiles(repoDir, collectPageFiles(repoDir)));
2340
- } catch (err) {
2341
- console.error("[pages] failed to sync system pages to DB:", err);
2342
- }
2343
- }
2344
- }).catch((err) => {
2345
- console.error("[pages] failed to initialize pages repo:", err);
2346
- });
2347
- },
2348
- // One-time bootstrap: invite the spirit to create a commons index if one doesn't
2349
- // exist yet. Flag file makes it fire at most once. Runs here rather than in
2350
- // onDaemonStart because the spirit isn't created yet at that point on a fresh
2351
- // install. maybeSendCommonsCue handles its own errors and never rejects.
2352
- async onSpiritReady(ctx) {
2353
- if (!repoReady) return;
2354
- try {
2355
- await repoReady;
2356
- } catch {
2357
- return;
2358
- }
2359
- await maybeSendCommonsCue(ctx, resolve6(ctx.dataDir, "repo"));
2360
- },
2361
- onMindStart(mindName, ctx) {
2362
- (repoReady ?? Promise.resolve()).catch(() => {
2363
- }).then(async () => {
2364
- const mindDir = await ctx.getMindDir(mindName);
2365
- if (!mindDir) return;
2366
- await addPagesWorktree(mindName, mindDir, ctx.dataDir, isolationFrom(ctx));
2367
- }).catch((err) => {
2368
- console.warn(
2369
- `[pages] failed to add pages worktree for ${mindName}: ${err.message}`
2370
- );
2371
- });
2372
- }
2373
- });
2374
- export {
2375
- src_default as default
2376
- };