@plumeria/unplugin 18.0.1 → 18.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 (3) hide show
  1. package/dist/core.js +118 -9
  2. package/dist/core.mjs +118 -9
  3. package/package.json +2 -2
package/dist/core.js CHANGED
@@ -826,6 +826,98 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
826
826
  return scannedTables.createObjectTable[hash];
827
827
  return null;
828
828
  };
829
+ const resolveBracketGroup = (node) => {
830
+ if (!utils_1.t.isMemberExpression(node) ||
831
+ !utils_1.t.isIdentifier(node.object) ||
832
+ node.property.type !== 'Computed' ||
833
+ utils_1.t.isStringLiteral(node.property.expression)) {
834
+ return null;
835
+ }
836
+ const varName = node.object.value;
837
+ const obj = resolveCreateObject(varName);
838
+ return obj
839
+ ? { varName, keyExpr: node.property.expression, obj }
840
+ : null;
841
+ };
842
+ const buildDecision = (node, prefix, off, counter) => {
843
+ if (node.type === 'ParenthesisExpression') {
844
+ return buildDecision(node.expression, prefix, off, counter);
845
+ }
846
+ if (node.type === 'ConditionalExpression') {
847
+ const a = buildDecision(node.consequent, prefix, off, counter);
848
+ if (!a)
849
+ return null;
850
+ const b = buildDecision(node.alternate, prefix, off, counter);
851
+ if (!b)
852
+ return null;
853
+ return {
854
+ keyExpr: `((${getSource(node.test)}) ? ${a.keyExpr} : ${b.keyExpr})`,
855
+ options: [...a.options, ...b.options],
856
+ leaves: a.leaves + b.leaves,
857
+ hasGroup: a.hasGroup || b.hasGroup,
858
+ };
859
+ }
860
+ if (node.type === 'BinaryExpression' && node.operator === '&&') {
861
+ const right = buildDecision(node.right, prefix, off, counter);
862
+ if (!right)
863
+ return null;
864
+ return {
865
+ keyExpr: `((${getSource(node.left)}) ? ${right.keyExpr} : ${JSON.stringify(off)})`,
866
+ options: right.options,
867
+ leaves: right.leaves,
868
+ hasGroup: right.hasGroup,
869
+ };
870
+ }
871
+ const group = resolveBracketGroup(node);
872
+ if (group) {
873
+ return {
874
+ keyExpr: getSource(group.keyExpr),
875
+ options: Object.entries(group.obj).map(([value, style]) => ({
876
+ value,
877
+ style: style,
878
+ })),
879
+ leaves: 1,
880
+ hasGroup: true,
881
+ };
882
+ }
883
+ const style = resolveStyleObject(node);
884
+ if (!style)
885
+ return null;
886
+ const value = `${prefix}${counter.n++}`;
887
+ return {
888
+ keyExpr: JSON.stringify(value),
889
+ options: [{ value, style }],
890
+ leaves: 1,
891
+ hasGroup: false,
892
+ };
893
+ };
894
+ const collectGroupKeys = (node, acc) => {
895
+ if (node.type === 'ParenthesisExpression') {
896
+ collectGroupKeys(node.expression, acc);
897
+ }
898
+ else if (node.type === 'ConditionalExpression') {
899
+ collectGroupKeys(node.consequent, acc);
900
+ collectGroupKeys(node.alternate, acc);
901
+ }
902
+ else if (node.type === 'BinaryExpression' &&
903
+ node.operator === '&&') {
904
+ collectGroupKeys(node.right, acc);
905
+ }
906
+ else {
907
+ const group = resolveBracketGroup(node);
908
+ if (group)
909
+ Object.keys(group.obj).forEach((k) => acc.add(k));
910
+ }
911
+ };
912
+ const resolveDecision = (node) => {
913
+ const groupKeys = new Set();
914
+ collectGroupKeys(node, groupKeys);
915
+ let prefix = '#';
916
+ while ([...groupKeys].some((k) => k.startsWith(prefix)))
917
+ prefix += '#';
918
+ const off = groupKeys.has('') ? `${prefix}off` : '';
919
+ return buildDecision(node, prefix, off, { n: 0 });
920
+ };
829
921
  const collectConditions = (node, currentTestStrings = []) => {
830
922
  const staticStyle = resolveStyleObject(node);
831
923
  if (staticStyle) {
@@ -880,14 +972,6 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
880
972
  else if (node.type === 'ParenthesisExpression') {
881
973
  return collectConditions(node.expression, currentTestStrings);
882
974
  }
883
- if (currentTestStrings.length > 0 &&
884
- utils_1.t.isMemberExpression(node) &&
885
- utils_1.t.isIdentifier(node.object) &&
886
- node.property.type === 'Computed' &&
887
- resolveCreateObject(node.object.value)) {
888
- const varName = node.object.value;
889
- 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);
890
- }
891
975
  assertResolvable(node);
892
976
  return false;
893
977
  };
@@ -1092,6 +1176,22 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
1092
1176
  continue;
1093
1177
  }
1094
1178
  }
1179
+ const decision = resolveDecision(expr);
1180
+ if (decision && (decision.hasGroup || decision.leaves > 2)) {
1181
+ const groupId = ++groupIdCounter;
1182
+ decision.options.forEach(({ value, style }) => conditionals.push({
1183
+ test: expr,
1184
+ testLHS: decision.keyExpr,
1185
+ testString: `${decision.keyExpr} === '${value}'`,
1186
+ truthy: style,
1187
+ falsy: {},
1188
+ groupId,
1189
+ groupName: undefined,
1190
+ valueName: value,
1191
+ varName: undefined,
1192
+ }));
1193
+ continue;
1194
+ }
1095
1195
  const handled = collectConditions(expr);
1096
1196
  if (handled)
1097
1197
  continue;
@@ -1225,7 +1325,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
1225
1325
  getSource(options[0].test);
1226
1326
  const lookupMap = {};
1227
1327
  options.forEach((opt) => {
1228
- if (opt.valueName && opt.truthy) {
1328
+ if (opt.valueName !== undefined && opt.truthy) {
1229
1329
  const className = processStyleRecords(opt.truthy)
1230
1330
  .map((r) => r.hash)
1231
1331
  .join(' ');
@@ -1263,6 +1363,15 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
1263
1363
  conflictVarGroups[c.groupId].push(c);
1264
1364
  }
1265
1365
  });
1366
+ Object.keys(conflictVarGroups).forEach((id) => {
1367
+ const groupId = Number(id);
1368
+ const opts = conflictVarGroups[groupId];
1369
+ if (opts.some((c) => c.valueName === ''))
1370
+ return;
1371
+ const off = conditionals.find((c) => c.groupId === groupId && c.valueName === '');
1372
+ if (off)
1373
+ opts.push({ ...off, truthy: {}, falsy: {} });
1374
+ });
1266
1375
  Object.entries(conflictVarGroups).forEach(([, opts]) => {
1267
1376
  dimensions.push({
1268
1377
  type: 'var',
package/dist/core.mjs CHANGED
@@ -790,6 +790,98 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
790
790
  return scannedTables.createObjectTable[hash];
791
791
  return null;
792
792
  };
793
+ const resolveBracketGroup = (node) => {
794
+ if (!t.isMemberExpression(node) ||
795
+ !t.isIdentifier(node.object) ||
796
+ node.property.type !== 'Computed' ||
797
+ t.isStringLiteral(node.property.expression)) {
798
+ return null;
799
+ }
800
+ const varName = node.object.value;
801
+ const obj = resolveCreateObject(varName);
802
+ return obj
803
+ ? { varName, keyExpr: node.property.expression, obj }
804
+ : null;
805
+ };
806
+ const buildDecision = (node, prefix, off, counter) => {
807
+ if (node.type === 'ParenthesisExpression') {
808
+ return buildDecision(node.expression, prefix, off, counter);
809
+ }
810
+ if (node.type === 'ConditionalExpression') {
811
+ const a = buildDecision(node.consequent, prefix, off, counter);
812
+ if (!a)
813
+ return null;
814
+ const b = buildDecision(node.alternate, prefix, off, counter);
815
+ if (!b)
816
+ return null;
817
+ return {
818
+ keyExpr: `((${getSource(node.test)}) ? ${a.keyExpr} : ${b.keyExpr})`,
819
+ options: [...a.options, ...b.options],
820
+ leaves: a.leaves + b.leaves,
821
+ hasGroup: a.hasGroup || b.hasGroup,
822
+ };
823
+ }
824
+ if (node.type === 'BinaryExpression' && node.operator === '&&') {
825
+ const right = buildDecision(node.right, prefix, off, counter);
826
+ if (!right)
827
+ return null;
828
+ return {
829
+ keyExpr: `((${getSource(node.left)}) ? ${right.keyExpr} : ${JSON.stringify(off)})`,
830
+ options: right.options,
831
+ leaves: right.leaves,
832
+ hasGroup: right.hasGroup,
833
+ };
834
+ }
835
+ const group = resolveBracketGroup(node);
836
+ if (group) {
837
+ return {
838
+ keyExpr: getSource(group.keyExpr),
839
+ options: Object.entries(group.obj).map(([value, style]) => ({
840
+ value,
841
+ style: style,
842
+ })),
843
+ leaves: 1,
844
+ hasGroup: true,
845
+ };
846
+ }
847
+ const style = resolveStyleObject(node);
848
+ if (!style)
849
+ return null;
850
+ const value = `${prefix}${counter.n++}`;
851
+ return {
852
+ keyExpr: JSON.stringify(value),
853
+ options: [{ value, style }],
854
+ leaves: 1,
855
+ hasGroup: false,
856
+ };
857
+ };
858
+ const collectGroupKeys = (node, acc) => {
859
+ if (node.type === 'ParenthesisExpression') {
860
+ collectGroupKeys(node.expression, acc);
861
+ }
862
+ else if (node.type === 'ConditionalExpression') {
863
+ collectGroupKeys(node.consequent, acc);
864
+ collectGroupKeys(node.alternate, acc);
865
+ }
866
+ else if (node.type === 'BinaryExpression' &&
867
+ node.operator === '&&') {
868
+ collectGroupKeys(node.right, acc);
869
+ }
870
+ else {
871
+ const group = resolveBracketGroup(node);
872
+ if (group)
873
+ Object.keys(group.obj).forEach((k) => acc.add(k));
874
+ }
875
+ };
876
+ const resolveDecision = (node) => {
877
+ const groupKeys = new Set();
878
+ collectGroupKeys(node, groupKeys);
879
+ let prefix = '#';
880
+ while ([...groupKeys].some((k) => k.startsWith(prefix)))
881
+ prefix += '#';
882
+ const off = groupKeys.has('') ? `${prefix}off` : '';
883
+ return buildDecision(node, prefix, off, { n: 0 });
884
+ };
793
885
  const collectConditions = (node, currentTestStrings = []) => {
794
886
  const staticStyle = resolveStyleObject(node);
795
887
  if (staticStyle) {
@@ -844,14 +936,6 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
844
936
  else if (node.type === 'ParenthesisExpression') {
845
937
  return collectConditions(node.expression, currentTestStrings);
846
938
  }
847
- if (currentTestStrings.length > 0 &&
848
- t.isMemberExpression(node) &&
849
- t.isIdentifier(node.object) &&
850
- node.property.type === 'Computed' &&
851
- resolveCreateObject(node.object.value)) {
852
- const varName = node.object.value;
853
- 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);
854
- }
855
939
  assertResolvable(node);
856
940
  return false;
857
941
  };
@@ -1056,6 +1140,22 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
1056
1140
  continue;
1057
1141
  }
1058
1142
  }
1143
+ const decision = resolveDecision(expr);
1144
+ if (decision && (decision.hasGroup || decision.leaves > 2)) {
1145
+ const groupId = ++groupIdCounter;
1146
+ decision.options.forEach(({ value, style }) => conditionals.push({
1147
+ test: expr,
1148
+ testLHS: decision.keyExpr,
1149
+ testString: `${decision.keyExpr} === '${value}'`,
1150
+ truthy: style,
1151
+ falsy: {},
1152
+ groupId,
1153
+ groupName: undefined,
1154
+ valueName: value,
1155
+ varName: undefined,
1156
+ }));
1157
+ continue;
1158
+ }
1059
1159
  const handled = collectConditions(expr);
1060
1160
  if (handled)
1061
1161
  continue;
@@ -1189,7 +1289,7 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
1189
1289
  getSource(options[0].test);
1190
1290
  const lookupMap = {};
1191
1291
  options.forEach((opt) => {
1192
- if (opt.valueName && opt.truthy) {
1292
+ if (opt.valueName !== undefined && opt.truthy) {
1193
1293
  const className = processStyleRecords(opt.truthy)
1194
1294
  .map((r) => r.hash)
1195
1295
  .join(' ');
@@ -1227,6 +1327,15 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
1227
1327
  conflictVarGroups[c.groupId].push(c);
1228
1328
  }
1229
1329
  });
1330
+ Object.keys(conflictVarGroups).forEach((id) => {
1331
+ const groupId = Number(id);
1332
+ const opts = conflictVarGroups[groupId];
1333
+ if (opts.some((c) => c.valueName === ''))
1334
+ return;
1335
+ const off = conditionals.find((c) => c.groupId === groupId && c.valueName === '');
1336
+ if (off)
1337
+ opts.push({ ...off, truthy: {}, falsy: {} });
1338
+ });
1230
1339
  Object.entries(conflictVarGroups).forEach(([, opts]) => {
1231
1340
  dimensions.push({
1232
1341
  type: 'var',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/unplugin",
3
- "version": "18.0.1",
3
+ "version": "18.1.0",
4
4
  "description": "Universal Plumeria plugin for various build tools",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -89,7 +89,7 @@
89
89
  "dependencies": {
90
90
  "@rollup/pluginutils": "^5.4.0",
91
91
  "unplugin": "^3.0.0",
92
- "@plumeria/utils": "^18.0.1"
92
+ "@plumeria/utils": "^18.1.0"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@swc/core": "1.15.43",