postcss-calc 11.1.1 → 11.2.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 (47) hide show
  1. package/README.md +40 -18
  2. package/package.json +16 -11
  3. package/src/index.js +8 -5
  4. package/src/lib/analyze.js +228 -0
  5. package/src/lib/block-index.js +118 -0
  6. package/src/lib/calculation-type.js +25 -0
  7. package/src/lib/compile.js +80 -0
  8. package/src/lib/convertUnits.js +15 -1
  9. package/src/lib/functions.js +364 -0
  10. package/src/lib/limits.js +49 -0
  11. package/src/lib/node.js +85 -39
  12. package/src/lib/opaque.js +20 -0
  13. package/src/lib/parser.js +493 -257
  14. package/src/lib/print.js +75 -0
  15. package/src/lib/regex.js +4 -0
  16. package/src/lib/scan.js +61 -0
  17. package/src/lib/serialize.js +574 -207
  18. package/src/lib/simplify/abs.js +1 -1
  19. package/src/lib/simplify/bucket.js +18 -23
  20. package/src/lib/simplify/call.js +6 -92
  21. package/src/lib/simplify/product.js +7 -4
  22. package/src/lib/simplify/round.js +4 -4
  23. package/src/lib/simplify/sum.js +22 -10
  24. package/src/lib/simplify.js +20 -5
  25. package/src/reduce.js +46 -118
  26. package/types/index.d.ts +4 -0
  27. package/types/lib/analyze.d.ts +18 -0
  28. package/types/lib/block-index.d.ts +35 -0
  29. package/types/lib/calculation-type.d.ts +18 -0
  30. package/types/lib/compile.d.ts +37 -0
  31. package/types/lib/convertUnits.d.ts +8 -1
  32. package/types/lib/functions.d.ts +40 -0
  33. package/types/lib/limits.d.ts +8 -0
  34. package/types/lib/node.d.ts +31 -9
  35. package/types/lib/opaque.d.ts +9 -0
  36. package/types/lib/parser.d.ts +47 -49
  37. package/types/lib/print.d.ts +16 -0
  38. package/types/lib/regex.d.ts +2 -0
  39. package/types/lib/scan.d.ts +35 -0
  40. package/types/lib/serialize.d.ts +19 -2
  41. package/types/lib/simplify/bucket.d.ts +2 -2
  42. package/types/lib/simplify/call.d.ts +4 -18
  43. package/types/lib/simplify/round.d.ts +3 -1
  44. package/types/lib/simplify.d.ts +5 -2
  45. package/types/reduce.d.ts +47 -6
  46. package/src/lib/tokenizer.js +0 -139
  47. package/types/lib/tokenizer.d.ts +0 -32
@@ -0,0 +1,75 @@
1
+ import { serializeResult } from './serialize.js';
2
+
3
+ /** @typedef {import('../reduce.js').ResolvedReduceCalcOptions} ResolvedReduceCalcOptions */
4
+ /** @typedef {import('../reduce.js').Replacement} Replacement */
5
+ /** @typedef {import('./serialize.js').SerializeOptions} SerializeOptions */
6
+
7
+ /**
8
+ * @param {string} value
9
+ * @param {Replacement} replacement
10
+ * @param {ResolvedReduceCalcOptions} options
11
+ * @param {SerializeOptions} serializeOptions
12
+ * @return {string}
13
+ */
14
+ function serializeReplacement(value, replacement, options, serializeOptions) {
15
+ let text;
16
+ try {
17
+ text = serializeResult(replacement.result, serializeOptions);
18
+ } catch (error) {
19
+ const err = error instanceof Error ? error : new Error('Error');
20
+ const original =
21
+ replacement.result.original ??
22
+ value.slice(replacement.start, replacement.end);
23
+ options.onParseError?.(err, original);
24
+ text = original;
25
+ }
26
+ if (
27
+ options.warnWhenCannotResolve &&
28
+ replacement.result.status === 'unresolved'
29
+ ) {
30
+ options.onWarn?.('Could not reduce expression: ' + value);
31
+ }
32
+ return text;
33
+ }
34
+
35
+ /**
36
+ * Serialize compiled candidates and splice the resulting text into the
37
+ * original source. Replacements are already non-overlapping because the
38
+ * finder treats a supported outer function as one range.
39
+ *
40
+ * @param {string} value
41
+ * @param {Replacement[]} replacements
42
+ * @param {ResolvedReduceCalcOptions} options
43
+ * @param {SerializeOptions} serializeOptions
44
+ * @return {string}
45
+ */
46
+ function applyReplacements(value, replacements, options, serializeOptions) {
47
+ if (replacements.length === 1) {
48
+ const replacement = replacements[0];
49
+ const text = serializeReplacement(
50
+ value,
51
+ replacement,
52
+ options,
53
+ serializeOptions
54
+ );
55
+ return (
56
+ value.slice(0, replacement.start) + text + value.slice(replacement.end)
57
+ );
58
+ }
59
+
60
+ let output = '';
61
+ let lastIndex = 0;
62
+ for (const replacement of replacements) {
63
+ const text = serializeReplacement(
64
+ value,
65
+ replacement,
66
+ options,
67
+ serializeOptions
68
+ );
69
+ output += value.slice(lastIndex, replacement.start) + text;
70
+ lastIndex = replacement.end;
71
+ }
72
+ return output + value.slice(lastIndex);
73
+ }
74
+
75
+ export { applyReplacements };
@@ -0,0 +1,4 @@
1
+ // CSS numeric token prefix, including an optional sign and exponent.
2
+ const CSS_NUMBER_PREFIX = /^[+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:[eE][+-]?\d+)?/;
3
+
4
+ export { CSS_NUMBER_PREFIX };
@@ -0,0 +1,61 @@
1
+ import { TokenType as CssType } from '@csstools/css-tokenizer';
2
+ import { lookupMathFunction } from './functions.js';
3
+
4
+ /**
5
+ * @typedef {object} Candidate
6
+ * @property {string} name
7
+ * @property {string} normalizedName
8
+ * @property {number} start
9
+ * @property {number} end
10
+ * @property {string} rootSpelling
11
+ * @property {boolean} calculation
12
+ * @property {number} sliceStart
13
+ * @property {number} sliceEnd
14
+ * @property {boolean} closed
15
+ */
16
+
17
+ /**
18
+ * Find complete supported math-function ranges. A supported function is
19
+ * treated as one candidate even when parsing it later fails, so nested
20
+ * calculations cannot produce partial output for an invalid outer function.
21
+ *
22
+ * @param {string} value
23
+ * @param {import('@csstools/css-tokenizer').CSSToken[]} tokens
24
+ * @param {ReturnType<typeof import('./block-index.js').indexBlocks>} index
25
+ * @return {Candidate[]}
26
+ */
27
+ function findCalculations(value, tokens, index) {
28
+ /** @type {Candidate[]} */
29
+ const candidates = [];
30
+ for (let i = 0; i < tokens.length; i++) {
31
+ const token = tokens[i];
32
+ if (token[0] !== CssType.Function) continue;
33
+
34
+ const name = token[4].value;
35
+ const lookup = lookupMathFunction(name);
36
+ if (!lookup) continue;
37
+ const isCalc = lookup.definition.calculation === true;
38
+
39
+ const close = index.closeOf(i, tokens.length);
40
+ const closed = close !== -1;
41
+ const end = closed ? tokens[close][3] + 1 : value.length;
42
+ const sliceStart = isCalc ? i + 1 : i;
43
+ const sliceEnd = closed ? close + (isCalc ? 0 : 1) : tokens.length - 1;
44
+ candidates.push({
45
+ name,
46
+ normalizedName: lookup.normalizedName,
47
+ start: token[2],
48
+ end,
49
+ rootSpelling: value.slice(token[2], token[3]),
50
+ calculation: isCalc,
51
+ sliceStart,
52
+ sliceEnd,
53
+ closed,
54
+ });
55
+ if (!closed) break;
56
+ i = close;
57
+ }
58
+ return candidates;
59
+ }
60
+
61
+ export { findCalculations };