@texuli/blocks 0.0.0-stage → 0.1.0-next.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 (257) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -2
  3. package/dist/code/CodeBlockView.svelte +135 -0
  4. package/dist/code/CodeBlockView.svelte.d.ts +5 -0
  5. package/dist/code/check.d.ts +15 -0
  6. package/dist/code/check.js +14 -0
  7. package/dist/code/code.css +201 -0
  8. package/dist/code/code.css.d.ts +1 -0
  9. package/dist/code/engine-entry.d.ts +10 -0
  10. package/dist/code/engine-entry.js +10 -0
  11. package/dist/code/engine.d.ts +18 -0
  12. package/dist/code/engine.js +18 -0
  13. package/dist/code/family-engine.d.ts +23 -0
  14. package/dist/code/family-engine.js +4 -0
  15. package/dist/code/family.d.ts +7 -0
  16. package/dist/code/family.js +5 -0
  17. package/dist/code/grammars.d.ts +12 -0
  18. package/dist/code/grammars.js +83 -0
  19. package/dist/code/highlight.d.ts +15 -0
  20. package/dist/code/highlight.js +53 -0
  21. package/dist/code/index.d.ts +13 -0
  22. package/dist/code/index.js +12 -0
  23. package/dist/code/labels.d.ts +27 -0
  24. package/dist/code/labels.js +24 -0
  25. package/dist/code/languages/bash.d.ts +3 -0
  26. package/dist/code/languages/bash.js +48 -0
  27. package/dist/code/languages/css.d.ts +10 -0
  28. package/dist/code/languages/css.js +67 -0
  29. package/dist/code/languages/html.d.ts +6 -0
  30. package/dist/code/languages/html.js +35 -0
  31. package/dist/code/languages/javascript.d.ts +3 -0
  32. package/dist/code/languages/javascript.js +113 -0
  33. package/dist/code/languages/json.d.ts +3 -0
  34. package/dist/code/languages/json.js +24 -0
  35. package/dist/code/languages/python.d.ts +3 -0
  36. package/dist/code/languages/python.js +35 -0
  37. package/dist/code/languages/shared.d.ts +22 -0
  38. package/dist/code/languages/shared.js +37 -0
  39. package/dist/code/languages/sql.d.ts +3 -0
  40. package/dist/code/languages/sql.js +32 -0
  41. package/dist/code/languages/yaml.d.ts +7 -0
  42. package/dist/code/languages/yaml.js +36 -0
  43. package/dist/code/renderers.d.ts +5 -0
  44. package/dist/code/renderers.js +5 -0
  45. package/dist/code/token-styles.d.ts +25 -0
  46. package/dist/code/token-styles.js +51 -0
  47. package/dist/code/tokenize-code.d.ts +17 -0
  48. package/dist/code/tokenize-code.js +34 -0
  49. package/dist/code/tokenizer.d.ts +76 -0
  50. package/dist/code/tokenizer.js +171 -0
  51. package/dist/core/catalog/entries.d.ts +10 -0
  52. package/dist/core/catalog/entries.js +589 -0
  53. package/dist/core/catalog/index.d.ts +4 -0
  54. package/dist/core/catalog/index.js +2 -0
  55. package/dist/core/catalog/types.d.ts +36 -0
  56. package/dist/core/catalog/types.js +1 -0
  57. package/dist/core/catalog/validate.d.ts +15 -0
  58. package/dist/core/catalog/validate.js +46 -0
  59. package/dist/core/formula/evaluate.d.ts +14 -0
  60. package/dist/core/formula/evaluate.js +181 -0
  61. package/dist/core/formula/index.d.ts +8 -0
  62. package/dist/core/formula/index.js +6 -0
  63. package/dist/core/formula/parse.d.ts +19 -0
  64. package/dist/core/formula/parse.js +452 -0
  65. package/dist/core/formula/types.d.ts +76 -0
  66. package/dist/core/formula/types.js +7 -0
  67. package/dist/core/index.d.ts +14 -0
  68. package/dist/core/index.js +13 -0
  69. package/dist/core/limits.d.ts +27 -0
  70. package/dist/core/limits.js +26 -0
  71. package/dist/core/safety.d.ts +30 -0
  72. package/dist/core/safety.js +110 -0
  73. package/dist/core/schema/blocks.d.ts +138 -0
  74. package/dist/core/schema/blocks.js +181 -0
  75. package/dist/core/schema/code-family.d.ts +4 -0
  76. package/dist/core/schema/code-family.js +75 -0
  77. package/dist/core/schema/line-spec.d.ts +7 -0
  78. package/dist/core/schema/line-spec.js +19 -0
  79. package/dist/core/schema/media-family.d.ts +4 -0
  80. package/dist/core/schema/media-family.js +260 -0
  81. package/dist/core/schema/parse-family.d.ts +14 -0
  82. package/dist/core/schema/parse-family.js +37 -0
  83. package/dist/core/schema/primitives.d.ts +73 -0
  84. package/dist/core/schema/primitives.js +140 -0
  85. package/dist/core/schema/text-family.d.ts +4 -0
  86. package/dist/core/schema/text-family.js +121 -0
  87. package/dist/core/schema/vocabulary.d.ts +20 -0
  88. package/dist/core/schema/vocabulary.js +33 -0
  89. package/dist/core/text.d.ts +31 -0
  90. package/dist/core/text.js +139 -0
  91. package/dist/core/untrusted.d.ts +20 -0
  92. package/dist/core/untrusted.js +377 -0
  93. package/dist/css-modules.d.ts +1 -0
  94. package/dist/css.d.ts +1 -0
  95. package/dist/data/ChartBlockView.svelte +77 -0
  96. package/dist/data/ChartBlockView.svelte.d.ts +10 -0
  97. package/dist/data/DataBlockView.svelte +109 -0
  98. package/dist/data/DataBlockView.svelte.d.ts +5 -0
  99. package/dist/data/check.d.ts +10 -0
  100. package/dist/data/check.js +9 -0
  101. package/dist/data/engine.d.ts +18 -0
  102. package/dist/data/engine.js +10 -0
  103. package/dist/data/family.d.ts +6 -0
  104. package/dist/data/family.js +4 -0
  105. package/dist/data/index.d.ts +9 -0
  106. package/dist/data/index.js +8 -0
  107. package/dist/data/labels.d.ts +8 -0
  108. package/dist/data/labels.js +8 -0
  109. package/dist/data/renderers.d.ts +2 -0
  110. package/dist/data/renderers.js +2 -0
  111. package/dist/data/schema.d.ts +84 -0
  112. package/dist/data/schema.js +385 -0
  113. package/dist/diagram/BoardDiagram.svelte +48 -0
  114. package/dist/diagram/BoardDiagram.svelte.d.ts +8 -0
  115. package/dist/diagram/DiagramFamily.svelte +46 -0
  116. package/dist/diagram/DiagramFamily.svelte.d.ts +10 -0
  117. package/dist/diagram/FlowDiagram.svelte +108 -0
  118. package/dist/diagram/FlowDiagram.svelte.d.ts +8 -0
  119. package/dist/diagram/TerminalDiagram.svelte +38 -0
  120. package/dist/diagram/TerminalDiagram.svelte.d.ts +8 -0
  121. package/dist/diagram/TreeDiagram.svelte +149 -0
  122. package/dist/diagram/TreeDiagram.svelte.d.ts +8 -0
  123. package/dist/diagram/diagram.css +287 -0
  124. package/dist/diagram/diagram.css.d.ts +1 -0
  125. package/dist/diagram/engine.d.ts +16 -0
  126. package/dist/diagram/engine.js +14 -0
  127. package/dist/diagram/family.d.ts +7 -0
  128. package/dist/diagram/family.js +5 -0
  129. package/dist/diagram/index.d.ts +10 -0
  130. package/dist/diagram/index.js +9 -0
  131. package/dist/diagram/layout.d.ts +26 -0
  132. package/dist/diagram/layout.js +165 -0
  133. package/dist/diagram/schema.d.ts +74 -0
  134. package/dist/diagram/schema.js +358 -0
  135. package/dist/diagram/tones.d.ts +6 -0
  136. package/dist/diagram/tones.js +16 -0
  137. package/dist/embed/EmbedApp.svelte +138 -0
  138. package/dist/embed/EmbedApp.svelte.d.ts +17 -0
  139. package/dist/embed/EmbedBlockView.svelte +32 -0
  140. package/dist/embed/EmbedBlockView.svelte.d.ts +5 -0
  141. package/dist/embed/LinkPreview.svelte +48 -0
  142. package/dist/embed/LinkPreview.svelte.d.ts +10 -0
  143. package/dist/embed/engine.d.ts +30 -0
  144. package/dist/embed/engine.js +17 -0
  145. package/dist/embed/family.d.ts +7 -0
  146. package/dist/embed/family.js +5 -0
  147. package/dist/embed/index.d.ts +5 -0
  148. package/dist/embed/index.js +3 -0
  149. package/dist/embed/renderers.d.ts +3 -0
  150. package/dist/embed/renderers.js +3 -0
  151. package/dist/embed/sandbox.d.ts +86 -0
  152. package/dist/embed/sandbox.js +114 -0
  153. package/dist/embed/schema.d.ts +30 -0
  154. package/dist/embed/schema.js +217 -0
  155. package/dist/index.d.ts +16 -0
  156. package/dist/index.js +15 -0
  157. package/dist/interactive/CalculatorBlock.svelte +61 -0
  158. package/dist/interactive/CalculatorBlock.svelte.d.ts +10 -0
  159. package/dist/interactive/ChecklistBlock.svelte +44 -0
  160. package/dist/interactive/ChecklistBlock.svelte.d.ts +10 -0
  161. package/dist/interactive/InteractiveBlockView.svelte +31 -0
  162. package/dist/interactive/InteractiveBlockView.svelte.d.ts +5 -0
  163. package/dist/interactive/PollBlock.svelte +111 -0
  164. package/dist/interactive/PollBlock.svelte.d.ts +10 -0
  165. package/dist/interactive/QuizBlock.svelte +75 -0
  166. package/dist/interactive/QuizBlock.svelte.d.ts +10 -0
  167. package/dist/interactive/check.d.ts +10 -0
  168. package/dist/interactive/check.js +9 -0
  169. package/dist/interactive/engine.d.ts +19 -0
  170. package/dist/interactive/engine.js +12 -0
  171. package/dist/interactive/family.d.ts +6 -0
  172. package/dist/interactive/family.js +4 -0
  173. package/dist/interactive/index.d.ts +13 -0
  174. package/dist/interactive/index.js +13 -0
  175. package/dist/interactive/interactive.css +97 -0
  176. package/dist/interactive/interactive.css.d.ts +1 -0
  177. package/dist/interactive/labels.d.ts +16 -0
  178. package/dist/interactive/labels.js +16 -0
  179. package/dist/interactive/renderers.d.ts +9 -0
  180. package/dist/interactive/renderers.js +9 -0
  181. package/dist/interactive/schema.d.ts +76 -0
  182. package/dist/interactive/schema.js +324 -0
  183. package/dist/map/MapBlockView.svelte +465 -0
  184. package/dist/map/MapBlockView.svelte.d.ts +5 -0
  185. package/dist/map/check.d.ts +11 -0
  186. package/dist/map/check.js +6 -0
  187. package/dist/map/engine.d.ts +19 -0
  188. package/dist/map/engine.js +8 -0
  189. package/dist/map/family.d.ts +7 -0
  190. package/dist/map/family.js +5 -0
  191. package/dist/map/index.d.ts +11 -0
  192. package/dist/map/index.js +10 -0
  193. package/dist/map/labels.d.ts +27 -0
  194. package/dist/map/labels.js +21 -0
  195. package/dist/map/renderers.d.ts +2 -0
  196. package/dist/map/renderers.js +2 -0
  197. package/dist/map/schema.d.ts +41 -0
  198. package/dist/map/schema.js +176 -0
  199. package/dist/map/view-model.d.ts +55 -0
  200. package/dist/map/view-model.js +168 -0
  201. package/dist/media/MediaBlockView.svelte +258 -0
  202. package/dist/media/MediaBlockView.svelte.d.ts +5 -0
  203. package/dist/media/check.d.ts +14 -0
  204. package/dist/media/check.js +13 -0
  205. package/dist/media/engine.d.ts +18 -0
  206. package/dist/media/engine.js +10 -0
  207. package/dist/media/family.d.ts +7 -0
  208. package/dist/media/family.js +5 -0
  209. package/dist/media/index.d.ts +11 -0
  210. package/dist/media/index.js +10 -0
  211. package/dist/media/labels.d.ts +7 -0
  212. package/dist/media/labels.js +12 -0
  213. package/dist/media/renderers.d.ts +5 -0
  214. package/dist/media/renderers.js +5 -0
  215. package/dist/media/resolve.d.ts +6 -0
  216. package/dist/media/resolve.js +15 -0
  217. package/dist/structure/NestedBlocks.svelte +65 -0
  218. package/dist/structure/NestedBlocks.svelte.d.ts +11 -0
  219. package/dist/structure/SafeBody.svelte +13 -0
  220. package/dist/structure/SafeBody.svelte.d.ts +7 -0
  221. package/dist/structure/StructureFamily.svelte +157 -0
  222. package/dist/structure/StructureFamily.svelte.d.ts +5 -0
  223. package/dist/structure/check.d.ts +14 -0
  224. package/dist/structure/check.js +27 -0
  225. package/dist/structure/engine.d.ts +18 -0
  226. package/dist/structure/engine.js +18 -0
  227. package/dist/structure/family.d.ts +7 -0
  228. package/dist/structure/family.js +5 -0
  229. package/dist/structure/index.d.ts +11 -0
  230. package/dist/structure/index.js +10 -0
  231. package/dist/structure/labels.d.ts +11 -0
  232. package/dist/structure/labels.js +11 -0
  233. package/dist/structure/renderers.d.ts +5 -0
  234. package/dist/structure/renderers.js +5 -0
  235. package/dist/structure/schema.d.ts +71 -0
  236. package/dist/structure/schema.js +327 -0
  237. package/dist/structure/structure.css +182 -0
  238. package/dist/structure/structure.css.d.ts +1 -0
  239. package/dist/text/RichText.svelte +169 -0
  240. package/dist/text/RichText.svelte.d.ts +13 -0
  241. package/dist/text/TextBlockView.svelte +177 -0
  242. package/dist/text/TextBlockView.svelte.d.ts +5 -0
  243. package/dist/text/check.d.ts +14 -0
  244. package/dist/text/check.js +13 -0
  245. package/dist/text/engine.d.ts +17 -0
  246. package/dist/text/engine.js +10 -0
  247. package/dist/text/family.d.ts +7 -0
  248. package/dist/text/family.js +5 -0
  249. package/dist/text/index.d.ts +12 -0
  250. package/dist/text/index.js +11 -0
  251. package/dist/text/labels.d.ts +22 -0
  252. package/dist/text/labels.js +29 -0
  253. package/dist/text/markdown.d.ts +80 -0
  254. package/dist/text/markdown.js +361 -0
  255. package/dist/text/renderers.d.ts +6 -0
  256. package/dist/text/renderers.js +6 -0
  257. package/package.json +167 -4
@@ -0,0 +1,83 @@
1
+ /** Languages with a grammar. Anything else renders as plain text. */
2
+ export const CODE_GRAMMAR_LANGUAGES = [
3
+ 'ts',
4
+ 'js',
5
+ 'json',
6
+ 'bash',
7
+ 'python',
8
+ 'html',
9
+ 'css',
10
+ 'sql',
11
+ 'yaml',
12
+ ];
13
+ const ALIASES = {
14
+ typescript: 'ts',
15
+ tsx: 'ts',
16
+ mts: 'ts',
17
+ cts: 'ts',
18
+ javascript: 'js',
19
+ jsx: 'js',
20
+ mjs: 'js',
21
+ cjs: 'js',
22
+ jsonc: 'json',
23
+ json5: 'json',
24
+ sh: 'bash',
25
+ shell: 'bash',
26
+ zsh: 'bash',
27
+ console: 'bash',
28
+ py: 'python',
29
+ python3: 'python',
30
+ htm: 'html',
31
+ xml: 'html',
32
+ svg: 'html',
33
+ svelte: 'html',
34
+ vue: 'html',
35
+ postgres: 'sql',
36
+ postgresql: 'sql',
37
+ sqlite: 'sql',
38
+ mysql: 'sql',
39
+ yml: 'yaml',
40
+ };
41
+ /** A language id or alias (`typescript`, `sh`, `yml`…) → a grammar language, or `null`. */
42
+ export function resolveCodeLanguage(lang) {
43
+ const key = lang.trim().toLowerCase();
44
+ if (CODE_GRAMMAR_LANGUAGES.includes(key)) {
45
+ return key;
46
+ }
47
+ return Object.hasOwn(ALIASES, key) ? ALIASES[key] : null;
48
+ }
49
+ /*
50
+ * One lazy chunk per grammar file: a code block downloads only the grammar of
51
+ * its own language, while the tokenizer core stays in the code family chunk.
52
+ */
53
+ const LOADERS = {
54
+ ts: () => import("./languages/javascript.js").then((m) => m.typescriptGrammar),
55
+ js: () => import("./languages/javascript.js").then((m) => m.javascriptGrammar),
56
+ json: () => import("./languages/json.js").then((m) => m.jsonGrammar),
57
+ bash: () => import("./languages/bash.js").then((m) => m.bashGrammar),
58
+ python: () => import("./languages/python.js").then((m) => m.pythonGrammar),
59
+ html: () => import("./languages/html.js").then((m) => m.htmlGrammar),
60
+ css: () => import("./languages/css.js").then((m) => m.cssGrammar),
61
+ sql: () => import("./languages/sql.js").then((m) => m.sqlGrammar),
62
+ yaml: () => import("./languages/yaml.js").then((m) => m.yamlGrammar),
63
+ };
64
+ const cache = new Map();
65
+ /**
66
+ * The grammar for a language id or alias, loaded on demand and cached; `null`
67
+ * for `text` and unknown languages. A failed load is not cached, so a later
68
+ * render can retry.
69
+ */
70
+ export function loadCodeGrammar(lang) {
71
+ const resolved = lang === undefined ? null : resolveCodeLanguage(lang);
72
+ if (resolved === null)
73
+ return Promise.resolve(null);
74
+ const cached = cache.get(resolved);
75
+ if (cached)
76
+ return cached;
77
+ const pending = LOADERS[resolved]().then((grammar) => grammar, () => {
78
+ cache.delete(resolved);
79
+ return null;
80
+ });
81
+ cache.set(resolved, pending);
82
+ return pending;
83
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Stepped line highlights for code blocks. A step is either a line spec
3
+ * string (`"1-2,4"`, the code block schema's form) or a list of line numbers
4
+ * and `[start, end]` ranges (`[[1, 2], 4]`). Lines are 1-based.
5
+ */
6
+ import { parseLineSpec } from '../core/schema/line-spec.js';
7
+ export { parseLineSpec };
8
+ export type HighlightStep = string | readonly (number | readonly [number, number])[];
9
+ /**
10
+ * The highlighted lines of every step: sorted, unique, clamped to
11
+ * `lineCount`. A malformed step highlights nothing rather than everything.
12
+ */
13
+ export declare function resolveHighlightSteps(steps: readonly HighlightStep[], lineCount: number): number[][];
14
+ /** Lines in a piece of code, counting a trailing empty line like editors do. */
15
+ export declare function countCodeLines(code: string): number;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Stepped line highlights for code blocks. A step is either a line spec
3
+ * string (`"1-2,4"`, the code block schema's form) or a list of line numbers
4
+ * and `[start, end]` ranges (`[[1, 2], 4]`). Lines are 1-based.
5
+ */
6
+ import { parseLineSpec } from "../core/schema/line-spec.js";
7
+ export { parseLineSpec };
8
+ function rangesOf(step) {
9
+ if (typeof step === 'string')
10
+ return parseLineSpec(step);
11
+ if (!Array.isArray(step))
12
+ return null;
13
+ const ranges = [];
14
+ for (const item of step) {
15
+ if (typeof item === 'number') {
16
+ if (!Number.isInteger(item) || item < 1)
17
+ return null;
18
+ ranges.push([item, item]);
19
+ }
20
+ else if (Array.isArray(item) && item.length === 2) {
21
+ const [a, b] = item;
22
+ if (!Number.isInteger(a) || !Number.isInteger(b) || a < 1 || b < a)
23
+ return null;
24
+ ranges.push([a, b]);
25
+ }
26
+ else {
27
+ return null;
28
+ }
29
+ }
30
+ return ranges;
31
+ }
32
+ /**
33
+ * The highlighted lines of every step: sorted, unique, clamped to
34
+ * `lineCount`. A malformed step highlights nothing rather than everything.
35
+ */
36
+ export function resolveHighlightSteps(steps, lineCount) {
37
+ const max = Math.max(0, Math.floor(lineCount));
38
+ return steps.map((step) => {
39
+ const ranges = rangesOf(step);
40
+ if (!ranges)
41
+ return [];
42
+ const lines = new Set();
43
+ for (const [start, end] of ranges) {
44
+ for (let line = start; line <= Math.min(end, max); line += 1)
45
+ lines.add(line);
46
+ }
47
+ return [...lines].sort((a, b) => a - b);
48
+ });
49
+ }
50
+ /** Lines in a piece of code, counting a trailing empty line like editors do. */
51
+ export function countCodeLines(code) {
52
+ return code.split('\n').length;
53
+ }
@@ -0,0 +1,13 @@
1
+ /// <reference path="../css-modules.d.ts" />
2
+ /**
3
+ * `@texuli/blocks/code` (T-blocks-code): the code family's light entry, with
4
+ * the guard, the lazy renderer entry, labels, language resolution and token
5
+ * styles. It loads no grammar and no Svelte. The tokenizer, every grammar and
6
+ * the highlight helpers live in `@texuli/blocks/code/tokenizer`; the
7
+ * renderer in `@texuli/blocks/code/renderers` or through `loadCodeFamily()`.
8
+ */
9
+ export { type CodeBlockCheck, checkCodeBlock } from './check.js';
10
+ export { CODE_BLOCK_TYPES, type CodeBlockViewProps, type CodeFamilyBlock, type CodeFamilyBlockType, isCodeFamilyBlock, loadCodeFamily, } from './family.js';
11
+ export { CODE_GRAMMAR_LANGUAGES, type CodeGrammarLanguage, loadCodeGrammar, resolveCodeLanguage, } from './grammars.js';
12
+ export { type CodeBlockLabelOverrides, type CodeBlockLabels, DEFAULT_CODE_BLOCK_LABELS, fillCodeLabel, resolveCodeBlockLabels, } from './labels.js';
13
+ export { activeHighlightIndex, CODE_COLOR_ROLES, CODE_TOKEN_STYLES, type CodeColorRole, type CodeTokenStyle, codeTokenClass, } from './token-styles.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `@texuli/blocks/code` (T-blocks-code): the code family's light entry, with
3
+ * the guard, the lazy renderer entry, labels, language resolution and token
4
+ * styles. It loads no grammar and no Svelte. The tokenizer, every grammar and
5
+ * the highlight helpers live in `@texuli/blocks/code/tokenizer`; the
6
+ * renderer in `@texuli/blocks/code/renderers` or through `loadCodeFamily()`.
7
+ */
8
+ export { checkCodeBlock } from "./check.js";
9
+ export { CODE_BLOCK_TYPES, isCodeFamilyBlock, loadCodeFamily, } from "./family.js";
10
+ export { CODE_GRAMMAR_LANGUAGES, loadCodeGrammar, resolveCodeLanguage, } from "./grammars.js";
11
+ export { DEFAULT_CODE_BLOCK_LABELS, fillCodeLabel, resolveCodeBlockLabels, } from "./labels.js";
12
+ export { activeHighlightIndex, CODE_COLOR_ROLES, CODE_TOKEN_STYLES, codeTokenClass, } from "./token-styles.js";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Every visible or announced string the code family renders that does not
3
+ * come from the block itself. Hosts pass translations; English is the
4
+ * default. `{name}` in a template is replaced by the block's name (its
5
+ * filename, or its language in capitals).
6
+ */
7
+ export interface CodeBlockLabels {
8
+ /** Shown in place of a block that failed validation. */
9
+ invalid: string;
10
+ /** Name of a code block with neither a filename nor a language. */
11
+ code: string;
12
+ /** Visible copy button text, and its state texts. */
13
+ copy: string;
14
+ copied: string;
15
+ copyFailed: string;
16
+ /** Accessible name of the copy button (template with `{name}`). */
17
+ copyName: string;
18
+ /** Announced after a copy succeeds or fails. */
19
+ copiedAnnouncement: string;
20
+ copyFailedAnnouncement: string;
21
+ }
22
+ export declare const DEFAULT_CODE_BLOCK_LABELS: Readonly<CodeBlockLabels>;
23
+ export type CodeBlockLabelOverrides = Partial<CodeBlockLabels>;
24
+ /** Merges host overrides over the English defaults; non-string overrides are ignored. */
25
+ export declare function resolveCodeBlockLabels(overrides?: CodeBlockLabelOverrides): CodeBlockLabels;
26
+ /** Replaces every `{name}` in a label template (plain text, never markup). */
27
+ export declare function fillCodeLabel(template: string, name: string): string;
@@ -0,0 +1,24 @@
1
+ export const DEFAULT_CODE_BLOCK_LABELS = /* @__PURE__ */ Object.freeze({
2
+ invalid: 'This block could not be shown.',
3
+ code: 'Code',
4
+ copy: 'Copy',
5
+ copied: 'Copied',
6
+ copyFailed: 'Copy failed',
7
+ copyName: 'Copy {name} code',
8
+ copiedAnnouncement: 'Code copied to the clipboard.',
9
+ copyFailedAnnouncement: 'The code could not be copied.',
10
+ });
11
+ /** Merges host overrides over the English defaults; non-string overrides are ignored. */
12
+ export function resolveCodeBlockLabels(overrides = {}) {
13
+ const labels = { ...DEFAULT_CODE_BLOCK_LABELS };
14
+ for (const key of Object.keys(labels)) {
15
+ const value = overrides[key];
16
+ if (typeof value === 'string')
17
+ labels[key] = value;
18
+ }
19
+ return labels;
20
+ }
21
+ /** Replaces every `{name}` in a label template (plain text, never markup). */
22
+ export function fillCodeLabel(template, name) {
23
+ return template.split('{name}').join(name);
24
+ }
@@ -0,0 +1,3 @@
1
+ import { type Grammar } from '../tokenizer.js';
2
+ /** Shell scripts: commands, flags, variables, quoting and comments. */
3
+ export declare const bashGrammar: Grammar;
@@ -0,0 +1,48 @@
1
+ import { sticky } from "../tokenizer.js";
2
+ import { HASH_COMMENT, WHITESPACE, words } from "./shared.js";
3
+ const KEYWORDS = words('if', 'then', 'else', 'elif', 'fi', 'for', 'while', 'until', 'do', 'done', 'case', 'esac', 'in', 'function', 'select', 'return', 'break', 'continue', 'export', 'local', 'readonly', 'declare', 'unset', 'shift', 'source', 'exit');
4
+ /** Tokens after which the next word is a command name. */
5
+ const COMMAND_STARTERS = words('|', '||', '&&', ';', '(', '{', '`', '$(', 'then', 'do', 'else', 'elif', '!');
6
+ /** True when only spaces or tabs separate `start` from a line start (bounded). */
7
+ function atLineStart(input, start) {
8
+ for (let i = start - 1, n = 0; i >= 0 && n < 64; i -= 1, n += 1) {
9
+ const char = input[i];
10
+ if (char === '\n')
11
+ return true;
12
+ if (char !== ' ' && char !== '\t')
13
+ return false;
14
+ }
15
+ return start <= 64 && input.slice(0, start).trim() === '';
16
+ }
17
+ function word(text, ctx) {
18
+ if (KEYWORDS.has(text))
19
+ return 'keyword';
20
+ const start = ctx.end - text.length;
21
+ if (ctx.prev === null || COMMAND_STARTERS.has(ctx.prev.text) || atLineStart(ctx.input, start)) {
22
+ return 'function';
23
+ }
24
+ return 'plain';
25
+ }
26
+ /** Shell scripts: commands, flags, variables, quoting and comments. */
27
+ export const bashGrammar = {
28
+ name: 'bash',
29
+ start: 'code',
30
+ states: {
31
+ code: [
32
+ WHITESPACE,
33
+ HASH_COMMENT,
34
+ // Single quotes have no escapes; both quotes may span lines.
35
+ { re: sticky(String.raw `'[^']*(?:'|(?![\s\S]))`), kind: 'string' },
36
+ // `\\[\s\S]?` lets a lone trailing backslash match too: an unterminated
37
+ // string always runs to the end instead of failing and being rescanned.
38
+ { re: sticky(String.raw `"(?:[^"\\]|\\[\s\S]?)*(?:"|(?![\s\S]))`), kind: 'string' },
39
+ { re: sticky(String.raw `\$\{[^}\n]*\}?|\$(?:[A-Za-z_]\w*|[0-9@#?$!*-])`), kind: 'variable' },
40
+ { re: sticky(String.raw `\$\(`), kind: 'punctuation' },
41
+ { re: sticky(String.raw `(?<=^|[ \t])--?[A-Za-z][\w-]*`), kind: 'attr' },
42
+ { re: sticky(String.raw `[A-Za-z_./~][\w./~:@%+-]*`), kind: word },
43
+ { re: sticky(String.raw `\d+`), kind: 'number' },
44
+ { re: sticky(String.raw `\|\||&&|[|&;<>!=]+`), kind: 'operator' },
45
+ { re: sticky(String.raw `[(){}[\]\x60\\]`), kind: 'punctuation' },
46
+ ],
47
+ },
48
+ };
@@ -0,0 +1,10 @@
1
+ import { type Grammar } from '../tokenizer.js';
2
+ /**
3
+ * CSS in four states: selectors (outside a block), declarations (inside a
4
+ * block), the colon after a property, and values. Inside a block, a word
5
+ * followed by `:` is a property unless a `{` follows within 200 characters
6
+ * before any `;` or `}` (then it is a nested selector such as `a:hover {`);
7
+ * the bound keeps scanning linear. After a nested block's `}` the grammar
8
+ * returns to selectors, which still reads the next selector correctly.
9
+ */
10
+ export declare const cssGrammar: Grammar;
@@ -0,0 +1,67 @@
1
+ import { sticky } from "../tokenizer.js";
2
+ import { BLOCK_COMMENT, DOUBLE_QUOTED, SINGLE_QUOTED, WHITESPACE } from "./shared.js";
3
+ const COMMON = [
4
+ WHITESPACE,
5
+ BLOCK_COMMENT,
6
+ DOUBLE_QUOTED,
7
+ SINGLE_QUOTED,
8
+ { re: sticky(String.raw `@[\w-]+`), kind: 'keyword' },
9
+ ];
10
+ const NUMBER = {
11
+ re: sticky(String.raw `-?(?:\d+\.?\d*|\.\d+)(?:%|[A-Za-z]+)?`),
12
+ kind: 'number',
13
+ };
14
+ /** Selector pieces, shared by the top level and rules nested in a block. */
15
+ const SELECTOR = [
16
+ { re: sticky(String.raw `[.#][\w-]+`), kind: 'attr' },
17
+ { re: sticky(String.raw `::?[A-Za-z][\w-]*`), kind: 'keyword' },
18
+ { re: sticky(String.raw `\{`), kind: 'punctuation', next: 'declaration' },
19
+ ];
20
+ /**
21
+ * CSS in four states: selectors (outside a block), declarations (inside a
22
+ * block), the colon after a property, and values. Inside a block, a word
23
+ * followed by `:` is a property unless a `{` follows within 200 characters
24
+ * before any `;` or `}` (then it is a nested selector such as `a:hover {`);
25
+ * the bound keeps scanning linear. After a nested block's `}` the grammar
26
+ * returns to selectors, which still reads the next selector correctly.
27
+ */
28
+ export const cssGrammar = {
29
+ name: 'css',
30
+ start: 'selector',
31
+ states: {
32
+ selector: [
33
+ ...COMMON,
34
+ ...SELECTOR,
35
+ // Media features such as `(max-width: 600px)`.
36
+ { re: sticky(String.raw `[A-Za-z][\w-]*(?=[ \t]*:[ \t])`), kind: 'property' },
37
+ { re: sticky(String.raw `[A-Za-z][\w-]*|\*`), kind: 'tag' },
38
+ NUMBER,
39
+ { re: sticky(String.raw `[>+~,()[\]=:]|\}`), kind: 'punctuation' },
40
+ ],
41
+ declaration: [
42
+ ...COMMON,
43
+ {
44
+ re: sticky(String.raw `(?:--[\w-]+|-?[A-Za-z][\w-]*)(?=[ \t]*:)(?![^;{}]{0,200}\{)`),
45
+ kind: 'property',
46
+ next: 'colon',
47
+ },
48
+ { re: sticky(String.raw `\}`), kind: 'punctuation', next: 'selector' },
49
+ ...SELECTOR,
50
+ { re: sticky(String.raw `[A-Za-z][\w-]*|\*`), kind: 'tag' },
51
+ { re: sticky(String.raw `[;,>+~()[\]=]`), kind: 'punctuation' },
52
+ ],
53
+ colon: [WHITESPACE, { re: sticky(':'), kind: 'punctuation', next: 'value' }],
54
+ value: [
55
+ ...COMMON,
56
+ { re: sticky(String.raw `#[\da-fA-F]{3,8}(?![\w-])`), kind: 'number' },
57
+ NUMBER,
58
+ { re: sticky('!important'), kind: 'keyword' },
59
+ { re: sticky(String.raw `--[\w-]+`), kind: 'variable' },
60
+ { re: sticky(String.raw `[A-Za-z_-][\w-]*(?=\()`), kind: 'function' },
61
+ { re: sticky(String.raw `[A-Za-z_-][\w-]*`), kind: 'constant' },
62
+ { re: sticky(';'), kind: 'punctuation', next: 'declaration' },
63
+ { re: sticky(String.raw `\}`), kind: 'punctuation', next: 'selector' },
64
+ { re: sticky('[(),/*+:]'), kind: 'punctuation' },
65
+ ],
66
+ },
67
+ };
@@ -0,0 +1,6 @@
1
+ import { type Grammar } from '../tokenizer.js';
2
+ /**
3
+ * HTML markup: comments, doctype, tags, attributes and entities. Embedded
4
+ * `<script>` and `<style>` bodies are not re-tokenized as JS or CSS.
5
+ */
6
+ export declare const htmlGrammar: Grammar;
@@ -0,0 +1,35 @@
1
+ import { sticky } from "../tokenizer.js";
2
+ import { WHITESPACE } from "./shared.js";
3
+ /**
4
+ * HTML markup: comments, doctype, tags, attributes and entities. Embedded
5
+ * `<script>` and `<style>` bodies are not re-tokenized as JS or CSS.
6
+ */
7
+ export const htmlGrammar = {
8
+ name: 'html',
9
+ start: 'text',
10
+ states: {
11
+ text: [
12
+ { re: sticky(String.raw `<!--[\s\S]*?(?:-->|(?![\s\S]))`), kind: 'comment' },
13
+ { re: sticky('<![^>]*>?'), kind: 'keyword' },
14
+ { re: sticky(String.raw `<\/?(?=[A-Za-z])`), kind: 'punctuation', next: 'tagName' },
15
+ {
16
+ re: sticky(String.raw `&(?:#\d{1,7}|#[xX][\da-fA-F]{1,6}|[A-Za-z][A-Za-z\d]{0,31});`),
17
+ kind: 'constant',
18
+ },
19
+ { re: sticky('[^<&]+'), kind: 'plain' },
20
+ ],
21
+ tagName: [{ re: sticky(String.raw `[A-Za-z][\w:-]*`), kind: 'tag', next: 'tag' }],
22
+ tag: [
23
+ WHITESPACE,
24
+ { re: sticky(String.raw `\/?>`), kind: 'punctuation', next: 'text' },
25
+ { re: sticky(String.raw `"[^"]*(?:"|(?![\s\S]))`), kind: 'string' },
26
+ { re: sticky(String.raw `'[^']*(?:'|(?![\s\S]))`), kind: 'string' },
27
+ { re: sticky('='), kind: 'operator' },
28
+ {
29
+ re: sticky(String.raw `[^\s"'>/=]+`),
30
+ kind: (_text, ctx) => (ctx.prev?.text === '=' ? 'string' : 'attr'),
31
+ },
32
+ { re: sticky('/'), kind: 'punctuation' },
33
+ ],
34
+ },
35
+ };
@@ -0,0 +1,3 @@
1
+ import { type Grammar } from '../tokenizer.js';
2
+ export declare const javascriptGrammar: Grammar;
3
+ export declare const typescriptGrammar: Grammar;
@@ -0,0 +1,113 @@
1
+ import { classifyWord, sticky } from "../tokenizer.js";
2
+ import { BLOCK_COMMENT, C_NUMBER, DOUBLE_QUOTED, SINGLE_QUOTED, SLASH_COMMENT, WHITESPACE, words, } from "./shared.js";
3
+ const JS_KEYWORDS = [
4
+ 'as',
5
+ 'async',
6
+ 'await',
7
+ 'break',
8
+ 'case',
9
+ 'catch',
10
+ 'class',
11
+ 'const',
12
+ 'continue',
13
+ 'debugger',
14
+ 'default',
15
+ 'delete',
16
+ 'do',
17
+ 'else',
18
+ 'export',
19
+ 'extends',
20
+ 'finally',
21
+ 'for',
22
+ 'from',
23
+ 'function',
24
+ 'if',
25
+ 'import',
26
+ 'in',
27
+ 'instanceof',
28
+ 'let',
29
+ 'new',
30
+ 'of',
31
+ 'return',
32
+ 'static',
33
+ 'super',
34
+ 'switch',
35
+ 'this',
36
+ 'throw',
37
+ 'try',
38
+ 'typeof',
39
+ 'var',
40
+ 'void',
41
+ 'while',
42
+ 'with',
43
+ 'yield',
44
+ ];
45
+ const TS_KEYWORDS = [
46
+ 'abstract',
47
+ 'asserts',
48
+ 'declare',
49
+ 'enum',
50
+ 'implements',
51
+ 'infer',
52
+ 'interface',
53
+ 'is',
54
+ 'keyof',
55
+ 'module',
56
+ 'namespace',
57
+ 'override',
58
+ 'private',
59
+ 'protected',
60
+ 'public',
61
+ 'readonly',
62
+ 'satisfies',
63
+ 'type',
64
+ 'unique',
65
+ ];
66
+ const CONSTANTS = words('true', 'false', 'null', 'undefined', 'NaN', 'Infinity');
67
+ const TYPE_INTRODUCERS = words('class', 'interface', 'type', 'enum', 'extends', 'implements', 'new');
68
+ const FUNCTION_INTRODUCERS = words('function');
69
+ /** `` `…` ``, possibly across lines; `${…}` stays part of the string. */
70
+ const TEMPLATE = {
71
+ re: sticky(String.raw `\x60(?:[^\x60\\]|\\[\s\S]?)*(?:\x60|(?![\s\S]))`),
72
+ kind: 'string',
73
+ };
74
+ function grammar(name, keywords, types) {
75
+ const word = classifyWord({
76
+ keywords,
77
+ constants: CONSTANTS,
78
+ types,
79
+ typeIntroducers: TYPE_INTRODUCERS,
80
+ functionIntroducers: FUNCTION_INTRODUCERS,
81
+ });
82
+ const capitalizedTypes = name === 'ts';
83
+ return {
84
+ name,
85
+ start: 'code',
86
+ states: {
87
+ code: [
88
+ WHITESPACE,
89
+ SLASH_COMMENT,
90
+ BLOCK_COMMENT,
91
+ DOUBLE_QUOTED,
92
+ SINGLE_QUOTED,
93
+ TEMPLATE,
94
+ {
95
+ re: sticky(String.raw `[A-Za-z_$][\w$]*`),
96
+ kind: (text, ctx) => {
97
+ const kind = word(text, ctx);
98
+ // In TypeScript a capitalized name that is not called is usually a type.
99
+ if (kind === 'plain' && capitalizedTypes && /^[A-Z]/.test(text))
100
+ return 'type';
101
+ return kind;
102
+ },
103
+ },
104
+ C_NUMBER,
105
+ { re: sticky(String.raw `@[A-Za-z_$][\w$]*`), kind: 'attr' },
106
+ { re: sticky(String.raw `\?\.|[+\-*/%=!<>&|^~?:]+`), kind: 'operator' },
107
+ { re: sticky(String.raw `[{}()[\];,.]`), kind: 'punctuation' },
108
+ ],
109
+ },
110
+ };
111
+ }
112
+ export const javascriptGrammar = grammar('js', words(...JS_KEYWORDS), words());
113
+ export const typescriptGrammar = grammar('ts', words(...JS_KEYWORDS, ...TS_KEYWORDS), words('string', 'number', 'boolean', 'any', 'unknown', 'never', 'object', 'symbol', 'bigint'));
@@ -0,0 +1,3 @@
1
+ import { type Grammar } from '../tokenizer.js';
2
+ /** JSON, plus the comments JSONC allows. A string followed by `:` is a property. */
3
+ export declare const jsonGrammar: Grammar;
@@ -0,0 +1,24 @@
1
+ import { nextNonBlank, sticky } from "../tokenizer.js";
2
+ import { BLOCK_COMMENT, SLASH_COMMENT, WHITESPACE } from "./shared.js";
3
+ /** JSON, plus the comments JSONC allows. A string followed by `:` is a property. */
4
+ export const jsonGrammar = {
5
+ name: 'json',
6
+ start: 'value',
7
+ states: {
8
+ value: [
9
+ WHITESPACE,
10
+ SLASH_COMMENT,
11
+ BLOCK_COMMENT,
12
+ {
13
+ re: sticky(String.raw `"(?:[^"\\\n]|\\.?)*(?:"|$)`),
14
+ kind: (_text, ctx) => (nextNonBlank(ctx.input, ctx.end) === ':' ? 'property' : 'string'),
15
+ },
16
+ { re: sticky(String.raw `-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?`), kind: 'number' },
17
+ {
18
+ re: sticky(String.raw `[A-Za-z_]\w*`),
19
+ kind: (text) => text === 'true' || text === 'false' || text === 'null' ? 'constant' : 'plain',
20
+ },
21
+ { re: sticky(String.raw `[{}[\],:]`), kind: 'punctuation' },
22
+ ],
23
+ },
24
+ };
@@ -0,0 +1,3 @@
1
+ import { type Grammar } from '../tokenizer.js';
2
+ /** Python 3: triple-quoted and prefixed strings, decorators, keywords and builtins. */
3
+ export declare const pythonGrammar: Grammar;
@@ -0,0 +1,35 @@
1
+ import { classifyWord, sticky } from "../tokenizer.js";
2
+ import { C_NUMBER, HASH_COMMENT, WHITESPACE, words } from "./shared.js";
3
+ const word = classifyWord({
4
+ keywords: words('and', 'as', 'assert', 'async', 'await', 'break', 'case', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'match', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'),
5
+ constants: words('True', 'False', 'None', 'Ellipsis', 'NotImplemented'),
6
+ builtins: words('abs', 'all', 'any', 'bool', 'dict', 'enumerate', 'filter', 'float', 'int', 'isinstance', 'len', 'list', 'map', 'max', 'min', 'open', 'print', 'range', 'round', 'set', 'sorted', 'str', 'sum', 'super', 'tuple', 'type', 'zip'),
7
+ typeIntroducers: words('class'),
8
+ functionIntroducers: words('def'),
9
+ });
10
+ const PREFIX = '(?:[rRbBuUfF]{1,2})?';
11
+ /** Python 3: triple-quoted and prefixed strings, decorators, keywords and builtins. */
12
+ export const pythonGrammar = {
13
+ name: 'python',
14
+ start: 'code',
15
+ states: {
16
+ code: [
17
+ WHITESPACE,
18
+ HASH_COMMENT,
19
+ // Triple quotes may span lines; unterminated ones run to the end.
20
+ {
21
+ re: sticky(`${PREFIX}${String.raw `(?:"""[\s\S]*?(?:"""|(?![\s\S]))|'''[\s\S]*?(?:'''|(?![\s\S])))`}`),
22
+ kind: 'string',
23
+ },
24
+ {
25
+ re: sticky(`${PREFIX}${String.raw `(?:"(?:[^"\\\n]|\\.?)*(?:"|$)|'(?:[^'\\\n]|\\.?)*(?:'|$))`}`),
26
+ kind: 'string',
27
+ },
28
+ { re: sticky(String.raw `(?<=^[ \t]*)@[A-Za-z_][\w.]*`), kind: 'attr' },
29
+ { re: sticky(String.raw `[A-Za-z_]\w*`), kind: word },
30
+ C_NUMBER,
31
+ { re: sticky(String.raw `[+\-*/%=!<>&|^~:@]+`), kind: 'operator' },
32
+ { re: sticky(String.raw `[()[\]{},.;]`), kind: 'punctuation' },
33
+ ],
34
+ },
35
+ };
@@ -0,0 +1,22 @@
1
+ import { type GrammarRule } from '../tokenizer.js';
2
+ /**
3
+ * Rules several grammars share. Each opening delimiter always matches: an
4
+ * unterminated single-line string ends at its line break (`$` with the `m`
5
+ * flag), an unterminated block comment or multi-line string at the end of
6
+ * the input (`$` without it). See tokenizer.ts for why that keeps scanning
7
+ * linear.
8
+ */
9
+ export declare const WHITESPACE: GrammarRule;
10
+ /** `"…"` on one line, with backslash escapes. */
11
+ export declare const DOUBLE_QUOTED: GrammarRule;
12
+ /** `'…'` on one line, with backslash escapes. */
13
+ export declare const SINGLE_QUOTED: GrammarRule;
14
+ /** `/* … *\/`, possibly across lines. */
15
+ export declare const BLOCK_COMMENT: GrammarRule;
16
+ /** `// …` to the end of the line. */
17
+ export declare const SLASH_COMMENT: GrammarRule;
18
+ /** `# …` at a line start or after whitespace (not `$#` or `a#b`). */
19
+ export declare const HASH_COMMENT: GrammarRule;
20
+ /** Decimal, hex, octal and binary numbers with `_` separators and exponents. */
21
+ export declare const C_NUMBER: GrammarRule;
22
+ export declare const words: (...list: string[]) => ReadonlySet<string>;