@maizzle/framework 6.0.0-rc.20 → 6.0.0-rc.22
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/build.d.ts.map +1 -1
- package/dist/build.js +53 -43
- package/dist/build.js.map +1 -1
- package/dist/components/Body.vue +1 -1
- package/dist/components/CodeBlock.vue +1 -1
- package/dist/components/CodeInline.vue +72 -2
- package/dist/components/Column.vue +2 -1
- package/dist/components/Container.vue +1 -11
- package/dist/components/Img.vue +199 -4
- package/dist/components/Preheader.vue +33 -5
- package/dist/components/Section.vue +9 -14
- package/dist/components/Text.vue +1 -1
- package/dist/composables/defineConfig.d.ts +3 -4
- package/dist/composables/defineConfig.d.ts.map +1 -1
- package/dist/composables/defineConfig.js +3 -4
- package/dist/composables/defineConfig.js.map +1 -1
- package/dist/composables/renderContext.d.ts +1 -2
- package/dist/composables/renderContext.d.ts.map +1 -1
- package/dist/composables/renderContext.js.map +1 -1
- package/dist/composables/useCurrentTemplate.d.ts +31 -0
- package/dist/composables/useCurrentTemplate.d.ts.map +1 -0
- package/dist/composables/useCurrentTemplate.js +35 -0
- package/dist/composables/useCurrentTemplate.js.map +1 -0
- package/dist/composables/useEvent.d.ts +1 -1
- package/dist/composables/useEvent.js +1 -1
- package/dist/composables/useEvent.js.map +1 -1
- package/dist/composables/usePreheader.d.ts +6 -5
- package/dist/composables/usePreheader.d.ts.map +1 -1
- package/dist/composables/usePreheader.js +3 -3
- package/dist/composables/usePreheader.js.map +1 -1
- package/dist/composables/useTransformers.d.ts +1 -1
- package/dist/composables/useTransformers.js +1 -1
- package/dist/composables/useTransformers.js.map +1 -1
- package/dist/events/index.d.ts +20 -8
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +5 -8
- package/dist/events/index.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/render/createRenderer.js +4 -3
- package/dist/render/createRenderer.js.map +1 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +3 -2
- package/dist/serve.js.map +1 -1
- package/dist/transformers/addAttributes.d.ts +18 -8
- package/dist/transformers/addAttributes.d.ts.map +1 -1
- package/dist/transformers/addAttributes.js +22 -8
- package/dist/transformers/addAttributes.js.map +1 -1
- package/dist/transformers/columnWidth.d.ts.map +1 -1
- package/dist/transformers/columnWidth.js +136 -150
- package/dist/transformers/columnWidth.js.map +1 -1
- package/dist/transformers/entities.d.ts.map +1 -1
- package/dist/transformers/entities.js +1 -0
- package/dist/transformers/entities.js.map +1 -1
- package/dist/transformers/index.d.ts.map +1 -1
- package/dist/transformers/index.js +7 -5
- package/dist/transformers/index.js.map +1 -1
- package/dist/transformers/inlineCss.js +2 -7
- package/dist/transformers/inlineCss.js.map +1 -1
- package/dist/transformers/inlineLink.js +2 -2
- package/dist/transformers/inlineLink.js.map +1 -1
- package/dist/transformers/minifyCodeInline.d.ts +29 -0
- package/dist/transformers/minifyCodeInline.d.ts.map +1 -0
- package/dist/transformers/minifyCodeInline.js +36 -0
- package/dist/transformers/minifyCodeInline.js.map +1 -0
- package/dist/transformers/msoPlaceholders.d.ts +10 -5
- package/dist/transformers/msoPlaceholders.d.ts.map +1 -1
- package/dist/transformers/msoPlaceholders.js +38 -7
- package/dist/transformers/msoPlaceholders.js.map +1 -1
- package/dist/transformers/safeSelectors.d.ts +37 -0
- package/dist/transformers/safeSelectors.d.ts.map +1 -0
- package/dist/transformers/{safeClassNames.js → safeSelectors.js} +24 -5
- package/dist/transformers/safeSelectors.js.map +1 -0
- package/dist/transformers/shorthandCss.js +38 -7
- package/dist/transformers/shorthandCss.js.map +1 -1
- package/dist/transformers/tailwindComponent.js +1 -1
- package/dist/transformers/tailwindComponent.js.map +1 -1
- package/dist/types/config.d.ts +19 -9
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/ast/serializer.d.ts.map +1 -1
- package/dist/utils/ast/serializer.js +27 -17
- package/dist/utils/ast/serializer.js.map +1 -1
- package/dist/utils/cssBox.d.ts +42 -0
- package/dist/utils/cssBox.d.ts.map +1 -0
- package/dist/utils/cssBox.js +156 -0
- package/dist/utils/cssBox.js.map +1 -0
- package/dist/utils/watchPaths.d.ts +11 -0
- package/dist/utils/watchPaths.d.ts.map +1 -0
- package/dist/utils/watchPaths.js +19 -0
- package/dist/utils/watchPaths.js.map +1 -0
- package/package.json +1 -1
- package/dist/transformers/safeClassNames.d.ts +0 -22
- package/dist/transformers/safeClassNames.d.ts.map +0 -1
- package/dist/transformers/safeClassNames.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tailwindComponent.js","names":[],"sources":["../../src/transformers/tailwindComponent.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport type { ChildNode, Element, Comment } from 'domhandler'\nimport { walk } from '../utils/ast/index.ts'\nimport { compileTailwindCss } from '../utils/compileTailwindCss.ts'\nimport type { TailwindBlock } from '../composables/renderContext.ts'\nimport type { MaizzleConfig } from '../types/config.ts'\n\nconst DEFAULT_SEED = '@import \"@maizzle/tailwindcss\";'\n\ninterface BlockMeta {\n id: string\n configCss?: string\n nested: boolean\n classes: Set<string>\n}\n\nconst OPEN_RE = /^mz-tw:(\\S+)$/\nconst CLOSE_RE = /^\\/mz-tw:(\\S+)$/\n\n/**\n * Compile Tailwind CSS for each top-level <Tailwind> block in the render\n * context. Nested <Tailwind> instances are flattened: their classes flow\n * up to the outermost block, their `#config` slot (if any) is ignored.\n * One <style> per outermost block is appended to <head>; marker comments\n * are stripped after.\n */\nexport async function tailwindComponent(\n dom: ChildNode[],\n blocks: TailwindBlock[],\n config: MaizzleConfig,\n filePath?: string,\n): Promise<ChildNode[]> {\n if (!blocks.length) return dom\n\n const map = new Map<string, BlockMeta>()\n for (const b of blocks) {\n map.set(b.id, { id: b.id, configCss: b.css, nested: false, classes: new Set() })\n }\n\n const stack: string[] = []\n const markers: Comment[] = []\n\n walk(dom, (node) => {\n if (node.type === 'comment') {\n const data = (node as Comment).data\n const open = data.match(OPEN_RE)\n const close = data.match(CLOSE_RE)\n if (open) {\n const id = open[1]\n const meta = map.get(id)\n if (meta && stack.length > 0) meta.nested = true\n if (meta) stack.push(id)\n markers.push(node as Comment)\n } else if (close) {\n const id = close[1]\n if (stack[stack.length - 1] === id) stack.pop()\n markers.push(node as Comment)\n }\n return\n }\n\n const el = node as Element\n // Always assign to the OUTERMOST active marker (stack[0]) so nested\n // <Tailwind> blocks merge their classes into the parent's scope.\n if (el.attribs?.class && stack.length > 0) {\n map.get(stack[0])!.classes.add(el.attribs.class)\n }\n })\n\n const fromPath = filePath ?? resolve(process.cwd(), 'template.vue')\n\n let head: Element | undefined\n walk(dom, (n) => {\n if (!head && (n as Element).name === 'head') head = n as Element\n })\n\n if (!head) {\n throw new Error('`Tailwind` component requires `Head` component to be present in the template.')\n }\n\n // Compile + inject one <style raw> per outermost block. `raw` opts the\n // existing tailwindcss transformer out of recompiling already-compiled CSS.\n for (const meta of map.values()) {\n if (meta.nested) continue\n\n const cssInput = buildCssInput(meta.configCss, meta.classes)\n const css = (await compileTailwindCss(cssInput, config, `${fromPath}?tw=${meta.id}`)).trim()\n if (!css) continue\n\n const styleNode: Element = {\n type: 'tag',\n name: 'style',\n attribs: { raw: '' },\n children: [],\n parent: head,\n prev: null,\n next: null,\n } as any\n\n const textNode = {\n type: 'text',\n data: css,\n parent: styleNode,\n prev: null,\n next: null,\n } as any\n\n styleNode.children = [textNode]\n head.children.push(styleNode)\n }\n\n // Strip marker comments from their parents\n for (const c of markers) {\n const parent = c.parent as Element | null\n if (!parent?.children) continue\n const i = parent.children.indexOf(c)\n if (i >= 0) parent.children.splice(i, 1)\n }\n\n return dom\n}\n\nfunction buildCssInput(configCss: string | undefined, classes: Set<string>): string {\n const seed = configCss ?? DEFAULT_SEED\n\n if (!classes.size) return seed\n\n const inline = [...classes].join(' ').replace(/\"/g, '\\\\\"')\n return `${seed}\\n@source inline(\"${inline}\");`\n}\n"],"mappings":";;;;;AAOA,MAAM,eAAe;AASrB,MAAM,UAAU;AAChB,MAAM,WAAW;;;;;;;;AASjB,eAAsB,kBACpB,KACA,QACA,QACA,UACsB;CACtB,IAAI,CAAC,OAAO,QAAQ,OAAO;CAE3B,MAAM,sBAAM,IAAI,KAAwB;CACxC,KAAK,MAAM,KAAK,QACd,IAAI,IAAI,EAAE,IAAI;EAAE,IAAI,EAAE;EAAI,WAAW,EAAE;EAAK,QAAQ;EAAO,yBAAS,IAAI,KAAK;EAAE,CAAC;CAGlF,MAAM,QAAkB,EAAE;CAC1B,MAAM,UAAqB,EAAE;CAE7B,KAAK,MAAM,SAAS;EAClB,IAAI,KAAK,SAAS,WAAW;GAC3B,MAAM,OAAQ,KAAiB;GAC/B,MAAM,OAAO,KAAK,MAAM,QAAQ;GAChC,MAAM,QAAQ,KAAK,MAAM,SAAS;GAClC,IAAI,MAAM;IACR,MAAM,KAAK,KAAK;IAChB,MAAM,OAAO,IAAI,IAAI,GAAG;IACxB,IAAI,QAAQ,MAAM,SAAS,GAAG,KAAK,SAAS;IAC5C,IAAI,MAAM,MAAM,KAAK,GAAG;IACxB,QAAQ,KAAK,KAAgB;UACxB,IAAI,OAAO;IAChB,MAAM,KAAK,MAAM;IACjB,IAAI,MAAM,MAAM,SAAS,OAAO,IAAI,MAAM,KAAK;IAC/C,QAAQ,KAAK,KAAgB;;GAE/B;;EAGF,MAAM,KAAK;EAGX,IAAI,GAAG,SAAS,SAAS,MAAM,SAAS,GACtC,IAAI,IAAI,MAAM,GAAG,CAAE,QAAQ,IAAI,GAAG,QAAQ,MAAM;GAElD;CAEF,MAAM,WAAW,YAAY,QAAQ,QAAQ,KAAK,EAAE,eAAe;CAEnE,IAAI;CACJ,KAAK,MAAM,MAAM;EACf,IAAI,CAAC,QAAS,EAAc,SAAS,QAAQ,OAAO;GACpD;CAEF,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,gFAAgF;CAKlG,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE;EAC/B,IAAI,KAAK,QAAQ;EAGjB,MAAM,OAAO,MAAM,mBADF,cAAc,KAAK,WAAW,KAAK,QACN,EAAE,QAAQ,GAAG,SAAS,MAAM,KAAK,KAAK,EAAE,MAAM;EAC5F,IAAI,CAAC,KAAK;EAEV,MAAM,YAAqB;GACzB,MAAM;GACN,MAAM;GACN,SAAS,EAAE,KAAK,IAAI;GACpB,UAAU,EAAE;GACZ,QAAQ;GACR,MAAM;GACN,MAAM;GACP;EAUD,UAAU,WAAW,CAAC;GAPpB,MAAM;GACN,MAAM;GACN,QAAQ;GACR,MAAM;GACN,MAAM;GAGsB,CAAC;EAC/B,KAAK,SAAS,KAAK,UAAU;;CAI/B,KAAK,MAAM,KAAK,SAAS;EACvB,MAAM,SAAS,EAAE;EACjB,IAAI,CAAC,QAAQ,UAAU;EACvB,MAAM,IAAI,OAAO,SAAS,QAAQ,EAAE;EACpC,IAAI,KAAK,GAAG,OAAO,SAAS,OAAO,GAAG,EAAE;;CAG1C,OAAO;;AAGT,SAAS,cAAc,WAA+B,SAA8B;CAClF,MAAM,OAAO,aAAa;CAE1B,IAAI,CAAC,QAAQ,MAAM,OAAO;CAG1B,OAAO,GAAG,KAAK,oBADA,CAAC,GAAG,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,MAAM,OACX,CAAC"}
|
|
1
|
+
{"version":3,"file":"tailwindComponent.js","names":[],"sources":["../../src/transformers/tailwindComponent.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport type { ChildNode, Element, Comment } from 'domhandler'\nimport { walk } from '../utils/ast/index.ts'\nimport { compileTailwindCss } from '../utils/compileTailwindCss.ts'\nimport type { TailwindBlock } from '../composables/renderContext.ts'\nimport type { MaizzleConfig } from '../types/config.ts'\n\nconst DEFAULT_SEED = '@import \"@maizzle/tailwindcss\" source(none);'\n\ninterface BlockMeta {\n id: string\n configCss?: string\n nested: boolean\n classes: Set<string>\n}\n\nconst OPEN_RE = /^mz-tw:(\\S+)$/\nconst CLOSE_RE = /^\\/mz-tw:(\\S+)$/\n\n/**\n * Compile Tailwind CSS for each top-level <Tailwind> block in the render\n * context. Nested <Tailwind> instances are flattened: their classes flow\n * up to the outermost block, their `#config` slot (if any) is ignored.\n * One <style> per outermost block is appended to <head>; marker comments\n * are stripped after.\n */\nexport async function tailwindComponent(\n dom: ChildNode[],\n blocks: TailwindBlock[],\n config: MaizzleConfig,\n filePath?: string,\n): Promise<ChildNode[]> {\n if (!blocks.length) return dom\n\n const map = new Map<string, BlockMeta>()\n for (const b of blocks) {\n map.set(b.id, { id: b.id, configCss: b.css, nested: false, classes: new Set() })\n }\n\n const stack: string[] = []\n const markers: Comment[] = []\n\n walk(dom, (node) => {\n if (node.type === 'comment') {\n const data = (node as Comment).data\n const open = data.match(OPEN_RE)\n const close = data.match(CLOSE_RE)\n if (open) {\n const id = open[1]\n const meta = map.get(id)\n if (meta && stack.length > 0) meta.nested = true\n if (meta) stack.push(id)\n markers.push(node as Comment)\n } else if (close) {\n const id = close[1]\n if (stack[stack.length - 1] === id) stack.pop()\n markers.push(node as Comment)\n }\n return\n }\n\n const el = node as Element\n // Always assign to the OUTERMOST active marker (stack[0]) so nested\n // <Tailwind> blocks merge their classes into the parent's scope.\n if (el.attribs?.class && stack.length > 0) {\n map.get(stack[0])!.classes.add(el.attribs.class)\n }\n })\n\n const fromPath = filePath ?? resolve(process.cwd(), 'template.vue')\n\n let head: Element | undefined\n walk(dom, (n) => {\n if (!head && (n as Element).name === 'head') head = n as Element\n })\n\n if (!head) {\n throw new Error('`Tailwind` component requires `Head` component to be present in the template.')\n }\n\n // Compile + inject one <style raw> per outermost block. `raw` opts the\n // existing tailwindcss transformer out of recompiling already-compiled CSS.\n for (const meta of map.values()) {\n if (meta.nested) continue\n\n const cssInput = buildCssInput(meta.configCss, meta.classes)\n const css = (await compileTailwindCss(cssInput, config, `${fromPath}?tw=${meta.id}`)).trim()\n if (!css) continue\n\n const styleNode: Element = {\n type: 'tag',\n name: 'style',\n attribs: { raw: '' },\n children: [],\n parent: head,\n prev: null,\n next: null,\n } as any\n\n const textNode = {\n type: 'text',\n data: css,\n parent: styleNode,\n prev: null,\n next: null,\n } as any\n\n styleNode.children = [textNode]\n head.children.push(styleNode)\n }\n\n // Strip marker comments from their parents\n for (const c of markers) {\n const parent = c.parent as Element | null\n if (!parent?.children) continue\n const i = parent.children.indexOf(c)\n if (i >= 0) parent.children.splice(i, 1)\n }\n\n return dom\n}\n\nfunction buildCssInput(configCss: string | undefined, classes: Set<string>): string {\n const seed = configCss ?? DEFAULT_SEED\n\n if (!classes.size) return seed\n\n const inline = [...classes].join(' ').replace(/\"/g, '\\\\\"')\n return `${seed}\\n@source inline(\"${inline}\");`\n}\n"],"mappings":";;;;;AAOA,MAAM,eAAe;AASrB,MAAM,UAAU;AAChB,MAAM,WAAW;;;;;;;;AASjB,eAAsB,kBACpB,KACA,QACA,QACA,UACsB;CACtB,IAAI,CAAC,OAAO,QAAQ,OAAO;CAE3B,MAAM,sBAAM,IAAI,KAAwB;CACxC,KAAK,MAAM,KAAK,QACd,IAAI,IAAI,EAAE,IAAI;EAAE,IAAI,EAAE;EAAI,WAAW,EAAE;EAAK,QAAQ;EAAO,yBAAS,IAAI,KAAK;EAAE,CAAC;CAGlF,MAAM,QAAkB,EAAE;CAC1B,MAAM,UAAqB,EAAE;CAE7B,KAAK,MAAM,SAAS;EAClB,IAAI,KAAK,SAAS,WAAW;GAC3B,MAAM,OAAQ,KAAiB;GAC/B,MAAM,OAAO,KAAK,MAAM,QAAQ;GAChC,MAAM,QAAQ,KAAK,MAAM,SAAS;GAClC,IAAI,MAAM;IACR,MAAM,KAAK,KAAK;IAChB,MAAM,OAAO,IAAI,IAAI,GAAG;IACxB,IAAI,QAAQ,MAAM,SAAS,GAAG,KAAK,SAAS;IAC5C,IAAI,MAAM,MAAM,KAAK,GAAG;IACxB,QAAQ,KAAK,KAAgB;UACxB,IAAI,OAAO;IAChB,MAAM,KAAK,MAAM;IACjB,IAAI,MAAM,MAAM,SAAS,OAAO,IAAI,MAAM,KAAK;IAC/C,QAAQ,KAAK,KAAgB;;GAE/B;;EAGF,MAAM,KAAK;EAGX,IAAI,GAAG,SAAS,SAAS,MAAM,SAAS,GACtC,IAAI,IAAI,MAAM,GAAG,CAAE,QAAQ,IAAI,GAAG,QAAQ,MAAM;GAElD;CAEF,MAAM,WAAW,YAAY,QAAQ,QAAQ,KAAK,EAAE,eAAe;CAEnE,IAAI;CACJ,KAAK,MAAM,MAAM;EACf,IAAI,CAAC,QAAS,EAAc,SAAS,QAAQ,OAAO;GACpD;CAEF,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,gFAAgF;CAKlG,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE;EAC/B,IAAI,KAAK,QAAQ;EAGjB,MAAM,OAAO,MAAM,mBADF,cAAc,KAAK,WAAW,KAAK,QACN,EAAE,QAAQ,GAAG,SAAS,MAAM,KAAK,KAAK,EAAE,MAAM;EAC5F,IAAI,CAAC,KAAK;EAEV,MAAM,YAAqB;GACzB,MAAM;GACN,MAAM;GACN,SAAS,EAAE,KAAK,IAAI;GACpB,UAAU,EAAE;GACZ,QAAQ;GACR,MAAM;GACN,MAAM;GACP;EAUD,UAAU,WAAW,CAAC;GAPpB,MAAM;GACN,MAAM;GACN,QAAQ;GACR,MAAM;GACN,MAAM;GAGsB,CAAC;EAC/B,KAAK,SAAS,KAAK,UAAU;;CAI/B,KAAK,MAAM,KAAK,SAAS;EACvB,MAAM,SAAS,EAAE;EACjB,IAAI,CAAC,QAAQ,UAAU;EACvB,MAAM,IAAI,OAAO,SAAS,QAAQ,EAAE;EACpC,IAAI,KAAK,GAAG,OAAO,SAAS,OAAO,GAAG,EAAE;;CAG1C,OAAO;;AAGT,SAAS,cAAc,WAA+B,SAA8B;CAClF,MAAM,OAAO,aAAa;CAE1B,IAAI,CAAC,QAAQ,MAAM,OAAO;CAG1B,OAAO,GAAG,KAAK,oBADA,CAAC,GAAG,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,MAAM,OACX,CAAC"}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RemoveValue } from "../plugins/postcss/removeDeclarations.js";
|
|
2
|
+
import { TemplateInfo } from "../events/index.js";
|
|
2
3
|
import { Directive, Plugin } from "vue";
|
|
3
4
|
import { Options } from "juice";
|
|
4
5
|
import * as _$oxfmt from "oxfmt";
|
|
@@ -374,8 +375,15 @@ interface MarkdownConfig extends Options$1 {
|
|
|
374
375
|
shikiTheme?: _$shiki.BundledTheme;
|
|
375
376
|
}
|
|
376
377
|
interface VueConfig {
|
|
377
|
-
/**
|
|
378
|
-
|
|
378
|
+
/**
|
|
379
|
+
* Vue plugins to register on the app instance before rendering.
|
|
380
|
+
*
|
|
381
|
+
* Pass a factory (`() => Plugin[]`) for stateful plugins like vue-i18n
|
|
382
|
+
* or Pinia to get a fresh instance per render — otherwise state leaks
|
|
383
|
+
* across templates (e.g. one template setting `locale.value = 'fr'`
|
|
384
|
+
* affects the next render).
|
|
385
|
+
*/
|
|
386
|
+
plugins?: Plugin[] | (() => Plugin[]);
|
|
379
387
|
/** Custom Vue directives to register globally. */
|
|
380
388
|
directives?: Record<string, Directive>;
|
|
381
389
|
/** Properties added to `app.config.globalProperties`, available in all templates. */
|
|
@@ -387,7 +395,7 @@ interface VueConfig {
|
|
|
387
395
|
* - `false` skips the listed transformer.
|
|
388
396
|
* - `true` force-enables it for this run (only meaningful for boolean-driven
|
|
389
397
|
* transformers: inlineCss, purgeCss, prettify, minify, shorthandCss,
|
|
390
|
-
* sixHex,
|
|
398
|
+
* sixHex, safeSelectors, entities). Layers on the matching
|
|
391
399
|
* `css.*` / `html.*` config slice.
|
|
392
400
|
* - missing keys keep their default behavior.
|
|
393
401
|
*
|
|
@@ -400,7 +408,7 @@ interface VueConfig {
|
|
|
400
408
|
* or framework state, not user opt-in.
|
|
401
409
|
*/
|
|
402
410
|
interface TransformerToggles {
|
|
403
|
-
|
|
411
|
+
safeSelectors?: boolean;
|
|
404
412
|
attributeToStyle?: boolean;
|
|
405
413
|
inlineCss?: boolean;
|
|
406
414
|
removeAttributes?: boolean;
|
|
@@ -688,7 +696,9 @@ interface MaizzleConfig {
|
|
|
688
696
|
*
|
|
689
697
|
* @example
|
|
690
698
|
* vue: {
|
|
691
|
-
* plugins
|
|
699
|
+
* // Use a factory for stateful plugins (vue-i18n, Pinia, vue-router)
|
|
700
|
+
* // so each render gets a fresh instance.
|
|
701
|
+
* plugins: () => [createI18n({ locale: 'en', messages })],
|
|
692
702
|
* directives: { focus: vFocus },
|
|
693
703
|
* globalProperties: { $format: dateFormat },
|
|
694
704
|
* }
|
|
@@ -698,21 +708,21 @@ interface MaizzleConfig {
|
|
|
698
708
|
beforeCreate?: (params: {
|
|
699
709
|
config: MaizzleConfig;
|
|
700
710
|
}) => void | Promise<void>;
|
|
701
|
-
/** Called before each template is rendered. Return a string to replace
|
|
711
|
+
/** Called before each template is rendered. Return a string to replace `template.source`. */
|
|
702
712
|
beforeRender?: (params: {
|
|
703
713
|
config: MaizzleConfig;
|
|
704
|
-
template:
|
|
714
|
+
template: TemplateInfo;
|
|
705
715
|
}) => string | void | Promise<string | void>;
|
|
706
716
|
/** Called after each template is rendered but before transformers run. Return a string to replace the output HTML. */
|
|
707
717
|
afterRender?: (params: {
|
|
708
718
|
config: MaizzleConfig;
|
|
709
|
-
template:
|
|
719
|
+
template: TemplateInfo;
|
|
710
720
|
html: string;
|
|
711
721
|
}) => string | void | Promise<string | void>;
|
|
712
722
|
/** Called after transformers have run on each template. Return a string to replace the output HTML. */
|
|
713
723
|
afterTransform?: (params: {
|
|
714
724
|
config: MaizzleConfig;
|
|
715
|
-
template:
|
|
725
|
+
template: TemplateInfo;
|
|
716
726
|
html: string;
|
|
717
727
|
}) => string | void | Promise<string | void>;
|
|
718
728
|
/** Called after all templates have been built. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","names":[],"sources":["../../src/types/config.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../../src/types/config.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer.d.ts","names":[],"sources":["../../../src/utils/ast/serializer.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"serializer.d.ts","names":[],"sources":["../../../src/utils/ast/serializer.ts"],"mappings":";;;;iBA0CgB,SAAA,CAAU,GAAA,EAAK,SAAA,IAAa,OAAA,GAAU,oBAAA"}
|
|
@@ -1,30 +1,40 @@
|
|
|
1
|
-
import { walk } from "./walker.js";
|
|
2
1
|
import render from "dom-serializer";
|
|
3
2
|
//#region src/utils/ast/serializer.ts
|
|
3
|
+
const RAW_TEXT_ELEMENTS = new Set(["script", "style"]);
|
|
4
4
|
/**
|
|
5
|
-
* Re-encode
|
|
5
|
+
* Re-encode `<` and `>` in text nodes before serialization.
|
|
6
6
|
*
|
|
7
|
-
* The
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* The parser decodes entities like `<` into raw `<` in text nodes. With
|
|
8
|
+
* `encodeEntities: false` (needed so other transformers can emit entity
|
|
9
|
+
* strings such as ` ` verbatim), the serializer would write those raw
|
|
10
|
+
* `<` characters as-is, turning escaped text (e.g. a Vue `{{ html }}`
|
|
11
|
+
* interpolation containing `<p>...</p>`) into real DOM downstream.
|
|
10
12
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
+
* `&` is intentionally not re-encoded: the `entities` transformer writes
|
|
14
|
+
* literal entity strings (` `, `—`) directly into text-node data
|
|
15
|
+
* and relies on the serializer leaving them alone.
|
|
16
|
+
*
|
|
17
|
+
* Skip `<script>` / `<style>` — their children are raw-text containers, and
|
|
18
|
+
* CSS/JS legitimately contains `<` and `>`.
|
|
13
19
|
*/
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (child.type === "text") {
|
|
20
|
-
const text = child;
|
|
20
|
+
function encodeTextNodes(dom, inRawText = false) {
|
|
21
|
+
for (const node of dom) {
|
|
22
|
+
if (node.type === "text") {
|
|
23
|
+
if (!inRawText) {
|
|
24
|
+
const text = node;
|
|
21
25
|
text.data = text.data.replace(/</g, "<").replace(/>/g, ">");
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if ("children" in node && node.children?.length) {
|
|
30
|
+
const el = node;
|
|
31
|
+
const nextRaw = inRawText || RAW_TEXT_ELEMENTS.has(el.name);
|
|
32
|
+
encodeTextNodes(el.children, nextRaw);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
25
35
|
}
|
|
26
36
|
function serialize(dom, options) {
|
|
27
|
-
|
|
37
|
+
encodeTextNodes(dom);
|
|
28
38
|
return render(dom, {
|
|
29
39
|
encodeEntities: false,
|
|
30
40
|
...options
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer.js","names":[],"sources":["../../../src/utils/ast/serializer.ts"],"sourcesContent":["import render from 'dom-serializer'\nimport type { ChildNode } from 'domhandler'\nimport type { DomSerializerOptions } from 'dom-serializer'\
|
|
1
|
+
{"version":3,"file":"serializer.js","names":[],"sources":["../../../src/utils/ast/serializer.ts"],"sourcesContent":["import render from 'dom-serializer'\nimport type { ChildNode, Element, Text } from 'domhandler'\nimport type { DomSerializerOptions } from 'dom-serializer'\n\nconst RAW_TEXT_ELEMENTS = new Set(['script', 'style'])\n\n/**\n * Re-encode `<` and `>` in text nodes before serialization.\n *\n * The parser decodes entities like `<` into raw `<` in text nodes. With\n * `encodeEntities: false` (needed so other transformers can emit entity\n * strings such as ` ` verbatim), the serializer would write those raw\n * `<` characters as-is, turning escaped text (e.g. a Vue `{{ html }}`\n * interpolation containing `<p>...</p>`) into real DOM downstream.\n *\n * `&` is intentionally not re-encoded: the `entities` transformer writes\n * literal entity strings (` `, `—`) directly into text-node data\n * and relies on the serializer leaving them alone.\n *\n * Skip `<script>` / `<style>` — their children are raw-text containers, and\n * CSS/JS legitimately contains `<` and `>`.\n */\nfunction encodeTextNodes(dom: ChildNode[], inRawText = false): void {\n for (const node of dom) {\n if (node.type === 'text') {\n if (!inRawText) {\n const text = node as Text\n text.data = text.data\n .replace(/</g, '<')\n .replace(/>/g, '>')\n }\n continue\n }\n\n if ('children' in node && (node as Element).children?.length) {\n const el = node as Element\n const nextRaw = inRawText || RAW_TEXT_ELEMENTS.has(el.name)\n encodeTextNodes(el.children as ChildNode[], nextRaw)\n }\n }\n}\n\nexport function serialize(dom: ChildNode[], options?: DomSerializerOptions): string {\n encodeTextNodes(dom)\n return render(dom, { encodeEntities: false, ...options })\n}\n"],"mappings":";;AAIA,MAAM,oBAAoB,IAAI,IAAI,CAAC,UAAU,QAAQ,CAAC;;;;;;;;;;;;;;;;;AAkBtD,SAAS,gBAAgB,KAAkB,YAAY,OAAa;CAClE,KAAK,MAAM,QAAQ,KAAK;EACtB,IAAI,KAAK,SAAS,QAAQ;GACxB,IAAI,CAAC,WAAW;IACd,MAAM,OAAO;IACb,KAAK,OAAO,KAAK,KACd,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO;;GAE1B;;EAGF,IAAI,cAAc,QAAS,KAAiB,UAAU,QAAQ;GAC5D,MAAM,KAAK;GACX,MAAM,UAAU,aAAa,kBAAkB,IAAI,GAAG,KAAK;GAC3D,gBAAgB,GAAG,UAAyB,QAAQ;;;;AAK1D,SAAgB,UAAU,KAAkB,SAAwC;CAClF,gBAAgB,IAAI;CACpB,OAAO,OAAO,KAAK;EAAE,gBAAgB;EAAO,GAAG;EAAS,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Root } from "postcss";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/cssBox.d.ts
|
|
4
|
+
declare const NO_BORDER_STYLES: Set<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Parse a length token into px. Handles `Npx`, `Nrem`, `Nem`, `Npt`, and
|
|
7
|
+
* unitless N (treated as px). Returns null for percentages, calc(),
|
|
8
|
+
* keywords, or anything that doesn't reduce to a concrete length.
|
|
9
|
+
*/
|
|
10
|
+
declare function lengthToPx(value: string): number | null;
|
|
11
|
+
/**
|
|
12
|
+
* Expand a 1-4 token CSS shorthand (T R B L) into a left/right pair:
|
|
13
|
+
* 1: all sides
|
|
14
|
+
* 2: TB RL
|
|
15
|
+
* 3: T RL B
|
|
16
|
+
* 4: T R B L
|
|
17
|
+
*/
|
|
18
|
+
declare function shorthandSides(value: string): {
|
|
19
|
+
left?: string;
|
|
20
|
+
right?: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Read horizontal padding (left + right) px from a parsed style root.
|
|
24
|
+
* Percentages are skipped since they'd need a known container width.
|
|
25
|
+
*/
|
|
26
|
+
declare function horizontalPaddingPx(root: Root): number;
|
|
27
|
+
/**
|
|
28
|
+
* Extract a px length from a CSS border shorthand (e.g. `1px solid red` → 1).
|
|
29
|
+
* Returns null when the value indicates no border (`none` or `hidden`).
|
|
30
|
+
* Defaults to 3px (CSS `medium`) when a visible style is set but no
|
|
31
|
+
* explicit width token is present in the shorthand value.
|
|
32
|
+
*/
|
|
33
|
+
declare function shorthandBorderWidthPx(value: string): number | null;
|
|
34
|
+
/**
|
|
35
|
+
* Read horizontal border widths (left + right) px from a parsed style root.
|
|
36
|
+
* Per-side `border-style: none|hidden` overrides count as zero
|
|
37
|
+
* contribution. Returns total px or 0 when nothing resolves.
|
|
38
|
+
*/
|
|
39
|
+
declare function horizontalBorderPx(root: Root): number;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { NO_BORDER_STYLES, horizontalBorderPx, horizontalPaddingPx, lengthToPx, shorthandBorderWidthPx, shorthandSides };
|
|
42
|
+
//# sourceMappingURL=cssBox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssBox.d.ts","names":[],"sources":["../../src/utils/cssBox.ts"],"mappings":";;;cAEa,gBAAA,EAAgB,GAAA;;AAA7B;;;;iBAOgB,UAAA,CAAW,KAAA;AAA3B;;;;;AAoBA;;AApBA,iBAoBgB,cAAA,CAAe,KAAA;EAAkB,IAAA;EAAe,KAAA;AAAA;;;;AAehE;iBAAgB,mBAAA,CAAoB,IAAA,EAAM,IAAA;;;;AA8B1C;;;iBAAgB,sBAAA,CAAuB,KAAA;;AAevC;;;;iBAAgB,kBAAA,CAAmB,IAAA,EAAM,IAAA"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
//#region src/utils/cssBox.ts
|
|
2
|
+
const NO_BORDER_STYLES = new Set(["none", "hidden"]);
|
|
3
|
+
/**
|
|
4
|
+
* Parse a length token into px. Handles `Npx`, `Nrem`, `Nem`, `Npt`, and
|
|
5
|
+
* unitless N (treated as px). Returns null for percentages, calc(),
|
|
6
|
+
* keywords, or anything that doesn't reduce to a concrete length.
|
|
7
|
+
*/
|
|
8
|
+
function lengthToPx(value) {
|
|
9
|
+
const m = value.trim().match(/^([\d.]+)(px|rem|em|pt)?$/i);
|
|
10
|
+
if (!m) return null;
|
|
11
|
+
const n = parseFloat(m[1]);
|
|
12
|
+
switch ((m[2] || "px").toLowerCase()) {
|
|
13
|
+
case "px": return n;
|
|
14
|
+
case "rem":
|
|
15
|
+
case "em": return n * 16;
|
|
16
|
+
case "pt": return n * 1.333;
|
|
17
|
+
default: return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Expand a 1-4 token CSS shorthand (T R B L) into a left/right pair:
|
|
22
|
+
* 1: all sides
|
|
23
|
+
* 2: TB RL
|
|
24
|
+
* 3: T RL B
|
|
25
|
+
* 4: T R B L
|
|
26
|
+
*/
|
|
27
|
+
function shorthandSides(value) {
|
|
28
|
+
const parts = value.trim().split(/\s+/);
|
|
29
|
+
switch (parts.length) {
|
|
30
|
+
case 1: return {
|
|
31
|
+
left: parts[0],
|
|
32
|
+
right: parts[0]
|
|
33
|
+
};
|
|
34
|
+
case 2:
|
|
35
|
+
case 3: return {
|
|
36
|
+
left: parts[1],
|
|
37
|
+
right: parts[1]
|
|
38
|
+
};
|
|
39
|
+
case 4: return {
|
|
40
|
+
left: parts[3],
|
|
41
|
+
right: parts[1]
|
|
42
|
+
};
|
|
43
|
+
default: return {};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Read horizontal padding (left + right) px from a parsed style root.
|
|
48
|
+
* Percentages are skipped since they'd need a known container width.
|
|
49
|
+
*/
|
|
50
|
+
function horizontalPaddingPx(root) {
|
|
51
|
+
let left = null;
|
|
52
|
+
let right = null;
|
|
53
|
+
root.walkDecls((d) => {
|
|
54
|
+
switch (d.prop) {
|
|
55
|
+
case "padding": {
|
|
56
|
+
const { left: l, right: r } = shorthandSides(d.value);
|
|
57
|
+
if (l) left = lengthToPx(l);
|
|
58
|
+
if (r) right = lengthToPx(r);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case "padding-left":
|
|
62
|
+
left = lengthToPx(d.value);
|
|
63
|
+
break;
|
|
64
|
+
case "padding-right":
|
|
65
|
+
right = lengthToPx(d.value);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return (left ?? 0) + (right ?? 0);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract a px length from a CSS border shorthand (e.g. `1px solid red` → 1).
|
|
73
|
+
* Returns null when the value indicates no border (`none` or `hidden`).
|
|
74
|
+
* Defaults to 3px (CSS `medium`) when a visible style is set but no
|
|
75
|
+
* explicit width token is present in the shorthand value.
|
|
76
|
+
*/
|
|
77
|
+
function shorthandBorderWidthPx(value) {
|
|
78
|
+
const tokens = value.trim().split(/\s+/);
|
|
79
|
+
if (tokens.some((t) => NO_BORDER_STYLES.has(t.toLowerCase()))) return null;
|
|
80
|
+
for (const t of tokens) {
|
|
81
|
+
const px = lengthToPx(t);
|
|
82
|
+
if (px != null) return px;
|
|
83
|
+
}
|
|
84
|
+
return 3;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Read horizontal border widths (left + right) px from a parsed style root.
|
|
88
|
+
* Per-side `border-style: none|hidden` overrides count as zero
|
|
89
|
+
* contribution. Returns total px or 0 when nothing resolves.
|
|
90
|
+
*/
|
|
91
|
+
function horizontalBorderPx(root) {
|
|
92
|
+
let left = null;
|
|
93
|
+
let right = null;
|
|
94
|
+
let leftNone = false;
|
|
95
|
+
let rightNone = false;
|
|
96
|
+
root.walkDecls((d) => {
|
|
97
|
+
switch (d.prop) {
|
|
98
|
+
case "border": {
|
|
99
|
+
const w = shorthandBorderWidthPx(d.value);
|
|
100
|
+
if (w == null) leftNone = rightNone = true;
|
|
101
|
+
else {
|
|
102
|
+
left = right = w;
|
|
103
|
+
leftNone = rightNone = false;
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case "border-width": {
|
|
108
|
+
const { left: l, right: r } = shorthandSides(d.value);
|
|
109
|
+
if (l) left = lengthToPx(l) ?? left;
|
|
110
|
+
if (r) right = lengthToPx(r) ?? right;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case "border-style": {
|
|
114
|
+
const { left: l, right: r } = shorthandSides(d.value);
|
|
115
|
+
if (l && NO_BORDER_STYLES.has(l.toLowerCase())) leftNone = true;
|
|
116
|
+
if (r && NO_BORDER_STYLES.has(r.toLowerCase())) rightNone = true;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case "border-left": {
|
|
120
|
+
const w = shorthandBorderWidthPx(d.value);
|
|
121
|
+
if (w == null) leftNone = true;
|
|
122
|
+
else {
|
|
123
|
+
left = w;
|
|
124
|
+
leftNone = false;
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case "border-right": {
|
|
129
|
+
const w = shorthandBorderWidthPx(d.value);
|
|
130
|
+
if (w == null) rightNone = true;
|
|
131
|
+
else {
|
|
132
|
+
right = w;
|
|
133
|
+
rightNone = false;
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case "border-left-width":
|
|
138
|
+
left = lengthToPx(d.value) ?? left;
|
|
139
|
+
break;
|
|
140
|
+
case "border-right-width":
|
|
141
|
+
right = lengthToPx(d.value) ?? right;
|
|
142
|
+
break;
|
|
143
|
+
case "border-left-style":
|
|
144
|
+
if (NO_BORDER_STYLES.has(d.value.trim().toLowerCase())) leftNone = true;
|
|
145
|
+
break;
|
|
146
|
+
case "border-right-style":
|
|
147
|
+
if (NO_BORDER_STYLES.has(d.value.trim().toLowerCase())) rightNone = true;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
return (leftNone ? 0 : left ?? 0) + (rightNone ? 0 : right ?? 0);
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
export { NO_BORDER_STYLES, horizontalBorderPx, horizontalPaddingPx, lengthToPx, shorthandBorderWidthPx, shorthandSides };
|
|
155
|
+
|
|
156
|
+
//# sourceMappingURL=cssBox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssBox.js","names":[],"sources":["../../src/utils/cssBox.ts"],"sourcesContent":["import type { Root } from 'postcss'\n\nexport const NO_BORDER_STYLES = new Set(['none', 'hidden'])\n\n/**\n * Parse a length token into px. Handles `Npx`, `Nrem`, `Nem`, `Npt`, and\n * unitless N (treated as px). Returns null for percentages, calc(),\n * keywords, or anything that doesn't reduce to a concrete length.\n */\nexport function lengthToPx(value: string): number | null {\n const m = value.trim().match(/^([\\d.]+)(px|rem|em|pt)?$/i)\n if (!m) return null\n const n = parseFloat(m[1])\n switch ((m[2] || 'px').toLowerCase()) {\n case 'px': return n\n case 'rem':\n case 'em': return n * 16\n case 'pt': return n * 1.333\n default: return null\n }\n}\n\n/**\n * Expand a 1-4 token CSS shorthand (T R B L) into a left/right pair:\n * 1: all sides\n * 2: TB RL\n * 3: T RL B\n * 4: T R B L\n */\nexport function shorthandSides(value: string): { left?: string; right?: string } {\n const parts = value.trim().split(/\\s+/)\n switch (parts.length) {\n case 1: return { left: parts[0], right: parts[0] }\n case 2:\n case 3: return { left: parts[1], right: parts[1] }\n case 4: return { left: parts[3], right: parts[1] }\n default: return {}\n }\n}\n\n/**\n * Read horizontal padding (left + right) px from a parsed style root.\n * Percentages are skipped since they'd need a known container width.\n */\nexport function horizontalPaddingPx(root: Root): number {\n let left: number | null = null\n let right: number | null = null\n\n root.walkDecls((d) => {\n switch (d.prop) {\n case 'padding': {\n const { left: l, right: r } = shorthandSides(d.value)\n if (l) left = lengthToPx(l)\n if (r) right = lengthToPx(r)\n break\n }\n case 'padding-left':\n left = lengthToPx(d.value)\n break\n case 'padding-right':\n right = lengthToPx(d.value)\n break\n }\n })\n\n return (left ?? 0) + (right ?? 0)\n}\n\n/**\n * Extract a px length from a CSS border shorthand (e.g. `1px solid red` → 1).\n * Returns null when the value indicates no border (`none` or `hidden`).\n * Defaults to 3px (CSS `medium`) when a visible style is set but no\n * explicit width token is present in the shorthand value.\n */\nexport function shorthandBorderWidthPx(value: string): number | null {\n const tokens = value.trim().split(/\\s+/)\n if (tokens.some((t) => NO_BORDER_STYLES.has(t.toLowerCase()))) return null\n for (const t of tokens) {\n const px = lengthToPx(t)\n if (px != null) return px\n }\n return 3\n}\n\n/**\n * Read horizontal border widths (left + right) px from a parsed style root.\n * Per-side `border-style: none|hidden` overrides count as zero\n * contribution. Returns total px or 0 when nothing resolves.\n */\nexport function horizontalBorderPx(root: Root): number {\n let left: number | null = null\n let right: number | null = null\n let leftNone = false\n let rightNone = false\n\n root.walkDecls((d) => {\n switch (d.prop) {\n case 'border': {\n const w = shorthandBorderWidthPx(d.value)\n if (w == null) {\n leftNone = rightNone = true\n }\n else {\n left = right = w\n leftNone = rightNone = false\n }\n break\n }\n case 'border-width': {\n const { left: l, right: r } = shorthandSides(d.value)\n if (l) left = lengthToPx(l) ?? left\n if (r) right = lengthToPx(r) ?? right\n break\n }\n case 'border-style': {\n const { left: l, right: r } = shorthandSides(d.value)\n if (l && NO_BORDER_STYLES.has(l.toLowerCase())) leftNone = true\n if (r && NO_BORDER_STYLES.has(r.toLowerCase())) rightNone = true\n break\n }\n case 'border-left': {\n const w = shorthandBorderWidthPx(d.value)\n if (w == null) leftNone = true\n else { left = w; leftNone = false }\n break\n }\n case 'border-right': {\n const w = shorthandBorderWidthPx(d.value)\n if (w == null) rightNone = true\n else { right = w; rightNone = false }\n break\n }\n case 'border-left-width':\n left = lengthToPx(d.value) ?? left\n break\n case 'border-right-width':\n right = lengthToPx(d.value) ?? right\n break\n case 'border-left-style':\n if (NO_BORDER_STYLES.has(d.value.trim().toLowerCase())) leftNone = true\n break\n case 'border-right-style':\n if (NO_BORDER_STYLES.has(d.value.trim().toLowerCase())) rightNone = true\n break\n }\n })\n\n return (leftNone ? 0 : (left ?? 0)) + (rightNone ? 0 : (right ?? 0))\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/utils/watchPaths.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Build a predicate that tells whether an absolute file path emitted by
|
|
4
|
+
* chokidar matches any of the given globs. Patterns are interpreted as
|
|
5
|
+
* project-relative; a leading `./` is stripped so user-supplied globs like
|
|
6
|
+
* `./locales/**` behave identically to `locales/**`.
|
|
7
|
+
*/
|
|
8
|
+
declare function createWatchedFileMatcher(patterns: string[], cwd: string): (file: string) => boolean;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { createWatchedFileMatcher };
|
|
11
|
+
//# sourceMappingURL=watchPaths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watchPaths.d.ts","names":[],"sources":["../../src/utils/watchPaths.ts"],"mappings":";;AAQA;;;;;iBAAgB,wBAAA,CAAyB,QAAA,YAAoB,GAAA,YAEnD,IAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { matchesGlob, relative } from "node:path";
|
|
2
|
+
//#region src/utils/watchPaths.ts
|
|
3
|
+
/**
|
|
4
|
+
* Build a predicate that tells whether an absolute file path emitted by
|
|
5
|
+
* chokidar matches any of the given globs. Patterns are interpreted as
|
|
6
|
+
* project-relative; a leading `./` is stripped so user-supplied globs like
|
|
7
|
+
* `./locales/**` behave identically to `locales/**`.
|
|
8
|
+
*/
|
|
9
|
+
function createWatchedFileMatcher(patterns, cwd) {
|
|
10
|
+
const normalized = patterns.map((p) => p.replace(/^\.\//, ""));
|
|
11
|
+
return (file) => {
|
|
12
|
+
const rel = relative(cwd, file).replace(/\\/g, "/");
|
|
13
|
+
return normalized.some((p) => matchesGlob(rel, p));
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { createWatchedFileMatcher };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=watchPaths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watchPaths.js","names":[],"sources":["../../src/utils/watchPaths.ts"],"sourcesContent":["import { matchesGlob, relative } from 'node:path'\n\n/**\n * Build a predicate that tells whether an absolute file path emitted by\n * chokidar matches any of the given globs. Patterns are interpreted as\n * project-relative; a leading `./` is stripped so user-supplied globs like\n * `./locales/**` behave identically to `locales/**`.\n */\nexport function createWatchedFileMatcher(patterns: string[], cwd: string) {\n const normalized = patterns.map(p => p.replace(/^\\.\\//, ''))\n return (file: string) => {\n const rel = relative(cwd, file).replace(/\\\\/g, '/')\n return normalized.some(p => matchesGlob(rel, p))\n }\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,yBAAyB,UAAoB,KAAa;CACxE,MAAM,aAAa,SAAS,KAAI,MAAK,EAAE,QAAQ,SAAS,GAAG,CAAC;CAC5D,QAAQ,SAAiB;EACvB,MAAM,MAAM,SAAS,KAAK,KAAK,CAAC,QAAQ,OAAO,IAAI;EACnD,OAAO,WAAW,MAAK,MAAK,YAAY,KAAK,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { CssConfig } from "../types/config.js";
|
|
2
|
-
import { ChildNode } from "domhandler";
|
|
3
|
-
|
|
4
|
-
//#region src/transformers/safeClassNames.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Safe class names transformer.
|
|
7
|
-
*
|
|
8
|
-
* Replaces unsafe characters (`:`, `/`, `[`, `]`, etc.) in:
|
|
9
|
-
* - CSS selectors inside `<style>` tags
|
|
10
|
-
* - HTML `class` attributes
|
|
11
|
-
*
|
|
12
|
-
* This makes Tailwind utility classes like `sm:text-base` safe for
|
|
13
|
-
* email clients that cannot handle escaped characters in class names.
|
|
14
|
-
*
|
|
15
|
-
* Enabled by default. Disable by setting `css.safe` to `false`.
|
|
16
|
-
* Customize replacements by passing a `Record<string, string>` — user
|
|
17
|
-
* values are merged on top of the defaults.
|
|
18
|
-
*/
|
|
19
|
-
declare function safeClassNames(dom: ChildNode[], config?: CssConfig): ChildNode[];
|
|
20
|
-
//#endregion
|
|
21
|
-
export { safeClassNames };
|
|
22
|
-
//# sourceMappingURL=safeClassNames.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"safeClassNames.d.ts","names":[],"sources":["../../src/transformers/safeClassNames.ts"],"mappings":";;;;;;AAsGA;;;;;;;;;;;;iBAAgB,cAAA,CAAe,GAAA,EAAK,SAAA,IAAa,MAAA,GAAQ,SAAA,GAAiB,SAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"safeClassNames.js","names":[],"sources":["../../src/transformers/safeClassNames.ts"],"sourcesContent":["import postcss from 'postcss'\nimport safeParser from 'postcss-safe-parser'\nimport type { ChildNode, Element } from 'domhandler'\nimport { walk } from '../utils/ast/index.ts'\nimport type { CssConfig } from '../types/config.ts'\n\nconst DEFAULT_REPLACEMENTS: Record<string, string> = {\n ':': '-',\n '/': '-',\n '%': 'pc',\n '.': '_',\n ',': '_',\n '#': '_',\n '[': '',\n ']': '',\n '(': '',\n ')': '',\n '{': '',\n '}': '',\n '!': '-i',\n '&': 'and-',\n '<': 'lt-',\n '=': 'eq-',\n '>': 'gt-',\n '|': 'or-',\n '@': 'at-',\n '?': 'q-',\n '\\\\': '-',\n '\"': '-',\n \"'\": '-',\n '*': '-',\n '+': '-',\n ';': '-',\n '^': '-',\n '`': '-',\n '~': '-',\n '$': '-',\n}\n\nfunction escapeForRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Replace escaped special characters in CSS selectors.\n *\n * Tailwind generates selectors like `.sm\\:text-base`. This function\n * replaces the `\\:` with `-` (or whatever the configured replacement is)\n * so the selector becomes `.sm-text-base`, which is safe for email clients.\n */\nfunction processCssSelectors(css: string, replacements: Record<string, string>): string {\n // Matches \\<char> in CSS selectors — e.g. \\: \\/ \\. \\[ etc.\n const selectorRegex = new RegExp(\n `\\\\\\\\(${Object.keys(replacements).map(escapeForRegex).join('|')})`,\n 'g',\n )\n\n return postcss([\n (root: postcss.Root) => {\n root.walkRules((rule: postcss.Rule) => {\n rule.selector = rule.selector\n .replace(selectorRegex, (_matched, char) => replacements[char] ?? _matched)\n // Handle CSS unicode escape for comma (\\2c → _)\n .replaceAll('\\\\2c ', '_')\n })\n },\n ]).process(css, { parser: safeParser }).css\n}\n\n/**\n * Replace unsafe special characters in a class attribute value.\n *\n * Splits on whitespace and replaces each char from the replacements map\n * in each class token individually.\n */\nfunction processClassAttr(classStr: string, replacements: Record<string, string>): string {\n return classStr\n .split(/\\s+/)\n .filter(Boolean)\n .map((cls) => {\n for (const [from, to] of Object.entries(replacements)) {\n cls = cls.split(from).join(to)\n }\n return cls\n })\n .join(' ')\n}\n\n/**\n * Safe class names transformer.\n *\n * Replaces unsafe characters (`:`, `/`, `[`, `]`, etc.) in:\n * - CSS selectors inside `<style>` tags\n * - HTML `class` attributes\n *\n * This makes Tailwind utility classes like `sm:text-base` safe for\n * email clients that cannot handle escaped characters in class names.\n *\n * Enabled by default. Disable by setting `css.safe` to `false`.\n * Customize replacements by passing a `Record<string, string>` — user\n * values are merged on top of the defaults.\n */\nexport function safeClassNames(dom: ChildNode[], config: CssConfig = {}): ChildNode[] {\n const option = config.safe ?? true\n\n if (!option) return dom\n\n const replacements: Record<string, string> =\n option && typeof option === 'object'\n ? { ...DEFAULT_REPLACEMENTS, ...option }\n : DEFAULT_REPLACEMENTS\n\n walk(dom, (node) => {\n const el = node as Element\n\n // Process CSS selectors inside <style> tags\n if (el.name === 'style' && el.children?.length) {\n const text = el.children.find((c) => c.type === 'text') as any\n if (text?.data?.trim()) {\n text.data = processCssSelectors(text.data, replacements)\n }\n }\n\n // Replace special chars in class attributes\n if ('attribs' in el && el.attribs?.class) {\n el.attribs.class = processClassAttr(el.attribs.class, replacements)\n }\n })\n\n return dom\n}\n"],"mappings":";;;;;AAMA,MAAM,uBAA+C;CACnD,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACN;AAED,SAAS,eAAe,GAAmB;CACzC,OAAO,EAAE,QAAQ,uBAAuB,OAAO;;;;;;;;;AAUjD,SAAS,oBAAoB,KAAa,cAA8C;CAEtF,MAAM,gBAAgB,IAAI,OACxB,QAAQ,OAAO,KAAK,aAAa,CAAC,IAAI,eAAe,CAAC,KAAK,IAAI,CAAC,IAChE,IACD;CAED,OAAO,QAAQ,EACZ,SAAuB;EACtB,KAAK,WAAW,SAAuB;GACrC,KAAK,WAAW,KAAK,SAClB,QAAQ,gBAAgB,UAAU,SAAS,aAAa,SAAS,SAAS,CAE1E,WAAW,SAAS,IAAI;IAC3B;GAEL,CAAC,CAAC,QAAQ,KAAK,EAAE,QAAQ,YAAY,CAAC,CAAC;;;;;;;;AAS1C,SAAS,iBAAiB,UAAkB,cAA8C;CACxF,OAAO,SACJ,MAAM,MAAM,CACZ,OAAO,QAAQ,CACf,KAAK,QAAQ;EACZ,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,aAAa,EACnD,MAAM,IAAI,MAAM,KAAK,CAAC,KAAK,GAAG;EAEhC,OAAO;GACP,CACD,KAAK,IAAI;;;;;;;;;;;;;;;;AAiBd,SAAgB,eAAe,KAAkB,SAAoB,EAAE,EAAe;CACpF,MAAM,SAAS,OAAO,QAAQ;CAE9B,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,eACJ,UAAU,OAAO,WAAW,WACxB;EAAE,GAAG;EAAsB,GAAG;EAAQ,GACtC;CAEN,KAAK,MAAM,SAAS;EAClB,MAAM,KAAK;EAGX,IAAI,GAAG,SAAS,WAAW,GAAG,UAAU,QAAQ;GAC9C,MAAM,OAAO,GAAG,SAAS,MAAM,MAAM,EAAE,SAAS,OAAO;GACvD,IAAI,MAAM,MAAM,MAAM,EACpB,KAAK,OAAO,oBAAoB,KAAK,MAAM,aAAa;;EAK5D,IAAI,aAAa,MAAM,GAAG,SAAS,OACjC,GAAG,QAAQ,QAAQ,iBAAiB,GAAG,QAAQ,OAAO,aAAa;GAErE;CAEF,OAAO"}
|