domflax 0.1.2 → 0.1.4
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/README.md +25 -8
- package/dist/{chunk-DNHOGPYV.js → chunk-3Z5ZWLXX.js} +407 -51
- package/dist/chunk-3Z5ZWLXX.js.map +1 -0
- package/dist/{chunk-DOQEBGWB.js → chunk-5FWENSD2.js} +63 -8
- package/dist/chunk-5FWENSD2.js.map +1 -0
- package/dist/chunk-EVENAJYI.js +336 -0
- package/dist/chunk-EVENAJYI.js.map +1 -0
- package/dist/{chunk-DWLB7FRR.js → chunk-H5KTGI3A.js} +153 -7
- package/dist/chunk-H5KTGI3A.js.map +1 -0
- package/dist/{chunk-6WVVF6AD.js → chunk-U5GOONKV.js} +5 -2
- package/dist/{chunk-6WVVF6AD.js.map → chunk-U5GOONKV.js.map} +1 -1
- package/dist/cli.cjs +995 -166
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +245 -229
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +614 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -18
- package/dist/index.d.ts +34 -18
- package/dist/index.js +4 -4
- package/dist/{pattern-F5xBtIE-.d.cts → pattern-CP9_HpVK.d.cts} +1 -1
- package/dist/{pattern-CV607P87.d.ts → pattern-CYgsv-jO.d.ts} +1 -1
- package/dist/pattern-kit.cjs.map +1 -1
- package/dist/pattern-kit.d.cts +2 -2
- package/dist/pattern-kit.d.ts +2 -2
- package/dist/pattern-kit.js +2 -2
- package/dist/{resolve-ops-DIwEelH-.d.ts → resolve-ops-Ci7LgYHC.d.cts} +9 -0
- package/dist/{resolve-ops-DIwEelH-.d.cts → resolve-ops-Ci7LgYHC.d.ts} +9 -0
- package/dist/verify.d.cts +1 -1
- package/dist/verify.d.ts +1 -1
- package/dist/verify.js +1 -1
- package/dist/webpack-loader.cjs +614 -68
- package/dist/webpack-loader.cjs.map +1 -1
- package/dist/webpack-loader.d.cts +2 -2
- package/dist/webpack-loader.d.ts +2 -2
- package/dist/webpack-loader.js +4 -4
- package/dist/worker.cjs +5955 -0
- package/dist/worker.cjs.map +1 -0
- package/dist/worker.d.cts +2 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.js +72 -0
- package/dist/worker.js.map +1 -0
- package/package.json +4 -2
- package/dist/chunk-DNHOGPYV.js.map +0 -1
- package/dist/chunk-DOQEBGWB.js.map +0 -1
- package/dist/chunk-DWLB7FRR.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -179,6 +179,7 @@ function defaultMeta(safetyFloor = 0) {
|
|
|
179
179
|
declaresCustomProperties: false,
|
|
180
180
|
whitespaceSensitive: false,
|
|
181
181
|
touched: false,
|
|
182
|
+
styleDirty: false,
|
|
182
183
|
synthetic: false,
|
|
183
184
|
safetyFloor
|
|
184
185
|
};
|
|
@@ -392,6 +393,14 @@ function markTouched(state, id) {
|
|
|
392
393
|
state.touched.add(id);
|
|
393
394
|
}
|
|
394
395
|
}
|
|
396
|
+
function markStyleDirty(state, id) {
|
|
397
|
+
const n = state.doc.nodes.get(id);
|
|
398
|
+
if (n) {
|
|
399
|
+
n.meta.touched = true;
|
|
400
|
+
n.meta.styleDirty = true;
|
|
401
|
+
state.touched.add(id);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
395
404
|
function removeSubtree(state, id) {
|
|
396
405
|
const node = state.doc.nodes.get(id);
|
|
397
406
|
if (!node) return;
|
|
@@ -683,7 +692,7 @@ function applyOne(state, op) {
|
|
|
683
692
|
return [precond(op, op.target, "setClassList target is not an element")];
|
|
684
693
|
}
|
|
685
694
|
el.computed = cloneStyleMap(op.style);
|
|
686
|
-
|
|
695
|
+
markStyleDirty(state, op.target);
|
|
687
696
|
return [];
|
|
688
697
|
}
|
|
689
698
|
case "mergeStyle": {
|
|
@@ -706,7 +715,7 @@ function applyOne(state, op) {
|
|
|
706
715
|
const src = doc.nodes.get(op.source);
|
|
707
716
|
if (src) markTouched(state, op.source);
|
|
708
717
|
}
|
|
709
|
-
|
|
718
|
+
markStyleDirty(state, op.target);
|
|
710
719
|
return [];
|
|
711
720
|
}
|
|
712
721
|
case "foldInheritedStyles":
|
|
@@ -757,7 +766,7 @@ function applyFold(state, op) {
|
|
|
757
766
|
}
|
|
758
767
|
if (folded) {
|
|
759
768
|
into.computed = { blocks: nextBlocks };
|
|
760
|
-
|
|
769
|
+
markStyleDirty(state, intoId);
|
|
761
770
|
}
|
|
762
771
|
}
|
|
763
772
|
for (const d of issues) state.diagnostics.push(d);
|
|
@@ -1090,8 +1099,123 @@ function buildMatchContext(doc, elementId, resolver, selectors, safety, phase, i
|
|
|
1090
1099
|
var DISPLAY = "display";
|
|
1091
1100
|
var POSITION = "position";
|
|
1092
1101
|
var TRANSFORM = "transform";
|
|
1102
|
+
var ALIGN_ITEMS = "align-items";
|
|
1103
|
+
var JUSTIFY_CONTENT = "justify-content";
|
|
1104
|
+
var JUSTIFY_ITEMS = "justify-items";
|
|
1105
|
+
var PLACE_ITEMS = "place-items";
|
|
1106
|
+
var PLACE_SELF = "place-self";
|
|
1093
1107
|
var CONTEXT_SAFE_DISPLAYS = /* @__PURE__ */ new Set(["block", "contents", ""]);
|
|
1094
1108
|
var STATIC_POSITIONS = /* @__PURE__ */ new Set(["static", ""]);
|
|
1109
|
+
var CENTERING_DISPLAYS = /* @__PURE__ */ new Set(["flex", "grid"]);
|
|
1110
|
+
var GRID_PARENT_DISPLAYS = /* @__PURE__ */ new Set(["grid"]);
|
|
1111
|
+
var STRETCHY_ITEM_ALIGN = /* @__PURE__ */ new Set(["normal", "stretch"]);
|
|
1112
|
+
var PARENT_ITEMS_ALIGN_PROPS = [ALIGN_ITEMS, JUSTIFY_ITEMS, PLACE_ITEMS];
|
|
1113
|
+
function isBaseCondition(block) {
|
|
1114
|
+
const c = block.condition;
|
|
1115
|
+
return c.media === "" && c.states.length === 0 && c.pseudoElement === "";
|
|
1116
|
+
}
|
|
1117
|
+
function baseValue(sm, prop) {
|
|
1118
|
+
for (const block of sm.blocks.values()) {
|
|
1119
|
+
if (!isBaseCondition(block)) continue;
|
|
1120
|
+
const d = block.decls.get(prop);
|
|
1121
|
+
return d ? String(d.value) : null;
|
|
1122
|
+
}
|
|
1123
|
+
return null;
|
|
1124
|
+
}
|
|
1125
|
+
function parentIsFillingGrid(before, wrapper, norm) {
|
|
1126
|
+
if (wrapper.parent == null) return false;
|
|
1127
|
+
const p = before.nodes.get(wrapper.parent);
|
|
1128
|
+
if (!p || p.kind !== "element") return false;
|
|
1129
|
+
const pc2 = norm.normalizeStyleMap(p.computed);
|
|
1130
|
+
let baseIsGrid = false;
|
|
1131
|
+
for (const block of pc2.blocks.values()) {
|
|
1132
|
+
const disp = block.decls.get(DISPLAY);
|
|
1133
|
+
if (disp) {
|
|
1134
|
+
if (!GRID_PARENT_DISPLAYS.has(String(disp.value))) return false;
|
|
1135
|
+
if (isBaseCondition(block)) baseIsGrid = true;
|
|
1136
|
+
}
|
|
1137
|
+
for (const prop of PARENT_ITEMS_ALIGN_PROPS) {
|
|
1138
|
+
const d = block.decls.get(prop);
|
|
1139
|
+
if (d && !STRETCHY_ITEM_ALIGN.has(String(d.value))) return false;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
return baseIsGrid;
|
|
1143
|
+
}
|
|
1144
|
+
function wrapperHasOnlyCenteringStyle(wrapperComputed, childComputed, norm) {
|
|
1145
|
+
for (const block of wrapperComputed.blocks.values()) {
|
|
1146
|
+
const base = isBaseCondition(block);
|
|
1147
|
+
const ck = conditionKey(block.condition);
|
|
1148
|
+
for (const [prop, decl] of block.decls) {
|
|
1149
|
+
const val = String(decl.value);
|
|
1150
|
+
if (prop === DISPLAY) {
|
|
1151
|
+
if (base && CENTERING_DISPLAYS.has(val)) continue;
|
|
1152
|
+
return false;
|
|
1153
|
+
}
|
|
1154
|
+
if (prop === ALIGN_ITEMS) {
|
|
1155
|
+
if (base && val === "center") continue;
|
|
1156
|
+
return false;
|
|
1157
|
+
}
|
|
1158
|
+
if (prop === JUSTIFY_CONTENT) {
|
|
1159
|
+
if (base && val === "center") continue;
|
|
1160
|
+
return false;
|
|
1161
|
+
}
|
|
1162
|
+
if (prop === POSITION) {
|
|
1163
|
+
if (STATIC_POSITIONS.has(val)) continue;
|
|
1164
|
+
return false;
|
|
1165
|
+
}
|
|
1166
|
+
if (prop === TRANSFORM) {
|
|
1167
|
+
if (val === "none") continue;
|
|
1168
|
+
return false;
|
|
1169
|
+
}
|
|
1170
|
+
if (isInherited2(decl, norm)) continue;
|
|
1171
|
+
if (childReproduces(childComputed, ck, prop, val)) continue;
|
|
1172
|
+
return false;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return true;
|
|
1176
|
+
}
|
|
1177
|
+
function wrapperCentersSingleElement(before, wrapper) {
|
|
1178
|
+
let elements = 0;
|
|
1179
|
+
for (const cid of wrapper.children) {
|
|
1180
|
+
const n = before.nodes.get(cid);
|
|
1181
|
+
if (!n) continue;
|
|
1182
|
+
if (n.kind === "element") {
|
|
1183
|
+
elements += 1;
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1186
|
+
if (n.kind === "comment") continue;
|
|
1187
|
+
if (n.kind === "text" && n.value.trim() === "") continue;
|
|
1188
|
+
return false;
|
|
1189
|
+
}
|
|
1190
|
+
return elements === 1;
|
|
1191
|
+
}
|
|
1192
|
+
function childHasSelfAlign(childBefore, norm) {
|
|
1193
|
+
if (!childBefore) return false;
|
|
1194
|
+
const sm = norm.normalizeStyleMap(childBefore);
|
|
1195
|
+
for (const block of sm.blocks.values()) {
|
|
1196
|
+
for (const prop of SELF_ALIGN_PROPS) {
|
|
1197
|
+
const d = block.decls.get(prop);
|
|
1198
|
+
if (d && !NEUTRAL_ALIGN.has(String(d.value))) return true;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
return false;
|
|
1202
|
+
}
|
|
1203
|
+
function childGainsPlaceSelfCenter(childAfter) {
|
|
1204
|
+
if (baseValue(childAfter, PLACE_SELF) === "center") return true;
|
|
1205
|
+
return baseValue(childAfter, "align-self") === "center" && baseValue(childAfter, "justify-self") === "center";
|
|
1206
|
+
}
|
|
1207
|
+
function isContextCompensatedCentering(before, wrapper, wrapperComputed, childBefore, childAfter, norm) {
|
|
1208
|
+
if (!childAfter) return false;
|
|
1209
|
+
if (!CENTERING_DISPLAYS.has(baseValue(wrapperComputed, DISPLAY) ?? "")) return false;
|
|
1210
|
+
if (baseValue(wrapperComputed, ALIGN_ITEMS) !== "center") return false;
|
|
1211
|
+
if (baseValue(wrapperComputed, JUSTIFY_CONTENT) !== "center") return false;
|
|
1212
|
+
const childAfterNorm = norm.normalizeStyleMap(childAfter);
|
|
1213
|
+
if (!childGainsPlaceSelfCenter(childAfterNorm)) return false;
|
|
1214
|
+
if (!wrapperHasOnlyCenteringStyle(wrapperComputed, childAfterNorm, norm)) return false;
|
|
1215
|
+
if (!wrapperCentersSingleElement(before, wrapper)) return false;
|
|
1216
|
+
if (childHasSelfAlign(childBefore, norm)) return false;
|
|
1217
|
+
return parentIsFillingGrid(before, wrapper, norm);
|
|
1218
|
+
}
|
|
1095
1219
|
var SELF_ALIGN_PROPS = [
|
|
1096
1220
|
"place-self",
|
|
1097
1221
|
"align-self",
|
|
@@ -1191,6 +1315,9 @@ function classifyFlattenOps(before, after, ops, norm) {
|
|
|
1191
1315
|
const wrapperComputed = norm.normalizeStyleMap(wrapper.computed);
|
|
1192
1316
|
const childAfter = childId != null ? getElement(after, childId)?.computed ?? null : null;
|
|
1193
1317
|
const childBefore = childId != null ? getElement(before, childId)?.computed ?? null : null;
|
|
1318
|
+
if (isContextCompensatedCentering(before, wrapper, wrapperComputed, childBefore, childAfter, norm)) {
|
|
1319
|
+
return { kind: "provably-safe", wrapperId, childId };
|
|
1320
|
+
}
|
|
1194
1321
|
if (establishesChildContext(wrapperComputed)) {
|
|
1195
1322
|
return { kind: "needs-verification", wrapperId, childId };
|
|
1196
1323
|
}
|
|
@@ -1626,15 +1753,34 @@ function sameTokens(a, b) {
|
|
|
1626
1753
|
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
|
|
1627
1754
|
return true;
|
|
1628
1755
|
}
|
|
1756
|
+
function residualStyle(computed2, covered, norm) {
|
|
1757
|
+
const cov = norm.normalizeStyleMap(covered);
|
|
1758
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
1759
|
+
for (const [key, block] of norm.normalizeStyleMap(computed2).blocks) {
|
|
1760
|
+
const covBlock = cov.blocks.get(key);
|
|
1761
|
+
const decls = /* @__PURE__ */ new Map();
|
|
1762
|
+
for (const [prop, decl] of block.decls) {
|
|
1763
|
+
const covDecl = covBlock?.decls.get(prop);
|
|
1764
|
+
if (covDecl && covDecl.value === decl.value && covDecl.important === decl.important) continue;
|
|
1765
|
+
decls.set(prop, decl);
|
|
1766
|
+
}
|
|
1767
|
+
if (decls.size > 0) blocks.set(key, { condition: block.condition, decls });
|
|
1768
|
+
}
|
|
1769
|
+
return { blocks };
|
|
1770
|
+
}
|
|
1629
1771
|
function syncClassesFromComputed(doc, resolver, norm) {
|
|
1630
1772
|
const sink = createSyntheticSink();
|
|
1631
1773
|
for (const id of elementIds(doc)) {
|
|
1632
1774
|
const el = getElement(doc, id);
|
|
1633
|
-
if (!el
|
|
1775
|
+
if (!el) continue;
|
|
1776
|
+
if (!el.meta.styleDirty) continue;
|
|
1634
1777
|
if (el.classes.opaque || el.classes.hasDynamic) continue;
|
|
1635
1778
|
const tokens = staticTokensOf(el.classes);
|
|
1779
|
+
const retained = tokens.filter((t) => !resolver.selectorUsage(t).droppable);
|
|
1780
|
+
const covered = retained.length > 0 ? resolver.resolve({ classes: retained }).styles : null;
|
|
1781
|
+
const target = covered ? residualStyle(el.computed, covered, norm) : el.computed;
|
|
1636
1782
|
const ctx = { normalizer: norm, sink };
|
|
1637
|
-
const emitted = resolver.emit(
|
|
1783
|
+
const emitted = resolver.emit(target, ctx).classes;
|
|
1638
1784
|
if (emitted.length === 0) continue;
|
|
1639
1785
|
const emittedSet = new Set(emitted);
|
|
1640
1786
|
const next = [];
|
|
@@ -2346,19 +2492,28 @@ var flexCenterWrapper = definePattern({
|
|
|
2346
2492
|
flattenInto: "child",
|
|
2347
2493
|
childGains: { placeSelf: "center" }
|
|
2348
2494
|
},
|
|
2349
|
-
// Collapsing a flex-centering wrapper to `place-self:center` on the child
|
|
2350
|
-
// the child's NEW parent is
|
|
2351
|
-
//
|
|
2352
|
-
//
|
|
2353
|
-
//
|
|
2354
|
-
// unwrap, opacity-barrier safety) is
|
|
2495
|
+
// Collapsing a flex-centering wrapper to `place-self:center` on the child is render-identical ONLY
|
|
2496
|
+
// when the child's NEW parent is a statically-known GRID that lets the wrapper fill its area (there
|
|
2497
|
+
// `place-self`'s align-self AND justify-self both take effect). Under that ONE context the flatten is
|
|
2498
|
+
// classified `provably-safe` and commits; under a flex/block/unknown parent — or when the wrapper
|
|
2499
|
+
// drops any own style — it stays `needs-verification` and the conservative production gate PRESERVES
|
|
2500
|
+
// it. Op-level correctness (purity, id-preserving unwrap, opacity-barrier safety) is additionally
|
|
2501
|
+
// asserted by the invariant suite over every pattern.
|
|
2355
2502
|
test: {
|
|
2503
|
+
cases: [
|
|
2504
|
+
{
|
|
2505
|
+
name: "grid parent \u2192 flattened (child gains place-self-center)",
|
|
2506
|
+
before: '<div className="grid"><div className="flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2507
|
+
after: '<div className="grid"><span className="bg-red-200 place-self-center">x</span></div>'
|
|
2508
|
+
}
|
|
2509
|
+
],
|
|
2356
2510
|
noMatch: [
|
|
2357
|
-
//
|
|
2358
|
-
// (the wrapper itself establishes a flex formatting context) → left unchanged.
|
|
2359
|
-
'<div className="grid"><div className="flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2360
|
-
// Non-flex/grid parent (document root): place-self centering would not hold → left unchanged.
|
|
2511
|
+
// Non-grid (flex) parent (document root): `justify-self` is ignored in flex → not provably safe.
|
|
2361
2512
|
'<div className="flex justify-center items-center"><div className="bg-red-200">Hello</div></div>',
|
|
2513
|
+
// Grid parent, but the wrapper drops padding when removed → not layout-neutral (rule 3).
|
|
2514
|
+
'<div className="grid"><div className="p-4 flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2515
|
+
// Grid parent forcing place-items-center: the wrapper would not fill its area → fill guard skips.
|
|
2516
|
+
'<div className="grid place-items-center"><div className="flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2362
2517
|
// onClick is a hard opacity barrier → the wrapper is load-bearing regardless of the gate.
|
|
2363
2518
|
'<div className="flex justify-center items-center" onClick={handleClick}><div className="bg-red-200">Hello</div></div>'
|
|
2364
2519
|
]
|
|
@@ -3562,11 +3717,11 @@ var paddingShorthand = definePattern({
|
|
|
3562
3717
|
});
|
|
3563
3718
|
|
|
3564
3719
|
// ../patterns/src/library/compress/place-shorthand.pattern.ts
|
|
3565
|
-
var
|
|
3566
|
-
var
|
|
3567
|
-
var
|
|
3720
|
+
var ALIGN_ITEMS2 = "align-items";
|
|
3721
|
+
var JUSTIFY_ITEMS2 = "justify-items";
|
|
3722
|
+
var PLACE_ITEMS2 = "place-items";
|
|
3568
3723
|
var ALIGN_CONTENT = "align-content";
|
|
3569
|
-
var
|
|
3724
|
+
var JUSTIFY_CONTENT2 = "justify-content";
|
|
3570
3725
|
var PLACE_CONTENT = "place-content";
|
|
3571
3726
|
var BASE_KEY8 = conditionKey(BASE_CONDITION);
|
|
3572
3727
|
function samePair(a, b) {
|
|
@@ -3606,21 +3761,21 @@ var placeShorthand = definePattern({
|
|
|
3606
3761
|
rewriteClasses(computed2) {
|
|
3607
3762
|
const base = computed2.blocks.get(BASE_KEY8);
|
|
3608
3763
|
if (!base) return null;
|
|
3609
|
-
const alignItems = base.decls.get(
|
|
3610
|
-
const justifyItems = base.decls.get(
|
|
3764
|
+
const alignItems = base.decls.get(ALIGN_ITEMS2);
|
|
3765
|
+
const justifyItems = base.decls.get(JUSTIFY_ITEMS2);
|
|
3611
3766
|
const alignContent = base.decls.get(ALIGN_CONTENT);
|
|
3612
|
-
const justifyContent = base.decls.get(
|
|
3767
|
+
const justifyContent = base.decls.get(JUSTIFY_CONTENT2);
|
|
3613
3768
|
const next = new Map(base.decls);
|
|
3614
3769
|
let collapsed = false;
|
|
3615
3770
|
if (samePair(alignItems, justifyItems)) {
|
|
3616
|
-
next.delete(
|
|
3617
|
-
next.delete(
|
|
3618
|
-
next.set(
|
|
3771
|
+
next.delete(ALIGN_ITEMS2);
|
|
3772
|
+
next.delete(JUSTIFY_ITEMS2);
|
|
3773
|
+
next.set(PLACE_ITEMS2, placeDecl(PLACE_ITEMS2, alignItems));
|
|
3619
3774
|
collapsed = true;
|
|
3620
3775
|
}
|
|
3621
3776
|
if (samePair(alignContent, justifyContent)) {
|
|
3622
3777
|
next.delete(ALIGN_CONTENT);
|
|
3623
|
-
next.delete(
|
|
3778
|
+
next.delete(JUSTIFY_CONTENT2);
|
|
3624
3779
|
next.set(PLACE_CONTENT, placeDecl(PLACE_CONTENT, alignContent));
|
|
3625
3780
|
collapsed = true;
|
|
3626
3781
|
}
|
|
@@ -4809,11 +4964,349 @@ function createCssResolver(cssFiles = [], options) {
|
|
|
4809
4964
|
var import_node_path = require("path");
|
|
4810
4965
|
var import_node_url = require("url");
|
|
4811
4966
|
|
|
4967
|
+
// ../frontend-html/src/backend.ts
|
|
4968
|
+
var import_magic_string = __toESM(require("magic-string"), 1);
|
|
4969
|
+
function staticTokensOf2(classes) {
|
|
4970
|
+
const out = [];
|
|
4971
|
+
for (const seg of classes.segments) {
|
|
4972
|
+
if (seg.kind === "static") for (const t of seg.tokens) out.push(t.value);
|
|
4973
|
+
}
|
|
4974
|
+
return out;
|
|
4975
|
+
}
|
|
4976
|
+
function sameTokens2(a, b) {
|
|
4977
|
+
if (a.length !== b.length) return false;
|
|
4978
|
+
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
|
|
4979
|
+
return true;
|
|
4980
|
+
}
|
|
4981
|
+
function primarySource(doc) {
|
|
4982
|
+
for (const sf of doc.sources.values()) {
|
|
4983
|
+
if (typeof sf.text === "string" && sf.text.length > 0) return sf;
|
|
4984
|
+
}
|
|
4985
|
+
return null;
|
|
4986
|
+
}
|
|
4987
|
+
function collectKept(doc) {
|
|
4988
|
+
const out = [];
|
|
4989
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4990
|
+
const visit = (id) => {
|
|
4991
|
+
if (seen.has(id)) return;
|
|
4992
|
+
seen.add(id);
|
|
4993
|
+
const n = doc.nodes.get(id);
|
|
4994
|
+
if (!n) return;
|
|
4995
|
+
out.push(n);
|
|
4996
|
+
if (n.kind === "element" || n.kind === "fragment") for (const c of n.children) visit(c);
|
|
4997
|
+
};
|
|
4998
|
+
visit(doc.root);
|
|
4999
|
+
return out;
|
|
5000
|
+
}
|
|
5001
|
+
function strictlyContains(a, b) {
|
|
5002
|
+
if (a.file !== b.file) return false;
|
|
5003
|
+
if (a.start <= b.start && b.end <= a.end) return !(a.start === b.start && a.end === b.end);
|
|
5004
|
+
return false;
|
|
5005
|
+
}
|
|
5006
|
+
function backrefIds(doc) {
|
|
5007
|
+
const out = [];
|
|
5008
|
+
const max = doc.alloc.peek;
|
|
5009
|
+
for (let i = 1; i < max; i += 1) {
|
|
5010
|
+
const id = i;
|
|
5011
|
+
if (doc.backref.get(id)) out.push(id);
|
|
5012
|
+
}
|
|
5013
|
+
return out;
|
|
5014
|
+
}
|
|
5015
|
+
function currentTokens(sf, valueSpan) {
|
|
5016
|
+
const raw = sf.text.slice(valueSpan.start, valueSpan.end).trim();
|
|
5017
|
+
const unquoted = raw.replace(/^['"]/, "").replace(/['"]$/, "");
|
|
5018
|
+
return unquoted.split(/\s+/).filter((t) => t.length > 0);
|
|
5019
|
+
}
|
|
5020
|
+
function editClasses(ms, doc, sf, el) {
|
|
5021
|
+
const classes = el.classes;
|
|
5022
|
+
if (classes.hasDynamic || classes.opaque) return false;
|
|
5023
|
+
const tokens = staticTokensOf2(classes);
|
|
5024
|
+
const valueSpan = classes.valueSpan;
|
|
5025
|
+
if (valueSpan && valueSpan.file === sf.id) {
|
|
5026
|
+
if (sameTokens2(currentTokens(sf, valueSpan), tokens)) return false;
|
|
5027
|
+
const current = sf.text.slice(valueSpan.start, valueSpan.end).trim();
|
|
5028
|
+
const quote = current.startsWith("'") ? "'" : '"';
|
|
5029
|
+
ms.overwrite(valueSpan.start, valueSpan.end, `${quote}${tokens.join(" ")}${quote}`);
|
|
5030
|
+
return true;
|
|
5031
|
+
}
|
|
5032
|
+
if (tokens.length === 0) return false;
|
|
5033
|
+
const openTag = doc.backref.get(el.id)?.openTagSpan;
|
|
5034
|
+
if (!openTag || openTag.file !== sf.id) return false;
|
|
5035
|
+
ms.appendLeft(openTag.start + 1 + el.tag.length, ` class="${tokens.join(" ")}"`);
|
|
5036
|
+
return true;
|
|
5037
|
+
}
|
|
5038
|
+
function surgicalPrint(doc) {
|
|
5039
|
+
const sf = primarySource(doc);
|
|
5040
|
+
if (!sf) return null;
|
|
5041
|
+
const ms = new import_magic_string.default(sf.text);
|
|
5042
|
+
const kept = collectKept(doc);
|
|
5043
|
+
const keptSpans = [];
|
|
5044
|
+
for (const n of kept) if (n.span && n.span.file === sf.id) keptSpans.push(n.span);
|
|
5045
|
+
const removed = [];
|
|
5046
|
+
for (const id of backrefIds(doc)) {
|
|
5047
|
+
if (doc.nodes.has(id)) continue;
|
|
5048
|
+
const back = doc.backref.get(id);
|
|
5049
|
+
if (!back || back.span.file !== sf.id) continue;
|
|
5050
|
+
const unwrapped = keptSpans.some((k) => strictlyContains(back.span, k));
|
|
5051
|
+
removed.push({ backref: back, unwrapped });
|
|
5052
|
+
}
|
|
5053
|
+
const fullRemovals = removed.filter((r) => !r.unwrapped).map((r) => r.backref.span);
|
|
5054
|
+
for (const r of removed) {
|
|
5055
|
+
const s = r.backref.span;
|
|
5056
|
+
if (fullRemovals.some((f) => f !== s && strictlyContains(f, s))) continue;
|
|
5057
|
+
if (r.unwrapped) {
|
|
5058
|
+
const open = r.backref.openTagSpan;
|
|
5059
|
+
const close = r.backref.closeTagSpan;
|
|
5060
|
+
if (open && open.file === sf.id && open.end > open.start) ms.remove(open.start, open.end);
|
|
5061
|
+
if (close && close.file === sf.id && close.end > close.start) ms.remove(close.start, close.end);
|
|
5062
|
+
} else {
|
|
5063
|
+
ms.remove(s.start, s.end);
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
for (const n of kept) if (n.kind === "element") editClasses(ms, doc, sf, n);
|
|
5067
|
+
return ms.toString();
|
|
5068
|
+
}
|
|
5069
|
+
function doPrint(doc) {
|
|
5070
|
+
return surgicalPrint(doc) ?? "";
|
|
5071
|
+
}
|
|
5072
|
+
|
|
5073
|
+
// ../frontend-html/src/parse.ts
|
|
5074
|
+
var import_node_module3 = require("module");
|
|
5075
|
+
|
|
5076
|
+
// ../frontend-html/src/walk.ts
|
|
5077
|
+
var HTML_LANGS = ["html"];
|
|
5078
|
+
var FILE_ID = 1;
|
|
5079
|
+
function looksLikeHtml(id, code) {
|
|
5080
|
+
if (/\.html?$/i.test(id)) return true;
|
|
5081
|
+
const head = code.slice(0, 256).trimStart().toLowerCase();
|
|
5082
|
+
return head.startsWith("<!doctype html") || head.startsWith("<html") || head.startsWith("<");
|
|
5083
|
+
}
|
|
5084
|
+
var OPAQUE_SUBTREE_TAGS = /* @__PURE__ */ new Set([
|
|
5085
|
+
"script",
|
|
5086
|
+
"style",
|
|
5087
|
+
"template",
|
|
5088
|
+
"svg",
|
|
5089
|
+
"pre",
|
|
5090
|
+
"textarea"
|
|
5091
|
+
]);
|
|
5092
|
+
function isOpaqueSubtreeTag(tag) {
|
|
5093
|
+
return OPAQUE_SUBTREE_TAGS.has(tag);
|
|
5094
|
+
}
|
|
5095
|
+
function elementIsOpaque(attrs) {
|
|
5096
|
+
for (const a of attrs) {
|
|
5097
|
+
const n = a.name.toLowerCase();
|
|
5098
|
+
if (n === "id" || n === "contenteditable") return true;
|
|
5099
|
+
if (n.startsWith("on")) return true;
|
|
5100
|
+
}
|
|
5101
|
+
return false;
|
|
5102
|
+
}
|
|
5103
|
+
function hasEventHandler(attrs) {
|
|
5104
|
+
for (const a of attrs) if (/^on/i.test(a.name)) return true;
|
|
5105
|
+
return false;
|
|
5106
|
+
}
|
|
5107
|
+
function span(start, end) {
|
|
5108
|
+
return { file: FILE_ID, start, end };
|
|
5109
|
+
}
|
|
5110
|
+
function attrsLocOf(loc) {
|
|
5111
|
+
if (!loc) return void 0;
|
|
5112
|
+
return loc.startTag?.attrs ?? loc.attrs;
|
|
5113
|
+
}
|
|
5114
|
+
function classValueSpan(loc, source) {
|
|
5115
|
+
const attrsLoc = attrsLocOf(loc);
|
|
5116
|
+
const cl = attrsLoc?.["class"];
|
|
5117
|
+
if (!cl) return null;
|
|
5118
|
+
const text = source.slice(cl.startOffset, cl.endOffset);
|
|
5119
|
+
const eq = text.indexOf("=");
|
|
5120
|
+
if (eq === -1) return null;
|
|
5121
|
+
let i = eq + 1;
|
|
5122
|
+
while (i < text.length && /\s/.test(text[i])) i += 1;
|
|
5123
|
+
if (i >= text.length) return null;
|
|
5124
|
+
return span(cl.startOffset + i, cl.endOffset);
|
|
5125
|
+
}
|
|
5126
|
+
|
|
5127
|
+
// ../frontend-html/src/parse.ts
|
|
5128
|
+
var cachedParse5 = null;
|
|
5129
|
+
function loadParse5() {
|
|
5130
|
+
if (cachedParse5) return cachedParse5;
|
|
5131
|
+
const req = (0, import_node_module3.createRequire)(importMetaUrl);
|
|
5132
|
+
cachedParse5 = req("parse5");
|
|
5133
|
+
return cachedParse5;
|
|
5134
|
+
}
|
|
5135
|
+
function doParse(code, ctx) {
|
|
5136
|
+
const diagnostics = [];
|
|
5137
|
+
const doc = createDocument("html");
|
|
5138
|
+
const backref = doc.backref;
|
|
5139
|
+
const parse5 = loadParse5();
|
|
5140
|
+
const document2 = parse5.parse(code, { sourceCodeLocationInfo: true });
|
|
5141
|
+
const eol = code.includes("\r\n") ? "\r\n" : "\n";
|
|
5142
|
+
const sourceFile = {
|
|
5143
|
+
id: FILE_ID,
|
|
5144
|
+
path: ctx.id,
|
|
5145
|
+
text: code,
|
|
5146
|
+
frontend: "html",
|
|
5147
|
+
eol,
|
|
5148
|
+
indentUnit: " ",
|
|
5149
|
+
native: document2
|
|
5150
|
+
};
|
|
5151
|
+
doc.sources.set(FILE_ID, sourceFile);
|
|
5152
|
+
const resolveComputed = (tokens, tag, nodeId) => {
|
|
5153
|
+
if (tokens.length === 0) return emptyStyleMap();
|
|
5154
|
+
const res = ctx.resolver.resolve({ classes: tokens, element: { tagName: tag, namespace: "html" } });
|
|
5155
|
+
for (const w of res.warnings) {
|
|
5156
|
+
diagnostics.push({
|
|
5157
|
+
code: "DF_STYLE_CONFLICT_UNRESOLVED",
|
|
5158
|
+
severity: w.severity,
|
|
5159
|
+
message: w.message,
|
|
5160
|
+
nodeId
|
|
5161
|
+
});
|
|
5162
|
+
}
|
|
5163
|
+
return ctx.normalizer.normalizeStyleMap(res.styles);
|
|
5164
|
+
};
|
|
5165
|
+
const splitTokens = (raw) => raw.split(/\s+/).filter((t) => t.length > 0);
|
|
5166
|
+
const appendChild = (node, parentId, out) => {
|
|
5167
|
+
const name = node.nodeName;
|
|
5168
|
+
if (name === "#text") {
|
|
5169
|
+
const value = node.value ?? "";
|
|
5170
|
+
const id = doc.alloc.next();
|
|
5171
|
+
const loc = node.sourceCodeLocation ?? null;
|
|
5172
|
+
doc.nodes.set(
|
|
5173
|
+
id,
|
|
5174
|
+
createText(id, value, {
|
|
5175
|
+
parent: parentId,
|
|
5176
|
+
span: loc ? span(loc.startOffset, loc.endOffset) : null,
|
|
5177
|
+
collapsible: /^\s*$/.test(value)
|
|
5178
|
+
})
|
|
5179
|
+
);
|
|
5180
|
+
out.push(id);
|
|
5181
|
+
return;
|
|
5182
|
+
}
|
|
5183
|
+
if (name === "#comment") {
|
|
5184
|
+
const id = doc.alloc.next();
|
|
5185
|
+
const loc = node.sourceCodeLocation ?? null;
|
|
5186
|
+
doc.nodes.set(
|
|
5187
|
+
id,
|
|
5188
|
+
createComment(id, node.data ?? "", {
|
|
5189
|
+
parent: parentId,
|
|
5190
|
+
span: loc ? span(loc.startOffset, loc.endOffset) : null
|
|
5191
|
+
})
|
|
5192
|
+
);
|
|
5193
|
+
out.push(id);
|
|
5194
|
+
return;
|
|
5195
|
+
}
|
|
5196
|
+
if (name === "#documentType") return;
|
|
5197
|
+
if (name.startsWith("#")) {
|
|
5198
|
+
for (const c of node.childNodes ?? []) appendChild(c, parentId, out);
|
|
5199
|
+
return;
|
|
5200
|
+
}
|
|
5201
|
+
out.push(buildElement(node, parentId));
|
|
5202
|
+
};
|
|
5203
|
+
const buildElement = (node, parentId) => {
|
|
5204
|
+
const id = doc.alloc.next();
|
|
5205
|
+
const tag = (node.tagName ?? node.nodeName).toLowerCase();
|
|
5206
|
+
const loc = node.sourceCodeLocation ?? null;
|
|
5207
|
+
const attrsArr = node.attrs ?? [];
|
|
5208
|
+
const opaqueSubtree = isOpaqueSubtreeTag(tag);
|
|
5209
|
+
const synthetic = loc == null;
|
|
5210
|
+
const opaque2 = opaqueSubtree || synthetic || elementIsOpaque(attrsArr);
|
|
5211
|
+
const meta = defaultMeta();
|
|
5212
|
+
meta.hasEventHandlers = hasEventHandler(attrsArr);
|
|
5213
|
+
meta.safetyFloor = opaque2 ? 0 : 3;
|
|
5214
|
+
let classes = emptyClassList();
|
|
5215
|
+
let classTokens = [];
|
|
5216
|
+
const entries = /* @__PURE__ */ new Map();
|
|
5217
|
+
const order = [];
|
|
5218
|
+
for (const a of attrsArr) {
|
|
5219
|
+
if (a.name.toLowerCase() === "class") {
|
|
5220
|
+
classTokens = splitTokens(a.value);
|
|
5221
|
+
const valueSpan = classValueSpan(loc, code);
|
|
5222
|
+
const clAttr = attrsLocOf(loc)?.["class"];
|
|
5223
|
+
const seg = {
|
|
5224
|
+
kind: "static",
|
|
5225
|
+
span: valueSpan ?? void 0,
|
|
5226
|
+
tokens: classTokens.map((value) => ({ value }))
|
|
5227
|
+
};
|
|
5228
|
+
classes = {
|
|
5229
|
+
form: "string-literal",
|
|
5230
|
+
segments: [seg],
|
|
5231
|
+
valueSpan,
|
|
5232
|
+
attrSpan: clAttr ? span(clAttr.startOffset, clAttr.endOffset) : void 0,
|
|
5233
|
+
hasDynamic: false,
|
|
5234
|
+
opaque: false,
|
|
5235
|
+
rewritable: valueSpan != null
|
|
5236
|
+
};
|
|
5237
|
+
continue;
|
|
5238
|
+
}
|
|
5239
|
+
const v = a.value;
|
|
5240
|
+
entries.set(a.name, { kind: "static", value: v === "" ? true : v });
|
|
5241
|
+
order.push(a.name);
|
|
5242
|
+
}
|
|
5243
|
+
const attrs = { entries, spreads: [], order };
|
|
5244
|
+
const computed2 = resolveComputed(classTokens, tag, id);
|
|
5245
|
+
const children = [];
|
|
5246
|
+
if (!opaqueSubtree) {
|
|
5247
|
+
for (const c of node.childNodes ?? []) appendChild(c, id, children);
|
|
5248
|
+
}
|
|
5249
|
+
const el = createElement(id, {
|
|
5250
|
+
tag,
|
|
5251
|
+
namespace: "html",
|
|
5252
|
+
isComponent: false,
|
|
5253
|
+
selfClosing: loc ? loc.endTag == null : false,
|
|
5254
|
+
classes,
|
|
5255
|
+
computed: computed2,
|
|
5256
|
+
attrs,
|
|
5257
|
+
children,
|
|
5258
|
+
parent: parentId,
|
|
5259
|
+
span: loc ? span(loc.startOffset, loc.endOffset) : null,
|
|
5260
|
+
meta
|
|
5261
|
+
});
|
|
5262
|
+
doc.nodes.set(id, el);
|
|
5263
|
+
if (loc) {
|
|
5264
|
+
backref.set(id, {
|
|
5265
|
+
nodeId: id,
|
|
5266
|
+
span: span(loc.startOffset, loc.endOffset),
|
|
5267
|
+
openTagSpan: loc.startTag ? span(loc.startTag.startOffset, loc.startTag.endOffset) : null,
|
|
5268
|
+
closeTagSpan: loc.endTag ? span(loc.endTag.startOffset, loc.endTag.endOffset) : null,
|
|
5269
|
+
innerSpan: null,
|
|
5270
|
+
selfClosing: loc.endTag == null
|
|
5271
|
+
});
|
|
5272
|
+
}
|
|
5273
|
+
return id;
|
|
5274
|
+
};
|
|
5275
|
+
const rootFrag = doc.nodes.get(doc.root);
|
|
5276
|
+
appendChild(document2, doc.root, rootFrag.children);
|
|
5277
|
+
return { doc, diagnostics };
|
|
5278
|
+
}
|
|
5279
|
+
|
|
5280
|
+
// ../frontend-html/src/index.ts
|
|
5281
|
+
var htmlFrontend = {
|
|
5282
|
+
name: "html",
|
|
5283
|
+
langs: HTML_LANGS,
|
|
5284
|
+
canParse(id, code) {
|
|
5285
|
+
return looksLikeHtml(id, code);
|
|
5286
|
+
},
|
|
5287
|
+
parse(code, ctx) {
|
|
5288
|
+
return doParse(code, ctx);
|
|
5289
|
+
}
|
|
5290
|
+
};
|
|
5291
|
+
function createHtmlFrontend() {
|
|
5292
|
+
return htmlFrontend;
|
|
5293
|
+
}
|
|
5294
|
+
var htmlBackend = {
|
|
5295
|
+
name: "html",
|
|
5296
|
+
langs: HTML_LANGS,
|
|
5297
|
+
print(doc, _plan, _ctx) {
|
|
5298
|
+
return { code: doPrint(doc), map: null, edits: [], diagnostics: [] };
|
|
5299
|
+
}
|
|
5300
|
+
};
|
|
5301
|
+
function createHtmlBackend() {
|
|
5302
|
+
return htmlBackend;
|
|
5303
|
+
}
|
|
5304
|
+
|
|
4812
5305
|
// ../frontend-jsx/src/frontend-ast.ts
|
|
4813
5306
|
var import_traverse = __toESM(require("@babel/traverse"), 1);
|
|
4814
5307
|
var traverse = typeof import_traverse.default === "function" ? import_traverse.default : import_traverse.default.default;
|
|
4815
5308
|
var JSX_LANGS = ["jsx", "tsx"];
|
|
4816
|
-
var
|
|
5309
|
+
var FILE_ID2 = 1;
|
|
4817
5310
|
function jsxName(node) {
|
|
4818
5311
|
switch (node.type) {
|
|
4819
5312
|
case "JSXIdentifier":
|
|
@@ -4937,7 +5430,7 @@ function looksLikeJsx(id, code) {
|
|
|
4937
5430
|
|
|
4938
5431
|
// ../frontend-jsx/src/frontend-parse.ts
|
|
4939
5432
|
var import_parser = require("@babel/parser");
|
|
4940
|
-
function
|
|
5433
|
+
function doParse2(code, ctx) {
|
|
4941
5434
|
const diagnostics = [];
|
|
4942
5435
|
const doc = createDocument("jsx");
|
|
4943
5436
|
const backref = doc.backref;
|
|
@@ -4947,7 +5440,7 @@ function doParse(code, ctx) {
|
|
|
4947
5440
|
});
|
|
4948
5441
|
const eol = code.includes("\r\n") ? "\r\n" : "\n";
|
|
4949
5442
|
const sourceFile = {
|
|
4950
|
-
id:
|
|
5443
|
+
id: FILE_ID2,
|
|
4951
5444
|
path: ctx.id,
|
|
4952
5445
|
text: code,
|
|
4953
5446
|
frontend: "jsx",
|
|
@@ -4955,23 +5448,23 @@ function doParse(code, ctx) {
|
|
|
4955
5448
|
indentUnit: " ",
|
|
4956
5449
|
native: ast
|
|
4957
5450
|
};
|
|
4958
|
-
doc.sources.set(
|
|
5451
|
+
doc.sources.set(FILE_ID2, sourceFile);
|
|
4959
5452
|
const spanOf = (node) => {
|
|
4960
5453
|
if (node.start == null || node.end == null) return null;
|
|
4961
|
-
const
|
|
4962
|
-
file:
|
|
5454
|
+
const span2 = {
|
|
5455
|
+
file: FILE_ID2,
|
|
4963
5456
|
start: node.start,
|
|
4964
5457
|
end: node.end,
|
|
4965
5458
|
startLoc: node.loc ? { line: node.loc.start.line, column: node.loc.start.column } : void 0,
|
|
4966
5459
|
endLoc: node.loc ? { line: node.loc.end.line, column: node.loc.end.column } : void 0
|
|
4967
5460
|
};
|
|
4968
|
-
return
|
|
5461
|
+
return span2;
|
|
4969
5462
|
};
|
|
4970
5463
|
const sliceOf = (node) => node.start == null || node.end == null ? "" : code.slice(node.start, node.end);
|
|
4971
5464
|
const internExpr = (node, spread) => {
|
|
4972
5465
|
const payload = { text: sliceOf(node), spread };
|
|
4973
5466
|
return doc.exprs.intern({
|
|
4974
|
-
span: spanOf(node) ?? { file:
|
|
5467
|
+
span: spanOf(node) ?? { file: FILE_ID2, start: 0, end: 0 },
|
|
4975
5468
|
kind: exprKind(node),
|
|
4976
5469
|
payload
|
|
4977
5470
|
});
|
|
@@ -5017,7 +5510,7 @@ function doParse(code, ctx) {
|
|
|
5017
5510
|
}
|
|
5018
5511
|
return emptyClassList();
|
|
5019
5512
|
};
|
|
5020
|
-
const
|
|
5513
|
+
const staticTokensOf4 = (classes) => {
|
|
5021
5514
|
const out = [];
|
|
5022
5515
|
for (const seg of classes.segments) {
|
|
5023
5516
|
if (seg.kind === "static") for (const t of seg.tokens) out.push(t.value);
|
|
@@ -5095,7 +5588,7 @@ function doParse(code, ctx) {
|
|
|
5095
5588
|
doc.nodes.set(id, createFragment(id, { children, parent: parentId, span: spanOf(node) }));
|
|
5096
5589
|
backref.set(id, {
|
|
5097
5590
|
nodeId: id,
|
|
5098
|
-
span: spanOf(node) ?? { file:
|
|
5591
|
+
span: spanOf(node) ?? { file: FILE_ID2, start: 0, end: 0 },
|
|
5099
5592
|
openTagSpan: spanOf(node.openingFragment),
|
|
5100
5593
|
closeTagSpan: spanOf(node.closingFragment),
|
|
5101
5594
|
innerSpan: null,
|
|
@@ -5144,7 +5637,7 @@ function doParse(code, ctx) {
|
|
|
5144
5637
|
}
|
|
5145
5638
|
let computed2 = emptyStyleMap();
|
|
5146
5639
|
if (!classes.hasDynamic) {
|
|
5147
|
-
const tokens =
|
|
5640
|
+
const tokens = staticTokensOf4(classes);
|
|
5148
5641
|
if (tokens.length > 0) {
|
|
5149
5642
|
const res = ctx.resolver.resolve({
|
|
5150
5643
|
classes: tokens,
|
|
@@ -5177,13 +5670,13 @@ function doParse(code, ctx) {
|
|
|
5177
5670
|
});
|
|
5178
5671
|
doc.nodes.set(id, el);
|
|
5179
5672
|
const inner = children.length > 0 ? spanOf(node.children[0]) && spanOf(node.children.at(-1)) ? {
|
|
5180
|
-
file:
|
|
5673
|
+
file: FILE_ID2,
|
|
5181
5674
|
start: spanOf(node.children[0]).start,
|
|
5182
5675
|
end: spanOf(node.children.at(-1)).end
|
|
5183
5676
|
} : null : null;
|
|
5184
5677
|
backref.set(id, {
|
|
5185
5678
|
nodeId: id,
|
|
5186
|
-
span: spanOf(node) ?? { file:
|
|
5679
|
+
span: spanOf(node) ?? { file: FILE_ID2, start: 0, end: 0 },
|
|
5187
5680
|
openTagSpan: spanOf(opening),
|
|
5188
5681
|
closeTagSpan: node.closingElement ? spanOf(node.closingElement) : null,
|
|
5189
5682
|
innerSpan: inner,
|
|
@@ -5218,7 +5711,7 @@ var jsxFrontend = {
|
|
|
5218
5711
|
return looksLikeJsx(id, code);
|
|
5219
5712
|
},
|
|
5220
5713
|
parse(code, ctx) {
|
|
5221
|
-
return
|
|
5714
|
+
return doParse2(code, ctx);
|
|
5222
5715
|
}
|
|
5223
5716
|
};
|
|
5224
5717
|
function createJsxFrontend() {
|
|
@@ -5226,7 +5719,7 @@ function createJsxFrontend() {
|
|
|
5226
5719
|
}
|
|
5227
5720
|
|
|
5228
5721
|
// ../frontend-jsx/src/backend.ts
|
|
5229
|
-
var
|
|
5722
|
+
var import_magic_string2 = __toESM(require("magic-string"), 1);
|
|
5230
5723
|
var JSX_LANGS2 = ["jsx", "tsx"];
|
|
5231
5724
|
function exprText(doc, ref) {
|
|
5232
5725
|
const rec = doc.exprs.get(ref);
|
|
@@ -5240,20 +5733,20 @@ function exprText(doc, ref) {
|
|
|
5240
5733
|
}
|
|
5241
5734
|
return { text: "", spread: false };
|
|
5242
5735
|
}
|
|
5243
|
-
function
|
|
5736
|
+
function staticTokensOf3(classes) {
|
|
5244
5737
|
const out = [];
|
|
5245
5738
|
for (const seg of classes.segments) {
|
|
5246
5739
|
if (seg.kind === "static") for (const t of seg.tokens) out.push(t.value);
|
|
5247
5740
|
}
|
|
5248
5741
|
return out;
|
|
5249
5742
|
}
|
|
5250
|
-
function
|
|
5743
|
+
function primarySource2(doc) {
|
|
5251
5744
|
for (const sf of doc.sources.values()) {
|
|
5252
5745
|
if (typeof sf.text === "string" && sf.text.length > 0) return sf;
|
|
5253
5746
|
}
|
|
5254
5747
|
return null;
|
|
5255
5748
|
}
|
|
5256
|
-
function
|
|
5749
|
+
function collectKept2(doc) {
|
|
5257
5750
|
const out = [];
|
|
5258
5751
|
const seen = /* @__PURE__ */ new Set();
|
|
5259
5752
|
const visit = (id) => {
|
|
@@ -5267,15 +5760,15 @@ function collectKept(doc) {
|
|
|
5267
5760
|
visit(doc.root);
|
|
5268
5761
|
return out;
|
|
5269
5762
|
}
|
|
5270
|
-
function
|
|
5763
|
+
function strictlyContains2(a, b) {
|
|
5271
5764
|
if (a.file !== b.file) return false;
|
|
5272
5765
|
if (a.start <= b.start && b.end <= a.end) return !(a.start === b.start && a.end === b.end);
|
|
5273
5766
|
return false;
|
|
5274
5767
|
}
|
|
5275
|
-
function
|
|
5768
|
+
function editClasses2(ms, doc, sf, el) {
|
|
5276
5769
|
const classes = el.classes;
|
|
5277
5770
|
if (classes.hasDynamic || classes.opaque) return false;
|
|
5278
|
-
const tokens =
|
|
5771
|
+
const tokens = staticTokensOf3(classes);
|
|
5279
5772
|
const valueSpan = classes.valueSpan;
|
|
5280
5773
|
if (valueSpan && valueSpan.file === sf.id) {
|
|
5281
5774
|
const current = sf.text.slice(valueSpan.start, valueSpan.end);
|
|
@@ -5339,10 +5832,10 @@ function transferKeyOnUnwrap(ms, doc, sf, region, kept) {
|
|
|
5339
5832
|
const inside = [];
|
|
5340
5833
|
for (const n of kept) {
|
|
5341
5834
|
if (n.kind !== "element" || !n.span || n.span.file !== sf.id) continue;
|
|
5342
|
-
if (
|
|
5835
|
+
if (strictlyContains2(region.span, n.span)) inside.push(n);
|
|
5343
5836
|
}
|
|
5344
5837
|
const maximal = inside.filter(
|
|
5345
|
-
(n) => !inside.some((o) => o !== n && o.span && n.span &&
|
|
5838
|
+
(n) => !inside.some((o) => o !== n && o.span && n.span && strictlyContains2(o.span, n.span))
|
|
5346
5839
|
);
|
|
5347
5840
|
if (maximal.length !== 1) return;
|
|
5348
5841
|
const child = maximal[0];
|
|
@@ -5351,25 +5844,25 @@ function transferKeyOnUnwrap(ms, doc, sf, region, kept) {
|
|
|
5351
5844
|
if (extractKeyAttr(sf.text.slice(childOpen.start, childOpen.end))) return;
|
|
5352
5845
|
ms.appendLeft(childOpen.start + 1 + child.tag.length, ` ${keyAttr}`);
|
|
5353
5846
|
}
|
|
5354
|
-
function
|
|
5355
|
-
const sf =
|
|
5847
|
+
function surgicalPrint2(doc) {
|
|
5848
|
+
const sf = primarySource2(doc);
|
|
5356
5849
|
if (!sf) return null;
|
|
5357
|
-
const ms = new
|
|
5358
|
-
const kept =
|
|
5850
|
+
const ms = new import_magic_string2.default(sf.text);
|
|
5851
|
+
const kept = collectKept2(doc);
|
|
5359
5852
|
const keptSpans = [];
|
|
5360
5853
|
for (const n of kept) if (n.span && n.span.file === sf.id) keptSpans.push(n.span);
|
|
5361
5854
|
const removed = [];
|
|
5362
|
-
for (const id of
|
|
5855
|
+
for (const id of backrefIds2(doc)) {
|
|
5363
5856
|
if (doc.nodes.has(id)) continue;
|
|
5364
5857
|
const back = doc.backref.get(id);
|
|
5365
5858
|
if (!back || back.span.file !== sf.id) continue;
|
|
5366
|
-
const unwrapped = keptSpans.some((k) =>
|
|
5859
|
+
const unwrapped = keptSpans.some((k) => strictlyContains2(back.span, k));
|
|
5367
5860
|
removed.push({ backref: back, unwrapped });
|
|
5368
5861
|
}
|
|
5369
5862
|
const fullRemovals = removed.filter((r) => !r.unwrapped).map((r) => r.backref.span);
|
|
5370
5863
|
for (const r of removed) {
|
|
5371
|
-
const
|
|
5372
|
-
const coveredByFull = fullRemovals.some((f) => f !==
|
|
5864
|
+
const span2 = r.backref.span;
|
|
5865
|
+
const coveredByFull = fullRemovals.some((f) => f !== span2 && strictlyContains2(f, span2));
|
|
5373
5866
|
if (coveredByFull) continue;
|
|
5374
5867
|
if (r.unwrapped) {
|
|
5375
5868
|
transferKeyOnUnwrap(ms, doc, sf, r.backref, kept);
|
|
@@ -5380,15 +5873,15 @@ function surgicalPrint(doc) {
|
|
|
5380
5873
|
ms.remove(close.start, close.end);
|
|
5381
5874
|
}
|
|
5382
5875
|
} else {
|
|
5383
|
-
ms.remove(
|
|
5876
|
+
ms.remove(span2.start, span2.end);
|
|
5384
5877
|
}
|
|
5385
5878
|
}
|
|
5386
5879
|
for (const n of kept) {
|
|
5387
|
-
if (n.kind === "element")
|
|
5880
|
+
if (n.kind === "element") editClasses2(ms, doc, sf, n);
|
|
5388
5881
|
}
|
|
5389
5882
|
return ms.toString();
|
|
5390
5883
|
}
|
|
5391
|
-
function
|
|
5884
|
+
function backrefIds2(doc) {
|
|
5392
5885
|
const out = [];
|
|
5393
5886
|
const max = doc.alloc.peek;
|
|
5394
5887
|
for (let i = 1; i < max; i += 1) {
|
|
@@ -5403,7 +5896,7 @@ function classText(doc, classes) {
|
|
|
5403
5896
|
if (dynamic && dynamic.kind === "dynamic") {
|
|
5404
5897
|
return `className={${exprText(doc, dynamic.expr).text}}`;
|
|
5405
5898
|
}
|
|
5406
|
-
const tokens =
|
|
5899
|
+
const tokens = staticTokensOf3(classes);
|
|
5407
5900
|
return `className="${tokens.join(" ")}"`;
|
|
5408
5901
|
}
|
|
5409
5902
|
function attrText(doc, name, value) {
|
|
@@ -5456,15 +5949,15 @@ function rePrint(doc) {
|
|
|
5456
5949
|
if (!root || root.kind !== "fragment") return printNode(doc, doc.root);
|
|
5457
5950
|
return root.children.map((c) => printNode(doc, c)).join("");
|
|
5458
5951
|
}
|
|
5459
|
-
function
|
|
5460
|
-
const surgical =
|
|
5952
|
+
function doPrint2(doc) {
|
|
5953
|
+
const surgical = surgicalPrint2(doc);
|
|
5461
5954
|
return surgical ?? rePrint(doc);
|
|
5462
5955
|
}
|
|
5463
5956
|
var jsxBackend = {
|
|
5464
5957
|
name: "babel-jsx",
|
|
5465
5958
|
langs: JSX_LANGS2,
|
|
5466
5959
|
print(doc, _plan, _ctx) {
|
|
5467
|
-
const code =
|
|
5960
|
+
const code = doPrint2(doc);
|
|
5468
5961
|
return { code, map: null, edits: [], diagnostics: [] };
|
|
5469
5962
|
}
|
|
5470
5963
|
};
|
|
@@ -5479,6 +5972,11 @@ function jsxKindOf(id) {
|
|
|
5479
5972
|
if (clean.endsWith(".jsx")) return "jsx";
|
|
5480
5973
|
return null;
|
|
5481
5974
|
}
|
|
5975
|
+
function htmlKindOf(id) {
|
|
5976
|
+
const clean = (id.split("?", 1)[0] ?? id).toLowerCase();
|
|
5977
|
+
if (clean.endsWith(".html") || clean.endsWith(".htm")) return "html";
|
|
5978
|
+
return null;
|
|
5979
|
+
}
|
|
5482
5980
|
function eolOf2(doc) {
|
|
5483
5981
|
for (const src of doc.sources.values()) return src.eol;
|
|
5484
5982
|
return "\n";
|
|
@@ -5546,9 +6044,51 @@ function runJsxPipeline(code, id, kind, resolver, patterns, safety) {
|
|
|
5546
6044
|
const { doc: optimized } = runPasses(doc, passes, ctx);
|
|
5547
6045
|
return finishPipeline(optimized, id, resolver);
|
|
5548
6046
|
}
|
|
6047
|
+
function prepareHtml(code, id, resolver, patterns, safety, gate) {
|
|
6048
|
+
const parsed = createHtmlFrontend().parse(code, {
|
|
6049
|
+
id,
|
|
6050
|
+
kind: "html",
|
|
6051
|
+
resolver,
|
|
6052
|
+
normalizer,
|
|
6053
|
+
config: {},
|
|
6054
|
+
onDiagnostic: () => {
|
|
6055
|
+
}
|
|
6056
|
+
});
|
|
6057
|
+
const doc = parsed.doc;
|
|
6058
|
+
const ctx = {
|
|
6059
|
+
doc,
|
|
6060
|
+
safetyCeiling: safety,
|
|
6061
|
+
normalizer,
|
|
6062
|
+
selectors: buildSelectorIndex(doc, resolver),
|
|
6063
|
+
resolver,
|
|
6064
|
+
gate
|
|
6065
|
+
};
|
|
6066
|
+
return { doc, ctx, passes: buildPasses(patterns) };
|
|
6067
|
+
}
|
|
6068
|
+
function finishHtmlPipeline(optimized, id, resolver) {
|
|
6069
|
+
syncClassesFromComputed(optimized, resolver, normalizer);
|
|
6070
|
+
const printed = createHtmlBackend().print(
|
|
6071
|
+
optimized,
|
|
6072
|
+
{ moduleId: id, ops: [], provenance: /* @__PURE__ */ new Map() },
|
|
6073
|
+
{
|
|
6074
|
+
normalizer,
|
|
6075
|
+
resolver,
|
|
6076
|
+
sink: createSyntheticSink(),
|
|
6077
|
+
eol: eolOf2(optimized),
|
|
6078
|
+
onDiagnostic: () => {
|
|
6079
|
+
}
|
|
6080
|
+
}
|
|
6081
|
+
);
|
|
6082
|
+
return printed.code;
|
|
6083
|
+
}
|
|
6084
|
+
function runHtmlPipeline(code, id, resolver, patterns, safety) {
|
|
6085
|
+
const { doc, ctx, passes } = prepareHtml(code, id, resolver, patterns, safety, "provably-safe");
|
|
6086
|
+
const { doc: optimized } = runPasses(doc, passes, ctx);
|
|
6087
|
+
return finishHtmlPipeline(optimized, id, resolver);
|
|
6088
|
+
}
|
|
5549
6089
|
|
|
5550
6090
|
// src/index.ts
|
|
5551
|
-
var DEFAULT_INCLUDE = [".jsx", ".tsx", ".html"];
|
|
6091
|
+
var DEFAULT_INCLUDE = [".jsx", ".tsx", ".html", ".htm"];
|
|
5552
6092
|
function resolveOptions(options) {
|
|
5553
6093
|
return {
|
|
5554
6094
|
provider: options.provider ?? "auto",
|
|
@@ -5584,9 +6124,15 @@ function createDomflax(options = {}) {
|
|
|
5584
6124
|
transform(code, id) {
|
|
5585
6125
|
if (!isSupported(id, resolved.include)) return { code, map: null };
|
|
5586
6126
|
const kind = jsxKindOf(id);
|
|
5587
|
-
if (kind
|
|
5588
|
-
|
|
5589
|
-
|
|
6127
|
+
if (kind !== null) {
|
|
6128
|
+
const out = runJsxPipeline(code, id, kind, getResolver(), patterns, resolved.safety);
|
|
6129
|
+
return { code: out, map: null };
|
|
6130
|
+
}
|
|
6131
|
+
if (htmlKindOf(id) !== null) {
|
|
6132
|
+
const out = runHtmlPipeline(code, id, getResolver(), patterns, resolved.safety);
|
|
6133
|
+
return { code: out, map: null };
|
|
6134
|
+
}
|
|
6135
|
+
return { code, map: null };
|
|
5590
6136
|
}
|
|
5591
6137
|
};
|
|
5592
6138
|
}
|