@maizzle/framework 6.0.5 → 6.0.6
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/composables/defineConfig.js +2 -1
- package/dist/composables/defineConfig.js.map +1 -1
- package/dist/plugins/postcss/quoteFontFamilies.js +1 -1
- package/dist/plugins/postcss/quoteFontFamilies.js.map +1 -1
- package/dist/render/createRenderer.js +3 -2
- package/dist/render/createRenderer.js.map +1 -1
- package/dist/render/parallel/buildWorker.js +2 -1
- package/dist/render/parallel/buildWorker.js.map +1 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +2 -1
- package/dist/serve.js.map +1 -1
- package/dist/server/compatibility.js +5 -5
- package/dist/server/compatibility.js.map +1 -1
- package/dist/server/linter.js +2 -2
- package/dist/server/linter.js.map +1 -1
- package/dist/server/sfc-utils.js +1 -1
- package/dist/server/sfc-utils.js.map +1 -1
- package/dist/server/ui/.vite/deps/@lucide_vue.js +7313 -6416
- package/dist/server/ui/.vite/deps/@lucide_vue.js.map +1 -1
- package/dist/server/ui/.vite/deps/@vueuse_core.js +2 -4
- package/dist/server/ui/.vite/deps/@vueuse_core.js.map +1 -1
- package/dist/server/ui/.vite/deps/@vueuse_shared.js +1 -3
- package/dist/server/ui/.vite/deps/@vueuse_shared.js.map +1 -1
- package/dist/server/ui/.vite/deps/_metadata.json +17 -17
- package/dist/server/ui/.vite/deps/class-variance-authority.js +0 -2
- package/dist/server/ui/.vite/deps/class-variance-authority.js.map +1 -1
- package/dist/server/ui/.vite/deps/clsx.js +0 -2
- package/dist/server/ui/.vite/deps/culori.js +0 -2
- package/dist/server/ui/.vite/deps/culori.js.map +1 -1
- package/dist/server/ui/.vite/deps/reka-ui.js +63 -37
- package/dist/server/ui/.vite/deps/reka-ui.js.map +1 -1
- package/dist/server/ui/.vite/deps/tailwind-merge.js +1 -3
- package/dist/server/ui/.vite/deps/tailwind-merge.js.map +1 -1
- package/dist/server/ui/.vite/deps/vue-router.js +1 -3
- package/dist/server/ui/.vite/deps/vue-router.js.map +1 -1
- package/dist/server/ui/.vite/deps/vue.js +1 -1
- package/dist/server/ui/.vite/deps/{vue.runtime.esm-bundler-Dz9O_TVp.js → vue.runtime.esm-bundler-DjHXh3xg.js} +9 -6
- package/dist/server/ui/.vite/deps/{vue.runtime.esm-bundler-Dz9O_TVp.js.map → vue.runtime.esm-bundler-DjHXh3xg.js.map} +1 -1
- package/dist/transformers/addAttributes.js +1 -1
- package/dist/transformers/addAttributes.js.map +1 -1
- package/dist/transformers/sixHex.js +1 -1
- package/dist/transformers/sixHex.js.map +1 -1
- package/dist/types/config.d.ts +15 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/ast/serializer.js +1 -1
- package/dist/utils/ast/serializer.js.map +1 -1
- package/dist/utils/cssBox.js +1 -1
- package/dist/utils/cssBox.js.map +1 -1
- package/node_modules/maizzle/dist/commands/new.mjs +2 -2
- package/node_modules/maizzle/node_modules/commander/Readme.md +11 -15
- package/node_modules/maizzle/node_modules/commander/index.js +14 -17
- package/node_modules/maizzle/node_modules/commander/lib/argument.js +3 -6
- package/node_modules/maizzle/node_modules/commander/lib/command.js +46 -33
- package/node_modules/maizzle/node_modules/commander/lib/error.js +2 -5
- package/node_modules/maizzle/node_modules/commander/lib/help.js +4 -20
- package/node_modules/maizzle/node_modules/commander/lib/option.js +3 -6
- package/node_modules/maizzle/node_modules/commander/lib/suggestSimilar.js +2 -4
- package/node_modules/maizzle/node_modules/commander/package.json +10 -28
- package/node_modules/maizzle/node_modules/commander/typings/index.d.ts +3 -3
- package/node_modules/maizzle/package.json +2 -2
- package/package.json +2 -2
- package/node_modules/maizzle/node_modules/commander/esm.mjs +0 -16
- package/node_modules/maizzle/node_modules/commander/typings/esm.d.mts +0 -3
- /package/dist/server/ui/.vite/deps/{chunk-EAsCxrDo.js → rolldown-runtime-EAsCxrDo.js} +0 -0
|
@@ -68,7 +68,7 @@ function addAttributesDom(dom, config = {}) {
|
|
|
68
68
|
if (attrName === "class" && el.attribs.class) {
|
|
69
69
|
const existingClasses = el.attribs.class.split(/\s+/).filter(Boolean);
|
|
70
70
|
const newClasses = String(attrValue).split(/\s+/).filter(Boolean);
|
|
71
|
-
const mergedClasses = [
|
|
71
|
+
const mergedClasses = [.../* @__PURE__ */ new Set([...existingClasses, ...newClasses])];
|
|
72
72
|
if (mergedClasses.join(" ") !== el.attribs.class) el.attribs.class = mergedClasses.join(" ");
|
|
73
73
|
} else if (!(attrName in el.attribs)) el.attribs[attrName] = String(attrValue);
|
|
74
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addAttributes.js","names":["merge"],"sources":["../../src/transformers/addAttributes.ts"],"sourcesContent":["import { defu as merge } from 'defu'\nimport type { ChildNode, Element } from 'domhandler'\nimport { parse, serialize, walk } from '../utils/ast/index.ts'\nimport type { AttributesConfig } from '../types/config.ts'\n\n/**\n * Default attributes to add to elements.\n */\nconst DEFAULT_ATTRIBUTES: Record<string, Record<string, string | boolean | number>> = {\n table: {\n cellpadding: 0,\n cellspacing: 0,\n role: 'none',\n },\n img: {\n alt: '',\n },\n}\n\n/**\n * Add attributes transformer.\n *\n * Automatically adds attributes to HTML elements based on CSS selectors.\n *\n * Default attributes (can be disabled by setting `attributes.add` to false):\n * - table: cellpadding=\"0\", cellspacing=\"0\", role=\"none\"\n * - img: alt=\"\"\n *\n * Supports tag, class, id, and attribute selectors.\n * Multiple selectors can be specified by comma-separating them.\n *\n * @param html HTML string to transform.\n * @param config Attributes config (see {@link AttributesConfig}).\n * @returns The transformed HTML string.\n *\n * @example\n * import { addAttributes } from '@maizzle/framework'\n *\n * const out = addAttributes('<div></div>', {\n * add: {\n * div: { role: 'article' },\n * '.test': { editable: true },\n * '#header': { 'data-id': 'main' },\n * 'div, p': { class: 'content' },\n * },\n * })\n */\nexport function addAttributes(html: string, config: AttributesConfig = {}): string {\n return serialize(addAttributesDom(parse(html), config))\n}\n\n/**\n * DOM-form of {@link addAttributes} used by the internal transformer pipeline.\n * Takes a parsed DOM, returns a parsed DOM — avoids redundant\n * serialize/parse round-trips when chained with other transformers.\n */\nexport function addAttributesDom(dom: ChildNode[], config: AttributesConfig = {}): ChildNode[] {\n const addConfig = config.add\n\n // Disabled when explicitly set to false\n if (addConfig === false) {\n return dom\n }\n\n // Deep merge user attributes on top of defaults using defu\n const userAttributes = typeof addConfig === 'object' ? addConfig : {}\n const attributesToAdd = merge(userAttributes, DEFAULT_ATTRIBUTES) as Record<string, false | Record<string, false | string | boolean | number>>\n\n // Process each selector pattern\n for (const [selectorPattern, attributes] of Object.entries(attributesToAdd)) {\n // User opted out of this selector entirely (e.g. `table: false`)\n if (attributes === false) continue\n // Split by comma for multiple selectors\n const selectors = selectorPattern.split(',').map(s => s.trim())\n\n walk(dom, (node) => {\n const el = node as Element\n if (!el.name) return\n\n // Check if element matches any selector in the pattern\n const matches = selectors.some(selector => elementMatches(el, selector))\n\n if (matches) {\n // Initialize attribs if needed\n if (!el.attribs) {\n el.attribs = {}\n }\n\n for (const [attrName, attrValue] of Object.entries(attributes)) {\n // User opted out of this specific attribute (e.g. `role: false`)\n if (attrValue === false) continue\n // Special handling for class - merge instead of replace\n if (attrName === 'class' && el.attribs.class) {\n const existingClasses = el.attribs.class.split(/\\s+/).filter(Boolean)\n const newClasses = String(attrValue).split(/\\s+/).filter(Boolean)\n const mergedClasses = [...new Set([...existingClasses, ...newClasses])]\n if (mergedClasses.join(' ') !== el.attribs.class) {\n el.attribs.class = mergedClasses.join(' ')\n }\n } else {\n // Only add attribute if not already present\n if (!(attrName in el.attribs)) {\n el.attribs[attrName] = String(attrValue)\n }\n }\n }\n }\n })\n }\n\n return dom\n}\n\n/**\n * Check if an element matches a CSS selector.\n * Supports: tag, .class, #id, [attribute], [attribute=value]\n */\nfunction elementMatches(el: Element, selector: string): boolean {\n // Remove whitespace\n selector = selector.trim()\n\n // Check for attribute selector [attr] or [attr=value]\n const attrMatch = selector.match(/^\\[([^\\]=]+)(?:=([^\\]]*))?\\]$/)\n if (attrMatch) {\n const [, attrName, attrValue] = attrMatch\n if (attrValue === undefined) {\n // Just checking if attribute exists\n return attrName in el.attribs\n } else {\n // Check if attribute has specific value\n return el.attribs?.[attrName] === attrValue\n }\n }\n\n // Check for class selector .class\n if (selector.startsWith('.')) {\n const className = selector.slice(1)\n const classes = el.attribs?.class?.split(/\\s+/) || []\n return classes.includes(className)\n }\n\n // Check for id selector #id\n if (selector.startsWith('#')) {\n const id = selector.slice(1)\n return el.attribs?.id === id\n }\n\n // Check for tag selector (possibly with attribute)\n // Split tag from attribute if present, e.g., \"div[role=alert]\"\n const tagAttrMatch = selector.match(/^([a-z][a-z0-9]*)\\[([^\\]]+)\\]$/i)\n if (tagAttrMatch) {\n const [, tagName, attrPart] = tagAttrMatch\n if (el.name !== tagName) return false\n\n // Parse attribute part: could be \"attr\" or \"attr=value\"\n const attrEqMatch = attrPart.match(/^([^=]+)(?:=(.*))?$/)\n if (attrEqMatch) {\n const [, attrName, attrValue] = attrEqMatch\n if (attrValue === undefined) {\n return attrName in el.attribs\n } else {\n return el.attribs?.[attrName] === attrValue\n }\n }\n return false\n }\n\n // Simple tag selector\n return el.name === selector\n}\n"],"mappings":";;;;;;;;;AAQA,MAAM,qBAAgF;CACpF,OAAO;EACL,aAAa;EACb,aAAa;EACb,MAAM;CACR;CACA,KAAK,EACH,KAAK,GACP;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,cAAc,MAAc,SAA2B,CAAC,GAAW;CACjF,OAAO,UAAU,iBAAiB,MAAM,IAAI,GAAG,MAAM,CAAC;AACxD;;;;;;AAOA,SAAgB,iBAAiB,KAAkB,SAA2B,CAAC,GAAgB;CAC7F,MAAM,YAAY,OAAO;CAGzB,IAAI,cAAc,OAChB,OAAO;CAKT,MAAM,kBAAkBA,OADD,OAAO,cAAc,WAAW,YAAY,CAAC,GACtB,kBAAkB;CAGhE,KAAK,MAAM,CAAC,iBAAiB,eAAe,OAAO,QAAQ,eAAe,GAAG;EAE3E,IAAI,eAAe,OAAO;EAE1B,MAAM,YAAY,gBAAgB,MAAM,GAAG,CAAC,CAAC,KAAI,MAAK,EAAE,KAAK,CAAC;EAE9D,KAAK,MAAM,SAAS;GAClB,MAAM,KAAK;GACX,IAAI,CAAC,GAAG,MAAM;GAKd,IAFgB,UAAU,MAAK,aAAY,eAAe,IAAI,QAAQ,CAE5D,GAAG;IAEX,IAAI,CAAC,GAAG,SACN,GAAG,UAAU,CAAC;IAGhB,KAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,UAAU,GAAG;KAE9D,IAAI,cAAc,OAAO;KAEzB,IAAI,aAAa,WAAW,GAAG,QAAQ,OAAO;MAC5C,MAAM,kBAAkB,GAAG,QAAQ,MAAM,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;MACpE,MAAM,aAAa,OAAO,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;MAChE,MAAM,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"addAttributes.js","names":["merge"],"sources":["../../src/transformers/addAttributes.ts"],"sourcesContent":["import { defu as merge } from 'defu'\nimport type { ChildNode, Element } from 'domhandler'\nimport { parse, serialize, walk } from '../utils/ast/index.ts'\nimport type { AttributesConfig } from '../types/config.ts'\n\n/**\n * Default attributes to add to elements.\n */\nconst DEFAULT_ATTRIBUTES: Record<string, Record<string, string | boolean | number>> = {\n table: {\n cellpadding: 0,\n cellspacing: 0,\n role: 'none',\n },\n img: {\n alt: '',\n },\n}\n\n/**\n * Add attributes transformer.\n *\n * Automatically adds attributes to HTML elements based on CSS selectors.\n *\n * Default attributes (can be disabled by setting `attributes.add` to false):\n * - table: cellpadding=\"0\", cellspacing=\"0\", role=\"none\"\n * - img: alt=\"\"\n *\n * Supports tag, class, id, and attribute selectors.\n * Multiple selectors can be specified by comma-separating them.\n *\n * @param html HTML string to transform.\n * @param config Attributes config (see {@link AttributesConfig}).\n * @returns The transformed HTML string.\n *\n * @example\n * import { addAttributes } from '@maizzle/framework'\n *\n * const out = addAttributes('<div></div>', {\n * add: {\n * div: { role: 'article' },\n * '.test': { editable: true },\n * '#header': { 'data-id': 'main' },\n * 'div, p': { class: 'content' },\n * },\n * })\n */\nexport function addAttributes(html: string, config: AttributesConfig = {}): string {\n return serialize(addAttributesDom(parse(html), config))\n}\n\n/**\n * DOM-form of {@link addAttributes} used by the internal transformer pipeline.\n * Takes a parsed DOM, returns a parsed DOM — avoids redundant\n * serialize/parse round-trips when chained with other transformers.\n */\nexport function addAttributesDom(dom: ChildNode[], config: AttributesConfig = {}): ChildNode[] {\n const addConfig = config.add\n\n // Disabled when explicitly set to false\n if (addConfig === false) {\n return dom\n }\n\n // Deep merge user attributes on top of defaults using defu\n const userAttributes = typeof addConfig === 'object' ? addConfig : {}\n const attributesToAdd = merge(userAttributes, DEFAULT_ATTRIBUTES) as Record<string, false | Record<string, false | string | boolean | number>>\n\n // Process each selector pattern\n for (const [selectorPattern, attributes] of Object.entries(attributesToAdd)) {\n // User opted out of this selector entirely (e.g. `table: false`)\n if (attributes === false) continue\n // Split by comma for multiple selectors\n const selectors = selectorPattern.split(',').map(s => s.trim())\n\n walk(dom, (node) => {\n const el = node as Element\n if (!el.name) return\n\n // Check if element matches any selector in the pattern\n const matches = selectors.some(selector => elementMatches(el, selector))\n\n if (matches) {\n // Initialize attribs if needed\n if (!el.attribs) {\n el.attribs = {}\n }\n\n for (const [attrName, attrValue] of Object.entries(attributes)) {\n // User opted out of this specific attribute (e.g. `role: false`)\n if (attrValue === false) continue\n // Special handling for class - merge instead of replace\n if (attrName === 'class' && el.attribs.class) {\n const existingClasses = el.attribs.class.split(/\\s+/).filter(Boolean)\n const newClasses = String(attrValue).split(/\\s+/).filter(Boolean)\n const mergedClasses = [...new Set([...existingClasses, ...newClasses])]\n if (mergedClasses.join(' ') !== el.attribs.class) {\n el.attribs.class = mergedClasses.join(' ')\n }\n } else {\n // Only add attribute if not already present\n if (!(attrName in el.attribs)) {\n el.attribs[attrName] = String(attrValue)\n }\n }\n }\n }\n })\n }\n\n return dom\n}\n\n/**\n * Check if an element matches a CSS selector.\n * Supports: tag, .class, #id, [attribute], [attribute=value]\n */\nfunction elementMatches(el: Element, selector: string): boolean {\n // Remove whitespace\n selector = selector.trim()\n\n // Check for attribute selector [attr] or [attr=value]\n const attrMatch = selector.match(/^\\[([^\\]=]+)(?:=([^\\]]*))?\\]$/)\n if (attrMatch) {\n const [, attrName, attrValue] = attrMatch\n if (attrValue === undefined) {\n // Just checking if attribute exists\n return attrName in el.attribs\n } else {\n // Check if attribute has specific value\n return el.attribs?.[attrName] === attrValue\n }\n }\n\n // Check for class selector .class\n if (selector.startsWith('.')) {\n const className = selector.slice(1)\n const classes = el.attribs?.class?.split(/\\s+/) || []\n return classes.includes(className)\n }\n\n // Check for id selector #id\n if (selector.startsWith('#')) {\n const id = selector.slice(1)\n return el.attribs?.id === id\n }\n\n // Check for tag selector (possibly with attribute)\n // Split tag from attribute if present, e.g., \"div[role=alert]\"\n const tagAttrMatch = selector.match(/^([a-z][a-z0-9]*)\\[([^\\]]+)\\]$/i)\n if (tagAttrMatch) {\n const [, tagName, attrPart] = tagAttrMatch\n if (el.name !== tagName) return false\n\n // Parse attribute part: could be \"attr\" or \"attr=value\"\n const attrEqMatch = attrPart.match(/^([^=]+)(?:=(.*))?$/)\n if (attrEqMatch) {\n const [, attrName, attrValue] = attrEqMatch\n if (attrValue === undefined) {\n return attrName in el.attribs\n } else {\n return el.attribs?.[attrName] === attrValue\n }\n }\n return false\n }\n\n // Simple tag selector\n return el.name === selector\n}\n"],"mappings":";;;;;;;;;AAQA,MAAM,qBAAgF;CACpF,OAAO;EACL,aAAa;EACb,aAAa;EACb,MAAM;CACR;CACA,KAAK,EACH,KAAK,GACP;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,cAAc,MAAc,SAA2B,CAAC,GAAW;CACjF,OAAO,UAAU,iBAAiB,MAAM,IAAI,GAAG,MAAM,CAAC;AACxD;;;;;;AAOA,SAAgB,iBAAiB,KAAkB,SAA2B,CAAC,GAAgB;CAC7F,MAAM,YAAY,OAAO;CAGzB,IAAI,cAAc,OAChB,OAAO;CAKT,MAAM,kBAAkBA,OADD,OAAO,cAAc,WAAW,YAAY,CAAC,GACtB,kBAAkB;CAGhE,KAAK,MAAM,CAAC,iBAAiB,eAAe,OAAO,QAAQ,eAAe,GAAG;EAE3E,IAAI,eAAe,OAAO;EAE1B,MAAM,YAAY,gBAAgB,MAAM,GAAG,CAAC,CAAC,KAAI,MAAK,EAAE,KAAK,CAAC;EAE9D,KAAK,MAAM,SAAS;GAClB,MAAM,KAAK;GACX,IAAI,CAAC,GAAG,MAAM;GAKd,IAFgB,UAAU,MAAK,aAAY,eAAe,IAAI,QAAQ,CAE5D,GAAG;IAEX,IAAI,CAAC,GAAG,SACN,GAAG,UAAU,CAAC;IAGhB,KAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,UAAU,GAAG;KAE9D,IAAI,cAAc,OAAO;KAEzB,IAAI,aAAa,WAAW,GAAG,QAAQ,OAAO;MAC5C,MAAM,kBAAkB,GAAG,QAAQ,MAAM,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;MACpE,MAAM,aAAa,OAAO,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;MAChE,MAAM,gBAAgB,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,iBAAiB,GAAG,UAAU,CAAC,CAAC;MACtE,IAAI,cAAc,KAAK,GAAG,MAAM,GAAG,QAAQ,OACzC,GAAG,QAAQ,QAAQ,cAAc,KAAK,GAAG;KAE7C,OAEE,IAAI,EAAE,YAAY,GAAG,UACnB,GAAG,QAAQ,YAAY,OAAO,SAAS;IAG7C;GACF;EACF,CAAC;CACH;CAEA,OAAO;AACT;;;;;AAMA,SAAS,eAAe,IAAa,UAA2B;CAE9D,WAAW,SAAS,KAAK;CAGzB,MAAM,YAAY,SAAS,MAAM,+BAA+B;CAChE,IAAI,WAAW;EACb,MAAM,GAAG,UAAU,aAAa;EAChC,IAAI,cAAc,KAAA,GAEhB,OAAO,YAAY,GAAG;OAGtB,OAAO,GAAG,UAAU,cAAc;CAEtC;CAGA,IAAI,SAAS,WAAW,GAAG,GAAG;EAC5B,MAAM,YAAY,SAAS,MAAM,CAAC;EAElC,QADgB,GAAG,SAAS,OAAO,MAAM,KAAK,KAAK,CAAC,EAAA,CACrC,SAAS,SAAS;CACnC;CAGA,IAAI,SAAS,WAAW,GAAG,GAAG;EAC5B,MAAM,KAAK,SAAS,MAAM,CAAC;EAC3B,OAAO,GAAG,SAAS,OAAO;CAC5B;CAIA,MAAM,eAAe,SAAS,MAAM,iCAAiC;CACrE,IAAI,cAAc;EAChB,MAAM,GAAG,SAAS,YAAY;EAC9B,IAAI,GAAG,SAAS,SAAS,OAAO;EAGhC,MAAM,cAAc,SAAS,MAAM,qBAAqB;EACxD,IAAI,aAAa;GACf,MAAM,GAAG,UAAU,aAAa;GAChC,IAAI,cAAc,KAAA,GAChB,OAAO,YAAY,GAAG;QAEtB,OAAO,GAAG,UAAU,cAAc;EAEtC;EACA,OAAO;CACT;CAGA,OAAO,GAAG,SAAS;AACrB"}
|
|
@@ -4,7 +4,7 @@ import { serialize } from "../utils/ast/serializer.js";
|
|
|
4
4
|
import "../utils/ast/index.js";
|
|
5
5
|
import { conv } from "color-shorthand-hex-to-six-digit";
|
|
6
6
|
//#region src/transformers/sixHex.ts
|
|
7
|
-
const targets = new Set(["bgcolor", "color"]);
|
|
7
|
+
const targets = /* @__PURE__ */ new Set(["bgcolor", "color"]);
|
|
8
8
|
/**
|
|
9
9
|
* Convert 3-digit HEX color codes to 6-digit in `bgcolor` and `color`
|
|
10
10
|
* attributes, for better email client compatibility.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sixHex.js","names":[],"sources":["../../src/transformers/sixHex.ts"],"sourcesContent":["import { conv } from 'color-shorthand-hex-to-six-digit'\nimport type { ChildNode, Element } from 'domhandler'\nimport { parse, serialize, walk } from '../utils/ast/index.ts'\n\nconst targets = new Set(['bgcolor', 'color'])\n\n/**\n * Convert 3-digit HEX color codes to 6-digit in `bgcolor` and `color`\n * attributes, for better email client compatibility.\n *\n * @param html HTML string to transform.\n * @returns The transformed HTML string.\n *\n * @example\n * import { sixHex } from '@maizzle/framework'\n *\n * const out = sixHex('<font color=\"#abc\">x</font>')\n */\nexport function sixHex(html: string): string {\n return serialize(sixHexDom(parse(html)))\n}\n\n/**\n * DOM-form of {@link sixHex} used by the internal transformer pipeline.\n * Takes a parsed DOM, returns a parsed DOM — avoids redundant\n * serialize/parse round-trips when chained with other transformers.\n */\nexport function sixHexDom(dom: ChildNode[]): ChildNode[] {\n walk(dom, (node) => {\n const el = node as Element\n\n if (!el.attribs) {\n return\n }\n\n for (const attr of targets) {\n const value = el.attribs[attr]\n\n if (value) {\n el.attribs[attr] = conv(value)\n }\n }\n })\n\n return dom\n}\n"],"mappings":";;;;;;AAIA,MAAM,
|
|
1
|
+
{"version":3,"file":"sixHex.js","names":[],"sources":["../../src/transformers/sixHex.ts"],"sourcesContent":["import { conv } from 'color-shorthand-hex-to-six-digit'\nimport type { ChildNode, Element } from 'domhandler'\nimport { parse, serialize, walk } from '../utils/ast/index.ts'\n\nconst targets = new Set(['bgcolor', 'color'])\n\n/**\n * Convert 3-digit HEX color codes to 6-digit in `bgcolor` and `color`\n * attributes, for better email client compatibility.\n *\n * @param html HTML string to transform.\n * @returns The transformed HTML string.\n *\n * @example\n * import { sixHex } from '@maizzle/framework'\n *\n * const out = sixHex('<font color=\"#abc\">x</font>')\n */\nexport function sixHex(html: string): string {\n return serialize(sixHexDom(parse(html)))\n}\n\n/**\n * DOM-form of {@link sixHex} used by the internal transformer pipeline.\n * Takes a parsed DOM, returns a parsed DOM — avoids redundant\n * serialize/parse round-trips when chained with other transformers.\n */\nexport function sixHexDom(dom: ChildNode[]): ChildNode[] {\n walk(dom, (node) => {\n const el = node as Element\n\n if (!el.attribs) {\n return\n }\n\n for (const attr of targets) {\n const value = el.attribs[attr]\n\n if (value) {\n el.attribs[attr] = conv(value)\n }\n }\n })\n\n return dom\n}\n"],"mappings":";;;;;;AAIA,MAAM,0BAAU,IAAI,IAAI,CAAC,WAAW,OAAO,CAAC;;;;;;;;;;;;;AAc5C,SAAgB,OAAO,MAAsB;CAC3C,OAAO,UAAU,UAAU,MAAM,IAAI,CAAC,CAAC;AACzC;;;;;;AAOA,SAAgB,UAAU,KAA+B;CACvD,KAAK,MAAM,SAAS;EAClB,MAAM,KAAK;EAEX,IAAI,CAAC,GAAG,SACN;EAGF,KAAK,MAAM,QAAQ,SAAS;GAC1B,MAAM,QAAQ,GAAG,QAAQ;GAEzB,IAAI,OACF,GAAG,QAAQ,QAAQ,KAAK,KAAK;EAEjC;CACF,CAAC;CAED,OAAO;AACT"}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -586,6 +586,21 @@ interface MaizzleConfig {
|
|
|
586
586
|
* @default 3000
|
|
587
587
|
*/
|
|
588
588
|
port?: number;
|
|
589
|
+
/**
|
|
590
|
+
* Expose the dev server on the network.
|
|
591
|
+
*
|
|
592
|
+
* Set to `true` to listen on all interfaces (prints a network URL +
|
|
593
|
+
* QR code), or pass a string to bind a specific address. The
|
|
594
|
+
* `--host` CLI flag takes precedence over this.
|
|
595
|
+
*
|
|
596
|
+
* @default false
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* server: {
|
|
600
|
+
* host: true,
|
|
601
|
+
* }
|
|
602
|
+
*/
|
|
603
|
+
host?: boolean | string;
|
|
589
604
|
/**
|
|
590
605
|
* Additional file paths to watch for changes.
|
|
591
606
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","names":[],"sources":["../../src/types/config.ts"],"mappings":";;;;;;;;KAKK,YAAA,GAAe,WAAA,CAAY,UAAA,QAAkB,KAAA;AAAA,UAGjC,eAAA;;AALa;;;;EAW5B,IAAA;EATkB;;;;;EAelB,UAAA;EAfqD;AAAA;AAGvD;;;EAkBE,MAAA;EAZA;;;;;EAkBA,EAAA,GAAK,MAAM;AAAA;AAAA,KAGD,QAAA,GAAW,MAAA;EACrB,QAAA,GAAW,eAAe;AAAA;AAAA,UAGX,SAAA;EAJM;;;;AACK;AAG5B;;;;;;EAYE,KAAA,GAAQ,QAAA;EAiBa;;;;;;;;;;EANrB,IAAA;IAQE,+BANA,GAAA,WAQS;IANT,IAAA,cAAkB,MAAA,SAAe,MAAA,6BAUpB;IARb,UAAA,GAAa,MAAA,kBAQS;IANtB,QAAA,YAkCiB;IAhCjB,SAAA;EAAA;AAAA;AAAA,UAIa,SAAA;EA2JM;;;;;EArJrB,IAAA;EAsBA;;;;;;;EAdA,KAAA,aAAkB,MAAA;EA4DhB;;;;;;;;;;;;;EA9CF,MAAA,aAAmB,YAAA;IA4GnB;;;;;;IArGE,gBAAA;IAqIK;AAAA;AAGT;;;IAlII,oBAAA;IAoJY;;;;;;IA7IZ,QAAA;IA6ImC;;;;;;;AAsB0B;AAGjE;;;IA1JI,gBAAA,GAAmB,MAAA;IA0JsB;AAO7C;;;;AAA2B;IA1JvB,aAAA;IAiKyB;;;;;;IA1JzB,cAAA;IAwKG;AAGP;;;;AAsBe;IA1LX,kBAAA;IA6LuB;;;;;;IAtLvB,UAAA,GAAa,MAAA;MAAiB,KAAA;MAAe,GAAA;IAAA;IAgM9B;;;;IA3Lf,SAAA;EAAA;EA0MkD;AAAA;AAGtD;;;;AAAwD;AACxD;;;;AAAiE;EAhM/D,KAAA;IAkM8B;;;;;IA5L5B,IAAA,wCAA4C,CAAA,UAAW,CAAA;EAAA;EAkMhB;AAG3C;;;;;;EA5LE,cAAA;EAyMmB;;;;;EAnMnB,IAAA,aAAiB,MAAA;EAiMjB;;;;;;AAEyB;EA3LzB,SAAA;IAAwB,IAAA;EAAA;EAgNS;;;;;;;EAxMjC,MAAA;EAgNA;;;;;;;;;AAOM;EA5MN,kBAAA,GAAqB,MAAA,SA3BE,WAAA;EAgPO;;;;;;;;;AAiBoB;AAapD;;EAtOE,OAAA;AAAA;AAAA,UAGe,gBAAA;EA4Ob;;;AASU;AAGd;;;;;;;;;;;;;EAtOE,GAAA,WAAc,MAAA,iBAAuB,MAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../../src/types/config.ts"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import render from "dom-serializer";
|
|
2
2
|
//#region src/utils/ast/serializer.ts
|
|
3
|
-
const RAW_TEXT_ELEMENTS = new Set(["script", "style"]);
|
|
3
|
+
const RAW_TEXT_ELEMENTS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
4
4
|
/**
|
|
5
5
|
* Re-encode `<` and `>` in text nodes before serialization.
|
|
6
6
|
*
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,oCAAoB,IAAI,IAAI,CAAC,UAAU,OAAO,CAAC;;;;;;;;;;;;;;;;;AAkBrD,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,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM;GACzB;GACA;EACF;EAEA,IAAI,cAAc,QAAS,KAAiB,UAAU,QAAQ;GAC5D,MAAM,KAAK;GACX,MAAM,UAAU,aAAa,kBAAkB,IAAI,GAAG,IAAI;GAC1D,gBAAgB,GAAG,UAAyB,OAAO;EACrD;CACF;AACF;AAEA,SAAgB,UAAU,KAAkB,SAAwC;CAClF,gBAAgB,GAAG;CACnB,OAAO,OAAO,KAAK;EAAE,gBAAgB;EAAO,GAAG;CAAQ,CAAC;AAC1D"}
|
package/dist/utils/cssBox.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/utils/cssBox.ts
|
|
2
|
-
const NO_BORDER_STYLES = new Set(["none", "hidden"]);
|
|
2
|
+
const NO_BORDER_STYLES = /* @__PURE__ */ new Set(["none", "hidden"]);
|
|
3
3
|
/**
|
|
4
4
|
* Parse a length token into px. Handles `Npx`, `Nrem`, `Nem`, `Npt`, and
|
|
5
5
|
* unitless N (treated as px). Returns null for percentages, calc(),
|
package/dist/utils/cssBox.js.map
CHANGED
|
@@ -1 +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 const unit = (m[2] || 'px').toLowerCase()\n return n * (unit === 'rem' || unit === 'em' ? 16 : unit === 'pt' ? 1.333 : 1)\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":";AAEA,MAAa,
|
|
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 const unit = (m[2] || 'px').toLowerCase()\n return n * (unit === 'rem' || unit === 'em' ? 16 : unit === 'pt' ? 1.333 : 1)\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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"}
|
|
@@ -122,9 +122,9 @@ async function newProject(starterArg, dirArg, options = {}) {
|
|
|
122
122
|
starter: async () => {
|
|
123
123
|
const starter = await p.select({
|
|
124
124
|
message: "Select a Starter",
|
|
125
|
-
initialValue: "maizzle/maizzle#
|
|
125
|
+
initialValue: "maizzle/maizzle#master",
|
|
126
126
|
options: [{
|
|
127
|
-
value: "maizzle/maizzle#
|
|
127
|
+
value: "maizzle/maizzle#master",
|
|
128
128
|
label: "Default"
|
|
129
129
|
}, {
|
|
130
130
|
value: "custom",
|
|
@@ -76,7 +76,7 @@ The two most used option types are a boolean option, and an option which takes i
|
|
|
76
76
|
Example file: [split.js](./examples/split.js)
|
|
77
77
|
|
|
78
78
|
```js
|
|
79
|
-
|
|
79
|
+
import { program } from 'commander';
|
|
80
80
|
|
|
81
81
|
program
|
|
82
82
|
.option('--first')
|
|
@@ -91,10 +91,10 @@ console.log(program.args[0].split(options.separator, limit));
|
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
```console
|
|
94
|
-
$ node split.js -s
|
|
94
|
+
$ node split.js -s - --fits a-b-c
|
|
95
95
|
error: unknown option '--fits'
|
|
96
96
|
(Did you mean --first?)
|
|
97
|
-
$ node split.js -s
|
|
97
|
+
$ node split.js -s - --first a-b-c
|
|
98
98
|
[ 'a' ]
|
|
99
99
|
```
|
|
100
100
|
|
|
@@ -103,7 +103,7 @@ Here is a more complete program using a subcommand and with descriptions for the
|
|
|
103
103
|
Example file: [string-util.js](./examples/string-util.js)
|
|
104
104
|
|
|
105
105
|
```js
|
|
106
|
-
|
|
106
|
+
import { Command } from 'commander';
|
|
107
107
|
const program = new Command();
|
|
108
108
|
|
|
109
109
|
program
|
|
@@ -138,7 +138,7 @@ Options:
|
|
|
138
138
|
-s, --separator <char> separator character (default: ",")
|
|
139
139
|
-h, --help display help for command
|
|
140
140
|
|
|
141
|
-
$ node string-util.js split --separator
|
|
141
|
+
$ node string-util.js split --separator=- a-b-c
|
|
142
142
|
[ 'a', 'b', 'c' ]
|
|
143
143
|
```
|
|
144
144
|
|
|
@@ -147,11 +147,10 @@ More samples can be found in the [examples](https://github.com/tj/commander.js/t
|
|
|
147
147
|
## Declaring _program_ variable
|
|
148
148
|
|
|
149
149
|
Commander exports a global object which is convenient for quick programs.
|
|
150
|
-
This is used in
|
|
150
|
+
This is used in some examples in this README for brevity.
|
|
151
151
|
|
|
152
152
|
```js
|
|
153
|
-
|
|
154
|
-
const { program } = require('commander');
|
|
153
|
+
import { program } from 'commander';
|
|
155
154
|
```
|
|
156
155
|
|
|
157
156
|
For larger programs which may use commander in multiple ways, including unit testing, it is better to create a local `Command` object to use.
|
|
@@ -276,10 +275,7 @@ cheese: stilton
|
|
|
276
275
|
### Other option types, negatable boolean and boolean|value
|
|
277
276
|
|
|
278
277
|
You can define a boolean option long name with a leading `no-` to set the option value to `false` when used.
|
|
279
|
-
Defined alone, this also makes the option `true` by default.
|
|
280
|
-
|
|
281
|
-
If you define `--foo` first, adding `--no-foo` does not change the default value from what it would
|
|
282
|
-
otherwise be.
|
|
278
|
+
Defined alone without a matching positive option, this also makes the option `true` by default.
|
|
283
279
|
|
|
284
280
|
Example file: [options-negatable.js](./examples/options-negatable.js)
|
|
285
281
|
|
|
@@ -558,7 +554,7 @@ Configuration options can be passed with the call to `.command()` and `.addComma
|
|
|
558
554
|
remove the command from the generated help output. Specifying `isDefault: true` will run the subcommand if no other
|
|
559
555
|
subcommand is specified. (Example file: [defaultCommand.js](./examples/defaultCommand.js).)
|
|
560
556
|
|
|
561
|
-
You can add alternative names for a command with `.alias()`. (Example file: [alias.
|
|
557
|
+
You can add alternative names for a command with `.alias()`. (Example file: [alias.cjs](./examples/alias.cjs).)
|
|
562
558
|
|
|
563
559
|
`.command()` automatically copies the inherited settings from the parent command to the newly created subcommand. This is only done during creation; any later setting changes to the parent are not inherited.
|
|
564
560
|
|
|
@@ -1060,7 +1056,7 @@ node -r ts-node/register pm.ts
|
|
|
1060
1056
|
This factory function creates a new command. It is exported and may be used instead of using `new`, like:
|
|
1061
1057
|
|
|
1062
1058
|
```js
|
|
1063
|
-
|
|
1059
|
+
import { createCommand } from 'commander';
|
|
1064
1060
|
const program = createCommand();
|
|
1065
1061
|
```
|
|
1066
1062
|
|
|
@@ -1163,7 +1159,7 @@ There is more information available about:
|
|
|
1163
1159
|
|
|
1164
1160
|
## Support
|
|
1165
1161
|
|
|
1166
|
-
The current version of Commander is fully supported on Long Term Support versions of Node.js, and requires at least
|
|
1162
|
+
The current version of Commander is fully supported on Long Term Support versions of Node.js, and requires at least v22.12.0.
|
|
1167
1163
|
|
|
1168
1164
|
Older major versions of Commander receive security updates for 12 months. For more see: [Release Policy](./docs/release-policy.md).
|
|
1169
1165
|
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { Argument } from './lib/argument.js';
|
|
2
|
+
import { Command } from './lib/command.js';
|
|
3
|
+
import { CommanderError, InvalidArgumentError } from './lib/error.js';
|
|
4
|
+
import { Help } from './lib/help.js';
|
|
5
|
+
import { Option } from './lib/option.js';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export const program = new Command();
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export const createCommand = (name) => new Command(name);
|
|
10
|
+
export const createOption = (flags, description) =>
|
|
11
|
+
new Option(flags, description);
|
|
12
|
+
export const createArgument = (name, description) =>
|
|
13
|
+
new Argument(name, description);
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Expose classes
|
|
15
17
|
*/
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
exports.Help = Help;
|
|
21
|
-
|
|
22
|
-
exports.CommanderError = CommanderError;
|
|
23
|
-
exports.InvalidArgumentError = InvalidArgumentError;
|
|
24
|
-
exports.InvalidOptionArgumentError = InvalidArgumentError; // Deprecated
|
|
19
|
+
export { Command, Option, Argument, Help };
|
|
20
|
+
export { CommanderError, InvalidArgumentError };
|
|
21
|
+
export { InvalidArgumentError as InvalidOptionArgumentError }; // Deprecated
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { InvalidArgumentError } from './error.js';
|
|
2
2
|
|
|
3
|
-
class Argument {
|
|
3
|
+
export class Argument {
|
|
4
4
|
/**
|
|
5
5
|
* Initialize a new command argument with the given name and description.
|
|
6
6
|
* The default is that the argument is required, and you can explicitly
|
|
@@ -140,11 +140,8 @@ class Argument {
|
|
|
140
140
|
* @private
|
|
141
141
|
*/
|
|
142
142
|
|
|
143
|
-
function humanReadableArgName(arg) {
|
|
143
|
+
export function humanReadableArgName(arg) {
|
|
144
144
|
const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');
|
|
145
145
|
|
|
146
146
|
return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']';
|
|
147
147
|
}
|
|
148
|
-
|
|
149
|
-
exports.Argument = Argument;
|
|
150
|
-
exports.humanReadableArgName = humanReadableArgName;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import childProcess from 'node:child_process';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
import { Argument, humanReadableArgName } from './argument.js';
|
|
9
|
+
import { CommanderError } from './error.js';
|
|
10
|
+
import { Help } from './help.js';
|
|
11
|
+
import { Option, DualOptions } from './option.js';
|
|
12
|
+
import { suggestSimilar } from './suggestSimilar.js';
|
|
12
13
|
|
|
13
|
-
class Command extends EventEmitter {
|
|
14
|
+
export class Command extends EventEmitter {
|
|
14
15
|
/**
|
|
15
16
|
* Initialize a new `Command`.
|
|
16
17
|
*
|
|
@@ -70,7 +71,7 @@ class Command extends EventEmitter {
|
|
|
70
71
|
useColor() ?? (process.stdout.isTTY && process.stdout.hasColors?.()),
|
|
71
72
|
getErrHasColors: () =>
|
|
72
73
|
useColor() ?? (process.stderr.isTTY && process.stderr.hasColors?.()),
|
|
73
|
-
stripColor: (str) =>
|
|
74
|
+
stripColor: (str) => stripVTControlCharacters(str),
|
|
74
75
|
};
|
|
75
76
|
|
|
76
77
|
this._hidden = false;
|
|
@@ -674,17 +675,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
674
675
|
const name = option.attributeName();
|
|
675
676
|
|
|
676
677
|
// store default value
|
|
677
|
-
if (option.
|
|
678
|
-
// --no-foo is special and defaults foo to true, unless a --foo option is already defined
|
|
679
|
-
const positiveLongFlag = option.long.replace(/^--no-/, '--');
|
|
680
|
-
if (!this._findOption(positiveLongFlag)) {
|
|
681
|
-
this.setOptionValueWithSource(
|
|
682
|
-
name,
|
|
683
|
-
option.defaultValue === undefined ? true : option.defaultValue,
|
|
684
|
-
'default',
|
|
685
|
-
);
|
|
686
|
-
}
|
|
687
|
-
} else if (option.defaultValue !== undefined) {
|
|
678
|
+
if (option.defaultValue !== undefined) {
|
|
688
679
|
this.setOptionValueWithSource(name, option.defaultValue, 'default');
|
|
689
680
|
}
|
|
690
681
|
|
|
@@ -1125,7 +1116,29 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1125
1116
|
}
|
|
1126
1117
|
|
|
1127
1118
|
_prepareForParse() {
|
|
1119
|
+
// Save the state the first time, then restore the state before each subsequent parse.
|
|
1128
1120
|
if (this._savedState === null) {
|
|
1121
|
+
// Do the special default of lone negated option to true, now that we have all the options.
|
|
1122
|
+
// Filter for negated options that have not been processed already.
|
|
1123
|
+
this.options
|
|
1124
|
+
.filter(
|
|
1125
|
+
(option) =>
|
|
1126
|
+
option.negate &&
|
|
1127
|
+
option.defaultValue === undefined &&
|
|
1128
|
+
this.getOptionValue(option.attributeName()) === undefined,
|
|
1129
|
+
)
|
|
1130
|
+
.forEach((option) => {
|
|
1131
|
+
// check for lone negated option: --no-foo without a --foo option
|
|
1132
|
+
const positiveLongFlag = option.long.replace(/^--no-/, '--');
|
|
1133
|
+
if (!this._findOption(positiveLongFlag)) {
|
|
1134
|
+
this.setOptionValueWithSource(
|
|
1135
|
+
option.attributeName(),
|
|
1136
|
+
true,
|
|
1137
|
+
'default',
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1129
1142
|
this.saveStateBeforeParse();
|
|
1130
1143
|
} else {
|
|
1131
1144
|
this.restoreStateBeforeParse();
|
|
@@ -1201,7 +1214,6 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1201
1214
|
|
|
1202
1215
|
_executeSubCommand(subcommand, args) {
|
|
1203
1216
|
args = args.slice();
|
|
1204
|
-
let launchWithNode = false; // Use node for source targets so do not need to get permissions correct, and on Windows.
|
|
1205
1217
|
const sourceExt = ['.js', '.ts', '.tsx', '.mjs', '.cjs'];
|
|
1206
1218
|
|
|
1207
1219
|
function findFile(baseDir, baseName) {
|
|
@@ -1262,7 +1274,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1262
1274
|
executableFile = localFile || executableFile;
|
|
1263
1275
|
}
|
|
1264
1276
|
|
|
1265
|
-
launchWithNode = sourceExt.includes(path.extname(executableFile));
|
|
1277
|
+
const launchWithNode = sourceExt.includes(path.extname(executableFile));
|
|
1266
1278
|
|
|
1267
1279
|
let proc;
|
|
1268
1280
|
if (process.platform !== 'win32') {
|
|
@@ -2148,8 +2160,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2148
2160
|
|
|
2149
2161
|
const expected = this.registeredArguments.length;
|
|
2150
2162
|
const s = expected === 1 ? '' : 's';
|
|
2163
|
+
const received = receivedArgs.length;
|
|
2151
2164
|
const forSubcommand = this.parent ? ` for '${this.name()}'` : '';
|
|
2152
|
-
const
|
|
2165
|
+
const details = receivedArgs.join(', ');
|
|
2166
|
+
const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${received}: ${details}.`;
|
|
2153
2167
|
this.error(message, { code: 'commander.excessArguments' });
|
|
2154
2168
|
}
|
|
2155
2169
|
|
|
@@ -2405,12 +2419,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2405
2419
|
|
|
2406
2420
|
/**
|
|
2407
2421
|
* Set the name of the command from script filename, such as process.argv[1],
|
|
2408
|
-
* or
|
|
2422
|
+
* or import.meta.filename.
|
|
2409
2423
|
*
|
|
2410
2424
|
* (Used internally and public although not documented in README.)
|
|
2411
2425
|
*
|
|
2412
2426
|
* @example
|
|
2413
|
-
* program.nameFromFilename(
|
|
2427
|
+
* program.nameFromFilename(import.meta.filename);
|
|
2414
2428
|
*
|
|
2415
2429
|
* @param {string} filename
|
|
2416
2430
|
* @return {Command}
|
|
@@ -2426,7 +2440,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2426
2440
|
* Get or set the directory for searching for executable subcommands of this command.
|
|
2427
2441
|
*
|
|
2428
2442
|
* @example
|
|
2429
|
-
* program.executableDir(
|
|
2443
|
+
* program.executableDir(import.meta.dirname);
|
|
2430
2444
|
* // or
|
|
2431
2445
|
* program.executableDir('subcommands');
|
|
2432
2446
|
*
|
|
@@ -2746,10 +2760,12 @@ function incrementNodeInspectorPort(args) {
|
|
|
2746
2760
|
}
|
|
2747
2761
|
|
|
2748
2762
|
/**
|
|
2763
|
+
* Exported for using from tests, not otherwise used outside this file.
|
|
2764
|
+
*
|
|
2749
2765
|
* @returns {boolean | undefined}
|
|
2750
2766
|
* @package
|
|
2751
2767
|
*/
|
|
2752
|
-
function useColor() {
|
|
2768
|
+
export function useColor() {
|
|
2753
2769
|
// Test for common conventions.
|
|
2754
2770
|
// NB: the observed behaviour is in combination with how author adds color! For example:
|
|
2755
2771
|
// - we do not test NODE_DISABLE_COLORS, but util:styletext does
|
|
@@ -2772,6 +2788,3 @@ function useColor() {
|
|
|
2772
2788
|
return true;
|
|
2773
2789
|
return undefined;
|
|
2774
2790
|
}
|
|
2775
|
-
|
|
2776
|
-
exports.Command = Command;
|
|
2777
|
-
exports.useColor = useColor; // exporting for tests
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CommanderError class
|
|
3
3
|
*/
|
|
4
|
-
class CommanderError extends Error {
|
|
4
|
+
export class CommanderError extends Error {
|
|
5
5
|
/**
|
|
6
6
|
* Constructs the CommanderError class
|
|
7
7
|
* @param {number} exitCode suggested exit code which could be used with process.exit
|
|
@@ -22,7 +22,7 @@ class CommanderError extends Error {
|
|
|
22
22
|
/**
|
|
23
23
|
* InvalidArgumentError class
|
|
24
24
|
*/
|
|
25
|
-
class InvalidArgumentError extends CommanderError {
|
|
25
|
+
export class InvalidArgumentError extends CommanderError {
|
|
26
26
|
/**
|
|
27
27
|
* Constructs the InvalidArgumentError class
|
|
28
28
|
* @param {string} [message] explanation of why argument is invalid
|
|
@@ -34,6 +34,3 @@ class InvalidArgumentError extends CommanderError {
|
|
|
34
34
|
this.name = this.constructor.name;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
exports.CommanderError = CommanderError;
|
|
39
|
-
exports.InvalidArgumentError = InvalidArgumentError;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { humanReadableArgName } from './argument.js';
|
|
2
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS`
|
|
@@ -9,7 +10,7 @@ const { humanReadableArgName } = require('./argument.js');
|
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
// Although this is a class, methods are static in style to allow override using subclass or just functions.
|
|
12
|
-
class Help {
|
|
13
|
+
export class Help {
|
|
13
14
|
constructor() {
|
|
14
15
|
this.helpWidth = undefined;
|
|
15
16
|
this.minWidthToWrap = 40;
|
|
@@ -533,7 +534,7 @@ class Help {
|
|
|
533
534
|
* @returns {number}
|
|
534
535
|
*/
|
|
535
536
|
displayWidth(str) {
|
|
536
|
-
return
|
|
537
|
+
return stripVTControlCharacters(str).length;
|
|
537
538
|
}
|
|
538
539
|
|
|
539
540
|
/**
|
|
@@ -728,20 +729,3 @@ class Help {
|
|
|
728
729
|
return wrappedLines.join('\n');
|
|
729
730
|
}
|
|
730
731
|
}
|
|
731
|
-
|
|
732
|
-
/**
|
|
733
|
-
* Strip style ANSI escape sequences from the string. In particular, SGR (Select Graphic Rendition) codes.
|
|
734
|
-
*
|
|
735
|
-
* @param {string} str
|
|
736
|
-
* @returns {string}
|
|
737
|
-
* @package
|
|
738
|
-
*/
|
|
739
|
-
|
|
740
|
-
function stripColor(str) {
|
|
741
|
-
// eslint-disable-next-line no-control-regex
|
|
742
|
-
const sgrPattern = /\x1b\[\d*(;\d*)*m/g;
|
|
743
|
-
return str.replace(sgrPattern, '');
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
exports.Help = Help;
|
|
747
|
-
exports.stripColor = stripColor;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { InvalidArgumentError } from './error.js';
|
|
2
2
|
|
|
3
|
-
class Option {
|
|
3
|
+
export class Option {
|
|
4
4
|
/**
|
|
5
5
|
* Initialize a new `Option` with the given `flags` and `description`.
|
|
6
6
|
*
|
|
@@ -265,7 +265,7 @@ class Option {
|
|
|
265
265
|
* use cases, but is tricky for others where we want separate behaviours despite
|
|
266
266
|
* the single shared option value.
|
|
267
267
|
*/
|
|
268
|
-
class DualOptions {
|
|
268
|
+
export class DualOptions {
|
|
269
269
|
/**
|
|
270
270
|
* @param {Option[]} options
|
|
271
271
|
*/
|
|
@@ -375,6 +375,3 @@ function splitOptionFlags(flags) {
|
|
|
375
375
|
|
|
376
376
|
return { shortFlag, longFlag };
|
|
377
377
|
}
|
|
378
|
-
|
|
379
|
-
exports.Option = Option;
|
|
380
|
-
exports.DualOptions = DualOptions;
|
|
@@ -24,7 +24,7 @@ function editDistance(a, b) {
|
|
|
24
24
|
// fill matrix
|
|
25
25
|
for (let j = 1; j <= b.length; j++) {
|
|
26
26
|
for (let i = 1; i <= a.length; i++) {
|
|
27
|
-
let cost
|
|
27
|
+
let cost;
|
|
28
28
|
if (a[i - 1] === b[j - 1]) {
|
|
29
29
|
cost = 0;
|
|
30
30
|
} else {
|
|
@@ -53,7 +53,7 @@ function editDistance(a, b) {
|
|
|
53
53
|
* @returns {string}
|
|
54
54
|
*/
|
|
55
55
|
|
|
56
|
-
function suggestSimilar(word, candidates) {
|
|
56
|
+
export function suggestSimilar(word, candidates) {
|
|
57
57
|
if (!candidates || candidates.length === 0) return '';
|
|
58
58
|
// remove possible duplicates
|
|
59
59
|
candidates = Array.from(new Set(candidates));
|
|
@@ -97,5 +97,3 @@ function suggestSimilar(word, candidates) {
|
|
|
97
97
|
}
|
|
98
98
|
return '';
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
exports.suggestSimilar = suggestSimilar;
|