@wyw-in-js/processor-utils 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/esm/BaseProcessor.js +70 -0
  3. package/esm/BaseProcessor.js.map +1 -0
  4. package/esm/TaggedTemplateProcessor.js +43 -0
  5. package/esm/TaggedTemplateProcessor.js.map +1 -0
  6. package/esm/index.js +7 -0
  7. package/esm/index.js.map +1 -0
  8. package/esm/types.js +2 -0
  9. package/esm/types.js.map +1 -0
  10. package/esm/utils/buildSlug.js +6 -0
  11. package/esm/utils/buildSlug.js.map +1 -0
  12. package/esm/utils/getClassNameAndSlug.js +42 -0
  13. package/esm/utils/getClassNameAndSlug.js.map +1 -0
  14. package/esm/utils/getVariableName.js +12 -0
  15. package/esm/utils/getVariableName.js.map +1 -0
  16. package/esm/utils/stripLines.js +16 -0
  17. package/esm/utils/stripLines.js.map +1 -0
  18. package/esm/utils/templateProcessor.js +125 -0
  19. package/esm/utils/templateProcessor.js.map +1 -0
  20. package/esm/utils/throwIfInvalid.js +29 -0
  21. package/esm/utils/throwIfInvalid.js.map +1 -0
  22. package/esm/utils/toCSS.js +50 -0
  23. package/esm/utils/toCSS.js.map +1 -0
  24. package/esm/utils/toValidCSSIdentifier.js +4 -0
  25. package/esm/utils/toValidCSSIdentifier.js.map +1 -0
  26. package/esm/utils/types.js +2 -0
  27. package/esm/utils/types.js.map +1 -0
  28. package/esm/utils/units.js +65 -0
  29. package/esm/utils/units.js.map +1 -0
  30. package/esm/utils/validateParams.js +40 -0
  31. package/esm/utils/validateParams.js.map +1 -0
  32. package/lib/BaseProcessor.js +78 -0
  33. package/lib/BaseProcessor.js.map +1 -0
  34. package/lib/TaggedTemplateProcessor.js +51 -0
  35. package/lib/TaggedTemplateProcessor.js.map +1 -0
  36. package/lib/index.js +67 -0
  37. package/lib/index.js.map +1 -0
  38. package/lib/types.js +2 -0
  39. package/lib/types.js.map +1 -0
  40. package/lib/utils/buildSlug.js +12 -0
  41. package/lib/utils/buildSlug.js.map +1 -0
  42. package/lib/utils/getClassNameAndSlug.js +49 -0
  43. package/lib/utils/getClassNameAndSlug.js.map +1 -0
  44. package/lib/utils/getVariableName.js +18 -0
  45. package/lib/utils/getVariableName.js.map +1 -0
  46. package/lib/utils/stripLines.js +22 -0
  47. package/lib/utils/stripLines.js.map +1 -0
  48. package/lib/utils/templateProcessor.js +135 -0
  49. package/lib/utils/templateProcessor.js.map +1 -0
  50. package/lib/utils/throwIfInvalid.js +35 -0
  51. package/lib/utils/throwIfInvalid.js.map +1 -0
  52. package/lib/utils/toCSS.js +58 -0
  53. package/lib/utils/toCSS.js.map +1 -0
  54. package/lib/utils/toValidCSSIdentifier.js +10 -0
  55. package/lib/utils/toValidCSSIdentifier.js.map +1 -0
  56. package/lib/utils/types.js +2 -0
  57. package/lib/utils/types.js.map +1 -0
  58. package/lib/utils/units.js +71 -0
  59. package/lib/utils/units.js.map +1 -0
  60. package/lib/utils/validateParams.js +54 -0
  61. package/lib/utils/validateParams.js.map +1 -0
  62. package/package.json +40 -0
  63. package/types/BaseProcessor.d.ts +66 -0
  64. package/types/BaseProcessor.js +59 -0
  65. package/types/TaggedTemplateProcessor.d.ts +20 -0
  66. package/types/TaggedTemplateProcessor.js +40 -0
  67. package/types/index.d.ts +9 -0
  68. package/types/index.js +29 -0
  69. package/types/types.d.ts +32 -0
  70. package/types/types.js +2 -0
  71. package/types/utils/buildSlug.d.ts +3 -0
  72. package/types/utils/buildSlug.js +9 -0
  73. package/types/utils/getClassNameAndSlug.d.ts +5 -0
  74. package/types/utils/getClassNameAndSlug.js +43 -0
  75. package/types/utils/getVariableName.d.ts +2 -0
  76. package/types/utils/getVariableName.js +15 -0
  77. package/types/utils/stripLines.d.ts +5 -0
  78. package/types/utils/stripLines.js +18 -0
  79. package/types/utils/templateProcessor.d.ts +10 -0
  80. package/types/utils/templateProcessor.js +140 -0
  81. package/types/utils/throwIfInvalid.d.ts +5 -0
  82. package/types/utils/throwIfInvalid.js +32 -0
  83. package/types/utils/toCSS.d.ts +3 -0
  84. package/types/utils/toCSS.js +61 -0
  85. package/types/utils/toValidCSSIdentifier.d.ts +1 -0
  86. package/types/utils/toValidCSSIdentifier.js +7 -0
  87. package/types/utils/types.d.ts +9 -0
  88. package/types/utils/types.js +2 -0
  89. package/types/utils/units.d.ts +44 -0
  90. package/types/utils/units.js +94 -0
  91. package/types/utils/validateParams.d.ts +16 -0
  92. package/types/utils/validateParams.js +39 -0
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const path_1 = require("path");
4
+ const shared_1 = require("@wyw-in-js/shared");
5
+ const buildSlug_1 = require("./buildSlug");
6
+ const toValidCSSIdentifier_1 = require("./toValidCSSIdentifier");
7
+ function getClassNameAndSlug(displayName, idx, options, context) {
8
+ const relativeFilename = (context.root && context.filename
9
+ ? (0, path_1.relative)(context.root, context.filename)
10
+ : context.filename ?? 'unknown').replace(/\\/g, path_1.posix.sep);
11
+ // Custom properties need to start with a letter, so we prefix the slug
12
+ // Also use append the index of the class to the filename for uniqueness in the file
13
+ const slug = (0, toValidCSSIdentifier_1.toValidCSSIdentifier)(`${displayName.charAt(0).toLowerCase()}${(0, shared_1.slugify)(`${relativeFilename}:${idx}`)}`);
14
+ // Collect some useful replacement patterns from the filename
15
+ // Available variables for the square brackets used in `classNameSlug` options
16
+ const ext = (0, path_1.extname)(relativeFilename);
17
+ const slugVars = {
18
+ hash: slug,
19
+ title: displayName,
20
+ file: relativeFilename,
21
+ ext,
22
+ name: (0, path_1.basename)(relativeFilename, ext),
23
+ dir: (0, path_1.dirname)(relativeFilename).split(path_1.sep).pop(),
24
+ };
25
+ let className = options.displayName
26
+ ? `${(0, toValidCSSIdentifier_1.toValidCSSIdentifier)(displayName)}_${slug}`
27
+ : slug;
28
+ // The className can be defined by the user either as fn or a string
29
+ if (typeof options.classNameSlug === 'function') {
30
+ try {
31
+ className = (0, toValidCSSIdentifier_1.toValidCSSIdentifier)(options.classNameSlug(slug, displayName, slugVars));
32
+ }
33
+ catch {
34
+ throw new Error('classNameSlug option must return a string');
35
+ }
36
+ }
37
+ if (typeof options.classNameSlug === 'string') {
38
+ className = (0, toValidCSSIdentifier_1.toValidCSSIdentifier)((0, buildSlug_1.buildSlug)(options.classNameSlug, slugVars));
39
+ }
40
+ shared_1.logger.extend('template-parse:generated-meta')(`slug: ${slug}, displayName: ${displayName}, className: ${className}`);
41
+ return { className, slug };
42
+ }
43
+ exports.default = getClassNameAndSlug;
@@ -0,0 +1,2 @@
1
+ import type { IOptions } from './types';
2
+ export declare function getVariableName(varId: string, rawVariableName: IOptions['variableNameConfig'] | undefined): string;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVariableName = void 0;
4
+ function getVariableName(varId, rawVariableName) {
5
+ switch (rawVariableName) {
6
+ case 'raw':
7
+ return varId;
8
+ case 'dashes':
9
+ return `--${varId}`;
10
+ case 'var':
11
+ default:
12
+ return `var(--${varId})`;
13
+ }
14
+ }
15
+ exports.getVariableName = getVariableName;
@@ -0,0 +1,5 @@
1
+ import type { Location } from '@wyw-in-js/shared';
2
+ export default function stripLines(loc: {
3
+ end: Location;
4
+ start: Location;
5
+ }, text: string | number): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Stripping away the new lines ensures that we preserve line numbers
4
+ // This is useful in case of tools such as the stylelint pre-processor
5
+ // This should be safe because strings cannot contain newline: https://www.w3.org/TR/CSS2/syndata.html#strings
6
+ function stripLines(loc, text) {
7
+ let result = String(text)
8
+ .replace(/[\r\n]+/g, ' ')
9
+ .trim();
10
+ // If the start and end line numbers aren't same, add new lines to span the text across multiple lines
11
+ if (loc.start.line !== loc.end.line) {
12
+ result += '\n'.repeat(loc.end.line - loc.start.line);
13
+ // Add extra spaces to offset the column
14
+ result += ' '.repeat(loc.end.column);
15
+ }
16
+ return result;
17
+ }
18
+ exports.default = stripLines;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * This file handles transforming template literals to class names or styled components and generates CSS content.
3
+ * It uses CSS code from template literals and evaluated values of lazy dependencies stored in ValueCache.
4
+ */
5
+ import type { TemplateElement } from '@babel/types';
6
+ import type { ExpressionValue, Replacements } from '@wyw-in-js/shared';
7
+ import type { TaggedTemplateProcessor } from '../TaggedTemplateProcessor';
8
+ import type { ValueCache, Rules } from '../types';
9
+ import type { IOptions } from './types';
10
+ export default function templateProcessor(tagProcessor: TaggedTemplateProcessor, [...template]: (TemplateElement | ExpressionValue)[], valueCache: ValueCache, variableNameConfig: IOptions['variableNameConfig'] | undefined): [rules: Rules, sourceMapReplacements: Replacements] | null;
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /* eslint-disable no-continue */
3
+ /**
4
+ * This file handles transforming template literals to class names or styled components and generates CSS content.
5
+ * It uses CSS code from template literals and evaluated values of lazy dependencies stored in ValueCache.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || function (mod) {
24
+ if (mod && mod.__esModule) return mod;
25
+ var result = {};
26
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
27
+ __setModuleDefault(result, mod);
28
+ return result;
29
+ };
30
+ var __importDefault = (this && this.__importDefault) || function (mod) {
31
+ return (mod && mod.__esModule) ? mod : { "default": mod };
32
+ };
33
+ Object.defineProperty(exports, "__esModule", { value: true });
34
+ const shared_1 = require("@wyw-in-js/shared");
35
+ const getVariableName_1 = require("./getVariableName");
36
+ const stripLines_1 = __importDefault(require("./stripLines"));
37
+ const throwIfInvalid_1 = __importDefault(require("./throwIfInvalid"));
38
+ const toCSS_1 = __importStar(require("./toCSS"));
39
+ const units_1 = require("./units");
40
+ // Match any valid CSS units followed by a separator such as ;, newline etc.
41
+ const unitRegex = new RegExp(`^(?:${units_1.units.join('|')})\\b`);
42
+ function templateProcessor(tagProcessor, [...template], valueCache, variableNameConfig) {
43
+ const sourceMapReplacements = [];
44
+ // Check if the variable is referenced anywhere for basic DCE
45
+ // Only works when it's assigned to a variable
46
+ const { isReferenced } = tagProcessor;
47
+ // Serialize the tagged template literal to a string
48
+ let cssText = '';
49
+ let item;
50
+ let lastTemplateElementLocation;
51
+ // eslint-disable-next-line no-cond-assign
52
+ while ((item = template.shift())) {
53
+ if ('type' in item) {
54
+ // It's a template element
55
+ cssText += item.value.cooked;
56
+ lastTemplateElementLocation = item.loc;
57
+ continue;
58
+ }
59
+ // It's an expression
60
+ const { ex } = item;
61
+ const { end } = ex.loc;
62
+ const beforeLength = cssText.length;
63
+ // The location will be end of the current string to start of next string
64
+ const next = template[0]; // template[0] is the next template element
65
+ const loc = {
66
+ // +1 because an expression location always shows 1 column before
67
+ start: {
68
+ line: lastTemplateElementLocation.end.line,
69
+ column: lastTemplateElementLocation.end.column + 1,
70
+ },
71
+ end: next
72
+ ? { line: next.loc.start.line, column: next.loc.start.column }
73
+ : { line: end.line, column: end.column + 1 },
74
+ };
75
+ const value = 'value' in item ? item.value : valueCache.get(item.ex.name);
76
+ // Is it props based interpolation?
77
+ if (item.kind === shared_1.ValueType.FUNCTION || typeof value === 'function') {
78
+ // Check if previous expression was a CSS variable that we replaced
79
+ // If it has a unit after it, we need to move the unit into the interpolation
80
+ // e.g. `var(--size)px` should actually be `var(--size)`
81
+ // So we check if the current text starts with a unit, and add the unit to the previous interpolation
82
+ // Another approach would be `calc(var(--size) * 1px), but some browsers don't support all units
83
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=956573
84
+ const matches = next.value.cooked?.match(unitRegex);
85
+ try {
86
+ if (matches) {
87
+ template.shift();
88
+ const [unit] = matches;
89
+ const varId = tagProcessor.addInterpolation(item.ex, cssText, item.source, unit);
90
+ cssText += (0, getVariableName_1.getVariableName)(varId, variableNameConfig);
91
+ cssText += next.value.cooked?.substring(unit?.length ?? 0) ?? '';
92
+ }
93
+ else {
94
+ const varId = tagProcessor.addInterpolation(item.ex, cssText, item.source);
95
+ cssText += (0, getVariableName_1.getVariableName)(varId, variableNameConfig);
96
+ }
97
+ }
98
+ catch (e) {
99
+ if (e instanceof Error) {
100
+ throw item.buildCodeFrameError(e.message);
101
+ }
102
+ throw e;
103
+ }
104
+ }
105
+ else {
106
+ (0, throwIfInvalid_1.default)(tagProcessor.isValidValue.bind(tagProcessor), value, item, item.source);
107
+ if (value !== undefined && typeof value !== 'function') {
108
+ // Skip the blank string instead of throw ing an error
109
+ if (value === '') {
110
+ continue;
111
+ }
112
+ if ((0, shared_1.hasEvalMeta)(value)) {
113
+ // If it's a React component wrapped in styled, get the class name
114
+ // Useful for interpolating components
115
+ cssText += `.${value.__wyw_meta.className}`;
116
+ }
117
+ else if ((0, toCSS_1.isCSSable)(value)) {
118
+ // If it's a plain object or an array, convert it to a CSS string
119
+ cssText += (0, stripLines_1.default)(loc, (0, toCSS_1.default)(value));
120
+ }
121
+ else {
122
+ // For anything else, assume it'll be stringified
123
+ cssText += (0, stripLines_1.default)(loc, value);
124
+ }
125
+ sourceMapReplacements.push({
126
+ original: loc,
127
+ length: cssText.length - beforeLength,
128
+ });
129
+ }
130
+ }
131
+ }
132
+ const rules = tagProcessor.extractRules(valueCache, cssText, tagProcessor.location);
133
+ // tagProcessor.doRuntimeReplacement(classes);
134
+ if (!isReferenced && !cssText.includes(':global')) {
135
+ return null;
136
+ }
137
+ // eslint-disable-next-line no-param-reassign
138
+ return [rules, sourceMapReplacements];
139
+ }
140
+ exports.default = templateProcessor;
@@ -0,0 +1,5 @@
1
+ import type { BuildCodeFrameErrorFn } from '@wyw-in-js/shared';
2
+ declare function throwIfInvalid<T>(checker: (value: unknown) => value is T, value: Error | unknown, ex: {
3
+ buildCodeFrameError: BuildCodeFrameErrorFn;
4
+ }, source: string): asserts value is T;
5
+ export default throwIfInvalid;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const isLikeError = (value) => typeof value === 'object' &&
4
+ value !== null &&
5
+ 'stack' in value &&
6
+ 'message' in value;
7
+ // Throw if we can't handle the interpolated value
8
+ function throwIfInvalid(checker, value, ex, source) {
9
+ // We can't use instanceof here so let's use duck typing
10
+ if (isLikeError(value) && value.stack && value.message) {
11
+ throw ex.buildCodeFrameError(`An error occurred when evaluating the expression:
12
+
13
+ > ${value.message}.
14
+
15
+ Make sure you are not using a browser or Node specific API and all the variables are available in static context.
16
+ Linaria have to extract pieces of your code to resolve the interpolated values.
17
+ Defining styled component or class will not work inside:
18
+ - function,
19
+ - class,
20
+ - method,
21
+ - loop,
22
+ because it cannot be statically determined in which context you use them.
23
+ That's why some variables may be not defined during evaluation.
24
+ `);
25
+ }
26
+ if (checker(value)) {
27
+ return;
28
+ }
29
+ const stringified = typeof value === 'object' ? JSON.stringify(value) : String(value);
30
+ throw ex.buildCodeFrameError(`The expression evaluated to '${stringified}', which is probably a mistake. If you want it to be inserted into CSS, explicitly cast or transform the value to a string, e.g. - 'String(${source})'.`);
31
+ }
32
+ exports.default = throwIfInvalid;
@@ -0,0 +1,3 @@
1
+ import type { CSSPropertyValue, CSSable } from '../types';
2
+ export declare const isCSSable: (o: unknown) => o is CSSPropertyValue | import("../types").ObjectWithSelectors | (CSSPropertyValue | import("../types").ObjectWithSelectors)[];
3
+ export default function toCSS(o: CSSable): string;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isCSSable = void 0;
4
+ const shared_1 = require("@wyw-in-js/shared");
5
+ const units_1 = require("./units");
6
+ const isCSSPropertyValue = (o) => {
7
+ return ((0, shared_1.isBoxedPrimitive)(o) ||
8
+ typeof o === 'string' ||
9
+ (typeof o === 'number' && Number.isFinite(o)));
10
+ };
11
+ const isCSSable = (o) => {
12
+ if (isCSSPropertyValue(o)) {
13
+ return true;
14
+ }
15
+ if (Array.isArray(o)) {
16
+ return o.every(exports.isCSSable);
17
+ }
18
+ if (typeof o === 'object') {
19
+ return o !== null && Object.values(o).every(exports.isCSSable);
20
+ }
21
+ return false;
22
+ };
23
+ exports.isCSSable = isCSSable;
24
+ const hyphenate = (s) => {
25
+ if (s.startsWith('--')) {
26
+ // It's a custom property which is already well formatted.
27
+ return s;
28
+ }
29
+ return (s
30
+ // Hyphenate CSS property names from camelCase version from JS string
31
+ .replace(/([A-Z])/g, (match, p1) => `-${p1.toLowerCase()}`)
32
+ // Special case for `-ms` because in JS it starts with `ms` unlike `Webkit`
33
+ .replace(/^ms-/, '-ms-'));
34
+ };
35
+ // Some tools such as polished.js output JS objects
36
+ // To support them transparently, we convert JS objects to CSS strings
37
+ function toCSS(o) {
38
+ if (Array.isArray(o)) {
39
+ return o.map(toCSS).join('\n');
40
+ }
41
+ if (isCSSPropertyValue(o)) {
42
+ return o.valueOf().toString();
43
+ }
44
+ return Object.entries(o)
45
+ .filter(([, value]) =>
46
+ // Ignore all falsy values except numbers
47
+ typeof value === 'number' || value)
48
+ .map(([key, value]) => {
49
+ if (!isCSSPropertyValue(value)) {
50
+ return `${key} { ${toCSS(value)} }`;
51
+ }
52
+ return `${hyphenate(key)}: ${typeof value === 'number' &&
53
+ value !== 0 &&
54
+ // Strip vendor prefixes when checking if the value is unitless
55
+ !(key.replace(/^(Webkit|Moz|O|ms)([A-Z])(.+)$/, (match, p1, p2, p3) => `${p2.toLowerCase()}${p3}`) in units_1.unitless)
56
+ ? `${value}px`
57
+ : value};`;
58
+ })
59
+ .join(' ');
60
+ }
61
+ exports.default = toCSS;
@@ -0,0 +1 @@
1
+ export declare function toValidCSSIdentifier(s: string): string;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toValidCSSIdentifier = void 0;
4
+ function toValidCSSIdentifier(s) {
5
+ return s.replace(/[^-_a-z0-9\u00A0-\uFFFF]/gi, '_').replace(/^\d/, '_');
6
+ }
7
+ exports.toValidCSSIdentifier = toValidCSSIdentifier;
@@ -0,0 +1,9 @@
1
+ import type { TransformOptions } from '@babel/core';
2
+ import type { ClassNameFn, VariableNameFn } from '@wyw-in-js/shared';
3
+ export interface IOptions {
4
+ classNameSlug?: string | ClassNameFn;
5
+ displayName: boolean;
6
+ variableNameConfig?: 'var' | 'dashes' | 'raw';
7
+ variableNameSlug?: string | VariableNameFn;
8
+ }
9
+ export type IFileContext = Pick<TransformOptions, 'root' | 'filename'>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,44 @@
1
+ export declare const units: string[];
2
+ export declare const unitless: {
3
+ animationIterationCount: boolean;
4
+ borderImageOutset: boolean;
5
+ borderImageSlice: boolean;
6
+ borderImageWidth: boolean;
7
+ boxFlex: boolean;
8
+ boxFlexGroup: boolean;
9
+ boxOrdinalGroup: boolean;
10
+ columnCount: boolean;
11
+ columns: boolean;
12
+ flex: boolean;
13
+ flexGrow: boolean;
14
+ flexPositive: boolean;
15
+ flexShrink: boolean;
16
+ flexNegative: boolean;
17
+ flexOrder: boolean;
18
+ gridRow: boolean;
19
+ gridRowEnd: boolean;
20
+ gridRowSpan: boolean;
21
+ gridRowStart: boolean;
22
+ gridColumn: boolean;
23
+ gridColumnEnd: boolean;
24
+ gridColumnSpan: boolean;
25
+ gridColumnStart: boolean;
26
+ fontWeight: boolean;
27
+ lineClamp: boolean;
28
+ lineHeight: boolean;
29
+ opacity: boolean;
30
+ order: boolean;
31
+ orphans: boolean;
32
+ tabSize: boolean;
33
+ widows: boolean;
34
+ zIndex: boolean;
35
+ zoom: boolean;
36
+ fillOpacity: boolean;
37
+ floodOpacity: boolean;
38
+ stopOpacity: boolean;
39
+ strokeDasharray: boolean;
40
+ strokeDashoffset: boolean;
41
+ strokeMiterlimit: boolean;
42
+ strokeOpacity: boolean;
43
+ strokeWidth: boolean;
44
+ };
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unitless = exports.units = void 0;
4
+ // https://www.w3.org/TR/css-values-4/
5
+ exports.units = [
6
+ // font relative lengths
7
+ 'em',
8
+ 'ex',
9
+ 'cap',
10
+ 'ch',
11
+ 'ic',
12
+ 'rem',
13
+ 'lh',
14
+ 'rlh',
15
+ // viewport percentage lengths
16
+ 'vw',
17
+ 'vh',
18
+ 'vi',
19
+ 'vb',
20
+ 'vmin',
21
+ 'vmax',
22
+ // absolute lengths
23
+ 'cm',
24
+ 'mm',
25
+ 'Q',
26
+ 'in',
27
+ 'pc',
28
+ 'pt',
29
+ 'px',
30
+ // angle units
31
+ 'deg',
32
+ 'grad',
33
+ 'rad',
34
+ 'turn',
35
+ // duration units
36
+ 's',
37
+ 'ms',
38
+ // frequency units
39
+ 'Hz',
40
+ 'kHz',
41
+ // resolution units
42
+ 'dpi',
43
+ 'dpcm',
44
+ 'dppx',
45
+ 'x',
46
+ // https://www.w3.org/TR/css-grid-1/#fr-unit
47
+ 'fr',
48
+ // percentages
49
+ '%',
50
+ ];
51
+ exports.unitless = {
52
+ animationIterationCount: true,
53
+ borderImageOutset: true,
54
+ borderImageSlice: true,
55
+ borderImageWidth: true,
56
+ boxFlex: true,
57
+ boxFlexGroup: true,
58
+ boxOrdinalGroup: true,
59
+ columnCount: true,
60
+ columns: true,
61
+ flex: true,
62
+ flexGrow: true,
63
+ flexPositive: true,
64
+ flexShrink: true,
65
+ flexNegative: true,
66
+ flexOrder: true,
67
+ gridRow: true,
68
+ gridRowEnd: true,
69
+ gridRowSpan: true,
70
+ gridRowStart: true,
71
+ gridColumn: true,
72
+ gridColumnEnd: true,
73
+ gridColumnSpan: true,
74
+ gridColumnStart: true,
75
+ fontWeight: true,
76
+ lineClamp: true,
77
+ lineHeight: true,
78
+ opacity: true,
79
+ order: true,
80
+ orphans: true,
81
+ tabSize: true,
82
+ widows: true,
83
+ zIndex: true,
84
+ zoom: true,
85
+ // SVG-related properties
86
+ fillOpacity: true,
87
+ floodOpacity: true,
88
+ stopOpacity: true,
89
+ strokeDasharray: true,
90
+ strokeDashoffset: true,
91
+ strokeMiterlimit: true,
92
+ strokeOpacity: true,
93
+ strokeWidth: true,
94
+ };
@@ -0,0 +1,16 @@
1
+ import type { Param, Params } from '../types';
2
+ type ParamName = Param[0];
3
+ type ParamConstraint = ParamName | [...ParamName[]] | '*';
4
+ export type ParamConstraints = [...ParamConstraint[]] | [...ParamConstraint[], '...'];
5
+ type ParamMapping = {
6
+ [K in ParamName]: Extract<Param, readonly [K, ...unknown[]]>;
7
+ };
8
+ type GetParamByName<T> = T extends '*' ? Param : T extends keyof ParamMapping ? ParamMapping[T] : T extends Array<infer TNames> ? TNames extends ParamName ? Extract<Param, readonly [TNames, ...unknown[]]> : never : never;
9
+ export type MapParams<TNames extends ParamConstraints, TRes extends Param[] = []> = TNames extends [infer THead, ...infer TTail] ? THead extends '...' ? [...TRes, ...Params] : MapParams<Extract<TTail, ParamConstraints>, // Extract the remaining ParamConstraints.
10
+ [
11
+ ...TRes,
12
+ GetParamByName<Extract<THead, ParamName | '*' | ParamName[]>>
13
+ ]> : TRes;
14
+ export declare function isValidParams<T extends ParamConstraints>(params: Params, constraints: T): params is MapParams<T>;
15
+ export declare function validateParams<T extends ParamConstraints>(params: Params, constraints: T, messageOrError: unknown): asserts params is MapParams<T>;
16
+ export {};
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateParams = exports.isValidParams = void 0;
4
+ function isValidParams(params, constraints) {
5
+ const length = Math.max(params.length, constraints.length);
6
+ for (let i = 0; i < length; i++) {
7
+ if (params[i] === undefined || constraints[i] === undefined) {
8
+ return false;
9
+ }
10
+ const constraint = constraints[i];
11
+ if (constraint === '...') {
12
+ return true;
13
+ }
14
+ if (constraint === '*') {
15
+ if (params[i] === undefined) {
16
+ return false;
17
+ }
18
+ }
19
+ else if (Array.isArray(constraint)) {
20
+ if (constraint.every((c) => c !== params[i]?.[0])) {
21
+ return false;
22
+ }
23
+ }
24
+ else if (constraint !== params[i]?.[0]) {
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ }
30
+ exports.isValidParams = isValidParams;
31
+ function validateParams(params, constraints, messageOrError) {
32
+ if (!isValidParams(params, constraints)) {
33
+ if (typeof messageOrError === 'string') {
34
+ throw new Error(messageOrError);
35
+ }
36
+ throw messageOrError;
37
+ }
38
+ }
39
+ exports.validateParams = validateParams;