markdown-flow-ui 0.2.35 → 0.2.36-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +12 -0
  2. package/dist/_virtual/index.es8.js +2 -2
  3. package/dist/_virtual/index.es9.js +2 -2
  4. package/dist/_virtual/index8.cjs +1 -1
  5. package/dist/_virtual/index9.cjs +1 -1
  6. package/dist/_virtual/variable-name.cjs +2 -0
  7. package/dist/_virtual/variable-name.cjs.map +1 -0
  8. package/dist/_virtual/variable-name.es.js +5 -0
  9. package/dist/_virtual/variable-name.es.js.map +1 -0
  10. package/dist/components/ContentRender/plugins/CustomVariable.cjs +1 -1
  11. package/dist/components/ContentRender/plugins/CustomVariable.cjs.map +1 -1
  12. package/dist/components/ContentRender/plugins/CustomVariable.es.js +52 -51
  13. package/dist/components/ContentRender/plugins/CustomVariable.es.js.map +1 -1
  14. package/dist/components/MarkdownFlowEditor/MarkdownFlowEditor.cjs +1 -1
  15. package/dist/components/MarkdownFlowEditor/MarkdownFlowEditor.cjs.map +1 -1
  16. package/dist/components/MarkdownFlowEditor/MarkdownFlowEditor.es.js +71 -70
  17. package/dist/components/MarkdownFlowEditor/MarkdownFlowEditor.es.js.map +1 -1
  18. package/dist/components/MarkdownFlowEditor/components/VariableSelect.cjs +1 -1
  19. package/dist/components/MarkdownFlowEditor/components/VariableSelect.cjs.map +1 -1
  20. package/dist/components/MarkdownFlowEditor/components/VariableSelect.es.js +16 -16
  21. package/dist/components/MarkdownFlowEditor/components/VariableSelect.es.js.map +1 -1
  22. package/dist/components/MarkdownFlowEditor/locales/ar-SA.json.cjs +1 -1
  23. package/dist/components/MarkdownFlowEditor/locales/ar-SA.json.d.ts +1 -1
  24. package/dist/components/MarkdownFlowEditor/locales/ar-SA.json.es.js +1 -1
  25. package/dist/components/MarkdownFlowEditor/locales/de-DE.json.cjs +1 -1
  26. package/dist/components/MarkdownFlowEditor/locales/de-DE.json.d.ts +1 -1
  27. package/dist/components/MarkdownFlowEditor/locales/de-DE.json.es.js +23 -23
  28. package/dist/components/MarkdownFlowEditor/locales/en-US.json.cjs +1 -1
  29. package/dist/components/MarkdownFlowEditor/locales/en-US.json.d.ts +1 -1
  30. package/dist/components/MarkdownFlowEditor/locales/en-US.json.es.js +15 -15
  31. package/dist/components/MarkdownFlowEditor/locales/es-ES.json.cjs +1 -1
  32. package/dist/components/MarkdownFlowEditor/locales/es-ES.json.d.ts +1 -1
  33. package/dist/components/MarkdownFlowEditor/locales/es-ES.json.es.js +13 -13
  34. package/dist/components/MarkdownFlowEditor/locales/fil-PH.json.cjs +1 -1
  35. package/dist/components/MarkdownFlowEditor/locales/fil-PH.json.d.ts +1 -1
  36. package/dist/components/MarkdownFlowEditor/locales/fil-PH.json.es.js +8 -8
  37. package/dist/components/MarkdownFlowEditor/locales/fr-FR.json.cjs +1 -1
  38. package/dist/components/MarkdownFlowEditor/locales/fr-FR.json.d.ts +1 -1
  39. package/dist/components/MarkdownFlowEditor/locales/fr-FR.json.es.js +13 -13
  40. package/dist/components/MarkdownFlowEditor/locales/ja-JP.json.cjs +1 -1
  41. package/dist/components/MarkdownFlowEditor/locales/ja-JP.json.d.ts +1 -1
  42. package/dist/components/MarkdownFlowEditor/locales/ja-JP.json.es.js +1 -1
  43. package/dist/components/MarkdownFlowEditor/locales/th-TH.json.cjs +1 -1
  44. package/dist/components/MarkdownFlowEditor/locales/th-TH.json.d.ts +1 -1
  45. package/dist/components/MarkdownFlowEditor/locales/th-TH.json.es.js +1 -1
  46. package/dist/components/MarkdownFlowEditor/locales/ur-PK.json.cjs +1 -1
  47. package/dist/components/MarkdownFlowEditor/locales/ur-PK.json.d.ts +1 -1
  48. package/dist/components/MarkdownFlowEditor/locales/ur-PK.json.es.js +1 -1
  49. package/dist/components/MarkdownFlowEditor/locales/vi-VN.json.cjs +1 -1
  50. package/dist/components/MarkdownFlowEditor/locales/vi-VN.json.d.ts +1 -1
  51. package/dist/components/MarkdownFlowEditor/locales/vi-VN.json.es.js +11 -11
  52. package/dist/components/MarkdownFlowEditor/locales/zh-CN.json.cjs +1 -1
  53. package/dist/components/MarkdownFlowEditor/locales/zh-CN.json.d.ts +1 -1
  54. package/dist/components/MarkdownFlowEditor/locales/zh-CN.json.es.js +1 -1
  55. package/dist/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.cjs +3 -3
  56. package/dist/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.cjs.map +1 -1
  57. package/dist/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.es.js +104 -103
  58. package/dist/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.es.js.map +1 -1
  59. package/dist/components/MarkdownFlowEditor/plugins/VariablePlaceholder.test.d.ts +1 -0
  60. package/dist/components/MarkdownFlowEditor/utils.cjs +1 -1
  61. package/dist/components/MarkdownFlowEditor/utils.cjs.map +1 -1
  62. package/dist/components/MarkdownFlowEditor/utils.d.ts +2 -3
  63. package/dist/components/MarkdownFlowEditor/utils.es.js +43 -50
  64. package/dist/components/MarkdownFlowEditor/utils.es.js.map +1 -1
  65. package/dist/components/MarkdownFlowEditor/utils.variables.test.d.ts +1 -0
  66. package/dist/lib/interaction-defaults.cjs +1 -1
  67. package/dist/lib/interaction-defaults.cjs.map +1 -1
  68. package/dist/lib/interaction-defaults.es.js +49 -49
  69. package/dist/lib/interaction-defaults.es.js.map +1 -1
  70. package/dist/node_modules/@braintree/sanitize-url/dist/index.cjs +1 -1
  71. package/dist/node_modules/@braintree/sanitize-url/dist/index.es.js +1 -1
  72. package/dist/node_modules/classnames/index.cjs +1 -1
  73. package/dist/node_modules/classnames/index.es.js +1 -1
  74. package/dist/node_modules/cose-base/cose-base.cjs +1 -1
  75. package/dist/node_modules/cose-base/cose-base.cjs.map +1 -1
  76. package/dist/node_modules/cose-base/cose-base.es.js +1 -1
  77. package/dist/node_modules/cytoscape-fcose/node_modules/cose-base/cose-base.cjs +1 -1
  78. package/dist/node_modules/cytoscape-fcose/node_modules/cose-base/cose-base.cjs.map +1 -1
  79. package/dist/node_modules/cytoscape-fcose/node_modules/cose-base/cose-base.es.js +1 -1
  80. package/dist/node_modules/cytoscape-fcose/node_modules/layout-base/layout-base.cjs +1 -1
  81. package/dist/node_modules/cytoscape-fcose/node_modules/layout-base/layout-base.cjs.map +1 -1
  82. package/dist/node_modules/cytoscape-fcose/node_modules/layout-base/layout-base.es.js +1 -1
  83. package/dist/node_modules/layout-base/layout-base.cjs +1 -1
  84. package/dist/node_modules/layout-base/layout-base.cjs.map +1 -1
  85. package/dist/node_modules/layout-base/layout-base.es.js +1 -1
  86. package/dist/node_modules/remark-flow/dist/index.cjs +1 -1
  87. package/dist/node_modules/remark-flow/dist/index.cjs.map +1 -1
  88. package/dist/node_modules/remark-flow/dist/index.es.js +41 -24
  89. package/dist/node_modules/remark-flow/dist/index.es.js.map +1 -1
  90. package/dist/node_modules/remark-flow/dist/interaction-parser.cjs +1 -1
  91. package/dist/node_modules/remark-flow/dist/interaction-parser.cjs.map +1 -1
  92. package/dist/node_modules/remark-flow/dist/interaction-parser.es.js +44 -45
  93. package/dist/node_modules/remark-flow/dist/interaction-parser.es.js.map +1 -1
  94. package/dist/node_modules/remark-flow/dist/variable-name.cjs +2 -0
  95. package/dist/node_modules/remark-flow/dist/variable-name.cjs.map +1 -0
  96. package/dist/node_modules/remark-flow/dist/variable-name.es.js +31 -0
  97. package/dist/node_modules/remark-flow/dist/variable-name.es.js.map +1 -0
  98. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"SyntaxHighlighter.cjs","sources":["../../../../src/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.ts"],"sourcesContent":["import {\n Decoration,\n DecorationSet,\n EditorView,\n ViewPlugin,\n ViewUpdate,\n} from \"@codemirror/view\";\nimport { RangeSetBuilder } from \"@codemirror/state\";\nimport { INTERACTION_CONTENT_SOURCE, isEscape } from \"remark-flow\";\n\nimport { createVariableExpressionRegexp } from \"../utils\";\n\nconst broadVariableRegex = /\\{\\{.*?\\}\\}/g;\nconst commentRegex = /<!--[\\s\\S]*?-->/g;\n// The grammar's own definition of where an interaction ends, so a `\\]` an option escaped does\n// not cut the highlight short, and the same `(?!\\()` the parser uses, so `?[text](url)` stays a\n// markdown link. Taken from remark-flow rather than written again here: the editor and the\n// parser have to agree about what they are looking at.\nconst controlBlockRegex = new RegExp(\n `\\\\?\\\\[(${INTERACTION_CONTENT_SOURCE})\\\\](?!\\\\()`,\n \"g\"\n);\n\nexport interface SyntaxHighlightRange {\n from: number;\n to: number;\n className: string;\n}\n\nfunction collectMultilineFixedOutputRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let pendingStart: number | null = null;\n let lineStart = 0;\n\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n\n if (lineText.trim() === \"!===\") {\n if (pendingStart === null) {\n pendingStart = lineStart;\n } else {\n ranges.push({\n from: pendingStart,\n to: lineEnd,\n className: \"syntax-fixed\",\n });\n pendingStart = null;\n }\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectSingleLineFixedOutputRanges(\n docText: string,\n commentRanges: SyntaxHighlightRange[]\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let commentIndex = 0;\n\n const isInsideComment = (index: number) => {\n while (\n commentIndex < commentRanges.length &&\n commentRanges[commentIndex].to <= index\n ) {\n commentIndex++;\n }\n\n const range = commentRanges[commentIndex];\n return !!range && index >= range.from && index < range.to;\n };\n\n let lineStart = 0;\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n const markerPositions: number[] = [];\n let searchFrom = 0;\n\n while (searchFrom < lineText.length) {\n const markerOffset = lineText.indexOf(\"===\", searchFrom);\n if (markerOffset === -1) {\n break;\n }\n\n const markerIndex = lineStart + markerOffset;\n const isNegated = markerIndex > 0 && docText[markerIndex - 1] === \"!\";\n if (!isNegated && !isInsideComment(markerIndex)) {\n markerPositions.push(markerIndex);\n }\n\n searchFrom = markerOffset + 3;\n }\n\n for (let i = 0; i + 1 < markerPositions.length; i += 2) {\n ranges.push({\n from: markerPositions[i],\n to: markerPositions[i + 1] + 3,\n className: \"syntax-fixed\",\n });\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectCommentRanges(docText: string): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let match;\n\n commentRegex.lastIndex = 0;\n while ((match = commentRegex.exec(docText)) !== null) {\n ranges.push({\n from: match.index,\n to: match.index + match[0].length,\n className: \"syntax-comment\",\n });\n }\n\n return ranges;\n}\n\n/**\n * Collects non-overlapping fixed-output and comment wrapper ranges.\n *\n * @param docText - Document text to scan.\n * @returns Outer syntax highlight ranges sorted by document position.\n */\nexport function collectOuterBlockRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const commentRanges = collectCommentRanges(docText);\n const blockRanges = [\n ...collectMultilineFixedOutputRanges(docText),\n ...collectSingleLineFixedOutputRanges(docText, commentRanges),\n ...commentRanges,\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n const outerRanges: SyntaxHighlightRange[] = [];\n\n for (const range of blockRanges) {\n const lastOuter = outerRanges[outerRanges.length - 1];\n if (!lastOuter || range.from >= lastOuter.to) {\n outerRanges.push(range);\n }\n }\n\n return outerRanges;\n}\n\n/**\n * Collects all custom syntax highlight ranges for editor decorations.\n *\n * @param docText - Document text to scan.\n * @param isCursorInside - Returns true when the current cursor is inside a range.\n * @returns Non-overlapping syntax highlight ranges sorted by document position.\n */\nexport function collectSyntaxHighlightRanges(\n docText: string,\n isCursorInside: (from: number, to: number) => boolean = () => false\n): SyntaxHighlightRange[] {\n const matches: SyntaxHighlightRange[] = [];\n const occupied: { from: number; to: number }[] = [];\n\n controlBlockRegex.lastIndex = 0;\n\n // Prevent overlapping decorations so styling stays deterministic\n const isOverlapping = (from: number, to: number) =>\n occupied.some((range) => !(to <= range.from || from >= range.to));\n\n const addMatch = (from: number, to: number, className: string) => {\n if (from >= to) return false;\n if (isOverlapping(from, to)) return false;\n occupied.push({ from, to });\n matches.push({ from, to, className });\n return true;\n };\n\n const classifyVariable = (raw: string) => {\n const inner = raw.slice(2, -2).trim();\n if (!inner) return { className: \"syntax-variable-invalid\", valid: false };\n const strict = createVariableExpressionRegexp();\n const strictMatch = strict.exec(raw);\n const valid =\n !!strictMatch && strictMatch.index === 0 && strictMatch[0] === raw;\n return {\n className: valid ? \"syntax-variable\" : \"syntax-variable-invalid\",\n valid,\n };\n };\n\n let match;\n\n // 1. Outer block ranges win over any syntax inside them.\n for (const range of collectOuterBlockRanges(docText)) {\n addMatch(range.from, range.to, range.className);\n }\n\n // 2. Control Blocks\n while ((match = controlBlockRegex.exec(docText)) !== null) {\n const fullStart = match.index;\n const fullEnd = match.index + match[0].length;\n const content = match[1];\n const contentStart = fullStart + 2; // after ?[\n if (isOverlapping(fullStart, fullEnd)) {\n continue;\n }\n\n // Outer brackets and question mark\n addMatch(fullStart, fullStart + 1, \"syntax-keyword\"); // ?\n addMatch(fullStart + 1, fullStart + 2, \"syntax-bracket\"); // [\n addMatch(fullEnd - 1, fullEnd, \"syntax-bracket\"); // ]\n\n if (content.startsWith(\"%\")) {\n // Input / Select\n const contentVariableRegex = /\\{\\{.*?\\}\\}/g;\n const firstVariableMatch = contentVariableRegex.exec(content);\n contentVariableRegex.lastIndex = 0;\n let percentClass = \"syntax-percent-invalid\";\n if (firstVariableMatch) {\n const classification = classifyVariable(firstVariableMatch[0]);\n const varFrom = contentStart + firstVariableMatch.index;\n const varTo = varFrom + firstVariableMatch[0].length;\n const cursorInsideVar = isCursorInside(varFrom, varTo);\n percentClass =\n classification.valid && !cursorInsideVar\n ? \"syntax-percent-valid\"\n : \"syntax-percent-invalid\";\n }\n addMatch(contentStart, contentStart + 1, percentClass); // %\n\n const operatorRanges: { from: number; to: number }[] = [];\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedTokenRanges: { from: number; to: number }[] = [];\n\n // Inner operators | || ... -- skipping any an option escaped, the way the parser does.\n // Painted as separators, they told the author the grammar had split an option that it\n // had in fact left whole.\n let scanIndex = 0;\n while (scanIndex < content.length) {\n if (isEscape(content, scanIndex)) {\n scanIndex += 2;\n continue;\n }\n const operator = content.startsWith(\"||\", scanIndex)\n ? \"||\"\n : content[scanIndex] === \"|\"\n ? \"|\"\n : content.startsWith(\"...\", scanIndex)\n ? \"...\"\n : null;\n if (!operator) {\n scanIndex += 1;\n continue;\n }\n operatorRanges.push({\n from: contentStart + scanIndex,\n to: contentStart + scanIndex + operator.length,\n });\n scanIndex += operator.length;\n }\n\n // Variables inside control block content\n let innerVariableMatch;\n const innerVariableRegex = /\\{\\{.*?\\}\\}/g;\n while ((innerVariableMatch = innerVariableRegex.exec(content)) !== null) {\n const rawVariable = innerVariableMatch[0];\n const classification = classifyVariable(rawVariable);\n variableRanges.push({\n from: contentStart + innerVariableMatch.index,\n to: contentStart + innerVariableMatch.index + rawVariable.length,\n className: classification.className,\n });\n }\n\n const allTokens = [\n ...operatorRanges.map((range) => ({\n ...range,\n className: \"syntax-keyword\",\n })),\n ...variableRanges.map((range) => ({\n ...range,\n className: range.className,\n })),\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of allTokens) {\n if (\n token.className.startsWith(\"syntax-variable\") &&\n isCursorInside(token.from, token.to)\n ) {\n continue;\n }\n if (addMatch(token.from, token.to, token.className)) {\n appliedTokenRanges.push({ from: token.from, to: token.to });\n }\n }\n\n // Content (Dark Blue) for remaining text segments\n const stringStart = contentStart + 1;\n const stringEnd = fullEnd - 1;\n let cursor = stringStart;\n const sortedApplied = appliedTokenRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of sortedApplied) {\n if (cursor < token.from) {\n addMatch(cursor, token.from, \"syntax-string\");\n }\n cursor = Math.max(cursor, token.to);\n }\n if (cursor < stringEnd) {\n addMatch(cursor, stringEnd, \"syntax-string\");\n }\n } else {\n // Button ?[text]\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedVariableRanges: { from: number; to: number }[] = [];\n\n let innerVariableMatch;\n const innerVariableRegex = /\\{\\{.*?\\}\\}/g;\n while ((innerVariableMatch = innerVariableRegex.exec(content)) !== null) {\n const rawVariable = innerVariableMatch[0];\n const classification = classifyVariable(rawVariable);\n variableRanges.push({\n from: contentStart + innerVariableMatch.index,\n to: contentStart + innerVariableMatch.index + rawVariable.length,\n className: classification.className,\n });\n }\n\n const sortedVariables = variableRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const variable of sortedVariables) {\n if (\n variable.className.startsWith(\"syntax-variable\") &&\n isCursorInside(variable.from, variable.to)\n ) {\n continue;\n }\n if (addMatch(variable.from, variable.to, variable.className)) {\n appliedVariableRanges.push({ from: variable.from, to: variable.to });\n }\n }\n\n const buttonTextStart = contentStart;\n const buttonTextEnd = fullEnd - 1;\n let cursor = buttonTextStart;\n\n for (const variable of appliedVariableRanges) {\n if (cursor < variable.from) {\n addMatch(cursor, variable.from, \"syntax-button-text\");\n }\n cursor = Math.max(cursor, variable.to);\n }\n if (cursor < buttonTextEnd) {\n addMatch(cursor, buttonTextEnd, \"syntax-button-text\");\n }\n }\n }\n\n // 3. Variables (only if not already decorated; invalid ones stay default outside control blocks)\n broadVariableRegex.lastIndex = 0;\n while ((match = broadVariableRegex.exec(docText)) !== null) {\n const text = match[0];\n const classification = classifyVariable(text);\n if (\n classification.valid &&\n !isCursorInside(match.index, match.index + match[0].length)\n ) {\n addMatch(\n match.index,\n match.index + match[0].length,\n classification.className\n );\n }\n }\n\n // Sort matches by 'from' asc, then 'to' desc (longest first)\n matches.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n return matches;\n}\n\nfunction buildDecorations(view: EditorView): DecorationSet {\n const builder = new RangeSetBuilder<Decoration>();\n const docText = view.state.doc.toString();\n const matches = collectSyntaxHighlightRanges(docText, (from, to) => {\n return view.state.selection.ranges.some((range) => {\n return range.from >= from && range.to <= to;\n });\n });\n\n for (const m of matches) {\n if (m.from < m.to) {\n try {\n builder.add(m.from, m.to, Decoration.mark({ class: m.className }));\n } catch (e) {\n console.warn(\"SyntaxHighlighter: Failed to add decoration\", m, e);\n }\n }\n }\n\n return builder.finish();\n}\n\nconst SyntaxHighlighter = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged || update.selectionSet) {\n this.decorations = buildDecorations(update.view);\n }\n }\n },\n {\n decorations: (instance) => instance.decorations,\n }\n);\n\nexport default SyntaxHighlighter;\n"],"names":["broadVariableRegex","commentRegex","controlBlockRegex","INTERACTION_CONTENT_SOURCE","collectMultilineFixedOutputRanges","docText","ranges","pendingStart","lineStart","newlineIndex","lineEnd","collectSingleLineFixedOutputRanges","commentRanges","commentIndex","isInsideComment","index","range","lineText","markerPositions","searchFrom","markerOffset","markerIndex","i","collectCommentRanges","match","collectOuterBlockRanges","blockRanges","a","b","outerRanges","lastOuter","collectSyntaxHighlightRanges","isCursorInside","matches","occupied","isOverlapping","from","to","addMatch","className","classifyVariable","raw","strictMatch","createVariableExpressionRegexp","valid","fullStart","fullEnd","content","contentStart","contentVariableRegex","firstVariableMatch","percentClass","classification","varFrom","varTo","cursorInsideVar","operatorRanges","variableRanges","appliedTokenRanges","scanIndex","isEscape","operator","innerVariableMatch","innerVariableRegex","rawVariable","allTokens","token","stringStart","stringEnd","cursor","sortedApplied","appliedVariableRanges","sortedVariables","variable","buttonTextStart","buttonTextEnd","text","buildDecorations","view","builder","RangeSetBuilder","m","Decoration","e","SyntaxHighlighter","ViewPlugin","update","instance"],"mappings":"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"}
1
+ {"version":3,"file":"SyntaxHighlighter.cjs","sources":["../../../../src/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.ts"],"sourcesContent":["import {\n Decoration,\n DecorationSet,\n EditorView,\n ViewPlugin,\n ViewUpdate,\n} from \"@codemirror/view\";\nimport { RangeSetBuilder } from \"@codemirror/state\";\nimport { INTERACTION_CONTENT_SOURCE, isEscape } from \"remark-flow\";\n\nimport { normalizeVariableName } from \"../utils\";\n\nconst broadVariableRegex = /\\{\\{.*?\\}\\}/g;\nconst commentRegex = /<!--[\\s\\S]*?-->/g;\n// The grammar's own definition of where an interaction ends, so a `\\]` an option escaped does\n// not cut the highlight short, and the same `(?!\\()` the parser uses, so `?[text](url)` stays a\n// markdown link. Taken from remark-flow rather than written again here: the editor and the\n// parser have to agree about what they are looking at.\nconst controlBlockRegex = new RegExp(\n `\\\\?\\\\[(${INTERACTION_CONTENT_SOURCE})\\\\](?!\\\\()`,\n \"g\"\n);\n\nexport interface SyntaxHighlightRange {\n from: number;\n to: number;\n className: string;\n}\n\nfunction collectMultilineFixedOutputRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let pendingStart: number | null = null;\n let lineStart = 0;\n\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n\n if (lineText.trim() === \"!===\") {\n if (pendingStart === null) {\n pendingStart = lineStart;\n } else {\n ranges.push({\n from: pendingStart,\n to: lineEnd,\n className: \"syntax-fixed\",\n });\n pendingStart = null;\n }\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectSingleLineFixedOutputRanges(\n docText: string,\n commentRanges: SyntaxHighlightRange[]\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let commentIndex = 0;\n\n const isInsideComment = (index: number) => {\n while (\n commentIndex < commentRanges.length &&\n commentRanges[commentIndex].to <= index\n ) {\n commentIndex++;\n }\n\n const range = commentRanges[commentIndex];\n return !!range && index >= range.from && index < range.to;\n };\n\n let lineStart = 0;\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n const markerPositions: number[] = [];\n let searchFrom = 0;\n\n while (searchFrom < lineText.length) {\n const markerOffset = lineText.indexOf(\"===\", searchFrom);\n if (markerOffset === -1) {\n break;\n }\n\n const markerIndex = lineStart + markerOffset;\n const isNegated = markerIndex > 0 && docText[markerIndex - 1] === \"!\";\n if (!isNegated && !isInsideComment(markerIndex)) {\n markerPositions.push(markerIndex);\n }\n\n searchFrom = markerOffset + 3;\n }\n\n for (let i = 0; i + 1 < markerPositions.length; i += 2) {\n ranges.push({\n from: markerPositions[i],\n to: markerPositions[i + 1] + 3,\n className: \"syntax-fixed\",\n });\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectCommentRanges(docText: string): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let match;\n\n commentRegex.lastIndex = 0;\n while ((match = commentRegex.exec(docText)) !== null) {\n ranges.push({\n from: match.index,\n to: match.index + match[0].length,\n className: \"syntax-comment\",\n });\n }\n\n return ranges;\n}\n\n/**\n * Collects non-overlapping fixed-output and comment wrapper ranges.\n *\n * @param docText - Document text to scan.\n * @returns Outer syntax highlight ranges sorted by document position.\n */\nexport function collectOuterBlockRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const commentRanges = collectCommentRanges(docText);\n const blockRanges = [\n ...collectMultilineFixedOutputRanges(docText),\n ...collectSingleLineFixedOutputRanges(docText, commentRanges),\n ...commentRanges,\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n const outerRanges: SyntaxHighlightRange[] = [];\n\n for (const range of blockRanges) {\n const lastOuter = outerRanges[outerRanges.length - 1];\n if (!lastOuter || range.from >= lastOuter.to) {\n outerRanges.push(range);\n }\n }\n\n return outerRanges;\n}\n\n/**\n * Collects all custom syntax highlight ranges for editor decorations.\n *\n * @param docText - Document text to scan.\n * @param isCursorInside - Returns true when the current cursor is inside a range.\n * @returns Non-overlapping syntax highlight ranges sorted by document position.\n */\nexport function collectSyntaxHighlightRanges(\n docText: string,\n isCursorInside: (from: number, to: number) => boolean = () => false\n): SyntaxHighlightRange[] {\n const matches: SyntaxHighlightRange[] = [];\n const occupied: { from: number; to: number }[] = [];\n\n controlBlockRegex.lastIndex = 0;\n\n // Prevent overlapping decorations so styling stays deterministic\n const isOverlapping = (from: number, to: number) =>\n occupied.some((range) => !(to <= range.from || from >= range.to));\n\n const addMatch = (from: number, to: number, className: string) => {\n if (from >= to) return false;\n if (isOverlapping(from, to)) return false;\n occupied.push({ from, to });\n matches.push({ from, to, className });\n return true;\n };\n\n const classifyVariable = (raw: string) => {\n const valid = normalizeVariableName(raw.slice(2, -2)) !== null;\n return {\n className: valid ? \"syntax-variable\" : \"syntax-variable-invalid\",\n valid,\n };\n };\n\n let match;\n\n // 1. Outer block ranges win over any syntax inside them.\n for (const range of collectOuterBlockRanges(docText)) {\n addMatch(range.from, range.to, range.className);\n }\n\n // 2. Control Blocks\n while ((match = controlBlockRegex.exec(docText)) !== null) {\n const fullStart = match.index;\n const fullEnd = match.index + match[0].length;\n const content = match[1];\n const contentStart = fullStart + 2; // after ?[\n if (isOverlapping(fullStart, fullEnd)) {\n continue;\n }\n\n // Outer brackets and question mark\n addMatch(fullStart, fullStart + 1, \"syntax-keyword\"); // ?\n addMatch(fullStart + 1, fullStart + 2, \"syntax-bracket\"); // [\n addMatch(fullEnd - 1, fullEnd, \"syntax-bracket\"); // ]\n\n if (content.startsWith(\"%\")) {\n // Input / Select\n const contentVariableRegex = new RegExp(broadVariableRegex.source, \"g\");\n const firstVariableMatch = contentVariableRegex.exec(content);\n contentVariableRegex.lastIndex = 0;\n let percentClass = \"syntax-percent-invalid\";\n if (firstVariableMatch?.index === 1) {\n const classification = classifyVariable(firstVariableMatch[0]);\n const varFrom = contentStart + firstVariableMatch.index;\n const varTo = varFrom + firstVariableMatch[0].length;\n const cursorInsideVar = isCursorInside(varFrom, varTo);\n percentClass =\n classification.valid && !cursorInsideVar\n ? \"syntax-percent-valid\"\n : \"syntax-percent-invalid\";\n }\n addMatch(contentStart, contentStart + 1, percentClass); // %\n\n const operatorRanges: { from: number; to: number }[] = [];\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedTokenRanges: { from: number; to: number }[] = [];\n\n // Keep a variable name atomic even when it contains option punctuation.\n for (const variableMatch of content.matchAll(broadVariableRegex)) {\n variableRanges.push({\n from: contentStart + variableMatch.index,\n to: contentStart + variableMatch.index + variableMatch[0].length,\n className: classifyVariable(variableMatch[0]).className,\n });\n }\n\n // Inner operators | || ... -- skipping any an option escaped, the way the parser does.\n // Painted as separators, they told the author the grammar had split an option that it\n // had in fact left whole.\n let scanIndex = 0;\n while (scanIndex < content.length) {\n const variable = variableRanges.find(\n (range) => contentStart + scanIndex === range.from\n );\n if (variable) {\n scanIndex = variable.to - contentStart;\n continue;\n }\n if (isEscape(content, scanIndex)) {\n scanIndex += 2;\n continue;\n }\n const operator = content.startsWith(\"||\", scanIndex)\n ? \"||\"\n : content[scanIndex] === \"|\"\n ? \"|\"\n : content.startsWith(\"...\", scanIndex)\n ? \"...\"\n : null;\n if (!operator) {\n scanIndex += 1;\n continue;\n }\n operatorRanges.push({\n from: contentStart + scanIndex,\n to: contentStart + scanIndex + operator.length,\n });\n scanIndex += operator.length;\n }\n\n const allTokens = [\n ...operatorRanges.map((range) => ({\n ...range,\n className: \"syntax-keyword\",\n })),\n ...variableRanges.map((range) => ({\n ...range,\n className: range.className,\n })),\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of allTokens) {\n if (\n token.className.startsWith(\"syntax-variable\") &&\n isCursorInside(token.from, token.to)\n ) {\n continue;\n }\n if (addMatch(token.from, token.to, token.className)) {\n appliedTokenRanges.push({ from: token.from, to: token.to });\n }\n }\n\n // Content (Dark Blue) for remaining text segments\n const stringStart = contentStart + 1;\n const stringEnd = fullEnd - 1;\n let cursor = stringStart;\n const sortedApplied = appliedTokenRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of sortedApplied) {\n if (cursor < token.from) {\n addMatch(cursor, token.from, \"syntax-string\");\n }\n cursor = Math.max(cursor, token.to);\n }\n if (cursor < stringEnd) {\n addMatch(cursor, stringEnd, \"syntax-string\");\n }\n } else {\n // Button ?[text]\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedVariableRanges: { from: number; to: number }[] = [];\n\n let innerVariableMatch;\n const innerVariableRegex = new RegExp(broadVariableRegex.source, \"g\");\n while ((innerVariableMatch = innerVariableRegex.exec(content)) !== null) {\n const rawVariable = innerVariableMatch[0];\n const classification = classifyVariable(rawVariable);\n variableRanges.push({\n from: contentStart + innerVariableMatch.index,\n to: contentStart + innerVariableMatch.index + rawVariable.length,\n className: classification.className,\n });\n }\n\n const sortedVariables = variableRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const variable of sortedVariables) {\n if (\n variable.className.startsWith(\"syntax-variable\") &&\n isCursorInside(variable.from, variable.to)\n ) {\n continue;\n }\n if (addMatch(variable.from, variable.to, variable.className)) {\n appliedVariableRanges.push({ from: variable.from, to: variable.to });\n }\n }\n\n const buttonTextStart = contentStart;\n const buttonTextEnd = fullEnd - 1;\n let cursor = buttonTextStart;\n\n for (const variable of appliedVariableRanges) {\n if (cursor < variable.from) {\n addMatch(cursor, variable.from, \"syntax-button-text\");\n }\n cursor = Math.max(cursor, variable.to);\n }\n if (cursor < buttonTextEnd) {\n addMatch(cursor, buttonTextEnd, \"syntax-button-text\");\n }\n }\n }\n\n // 3. Variables (only if not already decorated; invalid ones stay default outside control blocks)\n broadVariableRegex.lastIndex = 0;\n while ((match = broadVariableRegex.exec(docText)) !== null) {\n const text = match[0];\n const classification = classifyVariable(text);\n if (\n classification.valid &&\n !isCursorInside(match.index, match.index + match[0].length)\n ) {\n addMatch(\n match.index,\n match.index + match[0].length,\n classification.className\n );\n }\n }\n\n // Sort matches by 'from' asc, then 'to' desc (longest first)\n matches.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n return matches;\n}\n\nfunction buildDecorations(view: EditorView): DecorationSet {\n const builder = new RangeSetBuilder<Decoration>();\n const docText = view.state.doc.toString();\n const matches = collectSyntaxHighlightRanges(docText, (from, to) => {\n return view.state.selection.ranges.some((range) => {\n return range.from >= from && range.to <= to;\n });\n });\n\n for (const m of matches) {\n if (m.from < m.to) {\n try {\n builder.add(m.from, m.to, Decoration.mark({ class: m.className }));\n } catch (e) {\n console.warn(\"SyntaxHighlighter: Failed to add decoration\", m, e);\n }\n }\n }\n\n return builder.finish();\n}\n\nconst SyntaxHighlighter = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged || update.selectionSet) {\n this.decorations = buildDecorations(update.view);\n }\n }\n },\n {\n decorations: (instance) => instance.decorations,\n }\n);\n\nexport default SyntaxHighlighter;\n"],"names":["broadVariableRegex","commentRegex","controlBlockRegex","INTERACTION_CONTENT_SOURCE","collectMultilineFixedOutputRanges","docText","ranges","pendingStart","lineStart","newlineIndex","lineEnd","collectSingleLineFixedOutputRanges","commentRanges","commentIndex","isInsideComment","index","range","lineText","markerPositions","searchFrom","markerOffset","markerIndex","i","collectCommentRanges","match","collectOuterBlockRanges","blockRanges","a","b","outerRanges","lastOuter","collectSyntaxHighlightRanges","isCursorInside","matches","occupied","isOverlapping","from","to","addMatch","className","classifyVariable","raw","valid","normalizeVariableName","fullStart","fullEnd","content","contentStart","contentVariableRegex","firstVariableMatch","percentClass","classification","varFrom","varTo","cursorInsideVar","operatorRanges","variableRanges","appliedTokenRanges","variableMatch","scanIndex","variable","isEscape","operator","allTokens","token","stringStart","stringEnd","cursor","sortedApplied","appliedVariableRanges","innerVariableMatch","innerVariableRegex","rawVariable","sortedVariables","buttonTextStart","buttonTextEnd","text","buildDecorations","view","builder","RangeSetBuilder","m","Decoration","e","SyntaxHighlighter","ViewPlugin","update","instance"],"mappings":"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"}
@@ -1,31 +1,30 @@
1
- import { ViewPlugin as H, Decoration as A } from "../../../node_modules/@codemirror/view/dist/index.es.js";
2
- import { RangeSetBuilder as D } from "../../../node_modules/@codemirror/state/dist/index.es.js";
3
- import { d as M } from "../../../_virtual/index.es.js";
4
- import { createVariableExpressionRegexp as P } from "../utils.es.js";
5
- const V = /\{\{.*?\}\}/g, E = /<!--[\s\S]*?-->/g, O = new RegExp(
6
- `\\?\\[(${M.INTERACTION_CONTENT_SOURCE})\\](?!\\()`,
1
+ import { ViewPlugin as W, Decoration as A } from "../../../node_modules/@codemirror/view/dist/index.es.js";
2
+ import { RangeSetBuilder as B } from "../../../node_modules/@codemirror/state/dist/index.es.js";
3
+ import { d as O } from "../../../_virtual/index.es.js";
4
+ const w = /\{\{.*?\}\}/g, V = /<!--[\s\S]*?-->/g, I = new RegExp(
5
+ `\\?\\[(${O.INTERACTION_CONTENT_SOURCE})\\](?!\\()`,
7
6
  "g"
8
7
  );
9
- function T(e) {
8
+ function H(e) {
10
9
  const l = [];
11
10
  let c = null, f = 0;
12
11
  for (; f <= e.length; ) {
13
- const s = e.indexOf(`
14
- `, f), n = s === -1 ? e.length : s;
12
+ const r = e.indexOf(`
13
+ `, f), n = r === -1 ? e.length : r;
15
14
  if (e.slice(f, n).trim() === "!===" && (c === null ? c = f : (l.push({
16
15
  from: c,
17
16
  to: n,
18
17
  className: "syntax-fixed"
19
- }), c = null)), s === -1)
18
+ }), c = null)), r === -1)
20
19
  break;
21
- f = s + 1;
20
+ f = r + 1;
22
21
  }
23
22
  return l;
24
23
  }
25
- function _(e, l) {
24
+ function D(e, l) {
26
25
  const c = [];
27
26
  let f = 0;
28
- const s = (h) => {
27
+ const r = (h) => {
29
28
  for (; f < l.length && l[f].to <= h; )
30
29
  f++;
31
30
  const m = l[f];
@@ -34,19 +33,19 @@ function _(e, l) {
34
33
  let n = 0;
35
34
  for (; n <= e.length; ) {
36
35
  const h = e.indexOf(`
37
- `, n), m = h === -1 ? e.length : h, o = e.slice(n, m), r = [];
36
+ `, n), m = h === -1 ? e.length : h, o = e.slice(n, m), s = [];
38
37
  let u = 0;
39
38
  for (; u < o.length; ) {
40
39
  const a = o.indexOf("===", u);
41
40
  if (a === -1)
42
41
  break;
43
- const x = n + a;
44
- !(x > 0 && e[x - 1] === "!") && !s(x) && r.push(x), u = a + 3;
42
+ const d = n + a;
43
+ !(d > 0 && e[d - 1] === "!") && !r(d) && s.push(d), u = a + 3;
45
44
  }
46
- for (let a = 0; a + 1 < r.length; a += 2)
45
+ for (let a = 0; a + 1 < s.length; a += 2)
47
46
  c.push({
48
- from: r[a],
49
- to: r[a + 1] + 3,
47
+ from: s[a],
48
+ to: s[a + 1] + 3,
50
49
  className: "syntax-fixed"
51
50
  });
52
51
  if (h === -1)
@@ -55,10 +54,10 @@ function _(e, l) {
55
54
  }
56
55
  return c;
57
56
  }
58
- function L(e) {
57
+ function P(e) {
59
58
  const l = [];
60
59
  let c;
61
- for (E.lastIndex = 0; (c = E.exec(e)) !== null; )
60
+ for (V.lastIndex = 0; (c = V.exec(e)) !== null; )
62
61
  l.push({
63
62
  from: c.index,
64
63
  to: c.index + c[0].length,
@@ -66,139 +65,141 @@ function L(e) {
66
65
  });
67
66
  return l;
68
67
  }
69
- function U(e) {
70
- const l = L(e), c = [
71
- ...T(e),
72
- ..._(e, l),
68
+ function T(e) {
69
+ const l = P(e), c = [
70
+ ...H(e),
71
+ ...D(e, l),
73
72
  ...l
74
- ].sort((s, n) => s.from !== n.from ? s.from - n.from : n.to - s.to), f = [];
75
- for (const s of c) {
73
+ ].sort((r, n) => r.from !== n.from ? r.from - n.from : n.to - r.to), f = [];
74
+ for (const r of c) {
76
75
  const n = f[f.length - 1];
77
- (!n || s.from >= n.to) && f.push(s);
76
+ (!n || r.from >= n.to) && f.push(r);
78
77
  }
79
78
  return f;
80
79
  }
81
- function $(e, l = () => !1) {
80
+ function _(e, l = () => !1) {
82
81
  const c = [], f = [];
83
- O.lastIndex = 0;
84
- const s = (o, r) => f.some((u) => !(r <= u.from || o >= u.to)), n = (o, r, u) => o >= r || s(o, r) ? !1 : (f.push({ from: o, to: r }), c.push({ from: o, to: r, className: u }), !0), h = (o) => {
85
- if (!o.slice(2, -2).trim()) return { className: "syntax-variable-invalid", valid: !1 };
86
- const a = P().exec(o), x = !!a && a.index === 0 && a[0] === o;
82
+ I.lastIndex = 0;
83
+ const r = (o, s) => f.some((u) => !(s <= u.from || o >= u.to)), n = (o, s, u) => o >= s || r(o, s) ? !1 : (f.push({ from: o, to: s }), c.push({ from: o, to: s, className: u }), !0), h = (o) => {
84
+ const s = O.normalizeVariableName(o.slice(2, -2)) !== null;
87
85
  return {
88
- className: x ? "syntax-variable" : "syntax-variable-invalid",
89
- valid: x
86
+ className: s ? "syntax-variable" : "syntax-variable-invalid",
87
+ valid: s
90
88
  };
91
89
  };
92
90
  let m;
93
- for (const o of U(e))
91
+ for (const o of T(e))
94
92
  n(o.from, o.to, o.className);
95
- for (; (m = O.exec(e)) !== null; ) {
96
- const o = m.index, r = m.index + m[0].length, u = m[1], a = o + 2;
97
- if (!s(o, r))
98
- if (n(o, o + 1, "syntax-keyword"), n(o + 1, o + 2, "syntax-bracket"), n(r - 1, r, "syntax-bracket"), u.startsWith("%")) {
99
- const x = /\{\{.*?\}\}/g, y = x.exec(u);
100
- x.lastIndex = 0;
93
+ for (; (m = I.exec(e)) !== null; ) {
94
+ const o = m.index, s = m.index + m[0].length, u = m[1], a = o + 2;
95
+ if (!r(o, s))
96
+ if (n(o, o + 1, "syntax-keyword"), n(o + 1, o + 2, "syntax-bracket"), n(s - 1, s, "syntax-bracket"), u.startsWith("%")) {
97
+ const d = new RegExp(w.source, "g"), p = d.exec(u);
98
+ d.lastIndex = 0;
101
99
  let b = "syntax-percent-invalid";
102
- if (y) {
103
- const t = h(y[0]), d = a + y.index, W = d + y[0].length, B = l(d, W);
104
- b = t.valid && !B ? "syntax-percent-valid" : "syntax-percent-invalid";
100
+ if (p?.index === 1) {
101
+ const t = h(p[0]), x = a + p.index, E = x + p[0].length, F = l(x, E);
102
+ b = t.valid && !F ? "syntax-percent-valid" : "syntax-percent-invalid";
105
103
  }
106
104
  n(a, a + 1, b);
107
- const R = [], w = [], k = [];
105
+ const k = [], v = [], S = [];
106
+ for (const t of u.matchAll(w))
107
+ v.push({
108
+ from: a + t.index,
109
+ to: a + t.index + t[0].length,
110
+ className: h(t[0]).className
111
+ });
108
112
  let g = 0;
109
113
  for (; g < u.length; ) {
110
- if (M.isEscape(u, g)) {
114
+ const t = v.find(
115
+ (E) => a + g === E.from
116
+ );
117
+ if (t) {
118
+ g = t.to - a;
119
+ continue;
120
+ }
121
+ if (O.isEscape(u, g)) {
111
122
  g += 2;
112
123
  continue;
113
124
  }
114
- const t = u.startsWith("||", g) ? "||" : u[g] === "|" ? "|" : u.startsWith("...", g) ? "..." : null;
115
- if (!t) {
125
+ const x = u.startsWith("||", g) ? "||" : u[g] === "|" ? "|" : u.startsWith("...", g) ? "..." : null;
126
+ if (!x) {
116
127
  g += 1;
117
128
  continue;
118
129
  }
119
- R.push({
130
+ k.push({
120
131
  from: a + g,
121
- to: a + g + t.length
122
- }), g += t.length;
123
- }
124
- let p;
125
- const i = /\{\{.*?\}\}/g;
126
- for (; (p = i.exec(u)) !== null; ) {
127
- const t = p[0], d = h(t);
128
- w.push({
129
- from: a + p.index,
130
- to: a + p.index + t.length,
131
- className: d.className
132
- });
132
+ to: a + g + x.length
133
+ }), g += x.length;
133
134
  }
134
- const N = [
135
- ...R.map((t) => ({
135
+ const y = [
136
+ ...k.map((t) => ({
136
137
  ...t,
137
138
  className: "syntax-keyword"
138
139
  })),
139
- ...w.map((t) => ({
140
+ ...v.map((t) => ({
140
141
  ...t,
141
142
  className: t.className
142
143
  }))
143
- ].sort((t, d) => t.from !== d.from ? t.from - d.from : t.to - d.to);
144
- for (const t of N)
145
- t.className.startsWith("syntax-variable") && l(t.from, t.to) || n(t.from, t.to, t.className) && k.push({ from: t.from, to: t.to });
146
- const C = a + 1, S = r - 1;
147
- let v = C;
148
- const F = k.sort((t, d) => t.from !== d.from ? t.from - d.from : t.to - d.to);
149
- for (const t of F)
150
- v < t.from && n(v, t.from, "syntax-string"), v = Math.max(v, t.to);
151
- v < S && n(v, S, "syntax-string");
144
+ ].sort((t, x) => t.from !== x.from ? t.from - x.from : t.to - x.to);
145
+ for (const t of y)
146
+ t.className.startsWith("syntax-variable") && l(t.from, t.to) || n(t.from, t.to, t.className) && S.push({ from: t.from, to: t.to });
147
+ const i = a + 1, N = s - 1;
148
+ let R = i;
149
+ const C = S.sort((t, x) => t.from !== x.from ? t.from - x.from : t.to - x.to);
150
+ for (const t of C)
151
+ R < t.from && n(R, t.from, "syntax-string"), R = Math.max(R, t.to);
152
+ R < N && n(R, N, "syntax-string");
152
153
  } else {
153
- const x = [], y = [];
154
+ const d = [], p = [];
154
155
  let b;
155
- const R = /\{\{.*?\}\}/g;
156
- for (; (b = R.exec(u)) !== null; ) {
156
+ const k = new RegExp(w.source, "g");
157
+ for (; (b = k.exec(u)) !== null; ) {
157
158
  const i = b[0], N = h(i);
158
- x.push({
159
+ d.push({
159
160
  from: a + b.index,
160
161
  to: a + b.index + i.length,
161
162
  className: N.className
162
163
  });
163
164
  }
164
- const w = x.sort((i, N) => i.from !== N.from ? i.from - N.from : i.to - N.to);
165
- for (const i of w)
166
- i.className.startsWith("syntax-variable") && l(i.from, i.to) || n(i.from, i.to, i.className) && y.push({ from: i.from, to: i.to });
167
- const k = a, g = r - 1;
168
- let p = k;
169
- for (const i of y)
170
- p < i.from && n(p, i.from, "syntax-button-text"), p = Math.max(p, i.to);
171
- p < g && n(p, g, "syntax-button-text");
165
+ const v = d.sort((i, N) => i.from !== N.from ? i.from - N.from : i.to - N.to);
166
+ for (const i of v)
167
+ i.className.startsWith("syntax-variable") && l(i.from, i.to) || n(i.from, i.to, i.className) && p.push({ from: i.from, to: i.to });
168
+ const S = a, g = s - 1;
169
+ let y = S;
170
+ for (const i of p)
171
+ y < i.from && n(y, i.from, "syntax-button-text"), y = Math.max(y, i.to);
172
+ y < g && n(y, g, "syntax-button-text");
172
173
  }
173
174
  }
174
- for (V.lastIndex = 0; (m = V.exec(e)) !== null; ) {
175
- const o = m[0], r = h(o);
176
- r.valid && !l(m.index, m.index + m[0].length) && n(
175
+ for (w.lastIndex = 0; (m = w.exec(e)) !== null; ) {
176
+ const o = m[0], s = h(o);
177
+ s.valid && !l(m.index, m.index + m[0].length) && n(
177
178
  m.index,
178
179
  m.index + m[0].length,
179
- r.className
180
+ s.className
180
181
  );
181
182
  }
182
- return c.sort((o, r) => o.from !== r.from ? o.from - r.from : r.to - o.to), c;
183
+ return c.sort((o, s) => o.from !== s.from ? o.from - s.from : s.to - o.to), c;
183
184
  }
184
- function I(e) {
185
- const l = new D(), c = e.state.doc.toString(), f = $(c, (s, n) => e.state.selection.ranges.some((h) => h.from >= s && h.to <= n));
186
- for (const s of f)
187
- if (s.from < s.to)
185
+ function M(e) {
186
+ const l = new B(), c = e.state.doc.toString(), f = _(c, (r, n) => e.state.selection.ranges.some((h) => h.from >= r && h.to <= n));
187
+ for (const r of f)
188
+ if (r.from < r.to)
188
189
  try {
189
- l.add(s.from, s.to, A.mark({ class: s.className }));
190
+ l.add(r.from, r.to, A.mark({ class: r.className }));
190
191
  } catch (n) {
191
- console.warn("SyntaxHighlighter: Failed to add decoration", s, n);
192
+ console.warn("SyntaxHighlighter: Failed to add decoration", r, n);
192
193
  }
193
194
  return l.finish();
194
195
  }
195
- const J = H.fromClass(
196
+ const $ = W.fromClass(
196
197
  class {
197
198
  constructor(e) {
198
- this.decorations = I(e);
199
+ this.decorations = M(e);
199
200
  }
200
201
  update(e) {
201
- (e.docChanged || e.viewportChanged || e.selectionSet) && (this.decorations = I(e.view));
202
+ (e.docChanged || e.viewportChanged || e.selectionSet) && (this.decorations = M(e.view));
202
203
  }
203
204
  },
204
205
  {
@@ -206,8 +207,8 @@ const J = H.fromClass(
206
207
  }
207
208
  );
208
209
  export {
209
- U as collectOuterBlockRanges,
210
- $ as collectSyntaxHighlightRanges,
211
- J as default
210
+ T as collectOuterBlockRanges,
211
+ _ as collectSyntaxHighlightRanges,
212
+ $ as default
212
213
  };
213
214
  //# sourceMappingURL=SyntaxHighlighter.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SyntaxHighlighter.es.js","sources":["../../../../src/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.ts"],"sourcesContent":["import {\n Decoration,\n DecorationSet,\n EditorView,\n ViewPlugin,\n ViewUpdate,\n} from \"@codemirror/view\";\nimport { RangeSetBuilder } from \"@codemirror/state\";\nimport { INTERACTION_CONTENT_SOURCE, isEscape } from \"remark-flow\";\n\nimport { createVariableExpressionRegexp } from \"../utils\";\n\nconst broadVariableRegex = /\\{\\{.*?\\}\\}/g;\nconst commentRegex = /<!--[\\s\\S]*?-->/g;\n// The grammar's own definition of where an interaction ends, so a `\\]` an option escaped does\n// not cut the highlight short, and the same `(?!\\()` the parser uses, so `?[text](url)` stays a\n// markdown link. Taken from remark-flow rather than written again here: the editor and the\n// parser have to agree about what they are looking at.\nconst controlBlockRegex = new RegExp(\n `\\\\?\\\\[(${INTERACTION_CONTENT_SOURCE})\\\\](?!\\\\()`,\n \"g\"\n);\n\nexport interface SyntaxHighlightRange {\n from: number;\n to: number;\n className: string;\n}\n\nfunction collectMultilineFixedOutputRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let pendingStart: number | null = null;\n let lineStart = 0;\n\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n\n if (lineText.trim() === \"!===\") {\n if (pendingStart === null) {\n pendingStart = lineStart;\n } else {\n ranges.push({\n from: pendingStart,\n to: lineEnd,\n className: \"syntax-fixed\",\n });\n pendingStart = null;\n }\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectSingleLineFixedOutputRanges(\n docText: string,\n commentRanges: SyntaxHighlightRange[]\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let commentIndex = 0;\n\n const isInsideComment = (index: number) => {\n while (\n commentIndex < commentRanges.length &&\n commentRanges[commentIndex].to <= index\n ) {\n commentIndex++;\n }\n\n const range = commentRanges[commentIndex];\n return !!range && index >= range.from && index < range.to;\n };\n\n let lineStart = 0;\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n const markerPositions: number[] = [];\n let searchFrom = 0;\n\n while (searchFrom < lineText.length) {\n const markerOffset = lineText.indexOf(\"===\", searchFrom);\n if (markerOffset === -1) {\n break;\n }\n\n const markerIndex = lineStart + markerOffset;\n const isNegated = markerIndex > 0 && docText[markerIndex - 1] === \"!\";\n if (!isNegated && !isInsideComment(markerIndex)) {\n markerPositions.push(markerIndex);\n }\n\n searchFrom = markerOffset + 3;\n }\n\n for (let i = 0; i + 1 < markerPositions.length; i += 2) {\n ranges.push({\n from: markerPositions[i],\n to: markerPositions[i + 1] + 3,\n className: \"syntax-fixed\",\n });\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectCommentRanges(docText: string): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let match;\n\n commentRegex.lastIndex = 0;\n while ((match = commentRegex.exec(docText)) !== null) {\n ranges.push({\n from: match.index,\n to: match.index + match[0].length,\n className: \"syntax-comment\",\n });\n }\n\n return ranges;\n}\n\n/**\n * Collects non-overlapping fixed-output and comment wrapper ranges.\n *\n * @param docText - Document text to scan.\n * @returns Outer syntax highlight ranges sorted by document position.\n */\nexport function collectOuterBlockRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const commentRanges = collectCommentRanges(docText);\n const blockRanges = [\n ...collectMultilineFixedOutputRanges(docText),\n ...collectSingleLineFixedOutputRanges(docText, commentRanges),\n ...commentRanges,\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n const outerRanges: SyntaxHighlightRange[] = [];\n\n for (const range of blockRanges) {\n const lastOuter = outerRanges[outerRanges.length - 1];\n if (!lastOuter || range.from >= lastOuter.to) {\n outerRanges.push(range);\n }\n }\n\n return outerRanges;\n}\n\n/**\n * Collects all custom syntax highlight ranges for editor decorations.\n *\n * @param docText - Document text to scan.\n * @param isCursorInside - Returns true when the current cursor is inside a range.\n * @returns Non-overlapping syntax highlight ranges sorted by document position.\n */\nexport function collectSyntaxHighlightRanges(\n docText: string,\n isCursorInside: (from: number, to: number) => boolean = () => false\n): SyntaxHighlightRange[] {\n const matches: SyntaxHighlightRange[] = [];\n const occupied: { from: number; to: number }[] = [];\n\n controlBlockRegex.lastIndex = 0;\n\n // Prevent overlapping decorations so styling stays deterministic\n const isOverlapping = (from: number, to: number) =>\n occupied.some((range) => !(to <= range.from || from >= range.to));\n\n const addMatch = (from: number, to: number, className: string) => {\n if (from >= to) return false;\n if (isOverlapping(from, to)) return false;\n occupied.push({ from, to });\n matches.push({ from, to, className });\n return true;\n };\n\n const classifyVariable = (raw: string) => {\n const inner = raw.slice(2, -2).trim();\n if (!inner) return { className: \"syntax-variable-invalid\", valid: false };\n const strict = createVariableExpressionRegexp();\n const strictMatch = strict.exec(raw);\n const valid =\n !!strictMatch && strictMatch.index === 0 && strictMatch[0] === raw;\n return {\n className: valid ? \"syntax-variable\" : \"syntax-variable-invalid\",\n valid,\n };\n };\n\n let match;\n\n // 1. Outer block ranges win over any syntax inside them.\n for (const range of collectOuterBlockRanges(docText)) {\n addMatch(range.from, range.to, range.className);\n }\n\n // 2. Control Blocks\n while ((match = controlBlockRegex.exec(docText)) !== null) {\n const fullStart = match.index;\n const fullEnd = match.index + match[0].length;\n const content = match[1];\n const contentStart = fullStart + 2; // after ?[\n if (isOverlapping(fullStart, fullEnd)) {\n continue;\n }\n\n // Outer brackets and question mark\n addMatch(fullStart, fullStart + 1, \"syntax-keyword\"); // ?\n addMatch(fullStart + 1, fullStart + 2, \"syntax-bracket\"); // [\n addMatch(fullEnd - 1, fullEnd, \"syntax-bracket\"); // ]\n\n if (content.startsWith(\"%\")) {\n // Input / Select\n const contentVariableRegex = /\\{\\{.*?\\}\\}/g;\n const firstVariableMatch = contentVariableRegex.exec(content);\n contentVariableRegex.lastIndex = 0;\n let percentClass = \"syntax-percent-invalid\";\n if (firstVariableMatch) {\n const classification = classifyVariable(firstVariableMatch[0]);\n const varFrom = contentStart + firstVariableMatch.index;\n const varTo = varFrom + firstVariableMatch[0].length;\n const cursorInsideVar = isCursorInside(varFrom, varTo);\n percentClass =\n classification.valid && !cursorInsideVar\n ? \"syntax-percent-valid\"\n : \"syntax-percent-invalid\";\n }\n addMatch(contentStart, contentStart + 1, percentClass); // %\n\n const operatorRanges: { from: number; to: number }[] = [];\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedTokenRanges: { from: number; to: number }[] = [];\n\n // Inner operators | || ... -- skipping any an option escaped, the way the parser does.\n // Painted as separators, they told the author the grammar had split an option that it\n // had in fact left whole.\n let scanIndex = 0;\n while (scanIndex < content.length) {\n if (isEscape(content, scanIndex)) {\n scanIndex += 2;\n continue;\n }\n const operator = content.startsWith(\"||\", scanIndex)\n ? \"||\"\n : content[scanIndex] === \"|\"\n ? \"|\"\n : content.startsWith(\"...\", scanIndex)\n ? \"...\"\n : null;\n if (!operator) {\n scanIndex += 1;\n continue;\n }\n operatorRanges.push({\n from: contentStart + scanIndex,\n to: contentStart + scanIndex + operator.length,\n });\n scanIndex += operator.length;\n }\n\n // Variables inside control block content\n let innerVariableMatch;\n const innerVariableRegex = /\\{\\{.*?\\}\\}/g;\n while ((innerVariableMatch = innerVariableRegex.exec(content)) !== null) {\n const rawVariable = innerVariableMatch[0];\n const classification = classifyVariable(rawVariable);\n variableRanges.push({\n from: contentStart + innerVariableMatch.index,\n to: contentStart + innerVariableMatch.index + rawVariable.length,\n className: classification.className,\n });\n }\n\n const allTokens = [\n ...operatorRanges.map((range) => ({\n ...range,\n className: \"syntax-keyword\",\n })),\n ...variableRanges.map((range) => ({\n ...range,\n className: range.className,\n })),\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of allTokens) {\n if (\n token.className.startsWith(\"syntax-variable\") &&\n isCursorInside(token.from, token.to)\n ) {\n continue;\n }\n if (addMatch(token.from, token.to, token.className)) {\n appliedTokenRanges.push({ from: token.from, to: token.to });\n }\n }\n\n // Content (Dark Blue) for remaining text segments\n const stringStart = contentStart + 1;\n const stringEnd = fullEnd - 1;\n let cursor = stringStart;\n const sortedApplied = appliedTokenRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of sortedApplied) {\n if (cursor < token.from) {\n addMatch(cursor, token.from, \"syntax-string\");\n }\n cursor = Math.max(cursor, token.to);\n }\n if (cursor < stringEnd) {\n addMatch(cursor, stringEnd, \"syntax-string\");\n }\n } else {\n // Button ?[text]\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedVariableRanges: { from: number; to: number }[] = [];\n\n let innerVariableMatch;\n const innerVariableRegex = /\\{\\{.*?\\}\\}/g;\n while ((innerVariableMatch = innerVariableRegex.exec(content)) !== null) {\n const rawVariable = innerVariableMatch[0];\n const classification = classifyVariable(rawVariable);\n variableRanges.push({\n from: contentStart + innerVariableMatch.index,\n to: contentStart + innerVariableMatch.index + rawVariable.length,\n className: classification.className,\n });\n }\n\n const sortedVariables = variableRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const variable of sortedVariables) {\n if (\n variable.className.startsWith(\"syntax-variable\") &&\n isCursorInside(variable.from, variable.to)\n ) {\n continue;\n }\n if (addMatch(variable.from, variable.to, variable.className)) {\n appliedVariableRanges.push({ from: variable.from, to: variable.to });\n }\n }\n\n const buttonTextStart = contentStart;\n const buttonTextEnd = fullEnd - 1;\n let cursor = buttonTextStart;\n\n for (const variable of appliedVariableRanges) {\n if (cursor < variable.from) {\n addMatch(cursor, variable.from, \"syntax-button-text\");\n }\n cursor = Math.max(cursor, variable.to);\n }\n if (cursor < buttonTextEnd) {\n addMatch(cursor, buttonTextEnd, \"syntax-button-text\");\n }\n }\n }\n\n // 3. Variables (only if not already decorated; invalid ones stay default outside control blocks)\n broadVariableRegex.lastIndex = 0;\n while ((match = broadVariableRegex.exec(docText)) !== null) {\n const text = match[0];\n const classification = classifyVariable(text);\n if (\n classification.valid &&\n !isCursorInside(match.index, match.index + match[0].length)\n ) {\n addMatch(\n match.index,\n match.index + match[0].length,\n classification.className\n );\n }\n }\n\n // Sort matches by 'from' asc, then 'to' desc (longest first)\n matches.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n return matches;\n}\n\nfunction buildDecorations(view: EditorView): DecorationSet {\n const builder = new RangeSetBuilder<Decoration>();\n const docText = view.state.doc.toString();\n const matches = collectSyntaxHighlightRanges(docText, (from, to) => {\n return view.state.selection.ranges.some((range) => {\n return range.from >= from && range.to <= to;\n });\n });\n\n for (const m of matches) {\n if (m.from < m.to) {\n try {\n builder.add(m.from, m.to, Decoration.mark({ class: m.className }));\n } catch (e) {\n console.warn(\"SyntaxHighlighter: Failed to add decoration\", m, e);\n }\n }\n }\n\n return builder.finish();\n}\n\nconst SyntaxHighlighter = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged || update.selectionSet) {\n this.decorations = buildDecorations(update.view);\n }\n }\n },\n {\n decorations: (instance) => instance.decorations,\n }\n);\n\nexport default SyntaxHighlighter;\n"],"names":["broadVariableRegex","commentRegex","controlBlockRegex","INTERACTION_CONTENT_SOURCE","collectMultilineFixedOutputRanges","docText","ranges","pendingStart","lineStart","newlineIndex","lineEnd","collectSingleLineFixedOutputRanges","commentRanges","commentIndex","isInsideComment","index","range","lineText","markerPositions","searchFrom","markerOffset","markerIndex","i","collectCommentRanges","match","collectOuterBlockRanges","blockRanges","a","b","outerRanges","lastOuter","collectSyntaxHighlightRanges","isCursorInside","matches","occupied","isOverlapping","from","to","addMatch","className","classifyVariable","raw","strictMatch","createVariableExpressionRegexp","valid","fullStart","fullEnd","content","contentStart","contentVariableRegex","firstVariableMatch","percentClass","classification","varFrom","varTo","cursorInsideVar","operatorRanges","variableRanges","appliedTokenRanges","scanIndex","isEscape","operator","innerVariableMatch","innerVariableRegex","rawVariable","allTokens","token","stringStart","stringEnd","cursor","sortedApplied","appliedVariableRanges","sortedVariables","variable","buttonTextStart","buttonTextEnd","text","buildDecorations","view","builder","RangeSetBuilder","m","Decoration","e","SyntaxHighlighter","ViewPlugin","update","instance"],"mappings":";;;;AAYA,MAAMA,IAAqB,gBACrBC,IAAe,oBAKfC,IAAoB,IAAI;AAAA,EAC5B,UAAUC,EAAAA,0BAA0B;AAAA,EACpC;AACF;AAQA,SAASC,EACPC,GACwB;AACxB,QAAMC,IAAiC,CAAA;AACvC,MAAIC,IAA8B,MAC9BC,IAAY;AAEhB,SAAOA,KAAaH,EAAQ,UAAQ;AAClC,UAAMI,IAAeJ,EAAQ,QAAQ;AAAA,GAAMG,CAAS,GAC9CE,IAAUD,MAAiB,KAAKJ,EAAQ,SAASI;AAgBvD,QAfiBJ,EAAQ,MAAMG,GAAWE,CAAO,EAEpC,KAAA,MAAW,WAClBH,MAAiB,OACnBA,IAAeC,KAEfF,EAAO,KAAK;AAAA,MACV,MAAMC;AAAA,MACN,IAAIG;AAAA,MACJ,WAAW;AAAA,IAAA,CACZ,GACDH,IAAe,QAIfE,MAAiB;AACnB;AAGF,IAAAD,IAAYC,IAAe;AAAA,EAC7B;AAEA,SAAOH;AACT;AAEA,SAASK,EACPN,GACAO,GACwB;AACxB,QAAMN,IAAiC,CAAA;AACvC,MAAIO,IAAe;AAEnB,QAAMC,IAAkB,CAACC,MAAkB;AACzC,WACEF,IAAeD,EAAc,UAC7BA,EAAcC,CAAY,EAAE,MAAME;AAElC,MAAAF;AAGF,UAAMG,IAAQJ,EAAcC,CAAY;AACxC,WAAO,CAAC,CAACG,KAASD,KAASC,EAAM,QAAQD,IAAQC,EAAM;AAAA,EACzD;AAEA,MAAIR,IAAY;AAChB,SAAOA,KAAaH,EAAQ,UAAQ;AAClC,UAAMI,IAAeJ,EAAQ,QAAQ;AAAA,GAAMG,CAAS,GAC9CE,IAAUD,MAAiB,KAAKJ,EAAQ,SAASI,GACjDQ,IAAWZ,EAAQ,MAAMG,GAAWE,CAAO,GAC3CQ,IAA4B,CAAA;AAClC,QAAIC,IAAa;AAEjB,WAAOA,IAAaF,EAAS,UAAQ;AACnC,YAAMG,IAAeH,EAAS,QAAQ,OAAOE,CAAU;AACvD,UAAIC,MAAiB;AACnB;AAGF,YAAMC,IAAcb,IAAYY;AAEhC,MAAI,EADcC,IAAc,KAAKhB,EAAQgB,IAAc,CAAC,MAAM,QAChD,CAACP,EAAgBO,CAAW,KAC5CH,EAAgB,KAAKG,CAAW,GAGlCF,IAAaC,IAAe;AAAA,IAC9B;AAEA,aAASE,IAAI,GAAGA,IAAI,IAAIJ,EAAgB,QAAQI,KAAK;AACnD,MAAAhB,EAAO,KAAK;AAAA,QACV,MAAMY,EAAgBI,CAAC;AAAA,QACvB,IAAIJ,EAAgBI,IAAI,CAAC,IAAI;AAAA,QAC7B,WAAW;AAAA,MAAA,CACZ;AAGH,QAAIb,MAAiB;AACnB;AAGF,IAAAD,IAAYC,IAAe;AAAA,EAC7B;AAEA,SAAOH;AACT;AAEA,SAASiB,EAAqBlB,GAAyC;AACrE,QAAMC,IAAiC,CAAA;AACvC,MAAIkB;AAGJ,OADAvB,EAAa,YAAY,IACjBuB,IAAQvB,EAAa,KAAKI,CAAO,OAAO;AAC9C,IAAAC,EAAO,KAAK;AAAA,MACV,MAAMkB,EAAM;AAAA,MACZ,IAAIA,EAAM,QAAQA,EAAM,CAAC,EAAE;AAAA,MAC3B,WAAW;AAAA,IAAA,CACZ;AAGH,SAAOlB;AACT;AAQO,SAASmB,EACdpB,GACwB;AACxB,QAAMO,IAAgBW,EAAqBlB,CAAO,GAC5CqB,IAAc;AAAA,IAClB,GAAGtB,EAAkCC,CAAO;AAAA,IAC5C,GAAGM,EAAmCN,GAASO,CAAa;AAAA,IAC5D,GAAGA;AAAA,EAAA,EACH,KAAK,CAACe,GAAGC,MACLD,EAAE,SAASC,EAAE,OAAaD,EAAE,OAAOC,EAAE,OAClCA,EAAE,KAAKD,EAAE,EACjB,GAEKE,IAAsC,CAAA;AAE5C,aAAWb,KAASU,GAAa;AAC/B,UAAMI,IAAYD,EAAYA,EAAY,SAAS,CAAC;AACpD,KAAI,CAACC,KAAad,EAAM,QAAQc,EAAU,OACxCD,EAAY,KAAKb,CAAK;AAAA,EAE1B;AAEA,SAAOa;AACT;AASO,SAASE,EACd1B,GACA2B,IAAwD,MAAM,IACtC;AACxB,QAAMC,IAAkC,CAAA,GAClCC,IAA2C,CAAA;AAEjD,EAAAhC,EAAkB,YAAY;AAG9B,QAAMiC,IAAgB,CAACC,GAAcC,MACnCH,EAAS,KAAK,CAAClB,MAAU,EAAEqB,KAAMrB,EAAM,QAAQoB,KAAQpB,EAAM,GAAG,GAE5DsB,IAAW,CAACF,GAAcC,GAAYE,MACtCH,KAAQC,KACRF,EAAcC,GAAMC,CAAE,IAAU,MACpCH,EAAS,KAAK,EAAE,MAAAE,GAAM,IAAAC,EAAA,CAAI,GAC1BJ,EAAQ,KAAK,EAAE,MAAAG,GAAM,IAAAC,GAAI,WAAAE,GAAW,GAC7B,KAGHC,IAAmB,CAACC,MAAgB;AAExC,QAAI,CADUA,EAAI,MAAM,GAAG,EAAE,EAAE,KAAA,EACnB,QAAO,EAAE,WAAW,2BAA2B,OAAO,GAAA;AAElE,UAAMC,IADSC,EAAA,EACY,KAAKF,CAAG,GAC7BG,IACJ,CAAC,CAACF,KAAeA,EAAY,UAAU,KAAKA,EAAY,CAAC,MAAMD;AACjE,WAAO;AAAA,MACL,WAAWG,IAAQ,oBAAoB;AAAA,MACvC,OAAAA;AAAA,IAAA;AAAA,EAEJ;AAEA,MAAIpB;AAGJ,aAAWR,KAASS,EAAwBpB,CAAO;AACjD,IAAAiC,EAAStB,EAAM,MAAMA,EAAM,IAAIA,EAAM,SAAS;AAIhD,UAAQQ,IAAQtB,EAAkB,KAAKG,CAAO,OAAO,QAAM;AACzD,UAAMwC,IAAYrB,EAAM,OAClBsB,IAAUtB,EAAM,QAAQA,EAAM,CAAC,EAAE,QACjCuB,IAAUvB,EAAM,CAAC,GACjBwB,IAAeH,IAAY;AACjC,QAAI,CAAAV,EAAcU,GAAWC,CAAO;AASpC,UAJAR,EAASO,GAAWA,IAAY,GAAG,gBAAgB,GACnDP,EAASO,IAAY,GAAGA,IAAY,GAAG,gBAAgB,GACvDP,EAASQ,IAAU,GAAGA,GAAS,gBAAgB,GAE3CC,EAAQ,WAAW,GAAG,GAAG;AAE3B,cAAME,IAAuB,gBACvBC,IAAqBD,EAAqB,KAAKF,CAAO;AAC5D,QAAAE,EAAqB,YAAY;AACjC,YAAIE,IAAe;AACnB,YAAID,GAAoB;AACtB,gBAAME,IAAiBZ,EAAiBU,EAAmB,CAAC,CAAC,GACvDG,IAAUL,IAAeE,EAAmB,OAC5CI,IAAQD,IAAUH,EAAmB,CAAC,EAAE,QACxCK,IAAkBvB,EAAeqB,GAASC,CAAK;AACrD,UAAAH,IACEC,EAAe,SAAS,CAACG,IACrB,yBACA;AAAA,QACR;AACA,QAAAjB,EAASU,GAAcA,IAAe,GAAGG,CAAY;AAErD,cAAMK,IAAiD,CAAA,GACjDC,IACJ,CAAA,GACIC,IAAqD,CAAA;AAK3D,YAAIC,IAAY;AAChB,eAAOA,IAAYZ,EAAQ,UAAQ;AACjC,cAAIa,EAAAA,SAASb,GAASY,CAAS,GAAG;AAChC,YAAAA,KAAa;AACb;AAAA,UACF;AACA,gBAAME,IAAWd,EAAQ,WAAW,MAAMY,CAAS,IAC/C,OACAZ,EAAQY,CAAS,MAAM,MACrB,MACAZ,EAAQ,WAAW,OAAOY,CAAS,IACjC,QACA;AACR,cAAI,CAACE,GAAU;AACb,YAAAF,KAAa;AACb;AAAA,UACF;AACA,UAAAH,EAAe,KAAK;AAAA,YAClB,MAAMR,IAAeW;AAAA,YACrB,IAAIX,IAAeW,IAAYE,EAAS;AAAA,UAAA,CACzC,GACDF,KAAaE,EAAS;AAAA,QACxB;AAGA,YAAIC;AACJ,cAAMC,IAAqB;AAC3B,gBAAQD,IAAqBC,EAAmB,KAAKhB,CAAO,OAAO,QAAM;AACvE,gBAAMiB,IAAcF,EAAmB,CAAC,GAClCV,IAAiBZ,EAAiBwB,CAAW;AACnD,UAAAP,EAAe,KAAK;AAAA,YAClB,MAAMT,IAAec,EAAmB;AAAA,YACxC,IAAId,IAAec,EAAmB,QAAQE,EAAY;AAAA,YAC1D,WAAWZ,EAAe;AAAA,UAAA,CAC3B;AAAA,QACH;AAEA,cAAMa,IAAY;AAAA,UAChB,GAAGT,EAAe,IAAI,CAACxC,OAAW;AAAA,YAChC,GAAGA;AAAA,YACH,WAAW;AAAA,UAAA,EACX;AAAA,UACF,GAAGyC,EAAe,IAAI,CAACzC,OAAW;AAAA,YAChC,GAAGA;AAAA,YACH,WAAWA,EAAM;AAAA,UAAA,EACjB;AAAA,QAAA,EACF,KAAK,CAACW,GAAGC,MACLD,EAAE,SAASC,EAAE,OAAaD,EAAE,OAAOC,EAAE,OAClCD,EAAE,KAAKC,EAAE,EACjB;AAED,mBAAWsC,KAASD;AAClB,UACEC,EAAM,UAAU,WAAW,iBAAiB,KAC5ClC,EAAekC,EAAM,MAAMA,EAAM,EAAE,KAIjC5B,EAAS4B,EAAM,MAAMA,EAAM,IAAIA,EAAM,SAAS,KAChDR,EAAmB,KAAK,EAAE,MAAMQ,EAAM,MAAM,IAAIA,EAAM,IAAI;AAK9D,cAAMC,IAAcnB,IAAe,GAC7BoB,IAAYtB,IAAU;AAC5B,YAAIuB,IAASF;AACb,cAAMG,IAAgBZ,EAAmB,KAAK,CAAC/B,GAAGC,MAC5CD,EAAE,SAASC,EAAE,OAAaD,EAAE,OAAOC,EAAE,OAClCD,EAAE,KAAKC,EAAE,EACjB;AAED,mBAAWsC,KAASI;AAClB,UAAID,IAASH,EAAM,QACjB5B,EAAS+B,GAAQH,EAAM,MAAM,eAAe,GAE9CG,IAAS,KAAK,IAAIA,GAAQH,EAAM,EAAE;AAEpC,QAAIG,IAASD,KACX9B,EAAS+B,GAAQD,GAAW,eAAe;AAAA,MAE/C,OAAO;AAEL,cAAMX,IACJ,CAAA,GACIc,IAAwD,CAAA;AAE9D,YAAIT;AACJ,cAAMC,IAAqB;AAC3B,gBAAQD,IAAqBC,EAAmB,KAAKhB,CAAO,OAAO,QAAM;AACvE,gBAAMiB,IAAcF,EAAmB,CAAC,GAClCV,IAAiBZ,EAAiBwB,CAAW;AACnD,UAAAP,EAAe,KAAK;AAAA,YAClB,MAAMT,IAAec,EAAmB;AAAA,YACxC,IAAId,IAAec,EAAmB,QAAQE,EAAY;AAAA,YAC1D,WAAWZ,EAAe;AAAA,UAAA,CAC3B;AAAA,QACH;AAEA,cAAMoB,IAAkBf,EAAe,KAAK,CAAC9B,GAAGC,MAC1CD,EAAE,SAASC,EAAE,OAAaD,EAAE,OAAOC,EAAE,OAClCD,EAAE,KAAKC,EAAE,EACjB;AAED,mBAAW6C,KAAYD;AACrB,UACEC,EAAS,UAAU,WAAW,iBAAiB,KAC/CzC,EAAeyC,EAAS,MAAMA,EAAS,EAAE,KAIvCnC,EAASmC,EAAS,MAAMA,EAAS,IAAIA,EAAS,SAAS,KACzDF,EAAsB,KAAK,EAAE,MAAME,EAAS,MAAM,IAAIA,EAAS,IAAI;AAIvE,cAAMC,IAAkB1B,GAClB2B,IAAgB7B,IAAU;AAChC,YAAIuB,IAASK;AAEb,mBAAWD,KAAYF;AACrB,UAAIF,IAASI,EAAS,QACpBnC,EAAS+B,GAAQI,EAAS,MAAM,oBAAoB,GAEtDJ,IAAS,KAAK,IAAIA,GAAQI,EAAS,EAAE;AAEvC,QAAIJ,IAASM,KACXrC,EAAS+B,GAAQM,GAAe,oBAAoB;AAAA,MAExD;AAAA,EACF;AAIA,OADA3E,EAAmB,YAAY,IACvBwB,IAAQxB,EAAmB,KAAKK,CAAO,OAAO,QAAM;AAC1D,UAAMuE,IAAOpD,EAAM,CAAC,GACd4B,IAAiBZ,EAAiBoC,CAAI;AAC5C,IACExB,EAAe,SACf,CAACpB,EAAeR,EAAM,OAAOA,EAAM,QAAQA,EAAM,CAAC,EAAE,MAAM,KAE1Dc;AAAA,MACEd,EAAM;AAAA,MACNA,EAAM,QAAQA,EAAM,CAAC,EAAE;AAAA,MACvB4B,EAAe;AAAA,IAAA;AAAA,EAGrB;AAGA,SAAAnB,EAAQ,KAAK,CAACN,GAAGC,MACXD,EAAE,SAASC,EAAE,OAAaD,EAAE,OAAOC,EAAE,OAClCA,EAAE,KAAKD,EAAE,EACjB,GAEMM;AACT;AAEA,SAAS4C,EAAiBC,GAAiC;AACzD,QAAMC,IAAU,IAAIC,EAAA,GACd3E,IAAUyE,EAAK,MAAM,IAAI,SAAA,GACzB7C,IAAUF,EAA6B1B,GAAS,CAAC+B,GAAMC,MACpDyC,EAAK,MAAM,UAAU,OAAO,KAAK,CAAC9D,MAChCA,EAAM,QAAQoB,KAAQpB,EAAM,MAAMqB,CAC1C,CACF;AAED,aAAW4C,KAAKhD;AACd,QAAIgD,EAAE,OAAOA,EAAE;AACb,UAAI;AACF,QAAAF,EAAQ,IAAIE,EAAE,MAAMA,EAAE,IAAIC,EAAW,KAAK,EAAE,OAAOD,EAAE,UAAA,CAAW,CAAC;AAAA,MACnE,SAASE,GAAG;AACV,gBAAQ,KAAK,+CAA+CF,GAAGE,CAAC;AAAA,MAClE;AAIJ,SAAOJ,EAAQ,OAAA;AACjB;AAEA,MAAMK,IAAoBC,EAAW;AAAA,EACnC,MAAM;AAAA,IAGJ,YAAYP,GAAkB;AAC5B,WAAK,cAAcD,EAAiBC,CAAI;AAAA,IAC1C;AAAA,IAEA,OAAOQ,GAAoB;AACzB,OAAIA,EAAO,cAAcA,EAAO,mBAAmBA,EAAO,kBACxD,KAAK,cAAcT,EAAiBS,EAAO,IAAI;AAAA,IAEnD;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,aAAa,CAACC,MAAaA,EAAS;AAAA,EAAA;AAExC;"}
1
+ {"version":3,"file":"SyntaxHighlighter.es.js","sources":["../../../../src/components/MarkdownFlowEditor/plugins/SyntaxHighlighter.ts"],"sourcesContent":["import {\n Decoration,\n DecorationSet,\n EditorView,\n ViewPlugin,\n ViewUpdate,\n} from \"@codemirror/view\";\nimport { RangeSetBuilder } from \"@codemirror/state\";\nimport { INTERACTION_CONTENT_SOURCE, isEscape } from \"remark-flow\";\n\nimport { normalizeVariableName } from \"../utils\";\n\nconst broadVariableRegex = /\\{\\{.*?\\}\\}/g;\nconst commentRegex = /<!--[\\s\\S]*?-->/g;\n// The grammar's own definition of where an interaction ends, so a `\\]` an option escaped does\n// not cut the highlight short, and the same `(?!\\()` the parser uses, so `?[text](url)` stays a\n// markdown link. Taken from remark-flow rather than written again here: the editor and the\n// parser have to agree about what they are looking at.\nconst controlBlockRegex = new RegExp(\n `\\\\?\\\\[(${INTERACTION_CONTENT_SOURCE})\\\\](?!\\\\()`,\n \"g\"\n);\n\nexport interface SyntaxHighlightRange {\n from: number;\n to: number;\n className: string;\n}\n\nfunction collectMultilineFixedOutputRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let pendingStart: number | null = null;\n let lineStart = 0;\n\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n\n if (lineText.trim() === \"!===\") {\n if (pendingStart === null) {\n pendingStart = lineStart;\n } else {\n ranges.push({\n from: pendingStart,\n to: lineEnd,\n className: \"syntax-fixed\",\n });\n pendingStart = null;\n }\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectSingleLineFixedOutputRanges(\n docText: string,\n commentRanges: SyntaxHighlightRange[]\n): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let commentIndex = 0;\n\n const isInsideComment = (index: number) => {\n while (\n commentIndex < commentRanges.length &&\n commentRanges[commentIndex].to <= index\n ) {\n commentIndex++;\n }\n\n const range = commentRanges[commentIndex];\n return !!range && index >= range.from && index < range.to;\n };\n\n let lineStart = 0;\n while (lineStart <= docText.length) {\n const newlineIndex = docText.indexOf(\"\\n\", lineStart);\n const lineEnd = newlineIndex === -1 ? docText.length : newlineIndex;\n const lineText = docText.slice(lineStart, lineEnd);\n const markerPositions: number[] = [];\n let searchFrom = 0;\n\n while (searchFrom < lineText.length) {\n const markerOffset = lineText.indexOf(\"===\", searchFrom);\n if (markerOffset === -1) {\n break;\n }\n\n const markerIndex = lineStart + markerOffset;\n const isNegated = markerIndex > 0 && docText[markerIndex - 1] === \"!\";\n if (!isNegated && !isInsideComment(markerIndex)) {\n markerPositions.push(markerIndex);\n }\n\n searchFrom = markerOffset + 3;\n }\n\n for (let i = 0; i + 1 < markerPositions.length; i += 2) {\n ranges.push({\n from: markerPositions[i],\n to: markerPositions[i + 1] + 3,\n className: \"syntax-fixed\",\n });\n }\n\n if (newlineIndex === -1) {\n break;\n }\n\n lineStart = newlineIndex + 1;\n }\n\n return ranges;\n}\n\nfunction collectCommentRanges(docText: string): SyntaxHighlightRange[] {\n const ranges: SyntaxHighlightRange[] = [];\n let match;\n\n commentRegex.lastIndex = 0;\n while ((match = commentRegex.exec(docText)) !== null) {\n ranges.push({\n from: match.index,\n to: match.index + match[0].length,\n className: \"syntax-comment\",\n });\n }\n\n return ranges;\n}\n\n/**\n * Collects non-overlapping fixed-output and comment wrapper ranges.\n *\n * @param docText - Document text to scan.\n * @returns Outer syntax highlight ranges sorted by document position.\n */\nexport function collectOuterBlockRanges(\n docText: string\n): SyntaxHighlightRange[] {\n const commentRanges = collectCommentRanges(docText);\n const blockRanges = [\n ...collectMultilineFixedOutputRanges(docText),\n ...collectSingleLineFixedOutputRanges(docText, commentRanges),\n ...commentRanges,\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n const outerRanges: SyntaxHighlightRange[] = [];\n\n for (const range of blockRanges) {\n const lastOuter = outerRanges[outerRanges.length - 1];\n if (!lastOuter || range.from >= lastOuter.to) {\n outerRanges.push(range);\n }\n }\n\n return outerRanges;\n}\n\n/**\n * Collects all custom syntax highlight ranges for editor decorations.\n *\n * @param docText - Document text to scan.\n * @param isCursorInside - Returns true when the current cursor is inside a range.\n * @returns Non-overlapping syntax highlight ranges sorted by document position.\n */\nexport function collectSyntaxHighlightRanges(\n docText: string,\n isCursorInside: (from: number, to: number) => boolean = () => false\n): SyntaxHighlightRange[] {\n const matches: SyntaxHighlightRange[] = [];\n const occupied: { from: number; to: number }[] = [];\n\n controlBlockRegex.lastIndex = 0;\n\n // Prevent overlapping decorations so styling stays deterministic\n const isOverlapping = (from: number, to: number) =>\n occupied.some((range) => !(to <= range.from || from >= range.to));\n\n const addMatch = (from: number, to: number, className: string) => {\n if (from >= to) return false;\n if (isOverlapping(from, to)) return false;\n occupied.push({ from, to });\n matches.push({ from, to, className });\n return true;\n };\n\n const classifyVariable = (raw: string) => {\n const valid = normalizeVariableName(raw.slice(2, -2)) !== null;\n return {\n className: valid ? \"syntax-variable\" : \"syntax-variable-invalid\",\n valid,\n };\n };\n\n let match;\n\n // 1. Outer block ranges win over any syntax inside them.\n for (const range of collectOuterBlockRanges(docText)) {\n addMatch(range.from, range.to, range.className);\n }\n\n // 2. Control Blocks\n while ((match = controlBlockRegex.exec(docText)) !== null) {\n const fullStart = match.index;\n const fullEnd = match.index + match[0].length;\n const content = match[1];\n const contentStart = fullStart + 2; // after ?[\n if (isOverlapping(fullStart, fullEnd)) {\n continue;\n }\n\n // Outer brackets and question mark\n addMatch(fullStart, fullStart + 1, \"syntax-keyword\"); // ?\n addMatch(fullStart + 1, fullStart + 2, \"syntax-bracket\"); // [\n addMatch(fullEnd - 1, fullEnd, \"syntax-bracket\"); // ]\n\n if (content.startsWith(\"%\")) {\n // Input / Select\n const contentVariableRegex = new RegExp(broadVariableRegex.source, \"g\");\n const firstVariableMatch = contentVariableRegex.exec(content);\n contentVariableRegex.lastIndex = 0;\n let percentClass = \"syntax-percent-invalid\";\n if (firstVariableMatch?.index === 1) {\n const classification = classifyVariable(firstVariableMatch[0]);\n const varFrom = contentStart + firstVariableMatch.index;\n const varTo = varFrom + firstVariableMatch[0].length;\n const cursorInsideVar = isCursorInside(varFrom, varTo);\n percentClass =\n classification.valid && !cursorInsideVar\n ? \"syntax-percent-valid\"\n : \"syntax-percent-invalid\";\n }\n addMatch(contentStart, contentStart + 1, percentClass); // %\n\n const operatorRanges: { from: number; to: number }[] = [];\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedTokenRanges: { from: number; to: number }[] = [];\n\n // Keep a variable name atomic even when it contains option punctuation.\n for (const variableMatch of content.matchAll(broadVariableRegex)) {\n variableRanges.push({\n from: contentStart + variableMatch.index,\n to: contentStart + variableMatch.index + variableMatch[0].length,\n className: classifyVariable(variableMatch[0]).className,\n });\n }\n\n // Inner operators | || ... -- skipping any an option escaped, the way the parser does.\n // Painted as separators, they told the author the grammar had split an option that it\n // had in fact left whole.\n let scanIndex = 0;\n while (scanIndex < content.length) {\n const variable = variableRanges.find(\n (range) => contentStart + scanIndex === range.from\n );\n if (variable) {\n scanIndex = variable.to - contentStart;\n continue;\n }\n if (isEscape(content, scanIndex)) {\n scanIndex += 2;\n continue;\n }\n const operator = content.startsWith(\"||\", scanIndex)\n ? \"||\"\n : content[scanIndex] === \"|\"\n ? \"|\"\n : content.startsWith(\"...\", scanIndex)\n ? \"...\"\n : null;\n if (!operator) {\n scanIndex += 1;\n continue;\n }\n operatorRanges.push({\n from: contentStart + scanIndex,\n to: contentStart + scanIndex + operator.length,\n });\n scanIndex += operator.length;\n }\n\n const allTokens = [\n ...operatorRanges.map((range) => ({\n ...range,\n className: \"syntax-keyword\",\n })),\n ...variableRanges.map((range) => ({\n ...range,\n className: range.className,\n })),\n ].sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of allTokens) {\n if (\n token.className.startsWith(\"syntax-variable\") &&\n isCursorInside(token.from, token.to)\n ) {\n continue;\n }\n if (addMatch(token.from, token.to, token.className)) {\n appliedTokenRanges.push({ from: token.from, to: token.to });\n }\n }\n\n // Content (Dark Blue) for remaining text segments\n const stringStart = contentStart + 1;\n const stringEnd = fullEnd - 1;\n let cursor = stringStart;\n const sortedApplied = appliedTokenRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const token of sortedApplied) {\n if (cursor < token.from) {\n addMatch(cursor, token.from, \"syntax-string\");\n }\n cursor = Math.max(cursor, token.to);\n }\n if (cursor < stringEnd) {\n addMatch(cursor, stringEnd, \"syntax-string\");\n }\n } else {\n // Button ?[text]\n const variableRanges: { from: number; to: number; className: string }[] =\n [];\n const appliedVariableRanges: { from: number; to: number }[] = [];\n\n let innerVariableMatch;\n const innerVariableRegex = new RegExp(broadVariableRegex.source, \"g\");\n while ((innerVariableMatch = innerVariableRegex.exec(content)) !== null) {\n const rawVariable = innerVariableMatch[0];\n const classification = classifyVariable(rawVariable);\n variableRanges.push({\n from: contentStart + innerVariableMatch.index,\n to: contentStart + innerVariableMatch.index + rawVariable.length,\n className: classification.className,\n });\n }\n\n const sortedVariables = variableRanges.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return a.to - b.to;\n });\n\n for (const variable of sortedVariables) {\n if (\n variable.className.startsWith(\"syntax-variable\") &&\n isCursorInside(variable.from, variable.to)\n ) {\n continue;\n }\n if (addMatch(variable.from, variable.to, variable.className)) {\n appliedVariableRanges.push({ from: variable.from, to: variable.to });\n }\n }\n\n const buttonTextStart = contentStart;\n const buttonTextEnd = fullEnd - 1;\n let cursor = buttonTextStart;\n\n for (const variable of appliedVariableRanges) {\n if (cursor < variable.from) {\n addMatch(cursor, variable.from, \"syntax-button-text\");\n }\n cursor = Math.max(cursor, variable.to);\n }\n if (cursor < buttonTextEnd) {\n addMatch(cursor, buttonTextEnd, \"syntax-button-text\");\n }\n }\n }\n\n // 3. Variables (only if not already decorated; invalid ones stay default outside control blocks)\n broadVariableRegex.lastIndex = 0;\n while ((match = broadVariableRegex.exec(docText)) !== null) {\n const text = match[0];\n const classification = classifyVariable(text);\n if (\n classification.valid &&\n !isCursorInside(match.index, match.index + match[0].length)\n ) {\n addMatch(\n match.index,\n match.index + match[0].length,\n classification.className\n );\n }\n }\n\n // Sort matches by 'from' asc, then 'to' desc (longest first)\n matches.sort((a, b) => {\n if (a.from !== b.from) return a.from - b.from;\n return b.to - a.to;\n });\n\n return matches;\n}\n\nfunction buildDecorations(view: EditorView): DecorationSet {\n const builder = new RangeSetBuilder<Decoration>();\n const docText = view.state.doc.toString();\n const matches = collectSyntaxHighlightRanges(docText, (from, to) => {\n return view.state.selection.ranges.some((range) => {\n return range.from >= from && range.to <= to;\n });\n });\n\n for (const m of matches) {\n if (m.from < m.to) {\n try {\n builder.add(m.from, m.to, Decoration.mark({ class: m.className }));\n } catch (e) {\n console.warn(\"SyntaxHighlighter: Failed to add decoration\", m, e);\n }\n }\n }\n\n return builder.finish();\n}\n\nconst SyntaxHighlighter = ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n\n constructor(view: EditorView) {\n this.decorations = buildDecorations(view);\n }\n\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged || update.selectionSet) {\n this.decorations = buildDecorations(update.view);\n }\n }\n },\n {\n decorations: (instance) => instance.decorations,\n }\n);\n\nexport default SyntaxHighlighter;\n"],"names":["broadVariableRegex","commentRegex","controlBlockRegex","INTERACTION_CONTENT_SOURCE","collectMultilineFixedOutputRanges","docText","ranges","pendingStart","lineStart","newlineIndex","lineEnd","collectSingleLineFixedOutputRanges","commentRanges","commentIndex","isInsideComment","index","range","lineText","markerPositions","searchFrom","markerOffset","markerIndex","i","collectCommentRanges","match","collectOuterBlockRanges","blockRanges","a","b","outerRanges","lastOuter","collectSyntaxHighlightRanges","isCursorInside","matches","occupied","isOverlapping","from","to","addMatch","className","classifyVariable","raw","valid","normalizeVariableName","fullStart","fullEnd","content","contentStart","contentVariableRegex","firstVariableMatch","percentClass","classification","varFrom","varTo","cursorInsideVar","operatorRanges","variableRanges","appliedTokenRanges","variableMatch","scanIndex","variable","isEscape","operator","allTokens","token","stringStart","stringEnd","cursor","sortedApplied","appliedVariableRanges","innerVariableMatch","innerVariableRegex","rawVariable","sortedVariables","buttonTextStart","buttonTextEnd","text","buildDecorations","view","builder","RangeSetBuilder","m","Decoration","e","SyntaxHighlighter","ViewPlugin","update","instance"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./types.cjs"),E=require("./utils/video.cjs"),g="[\\p{L}\\p{N}_]+",h=new RegExp(`^${g}$`,"u"),w=`\\{\\{(${g})\\}\\}`,c="===",$=()=>new RegExp(w,"gu"),f=t=>typeof t=="string"&&h.test(t),V=t=>{if(!t)return[];const e=[],a=$();let r;for(;(r=a.exec(t))!==null;)e.push(r[1]);return e},x=(t,e)=>{switch(t){case p.SelectedOption.Image:return{resourceUrl:e.url,resourceTitle:e.title,scalePercent:e.scalePercent};case p.SelectedOption.Video:return{resourceUrl:e.url,resourceTitle:e.title};case p.SelectedOption.Variable:return{variableName:e.title};default:return{resourceUrl:e.url??"",resourceTitle:e.title??""}}};function S(t,e){return a=>{const r=a.matchBefore(/\/(\w*)$/);if(!r)return null;const l=(n,o,i,s,d)=>{n.dispatch({changes:{from:i,to:s,insert:""}}),t(d)};return{from:r.from,to:r.to,options:[{label:e?.variable??"Variable",apply:(n,o,i,s)=>{l(n,o,i,s,p.SelectedOption.Variable)}},{label:e?.image??"Image",apply:(n,o,i,s)=>{l(n,o,i,s,p.SelectedOption.Image)}},{label:e?.video??"Video",apply:(n,o,i,s)=>{l(n,o,i,s,p.SelectedOption.Video)}}],filter:!1}}}const b=t=>E.getVideoEmbedUrl(t),u=t=>t.replace(/&/g,"&amp;").replace(/"/g,"&quot;"),I=t=>t.replace(/([\[\]\\])/g,"\\$1"),R=t=>Math.max(1,Math.min(1e3,Math.round(t))),m=t=>{const e=t.trim();return e?new RegExp(`^${c}\\s*[\\s\\S]*?\\s*${c}$`).test(e)?e:`${c} ${e} ${c}`:`${c}${c}`},O=t=>{const e=t.trim(),a=new RegExp(`^${c}\\s*([\\s\\S]*?)\\s*${c}$`);return(e.match(a)?.[1]??e).trim()},A=({resourceUrl:t,resourceTitle:e,scalePercent:a})=>{const r=typeof a=="number"?R(a):void 0,l=u(t),n=e?u(e):void 0,o=e?I(e):"",i=typeof r=="number"&&r!==100?` width="${r}%"`:"",s=n?` alt="${n}" title="${n}"`:"",d=!r||r===100?`![${o}](${t})`:`<img src="${l}"${s}${i} />`;return m(d)},T=(t,e)=>{const a=b(t),r=e?u(e):"",l=u(t),n=u(a),o=`<iframe data-tag="video" data-title="${r}" data-url="${l}" class="w-full aspect-video rounded-lg border-0" src="${n}" allowfullscreen="" allow="autoplay; encrypted-media"></iframe>`;return m(o)};exports.createSlashCommands=S;exports.createVariableExpressionRegexp=$;exports.extractVariableNames=V;exports.getEmbedUrl=b;exports.getImageContentToInsert=A;exports.getVideoContentToInsert=T;exports.isValidVariableName=f;exports.parseContentInfo=x;exports.unwrapFixedOutput=O;exports.wrapWithFixedOutput=m;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("./types.cjs"),$=require("./utils/video.cjs"),m=require("../../_virtual/index.cjs"),s="===",x=()=>m.distExports.createVariableExpressionRegex("gu"),f=(t,e)=>{switch(t){case d.SelectedOption.Image:return{resourceUrl:e.url,resourceTitle:e.title,scalePercent:e.scalePercent};case d.SelectedOption.Video:return{resourceUrl:e.url,resourceTitle:e.title};case d.SelectedOption.Variable:return{variableName:e.title};default:return{resourceUrl:e.url??"",resourceTitle:e.title??""}}};function w(t,e){return o=>{const n=o.matchBefore(/\/(\w*)$/);if(!n)return null;const c=(r,a,i,l,u)=>{r.dispatch({changes:{from:i,to:l,insert:""}}),t(u)};return{from:n.from,to:n.to,options:[{label:e?.variable??"Variable",apply:(r,a,i,l)=>{c(r,a,i,l,d.SelectedOption.Variable)}},{label:e?.image??"Image",apply:(r,a,i,l)=>{c(r,a,i,l,d.SelectedOption.Image)}},{label:e?.video??"Video",apply:(r,a,i,l)=>{c(r,a,i,l,d.SelectedOption.Video)}}],filter:!1}}}const b=t=>$.getVideoEmbedUrl(t),p=t=>t.replace(/&/g,"&amp;").replace(/"/g,"&quot;"),h=t=>t.replace(/([\[\]\\])/g,"\\$1"),V=t=>Math.max(1,Math.min(1e3,Math.round(t))),g=t=>{const e=t.trim();return e?new RegExp(`^${s}\\s*[\\s\\S]*?\\s*${s}$`).test(e)?e:`${s} ${e} ${s}`:`${s}${s}`},S=t=>{const e=t.trim(),o=new RegExp(`^${s}\\s*([\\s\\S]*?)\\s*${s}$`);return(e.match(o)?.[1]??e).trim()},E=({resourceUrl:t,resourceTitle:e,scalePercent:o})=>{const n=typeof o=="number"?V(o):void 0,c=p(t),r=e?p(e):void 0,a=e?h(e):"",i=typeof n=="number"&&n!==100?` width="${n}%"`:"",l=r?` alt="${r}" title="${r}"`:"",u=!n||n===100?`![${a}](${t})`:`<img src="${c}"${l}${i} />`;return g(u)},I=(t,e)=>{const o=b(t),n=e?p(e):"",c=p(t),r=p(o),a=`<iframe data-tag="video" data-title="${n}" data-url="${c}" class="w-full aspect-video rounded-lg border-0" src="${r}" allowfullscreen="" allow="autoplay; encrypted-media"></iframe>`;return g(a)};exports.createSlashCommands=w;exports.createVariableExpressionRegexp=x;exports.extractVariableNames=m.distExports.extractVariableNames;exports.getEmbedUrl=b;exports.getImageContentToInsert=E;exports.getVideoContentToInsert=I;exports.normalizeVariableName=m.distExports.normalizeVariableName;exports.parseContentInfo=f;exports.unwrapFixedOutput=S;exports.wrapWithFixedOutput=g;
2
2
  //# sourceMappingURL=utils.cjs.map