typeglish 0.1.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 (51) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +13 -0
  3. package/README.md +301 -0
  4. package/dist/chunk-3NQ3VYO6.js +566 -0
  5. package/dist/chunk-3NQ3VYO6.js.map +1 -0
  6. package/dist/chunk-KRYC4OTL.js +3573 -0
  7. package/dist/chunk-KRYC4OTL.js.map +1 -0
  8. package/dist/chunk-NLQIL5WD.js +25 -0
  9. package/dist/chunk-NLQIL5WD.js.map +1 -0
  10. package/dist/chunk-PR4QN5HX.js +39 -0
  11. package/dist/chunk-PR4QN5HX.js.map +1 -0
  12. package/dist/chunk-PXAMTGYY.js +3 -0
  13. package/dist/chunk-PXAMTGYY.js.map +1 -0
  14. package/dist/chunk-VMACILYN.js +140 -0
  15. package/dist/chunk-VMACILYN.js.map +1 -0
  16. package/dist/chunk-Y64EAEYB.js +10919 -0
  17. package/dist/chunk-Y64EAEYB.js.map +1 -0
  18. package/dist/chunk-YH4ZLQ4G.js +4260 -0
  19. package/dist/chunk-YH4ZLQ4G.js.map +1 -0
  20. package/dist/chunk-ZKMHZHID.js +56 -0
  21. package/dist/chunk-ZKMHZHID.js.map +1 -0
  22. package/dist/cli.d.ts +1 -0
  23. package/dist/cli.js +447 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/compile-DViQS2oG.d.ts +310 -0
  26. package/dist/diagnostics-BWJ_oMd8.d.ts +49 -0
  27. package/dist/exhaustiveness-VBVWCX5W.js +123 -0
  28. package/dist/exhaustiveness-VBVWCX5W.js.map +1 -0
  29. package/dist/index-Df_QnTgq.d.ts +313 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.js +7 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/mcp.d.ts +11 -0
  34. package/dist/mcp.js +36378 -0
  35. package/dist/mcp.js.map +1 -0
  36. package/dist/monaco.css +46 -0
  37. package/dist/monaco.d.ts +43 -0
  38. package/dist/monaco.js +971 -0
  39. package/dist/monaco.js.map +1 -0
  40. package/dist/node.d.ts +21 -0
  41. package/dist/node.js +8 -0
  42. package/dist/node.js.map +1 -0
  43. package/dist/spell-node.d.ts +8 -0
  44. package/dist/spell-node.js +23 -0
  45. package/dist/spell-node.js.map +1 -0
  46. package/dist/spell.d.ts +18 -0
  47. package/dist/spell.js +4 -0
  48. package/dist/spell.js.map +1 -0
  49. package/dist/z3-MWU3GSVT.js +5 -0
  50. package/dist/z3-MWU3GSVT.js.map +1 -0
  51. package/package.json +160 -0
package/dist/monaco.js ADDED
@@ -0,0 +1,971 @@
1
+ import { OBLIGATE, PROHIBIT, compile, layoutColumns, INDENT_UNIT } from './chunk-KRYC4OTL.js';
2
+ export { compile } from './chunk-KRYC4OTL.js';
3
+ import { MANY_CLASS, NON_ACTION_LEADS, structure, COMPLETION_TRIGGERS, renumberSubSteps, BUILTIN_CONFIG_SCHEMA } from './chunk-YH4ZLQ4G.js';
4
+ import { keywordRegex, MODAL_KEYWORDS, CONTROL_KEYWORDS, BRANCH_KEYWORDS, DEFINITION_KEYWORDS, OPERATOR_KEYWORDS, copulaConnector, keywordAltCI, QUANTIFIER_KEYWORDS, QUANTIFIER_WORDS, NUMBER_WORDS, CARDINAL_QUANTITIES, COMPARISON_SYMBOLS, EXACTNESS_MARKERS, copulaAlternation, FREQUENCY_KEYWORDS, keywordAlt, COMPARISON_KEYWORDS, COMMAND_WORDS, TAG_NAME_SRC, isProseBlock, lineOrdinals } from './chunk-Y64EAEYB.js';
5
+ import './chunk-PR4QN5HX.js';
6
+
7
+ // src/core/semantic-tokens.ts
8
+ var SEM_TOKEN_TYPES = [
9
+ "directive",
10
+ // 0 $IMPORT/$CONFIG/$REQUIRE/$SWITCH … — import red
11
+ "keyword",
12
+ // 1 IF/WHEN/THEN — control purple
13
+ "modal",
14
+ // 2 MUST/NEVER/NOT — red
15
+ "operator",
16
+ // 3 IS/ARE/AND/OR/INCLUDING — cyan
17
+ "variable",
18
+ // 4 @{x} / $x — insertion blue
19
+ "section",
20
+ // 5 <tag> / @<x> — section blue
21
+ "tool",
22
+ // 6 @[x] — insertion blue
23
+ "comment",
24
+ // 7 // free comment — muted green
25
+ "string",
26
+ // 8 "…" literal + fenced code — orange
27
+ "heading",
28
+ // 9 # heading — section blue
29
+ "declaration",
30
+ // 10 a declared subject/owner/name/value — gold
31
+ "property",
32
+ // 11 a possessed property noun — muted gold
33
+ "annotation",
34
+ // 12 RETIRED from emission (kept for index stability) — @@ notes now emit 'comment': an annotation IS an attached comment
35
+ "list",
36
+ // 13 - * 1. list markers — grey
37
+ "link",
38
+ // 14 [text](href) — blue
39
+ "strong",
40
+ // 15 **bold**
41
+ "emphasis",
42
+ // 16 *italic*
43
+ "strike",
44
+ // 17 ~~struck~~
45
+ "code",
46
+ // 18 `inline code`
47
+ "markup",
48
+ // 19 the **, *, ~~, ` markers themselves — dim
49
+ "quantifier",
50
+ // 20 ALL/SOME/NO/ONLY/MOST + cardinal quantities (only one, many) — quantity green
51
+ "scaffold",
52
+ // 21 <$name> tags — control-plane, hidden from the MODEL (strip whole extent) — directive red
53
+ "literal",
54
+ // 22 <"name"> tags — literal zone, hidden from the CHECKER (verbatim body) — string orange
55
+ "defterm",
56
+ // 23 a definition entry's `term::` — the reference-table label, gold
57
+ "defbody",
58
+ // 24 a definition entry's body/continuations — one neutral colour (rendered, not authored)
59
+ "toolkey",
60
+ // 25 a $TOOL/$SERVICE body field key + its `::` — a record key, blue
61
+ "toolval"
62
+ // 26 a $TOOL/$SERVICE body value / free body line — one neutral colour, like defbody
63
+ ];
64
+ var TOKEN_CLASSIFICATION = {
65
+ directive: { base: "macro", modifier: "directive" },
66
+ // $-commands read as preprocessor abroad
67
+ keyword: { base: "keyword", modifier: null },
68
+ modal: { base: "keyword", modifier: "modal" },
69
+ operator: { base: "operator", modifier: null },
70
+ variable: { base: "variable", modifier: "interpolation" },
71
+ section: { base: "namespace", modifier: "section" },
72
+ // a section is a named container
73
+ tool: { base: "function", modifier: "tool" },
74
+ // a tool is callable
75
+ comment: { base: "comment", modifier: null },
76
+ string: { base: "string", modifier: null },
77
+ heading: { base: "namespace", modifier: "heading" },
78
+ declaration: { base: "variable", modifier: "declaration" },
79
+ // 'declaration' is a STANDARD modifier
80
+ property: { base: "property", modifier: null },
81
+ annotation: { base: "comment", modifier: "annotation" },
82
+ // retired from emission
83
+ list: { base: "list", modifier: null },
84
+ // graceful silence — plain markers abroad
85
+ link: { base: "link", modifier: null },
86
+ // graceful silence
87
+ strong: { base: "strong", modifier: null },
88
+ // graceful silence (style-only)
89
+ emphasis: { base: "emphasis", modifier: null },
90
+ strike: { base: "strike", modifier: null },
91
+ code: { base: "code", modifier: null },
92
+ markup: { base: "markup", modifier: null },
93
+ quantifier: { base: "keyword", modifier: "quantifier" },
94
+ scaffold: { base: "macro", modifier: "scaffold" },
95
+ literal: { base: "string", modifier: "literalZone" },
96
+ defterm: { base: "property", modifier: "defterm" },
97
+ defbody: { base: "defbody", modifier: null },
98
+ // graceful silence — a plain body abroad is right
99
+ toolkey: { base: "property", modifier: "toolkey" },
100
+ toolval: { base: "toolval", modifier: null }
101
+ // graceful silence
102
+ };
103
+ var SEM_LEGEND = (() => {
104
+ const tokenTypes = [];
105
+ const tokenModifiers = [];
106
+ for (const t of SEM_TOKEN_TYPES) {
107
+ const c = TOKEN_CLASSIFICATION[t];
108
+ if (!tokenTypes.includes(c.base)) tokenTypes.push(c.base);
109
+ if (c.modifier !== null && !tokenModifiers.includes(c.modifier)) tokenModifiers.push(c.modifier);
110
+ }
111
+ return { tokenTypes, tokenModifiers };
112
+ })();
113
+ keywordRegex(MODAL_KEYWORDS);
114
+ keywordRegex([...CONTROL_KEYWORDS, ...BRANCH_KEYWORDS, ...DEFINITION_KEYWORDS]);
115
+ keywordRegex(OPERATOR_KEYWORDS);
116
+ new RegExp(`(?<!\\b(?:${keywordAltCI(QUANTIFIER_KEYWORDS)})\\s)\\b(?![Tt]here\\b)([A-Za-z][A-Za-z0-9_]*)(${copulaConnector}\\b)`);
117
+ keywordAltCI(QUANTIFIER_WORDS.filter((q) => q.kind !== "exclusive").flatMap((q) => q.words));
118
+ keywordAltCI(QUANTIFIER_WORDS.filter((q) => q.kind === "exclusive").flatMap((q) => q.words));
119
+ var CLAUSE_LEAD = `^\\s*(?:[-*+]\\s+|\\d+[.)]\\s+)?|\\b${keywordAltCI(["THEN"])}\\s+`;
120
+ var NUM_ALT = `(?:${Object.keys(NUMBER_WORDS).map((w) => keywordAltCI([w])).join("|")}|\\d+)`;
121
+ var CARD_FIXED_ALT = [...CARDINAL_QUANTITIES].sort((a, b) => b.phrase.length - a.phrase.length).map((q) => keywordAltCI([q.phrase])).join("|");
122
+ var BOUND_ALT = COMPARISON_SYMBOLS.filter((c) => c.bound !== void 0).map((c) => keywordAltCI([c.bound])).join("|");
123
+ var CARD_QUANTITY = `(?:(?:${keywordAltCI([...EXACTNESS_MARKERS])})\\s+${NUM_ALT}|(?:${BOUND_ALT})\\s+${NUM_ALT}|${CARD_FIXED_ALT}|${NUM_ALT})`;
124
+ [new RegExp(`(\\b${keywordAltCI(["THERE"])}\\s+(?:${keywordAltCI(["IS", "ARE", "WAS", "WERE", "EXISTS", "EXIST"])})\\s+)(${CARD_QUANTITY})(?=\\s+[A-Za-z])`), ["", "quantifier"]];
125
+ var CARD_FIXED_HAVE_ALT = [...CARDINAL_QUANTITIES].filter((q) => q.phrase !== "a" && q.phrase !== "an").sort((a, b) => b.phrase.length - a.phrase.length).map((q) => keywordAltCI([q.phrase])).join("|");
126
+ var CARD_QUANTITY_HAVE = `(?:(?:${keywordAltCI([...EXACTNESS_MARKERS])})\\s+${NUM_ALT}|(?:${BOUND_ALT})\\s+${NUM_ALT}|${CARD_FIXED_HAVE_ALT}|${NUM_ALT})`;
127
+ [new RegExp(`(\\b(?:${keywordAltCI(["HAS", "HAVE"])})\\s+)(${CARD_QUANTITY_HAVE})(?=\\s+[A-Za-z])`), ["", "quantifier"]];
128
+ var SUBJ_ABSTAIN_1 = `(?<!\\b(?:${keywordAltCI(QUANTIFIER_KEYWORDS)}|${NUM_ALT})\\s)`;
129
+ var SUBJ_ABSTAIN_2 = `(?<!\\b(?:${keywordAltCI(QUANTIFIER_KEYWORDS)}|${NUM_ALT})\\s[A-Za-z][A-Za-z0-9_]*\\s)`;
130
+ var MANY_ALT = MANY_CLASS.map((w) => keywordAltCI([w])).join("|");
131
+ var NUM_GE2_ALT = `(?:${Object.entries(NUMBER_WORDS).filter(([, n]) => n >= 2).map(([w]) => keywordAltCI([w])).join("|")}|[2-9]|[1-9]\\d+)`;
132
+ [new RegExp(`${SUBJ_ABSTAIN_1}${SUBJ_ABSTAIN_2}\\b((?:${copulaAlternation})\\s+)(${keywordAltCI(["THE"])}\\s+${keywordAltCI(["ONLY"])})(?=\\s+[A-Za-z])`), ["", "quantifier"]];
133
+ [new RegExp(`${SUBJ_ABSTAIN_1}${SUBJ_ABSTAIN_2}\\b((?:${copulaAlternation})\\s+)(${keywordAltCI(["ONE"])}\\s+${keywordAltCI(["OF"])}\\s+(?:${keywordAltCI(["THE"])}\\s+)?(?:${MANY_ALT}|${NUM_GE2_ALT}))(?=\\s+[A-Za-z])`), ["", "quantifier"]];
134
+ var ACTION_VERB_EXCL = [
135
+ ...NON_ACTION_LEADS,
136
+ ...QUANTIFIER_KEYWORDS.map((w) => w.toLowerCase()),
137
+ ...Object.keys(NUMBER_WORDS),
138
+ ...EXACTNESS_MARKERS.map((w) => w.toLowerCase()),
139
+ ...CARDINAL_QUANTITIES.map((q) => q.phrase.split(" ")[0] ?? ""),
140
+ ...[...OBLIGATE, ...PROHIBIT].map((w) => (w.split(" ")[0] ?? "").toLowerCase())
141
+ ].filter((w) => w !== "");
142
+ var ACTION_VERB = `(?!(?:${[...new Set(ACTION_VERB_EXCL)].map((w) => keywordAltCI([w])).join("|")})\\b)[A-Za-z][A-Za-z-]*`;
143
+ var OBLIGATE_ALT = OBLIGATE.map((w) => keywordAltCI([w])).join("|");
144
+ [new RegExp(`((?:${OBLIGATE_ALT})\\s+(?!${keywordAltCI(["NOT"])}\\b)${ACTION_VERB}\\s+)(${CARD_QUANTITY_HAVE})(?=\\s+[A-Za-z])`), ["", "quantifier"]];
145
+ var FREQ_COLOR_ALT = FREQUENCY_KEYWORDS.map((w) => keywordAltCI([w])).join("|");
146
+ [new RegExp(`((?:${CLAUSE_LEAD})(?:[Yy]ou\\s+)?|(?:${keywordAlt(MODAL_KEYWORDS)})\\s+(?:${keywordAltCI(["NOT"])}\\s+)?)(${FREQ_COLOR_ALT})\\b(?=,?\\s+[A-Za-z])`), ["", "quantifier"]];
147
+ new RegExp(`\\b((?!(?:${keywordAltCI([...BRANCH_KEYWORDS, ...CONTROL_KEYWORDS])})\\b)[A-Za-z][A-Za-z0-9_]*)(\\s+(?:${keywordAlt(MODAL_KEYWORDS)})\\b)`);
148
+ [new RegExp(`(@\\{[A-Za-z0-9_.]+\\})(\\s+)(${keywordAlt(COMPARISON_KEYWORDS)})\\b`), ["variable", "", "operator"]];
149
+ new Map(SEM_LEGEND.tokenTypes.map((t, i) => [t, i]));
150
+ new Map(SEM_LEGEND.tokenModifiers.map((m, i) => [m, 1 << i]));
151
+
152
+ // src/core/editor-config.ts
153
+ var COMMENT_SYNTAX = { line: "//", block: ["/*", "*/"] };
154
+ var COLORIZED_BRACKET_PAIRS = [];
155
+ var OPEN_TAG_LINE_SRC = `^\\s*<${TAG_NAME_SRC}(\\s[^>]*)?>\\s*(\\/\\/.*)?$`;
156
+ var CLOSE_TAG_LINE_SRC = `^\\s*<\\/${TAG_NAME_SRC}>\\s*(\\/\\/.*)?$`;
157
+ var AUTO_CLOSE_TAG_SRC = `^\\s*<(${TAG_NAME_SRC})>$`;
158
+ var INDENT_OPENERS_SRC = `^\\s*(?:<${TAG_NAME_SRC}(?:\\s[^>]*)?>|\\$(?:ELSE\\s+)?IF\\s+[^:]*:|\\$ELSE\\s*:|\\$(?:TOOL|SERVICE)\\s+[a-z][a-z0-9_]*|\\$TEST\\b[^:]*:\\s*"[^"]*")\\s*(\\/\\/.*)?$`;
159
+ var TOKEN_PALETTE = {
160
+ directive: { fg: "ff7b72", bold: true },
161
+ // $IMPORT/$CONFIG/$REQUIRE — import red
162
+ keyword: { fg: "c586c0", bold: true },
163
+ // IF/WHEN/THEN — control purple
164
+ modal: { fg: "ff7b72", bold: true },
165
+ // MUST/NEVER/NOT — red
166
+ operator: { fg: "56b6c2" },
167
+ // IS/ARE/AND/OR/INCLUDING — cyan
168
+ variable: { fg: "79c0ff" },
169
+ // @{x} / $x — insertion blue
170
+ section: { fg: "58a6ff", bold: true },
171
+ // <tag> / @<x> — section blue
172
+ tool: { fg: "79c0ff" },
173
+ // @[x] — insertion blue
174
+ comment: { fg: "6b8f71", italic: true },
175
+ // // comment AND @@ annotation — muted green
176
+ string: { fg: "ffa657" },
177
+ // "…" literal + fenced code — orange
178
+ heading: { fg: "58a6ff", bold: true },
179
+ // # heading — section blue
180
+ declaration: { fg: "e3b341", bold: true },
181
+ // a declared subject/owner/name/value — gold
182
+ property: { fg: "c9a86a" },
183
+ // a possessed property noun — muted gold
184
+ annotation: { fg: "6b8f71", italic: true },
185
+ // RETIRED from emission — kept for legend index stability
186
+ list: { fg: "8b949e" },
187
+ // - * 1. list markers — grey
188
+ link: { fg: "4493f8" },
189
+ // [text](href)
190
+ strong: { bold: true },
191
+ // **bold** — content bold, colour kept
192
+ emphasis: { italic: true },
193
+ // *italic*
194
+ strike: { fg: "8b949e", strikethrough: true },
195
+ // ~~struck~~
196
+ code: { fg: "79c0ff" },
197
+ // `inline code`
198
+ markup: { fg: "6e7681" },
199
+ // the **, *, ~~, ` markers — dim so content pops
200
+ quantifier: { fg: "7ee787", bold: true },
201
+ // ALL/SOME/NO/ONLY/MOST — quantity green
202
+ scaffold: { fg: "ff7b72", bold: true },
203
+ // <$name> tags — control-plane, $-family red
204
+ literal: { fg: "ffa657", bold: true },
205
+ // <"name"> tags — literal zone, quote-family orange
206
+ defterm: { fg: "e3b341", bold: true },
207
+ // a definition `term::` — the reference-table label, gold
208
+ defbody: { fg: "a8b3bd" },
209
+ // a definition body — one neutral colour
210
+ toolkey: { fg: "79c0ff", bold: true },
211
+ // a $TOOL/$SERVICE field key — a record key, blue
212
+ toolval: { fg: "a8b3bd" }
213
+ // a $TOOL/$SERVICE value — neutral, like defbody
214
+ };
215
+ var EDITOR_CHROME = {
216
+ "editor.background": "#0d1117",
217
+ "editor.foreground": "#e6edf3",
218
+ "editorLineNumber.foreground": "#6e7681",
219
+ "editorLineNumber.activeForeground": "#e6edf3",
220
+ "editor.lineHighlightBackground": "#161b22",
221
+ "editorGutter.background": "#0d1117",
222
+ "editorIndentGuide.background1": "#21262d",
223
+ "editorWidget.background": "#161b22",
224
+ "editorWidget.border": "#2a3340",
225
+ "editorHoverWidget.background": "#161b22",
226
+ "editorHoverWidget.border": "#2a3340",
227
+ // Suggest (autocomplete) dropdown. Without these it inherits a background ~9 RGB points off the
228
+ // editor's (#161b22 vs #0d1117) with no border or shadow, so it blends into the text and reads as
229
+ // "cut off." Give it an elevated surface, a clear border, an accent-filled selection, and a real
230
+ // drop shadow so it reads as a floating box.
231
+ "editorSuggestWidget.background": "#1c2330",
232
+ "editorSuggestWidget.border": "#3d4a5c",
233
+ "editorSuggestWidget.foreground": "#e6edf3",
234
+ "editorSuggestWidget.selectedBackground": "#1f6feb",
235
+ "editorSuggestWidget.selectedForeground": "#ffffff",
236
+ "editorSuggestWidget.highlightForeground": "#79c0ff",
237
+ "editorSuggestWidget.focusHighlightForeground": "#cae8ff",
238
+ "widget.shadow": "#00000088"
239
+ };
240
+
241
+ // src/web/blocks.ts
242
+ var BLOCK_TYPES = {
243
+ role: {
244
+ label: "Role",
245
+ does: "Sets the agent's persona and purpose.",
246
+ doesNot: "Hold rules or steps \u2014 put those in Constraints or Process.",
247
+ bodyShape: "prose",
248
+ unit: "line",
249
+ canHaveChildren: false,
250
+ accent: "var(--v-role)"
251
+ },
252
+ constraints: {
253
+ label: "Constraints",
254
+ does: "Testable rules the model must follow \u2014 one per line.",
255
+ doesNot: "Describe persona or sequence.",
256
+ bodyShape: "rules",
257
+ unit: "rule",
258
+ canHaveChildren: true,
259
+ accent: "var(--v-prohibition)"
260
+ },
261
+ process: {
262
+ label: "Process",
263
+ does: "Ordered steps the agent works through.",
264
+ doesNot: "Hold standalone rules.",
265
+ bodyShape: "steps",
266
+ unit: "step",
267
+ canHaveChildren: true,
268
+ accent: "var(--v-conditional)"
269
+ },
270
+ examples: {
271
+ label: "Examples",
272
+ does: "Few-shot examples that show the desired behaviour.",
273
+ doesNot: "State rules \u2014 show, don't tell.",
274
+ bodyShape: "pairs",
275
+ unit: "line",
276
+ canHaveChildren: true,
277
+ accent: "var(--v-example)"
278
+ },
279
+ output: {
280
+ label: "Output",
281
+ does: "The required output format or shape.",
282
+ doesNot: "Hold persona or rules.",
283
+ bodyShape: "spec",
284
+ unit: "line",
285
+ canHaveChildren: false,
286
+ accent: "var(--v-format)"
287
+ },
288
+ tone: {
289
+ label: "Tone",
290
+ does: "Voice and writing style.",
291
+ doesNot: "Hold rules or steps.",
292
+ bodyShape: "prose",
293
+ unit: "line",
294
+ canHaveChildren: false,
295
+ accent: "var(--v-directive)"
296
+ },
297
+ prose: {
298
+ label: "Prose",
299
+ does: "Free-form text \u2014 the escape hatch.",
300
+ doesNot: "Get analysed or measured structurally.",
301
+ bodyShape: "prose",
302
+ unit: "line",
303
+ canHaveChildren: false,
304
+ accent: "var(--inert)"
305
+ },
306
+ comment: {
307
+ label: "Comment",
308
+ does: "A note for authors.",
309
+ doesNot: "Ever reach the model.",
310
+ bodyShape: "note",
311
+ unit: "line",
312
+ canHaveChildren: false,
313
+ accent: "var(--comment)"
314
+ }
315
+ };
316
+
317
+ // src/core/profile.ts
318
+ function profileHoverMarkdown(info) {
319
+ const rows = [];
320
+ if (info.residual !== void 0)
321
+ ;
322
+ if (info.coveredBy)
323
+ ;
324
+ if (info.cases) ;
325
+ else if (info.isHardRule)
326
+ ;
327
+ if (info.delta)
328
+ ;
329
+ if (rows.length === 0) return null;
330
+ return `**statement profile** \u2014 what the compiler has measured about this statement:
331
+
332
+ - ${rows.join("\n- ")}`;
333
+ }
334
+
335
+ // src/web/lsp-client.ts
336
+ var worker = null;
337
+ var nextId = 1;
338
+ var pending = /* @__PURE__ */ new Map();
339
+ var readyCallbacks = /* @__PURE__ */ new Set();
340
+ function getWorker() {
341
+ if (!worker) {
342
+ worker = new Worker(new URL("./lsp-worker.ts", import.meta.url), { type: "module" });
343
+ worker.onmessage = (e) => {
344
+ const msg = e.data;
345
+ if ("notification" in msg) {
346
+ if (msg.notification === "dictionaryReady") for (const cb of readyCallbacks) cb();
347
+ return;
348
+ }
349
+ const resolve = pending.get(msg.id);
350
+ if (resolve) {
351
+ pending.delete(msg.id);
352
+ resolve(msg.result);
353
+ }
354
+ };
355
+ }
356
+ return worker;
357
+ }
358
+ if (import.meta.hot) {
359
+ import.meta.hot.on("vite:beforeUpdate", () => {
360
+ worker?.terminate();
361
+ worker = null;
362
+ pending.clear();
363
+ });
364
+ }
365
+ function send(req) {
366
+ const id = nextId++;
367
+ return new Promise((resolve) => {
368
+ pending.set(id, resolve);
369
+ getWorker().postMessage({ ...req, id });
370
+ });
371
+ }
372
+ function requestCompletion(before, source, line, schema) {
373
+ return send({ kind: "completion", before, source, line, schema });
374
+ }
375
+ function requestHover(source, line, character) {
376
+ return send({ kind: "hover", source, line, character });
377
+ }
378
+ function requestDefinition(source, line, character) {
379
+ return send({ kind: "definition", source, line, character });
380
+ }
381
+ function requestSemanticTokens(source) {
382
+ return send({ kind: "semanticTokens", source });
383
+ }
384
+ function requestDocumentSymbols(source) {
385
+ return send({ kind: "documentSymbol", source });
386
+ }
387
+ function requestFoldingRanges(source) {
388
+ return send({ kind: "foldingRanges", source });
389
+ }
390
+ function requestLinkedEdit(source, line) {
391
+ return send({ kind: "linkedEdit", source, line });
392
+ }
393
+
394
+ // src/web/monaco-setup.ts
395
+ var LANG_ID = "tg";
396
+ var FILE_EXT = ".tg";
397
+ var THEME_ID = "typeglish-dark";
398
+ var profileFn = null;
399
+ var configSchemaCtx = BUILTIN_CONFIG_SCHEMA;
400
+ function profileMarkdown(line0) {
401
+ const info = profileFn?.(line0);
402
+ return info ? profileHoverMarkdown(info) : null;
403
+ }
404
+ function inferBlockType(label) {
405
+ const norm = label.trim().toLowerCase();
406
+ for (const key of Object.keys(BLOCK_TYPES)) {
407
+ if (BLOCK_TYPES[key].label.toLowerCase() === norm) return key;
408
+ }
409
+ return null;
410
+ }
411
+ function setupMonaco(monaco) {
412
+ const alreadyRegistered = monaco.languages.getLanguages().some((l) => l.id === LANG_ID);
413
+ if (!alreadyRegistered) {
414
+ monaco.languages.register({ id: LANG_ID, extensions: [FILE_EXT], aliases: ["TypeGlish", "tg"] });
415
+ }
416
+ const OPEN_TAG = new RegExp(OPEN_TAG_LINE_SRC, "i");
417
+ monaco.languages.setLanguageConfiguration(LANG_ID, {
418
+ // `//` and `/* … */` — enables the editor's native toggle-comment on `.tg`.
419
+ comments: { lineComment: COMMENT_SYNTAX.line, blockComment: COMMENT_SYNTAX.block },
420
+ // NO colorized bracket pairs — the switch that actually disables bracket-pair colorization (the
421
+ // editor option is unreliably honoured). Brackets are prose punctuation, pointer-token interiors,
422
+ // or neutral definition-body text — never pairs to rainbow by nesting depth.
423
+ colorizedBracketPairs: COLORIZED_BRACKET_PAIRS,
424
+ indentationRules: {
425
+ increaseIndentPattern: new RegExp(INDENT_OPENERS_SRC, "i"),
426
+ decreaseIndentPattern: new RegExp(CLOSE_TAG_LINE_SRC, "i")
427
+ },
428
+ onEnterRules: [
429
+ {
430
+ beforeText: OPEN_TAG,
431
+ action: { indentAction: monaco.languages.IndentAction.Indent }
432
+ }
433
+ ]
434
+ });
435
+ const theme = {
436
+ base: "vs-dark",
437
+ inherit: true,
438
+ // One rule per token type — DERIVED, never authored here: the classification (semantic-tokens.ts)
439
+ // says how each type travels on the wire (`base.modifier`), the palette (editor-config.ts) says how
440
+ // it paints. This file only assembles the two SSOTs, so the exact palette lands wherever our theme
441
+ // is installed while a foreign editor's theme colours the standard bases natively.
442
+ rules: SEM_TOKEN_TYPES.map((t) => {
443
+ const c = TOKEN_CLASSIFICATION[t];
444
+ const p = TOKEN_PALETTE[t];
445
+ const fontStyle = [p.bold === true ? "bold" : null, p.italic === true ? "italic" : null, p.strikethrough === true ? "strikethrough" : null].filter((s) => s !== null).join(" ");
446
+ return {
447
+ token: c.modifier !== null ? `${c.base}.${c.modifier}` : c.base,
448
+ ...p.fg !== void 0 ? { foreground: p.fg } : {},
449
+ ...fontStyle !== "" ? { fontStyle } : {}
450
+ };
451
+ }),
452
+ // The chrome (surfaces, gutter, widgets) is editor-config's — the same table a VS Code theme
453
+ // generator would read, so the playground and any generated theme can never disagree.
454
+ colors: EDITOR_CHROME
455
+ };
456
+ monaco.editor.defineTheme(THEME_ID, theme);
457
+ if (alreadyRegistered) return;
458
+ monaco.languages.registerFoldingRangeProvider(LANG_ID, {
459
+ async provideFoldingRanges(model) {
460
+ return await requestFoldingRanges(model.getValue());
461
+ }
462
+ });
463
+ monaco.languages.registerLinkedEditingRangeProvider(LANG_ID, {
464
+ async provideLinkedEditingRanges(model, position) {
465
+ const spans = await requestLinkedEdit(model.getValue(), position.lineNumber - 1);
466
+ if (!spans) return null;
467
+ const toRange = (s) => new monaco.Range(s.line + 1, s.start + 1, s.line + 1, s.end + 1);
468
+ return { ranges: [toRange(spans.open), toRange(spans.close)], wordPattern: /[a-z][a-z0-9_]*/i };
469
+ }
470
+ });
471
+ monaco.languages.registerDocumentSymbolProvider(LANG_ID, {
472
+ async provideDocumentSymbols(model) {
473
+ const lineCount = model.getLineCount();
474
+ const toSymbol = (n) => {
475
+ const start = Math.min(n.line + 1, lineCount);
476
+ const end = Math.min(Math.max(n.endLine, start), lineCount);
477
+ const display = n.name.startsWith("#") ? n.name.replace(/^#+\s*/, "") : n.tag;
478
+ return {
479
+ name: display || n.tag,
480
+ detail: "",
481
+ kind: monaco.languages.SymbolKind.Namespace,
482
+ tags: [],
483
+ range: new monaco.Range(start, 1, end, model.getLineMaxColumn(end)),
484
+ selectionRange: new monaco.Range(start, 1, start, model.getLineMaxColumn(start)),
485
+ children: n.children.map(toSymbol)
486
+ };
487
+ };
488
+ const nodes = await requestDocumentSymbols(model.getValue());
489
+ return nodes.map(toSymbol);
490
+ }
491
+ });
492
+ monaco.languages.registerDefinitionProvider(LANG_ID, {
493
+ async provideDefinition(model, position) {
494
+ const loc = await requestDefinition(model.getValue(), position.lineNumber - 1, position.column - 1);
495
+ if (!loc) return null;
496
+ const tl = loc.line + 1;
497
+ return { uri: model.uri, range: new monaco.Range(tl, 1, tl, model.getLineMaxColumn(tl)) };
498
+ }
499
+ });
500
+ monaco.languages.registerHoverProvider(LANG_ID, {
501
+ async provideHover(model, position) {
502
+ const line = model.getLineContent(position.lineNumber);
503
+ const profile = profileMarkdown(position.lineNumber - 1);
504
+ const h = line.match(/^#{1,6}\s+(.+?)\s*$/);
505
+ if (h) {
506
+ const type = inferBlockType(h[1] ?? "");
507
+ if (type) {
508
+ const def = BLOCK_TYPES[type];
509
+ return { contents: [{ value: `**${def.label} block**` }, { value: `**Does:** ${def.does}` }, { value: `**Doesn't:** ${def.doesNot}` }] };
510
+ }
511
+ return { contents: [{ value: "**Section**" }] };
512
+ }
513
+ if (/^\s*\/\//.test(line) || /^\s*\/\*/.test(line)) {
514
+ return { contents: [{ value: "Comment \u2014 never sent to the model." }] };
515
+ }
516
+ const md = await requestHover(model.getValue(), position.lineNumber - 1, position.column - 1);
517
+ if (md) return { contents: [{ value: md }, ...profile ? [{ value: profile }] : []] };
518
+ if (profile) return { contents: [{ value: profile }] };
519
+ return null;
520
+ }
521
+ });
522
+ monaco.languages.registerDocumentSemanticTokensProvider(LANG_ID, {
523
+ getLegend: () => ({ tokenTypes: [...SEM_LEGEND.tokenTypes], tokenModifiers: [...SEM_LEGEND.tokenModifiers] }),
524
+ provideDocumentSemanticTokens: async (model) => {
525
+ const data = await requestSemanticTokens(model.getValue());
526
+ return { data: new Uint32Array(data) };
527
+ },
528
+ releaseDocumentSemanticTokens: () => void 0
529
+ });
530
+ const KIND = {
531
+ section: monaco.languages.CompletionItemKind.Module,
532
+ variable: monaco.languages.CompletionItemKind.Variable,
533
+ step: monaco.languages.CompletionItemKind.Reference,
534
+ route: monaco.languages.CompletionItemKind.Reference,
535
+ tool: monaco.languages.CompletionItemKind.Function,
536
+ alias: monaco.languages.CompletionItemKind.Reference,
537
+ // a `@@ name:` statement alias — a named pointer, like a step/route
538
+ keyword: monaco.languages.CompletionItemKind.Keyword
539
+ };
540
+ const SNIPPET = monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet;
541
+ monaco.languages.registerCompletionItemProvider(LANG_ID, {
542
+ // The trigger set is the SHARED source of truth (COMPLETION_TRIGGERS) — the LSP uses the same list, so the
543
+ // web preview and every IDE auto-open completions identically. Space/colon open the value pickers
544
+ // (`$CONFIG modality ␣`, `$REQUIRE variable x:`); safe because completionsAt is context-gated (no rule → []).
545
+ triggerCharacters: [...COMPLETION_TRIGGERS],
546
+ async provideCompletionItems(model, position) {
547
+ const before = model.getValueInRange({ startLineNumber: position.lineNumber, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column });
548
+ const struct = await requestCompletion(before, model.getValue(), position.lineNumber - 1, configSchemaCtx);
549
+ return {
550
+ suggestions: struct.map((c) => ({
551
+ label: c.label,
552
+ kind: KIND[c.kind],
553
+ insertText: c.insert,
554
+ detail: c.detail,
555
+ range: new monaco.Range(position.lineNumber, position.column - c.replace, position.lineNumber, position.column),
556
+ ...c.snippet ? { insertTextRules: SNIPPET } : {}
557
+ }))
558
+ };
559
+ }
560
+ });
561
+ }
562
+
563
+ // src/web/operators.ts
564
+ var COMMAND_FORMS = [...COMMAND_WORDS].sort((a, b) => b.length - a.length);
565
+ var MARKER_RE = /^(\s*(?:[-*+]\s+|\d+(?:\.\d+)*[.)]\s+)?)([\s\S]*)$/;
566
+ function splitMarker(line) {
567
+ const m = line.match(MARKER_RE);
568
+ return { prefix: m?.[1] ?? "", clause: m?.[2] ?? line };
569
+ }
570
+ function nextListItem(lineText) {
571
+ const unordered = lineText.match(/^(\s*)([-*+])\s+(.*)$/);
572
+ const step = lineText.match(/^(\s*)(\d+(?:\.\d+)*)([.)])\s+(.*)$/);
573
+ if (!unordered && !step) return null;
574
+ const content = unordered?.[3] ?? step?.[4] ?? "";
575
+ if (content.trim() === "") return { terminate: true };
576
+ const indent = unordered?.[1] ?? step?.[1] ?? "";
577
+ if (unordered) return { terminate: false, prefix: `${indent}${unordered[2] ?? "-"} ` };
578
+ const segs = (step?.[2] ?? "0").split(".");
579
+ segs[segs.length - 1] = String(Number(segs[segs.length - 1]) + 1);
580
+ return { terminate: false, prefix: `${indent}${segs.join(".")}${step?.[3] ?? "."} ` };
581
+ }
582
+ function nestStep(lines, line0, outdent) {
583
+ const cur = (lines[line0] ?? "").match(/^(\s*)(\d+(?:\.\d+)*)([.)])(?:\s.*)?$/);
584
+ if (!cur) return null;
585
+ const ord = cur[2] ?? "";
586
+ const delim = cur[3] ?? ".";
587
+ const segs = ord.split(".").map(Number);
588
+ const start = (cur[1] ?? "").length;
589
+ const end = start + ord.length + delim.length;
590
+ if (outdent) {
591
+ if (segs.length === 1) return null;
592
+ const up = segs.slice(0, -1);
593
+ up[up.length - 1] = (up[up.length - 1] ?? 0) + 1;
594
+ return { start, end, text: `${up.join(".")}${delim}` };
595
+ }
596
+ const depth = segs.length;
597
+ let parent = null;
598
+ for (let i = line0 - 1; i >= 0; i -= 1) {
599
+ const t = (lines[i] ?? "").trim();
600
+ if (/^#{1,6}\s/.test(t)) return null;
601
+ const m = t.match(/^(\d+(?:\.\d+)*)[.)]\s/);
602
+ if (!m) continue;
603
+ const d = (m[1] ?? "").split(".").length;
604
+ if (d === depth) {
605
+ parent = m[1] ?? "";
606
+ break;
607
+ }
608
+ if (d < depth) return null;
609
+ }
610
+ if (parent === null) return null;
611
+ const childRe = new RegExp(`^${parent.replace(/\./g, "\\.")}\\.\\d+[.)]\\s`);
612
+ let kids = 0;
613
+ for (let i = line0 - 1; i >= 0; i -= 1) {
614
+ const t = (lines[i] ?? "").trim();
615
+ if (/^#{1,6}\s/.test(t)) break;
616
+ if (childRe.test(t)) kids += 1;
617
+ }
618
+ return { start, end, text: `${parent}.${kids + 1}${delim}` };
619
+ }
620
+ function matchLeadingCommand(clause) {
621
+ if (!clause.startsWith("$")) return null;
622
+ const body = clause.slice(1);
623
+ for (const word of COMMAND_FORMS) {
624
+ if (body.length < word.length) continue;
625
+ if (body.slice(0, word.length).toUpperCase() !== word) continue;
626
+ const next = body[word.length];
627
+ if (next === void 0 || /\s/.test(next) || next === ":") return { len: word.length + 1, upper: `$${word}` };
628
+ }
629
+ return null;
630
+ }
631
+ function enclosingBlock(lines, idx) {
632
+ for (let i = Math.min(idx, lines.length) - 1; i >= 0; i -= 1) {
633
+ const m = (lines[i] ?? "").match(/^#{1,6}\s+(.+?)\s*$/);
634
+ if (m) return m[1] ?? "";
635
+ }
636
+ return "";
637
+ }
638
+ function autoCloseSectionTag(head, tail) {
639
+ if (tail.trim() !== "") return null;
640
+ const m = head.match(new RegExp(AUTO_CLOSE_TAG_SRC, "i"));
641
+ return m ? { tag: m[1] ?? "" } : null;
642
+ }
643
+
644
+ // src/lib/monaco.ts
645
+ function setupTypeGlish(monaco) {
646
+ setupMonaco(monaco);
647
+ }
648
+ function applyDiagnostics(monaco, model, compileOptions) {
649
+ const sev = monaco.MarkerSeverity;
650
+ monaco.editor.setModelMarkers(
651
+ model,
652
+ LANG_ID,
653
+ compile(model.getValue(), compileOptions).diagnostics.map((d) => ({
654
+ startLineNumber: d.line + 1,
655
+ startColumn: d.start + 1,
656
+ endLineNumber: d.line + 1,
657
+ endColumn: d.end + 1,
658
+ message: d.message,
659
+ source: d.source,
660
+ severity: d.severity === "error" ? sev.Error : d.severity === "warn" ? sev.Warning : sev.Info
661
+ }))
662
+ );
663
+ }
664
+ function attachTypeGlish(monaco, editor, opts = {}) {
665
+ const subs = [];
666
+ const structDecos = editor.createDecorationsCollection([]);
667
+ if (opts.numberBlankLines !== true) {
668
+ let ordinalKey = "";
669
+ const applyLineOrdinals = () => {
670
+ const model = editor.getModel();
671
+ if (!model) return;
672
+ const ords = lineOrdinals(model.getLinesContent());
673
+ const ordinals = ["", ...ords.map((o) => o === null ? "" : String(o))];
674
+ const key = ords.map((o) => o === null ? "0" : "1").join("");
675
+ if (key === ordinalKey) return;
676
+ ordinalKey = key;
677
+ editor.updateOptions({ lineNumbers: (n) => ordinals[n] ?? "" });
678
+ };
679
+ applyLineOrdinals();
680
+ subs.push(editor.onDidChangeModelContent(applyLineOrdinals));
681
+ }
682
+ const refresh = () => {
683
+ const model = editor.getModel();
684
+ if (!model) return;
685
+ if (opts.structure !== false) {
686
+ const s = structure(model.getValue());
687
+ const decos = [];
688
+ for (const r of s.references) {
689
+ const cls = r.targetId ? "tg-ref" : "tg-ref-dangling";
690
+ decos.push({ range: new monaco.Range(r.loc.line + 1, r.loc.start + 1, r.loc.line + 1, r.loc.end + 1), options: { inlineClassName: cls } });
691
+ }
692
+ structDecos.set(decos);
693
+ }
694
+ if (opts.diagnostics !== false) applyDiagnostics(monaco, model, opts.compileOptions);
695
+ };
696
+ refresh();
697
+ let refreshTimer;
698
+ subs.push(
699
+ editor.onDidChangeModelContent(() => {
700
+ if (refreshTimer !== void 0) clearTimeout(refreshTimer);
701
+ refreshTimer = setTimeout(refresh, 150);
702
+ })
703
+ );
704
+ subs.push({
705
+ dispose: () => {
706
+ if (refreshTimer !== void 0) clearTimeout(refreshTimer);
707
+ }
708
+ });
709
+ if (opts.authoring !== false) {
710
+ editor.updateOptions({ linkedEditing: true, autoIndent: "full", bracketPairColorization: { enabled: false } });
711
+ const pinIndentUnit = () => {
712
+ editor.getModel()?.updateOptions({ tabSize: INDENT_UNIT, insertSpaces: true });
713
+ };
714
+ pinIndentUnit();
715
+ subs.push(editor.onDidChangeModel(pinIndentUnit));
716
+ subs.push(
717
+ editor.onKeyDown((e) => {
718
+ if (e.keyCode === monaco.KeyCode.Enter && !e.shiftKey && !e.altKey) {
719
+ if (handleListEnter(monaco, editor)) {
720
+ e.preventDefault();
721
+ e.stopPropagation();
722
+ }
723
+ } else if (e.keyCode === monaco.KeyCode.Tab) {
724
+ if (handleListTab(monaco, editor, e.shiftKey)) {
725
+ e.preventDefault();
726
+ e.stopPropagation();
727
+ }
728
+ }
729
+ })
730
+ );
731
+ subs.push(
732
+ editor.onDidChangeModelContent((ev) => {
733
+ if (ev.changes.length === 1 && ev.changes[0]) {
734
+ handleTagClose(monaco, editor, ev.changes[0]);
735
+ handleCloseTagOutdent(monaco, editor, ev.changes[0]);
736
+ }
737
+ })
738
+ );
739
+ let recasing = false;
740
+ subs.push(
741
+ editor.onDidChangeModelContent((ev) => {
742
+ if (recasing || ev.changes.length !== 1) return;
743
+ const change = ev.changes[0];
744
+ if (!change) return;
745
+ recasing = true;
746
+ try {
747
+ autoUppercaseCommand(monaco, editor, change);
748
+ } finally {
749
+ recasing = false;
750
+ }
751
+ })
752
+ );
753
+ }
754
+ if (opts.autoIndent !== false) {
755
+ let renumberTimer;
756
+ let renumbering = false;
757
+ const scheduleRenumber = () => {
758
+ if (renumbering) return;
759
+ if (renumberTimer) clearTimeout(renumberTimer);
760
+ renumberTimer = setTimeout(() => {
761
+ renumbering = true;
762
+ try {
763
+ applyRenumber(monaco, editor);
764
+ } finally {
765
+ renumbering = false;
766
+ }
767
+ }, 120);
768
+ };
769
+ subs.push(
770
+ editor.onDidChangeModelContent((ev) => {
771
+ const ch = ev.changes.length === 1 ? ev.changes[0] : void 0;
772
+ if (ch && completesMarker(monaco, editor, ch)) indentNewLine(monaco, editor, ch.range.startLineNumber);
773
+ if (ch) snapNewbornContent(monaco, editor, ch);
774
+ scheduleRenumber();
775
+ })
776
+ );
777
+ let lastLine = editor.getPosition()?.lineNumber ?? 1;
778
+ subs.push(
779
+ editor.onDidChangeCursorPosition((e) => {
780
+ const departed = lastLine;
781
+ lastLine = e.position.lineNumber;
782
+ if (departed === e.position.lineNumber) return;
783
+ const model = editor.getModel();
784
+ if (!model || departed < 1 || departed > model.getLineCount()) return;
785
+ const text = model.getLineContent(departed);
786
+ if (text.length > 0 && text.trim() === "") {
787
+ editor.executeEdits("tg-reap-whitespace", [
788
+ { range: new monaco.Range(departed, 1, departed, text.length + 1), text: "" }
789
+ ]);
790
+ }
791
+ })
792
+ );
793
+ }
794
+ return {
795
+ dispose() {
796
+ for (const s of subs) s.dispose();
797
+ structDecos.clear();
798
+ }
799
+ };
800
+ }
801
+ function applyRenumber(monaco, editor) {
802
+ const model = editor.getModel();
803
+ if (!model) return;
804
+ const oldLines = model.getValue().split("\n");
805
+ const newLines = renumberSubSteps(oldLines);
806
+ if (newLines === oldLines) return;
807
+ const edits = [];
808
+ for (let i = 0; i < oldLines.length; i += 1) {
809
+ const a = oldLines[i] ?? "";
810
+ const b = newLines[i] ?? "";
811
+ if (a === b) continue;
812
+ let p = 0;
813
+ while (p < a.length && p < b.length && a[p] === b[p]) p += 1;
814
+ let s = 0;
815
+ while (s < a.length - p && s < b.length - p && a[a.length - 1 - s] === b[b.length - 1 - s]) s += 1;
816
+ edits.push({ range: new monaco.Range(i + 1, p + 1, i + 1, a.length - s + 1), text: b.slice(p, b.length - s) });
817
+ }
818
+ if (edits.length > 0) editor.executeEdits("tg-renumber", edits);
819
+ }
820
+ function indentNewLine(monaco, editor, lineNumber) {
821
+ const model = editor.getModel();
822
+ if (!model || lineNumber < 1 || lineNumber > model.getLineCount()) return;
823
+ const text = model.getLineContent(lineNumber);
824
+ const trimmed = text.trim();
825
+ if (trimmed === "") return;
826
+ let inFence = false;
827
+ for (let i = 1; i < lineNumber; i += 1) {
828
+ const t = model.getLineContent(i).trim();
829
+ if (t.startsWith("```") || t.startsWith("~~~")) inFence = !inFence;
830
+ }
831
+ if (inFence) return;
832
+ const lines = model.getValue().split("\n");
833
+ if (/^\s*(?:#{1,6}|\d+(?:\.\d+)*[.)]|[-*+])\s*$/i.test(text)) lines[lineNumber - 1] = `${text.replace(/\s+$/, "")} x`;
834
+ const target = layoutColumns(lines).col[lineNumber - 1];
835
+ if (target === null || target === void 0) return;
836
+ const current = text.length - text.trimStart().length;
837
+ if (current !== target) editor.executeEdits("tg-indent-line", [{ range: new monaco.Range(lineNumber, 1, lineNumber, current + 1), text: " ".repeat(target) }]);
838
+ }
839
+ function handleTagClose(monaco, editor, change) {
840
+ if (change.text !== ">" || change.rangeLength !== 0) return;
841
+ const model = editor.getModel();
842
+ if (!model) return;
843
+ const ln = change.range.startLineNumber;
844
+ const caretCol = change.range.startColumn + 1;
845
+ const line = model.getLineContent(ln);
846
+ const close = autoCloseSectionTag(line.slice(0, caretCol - 1), line.slice(caretCol - 1));
847
+ if (!close) return;
848
+ const hypothetical = model.getLinesContent().slice();
849
+ hypothetical.splice(ln - 1, 1, `<${close.tag}>`, "", `</${close.tag}>`);
850
+ const tagIndent = layoutColumns(hypothetical).col[ln - 1] ?? 0;
851
+ const indent = " ".repeat(tagIndent);
852
+ const body = " ".repeat(tagIndent + 2);
853
+ const block = `${indent}<${close.tag}>
854
+ ${body}
855
+ ${indent}</${close.tag}>`;
856
+ editor.executeEdits(
857
+ "tg-tag-close",
858
+ [{ range: new monaco.Range(ln, 1, ln, model.getLineMaxColumn(ln)), text: block }],
859
+ [new monaco.Selection(ln + 1, body.length + 1, ln + 1, body.length + 1)]
860
+ );
861
+ }
862
+ function snapNewbornContent(monaco, editor, change) {
863
+ if (change.rangeLength !== 0) return;
864
+ if (change.text === "" || change.text.includes("\n") || change.text.trim() === "") return;
865
+ const model = editor.getModel();
866
+ if (!model) return;
867
+ const ln = change.range.startLineNumber;
868
+ if (change.range.endLineNumber !== ln || ln > model.getLineCount()) return;
869
+ const line = model.getLineContent(ln);
870
+ const before = line.slice(0, change.range.startColumn - 1) + line.slice(change.range.startColumn - 1 + change.text.length);
871
+ if (before.trim() !== "") return;
872
+ const lines = model.getLinesContent();
873
+ const target = layoutColumns(lines).col[ln - 1];
874
+ if (target === null || target === void 0) return;
875
+ const body = line.trim();
876
+ const current = line.length - line.trimStart().length;
877
+ const trailing = line.length - line.trimEnd().length;
878
+ if (current === target && trailing === 0) return;
879
+ const caret = editor.getPosition();
880
+ const caretOffsetInBody = caret && caret.lineNumber === ln ? Math.max(0, caret.column - 1 - current) : body.length;
881
+ editor.executeEdits(
882
+ "tg-newborn-indent",
883
+ [{ range: new monaco.Range(ln, 1, ln, line.length + 1), text: " ".repeat(target) + body }],
884
+ [new monaco.Selection(ln, target + caretOffsetInBody + 1, ln, target + caretOffsetInBody + 1)]
885
+ );
886
+ }
887
+ function handleCloseTagOutdent(monaco, editor, change) {
888
+ if (change.text !== ">" || change.rangeLength !== 0) return;
889
+ const model = editor.getModel();
890
+ if (!model) return;
891
+ const ln = change.range.startLineNumber;
892
+ const line = model.getLineContent(ln);
893
+ if (!new RegExp(CLOSE_TAG_LINE_SRC, "i").test(line)) return;
894
+ const target = layoutColumns(model.getLinesContent()).col[ln - 1];
895
+ if (target === null || target === void 0) return;
896
+ const current = line.length - line.trimStart().length;
897
+ if (current === target) return;
898
+ editor.executeEdits("tg-close-outdent", [
899
+ { range: new monaco.Range(ln, 1, ln, current + 1), text: " ".repeat(target) }
900
+ ]);
901
+ }
902
+ function completesMarker(monaco, editor, change) {
903
+ if (change.text !== " " || change.rangeLength !== 0) return false;
904
+ const model = editor.getModel();
905
+ if (!model) return false;
906
+ const ln = change.range.startLineNumber;
907
+ const head = model.getValueInRange(new monaco.Range(ln, 1, ln, change.range.startColumn));
908
+ return /^\s*(?:#{1,6}|\d+(?:\.\d+)*[.)]|[-*+])$/i.test(head);
909
+ }
910
+ function handleListEnter(monaco, editor) {
911
+ const model = editor.getModel();
912
+ const pos = editor.getPosition();
913
+ const sel = editor.getSelection();
914
+ if (!model || !pos || !sel) return false;
915
+ const lineNumber = pos.lineNumber;
916
+ const lineText = model.getLineContent(lineNumber);
917
+ const next = nextListItem(lineText);
918
+ if (!next) return false;
919
+ if (next.terminate) {
920
+ editor.executeEdits("list", [{ range: new monaco.Range(lineNumber, 1, lineNumber, lineText.length + 1), text: "" }]);
921
+ return true;
922
+ }
923
+ editor.executeEdits("list", [{ range: sel, text: `
924
+ ${next.prefix}` }]);
925
+ return true;
926
+ }
927
+ function handleListTab(monaco, editor, outdent) {
928
+ const model = editor.getModel();
929
+ const pos = editor.getPosition();
930
+ const sel = editor.getSelection();
931
+ if (!model || !pos || sel && !sel.isEmpty()) return false;
932
+ const lineNumber = pos.lineNumber;
933
+ const lineText = model.getLineContent(lineNumber);
934
+ const nest = nestStep(model.getLinesContent(), lineNumber - 1, outdent);
935
+ if (nest) {
936
+ editor.executeEdits("list-nest", [{ range: new monaco.Range(lineNumber, nest.start + 1, lineNumber, nest.end + 1), text: nest.text }]);
937
+ indentNewLine(monaco, editor, lineNumber);
938
+ return true;
939
+ }
940
+ if (/^\s*\d+(?:\.\d+)*[.)]\s/.test(lineText)) return true;
941
+ if (!/^\s*[-*+]\s/.test(lineText)) return false;
942
+ if (outdent) {
943
+ const lead = lineText.length - lineText.trimStart().length;
944
+ const remove = Math.min(2, lead);
945
+ if (remove > 0) {
946
+ editor.executeEdits("list-tab", [{ range: new monaco.Range(lineNumber, 1, lineNumber, remove + 1), text: "" }]);
947
+ editor.setPosition({ lineNumber, column: Math.max(1, pos.column - remove) });
948
+ }
949
+ return true;
950
+ }
951
+ editor.executeEdits("list-tab", [{ range: new monaco.Range(lineNumber, 1, lineNumber, 1), text: " " }]);
952
+ editor.setPosition({ lineNumber, column: pos.column + 2 });
953
+ return true;
954
+ }
955
+ function autoUppercaseCommand(monaco, editor, change) {
956
+ if (change.text !== " " || change.rangeLength !== 0) return;
957
+ const model = editor.getModel();
958
+ if (!model) return;
959
+ const ln = change.range.startLineNumber;
960
+ const head = model.getValueInRange(new monaco.Range(ln, 1, ln, change.range.startColumn));
961
+ const { prefix, clause } = splitMarker(head);
962
+ const hit = matchLeadingCommand(clause);
963
+ if (!hit || clause.slice(0, hit.len) === hit.upper) return;
964
+ if (isProseBlock(enclosingBlock(model.getLinesContent(), ln - 1))) return;
965
+ const startColumn = prefix.length + 1;
966
+ editor.executeEdits("auto-uppercase", [{ range: new monaco.Range(ln, startColumn, ln, startColumn + hit.len), text: hit.upper }]);
967
+ }
968
+
969
+ export { FILE_EXT, LANG_ID, THEME_ID, applyDiagnostics, attachTypeGlish, setupTypeGlish };
970
+ //# sourceMappingURL=monaco.js.map
971
+ //# sourceMappingURL=monaco.js.map