@plumeria/turbopack-loader 18.0.1 → 18.1.1

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 (2) hide show
  1. package/dist/index.js +195 -34
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -796,6 +796,8 @@ async function loader(source) {
796
796
  });
797
797
  const conditionals = [];
798
798
  let groupIdCounter = 0;
799
+ let sourceOrder = 0;
800
+ const baseChunks = [];
799
801
  let baseStyle = {};
800
802
  let isOptimizable = true;
801
803
  const resolveCreateObject = (varName) => {
@@ -809,11 +811,101 @@ async function loader(source) {
809
811
  return scannedTables.createObjectTable[hash];
810
812
  return null;
811
813
  };
814
+ const resolveBracketGroup = (node) => {
815
+ if (!utils_1.t.isMemberExpression(node) ||
816
+ !utils_1.t.isIdentifier(node.object) ||
817
+ node.property.type !== 'Computed' ||
818
+ utils_1.t.isStringLiteral(node.property.expression)) {
819
+ return null;
820
+ }
821
+ const varName = node.object.value;
822
+ const obj = resolveCreateObject(varName);
823
+ return obj ? { varName, keyExpr: node.property.expression, obj } : null;
824
+ };
825
+ const buildDecision = (node, prefix, off, counter) => {
826
+ if (node.type === 'ParenthesisExpression') {
827
+ return buildDecision(node.expression, prefix, off, counter);
828
+ }
829
+ if (node.type === 'ConditionalExpression') {
830
+ const a = buildDecision(node.consequent, prefix, off, counter);
831
+ if (!a)
832
+ return null;
833
+ const b = buildDecision(node.alternate, prefix, off, counter);
834
+ if (!b)
835
+ return null;
836
+ return {
837
+ keyExpr: `((${getSource(node.test)}) ? ${a.keyExpr} : ${b.keyExpr})`,
838
+ options: [...a.options, ...b.options],
839
+ leaves: a.leaves + b.leaves,
840
+ hasGroup: a.hasGroup || b.hasGroup,
841
+ };
842
+ }
843
+ if (node.type === 'BinaryExpression' && node.operator === '&&') {
844
+ const right = buildDecision(node.right, prefix, off, counter);
845
+ if (!right)
846
+ return null;
847
+ return {
848
+ keyExpr: `((${getSource(node.left)}) ? ${right.keyExpr} : ${JSON.stringify(off)})`,
849
+ options: right.options,
850
+ leaves: right.leaves,
851
+ hasGroup: right.hasGroup,
852
+ };
853
+ }
854
+ const group = resolveBracketGroup(node);
855
+ if (group) {
856
+ return {
857
+ keyExpr: getSource(group.keyExpr),
858
+ options: Object.entries(group.obj).map(([value, style]) => ({
859
+ value,
860
+ style: style,
861
+ })),
862
+ leaves: 1,
863
+ hasGroup: true,
864
+ };
865
+ }
866
+ const style = resolveStyleObject(node);
867
+ if (!style)
868
+ return null;
869
+ const value = `${prefix}${counter.n++}`;
870
+ return {
871
+ keyExpr: JSON.stringify(value),
872
+ options: [{ value, style }],
873
+ leaves: 1,
874
+ hasGroup: false,
875
+ };
876
+ };
877
+ const collectGroupKeys = (node, acc) => {
878
+ if (node.type === 'ParenthesisExpression') {
879
+ collectGroupKeys(node.expression, acc);
880
+ }
881
+ else if (node.type === 'ConditionalExpression') {
882
+ collectGroupKeys(node.consequent, acc);
883
+ collectGroupKeys(node.alternate, acc);
884
+ }
885
+ else if (node.type === 'BinaryExpression' && node.operator === '&&') {
886
+ collectGroupKeys(node.right, acc);
887
+ }
888
+ else {
889
+ const group = resolveBracketGroup(node);
890
+ if (group)
891
+ Object.keys(group.obj).forEach((k) => acc.add(k));
892
+ }
893
+ };
894
+ const resolveDecision = (node) => {
895
+ const groupKeys = new Set();
896
+ collectGroupKeys(node, groupKeys);
897
+ let prefix = '#';
898
+ while ([...groupKeys].some((k) => k.startsWith(prefix)))
899
+ prefix += '#';
900
+ const off = groupKeys.has('') ? `${prefix}off` : '';
901
+ return buildDecision(node, prefix, off, { n: 0 });
902
+ };
812
903
  const collectConditions = (node, currentTestStrings = []) => {
813
904
  const staticStyle = resolveStyleObject(node);
814
905
  if (staticStyle) {
815
906
  if (currentTestStrings.length === 0) {
816
907
  baseStyle = (0, utils_1.deepMerge)(baseStyle, staticStyle);
908
+ baseChunks.push({ order: sourceOrder++, style: staticStyle });
817
909
  }
818
910
  else {
819
911
  conditionals.push({
@@ -822,6 +914,7 @@ async function loader(source) {
822
914
  truthy: staticStyle,
823
915
  falsy: {},
824
916
  varName: undefined,
917
+ order: sourceOrder++,
825
918
  });
826
919
  }
827
920
  return true;
@@ -838,6 +931,7 @@ async function loader(source) {
838
931
  truthy: trueStyle,
839
932
  falsy: falseStyle,
840
933
  varName: undefined,
934
+ order: sourceOrder++,
841
935
  });
842
936
  return true;
843
937
  }
@@ -862,14 +956,6 @@ async function loader(source) {
862
956
  else if (node.type === 'ParenthesisExpression') {
863
957
  return collectConditions(node.expression, currentTestStrings);
864
958
  }
865
- if (currentTestStrings.length > 0 &&
866
- utils_1.t.isMemberExpression(node) &&
867
- utils_1.t.isIdentifier(node.object) &&
868
- node.property.type === 'Computed' &&
869
- resolveCreateObject(node.object.value)) {
870
- const varName = node.object.value;
871
- throwCompilationError(`Plumeria: "${getSource(node)}" cannot be used inside a condition, because its bracket key is not a literal.\nMove the condition into the brackets instead, e.g. ${varName}[cond ? 'a' : 'b'].`, node);
872
- }
873
959
  assertResolvable(node);
874
960
  return false;
875
961
  };
@@ -896,6 +982,7 @@ async function loader(source) {
896
982
  }
897
983
  if (propPossibilities && propPossibilities.length > 0) {
898
984
  const currentGroupId = ++groupIdCounter;
985
+ const currentOrder = sourceOrder++;
899
986
  const uniqueEntries = [];
900
987
  propPossibilities.forEach((entry) => {
901
988
  if (!uniqueEntries.some((x) => x.key === entry.key)) {
@@ -910,6 +997,7 @@ async function loader(source) {
910
997
  truthy: entry.styleObj,
911
998
  falsy: {},
912
999
  groupId: currentGroupId,
1000
+ order: currentOrder,
913
1001
  groupName: undefined,
914
1002
  valueName: entry.key,
915
1003
  varName,
@@ -966,11 +1054,18 @@ async function loader(source) {
966
1054
  if (!groupVariants)
967
1055
  continue;
968
1056
  const currentGroupId = ++groupIdCounter;
1057
+ const currentOrder = sourceOrder++;
969
1058
  const valSource = getSource(valExpr);
970
1059
  if (valExpr.type === 'StringLiteral') {
971
1060
  const groupVariantsAsObj = groupVariants;
972
- if (groupVariantsAsObj[valExpr.value])
973
- baseStyle = (0, utils_1.deepMerge)(baseStyle, groupVariantsAsObj[valExpr.value]);
1061
+ const picked = groupVariantsAsObj[valExpr.value];
1062
+ if (picked) {
1063
+ baseStyle = (0, utils_1.deepMerge)(baseStyle, picked);
1064
+ baseChunks.push({
1065
+ order: sourceOrder++,
1066
+ style: picked,
1067
+ });
1068
+ }
974
1069
  continue;
975
1070
  }
976
1071
  Object.entries(groupVariants).forEach(([optionName, style]) => {
@@ -981,6 +1076,7 @@ async function loader(source) {
981
1076
  truthy: style,
982
1077
  falsy: {},
983
1078
  groupId: currentGroupId,
1079
+ order: currentOrder,
984
1080
  groupName,
985
1081
  valueName: optionName,
986
1082
  varName,
@@ -992,11 +1088,15 @@ async function loader(source) {
992
1088
  }
993
1089
  const argSource = getSource(arg);
994
1090
  if (utils_1.t.isStringLiteral(arg)) {
995
- if (variantObj[arg.value])
996
- baseStyle = (0, utils_1.deepMerge)(baseStyle, variantObj[arg.value]);
1091
+ const picked = variantObj[arg.value];
1092
+ if (picked) {
1093
+ baseStyle = (0, utils_1.deepMerge)(baseStyle, picked);
1094
+ baseChunks.push({ order: sourceOrder++, style: picked });
1095
+ }
997
1096
  continue;
998
1097
  }
999
1098
  const currentGroupId = ++groupIdCounter;
1099
+ const currentOrder = sourceOrder++;
1000
1100
  Object.entries(variantObj).forEach(([key, style]) => {
1001
1101
  conditionals.push({
1002
1102
  test: arg,
@@ -1005,6 +1105,7 @@ async function loader(source) {
1005
1105
  truthy: style,
1006
1106
  falsy: {},
1007
1107
  groupId: currentGroupId,
1108
+ order: currentOrder,
1008
1109
  groupName: undefined,
1009
1110
  valueName: key,
1010
1111
  varName,
@@ -1032,6 +1133,7 @@ async function loader(source) {
1032
1133
  if (!groupVariants)
1033
1134
  return;
1034
1135
  const currentGroupId = ++groupIdCounter;
1136
+ const currentOrder = sourceOrder++;
1035
1137
  Object.entries(groupVariants).forEach(([optionName, style]) => {
1036
1138
  conditionals.push({
1037
1139
  test: expr,
@@ -1040,6 +1142,7 @@ async function loader(source) {
1040
1142
  truthy: style,
1041
1143
  falsy: {},
1042
1144
  groupId: currentGroupId,
1145
+ order: currentOrder,
1043
1146
  groupName,
1044
1147
  valueName: optionName,
1045
1148
  varName,
@@ -1058,6 +1161,7 @@ async function loader(source) {
1058
1161
  const dynExpr = expr.property.expression;
1059
1162
  const dynSource = getSource(dynExpr);
1060
1163
  const currentGroupId = ++groupIdCounter;
1164
+ const currentOrder = sourceOrder++;
1061
1165
  Object.entries(styleObj).forEach(([optionName, style]) => {
1062
1166
  conditionals.push({
1063
1167
  test: dynExpr,
@@ -1066,6 +1170,7 @@ async function loader(source) {
1066
1170
  truthy: style,
1067
1171
  falsy: {},
1068
1172
  groupId: currentGroupId,
1173
+ order: currentOrder,
1069
1174
  groupName: undefined,
1070
1175
  valueName: optionName,
1071
1176
  varName,
@@ -1074,6 +1179,24 @@ async function loader(source) {
1074
1179
  continue;
1075
1180
  }
1076
1181
  }
1182
+ const decision = resolveDecision(expr);
1183
+ if (decision && (decision.hasGroup || decision.leaves > 2)) {
1184
+ const groupId = ++groupIdCounter;
1185
+ const currentOrder = sourceOrder++;
1186
+ decision.options.forEach(({ value, style }) => conditionals.push({
1187
+ test: expr,
1188
+ testLHS: decision.keyExpr,
1189
+ testString: `${decision.keyExpr} === '${value}'`,
1190
+ truthy: style,
1191
+ falsy: {},
1192
+ groupId,
1193
+ order: currentOrder,
1194
+ groupName: undefined,
1195
+ valueName: value,
1196
+ varName: undefined,
1197
+ }));
1198
+ continue;
1199
+ }
1077
1200
  const handled = collectConditions(expr);
1078
1201
  if (handled)
1079
1202
  continue;
@@ -1203,7 +1326,7 @@ async function loader(source) {
1203
1326
  getSource(options[0].test);
1204
1327
  const lookupMap = {};
1205
1328
  options.forEach((opt) => {
1206
- if (opt.valueName && opt.truthy) {
1329
+ if (opt.valueName !== undefined && opt.truthy) {
1207
1330
  const className = processStyleRecords(opt.truthy)
1208
1331
  .map((r) => r.hash)
1209
1332
  .join(' ');
@@ -1220,17 +1343,38 @@ async function loader(source) {
1220
1343
  });
1221
1344
  if (Object.keys(baseConflict).length > 0 ||
1222
1345
  conflictConditionals.length > 0) {
1223
- const dimensions = [];
1346
+ const ordered = [];
1347
+ baseChunks.forEach(({ order, style }) => {
1348
+ const conflicting = {};
1349
+ Object.entries(style).forEach(([key, value]) => {
1350
+ if (conflictingKeys.has(key))
1351
+ conflicting[key] = value;
1352
+ });
1353
+ if (Object.keys(conflicting).length === 0)
1354
+ return;
1355
+ ordered.push({
1356
+ order,
1357
+ dimension: {
1358
+ type: 'const',
1359
+ options: [
1360
+ { value: undefined, style: conflicting, label: 'base' },
1361
+ ],
1362
+ },
1363
+ });
1364
+ });
1224
1365
  conflictConditionals
1225
1366
  .filter((c) => c.groupId === undefined)
1226
1367
  .forEach((c) => {
1227
- dimensions.push({
1228
- type: 'std',
1229
- testExpr: c.testString ?? getSource(c.test),
1230
- options: [
1231
- { value: 0, style: c.falsy, label: 'false' },
1232
- { value: 1, style: c.truthy, label: 'true' },
1233
- ],
1368
+ ordered.push({
1369
+ order: c.order ?? 0,
1370
+ dimension: {
1371
+ type: 'std',
1372
+ testExpr: c.testString ?? getSource(c.test),
1373
+ options: [
1374
+ { value: 0, style: c.falsy, label: 'false' },
1375
+ { value: 1, style: c.truthy, label: 'true' },
1376
+ ],
1377
+ },
1234
1378
  });
1235
1379
  });
1236
1380
  const conflictVarGroups = {};
@@ -1241,17 +1385,33 @@ async function loader(source) {
1241
1385
  conflictVarGroups[c.groupId].push(c);
1242
1386
  }
1243
1387
  });
1388
+ Object.keys(conflictVarGroups).forEach((id) => {
1389
+ const groupId = Number(id);
1390
+ const opts = conflictVarGroups[groupId];
1391
+ if (opts.some((c) => c.valueName === ''))
1392
+ return;
1393
+ const off = conditionals.find((c) => c.groupId === groupId && c.valueName === '');
1394
+ if (off)
1395
+ opts.push({ ...off, truthy: {}, falsy: {} });
1396
+ });
1244
1397
  Object.entries(conflictVarGroups).forEach(([, opts]) => {
1245
- dimensions.push({
1246
- type: 'var',
1247
- testExpr: opts[0].testLHS ?? opts[0].testString ?? getSource(opts[0].test),
1248
- options: opts.map((opt) => ({
1249
- value: opt.valueName,
1250
- style: opt.truthy,
1251
- label: opt.valueName || 'default',
1252
- })),
1398
+ ordered.push({
1399
+ order: opts[0].order ?? 0,
1400
+ dimension: {
1401
+ type: 'var',
1402
+ testExpr: opts[0].testLHS ??
1403
+ opts[0].testString ??
1404
+ getSource(opts[0].test),
1405
+ options: opts.map((opt) => ({
1406
+ value: opt.valueName,
1407
+ style: opt.truthy,
1408
+ label: opt.valueName || 'default',
1409
+ })),
1410
+ },
1253
1411
  });
1254
1412
  });
1413
+ ordered.sort((a, b) => a.order - b.order);
1414
+ const dimensions = ordered.map((o) => o.dimension);
1255
1415
  const results = {};
1256
1416
  const recurse = (dimIndex, currentStyle, keyParts) => {
1257
1417
  if (dimIndex >= dimensions.length) {
@@ -1262,18 +1422,19 @@ async function loader(source) {
1262
1422
  results[keyParts.join('__')] = className;
1263
1423
  return;
1264
1424
  }
1265
- dimensions[dimIndex].options.forEach((opt) => recurse(dimIndex + 1, (0, utils_1.deepMerge)(currentStyle, opt.style), [
1266
- ...keyParts,
1267
- String(opt.value),
1268
- ]));
1425
+ const dimension = dimensions[dimIndex];
1426
+ dimension.options.forEach((opt) => recurse(dimIndex + 1, (0, utils_1.deepMerge)(currentStyle, opt.style), dimension.type === 'const'
1427
+ ? keyParts
1428
+ : [...keyParts, String(opt.value)]));
1269
1429
  };
1270
- recurse(0, baseConflict, []);
1430
+ recurse(0, {}, []);
1271
1431
  const baseConflictClass = Object.keys(baseConflict).length > 0
1272
1432
  ? processStyleRecords(baseConflict)
1273
1433
  .map((r) => r.hash)
1274
1434
  .join(' ')
1275
1435
  : '';
1276
1436
  const masterKeyExpr = dimensions
1437
+ .filter((dim) => dim.type !== 'const')
1277
1438
  .map((dim) => dim.type === 'std'
1278
1439
  ? `(${dim.testExpr} ? "1" : "0")`
1279
1440
  : dim.testExpr || '""')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/turbopack-loader",
3
- "version": "18.0.1",
3
+ "version": "18.1.1",
4
4
  "description": "Plumeria Turbopack-loader",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -22,8 +22,8 @@
22
22
  "zero-virtual.css"
23
23
  ],
24
24
  "dependencies": {
25
- "@plumeria/compiler": "^18.0.1",
26
- "@plumeria/utils": "^18.0.1"
25
+ "@plumeria/compiler": "^18.1.1",
26
+ "@plumeria/utils": "^18.1.1"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@swc/core": "1.15.43",