@plumeria/turbopack-loader 13.2.3 → 14.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.
package/dist/index.js CHANGED
@@ -39,6 +39,7 @@ const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
40
  const zss_engine_1 = require("zss-engine");
41
41
  const utils_1 = require("@plumeria/utils");
42
+ const split_css_rules_1 = require("./split-css-rules");
42
43
  let lastValidCss = '';
43
44
  async function loader(source) {
44
45
  const callback = this.async();
@@ -69,6 +70,25 @@ async function loader(source) {
69
70
  const sourceBuffer = Buffer.from(source, 'utf-8');
70
71
  const leadingBytes = Buffer.byteLength(source.slice(0, leadingLen), 'utf-8');
71
72
  const baseByteOffset = ast.span.start - leadingBytes;
73
+ const throwCompilationError = (message, node) => {
74
+ let suffix = '';
75
+ if (node) {
76
+ const offset = node.span.start - baseByteOffset;
77
+ let line = 1;
78
+ let colStart = 0;
79
+ for (let i = 0; i < offset && i < sourceBuffer.length; i++) {
80
+ if (sourceBuffer[i] === 10) {
81
+ line++;
82
+ colStart = i + 1;
83
+ }
84
+ }
85
+ const col = offset - colStart + 1;
86
+ suffix = ` (${path.basename(resourcePath)}:${line}:${col})`;
87
+ }
88
+ const err = new Error(`${message}${suffix}`);
89
+ err.stack = err.message;
90
+ throw err;
91
+ };
72
92
  for (const node of ast.body) {
73
93
  if (node.type === 'ImportDeclaration') {
74
94
  const sourcePath = node.source.value;
@@ -257,7 +277,7 @@ async function loader(source) {
257
277
  if ((localCreateStyles[varName] &&
258
278
  localCreateStyles[varName].type === 'variant') ||
259
279
  mergedVariantsTable[varName]) {
260
- throw new Error(`Plumeria: Assigning the return value of "css.variants" to a variable is not supported.\nPlease pass the variant function directly to "css.use". Found assignment to: ${utils_1.t.isIdentifier(decl.id) ? decl.id.value : 'unknown'}`);
280
+ throwCompilationError(`Plumeria: Assigning the return value of css.variants() to a variable is not supported.\nPlease pass the variant function directly to styleName or css.use(). Found assignment to: ${utils_1.t.isIdentifier(decl.id) ? decl.id.value : 'unknown'}`, init);
261
281
  }
262
282
  }
263
283
  };
@@ -410,7 +430,7 @@ async function loader(source) {
410
430
  selector = selectorExpr.value;
411
431
  }
412
432
  if (selector.startsWith('@') && !(0, zss_engine_1.isAtRule)(selector)) {
413
- throw new Error(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`);
433
+ throwCompilationError(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`, selectorExpr);
414
434
  }
415
435
  const obj = (0, utils_1.objectExpressionToObject)(init.arguments[1].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
416
436
  const hash = (0, zss_engine_1.genBase36Hash)({ _themeSelector: selector, ...obj }, 1, 8);
@@ -591,7 +611,7 @@ async function loader(source) {
591
611
  selector = selectorExpr.value;
592
612
  }
593
613
  if (selector.startsWith('@') && !(0, zss_engine_1.isAtRule)(selector)) {
594
- throw new Error(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`);
614
+ throwCompilationError(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`, selectorExpr);
595
615
  }
596
616
  const obj = (0, utils_1.objectExpressionToObject)(args[1].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
597
617
  const hash = (0, zss_engine_1.genBase36Hash)({ _themeSelector: selector, ...obj }, 1, 8);
@@ -672,6 +692,24 @@ async function loader(source) {
672
692
  let groupIdCounter = 0;
673
693
  let baseStyle = {};
674
694
  let isOptimizable = true;
695
+ const getRootIdentifier = (node) => {
696
+ if (utils_1.t.isIdentifier(node)) {
697
+ return node.value;
698
+ }
699
+ if (utils_1.t.isMemberExpression(node)) {
700
+ return getRootIdentifier(node.object);
701
+ }
702
+ if (utils_1.t.isCallExpression(node)) {
703
+ const callee = node.callee;
704
+ if (callee.type !== 'Super' && callee.type !== 'Import') {
705
+ return getRootIdentifier(callee);
706
+ }
707
+ }
708
+ if (node.type === 'ParenthesisExpression') {
709
+ return getRootIdentifier(node.expression);
710
+ }
711
+ return null;
712
+ };
675
713
  const collectConditions = (node, currentTestStrings = []) => {
676
714
  const staticStyle = resolveStyleObject(node);
677
715
  if (staticStyle) {
@@ -742,6 +780,21 @@ async function loader(source) {
742
780
  variantObj = localCreateStyles[varName].obj;
743
781
  if (variantObj) {
744
782
  const callArgs = expr.arguments;
783
+ const hasSpread = callArgs.some((a) => {
784
+ if (a.spread)
785
+ return true;
786
+ if (a.expression.type === 'ObjectExpression') {
787
+ return a.expression.properties.some((p) => p.type === 'SpreadElement');
788
+ }
789
+ return false;
790
+ });
791
+ if (hasSpread) {
792
+ throwCompilationError(`Plumeria: Spread operator in ${getSource(expr)} is not supported. ` +
793
+ `Please pass specific variant options directly.`, expr);
794
+ }
795
+ if (callArgs.length !== 1) {
796
+ throwCompilationError(`Plumeria: Variant function "${varName}" expects exactly 1 argument, found ${callArgs.length}.`, expr);
797
+ }
745
798
  if (callArgs.length === 1 && !callArgs[0].spread) {
746
799
  const arg = callArgs[0].expression;
747
800
  if (arg.type === 'ObjectExpression') {
@@ -848,6 +901,17 @@ async function loader(source) {
848
901
  const handled = collectConditions(expr);
849
902
  if (handled)
850
903
  continue;
904
+ if (utils_1.t.isMemberExpression(expr) || utils_1.t.isIdentifier(expr)) {
905
+ const rootId = getRootIdentifier(expr);
906
+ const isPlumeriaStyle = rootId &&
907
+ ((localCreateStyles[rootId] !== undefined &&
908
+ localCreateStyles[rootId].type !== 'constant') ||
909
+ mergedCreateTable[rootId] !== undefined ||
910
+ mergedVariantsTable[rootId] !== undefined);
911
+ if (!isPlumeriaStyle) {
912
+ throwCompilationError(`Plumeria: Dynamic or unresolvable style object "${getSource(expr)}" is not supported.`, expr);
913
+ }
914
+ }
851
915
  isOptimizable = false;
852
916
  break;
853
917
  }
@@ -1420,7 +1484,7 @@ async function loader(source) {
1420
1484
  const propKey = callee.property.value;
1421
1485
  const styleInfo = localCreateStyles[varName];
1422
1486
  if (styleInfo?.functions?.[propKey]) {
1423
- throw new Error(`Plumeria: css.use(${getSource(expr)}) does not support dynamic function keys.\n`);
1487
+ throwCompilationError(`Plumeria: css.use(${getSource(expr)}) does not support dynamic function keys.`, expr);
1424
1488
  }
1425
1489
  }
1426
1490
  const { classParts, isOptimizable, baseStyle } = buildClassParts(args);
@@ -1477,15 +1541,24 @@ async function loader(source) {
1477
1541
  return callback(null, transformedSource);
1478
1542
  }
1479
1543
  if (extractedSheets.length > 0 && process.env.NODE_ENV === 'development') {
1480
- const newCss = optInCSS + '\n';
1481
1544
  let currentCss = '';
1482
1545
  try {
1483
1546
  currentCss = fs.readFileSync(VIRTUAL_FILE_PATH, 'utf-8');
1484
1547
  }
1485
1548
  catch (e) {
1486
1549
  }
1487
- if (!currentCss.includes(optInCSS) || isThemeCSS) {
1488
- const nextCss = currentCss + '\n' + newCss;
1550
+ const currentRules = (0, split_css_rules_1.splitCssRules)(currentCss);
1551
+ const newRules = (0, split_css_rules_1.splitCssRules)(optInCSS);
1552
+ const ruleSet = new Set(currentRules);
1553
+ let hasNewRule = false;
1554
+ for (const rule of newRules) {
1555
+ if (!ruleSet.has(rule)) {
1556
+ ruleSet.add(rule);
1557
+ hasNewRule = true;
1558
+ }
1559
+ }
1560
+ if (hasNewRule || isThemeCSS) {
1561
+ const nextCss = Array.from(ruleSet).join('\n\n') + '\n';
1489
1562
  fs.writeFileSync(VIRTUAL_FILE_PATH, nextCss, 'utf-8');
1490
1563
  lastValidCss = nextCss;
1491
1564
  }
@@ -0,0 +1 @@
1
+ export declare function splitCssRules(css: string): string[];
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splitCssRules = splitCssRules;
4
+ function splitCssRules(css) {
5
+ const rules = [];
6
+ let currentRule = '';
7
+ let depth = 0;
8
+ let inComment = false;
9
+ let inString = null;
10
+ for (let i = 0; i < css.length; i++) {
11
+ const char = css[i];
12
+ const nextChar = css[i + 1];
13
+ if (inComment) {
14
+ currentRule += char;
15
+ if (char === '*' && nextChar === '/') {
16
+ currentRule += '/';
17
+ i++;
18
+ inComment = false;
19
+ }
20
+ continue;
21
+ }
22
+ if (char === '/' && nextChar === '*') {
23
+ currentRule += '/*';
24
+ i++;
25
+ inComment = true;
26
+ continue;
27
+ }
28
+ if (inString) {
29
+ currentRule += char;
30
+ if (char === '\\') {
31
+ if (nextChar) {
32
+ currentRule += nextChar;
33
+ i++;
34
+ }
35
+ }
36
+ else if (char === inString) {
37
+ inString = null;
38
+ }
39
+ continue;
40
+ }
41
+ if (char === '"' || char === "'") {
42
+ currentRule += char;
43
+ inString = char;
44
+ continue;
45
+ }
46
+ currentRule += char;
47
+ if (char === '{') {
48
+ depth++;
49
+ }
50
+ else if (char === '}') {
51
+ depth--;
52
+ if (depth === 0) {
53
+ const trimmed = currentRule.trim();
54
+ if (trimmed)
55
+ rules.push(trimmed);
56
+ currentRule = '';
57
+ }
58
+ }
59
+ else if (char === ';' && depth === 0) {
60
+ const trimmed = currentRule.trim();
61
+ if (trimmed)
62
+ rules.push(trimmed);
63
+ currentRule = '';
64
+ }
65
+ }
66
+ const trimmed = currentRule.trim();
67
+ if (trimmed && depth === 0) {
68
+ rules.push(trimmed);
69
+ }
70
+ return rules;
71
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/turbopack-loader",
3
- "version": "13.2.3",
3
+ "version": "14.1.0",
4
4
  "description": "Plumeria Turbopack-loader",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -22,7 +22,7 @@
22
22
  "zero-virtual.css"
23
23
  ],
24
24
  "dependencies": {
25
- "@plumeria/utils": "^13.2.3"
25
+ "@plumeria/utils": "^14.1.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@swc/core": "1.15.41",