@wix/origami-transforms 0.1.28 → 0.1.30

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 (75) 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/calls.d.ts +3 -0
  11. package/dist/cssPlugins/spx/index.d.ts +7 -2
  12. package/dist/cssPlugins/spxThemeVariables/index.d.ts +6 -0
  13. package/dist/cssPlugins/spxThemeVariables/utils/breakpointUtils.d.ts +23 -0
  14. package/dist/cssPlugins/spxThemeVariables/utils/copyPlanUtils.d.ts +14 -0
  15. package/dist/cssPlugins/spxThemeVariables/utils/cssTreeUtils.d.ts +10 -0
  16. package/dist/cssPlugins/spxThemeVariables/utils/restateUtils.d.ts +9 -0
  17. package/dist/cssPlugins/spxThemeVariables/utils/sectionUtils.d.ts +6 -0
  18. package/dist/cssPlugins/spxThemeVariables/utils/stylesheetUtils.d.ts +10 -0
  19. package/dist/cssPlugins/spxThemeVariables/utils/themeUtils.d.ts +6 -0
  20. package/dist/cssPlugins/spxThemeVariables/utils/wrappingAtRuleUtils.d.ts +10 -0
  21. package/dist/cssPlugins/spxThemeVariables/utils/writeUtils.d.ts +17 -0
  22. package/dist/cssPlugins/stackChildren.d.ts +5 -2
  23. package/dist/cssPlugins/wixVectorUrls.d.ts +6 -2
  24. package/dist/jsxPlugins/index.d.ts +2 -2
  25. package/dist/jsxPlugins/mediaValidation/index.d.ts +5 -2
  26. package/dist/jsxPlugins/origamiCompatibility/index.d.ts +6 -2
  27. package/dist/jsxPlugins/pageSlots.d.ts +7 -6
  28. package/dist/jsxPlugins/validation/checks.d.ts +7 -7
  29. package/dist/jsxPlugins/validation/index.d.ts +5 -2
  30. package/dist/jsxPlugins/validation/rules.d.ts +25 -0
  31. package/dist/transform/bi.d.ts +9 -0
  32. package/dist/transform/layoutError.d.ts +7 -4
  33. package/dist/transform/pipeline.d.ts +2 -2
  34. package/dist/transform/types.d.ts +11 -11
  35. package/package.json +3 -3
  36. package/src/cssPlugins/componentPosition.js +5 -1
  37. package/src/cssPlugins/customEnums.js +17 -11
  38. package/src/cssPlugins/customMedia.js +10 -3
  39. package/src/cssPlugins/fonts.js +5 -1
  40. package/src/cssPlugins/index.js +3 -1
  41. package/src/cssPlugins/layout/index.js +8 -1
  42. package/src/cssPlugins/layout/parser.js +15 -14
  43. package/src/cssPlugins/mixins.js +13 -6
  44. package/src/cssPlugins/presets.js +5 -1
  45. package/src/cssPlugins/shapeDividers.js +5 -1
  46. package/src/cssPlugins/spx/README.md +12 -3
  47. package/src/cssPlugins/spx/calls.js +28 -1
  48. package/src/cssPlugins/spx/cascade.js +26 -6
  49. package/src/cssPlugins/spx/index.js +8 -1
  50. package/src/cssPlugins/spxThemeVariables/README.md +14 -0
  51. package/src/cssPlugins/spxThemeVariables/index.js +36 -0
  52. package/src/cssPlugins/spxThemeVariables/utils/breakpointUtils.js +126 -0
  53. package/src/cssPlugins/spxThemeVariables/utils/copyPlanUtils.js +162 -0
  54. package/src/cssPlugins/spxThemeVariables/utils/cssTreeUtils.js +58 -0
  55. package/src/cssPlugins/spxThemeVariables/utils/restateUtils.js +134 -0
  56. package/src/cssPlugins/spxThemeVariables/utils/sectionUtils.js +32 -0
  57. package/src/cssPlugins/spxThemeVariables/utils/stylesheetUtils.js +98 -0
  58. package/src/cssPlugins/spxThemeVariables/utils/themeUtils.js +90 -0
  59. package/src/cssPlugins/spxThemeVariables/utils/wrappingAtRuleUtils.js +68 -0
  60. package/src/cssPlugins/spxThemeVariables/utils/writeUtils.js +98 -0
  61. package/src/cssPlugins/stackChildren.js +6 -2
  62. package/src/cssPlugins/wixVectorUrls.js +5 -1
  63. package/src/jsxPlugins/index.js +1 -1
  64. package/src/jsxPlugins/mediaValidation/index.js +10 -5
  65. package/src/jsxPlugins/origamiCompatibility/index.js +5 -1
  66. package/src/jsxPlugins/pageSlots.js +6 -1
  67. package/src/jsxPlugins/validation/checks.js +15 -8
  68. package/src/jsxPlugins/validation/index.js +9 -3
  69. package/src/jsxPlugins/validation/rules.js +14 -0
  70. package/src/transform/bi.js +30 -0
  71. package/src/transform/css/runPlugins.js +5 -7
  72. package/src/transform/jsx/runPlugins.js +3 -6
  73. package/src/transform/layoutError.js +7 -3
  74. package/src/transform/pipeline.js +2 -2
  75. package/src/transform/types.js +28 -6
@@ -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 +1,4 @@
1
+ export const THEME_SPX: "--theme-spx(";
1
2
  export function lowerCalls(declaration: import("postcss").Declaration, resolve: (value: number) => string, invalidCall: () => Error): void;
3
+ export function lowerThemeCalls(declaration: import("postcss").Declaration, resolve: (value: number, themeRefWidth: number) => string, invalidCall: () => Error): void;
4
+ export function toThemeCalls(value: string, themeRefWidth: number): string;
@@ -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];
@@ -0,0 +1,6 @@
1
+ /** @typedef {typeof checks[number]} Check */
2
+ /** @type {import('../../transform/types.js').CssTransformPlugin<Check>} */
3
+ export const spxThemeVariablesPlugin: import("../../transform/types.js").CssTransformPlugin<Check>;
4
+ export type Check = (typeof checks)[number];
5
+ declare const checks: readonly [];
6
+ export {};
@@ -0,0 +1,23 @@
1
+ export function maxWidthOf(query: string): number | undefined;
2
+ export function breakpointOf(ancestors: readonly import("postcss").Node[]): string;
3
+ export function widestFirst(breakpoints: readonly string[]): string[];
4
+ export function themeBreakpointsOf({ breakpoints }: ThemeVariables): string[];
5
+ export function inheritedBreakpointsOf({ breakpoints }: ThemeVariables, breakpoint: string): string[];
6
+ export function cascadeAt({ rules }: ThemeVariables, cascadeBreakpoints: readonly string[]): Map<string, CascadedVariable>;
7
+ export function resolveRefWidths(breakpoints: readonly string[], ownRefWidths: Map<string, number>): Map<string, number>;
8
+ export function refWidthAt({ refWidthByBreakpoint }: ThemeVariables, breakpoint: string): number;
9
+ export type VariableMap = Map<string, import("postcss").Declaration>;
10
+ export type ThemeRule = {
11
+ scanned: import("./stylesheetUtils.js").ScannedRule;
12
+ variables: VariableMap;
13
+ };
14
+ export type ThemeVariables = {
15
+ rules: ThemeRule[];
16
+ breakpoints: string[];
17
+ refWidthByBreakpoint: Map<string, number>;
18
+ };
19
+ export type CascadedVariable = {
20
+ declaration: import("postcss").Declaration;
21
+ breakpoint: string;
22
+ index: number;
23
+ };
@@ -0,0 +1,14 @@
1
+ export function planBreakpoints(theme: ThemeVariables): BreakpointPlan;
2
+ export function planThemeCopies(theme: ThemeVariables, breakpointPlan: BreakpointPlan): ThemeCopies;
3
+ export type CascadedVariable = import("./breakpointUtils.js").CascadedVariable;
4
+ export type ThemeVariables = import("./breakpointUtils.js").ThemeVariables;
5
+ export type VariableMap = import("./breakpointUtils.js").VariableMap;
6
+ export type Declaration = import("postcss").Declaration;
7
+ export type ThemeCopies = Map<string, VariableMap>;
8
+ export type VariableReferences = Map<string, string[]>;
9
+ export type BreakpointPlan = Map<string, string[]>;
10
+ export type CopyCriteria = {
11
+ ownVariables: VariableMap;
12
+ scaleDependent: Set<string>;
13
+ widerCopied: Set<string>;
14
+ };
@@ -0,0 +1,10 @@
1
+ export const DESKTOP: "";
2
+ export function ancestorsOf(node: import("postcss").Node): import("postcss").Node[];
3
+ export function isAtRule(node: import("postcss").Node): node is import("postcss").AtRule;
4
+ export function collapseWhitespace(text: string): string;
5
+ export function isInContainerDefaults(ancestors: readonly import("postcss").Node[]): boolean;
6
+ export function isTopLevel(ancestors: readonly import("postcss").Node[]): ancestors is readonly import("postcss").AtRule[];
7
+ export function hasRootSelector(rule: import("postcss").Rule): boolean;
8
+ export function isCustomProperty(prop: string): boolean;
9
+ export function isMedia(node: import("postcss").Node): node is import("postcss").AtRule;
10
+ export function declarationsOf(rule: import("postcss").Rule): import("postcss").Declaration[];
@@ -0,0 +1,9 @@
1
+ export function restateThemeVariables(theme: ThemeVariables, breakpointPlan: BreakpointPlan): void;
2
+ export type CascadedVariable = import("./breakpointUtils.js").CascadedVariable;
3
+ export type ThemeVariables = import("./breakpointUtils.js").ThemeVariables;
4
+ export type BreakpointPlan = import("./copyPlanUtils.js").BreakpointPlan;
5
+ export type RestateTarget = {
6
+ breakpoint: string;
7
+ index: number;
8
+ refWidth: number;
9
+ };
@@ -0,0 +1,6 @@
1
+ /** @typedef {import('./stylesheetUtils.js').ScannedRule} ScannedRule */
2
+ /** @typedef {import('./wrappingAtRuleUtils.js').Section} Section */
3
+ export const CONTENT_MAX_WIDTH: "--content-max-width";
4
+ export function readSectionRules(layoutRules: readonly ScannedRule[]): Section[];
5
+ export type ScannedRule = import("./stylesheetUtils.js").ScannedRule;
6
+ export type Section = import("./wrappingAtRuleUtils.js").Section;
@@ -0,0 +1,10 @@
1
+ export function scanStylesheet(root: import("postcss").Root, siteFolder: string): StylesheetScan;
2
+ export type ScannedRule = {
3
+ rule: import("postcss").Rule;
4
+ breakpoint: string;
5
+ declarations: import("postcss").Declaration[];
6
+ };
7
+ export type StylesheetScan = {
8
+ themeRules: ScannedRule[];
9
+ layoutRules: ScannedRule[];
10
+ };
@@ -0,0 +1,6 @@
1
+ export function readThemeVariables(themeRules: readonly ScannedRule[]): ThemeVariables;
2
+ export function tagThemeVariables(themeRules: readonly ScannedRule[], theme: ThemeVariables): void;
3
+ export type ThemeRule = import("./breakpointUtils.js").ThemeRule;
4
+ export type ThemeVariables = import("./breakpointUtils.js").ThemeVariables;
5
+ export type VariableMap = import("./breakpointUtils.js").VariableMap;
6
+ export type ScannedRule = import("./stylesheetUtils.js").ScannedRule;
@@ -0,0 +1,10 @@
1
+ export function wrappingAtRulesOf(rule: import("postcss").Rule): import("postcss").AtRule[];
2
+ export function groupSectionsByWrappingAtRules(sections: readonly Section[]): SectionGroup[];
3
+ export type Section = {
4
+ selector: string;
5
+ wrappingAtRules: import("postcss").AtRule[];
6
+ };
7
+ export type SectionGroup = {
8
+ wrappingAtRules: import("postcss").AtRule[];
9
+ selectors: string[];
10
+ };
@@ -0,0 +1,17 @@
1
+ /** @typedef {import('./copyPlanUtils.js').ThemeCopies} ThemeCopies */
2
+ /** @typedef {import('./wrappingAtRuleUtils.js').Section} Section */
3
+ /** @typedef {import('./wrappingAtRuleUtils.js').SectionGroup} SectionGroup */
4
+ /**
5
+ * @typedef {object} BreakpointCopies
6
+ * @property {string} breakpoint
7
+ * @property {import('postcss').Declaration[]} declarations
8
+ */
9
+ export const THEME_COPIES_LAYER: "origami-theme-copies";
10
+ export function writeCopies(root: import("postcss").Root, themeCopies: ThemeCopies, sections: readonly Section[]): void;
11
+ export type ThemeCopies = import("./copyPlanUtils.js").ThemeCopies;
12
+ export type Section = import("./wrappingAtRuleUtils.js").Section;
13
+ export type SectionGroup = import("./wrappingAtRuleUtils.js").SectionGroup;
14
+ export type BreakpointCopies = {
15
+ breakpoint: string;
16
+ declarations: import("postcss").Declaration[];
17
+ };
@@ -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,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
+ };
@@ -2,3 +2,12 @@
2
2
  export function countPlugin(context: any, duration: any): void;
3
3
  /** @param {'malformed_custom_enum' | 'unmappable_preset' | 'svg_not_loaded' | 'media_not_wix'} key */
4
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,17 +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
  });
12
14
  error_name: string;
13
15
  stack: string;
14
- violations: readonly string[];
16
+ plugin: Pick<import("./types.js").TransformPluginBase<Check>, "checks">;
17
+ violations: readonly import("./types.js").Violation<NoInfer<Check>>[];
15
18
  location: {
16
19
  file?: string;
17
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
@@ -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,7 +68,7 @@ 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 & {
71
+ export type CssTransformPlugin<Check extends string> = TransformPluginBase<Check> & {
72
72
  prepare?: (root: import("postcss").Root, context: CssTransformContext) => Promise<void | {
73
73
  fetched: number;
74
74
  failed: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/origami-transforms",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "description": "Babel and PostCSS checks and transforms for Wix origami page files.",
5
5
  "main": "./src/index.js",
6
6
  "files": [
@@ -13,7 +13,7 @@
13
13
  "test": "node --test test/*.spec.js",
14
14
  "test:browser": "node test/spx.browser.mjs && node test/semanticContainer.browser.mjs",
15
15
  "clean": "rm -rf dist tsconfig.tsbuildinfo",
16
- "typecheck": "tsc --noEmit"
16
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.checks.json"
17
17
  },
18
18
  "dependencies": {
19
19
  "@babel/core": "^7.26.0",
@@ -71,5 +71,5 @@
71
71
  },
72
72
  "type": "module",
73
73
  "types": "./dist/index.d.ts",
74
- "falconPackageHash": "1fbeabb662063771eaf3dbbb2b84d3ea8ba71598556ee82a91d545fa"
74
+ "falconPackageHash": "3dbca0d8f0a2ca89672ec04b7c608fae13a2f9a9cbdbf55285316758"
75
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
 
@@ -337,7 +341,8 @@ export const customEnumsPlugin = {
337
341
  }
338
342
 
339
343
  // Every declaration is checked before any is rewritten: a failed run leaves the stylesheet as it was.
340
- const violations = new Set()
344
+ /** @type {Map<string, import('../transform/types.js').Violation<Check>>} */
345
+ const violations = new Map()
341
346
  /** @type {any} The first violation's source, whose position the bundler prints. */
342
347
  let first
343
348
  // The rules with an enum that resolves, the only ones a selector list is split in.
@@ -348,17 +353,18 @@ export const customEnumsPlugin = {
348
353
  const results = resolve(rule, own).map(selector => lookup(declaration, selector))
349
354
  if (results.some(result => result !== null)) resolving.add(rule)
350
355
  if (results.length > 1 && results.some(result => result !== null)) {
351
- 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.'])]
352
357
  }
353
- return results.filter(result => typeof result === 'string')
358
+ return results.filter(result => Array.isArray(result))
354
359
  })
355
- for (const problem of problems) {
360
+ for (const [check, problem] of problems) {
356
361
  first ??= declaration.source
357
- 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 })
358
364
  }
359
365
  }
360
366
  if (violations.size) {
361
- throw new LayoutError([...violations], {
367
+ throw new LayoutError(customEnumsPlugin, [...violations.values()], {
362
368
  file: first?.input.file,
363
369
  line: first?.start?.line,
364
370
  column: first?.start?.column,
@@ -380,7 +386,7 @@ export const customEnumsPlugin = {
380
386
  const rule = ruleOf(declaration)
381
387
  if (rule === undefined) continue
382
388
  const [selector] = resolve(rule, rule.selector)
383
- const options = /** @type {Exclude<ReturnType<typeof lookup>, string>} */ (lookup(declaration, selector))
389
+ const options = /** @type {Exclude<ReturnType<typeof lookup>, string[]>} */ (lookup(declaration, selector))
384
390
  if (options !== null) declaration.replaceWith(expansion(declaration, options))
385
391
  }
386
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
  },