@wix/origami-transforms 0.1.27 → 0.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/cssPlugins/componentPosition.d.ts +6 -2
  2. package/dist/cssPlugins/customEnums.d.ts +5 -2
  3. package/dist/cssPlugins/customMedia.d.ts +7 -2
  4. package/dist/cssPlugins/fonts.d.ts +6 -2
  5. package/dist/cssPlugins/index.d.ts +2 -2
  6. package/dist/cssPlugins/layout/index.d.ts +7 -2
  7. package/dist/cssPlugins/mixins.d.ts +7 -2
  8. package/dist/cssPlugins/presets.d.ts +6 -2
  9. package/dist/cssPlugins/shapeDividers.d.ts +6 -2
  10. package/dist/cssPlugins/spx/index.d.ts +7 -2
  11. package/dist/cssPlugins/stackChildren.d.ts +5 -2
  12. package/dist/cssPlugins/svg.d.ts +4 -1
  13. package/dist/cssPlugins/wixVectorUrls.d.ts +6 -2
  14. package/dist/jsxPlugins/index.d.ts +2 -2
  15. package/dist/jsxPlugins/mediaValidation/index.d.ts +5 -2
  16. package/dist/jsxPlugins/origamiCompatibility/index.d.ts +6 -2
  17. package/dist/jsxPlugins/pageSlots.d.ts +7 -6
  18. package/dist/jsxPlugins/validation/checks.d.ts +7 -7
  19. package/dist/jsxPlugins/validation/index.d.ts +5 -2
  20. package/dist/jsxPlugins/validation/rules.d.ts +25 -0
  21. package/dist/transform/bi.d.ts +13 -0
  22. package/dist/transform/context.d.ts +1 -0
  23. package/dist/transform/css/runPlugins.d.ts +4 -1
  24. package/dist/transform/layoutError.d.ts +8 -4
  25. package/dist/transform/pipeline.d.ts +7 -9
  26. package/dist/transform/types.d.ts +16 -13
  27. package/package.json +6 -4
  28. package/src/cssPlugins/componentPosition.js +5 -1
  29. package/src/cssPlugins/customEnums.js +19 -12
  30. package/src/cssPlugins/customMedia.js +10 -3
  31. package/src/cssPlugins/fonts.js +5 -1
  32. package/src/cssPlugins/index.js +1 -1
  33. package/src/cssPlugins/layout/index.js +8 -1
  34. package/src/cssPlugins/layout/parser.js +15 -14
  35. package/src/cssPlugins/mixins.js +13 -6
  36. package/src/cssPlugins/presets.js +7 -2
  37. package/src/cssPlugins/shapeDividers.js +6 -2
  38. package/src/cssPlugins/spx/calls.js +2 -1
  39. package/src/cssPlugins/spx/cascade.js +3 -2
  40. package/src/cssPlugins/spx/index.js +8 -1
  41. package/src/cssPlugins/stackChildren.js +6 -2
  42. package/src/cssPlugins/svg.js +5 -2
  43. package/src/cssPlugins/wixVectorUrls.js +6 -2
  44. package/src/jsxPlugins/index.js +1 -1
  45. package/src/jsxPlugins/mediaValidation/index.js +14 -5
  46. package/src/jsxPlugins/origamiCompatibility/index.js +5 -1
  47. package/src/jsxPlugins/pageSlots.js +6 -1
  48. package/src/jsxPlugins/validation/checks.js +15 -8
  49. package/src/jsxPlugins/validation/index.js +9 -3
  50. package/src/jsxPlugins/validation/rules.js +14 -0
  51. package/src/transform/bi.js +64 -0
  52. package/src/transform/context.js +39 -0
  53. package/src/transform/css/postcssPlugin.js +18 -3
  54. package/src/transform/css/runPlugins.js +23 -3
  55. package/src/transform/jsx/runPlugins.js +17 -2
  56. package/src/transform/layoutError.js +8 -3
  57. package/src/transform/pipeline.js +25 -5
  58. package/src/transform/types.js +30 -8
@@ -1,2 +1,6 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const componentPositionPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
3
+ export const componentPositionPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
4
+ export type Check = (typeof checks)[number];
5
+ declare const checks: readonly [];
6
+ export {};
@@ -1,3 +1,6 @@
1
1
  export function removeCustomEnums(root: any): void;
2
- /** @type {import('../transform/types.js').CssTransformPlugin} */
3
- export const customEnumsPlugin: import("../transform/types.js").CssTransformPlugin;
2
+ export const checks: readonly ["duplicate_enum", "non_literal_enum_value", "unknown_enum_value", "enum_parent_selector_list"];
3
+ /** @typedef {typeof checks[number]} Check */
4
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
5
+ export const customEnumsPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
6
+ export type Check = (typeof checks)[number];
@@ -1,2 +1,7 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const customMediaPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ export const checks: readonly ["unresolved_custom_media"];
2
+ export function fail<E extends Error>(check: Check, error: E): E & {
3
+ check: "unresolved_custom_media";
4
+ };
5
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
6
+ export const customMediaPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
7
+ export type Check = (typeof checks)[number];
@@ -1,2 +1,6 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const fontsPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
3
+ export const fontsPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
4
+ export type Check = (typeof checks)[number];
5
+ declare const checks: readonly [];
6
+ export {};
@@ -1,2 +1,2 @@
1
- /** @type {readonly import('../transform/types.js').CssTransformPlugin[]} */
2
- export const cssPlugins: readonly import("../transform/types.js").CssTransformPlugin[];
1
+ /** @type {readonly import('../transform/types.js').CssTransformPlugin<string>[]} */
2
+ export const cssPlugins: readonly import("../transform/types.js").CssTransformPlugin<string>[];
@@ -1,2 +1,7 @@
1
- /** @type {import('../../transform/types.js').CssTransformPlugin} */
2
- export const layoutPlugin: import("../../transform/types.js").CssTransformPlugin;
1
+ export const checks: readonly ["unknown_target", "target_requires_component_id", "invalid_target_envelope", "target_not_site_layout", "duplicate_target", "target_requires_declarations", "duplicate_target_property", "property_wrong_target", "content_position_not_relative", "unsupported_overflow", "unsupported_content_alignment", "inconsistent_container_display", "duplicate_root_property", "property_requires_target"];
2
+ export function fail<E extends Error>(check: Check, error: E): E & {
3
+ check: "unknown_target" | "target_requires_component_id" | "invalid_target_envelope" | "target_not_site_layout" | "duplicate_target" | "target_requires_declarations" | "duplicate_target_property" | "property_wrong_target" | "content_position_not_relative" | "unsupported_overflow" | "unsupported_content_alignment" | "inconsistent_container_display" | "duplicate_root_property" | "property_requires_target";
4
+ };
5
+ /** @type {import('../../transform/types.js').CssTransformPlugin<Check>} */
6
+ export const layoutPlugin: import("../../transform/types.js").CssTransformPlugin<Check>;
7
+ export type Check = (typeof checks)[number];
@@ -1,2 +1,7 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const mixinsPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ export const checks: readonly ["missing_mixin", "cyclic_apply", "expansion_depth_exceeded", "cloned_node_budget_exceeded", "cloned_css_budget_exceeded"];
2
+ export function fail<E extends Error>(check: Check, error: E): E & {
3
+ check: "missing_mixin" | "cyclic_apply" | "expansion_depth_exceeded" | "cloned_node_budget_exceeded" | "cloned_css_budget_exceeded";
4
+ };
5
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
6
+ export const mixinsPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
7
+ export type Check = (typeof checks)[number];
@@ -1,2 +1,6 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const presetsPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
3
+ export const presetsPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
4
+ export type Check = (typeof checks)[number];
5
+ declare const checks: readonly [];
6
+ export {};
@@ -1,2 +1,6 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const shapeDividersPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
3
+ export const shapeDividersPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
4
+ export type Check = (typeof checks)[number];
5
+ declare const checks: readonly [];
6
+ export {};
@@ -1,2 +1,7 @@
1
- /** @type {import('../../transform/types.js').CssTransformPlugin} */
2
- export const spxPlugin: import("../../transform/types.js").CssTransformPlugin;
1
+ export const checks: readonly ["unsupported_spx_resolver", "invalid_spx_reference_width", "non_literal_spx_argument"];
2
+ export function fail<E extends Error>(check: Check, error: E): E & {
3
+ check: "unsupported_spx_resolver" | "invalid_spx_reference_width" | "non_literal_spx_argument";
4
+ };
5
+ /** @type {import('../../transform/types.js').CssTransformPlugin<Check>} */
6
+ export const spxPlugin: import("../../transform/types.js").CssTransformPlugin<Check>;
7
+ export type Check = (typeof checks)[number];
@@ -1,2 +1,5 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const stackChildrenPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ export const checks: readonly ["child_not_in_stack"];
2
+ /** @typedef {typeof checks[number]} Check */
3
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
4
+ export const stackChildrenPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
5
+ export type Check = (typeof checks)[number];
@@ -1,4 +1,7 @@
1
- export function loadSvgs(ids: any): Promise<undefined> | undefined;
1
+ export function loadSvgs(ids: any): Promise<{
2
+ fetched: number;
3
+ failed: number;
4
+ }> | undefined;
2
5
  export function loadedSvg(id: any): any;
3
6
  export function svgInfo(svg: any): {
4
7
  type: any;
@@ -1,2 +1,6 @@
1
- /** @type {import('../transform/types.js').CssTransformPlugin} */
2
- export const wixVectorUrlsPlugin: import("../transform/types.js").CssTransformPlugin;
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
3
+ export const wixVectorUrlsPlugin: import("../transform/types.js").CssTransformPlugin<Check>;
4
+ export type Check = (typeof checks)[number];
5
+ declare const checks: readonly [];
6
+ export {};
@@ -1,2 +1,2 @@
1
- /** @type {readonly import('../transform/types.js').JsxTransformPlugin[]} */
2
- export const jsxPlugins: readonly import("../transform/types.js").JsxTransformPlugin[];
1
+ /** @type {readonly import('../transform/types.js').JsxTransformPlugin<string>[]} */
2
+ export const jsxPlugins: readonly import("../transform/types.js").JsxTransformPlugin<string>[];
@@ -1,2 +1,5 @@
1
- /** @type {import('../../transform/types.js').JsxTransformPlugin} */
2
- export const mediaValidationPlugin: import("../../transform/types.js").JsxTransformPlugin;
1
+ export const checks: readonly ["media_not_wix"];
2
+ /** @typedef {typeof checks[number]} Check */
3
+ /** @type {import('../../transform/types.js').JsxTransformPlugin<Check>} */
4
+ export const mediaValidationPlugin: import("../../transform/types.js").JsxTransformPlugin<Check>;
5
+ export type Check = (typeof checks)[number];
@@ -1,2 +1,6 @@
1
- /** @type {import('../../transform/types.js').JsxTransformPlugin} */
2
- export const origamiCompatibilityPlugin: import("../../transform/types.js").JsxTransformPlugin;
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** @type {import('../../transform/types.js').JsxTransformPlugin<Check>} */
3
+ export const origamiCompatibilityPlugin: import("../../transform/types.js").JsxTransformPlugin<Check>;
4
+ export type Check = (typeof checks)[number];
5
+ declare const checks: readonly [];
6
+ export {};
@@ -1,6 +1,7 @@
1
- export namespace pageSlotsPlugin {
2
- let name: string;
3
- let order: number;
4
- function appliesTo(context: any): boolean;
5
- function transform(program: any): void;
6
- }
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** Transitional support for DM's literal Page children alongside authored slot props.
3
+ * @type {import('../transform/types.js').JsxTransformPlugin<Check>} */
4
+ export const pageSlotsPlugin: import("../transform/types.js").JsxTransformPlugin<Check>;
5
+ export type Check = (typeof checks)[number];
6
+ declare const checks: readonly [];
7
+ export {};
@@ -1,12 +1,12 @@
1
1
  export function assertKnownConstraints(rules: any): void;
2
2
  export function constrainsChildren(rule: any): boolean;
3
- export function checkRule(rule: any, { node, componentOf, report }: {
3
+ export function checkRule(rule: import("./rules.js").Rule, { node, componentOf, report }: {
4
4
  node: any;
5
- componentOf: any;
6
- report: any;
5
+ componentOf: (node: any) => string | undefined;
6
+ report: (check: import("./index.js").Check, message: string) => void;
7
7
  }): void;
8
- export function checkCreateElement(rule: any, { node, component, report }: {
8
+ export function checkCreateElement(rule: import("./rules.js").Rule, { node, component, report }: {
9
9
  node: any;
10
- component: any;
11
- report: any;
12
- }): any;
10
+ component: string;
11
+ report: (check: import("./index.js").Check, message: string) => void;
12
+ }): void;
@@ -1,2 +1,5 @@
1
- /** @type {import('../../transform/types.js').JsxTransformPlugin} */
2
- export const layoutValidationPlugin: import("../../transform/types.js").JsxTransformPlugin;
1
+ export const checks: readonly ["section_wrong_child", "section_too_few_children", "section_too_many_children", "section_non_literal_children", "section_create_element"];
2
+ /** @typedef {typeof checks[number]} Check */
3
+ /** @type {import('../../transform/types.js').JsxTransformPlugin<Check>} */
4
+ export const layoutValidationPlugin: import("../../transform/types.js").JsxTransformPlugin<Check>;
5
+ export type Check = (typeof checks)[number];
@@ -1,7 +1,32 @@
1
+ /**
2
+ * @typedef {object} Rule
3
+ * @property {string} id
4
+ * @property {string[]} components
5
+ * @property {string[]} allowedChildren
6
+ * @property {number} minChildren
7
+ * @property {number} maxChildren
8
+ * @property {Record<'allowedChildren' | 'minChildren' | 'maxChildren' | 'literal' | 'createElement', import('./index.js').Check>} checks
9
+ */
10
+ /** @satisfies {Rule[]} */
1
11
  export const RULES: {
2
12
  id: string;
13
+ checks: {
14
+ allowedChildren: "section_wrong_child";
15
+ minChildren: "section_too_few_children";
16
+ maxChildren: "section_too_many_children";
17
+ literal: "section_non_literal_children";
18
+ createElement: "section_create_element";
19
+ };
3
20
  components: string[];
4
21
  allowedChildren: string[];
5
22
  minChildren: number;
6
23
  maxChildren: number;
7
24
  }[];
25
+ export type Rule = {
26
+ id: string;
27
+ components: string[];
28
+ allowedChildren: string[];
29
+ minChildren: number;
30
+ maxChildren: number;
31
+ checks: Record<"allowedChildren" | "minChildren" | "maxChildren" | "literal" | "createElement", import("./index.js").Check>;
32
+ };
@@ -0,0 +1,13 @@
1
+ /** Aggregate completed dev invocations; paths are only in this local set, never in rows. */
2
+ export function countPlugin(context: any, duration: any): void;
3
+ /** @param {'malformed_custom_enum' | 'unmappable_preset' | 'svg_not_loaded' | 'media_not_wix'} key */
4
+ export function warn(key: "malformed_custom_enum" | "unmappable_preset" | "svg_not_loaded" | "media_not_wix"): void;
5
+ /**
6
+ * @template {string} Check
7
+ * @param {import('./types.js').TransformPluginBase<Check>} plugin
8
+ * @param {unknown} cause
9
+ * @returns {Check | undefined}
10
+ */
11
+ export function declaredCheck<Check extends string>(plugin: import("./types.js").TransformPluginBase<Check>, cause: unknown): Check | undefined;
12
+ /** Finish a plugin failure, projecting only its declared keys into check children. */
13
+ export function recordPluginFailure(plugin: any, cause: any, pageId: any): void;
@@ -1,3 +1,4 @@
1
+ export function pageIdFor(context: any): any;
1
2
  export function createContextFactory({ layout, command }: {
2
3
  layout: any;
3
4
  command: any;
@@ -1,4 +1,7 @@
1
- export function pluginError(plugin: any, context: any, cause: any): Error;
1
+ export function pluginError(plugin: any, context: any, cause: any): Error & {
2
+ error_name: import("@wix/origami-bi").ErrorName;
3
+ error_kind: import("@wix/origami-bi").ErrorKind;
4
+ };
2
5
  export function runCssPlugins({ plugins, root, context }: {
3
6
  plugins: any;
4
7
  root: any;
@@ -1,16 +1,20 @@
1
- export class LayoutError extends Error {
1
+ /** @template {string} Check */
2
+ export class LayoutError<Check extends string> extends Error {
2
3
  /**
3
- * @param {readonly string[]} violations
4
+ * @param {Pick<import('./types.js').TransformPluginBase<Check>, 'checks'>} plugin
5
+ * @param {readonly import('./types.js').Violation<NoInfer<Check>>[]} violations
4
6
  * @param {{ file?: string, line?: number, column?: number }} [location] The first violation's, which the
5
7
  * bundler prints as the error's position (Vite's CSS stage reads `file`, `line` and `column`).
6
8
  */
7
- constructor(violations: readonly string[], location?: {
9
+ constructor(plugin: Pick<import("./types.js").TransformPluginBase<Check>, "checks">, violations: readonly import("./types.js").Violation<NoInfer<Check>>[], location?: {
8
10
  file?: string;
9
11
  line?: number;
10
12
  column?: number;
11
13
  });
14
+ error_name: string;
12
15
  stack: string;
13
- violations: readonly string[];
16
+ plugin: Pick<import("./types.js").TransformPluginBase<Check>, "checks">;
17
+ violations: readonly import("./types.js").Violation<NoInfer<Check>>[];
14
18
  location: {
15
19
  file?: string;
16
20
  line?: number;
@@ -1,7 +1,7 @@
1
1
  export function createTransformPipeline({ layout, jsxPlugins, cssPlugins }: {
2
2
  layout: import("./types.js").SiteLayout;
3
- jsxPlugins?: readonly import("./types.js").JsxTransformPlugin[];
4
- cssPlugins?: readonly import("./types.js").CssTransformPlugin[];
3
+ jsxPlugins?: readonly import("./types.js").JsxTransformPlugin<string>[];
4
+ cssPlugins?: readonly import("./types.js").CssTransformPlugin<string>[];
5
5
  }): {
6
6
  /** Whether any JSX transform selects this module (structure.jsx/.tsx by default).
7
7
  * @param {string} id
@@ -15,15 +15,10 @@ export function createTransformPipeline({ layout, jsxPlugins, cssPlugins }: {
15
15
  * @param {{ ssr?: boolean | undefined }} [contextOptions] */
16
16
  transformJsx: (code: string, id: string, { ssr }?: {
17
17
  ssr?: boolean | undefined;
18
- }) => Promise<{
19
- code: any;
20
- map: any;
21
- }>;
18
+ }) => Promise<any>;
22
19
  postcssPlugin: {
20
+ Once: (...args: any[]) => any;
23
21
  postcssPlugin: string;
24
- Once(root: any, { result }: {
25
- result: any;
26
- }): void | Promise<void>;
27
22
  };
28
23
  babelOptionsFor: (id: any, { ssr }?: {
29
24
  ssr?: boolean | undefined;
@@ -43,5 +38,8 @@ export function createTransformPipeline({ layout, jsxPlugins, cssPlugins }: {
43
38
  };
44
39
  /** Whether a stylesheet whose last CSS run failed declared `file`, so an edit to it may fix the stylesheet. */
45
40
  failedStylesheetDependsOn: (file: any) => boolean;
41
+ close: () => any;
42
+ /** @param {string} file @param {() => void} reload */
43
+ handleHotUpdate: (file: string, reload: () => void) => any;
46
44
  setCommand: (value: any) => void;
47
45
  };
@@ -32,15 +32,15 @@ export type TransformContext = {
32
32
  */
33
33
  ssr: boolean;
34
34
  };
35
- /**
36
- * The transform-plugin contract.
37
- *
38
- * Both stages have the same shape: an engine parses the file once, and each plugin is handed that
39
- * AST plus the file's context and does what it likes with it. Babel and PostCSS are engines here,
40
- * not plugin hosts — a plugin never has to know either one's own plugin protocol. Which stage a
41
- * plugin belongs to is decided by the list it is registered in, so no descriptor restates it.
42
- */
43
- export type TransformPluginBase = {
35
+ export type Violation<Check extends string> = {
36
+ check: Check;
37
+ message: string;
38
+ };
39
+ export type CheckError<Check extends string> = Error & {
40
+ check: Check;
41
+ };
42
+ export type TransformPluginBase<Check extends string> = {
43
+ checks: readonly Check[];
44
44
  name: string;
45
45
  /**
46
46
  * Ascending. Ties break by registration order.
@@ -59,7 +59,7 @@ export type TransformPluginBase = {
59
59
  * `parserPlugins` are Babel parser plugins the file needs; they are unioned across selected plugins
60
60
  * and applied before any of them run.
61
61
  */
62
- export type JsxTransformPlugin = TransformPluginBase & {
62
+ export type JsxTransformPlugin<Check extends string> = TransformPluginBase<Check> & {
63
63
  transform: (program: any, context: TransformContext) => void;
64
64
  parserPlugins?: readonly string[];
65
65
  };
@@ -68,8 +68,11 @@ export type JsxTransformPlugin = TransformPluginBase & {
68
68
  * plugin's `validate` or `transform` runs. It returns a promise only when it has something to load, so a stylesheet
69
69
  * that needs nothing loaded stays synchronous for PostCSS.
70
70
  */
71
- export type CssTransformPlugin = TransformPluginBase & {
72
- prepare?: (root: import("postcss").Root, context: CssTransformContext) => Promise<void> | void;
71
+ export type CssTransformPlugin<Check extends string> = TransformPluginBase<Check> & {
72
+ prepare?: (root: import("postcss").Root, context: CssTransformContext) => Promise<void | {
73
+ fetched: number;
74
+ failed: number;
75
+ }> | void;
73
76
  validate?: (root: import("postcss").Root, context: CssTransformContext) => void;
74
77
  transform: (root: import("postcss").Root, context: CssTransformContext) => void;
75
78
  };
@@ -80,5 +83,5 @@ export type CssTransformPlugin = TransformPluginBase & {
80
83
  */
81
84
  export type CssTransformContext = TransformContext & {
82
85
  addDependency?: (file: string) => void;
83
- warn?: (node: import("postcss").Node, text: string) => void;
86
+ warn?: (node: import("postcss").Node, text: string, key?: "malformed_custom_enum" | "unmappable_preset" | "svg_not_loaded") => void;
84
87
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/origami-transforms",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "Babel and PostCSS checks and transforms for Wix origami page files.",
5
5
  "main": "./src/index.js",
6
6
  "files": [
@@ -12,7 +12,8 @@
12
12
  "lint": "oxlint .",
13
13
  "test": "node --test test/*.spec.js",
14
14
  "test:browser": "node test/spx.browser.mjs && node test/semanticContainer.browser.mjs",
15
- "clean": "rm -rf dist tsconfig.tsbuildinfo"
15
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
16
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.checks.json"
16
17
  },
17
18
  "dependencies": {
18
19
  "@babel/core": "^7.26.0",
@@ -21,7 +22,8 @@
21
22
  "@wix/origami-fonts": "1.0.4",
22
23
  "@wix/origami-system-components": "1.10.6",
23
24
  "postcss": "^8.5.3",
24
- "postcss-custom-media": "^12.0.1"
25
+ "postcss-custom-media": "^12.0.1",
26
+ "@wix/origami-bi": "0.10.0"
25
27
  },
26
28
  "devDependencies": {
27
29
  "@types/node": "^22.0.0",
@@ -69,5 +71,5 @@
69
71
  },
70
72
  "type": "module",
71
73
  "types": "./dist/index.d.ts",
72
- "falconPackageHash": "1c7523e78958c85b77bf2e3bdfc4a2a7b6842c08c8be0cebea118c68"
74
+ "falconPackageHash": "26f18af79b8f5dd98a7aba58e68be7f9dd09c52bdd522e0eb33180c4"
73
75
  }
@@ -6,8 +6,12 @@ import { isLayoutSource } from './layout/parser.js'
6
6
  // One class or id: DM writes `.compId`, and layout.css still accepts `#compId` (see layout/parser.js).
7
7
  const SINGLE_CLASS_OR_ID = /^[.#][\w-]+$/
8
8
 
9
- /** @type {import('../transform/types.js').CssTransformPlugin} */
9
+ const checks = /** @type {const} */ ([])
10
+ /** @typedef {typeof checks[number]} Check */
11
+
12
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
10
13
  export const componentPositionPlugin = {
14
+ checks,
11
15
  name: 'component-position',
12
16
  order: 14,
13
17
  transform(root, context) {
@@ -222,8 +222,12 @@ export const removeCustomEnums = root => {
222
222
  for (const rule of emptied) if (rule?.type === 'rule' && rule.nodes.length === 0) rule.remove()
223
223
  }
224
224
 
225
- /** @type {import('../transform/types.js').CssTransformPlugin} */
225
+ export const checks = /** @type {const} */ (['duplicate_enum', 'non_literal_enum_value', 'unknown_enum_value', 'enum_parent_selector_list'])
226
+ /** @typedef {typeof checks[number]} Check */
227
+
228
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
226
229
  export const customEnumsPlugin = {
230
+ checks,
227
231
  name: 'custom-enums',
228
232
  // After mixins copy their bodies in, before presets and layout move declarations out of the instance's rule.
229
233
  order: 11,
@@ -311,13 +315,13 @@ export const customEnumsPlugin = {
311
315
  const matching = enums.filter(item => item.key === declaration.prop && item.inline === nearest)
312
316
  if (matching.length === 0) return null
313
317
  const key = declaration.prop.slice(2)
314
- if (matching.length > 1) return `the element has custom enum ${key} more than once, so it can't say which.`
318
+ if (matching.length > 1) return /** @satisfies {[Check, string]} */ (['duplicate_enum', `the element has custom enum ${key} more than once, so it can't say which.`])
315
319
  const [found] = matching
316
320
  const value = declaration.value.trim()
317
321
  const allowed = Object.keys(found.options).join(', ')
318
- if (/\bvar\(/.test(value)) return `a custom enum's value must be literal, one of ${allowed}.`
322
+ if (/\bvar\(/.test(value)) return /** @satisfies {[Check, string]} */ (['non_literal_enum_value', `a custom enum's value must be literal, one of ${allowed}.`])
319
323
  const options = found.options[value]
320
- if (options === undefined) return `"${value}" is not an option of ${key}; use one of ${allowed}.`
324
+ if (options === undefined) return /** @satisfies {[Check, string]} */ (['unknown_enum_value', `"${value}" is not an option of ${key}; use one of ${allowed}.`])
321
325
  return options
322
326
  }
323
327
 
@@ -331,12 +335,14 @@ export const customEnumsPlugin = {
331
335
  `type, such as wixEditorElements.Button, in an element rule under the editor element's. That ` +
332
336
  `element's enums are left as authored.`
333
337
  : `custom-enums: @custom-enum ${block.params}${where(block)}: can't be read; it needs a --key, a ` +
334
- `default: that is one of its @option blocks, and an element rule around it. Its key is left as authored.`
338
+ `default: that is one of its @option blocks, and an element rule around it. Its key is left as authored.`,
339
+ 'malformed_custom_enum'
335
340
  )
336
341
  }
337
342
 
338
343
  // Every declaration is checked before any is rewritten: a failed run leaves the stylesheet as it was.
339
- const violations = new Set()
344
+ /** @type {Map<string, import('../transform/types.js').Violation<Check>>} */
345
+ const violations = new Map()
340
346
  /** @type {any} The first violation's source, whose position the bundler prints. */
341
347
  let first
342
348
  // The rules with an enum that resolves, the only ones a selector list is split in.
@@ -347,17 +353,18 @@ export const customEnumsPlugin = {
347
353
  const results = resolve(rule, own).map(selector => lookup(declaration, selector))
348
354
  if (results.some(result => result !== null)) resolving.add(rule)
349
355
  if (results.length > 1 && results.some(result => result !== null)) {
350
- return ['set a custom enum on one instance rule, not under a parent selector list.']
356
+ return [/** @satisfies {[Check, string]} */ (['enum_parent_selector_list', 'set a custom enum on one instance rule, not under a parent selector list.'])]
351
357
  }
352
- return results.filter(result => typeof result === 'string')
358
+ return results.filter(result => Array.isArray(result))
353
359
  })
354
- for (const problem of problems) {
360
+ for (const [check, problem] of problems) {
355
361
  first ??= declaration.source
356
- violations.add(`custom-enums: ${declaration.prop}: ${declaration.value}${where(declaration)}: ${problem}`)
362
+ const message = `custom-enums: ${declaration.prop}: ${declaration.value}${where(declaration)}: ${problem}`
363
+ violations.set(message, { check, message })
357
364
  }
358
365
  }
359
366
  if (violations.size) {
360
- throw new LayoutError([...violations], {
367
+ throw new LayoutError(customEnumsPlugin, [...violations.values()], {
361
368
  file: first?.input.file,
362
369
  line: first?.start?.line,
363
370
  column: first?.start?.column,
@@ -379,7 +386,7 @@ export const customEnumsPlugin = {
379
386
  const rule = ruleOf(declaration)
380
387
  if (rule === undefined) continue
381
388
  const [selector] = resolve(rule, rule.selector)
382
- const options = /** @type {Exclude<ReturnType<typeof lookup>, string>} */ (lookup(declaration, selector))
389
+ const options = /** @type {Exclude<ReturnType<typeof lookup>, string[]>} */ (lookup(declaration, selector))
383
390
  if (options !== null) declaration.replaceWith(expansion(declaration, options))
384
391
  }
385
392
  },
@@ -27,8 +27,15 @@ const usesCustomMedia = root => {
27
27
  return used
28
28
  }
29
29
 
30
- /** @type {import('../transform/types.js').CssTransformPlugin} */
30
+ export const checks = /** @type {const} */ (['unresolved_custom_media'])
31
+ /** @typedef {typeof checks[number]} Check */
32
+
33
+ /** @template {Error} E @param {Check} check @param {E} error */
34
+ export const fail = (check, error) => Object.assign(error, { check })
35
+
36
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
31
37
  export const customMediaPlugin = {
38
+ checks,
32
39
  name: 'custom-media',
33
40
  order: 0,
34
41
  transform(root, context) {
@@ -43,9 +50,9 @@ export const customMediaPlugin = {
43
50
  // disables the whole block.
44
51
  root.walkAtRules('media', atRule => {
45
52
  if (CUSTOM_MEDIA_QUERY.test(atRule.params)) {
46
- throw new Error(
53
+ throw fail('unresolved_custom_media', new Error(
47
54
  `@media ${atRule.params} has no usable @custom-media definition: it is missing or cyclic`
48
- )
55
+ ))
49
56
  }
50
57
  })
51
58
  },
@@ -49,8 +49,12 @@ const fontIdsOf = declaration => {
49
49
  return family.split(',').map(name => name.trim().replace(/^(['"])(.*)\1$/, '$2').toLowerCase())
50
50
  }
51
51
 
52
- /** @type {import('../transform/types.js').CssTransformPlugin} */
52
+ const checks = /** @type {const} */ ([])
53
+ /** @typedef {typeof checks[number]} Check */
54
+
55
+ /** @type {import('../transform/types.js').CssTransformPlugin<Check>} */
53
56
  export const fontsPlugin = {
57
+ checks,
54
58
  name: 'fonts',
55
59
  // Reads the declarations as authored, before spx rewrites the sizes the family follows.
56
60
  order: 5,
@@ -29,7 +29,7 @@ import { spxPlugin } from './spx/index.js'
29
29
  import { stackChildrenPlugin } from './stackChildren.js'
30
30
  import { wixVectorUrlsPlugin } from './wixVectorUrls.js'
31
31
 
32
- /** @type {readonly import('../transform/types.js').CssTransformPlugin[]} */
32
+ /** @type {readonly import('../transform/types.js').CssTransformPlugin<string>[]} */
33
33
  export const cssPlugins = Object.freeze([
34
34
  customMediaPlugin,
35
35
  fontsPlugin,
@@ -1,8 +1,15 @@
1
1
  import { compileContainers } from './compiler.js'
2
2
  import { parseTargets } from './parser.js'
3
3
 
4
- /** @type {import('../../transform/types.js').CssTransformPlugin} */
4
+ export const checks = /** @type {const} */ (['unknown_target', 'target_requires_component_id', 'invalid_target_envelope', 'target_not_site_layout', 'duplicate_target', 'target_requires_declarations', 'duplicate_target_property', 'property_wrong_target', 'content_position_not_relative', 'unsupported_overflow', 'unsupported_content_alignment', 'inconsistent_container_display', 'duplicate_root_property', 'property_requires_target'])
5
+ /** @typedef {typeof checks[number]} Check */
6
+
7
+ /** @template {Error} E @param {Check} check @param {E} error */
8
+ export const fail = (check, error) => Object.assign(error, { check })
9
+
10
+ /** @type {import('../../transform/types.js').CssTransformPlugin<Check>} */
5
11
  export const layoutPlugin = {
12
+ checks,
6
13
  name: 'layout',
7
14
  order: 15,
8
15
  validate: (root, context) => {