@samva/markup 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -0
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/dist/ast-DAhnAvQN.d.ts +120 -0
- package/dist/ast.d.ts +2 -0
- package/dist/ast.js +159 -0
- package/dist/ast.js.map +1 -0
- package/dist/candidate.d.ts +29 -0
- package/dist/candidate.js +88 -0
- package/dist/candidate.js.map +1 -0
- package/dist/checks-CW0nFj5n.js +58922 -0
- package/dist/checks-CW0nFj5n.js.map +1 -0
- package/dist/checks.d.ts +26 -0
- package/dist/checks.js +2 -0
- package/dist/classes.d.ts +27 -0
- package/dist/classes.js +184 -0
- package/dist/classes.js.map +1 -0
- package/dist/compile-sms.d.ts +28 -0
- package/dist/compile-sms.js +44 -0
- package/dist/compile-sms.js.map +1 -0
- package/dist/compile-whatsapp.d.ts +56 -0
- package/dist/compile-whatsapp.js +186 -0
- package/dist/compile-whatsapp.js.map +1 -0
- package/dist/compile.d.ts +93 -0
- package/dist/compile.js +938 -0
- package/dist/compile.js.map +1 -0
- package/dist/components.d.ts +289 -0
- package/dist/components.js +106 -0
- package/dist/components.js.map +1 -0
- package/dist/conditionals.d.ts +10 -0
- package/dist/conditionals.js +42 -0
- package/dist/conditionals.js.map +1 -0
- package/dist/diagnostics-oveE-laV.d.ts +79 -0
- package/dist/diagnostics.d.ts +2 -0
- package/dist/diagnostics.js +62 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/emit.d.ts +50 -0
- package/dist/emit.js +151 -0
- package/dist/emit.js.map +1 -0
- package/dist/footer.d.ts +66 -0
- package/dist/footer.js +90 -0
- package/dist/footer.js.map +1 -0
- package/dist/interpolate.d.ts +27 -0
- package/dist/interpolate.js +61 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +10 -0
- package/dist/jsx-dev-runtime.js +7 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime-fSxcvlx4.d.ts +57 -0
- package/dist/jsx-runtime.d.ts +2 -0
- package/dist/jsx-runtime.js +102 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/lexer.d.ts +60 -0
- package/dist/lexer.js +269 -0
- package/dist/lexer.js.map +1 -0
- package/dist/model.d.ts +39 -0
- package/dist/model.js +90 -0
- package/dist/model.js.map +1 -0
- package/dist/ops.d.ts +208 -0
- package/dist/ops.js +546 -0
- package/dist/ops.js.map +1 -0
- package/dist/parser-yzjUOGhc.d.ts +387 -0
- package/dist/parser.d.ts +2 -0
- package/dist/parser.js +821 -0
- package/dist/parser.js.map +1 -0
- package/dist/predicate-DTtVtLK7.d.ts +49 -0
- package/dist/predicate.d.ts +2 -0
- package/dist/predicate.js +417 -0
- package/dist/predicate.js.map +1 -0
- package/dist/presets/category-mapping.d.ts +13 -0
- package/dist/presets/category-mapping.js +49 -0
- package/dist/presets/category-mapping.js.map +1 -0
- package/dist/presets/public-gallery.d.ts +490 -0
- package/dist/presets/public-gallery.js +563 -0
- package/dist/presets/public-gallery.js.map +1 -0
- package/dist/presets/public-handoff.d.ts +68 -0
- package/dist/presets/public-handoff.js +105 -0
- package/dist/presets/public-handoff.js.map +1 -0
- package/dist/presets/public-preview-artifacts.d.ts +41 -0
- package/dist/presets/public-preview-artifacts.js +109 -0
- package/dist/presets/public-preview-artifacts.js.map +1 -0
- package/dist/presets/public-preview.d.ts +1168 -0
- package/dist/presets/public-preview.js +1158 -0
- package/dist/presets/public-preview.js.map +1 -0
- package/dist/presets/sources.d.ts +7 -0
- package/dist/presets/sources.js +54 -0
- package/dist/presets/sources.js.map +1 -0
- package/dist/presets.d.ts +350 -0
- package/dist/presets.js +1251 -0
- package/dist/presets.js.map +1 -0
- package/dist/printer.d.ts +6 -0
- package/dist/printer.js +122 -0
- package/dist/printer.js.map +1 -0
- package/dist/registry.d.ts +42 -0
- package/dist/registry.js +646 -0
- package/dist/registry.js.map +1 -0
- package/dist/render-template.d.ts +42 -0
- package/dist/render-template.js +74 -0
- package/dist/render-template.js.map +1 -0
- package/dist/sms-segments-y4FpPilJ.d.ts +13 -0
- package/dist/sms-segments.d.ts +2 -0
- package/dist/sms-segments.js +46 -0
- package/dist/sms-segments.js.map +1 -0
- package/dist/theme-6ApjjiBo.d.ts +116 -0
- package/dist/theme-css.d.ts +24 -0
- package/dist/theme-css.js +509 -0
- package/dist/theme-css.js.map +1 -0
- package/dist/theme.d.ts +2 -0
- package/dist/theme.js +95 -0
- package/dist/theme.js.map +1 -0
- package/dist/tokens.d.ts +6 -0
- package/dist/tokens.js +417 -0
- package/dist/tokens.js.map +1 -0
- package/dist/variables-3NGLpNTB.d.ts +77 -0
- package/dist/variables.d.ts +2 -0
- package/dist/variables.js +141 -0
- package/dist/variables.js.map +1 -0
- package/dist/version-BITr58kk.js +96 -0
- package/dist/version-BITr58kk.js.map +1 -0
- package/generated/sml-agent-contract.json +917 -0
- package/generated/sml-email-agent-contract.json +790 -0
- package/generated/sml-email-language-reference.md +160 -0
- package/generated/sml-language-reference.md +220 -0
- package/package.json +203 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicate.js","names":[],"sources":["../src/predicate.ts"],"sourcesContent":["import { Result } from \"effect\";\n\nimport type { Diagnostic, Span } from \"./diagnostics\";\n\n// Closed predicate grammar for <If test=\"...\"> (design brief §7c):\n//\n// expr := or\n// or := and (\"or\" and)*\n// and := unary (\"and\" unary)*\n// unary := \"not\"? primary\n// primary := \"(\" expr \")\" | comparison | name\n// comparison := name op literal op ∈ { == != > >= < <= }\n// literal := 'single-quoted string' | number\n//\n// Bare name = present-and-non-empty. NO arithmetic, calls, methods, or paths.\n// This one module (parse / evaluate / print / collect) is shared by the\n// compiler (artifact markers), checks, send-time branch selection, and the\n// canvas — the semantics cannot fork.\n//\n// String literals have no escape syntax and may not contain `--`: predicates\n// are embedded verbatim in HTML comment markers, and `--` would terminate the\n// comment early.\n\nexport type ComparisonOp = \"==\" | \"!=\" | \">\" | \">=\" | \"<\" | \"<=\";\n\nexport type PredicateLiteral =\n | { readonly kind: \"string\"; readonly value: string }\n | { readonly kind: \"number\"; readonly value: number };\n\nexport type PredicateAst =\n | {\n readonly kind: \"or\";\n readonly left: PredicateAst;\n readonly right: PredicateAst;\n readonly span: Span;\n }\n | {\n readonly kind: \"and\";\n readonly left: PredicateAst;\n readonly right: PredicateAst;\n readonly span: Span;\n }\n | { readonly kind: \"not\"; readonly operand: PredicateAst; readonly span: Span }\n | {\n readonly kind: \"comparison\";\n readonly name: string;\n readonly op: ComparisonOp;\n readonly literal: PredicateLiteral;\n readonly span: Span;\n }\n | { readonly kind: \"name\"; readonly name: string; readonly span: Span };\n\n// ── Lexer ─────────────────────────────────────────────────────────────────────\n\nconst CHAR_TAB = 9;\nconst CHAR_LINE_FEED = 10;\nconst CHAR_CARRIAGE_RETURN = 13;\nconst CHAR_SPACE = 32;\nconst CHAR_BANG = 33;\nconst CHAR_SINGLE_QUOTE = 39;\nconst CHAR_OPEN_PAREN = 40;\nconst CHAR_CLOSE_PAREN = 41;\nconst CHAR_MINUS = 45;\nconst CHAR_DOT = 46;\nconst CHAR_LESS_THAN = 60;\nconst CHAR_EQUALS = 61;\nconst CHAR_GREATER_THAN = 62;\nconst CHAR_UNDERSCORE = 95;\nconst CHAR_0 = 48;\nconst CHAR_9 = 57;\nconst CHAR_UPPER_A = 65;\nconst CHAR_UPPER_Z = 90;\nconst CHAR_LOWER_A = 97;\nconst CHAR_LOWER_Z = 122;\n\nconst isWhitespace = (code: number): boolean =>\n code === CHAR_SPACE ||\n code === CHAR_TAB ||\n code === CHAR_LINE_FEED ||\n code === CHAR_CARRIAGE_RETURN;\n\nconst isDigit = (code: number): boolean => code >= CHAR_0 && code <= CHAR_9;\n\nconst isLetter = (code: number): boolean =>\n (code >= CHAR_UPPER_A && code <= CHAR_UPPER_Z) || (code >= CHAR_LOWER_A && code <= CHAR_LOWER_Z);\n\nconst isNameStart = (code: number): boolean => isLetter(code) || code === CHAR_UNDERSCORE;\n\nconst isNameChar = (code: number): boolean => isNameStart(code) || isDigit(code);\n\ntype PredicateTokenKind = \"name\" | \"number\" | \"string\" | \"op\" | \"lparen\" | \"rparen\" | \"eof\";\n\ninterface PredicateToken {\n readonly kind: PredicateTokenKind;\n /** Absolute span (baseOffset already applied). */\n readonly span: Span;\n /** Name text or operator text. */\n readonly text: string;\n /** String literal contents (without quotes). */\n readonly string?: string | undefined;\n /** Number literal value. */\n readonly number?: number | undefined;\n}\n\nconst KEYWORDS = [\"and\", \"or\", \"not\"] as const;\n\nconst isKeyword = (text: string): boolean => (KEYWORDS as ReadonlyArray<string>).includes(text);\n\ninterface LexFailure {\n readonly diagnostic: Diagnostic;\n}\n\nconst tokenize = (\n source: string,\n baseOffset: number,\n): Result.Result<ReadonlyArray<PredicateToken>, LexFailure> => {\n const tokens: Array<PredicateToken> = [];\n let index = 0;\n const length = source.length;\n\n const failAt = (code: string, message: string, start: number, end: number) =>\n Result.fail<LexFailure>({\n diagnostic: { code, message, span: { start: baseOffset + start, end: baseOffset + end } },\n });\n\n while (index < length) {\n const code = source.charCodeAt(index);\n if (isWhitespace(code)) {\n index++;\n continue;\n }\n const start = index;\n\n if (code === CHAR_OPEN_PAREN) {\n index++;\n tokens.push({\n kind: \"lparen\",\n text: \"(\",\n span: { start: baseOffset + start, end: baseOffset + index },\n });\n continue;\n }\n if (code === CHAR_CLOSE_PAREN) {\n index++;\n tokens.push({\n kind: \"rparen\",\n text: \")\",\n span: { start: baseOffset + start, end: baseOffset + index },\n });\n continue;\n }\n\n if (code === CHAR_EQUALS || code === CHAR_BANG) {\n if (source.charCodeAt(index + 1) === CHAR_EQUALS) {\n index += 2;\n tokens.push({\n kind: \"op\",\n text: code === CHAR_EQUALS ? \"==\" : \"!=\",\n span: { start: baseOffset + start, end: baseOffset + index },\n });\n continue;\n }\n const found = String.fromCharCode(code);\n const fix = code === CHAR_EQUALS ? \"write == to compare\" : \"write != to compare\";\n return failAt(\"predicate-invalid-operator\", `unexpected ${found} — ${fix}`, start, start + 1);\n }\n if (code === CHAR_GREATER_THAN || code === CHAR_LESS_THAN) {\n index++;\n if (source.charCodeAt(index) === CHAR_EQUALS) index++;\n tokens.push({\n kind: \"op\",\n text: source.slice(start, index),\n span: { start: baseOffset + start, end: baseOffset + index },\n });\n continue;\n }\n\n if (code === CHAR_SINGLE_QUOTE) {\n index++;\n const contentStart = index;\n while (index < length && source.charCodeAt(index) !== CHAR_SINGLE_QUOTE) index++;\n if (index >= length) {\n return failAt(\n \"predicate-unterminated-string\",\n \"unterminated string — add a closing '\",\n start,\n length,\n );\n }\n const value = source.slice(contentStart, index);\n index++;\n if (value.includes(\"--\")) {\n return failAt(\n \"predicate-string-double-dash\",\n \"string literals cannot contain -- (predicates are embedded in HTML comment markers)\",\n start,\n index,\n );\n }\n tokens.push({\n kind: \"string\",\n text: source.slice(start, index),\n string: value,\n span: { start: baseOffset + start, end: baseOffset + index },\n });\n continue;\n }\n\n if (isDigit(code) || (code === CHAR_MINUS && isDigit(source.charCodeAt(index + 1)))) {\n index++;\n while (index < length && isDigit(source.charCodeAt(index))) index++;\n if (source.charCodeAt(index) === CHAR_DOT && isDigit(source.charCodeAt(index + 1))) {\n index++;\n while (index < length && isDigit(source.charCodeAt(index))) index++;\n }\n tokens.push({\n kind: \"number\",\n text: source.slice(start, index),\n number: Number.parseFloat(source.slice(start, index)),\n span: { start: baseOffset + start, end: baseOffset + index },\n });\n continue;\n }\n\n if (isNameStart(code)) {\n index++;\n while (index < length && isNameChar(source.charCodeAt(index))) index++;\n if (source.charCodeAt(index) === CHAR_DOT) {\n return failAt(\n \"predicate-path-not-supported\",\n `unexpected . after \"${source.slice(start, index)}\" — predicates use flat variable names, not paths`,\n start,\n index + 1,\n );\n }\n tokens.push({\n kind: \"name\",\n text: source.slice(start, index),\n span: { start: baseOffset + start, end: baseOffset + index },\n });\n continue;\n }\n\n if (code === CHAR_DOT) {\n return failAt(\n \"predicate-path-not-supported\",\n \"unexpected . — predicates use flat variable names, not paths\",\n start,\n start + 1,\n );\n }\n return failAt(\n \"predicate-unexpected-character\",\n `unexpected character ${JSON.stringify(String.fromCharCode(code))} in predicate`,\n start,\n start + 1,\n );\n }\n\n tokens.push({\n kind: \"eof\",\n text: \"\",\n span: { start: baseOffset + length, end: baseOffset + length },\n });\n return Result.succeed(tokens);\n};\n\n// ── Parser ────────────────────────────────────────────────────────────────────\n\nconst COMPARISON_OPS: ReadonlyArray<ComparisonOp> = [\"==\", \"!=\", \">\", \">=\", \"<\", \"<=\"];\n\n/**\n * Parses a predicate. `baseOffset` is the absolute source offset of the\n * predicate's first character (an <If> test attribute passes valueSpan.start),\n * so diagnostic and node spans point into the containing document.\n */\nexport const parsePredicate = (\n source: string,\n baseOffset = 0,\n): Result.Result<PredicateAst, ReadonlyArray<Diagnostic>> => {\n const lexed = tokenize(source, baseOffset);\n if (Result.isFailure(lexed)) return Result.fail([lexed.failure.diagnostic]);\n const tokens = lexed.success;\n let index = 0;\n let diagnostic: Diagnostic | undefined;\n\n const fail = (code: string, message: string, span: Span): null => {\n diagnostic ??= { code, message, span };\n return null;\n };\n\n const peek = (): PredicateToken => tokens[index]!;\n const advance = (): PredicateToken => tokens[index++]!;\n\n const isKeywordToken = (token: PredicateToken, keyword: string): boolean =>\n token.kind === \"name\" && token.text === keyword;\n\n const parsePrimary = (): PredicateAst | null => {\n const token = advance();\n if (token.kind === \"lparen\") {\n const inner = parseOr();\n if (inner === null) return null;\n const close = advance();\n if (close.kind !== \"rparen\") {\n return fail(\"predicate-missing-paren\", \"missing ) — close the group\", close.span);\n }\n return inner;\n }\n if (token.kind === \"name\") {\n if (isKeyword(token.text)) {\n return fail(\n \"predicate-unexpected-token\",\n `unexpected \"${token.text}\" — expected a variable name, comparison, or ( group )`,\n token.span,\n );\n }\n const opToken = peek();\n if (opToken.kind !== \"op\") {\n return { kind: \"name\", name: token.text, span: token.span };\n }\n advance();\n const op = COMPARISON_OPS.find((candidate) => candidate === opToken.text);\n if (op === undefined) {\n return fail(\n \"predicate-invalid-operator\",\n `unknown operator ${opToken.text} — use ==, !=, >, >=, <, or <=`,\n opToken.span,\n );\n }\n const literalToken = advance();\n if (literalToken.kind === \"string\") {\n return {\n kind: \"comparison\",\n name: token.text,\n op,\n literal: { kind: \"string\", value: literalToken.string! },\n span: { start: token.span.start, end: literalToken.span.end },\n };\n }\n if (literalToken.kind === \"number\") {\n return {\n kind: \"comparison\",\n name: token.text,\n op,\n literal: { kind: \"number\", value: literalToken.number! },\n span: { start: token.span.start, end: literalToken.span.end },\n };\n }\n return fail(\n \"predicate-expected-literal\",\n `expected a literal after ${op} — write ${token.text} ${op} 'value' or ${token.text} ${op} 5`,\n literalToken.span,\n );\n }\n if (token.kind === \"eof\") {\n return fail(\n \"predicate-unexpected-end\",\n \"unexpected end of predicate — expected a variable name, comparison, or ( group )\",\n token.span,\n );\n }\n return fail(\n \"predicate-unexpected-token\",\n `unexpected ${token.text} — comparisons put the variable first: name == 'value'`,\n token.span,\n );\n };\n\n const parseUnary = (): PredicateAst | null => {\n const token = peek();\n if (isKeywordToken(token, \"not\")) {\n advance();\n const operand = parsePrimary();\n if (operand === null) return null;\n return {\n kind: \"not\",\n operand,\n span: { start: token.span.start, end: operand.span.end },\n };\n }\n return parsePrimary();\n };\n\n const parseAnd = (): PredicateAst | null => {\n let left = parseUnary();\n while (left !== null && isKeywordToken(peek(), \"and\")) {\n advance();\n const right = parseUnary();\n if (right === null) return null;\n left = {\n kind: \"and\",\n left,\n right,\n span: { start: left.span.start, end: right.span.end },\n };\n }\n return left;\n };\n\n const parseOr = (): PredicateAst | null => {\n let left = parseAnd();\n while (left !== null && isKeywordToken(peek(), \"or\")) {\n advance();\n const right = parseAnd();\n if (right === null) return null;\n left = {\n kind: \"or\",\n left,\n right,\n span: { start: left.span.start, end: right.span.end },\n };\n }\n return left;\n };\n\n if (source.trim().length === 0) {\n return Result.fail([\n {\n code: \"predicate-empty\",\n message: \"empty predicate — write e.g. plan == 'pro'\",\n span: { start: baseOffset, end: baseOffset + source.length },\n },\n ]);\n }\n\n const ast = parseOr();\n if (ast !== null && diagnostic === undefined) {\n const trailing = peek();\n if (trailing.kind !== \"eof\") {\n fail(\n \"predicate-trailing-input\",\n `unexpected ${JSON.stringify(trailing.text)} after the predicate — join clauses with \"and\" or \"or\"`,\n trailing.span,\n );\n }\n }\n if (ast === null || diagnostic !== undefined) {\n return Result.fail([\n diagnostic ?? {\n code: \"predicate-parse-failed\",\n message: \"predicate parse failed\",\n span: { start: baseOffset, end: baseOffset + source.length },\n },\n ]);\n }\n return Result.succeed(ast);\n};\n\n// ── Evaluation ────────────────────────────────────────────────────────────────\n\nconst toNumber = (value: unknown): number => {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\" && value.trim() !== \"\") return Number(value);\n return Number.NaN;\n};\n\nconst compareNumbers = (op: ComparisonOp, left: number, right: number): boolean => {\n switch (op) {\n case \"==\":\n return left === right;\n case \"!=\":\n return left !== right;\n case \">\":\n return left > right;\n case \">=\":\n return left >= right;\n case \"<\":\n return left < right;\n case \"<=\":\n return left <= right;\n }\n};\n\nconst evaluateComparison = (\n node: Extract<PredicateAst, { kind: \"comparison\" }>,\n variables: Record<string, unknown>,\n): boolean => {\n const value = variables[node.name];\n // Missing variable ⇒ comparison is false — for != too: absence is not a\n // value that differs, it is no value at all (brief §7c).\n if (value === undefined || value === null) return false;\n if (node.literal.kind === \"number\") {\n const left = toNumber(value);\n if (Number.isNaN(left)) return false;\n return compareNumbers(node.op, left, node.literal.value);\n }\n if (node.op === \"==\" || node.op === \"!=\") {\n if (typeof value !== \"string\") return false;\n return node.op === \"==\" ? value === node.literal.value : value !== node.literal.value;\n }\n // Ordering against a string literal: numeric ops coerce numbers; a\n // non-numeric side is a type mismatch ⇒ false.\n const left = toNumber(value);\n const right = toNumber(node.literal.value);\n if (Number.isNaN(left) || Number.isNaN(right)) return false;\n return compareNumbers(node.op, left, right);\n};\n\nexport const evaluatePredicate = (\n ast: PredicateAst,\n variables: Record<string, unknown>,\n): boolean => {\n switch (ast.kind) {\n case \"or\":\n return evaluatePredicate(ast.left, variables) || evaluatePredicate(ast.right, variables);\n case \"and\":\n return evaluatePredicate(ast.left, variables) && evaluatePredicate(ast.right, variables);\n case \"not\":\n return !evaluatePredicate(ast.operand, variables);\n case \"comparison\":\n return evaluateComparison(ast, variables);\n case \"name\": {\n const value = variables[ast.name];\n return value !== undefined && value !== null && value !== \"\";\n }\n }\n};\n\n// ── Printing ──────────────────────────────────────────────────────────────────\n\nconst precedence = (node: PredicateAst): number => {\n switch (node.kind) {\n case \"or\":\n return 1;\n case \"and\":\n return 2;\n case \"not\":\n return 3;\n case \"comparison\":\n case \"name\":\n return 4;\n }\n};\n\nconst printLiteral = (literal: PredicateLiteral): string =>\n literal.kind === \"string\" ? `'${literal.value}'` : String(literal.value);\n\nconst printNode = (node: PredicateAst, minPrecedence: number): string => {\n const wrap = (text: string): string => (precedence(node) < minPrecedence ? `(${text})` : text);\n switch (node.kind) {\n case \"or\":\n return wrap(`${printNode(node.left, 1)} or ${printNode(node.right, 1)}`);\n case \"and\":\n return wrap(`${printNode(node.left, 2)} and ${printNode(node.right, 2)}`);\n case \"not\":\n // The grammar allows \"not\" only before a primary — parenthesize anything\n // looser so print ∘ parse is a fixpoint.\n return wrap(`not ${printNode(node.operand, 4)}`);\n case \"comparison\":\n return wrap(`${node.name} ${node.op} ${printLiteral(node.literal)}`);\n case \"name\":\n return wrap(node.name);\n }\n};\n\n/** Canonical form: single space around operators/keywords, minimal parens. */\nexport const printPredicate = (ast: PredicateAst): string => printNode(ast, 0);\n\n// ── Variable collection ───────────────────────────────────────────────────────\n\nexport const collectPredicateVariables = (ast: PredicateAst): Set<string> => {\n const names = new Set<string>();\n const visit = (node: PredicateAst): void => {\n switch (node.kind) {\n case \"or\":\n case \"and\":\n visit(node.left);\n visit(node.right);\n return;\n case \"not\":\n visit(node.operand);\n return;\n case \"comparison\":\n case \"name\":\n names.add(node.name);\n return;\n }\n };\n visit(ast);\n return names;\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PresetCategory } from "../presets.js";
|
|
2
|
+
import { TemplateCollectionId } from "./public-gallery.js";
|
|
3
|
+
//#region presets/category-mapping.d.ts
|
|
4
|
+
declare const LAB_DIMENSIONS: readonly ["newsletter", "receipt", "security", "product-update", "onboarding", "promotion", "shipping", "social-notification"];
|
|
5
|
+
type LabDimension = (typeof LAB_DIMENSIONS)[number];
|
|
6
|
+
declare const LAB_KINDS: readonly ["newsletter", "receipt", "security", "product-update", "onboarding", "promotion", "shipping", "social-notification", "digest", "invoice", "account", "event", "statement", "developer-notification", "unknown"];
|
|
7
|
+
type LabKind = (typeof LAB_KINDS)[number];
|
|
8
|
+
declare const labKindToPresetCategory: Record<LabKind, PresetCategory>;
|
|
9
|
+
declare const presetCategoryToCollection: Record<PresetCategory, TemplateCollectionId>;
|
|
10
|
+
declare const labKindToCollection: (kind: LabKind) => TemplateCollectionId;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { LAB_DIMENSIONS, LAB_KINDS, LabDimension, LabKind, labKindToCollection, labKindToPresetCategory, presetCategoryToCollection };
|
|
13
|
+
//# sourceMappingURL=category-mapping.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//#region presets/category-mapping.ts
|
|
2
|
+
const LAB_DIMENSIONS = [
|
|
3
|
+
"newsletter",
|
|
4
|
+
"receipt",
|
|
5
|
+
"security",
|
|
6
|
+
"product-update",
|
|
7
|
+
"onboarding",
|
|
8
|
+
"promotion",
|
|
9
|
+
"shipping",
|
|
10
|
+
"social-notification"
|
|
11
|
+
];
|
|
12
|
+
const LAB_KINDS = [
|
|
13
|
+
...LAB_DIMENSIONS,
|
|
14
|
+
"digest",
|
|
15
|
+
"invoice",
|
|
16
|
+
"account",
|
|
17
|
+
"event",
|
|
18
|
+
"statement",
|
|
19
|
+
"developer-notification",
|
|
20
|
+
"unknown"
|
|
21
|
+
];
|
|
22
|
+
const labKindToPresetCategory = {
|
|
23
|
+
newsletter: "digest",
|
|
24
|
+
receipt: "transactional",
|
|
25
|
+
security: "transactional",
|
|
26
|
+
"product-update": "marketing",
|
|
27
|
+
onboarding: "lifecycle",
|
|
28
|
+
promotion: "marketing",
|
|
29
|
+
shipping: "transactional",
|
|
30
|
+
"social-notification": "transactional",
|
|
31
|
+
digest: "digest",
|
|
32
|
+
invoice: "transactional",
|
|
33
|
+
account: "transactional",
|
|
34
|
+
event: "marketing",
|
|
35
|
+
statement: "transactional",
|
|
36
|
+
"developer-notification": "transactional",
|
|
37
|
+
unknown: "transactional"
|
|
38
|
+
};
|
|
39
|
+
const presetCategoryToCollection = {
|
|
40
|
+
transactional: "category:transactional",
|
|
41
|
+
digest: "category:digest-editorial",
|
|
42
|
+
marketing: "category:marketing",
|
|
43
|
+
lifecycle: "category:lifecycle"
|
|
44
|
+
};
|
|
45
|
+
const labKindToCollection = (kind) => presetCategoryToCollection[labKindToPresetCategory[kind]];
|
|
46
|
+
//#endregion
|
|
47
|
+
export { LAB_DIMENSIONS, LAB_KINDS, labKindToCollection, labKindToPresetCategory, presetCategoryToCollection };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=category-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"category-mapping.js","names":[],"sources":["../../presets/category-mapping.ts"],"sourcesContent":["import type { PresetCategory } from \"./catalog\";\nimport type { TemplateCollectionId } from \"./public-gallery\";\n\n// One reconciliation point for the category vocabularies that meet when SML Email\n// Lab corpus is promoted into the preset registry and surfaced in the public\n// gallery. The preset catalog `category` (catalog.ts) is the canonical axis: the\n// lab's classification folds into it, and it binds 1:1 to the public gallery's\n// `category`-family collection.\n//\n// The platform's generic message-template categories are deliberately NOT\n// merged here. No preset flow writes them. Preset category stays the corpus\n// axis; the two vocabularies are distinct by design, not by oversight.\n\n// ── SML Email Lab taxonomy (external repo, mirrored here) ────────────────────\n// The 8 corpus dimensions the lab classifies candidates by.\nexport const LAB_DIMENSIONS = [\n \"newsletter\",\n \"receipt\",\n \"security\",\n \"product-update\",\n \"onboarding\",\n \"promotion\",\n \"shipping\",\n \"social-notification\",\n] as const;\nexport type LabDimension = (typeof LAB_DIMENSIONS)[number];\n\n// The full 15-kind classification: the 8 dimensions plus finer/utility kinds the\n// lab emits. `unknown` is the lab's fallback bucket for unclassified candidates.\nexport const LAB_KINDS = [\n ...LAB_DIMENSIONS,\n \"digest\",\n \"invoice\",\n \"account\",\n \"event\",\n \"statement\",\n \"developer-notification\",\n \"unknown\",\n] as const;\nexport type LabKind = (typeof LAB_KINDS)[number];\n\n// ── lab kind → preset category ──────────────────────────────────────────────\n// Total over LAB_KINDS. `unknown` falls to `transactional`: the most\n// conservative bucket (no marketing/list semantics), safe to re-classify later.\nexport const labKindToPresetCategory: Record<LabKind, PresetCategory> = {\n newsletter: \"digest\",\n receipt: \"transactional\",\n security: \"transactional\",\n \"product-update\": \"marketing\",\n onboarding: \"lifecycle\",\n promotion: \"marketing\",\n shipping: \"transactional\",\n \"social-notification\": \"transactional\",\n digest: \"digest\",\n invoice: \"transactional\",\n account: \"transactional\",\n event: \"marketing\",\n statement: \"transactional\",\n \"developer-notification\": \"transactional\",\n unknown: \"transactional\",\n};\n\n// ── preset category → public-gallery `category`-family collection ────────────\n// A bijection onto the four `category:*` collections in public-gallery.ts. The\n// other collection families (industry/stage/style) are per-template secondary\n// axes and are assigned on each PublicTemplate, not derivable from category.\nexport const presetCategoryToCollection: Record<PresetCategory, TemplateCollectionId> = {\n transactional: \"category:transactional\",\n digest: \"category:digest-editorial\",\n marketing: \"category:marketing\",\n lifecycle: \"category:lifecycle\",\n};\n\n// Convenience: fold a lab kind straight to its public `category`-family collection.\nexport const labKindToCollection = (kind: LabKind): TemplateCollectionId =>\n presetCategoryToCollection[labKindToPresetCategory[kind]];\n"],"mappings":";AAeA,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAKA,MAAa,YAAY;CACvB,GAAG;CACH;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAMA,MAAa,0BAA2D;CACtE,YAAY;CACZ,SAAS;CACT,UAAU;CACV,kBAAkB;CAClB,YAAY;CACZ,WAAW;CACX,UAAU;CACV,uBAAuB;CACvB,QAAQ;CACR,SAAS;CACT,SAAS;CACT,OAAO;CACP,WAAW;CACX,0BAA0B;CAC1B,SAAS;AACX;AAMA,MAAa,6BAA2E;CACtF,eAAe;CACf,QAAQ;CACR,WAAW;CACX,WAAW;AACb;AAGA,MAAa,uBAAuB,SAClC,2BAA2B,wBAAwB"}
|