@useinsider/ab-components 0.0.121 → 0.0.122
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.
- package/dist/ab-components.cjs.js +83 -81
- package/dist/ab-components.cjs.js.map +1 -1
- package/dist/ab-components.es.js +17 -16
- package/dist/ab-components.iife.js +86 -84
- package/dist/ab-components.iife.js.map +1 -1
- package/dist/ab-components.umd.js +86 -84
- package/dist/ab-components.umd.js.map +1 -1
- package/dist/{index-C5Z39dyx.js → index-BiQ459-D.js} +1155 -1125
- package/dist/{index-C5Z39dyx.js.map → index-BiQ459-D.js.map} +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/{liquid-DKvAYGwv.js → liquid-h4_E6Y81.js} +2 -2
- package/dist/{liquid-DKvAYGwv.js.map → liquid-h4_E6Y81.js.map} +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -823,6 +823,19 @@ declare interface DropdownProps {
|
|
|
823
823
|
validateAddItem?: (item: string, items: MenuItem_2[]) => string | null;
|
|
824
824
|
}
|
|
825
825
|
|
|
826
|
+
/**
|
|
827
|
+
* The subset of {@link getLiquidVariables} that is actually PRINTED to the user
|
|
828
|
+
* via a `{{ }}` output — as opposed to variables referenced only in control flow
|
|
829
|
+
* (`{% if x %}`, `{% for p in items %}`), which never render a value.
|
|
830
|
+
*
|
|
831
|
+
* A variable counts as printed when any of its references falls inside an output
|
|
832
|
+
* token. `{% if x %}{{ x }}{% endif %}` therefore reports `x` (it is printed on
|
|
833
|
+
* one branch); `{% if x %}…{% endif %}` alone does not.
|
|
834
|
+
*
|
|
835
|
+
* Same empty/invalid-input contract as {@link getLiquidVariables}.
|
|
836
|
+
*/
|
|
837
|
+
export declare function getLiquidOutputVariables(code: string): string[];
|
|
838
|
+
|
|
826
839
|
/**
|
|
827
840
|
* External (global) variables referenced by `{{ }}` / `{% %}` in a Liquid
|
|
828
841
|
* snippet, as full dotted paths (e.g. `e_purchase.amount`), de-duplicated.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as f } from "./index-
|
|
1
|
+
import { L as f } from "./index-BiQ459-D.js";
|
|
2
2
|
const g = new f(), h = /* @__PURE__ */ new Set(["if", "unless", "for", "case", "capture", "comment", "raw", "tablerow"]), w = {
|
|
3
3
|
endif: "if",
|
|
4
4
|
endunless: "unless",
|
|
@@ -149,4 +149,4 @@ export {
|
|
|
149
149
|
S as findUnknownVariables,
|
|
150
150
|
u as positionAt
|
|
151
151
|
};
|
|
152
|
-
//# sourceMappingURL=liquid-
|
|
152
|
+
//# sourceMappingURL=liquid-h4_E6Y81.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"liquid-DKvAYGwv.js","sources":["../src/components/MonacoEditor/validators/liquid.ts"],"sourcesContent":["// cspell:ignore liquidjs endunless endcapture endcomment endraw tablerow endtablerow elsif forloop tablerowloop\nimport type { editor as Editor } from 'monaco-editor';\nimport { Liquid } from 'liquidjs';\n\n// Parse-only engine: validates Liquid syntax, mirroring the liquid.js grammar\n// Pandora renders with. Used as a fallback for expression/filter errors that the\n// structural scan below doesn't cover. Undefined variables/filters are NOT errors\n// here — those only surface server-side at render time.\nconst engine = new Liquid();\n\ninterface LiquidErrorInfo {\n line: number;\n column: number;\n message: string;\n}\n\ninterface LiquidLikeError {\n message?: string;\n token?: { getPosition?: () => [number, number] };\n}\n\n// Block tags that must be closed by a matching `end<tag>`.\nconst BLOCK_OPENERS = new Set(['if', 'unless', 'for', 'case', 'capture', 'comment', 'raw', 'tablerow']);\nconst BLOCK_CLOSERS: Record<string, string> = {\n endif: 'if',\n endunless: 'unless',\n endfor: 'for',\n endcase: 'case',\n endcapture: 'capture',\n endcomment: 'comment',\n endraw: 'raw',\n endtablerow: 'tablerow',\n};\n\nexport function positionAt(value: string, index: number): { line: number; column: number } {\n let line = 1;\n let lastBreak = -1;\n\n for (let i = 0; i < index; i += 1) {\n if (value[i] === '\\n') {\n line += 1;\n lastBreak = i;\n }\n }\n\n return { line, column: index - lastBreak };\n}\n\n/**\n * Structural scan reporting EVERY broken delimiter and unbalanced block tag, so\n * each faulty line gets its own marker. `liquidjs.parse` only throws on the\n * first error, which is why we can't rely on it for multi-error highlighting.\n */\nexport function findStructuralErrors(value: string): LiquidErrorInfo[] {\n const errors: LiquidErrorInfo[] = [];\n const blockStack: { tag: string; index: number }[] = [];\n const delimiters = /\\{\\{|\\}\\}|\\{%|%\\}/g;\n\n let openType: '{{' | '{%' | null = null;\n let openIndex = -1;\n // While inside `{% comment %}`/`{% raw %}`, ignore inner block tags.\n let rawBlock: string | null = null;\n let match = delimiters.exec(value);\n\n while (match !== null) {\n const token = match[0];\n\n if (token === '{{' || token === '{%') {\n if (openType) {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Unclosed ${openType} — '${openType === '{{' ? '}}' : '%}'}' expected.` });\n }\n\n openType = token;\n openIndex = match.index;\n } else if (openType) {\n const expected = openType === '{{' ? '}}' : '%}';\n\n if (token !== expected) {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Mismatched delimiter — '${expected}' expected.` });\n } else if (openType === '{%') {\n const word = value.slice(openIndex + 2, match.index).trim().split(/\\s+/)[0] ?? '';\n\n if (rawBlock) {\n if (word === `end${rawBlock}`) {\n blockStack.pop();\n rawBlock = null;\n }\n } else if (BLOCK_OPENERS.has(word)) {\n blockStack.push({ tag: word, index: openIndex });\n\n if (word === 'comment' || word === 'raw') {\n rawBlock = word;\n }\n } else {\n const opener = BLOCK_CLOSERS[word];\n\n if (opener) {\n if (blockStack.length > 0 && blockStack[blockStack.length - 1].tag === opener) {\n blockStack.pop();\n } else {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Unexpected {% ${word} %}.` });\n }\n }\n }\n }\n\n openType = null;\n openIndex = -1;\n }\n\n match = delimiters.exec(value);\n }\n\n if (openType) {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Unclosed ${openType}.` });\n }\n\n blockStack.forEach(block => {\n const pos = positionAt(value, block.index);\n\n errors.push({ ...pos, message: `Unclosed {% ${block.tag} %} — '{% end${block.tag} %}' missing.` });\n });\n\n return errors;\n}\n\n// Liquid built-ins / literals that are valid inside `{{ }}` without being a\n// dynamic-content variable or a locally-assigned one.\nconst BUILTIN_VARS = new Set(['true', 'false', 'nil', 'null', 'empty', 'blank', 'forloop', 'tablerowloop']);\n\n// Variables introduced locally by the template itself (so they're not \"unknown\").\nexport function collectLocalVariables(value: string): Set<string> {\n const locals = new Set<string>();\n const assignRe = /\\{%-?\\s*(?:assign|capture)\\s+([a-zA-Z_]\\w*)/g;\n const loopRe = /\\{%-?\\s*(?:for|tablerow)\\s+([a-zA-Z_]\\w*)\\s+in\\b/g;\n\n let match = assignRe.exec(value);\n\n while (match !== null) {\n locals.add(match[1]);\n match = assignRe.exec(value);\n }\n\n match = loopRe.exec(value);\n\n while (match !== null) {\n locals.add(match[1]);\n match = loopRe.exec(value);\n }\n\n return locals;\n}\n\n/**\n * Flags `{{ output }}` whose variable is neither a known dynamic-content key, a\n * locally-assigned variable, nor a built-in/literal. Skipped entirely when no\n * known keys are supplied (e.g. the dynamic-content list hasn't loaded yet), to\n * avoid false positives.\n */\nexport function findUnknownVariables(value: string, knownKeys: string[]): LiquidErrorInfo[] {\n const errors: LiquidErrorInfo[] = [];\n const known = new Set<string>(BUILTIN_VARS);\n\n knownKeys.forEach(key => {\n known.add(key);\n\n const [root] = key.split('.');\n\n if (root) {\n known.add(root);\n }\n });\n\n collectLocalVariables(value).forEach(local => known.add(local));\n\n const outputRe = /\\{\\{-?([\\s\\S]*?)-?\\}\\}/g;\n let match = outputRe.exec(value);\n\n while (match !== null) {\n const expression = (match[1].split('|')[0] ?? '').trim();\n const token = expression.match(/^[a-zA-Z_][\\w.]*/)?.[0];\n\n if (token) {\n const [root] = token.split('.');\n\n if (!known.has(token) && !known.has(root)) {\n errors.push({ ...positionAt(value, match.index), message: `Unknown dynamic content variable: ${token}` });\n }\n }\n\n match = outputRe.exec(value);\n }\n\n return errors;\n}\n\nfunction getEnginePosition(error: unknown): { line: number; column: number } {\n const token = (error as LiquidLikeError)?.token;\n\n if (token && typeof token.getPosition === 'function') {\n const [line, column] = token.getPosition();\n\n return { line: line || 1, column: column || 1 };\n }\n\n const message = (error as LiquidLikeError)?.message ?? '';\n const match = message.match(/line:(\\d+),\\s*col:(\\d+)/);\n\n if (match) {\n return { line: Number(match[1]), column: Number(match[2]) };\n }\n\n return { line: 1, column: 1 };\n}\n\nconst liquidValidator = (\n editor: Editor.IStandaloneCodeEditor,\n monaco: typeof import('monaco-editor/esm/vs/editor/editor.api'),\n knownKeys: string[] = []\n) => {\n const model = editor.getModel();\n\n if (!model) {\n return {\n valid: true,\n results: [],\n };\n }\n\n const value = editor.getValue();\n const toMarker = (info: LiquidErrorInfo): Editor.IMarkerData => ({\n startLineNumber: info.line,\n endLineNumber: info.line,\n startColumn: info.column,\n endColumn: info.column + 1,\n message: info.message,\n severity: monaco.MarkerSeverity.Error,\n });\n\n // 1. Structural scan + unknown-variable scan — one marker per broken line.\n const structural = [\n ...findStructuralErrors(value),\n ...(knownKeys.length > 0 ? findUnknownVariables(value, knownKeys) : []),\n ];\n\n if (structural.length > 0) {\n const markers = structural.map(toMarker);\n\n monaco.editor.setModelMarkers(model, 'owner', markers);\n\n return {\n valid: false,\n results: markers,\n };\n }\n\n // 2. Fallback: liquidjs catches expression/filter errors (single error).\n try {\n engine.parse(value);\n\n monaco.editor.setModelMarkers(model, 'owner', []);\n\n return {\n valid: true,\n results: [],\n };\n } catch (error) {\n const marker = toMarker({\n ...getEnginePosition(error),\n message: (error as LiquidLikeError)?.message ?? 'Invalid Liquid syntax',\n });\n\n monaco.editor.setModelMarkers(model, 'owner', [marker]);\n\n return {\n valid: false,\n results: [marker],\n };\n }\n};\n\nexport default liquidValidator;\n"],"names":["engine","Liquid","BLOCK_OPENERS","BLOCK_CLOSERS","positionAt","value","index","line","lastBreak","i","findStructuralErrors","errors","blockStack","delimiters","openType","openIndex","rawBlock","match","token","pos","expected","word","opener","block","BUILTIN_VARS","collectLocalVariables","locals","assignRe","loopRe","findUnknownVariables","knownKeys","known","key","root","local","outputRe","_a","getEnginePosition","error","column","liquidValidator","editor","monaco","model","toMarker","info","structural","markers","marker"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"liquid-h4_E6Y81.js","sources":["../src/components/MonacoEditor/validators/liquid.ts"],"sourcesContent":["// cspell:ignore liquidjs endunless endcapture endcomment endraw tablerow endtablerow elsif forloop tablerowloop\nimport type { editor as Editor } from 'monaco-editor';\nimport { Liquid } from 'liquidjs';\n\n// Parse-only engine: validates Liquid syntax, mirroring the liquid.js grammar\n// Pandora renders with. Used as a fallback for expression/filter errors that the\n// structural scan below doesn't cover. Undefined variables/filters are NOT errors\n// here — those only surface server-side at render time.\nconst engine = new Liquid();\n\ninterface LiquidErrorInfo {\n line: number;\n column: number;\n message: string;\n}\n\ninterface LiquidLikeError {\n message?: string;\n token?: { getPosition?: () => [number, number] };\n}\n\n// Block tags that must be closed by a matching `end<tag>`.\nconst BLOCK_OPENERS = new Set(['if', 'unless', 'for', 'case', 'capture', 'comment', 'raw', 'tablerow']);\nconst BLOCK_CLOSERS: Record<string, string> = {\n endif: 'if',\n endunless: 'unless',\n endfor: 'for',\n endcase: 'case',\n endcapture: 'capture',\n endcomment: 'comment',\n endraw: 'raw',\n endtablerow: 'tablerow',\n};\n\nexport function positionAt(value: string, index: number): { line: number; column: number } {\n let line = 1;\n let lastBreak = -1;\n\n for (let i = 0; i < index; i += 1) {\n if (value[i] === '\\n') {\n line += 1;\n lastBreak = i;\n }\n }\n\n return { line, column: index - lastBreak };\n}\n\n/**\n * Structural scan reporting EVERY broken delimiter and unbalanced block tag, so\n * each faulty line gets its own marker. `liquidjs.parse` only throws on the\n * first error, which is why we can't rely on it for multi-error highlighting.\n */\nexport function findStructuralErrors(value: string): LiquidErrorInfo[] {\n const errors: LiquidErrorInfo[] = [];\n const blockStack: { tag: string; index: number }[] = [];\n const delimiters = /\\{\\{|\\}\\}|\\{%|%\\}/g;\n\n let openType: '{{' | '{%' | null = null;\n let openIndex = -1;\n // While inside `{% comment %}`/`{% raw %}`, ignore inner block tags.\n let rawBlock: string | null = null;\n let match = delimiters.exec(value);\n\n while (match !== null) {\n const token = match[0];\n\n if (token === '{{' || token === '{%') {\n if (openType) {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Unclosed ${openType} — '${openType === '{{' ? '}}' : '%}'}' expected.` });\n }\n\n openType = token;\n openIndex = match.index;\n } else if (openType) {\n const expected = openType === '{{' ? '}}' : '%}';\n\n if (token !== expected) {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Mismatched delimiter — '${expected}' expected.` });\n } else if (openType === '{%') {\n const word = value.slice(openIndex + 2, match.index).trim().split(/\\s+/)[0] ?? '';\n\n if (rawBlock) {\n if (word === `end${rawBlock}`) {\n blockStack.pop();\n rawBlock = null;\n }\n } else if (BLOCK_OPENERS.has(word)) {\n blockStack.push({ tag: word, index: openIndex });\n\n if (word === 'comment' || word === 'raw') {\n rawBlock = word;\n }\n } else {\n const opener = BLOCK_CLOSERS[word];\n\n if (opener) {\n if (blockStack.length > 0 && blockStack[blockStack.length - 1].tag === opener) {\n blockStack.pop();\n } else {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Unexpected {% ${word} %}.` });\n }\n }\n }\n }\n\n openType = null;\n openIndex = -1;\n }\n\n match = delimiters.exec(value);\n }\n\n if (openType) {\n const pos = positionAt(value, openIndex);\n\n errors.push({ ...pos, message: `Unclosed ${openType}.` });\n }\n\n blockStack.forEach(block => {\n const pos = positionAt(value, block.index);\n\n errors.push({ ...pos, message: `Unclosed {% ${block.tag} %} — '{% end${block.tag} %}' missing.` });\n });\n\n return errors;\n}\n\n// Liquid built-ins / literals that are valid inside `{{ }}` without being a\n// dynamic-content variable or a locally-assigned one.\nconst BUILTIN_VARS = new Set(['true', 'false', 'nil', 'null', 'empty', 'blank', 'forloop', 'tablerowloop']);\n\n// Variables introduced locally by the template itself (so they're not \"unknown\").\nexport function collectLocalVariables(value: string): Set<string> {\n const locals = new Set<string>();\n const assignRe = /\\{%-?\\s*(?:assign|capture)\\s+([a-zA-Z_]\\w*)/g;\n const loopRe = /\\{%-?\\s*(?:for|tablerow)\\s+([a-zA-Z_]\\w*)\\s+in\\b/g;\n\n let match = assignRe.exec(value);\n\n while (match !== null) {\n locals.add(match[1]);\n match = assignRe.exec(value);\n }\n\n match = loopRe.exec(value);\n\n while (match !== null) {\n locals.add(match[1]);\n match = loopRe.exec(value);\n }\n\n return locals;\n}\n\n/**\n * Flags `{{ output }}` whose variable is neither a known dynamic-content key, a\n * locally-assigned variable, nor a built-in/literal. Skipped entirely when no\n * known keys are supplied (e.g. the dynamic-content list hasn't loaded yet), to\n * avoid false positives.\n */\nexport function findUnknownVariables(value: string, knownKeys: string[]): LiquidErrorInfo[] {\n const errors: LiquidErrorInfo[] = [];\n const known = new Set<string>(BUILTIN_VARS);\n\n knownKeys.forEach(key => {\n known.add(key);\n\n const [root] = key.split('.');\n\n if (root) {\n known.add(root);\n }\n });\n\n collectLocalVariables(value).forEach(local => known.add(local));\n\n const outputRe = /\\{\\{-?([\\s\\S]*?)-?\\}\\}/g;\n let match = outputRe.exec(value);\n\n while (match !== null) {\n const expression = (match[1].split('|')[0] ?? '').trim();\n const token = expression.match(/^[a-zA-Z_][\\w.]*/)?.[0];\n\n if (token) {\n const [root] = token.split('.');\n\n if (!known.has(token) && !known.has(root)) {\n errors.push({ ...positionAt(value, match.index), message: `Unknown dynamic content variable: ${token}` });\n }\n }\n\n match = outputRe.exec(value);\n }\n\n return errors;\n}\n\nfunction getEnginePosition(error: unknown): { line: number; column: number } {\n const token = (error as LiquidLikeError)?.token;\n\n if (token && typeof token.getPosition === 'function') {\n const [line, column] = token.getPosition();\n\n return { line: line || 1, column: column || 1 };\n }\n\n const message = (error as LiquidLikeError)?.message ?? '';\n const match = message.match(/line:(\\d+),\\s*col:(\\d+)/);\n\n if (match) {\n return { line: Number(match[1]), column: Number(match[2]) };\n }\n\n return { line: 1, column: 1 };\n}\n\nconst liquidValidator = (\n editor: Editor.IStandaloneCodeEditor,\n monaco: typeof import('monaco-editor/esm/vs/editor/editor.api'),\n knownKeys: string[] = []\n) => {\n const model = editor.getModel();\n\n if (!model) {\n return {\n valid: true,\n results: [],\n };\n }\n\n const value = editor.getValue();\n const toMarker = (info: LiquidErrorInfo): Editor.IMarkerData => ({\n startLineNumber: info.line,\n endLineNumber: info.line,\n startColumn: info.column,\n endColumn: info.column + 1,\n message: info.message,\n severity: monaco.MarkerSeverity.Error,\n });\n\n // 1. Structural scan + unknown-variable scan — one marker per broken line.\n const structural = [\n ...findStructuralErrors(value),\n ...(knownKeys.length > 0 ? findUnknownVariables(value, knownKeys) : []),\n ];\n\n if (structural.length > 0) {\n const markers = structural.map(toMarker);\n\n monaco.editor.setModelMarkers(model, 'owner', markers);\n\n return {\n valid: false,\n results: markers,\n };\n }\n\n // 2. Fallback: liquidjs catches expression/filter errors (single error).\n try {\n engine.parse(value);\n\n monaco.editor.setModelMarkers(model, 'owner', []);\n\n return {\n valid: true,\n results: [],\n };\n } catch (error) {\n const marker = toMarker({\n ...getEnginePosition(error),\n message: (error as LiquidLikeError)?.message ?? 'Invalid Liquid syntax',\n });\n\n monaco.editor.setModelMarkers(model, 'owner', [marker]);\n\n return {\n valid: false,\n results: [marker],\n };\n }\n};\n\nexport default liquidValidator;\n"],"names":["engine","Liquid","BLOCK_OPENERS","BLOCK_CLOSERS","positionAt","value","index","line","lastBreak","i","findStructuralErrors","errors","blockStack","delimiters","openType","openIndex","rawBlock","match","token","pos","expected","word","opener","block","BUILTIN_VARS","collectLocalVariables","locals","assignRe","loopRe","findUnknownVariables","knownKeys","known","key","root","local","outputRe","_a","getEnginePosition","error","column","liquidValidator","editor","monaco","model","toMarker","info","structural","markers","marker"],"mappings":"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"}
|