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/webpack-loader.cjs
CHANGED
|
@@ -107,6 +107,7 @@ function defaultMeta(safetyFloor = 0) {
|
|
|
107
107
|
declaresCustomProperties: false,
|
|
108
108
|
whitespaceSensitive: false,
|
|
109
109
|
touched: false,
|
|
110
|
+
styleDirty: false,
|
|
110
111
|
synthetic: false,
|
|
111
112
|
safetyFloor
|
|
112
113
|
};
|
|
@@ -287,6 +288,14 @@ function markTouched(state, id) {
|
|
|
287
288
|
state.touched.add(id);
|
|
288
289
|
}
|
|
289
290
|
}
|
|
291
|
+
function markStyleDirty(state, id) {
|
|
292
|
+
const n = state.doc.nodes.get(id);
|
|
293
|
+
if (n) {
|
|
294
|
+
n.meta.touched = true;
|
|
295
|
+
n.meta.styleDirty = true;
|
|
296
|
+
state.touched.add(id);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
290
299
|
function removeSubtree(state, id) {
|
|
291
300
|
const node = state.doc.nodes.get(id);
|
|
292
301
|
if (!node) return;
|
|
@@ -578,7 +587,7 @@ function applyOne(state, op) {
|
|
|
578
587
|
return [precond(op, op.target, "setClassList target is not an element")];
|
|
579
588
|
}
|
|
580
589
|
el.computed = cloneStyleMap(op.style);
|
|
581
|
-
|
|
590
|
+
markStyleDirty(state, op.target);
|
|
582
591
|
return [];
|
|
583
592
|
}
|
|
584
593
|
case "mergeStyle": {
|
|
@@ -601,7 +610,7 @@ function applyOne(state, op) {
|
|
|
601
610
|
const src = doc.nodes.get(op.source);
|
|
602
611
|
if (src) markTouched(state, op.source);
|
|
603
612
|
}
|
|
604
|
-
|
|
613
|
+
markStyleDirty(state, op.target);
|
|
605
614
|
return [];
|
|
606
615
|
}
|
|
607
616
|
case "foldInheritedStyles":
|
|
@@ -652,7 +661,7 @@ function applyFold(state, op) {
|
|
|
652
661
|
}
|
|
653
662
|
if (folded) {
|
|
654
663
|
into.computed = { blocks: nextBlocks };
|
|
655
|
-
|
|
664
|
+
markStyleDirty(state, intoId);
|
|
656
665
|
}
|
|
657
666
|
}
|
|
658
667
|
for (const d of issues) state.diagnostics.push(d);
|
|
@@ -912,8 +921,123 @@ function buildMatchContext(doc, elementId, resolver, selectors, safety, phase, i
|
|
|
912
921
|
var DISPLAY = "display";
|
|
913
922
|
var POSITION = "position";
|
|
914
923
|
var TRANSFORM = "transform";
|
|
924
|
+
var ALIGN_ITEMS = "align-items";
|
|
925
|
+
var JUSTIFY_CONTENT = "justify-content";
|
|
926
|
+
var JUSTIFY_ITEMS = "justify-items";
|
|
927
|
+
var PLACE_ITEMS = "place-items";
|
|
928
|
+
var PLACE_SELF = "place-self";
|
|
915
929
|
var CONTEXT_SAFE_DISPLAYS = /* @__PURE__ */ new Set(["block", "contents", ""]);
|
|
916
930
|
var STATIC_POSITIONS = /* @__PURE__ */ new Set(["static", ""]);
|
|
931
|
+
var CENTERING_DISPLAYS = /* @__PURE__ */ new Set(["flex", "grid"]);
|
|
932
|
+
var GRID_PARENT_DISPLAYS = /* @__PURE__ */ new Set(["grid"]);
|
|
933
|
+
var STRETCHY_ITEM_ALIGN = /* @__PURE__ */ new Set(["normal", "stretch"]);
|
|
934
|
+
var PARENT_ITEMS_ALIGN_PROPS = [ALIGN_ITEMS, JUSTIFY_ITEMS, PLACE_ITEMS];
|
|
935
|
+
function isBaseCondition(block) {
|
|
936
|
+
const c = block.condition;
|
|
937
|
+
return c.media === "" && c.states.length === 0 && c.pseudoElement === "";
|
|
938
|
+
}
|
|
939
|
+
function baseValue(sm, prop) {
|
|
940
|
+
for (const block of sm.blocks.values()) {
|
|
941
|
+
if (!isBaseCondition(block)) continue;
|
|
942
|
+
const d = block.decls.get(prop);
|
|
943
|
+
return d ? String(d.value) : null;
|
|
944
|
+
}
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
function parentIsFillingGrid(before, wrapper, norm) {
|
|
948
|
+
if (wrapper.parent == null) return false;
|
|
949
|
+
const p = before.nodes.get(wrapper.parent);
|
|
950
|
+
if (!p || p.kind !== "element") return false;
|
|
951
|
+
const pc2 = norm.normalizeStyleMap(p.computed);
|
|
952
|
+
let baseIsGrid = false;
|
|
953
|
+
for (const block of pc2.blocks.values()) {
|
|
954
|
+
const disp = block.decls.get(DISPLAY);
|
|
955
|
+
if (disp) {
|
|
956
|
+
if (!GRID_PARENT_DISPLAYS.has(String(disp.value))) return false;
|
|
957
|
+
if (isBaseCondition(block)) baseIsGrid = true;
|
|
958
|
+
}
|
|
959
|
+
for (const prop of PARENT_ITEMS_ALIGN_PROPS) {
|
|
960
|
+
const d = block.decls.get(prop);
|
|
961
|
+
if (d && !STRETCHY_ITEM_ALIGN.has(String(d.value))) return false;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
return baseIsGrid;
|
|
965
|
+
}
|
|
966
|
+
function wrapperHasOnlyCenteringStyle(wrapperComputed, childComputed, norm) {
|
|
967
|
+
for (const block of wrapperComputed.blocks.values()) {
|
|
968
|
+
const base = isBaseCondition(block);
|
|
969
|
+
const ck = conditionKey(block.condition);
|
|
970
|
+
for (const [prop, decl] of block.decls) {
|
|
971
|
+
const val = String(decl.value);
|
|
972
|
+
if (prop === DISPLAY) {
|
|
973
|
+
if (base && CENTERING_DISPLAYS.has(val)) continue;
|
|
974
|
+
return false;
|
|
975
|
+
}
|
|
976
|
+
if (prop === ALIGN_ITEMS) {
|
|
977
|
+
if (base && val === "center") continue;
|
|
978
|
+
return false;
|
|
979
|
+
}
|
|
980
|
+
if (prop === JUSTIFY_CONTENT) {
|
|
981
|
+
if (base && val === "center") continue;
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
if (prop === POSITION) {
|
|
985
|
+
if (STATIC_POSITIONS.has(val)) continue;
|
|
986
|
+
return false;
|
|
987
|
+
}
|
|
988
|
+
if (prop === TRANSFORM) {
|
|
989
|
+
if (val === "none") continue;
|
|
990
|
+
return false;
|
|
991
|
+
}
|
|
992
|
+
if (isInherited2(decl, norm)) continue;
|
|
993
|
+
if (childReproduces(childComputed, ck, prop, val)) continue;
|
|
994
|
+
return false;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return true;
|
|
998
|
+
}
|
|
999
|
+
function wrapperCentersSingleElement(before, wrapper) {
|
|
1000
|
+
let elements = 0;
|
|
1001
|
+
for (const cid of wrapper.children) {
|
|
1002
|
+
const n = before.nodes.get(cid);
|
|
1003
|
+
if (!n) continue;
|
|
1004
|
+
if (n.kind === "element") {
|
|
1005
|
+
elements += 1;
|
|
1006
|
+
continue;
|
|
1007
|
+
}
|
|
1008
|
+
if (n.kind === "comment") continue;
|
|
1009
|
+
if (n.kind === "text" && n.value.trim() === "") continue;
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
return elements === 1;
|
|
1013
|
+
}
|
|
1014
|
+
function childHasSelfAlign(childBefore, norm) {
|
|
1015
|
+
if (!childBefore) return false;
|
|
1016
|
+
const sm = norm.normalizeStyleMap(childBefore);
|
|
1017
|
+
for (const block of sm.blocks.values()) {
|
|
1018
|
+
for (const prop of SELF_ALIGN_PROPS) {
|
|
1019
|
+
const d = block.decls.get(prop);
|
|
1020
|
+
if (d && !NEUTRAL_ALIGN.has(String(d.value))) return true;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
function childGainsPlaceSelfCenter(childAfter) {
|
|
1026
|
+
if (baseValue(childAfter, PLACE_SELF) === "center") return true;
|
|
1027
|
+
return baseValue(childAfter, "align-self") === "center" && baseValue(childAfter, "justify-self") === "center";
|
|
1028
|
+
}
|
|
1029
|
+
function isContextCompensatedCentering(before, wrapper, wrapperComputed, childBefore, childAfter, norm) {
|
|
1030
|
+
if (!childAfter) return false;
|
|
1031
|
+
if (!CENTERING_DISPLAYS.has(baseValue(wrapperComputed, DISPLAY) ?? "")) return false;
|
|
1032
|
+
if (baseValue(wrapperComputed, ALIGN_ITEMS) !== "center") return false;
|
|
1033
|
+
if (baseValue(wrapperComputed, JUSTIFY_CONTENT) !== "center") return false;
|
|
1034
|
+
const childAfterNorm = norm.normalizeStyleMap(childAfter);
|
|
1035
|
+
if (!childGainsPlaceSelfCenter(childAfterNorm)) return false;
|
|
1036
|
+
if (!wrapperHasOnlyCenteringStyle(wrapperComputed, childAfterNorm, norm)) return false;
|
|
1037
|
+
if (!wrapperCentersSingleElement(before, wrapper)) return false;
|
|
1038
|
+
if (childHasSelfAlign(childBefore, norm)) return false;
|
|
1039
|
+
return parentIsFillingGrid(before, wrapper, norm);
|
|
1040
|
+
}
|
|
917
1041
|
var SELF_ALIGN_PROPS = [
|
|
918
1042
|
"place-self",
|
|
919
1043
|
"align-self",
|
|
@@ -1013,6 +1137,9 @@ function classifyFlattenOps(before, after, ops, norm) {
|
|
|
1013
1137
|
const wrapperComputed = norm.normalizeStyleMap(wrapper.computed);
|
|
1014
1138
|
const childAfter = childId != null ? getElement(after, childId)?.computed ?? null : null;
|
|
1015
1139
|
const childBefore = childId != null ? getElement(before, childId)?.computed ?? null : null;
|
|
1140
|
+
if (isContextCompensatedCentering(before, wrapper, wrapperComputed, childBefore, childAfter, norm)) {
|
|
1141
|
+
return { kind: "provably-safe", wrapperId, childId };
|
|
1142
|
+
}
|
|
1016
1143
|
if (establishesChildContext(wrapperComputed)) {
|
|
1017
1144
|
return { kind: "needs-verification", wrapperId, childId };
|
|
1018
1145
|
}
|
|
@@ -1441,15 +1568,34 @@ function sameTokens(a, b) {
|
|
|
1441
1568
|
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
|
|
1442
1569
|
return true;
|
|
1443
1570
|
}
|
|
1571
|
+
function residualStyle(computed2, covered, norm) {
|
|
1572
|
+
const cov = norm.normalizeStyleMap(covered);
|
|
1573
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
1574
|
+
for (const [key, block] of norm.normalizeStyleMap(computed2).blocks) {
|
|
1575
|
+
const covBlock = cov.blocks.get(key);
|
|
1576
|
+
const decls = /* @__PURE__ */ new Map();
|
|
1577
|
+
for (const [prop, decl] of block.decls) {
|
|
1578
|
+
const covDecl = covBlock?.decls.get(prop);
|
|
1579
|
+
if (covDecl && covDecl.value === decl.value && covDecl.important === decl.important) continue;
|
|
1580
|
+
decls.set(prop, decl);
|
|
1581
|
+
}
|
|
1582
|
+
if (decls.size > 0) blocks.set(key, { condition: block.condition, decls });
|
|
1583
|
+
}
|
|
1584
|
+
return { blocks };
|
|
1585
|
+
}
|
|
1444
1586
|
function syncClassesFromComputed(doc, resolver, norm) {
|
|
1445
1587
|
const sink = createSyntheticSink();
|
|
1446
1588
|
for (const id of elementIds(doc)) {
|
|
1447
1589
|
const el = getElement(doc, id);
|
|
1448
|
-
if (!el
|
|
1590
|
+
if (!el) continue;
|
|
1591
|
+
if (!el.meta.styleDirty) continue;
|
|
1449
1592
|
if (el.classes.opaque || el.classes.hasDynamic) continue;
|
|
1450
1593
|
const tokens = staticTokensOf(el.classes);
|
|
1594
|
+
const retained = tokens.filter((t) => !resolver.selectorUsage(t).droppable);
|
|
1595
|
+
const covered = retained.length > 0 ? resolver.resolve({ classes: retained }).styles : null;
|
|
1596
|
+
const target = covered ? residualStyle(el.computed, covered, norm) : el.computed;
|
|
1451
1597
|
const ctx = { normalizer: norm, sink };
|
|
1452
|
-
const emitted = resolver.emit(
|
|
1598
|
+
const emitted = resolver.emit(target, ctx).classes;
|
|
1453
1599
|
if (emitted.length === 0) continue;
|
|
1454
1600
|
const emittedSet = new Set(emitted);
|
|
1455
1601
|
const next = [];
|
|
@@ -2161,19 +2307,28 @@ var flexCenterWrapper = definePattern({
|
|
|
2161
2307
|
flattenInto: "child",
|
|
2162
2308
|
childGains: { placeSelf: "center" }
|
|
2163
2309
|
},
|
|
2164
|
-
// Collapsing a flex-centering wrapper to `place-self:center` on the child
|
|
2165
|
-
// the child's NEW parent is
|
|
2166
|
-
//
|
|
2167
|
-
//
|
|
2168
|
-
//
|
|
2169
|
-
// unwrap, opacity-barrier safety) is
|
|
2310
|
+
// Collapsing a flex-centering wrapper to `place-self:center` on the child is render-identical ONLY
|
|
2311
|
+
// when the child's NEW parent is a statically-known GRID that lets the wrapper fill its area (there
|
|
2312
|
+
// `place-self`'s align-self AND justify-self both take effect). Under that ONE context the flatten is
|
|
2313
|
+
// classified `provably-safe` and commits; under a flex/block/unknown parent — or when the wrapper
|
|
2314
|
+
// drops any own style — it stays `needs-verification` and the conservative production gate PRESERVES
|
|
2315
|
+
// it. Op-level correctness (purity, id-preserving unwrap, opacity-barrier safety) is additionally
|
|
2316
|
+
// asserted by the invariant suite over every pattern.
|
|
2170
2317
|
test: {
|
|
2318
|
+
cases: [
|
|
2319
|
+
{
|
|
2320
|
+
name: "grid parent \u2192 flattened (child gains place-self-center)",
|
|
2321
|
+
before: '<div className="grid"><div className="flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2322
|
+
after: '<div className="grid"><span className="bg-red-200 place-self-center">x</span></div>'
|
|
2323
|
+
}
|
|
2324
|
+
],
|
|
2171
2325
|
noMatch: [
|
|
2172
|
-
//
|
|
2173
|
-
// (the wrapper itself establishes a flex formatting context) → left unchanged.
|
|
2174
|
-
'<div className="grid"><div className="flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2175
|
-
// Non-flex/grid parent (document root): place-self centering would not hold → left unchanged.
|
|
2326
|
+
// Non-grid (flex) parent (document root): `justify-self` is ignored in flex → not provably safe.
|
|
2176
2327
|
'<div className="flex justify-center items-center"><div className="bg-red-200">Hello</div></div>',
|
|
2328
|
+
// Grid parent, but the wrapper drops padding when removed → not layout-neutral (rule 3).
|
|
2329
|
+
'<div className="grid"><div className="p-4 flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2330
|
+
// Grid parent forcing place-items-center: the wrapper would not fill its area → fill guard skips.
|
|
2331
|
+
'<div className="grid place-items-center"><div className="flex items-center justify-center"><span className="bg-red-200">x</span></div></div>',
|
|
2177
2332
|
// onClick is a hard opacity barrier → the wrapper is load-bearing regardless of the gate.
|
|
2178
2333
|
'<div className="flex justify-center items-center" onClick={handleClick}><div className="bg-red-200">Hello</div></div>'
|
|
2179
2334
|
]
|
|
@@ -3377,11 +3532,11 @@ var paddingShorthand = definePattern({
|
|
|
3377
3532
|
});
|
|
3378
3533
|
|
|
3379
3534
|
// ../patterns/src/library/compress/place-shorthand.pattern.ts
|
|
3380
|
-
var
|
|
3381
|
-
var
|
|
3382
|
-
var
|
|
3535
|
+
var ALIGN_ITEMS2 = "align-items";
|
|
3536
|
+
var JUSTIFY_ITEMS2 = "justify-items";
|
|
3537
|
+
var PLACE_ITEMS2 = "place-items";
|
|
3383
3538
|
var ALIGN_CONTENT = "align-content";
|
|
3384
|
-
var
|
|
3539
|
+
var JUSTIFY_CONTENT2 = "justify-content";
|
|
3385
3540
|
var PLACE_CONTENT = "place-content";
|
|
3386
3541
|
var BASE_KEY8 = conditionKey(BASE_CONDITION);
|
|
3387
3542
|
function samePair(a, b) {
|
|
@@ -3421,21 +3576,21 @@ var placeShorthand = definePattern({
|
|
|
3421
3576
|
rewriteClasses(computed2) {
|
|
3422
3577
|
const base = computed2.blocks.get(BASE_KEY8);
|
|
3423
3578
|
if (!base) return null;
|
|
3424
|
-
const alignItems = base.decls.get(
|
|
3425
|
-
const justifyItems = base.decls.get(
|
|
3579
|
+
const alignItems = base.decls.get(ALIGN_ITEMS2);
|
|
3580
|
+
const justifyItems = base.decls.get(JUSTIFY_ITEMS2);
|
|
3426
3581
|
const alignContent = base.decls.get(ALIGN_CONTENT);
|
|
3427
|
-
const justifyContent = base.decls.get(
|
|
3582
|
+
const justifyContent = base.decls.get(JUSTIFY_CONTENT2);
|
|
3428
3583
|
const next = new Map(base.decls);
|
|
3429
3584
|
let collapsed = false;
|
|
3430
3585
|
if (samePair(alignItems, justifyItems)) {
|
|
3431
|
-
next.delete(
|
|
3432
|
-
next.delete(
|
|
3433
|
-
next.set(
|
|
3586
|
+
next.delete(ALIGN_ITEMS2);
|
|
3587
|
+
next.delete(JUSTIFY_ITEMS2);
|
|
3588
|
+
next.set(PLACE_ITEMS2, placeDecl(PLACE_ITEMS2, alignItems));
|
|
3434
3589
|
collapsed = true;
|
|
3435
3590
|
}
|
|
3436
3591
|
if (samePair(alignContent, justifyContent)) {
|
|
3437
3592
|
next.delete(ALIGN_CONTENT);
|
|
3438
|
-
next.delete(
|
|
3593
|
+
next.delete(JUSTIFY_CONTENT2);
|
|
3439
3594
|
next.set(PLACE_CONTENT, placeDecl(PLACE_CONTENT, alignContent));
|
|
3440
3595
|
collapsed = true;
|
|
3441
3596
|
}
|
|
@@ -4624,11 +4779,349 @@ function createCssResolver(cssFiles = [], options) {
|
|
|
4624
4779
|
var import_node_path = require("path");
|
|
4625
4780
|
var import_node_url = require("url");
|
|
4626
4781
|
|
|
4782
|
+
// ../frontend-html/src/backend.ts
|
|
4783
|
+
var import_magic_string = __toESM(require("magic-string"), 1);
|
|
4784
|
+
function staticTokensOf2(classes) {
|
|
4785
|
+
const out = [];
|
|
4786
|
+
for (const seg of classes.segments) {
|
|
4787
|
+
if (seg.kind === "static") for (const t of seg.tokens) out.push(t.value);
|
|
4788
|
+
}
|
|
4789
|
+
return out;
|
|
4790
|
+
}
|
|
4791
|
+
function sameTokens2(a, b) {
|
|
4792
|
+
if (a.length !== b.length) return false;
|
|
4793
|
+
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
|
|
4794
|
+
return true;
|
|
4795
|
+
}
|
|
4796
|
+
function primarySource(doc) {
|
|
4797
|
+
for (const sf of doc.sources.values()) {
|
|
4798
|
+
if (typeof sf.text === "string" && sf.text.length > 0) return sf;
|
|
4799
|
+
}
|
|
4800
|
+
return null;
|
|
4801
|
+
}
|
|
4802
|
+
function collectKept(doc) {
|
|
4803
|
+
const out = [];
|
|
4804
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4805
|
+
const visit = (id) => {
|
|
4806
|
+
if (seen.has(id)) return;
|
|
4807
|
+
seen.add(id);
|
|
4808
|
+
const n = doc.nodes.get(id);
|
|
4809
|
+
if (!n) return;
|
|
4810
|
+
out.push(n);
|
|
4811
|
+
if (n.kind === "element" || n.kind === "fragment") for (const c of n.children) visit(c);
|
|
4812
|
+
};
|
|
4813
|
+
visit(doc.root);
|
|
4814
|
+
return out;
|
|
4815
|
+
}
|
|
4816
|
+
function strictlyContains(a, b) {
|
|
4817
|
+
if (a.file !== b.file) return false;
|
|
4818
|
+
if (a.start <= b.start && b.end <= a.end) return !(a.start === b.start && a.end === b.end);
|
|
4819
|
+
return false;
|
|
4820
|
+
}
|
|
4821
|
+
function backrefIds(doc) {
|
|
4822
|
+
const out = [];
|
|
4823
|
+
const max = doc.alloc.peek;
|
|
4824
|
+
for (let i = 1; i < max; i += 1) {
|
|
4825
|
+
const id = i;
|
|
4826
|
+
if (doc.backref.get(id)) out.push(id);
|
|
4827
|
+
}
|
|
4828
|
+
return out;
|
|
4829
|
+
}
|
|
4830
|
+
function currentTokens(sf, valueSpan) {
|
|
4831
|
+
const raw = sf.text.slice(valueSpan.start, valueSpan.end).trim();
|
|
4832
|
+
const unquoted = raw.replace(/^['"]/, "").replace(/['"]$/, "");
|
|
4833
|
+
return unquoted.split(/\s+/).filter((t) => t.length > 0);
|
|
4834
|
+
}
|
|
4835
|
+
function editClasses(ms, doc, sf, el) {
|
|
4836
|
+
const classes = el.classes;
|
|
4837
|
+
if (classes.hasDynamic || classes.opaque) return false;
|
|
4838
|
+
const tokens = staticTokensOf2(classes);
|
|
4839
|
+
const valueSpan = classes.valueSpan;
|
|
4840
|
+
if (valueSpan && valueSpan.file === sf.id) {
|
|
4841
|
+
if (sameTokens2(currentTokens(sf, valueSpan), tokens)) return false;
|
|
4842
|
+
const current = sf.text.slice(valueSpan.start, valueSpan.end).trim();
|
|
4843
|
+
const quote = current.startsWith("'") ? "'" : '"';
|
|
4844
|
+
ms.overwrite(valueSpan.start, valueSpan.end, `${quote}${tokens.join(" ")}${quote}`);
|
|
4845
|
+
return true;
|
|
4846
|
+
}
|
|
4847
|
+
if (tokens.length === 0) return false;
|
|
4848
|
+
const openTag = doc.backref.get(el.id)?.openTagSpan;
|
|
4849
|
+
if (!openTag || openTag.file !== sf.id) return false;
|
|
4850
|
+
ms.appendLeft(openTag.start + 1 + el.tag.length, ` class="${tokens.join(" ")}"`);
|
|
4851
|
+
return true;
|
|
4852
|
+
}
|
|
4853
|
+
function surgicalPrint(doc) {
|
|
4854
|
+
const sf = primarySource(doc);
|
|
4855
|
+
if (!sf) return null;
|
|
4856
|
+
const ms = new import_magic_string.default(sf.text);
|
|
4857
|
+
const kept = collectKept(doc);
|
|
4858
|
+
const keptSpans = [];
|
|
4859
|
+
for (const n of kept) if (n.span && n.span.file === sf.id) keptSpans.push(n.span);
|
|
4860
|
+
const removed = [];
|
|
4861
|
+
for (const id of backrefIds(doc)) {
|
|
4862
|
+
if (doc.nodes.has(id)) continue;
|
|
4863
|
+
const back = doc.backref.get(id);
|
|
4864
|
+
if (!back || back.span.file !== sf.id) continue;
|
|
4865
|
+
const unwrapped = keptSpans.some((k) => strictlyContains(back.span, k));
|
|
4866
|
+
removed.push({ backref: back, unwrapped });
|
|
4867
|
+
}
|
|
4868
|
+
const fullRemovals = removed.filter((r) => !r.unwrapped).map((r) => r.backref.span);
|
|
4869
|
+
for (const r of removed) {
|
|
4870
|
+
const s = r.backref.span;
|
|
4871
|
+
if (fullRemovals.some((f) => f !== s && strictlyContains(f, s))) continue;
|
|
4872
|
+
if (r.unwrapped) {
|
|
4873
|
+
const open = r.backref.openTagSpan;
|
|
4874
|
+
const close = r.backref.closeTagSpan;
|
|
4875
|
+
if (open && open.file === sf.id && open.end > open.start) ms.remove(open.start, open.end);
|
|
4876
|
+
if (close && close.file === sf.id && close.end > close.start) ms.remove(close.start, close.end);
|
|
4877
|
+
} else {
|
|
4878
|
+
ms.remove(s.start, s.end);
|
|
4879
|
+
}
|
|
4880
|
+
}
|
|
4881
|
+
for (const n of kept) if (n.kind === "element") editClasses(ms, doc, sf, n);
|
|
4882
|
+
return ms.toString();
|
|
4883
|
+
}
|
|
4884
|
+
function doPrint(doc) {
|
|
4885
|
+
return surgicalPrint(doc) ?? "";
|
|
4886
|
+
}
|
|
4887
|
+
|
|
4888
|
+
// ../frontend-html/src/parse.ts
|
|
4889
|
+
var import_node_module3 = require("module");
|
|
4890
|
+
|
|
4891
|
+
// ../frontend-html/src/walk.ts
|
|
4892
|
+
var HTML_LANGS = ["html"];
|
|
4893
|
+
var FILE_ID = 1;
|
|
4894
|
+
function looksLikeHtml(id, code) {
|
|
4895
|
+
if (/\.html?$/i.test(id)) return true;
|
|
4896
|
+
const head = code.slice(0, 256).trimStart().toLowerCase();
|
|
4897
|
+
return head.startsWith("<!doctype html") || head.startsWith("<html") || head.startsWith("<");
|
|
4898
|
+
}
|
|
4899
|
+
var OPAQUE_SUBTREE_TAGS = /* @__PURE__ */ new Set([
|
|
4900
|
+
"script",
|
|
4901
|
+
"style",
|
|
4902
|
+
"template",
|
|
4903
|
+
"svg",
|
|
4904
|
+
"pre",
|
|
4905
|
+
"textarea"
|
|
4906
|
+
]);
|
|
4907
|
+
function isOpaqueSubtreeTag(tag) {
|
|
4908
|
+
return OPAQUE_SUBTREE_TAGS.has(tag);
|
|
4909
|
+
}
|
|
4910
|
+
function elementIsOpaque(attrs) {
|
|
4911
|
+
for (const a of attrs) {
|
|
4912
|
+
const n = a.name.toLowerCase();
|
|
4913
|
+
if (n === "id" || n === "contenteditable") return true;
|
|
4914
|
+
if (n.startsWith("on")) return true;
|
|
4915
|
+
}
|
|
4916
|
+
return false;
|
|
4917
|
+
}
|
|
4918
|
+
function hasEventHandler(attrs) {
|
|
4919
|
+
for (const a of attrs) if (/^on/i.test(a.name)) return true;
|
|
4920
|
+
return false;
|
|
4921
|
+
}
|
|
4922
|
+
function span(start, end) {
|
|
4923
|
+
return { file: FILE_ID, start, end };
|
|
4924
|
+
}
|
|
4925
|
+
function attrsLocOf(loc) {
|
|
4926
|
+
if (!loc) return void 0;
|
|
4927
|
+
return loc.startTag?.attrs ?? loc.attrs;
|
|
4928
|
+
}
|
|
4929
|
+
function classValueSpan(loc, source) {
|
|
4930
|
+
const attrsLoc = attrsLocOf(loc);
|
|
4931
|
+
const cl = attrsLoc?.["class"];
|
|
4932
|
+
if (!cl) return null;
|
|
4933
|
+
const text = source.slice(cl.startOffset, cl.endOffset);
|
|
4934
|
+
const eq = text.indexOf("=");
|
|
4935
|
+
if (eq === -1) return null;
|
|
4936
|
+
let i = eq + 1;
|
|
4937
|
+
while (i < text.length && /\s/.test(text[i])) i += 1;
|
|
4938
|
+
if (i >= text.length) return null;
|
|
4939
|
+
return span(cl.startOffset + i, cl.endOffset);
|
|
4940
|
+
}
|
|
4941
|
+
|
|
4942
|
+
// ../frontend-html/src/parse.ts
|
|
4943
|
+
var cachedParse5 = null;
|
|
4944
|
+
function loadParse5() {
|
|
4945
|
+
if (cachedParse5) return cachedParse5;
|
|
4946
|
+
const req = (0, import_node_module3.createRequire)(importMetaUrl);
|
|
4947
|
+
cachedParse5 = req("parse5");
|
|
4948
|
+
return cachedParse5;
|
|
4949
|
+
}
|
|
4950
|
+
function doParse(code, ctx) {
|
|
4951
|
+
const diagnostics = [];
|
|
4952
|
+
const doc = createDocument("html");
|
|
4953
|
+
const backref = doc.backref;
|
|
4954
|
+
const parse5 = loadParse5();
|
|
4955
|
+
const document2 = parse5.parse(code, { sourceCodeLocationInfo: true });
|
|
4956
|
+
const eol = code.includes("\r\n") ? "\r\n" : "\n";
|
|
4957
|
+
const sourceFile = {
|
|
4958
|
+
id: FILE_ID,
|
|
4959
|
+
path: ctx.id,
|
|
4960
|
+
text: code,
|
|
4961
|
+
frontend: "html",
|
|
4962
|
+
eol,
|
|
4963
|
+
indentUnit: " ",
|
|
4964
|
+
native: document2
|
|
4965
|
+
};
|
|
4966
|
+
doc.sources.set(FILE_ID, sourceFile);
|
|
4967
|
+
const resolveComputed = (tokens, tag, nodeId) => {
|
|
4968
|
+
if (tokens.length === 0) return emptyStyleMap();
|
|
4969
|
+
const res = ctx.resolver.resolve({ classes: tokens, element: { tagName: tag, namespace: "html" } });
|
|
4970
|
+
for (const w of res.warnings) {
|
|
4971
|
+
diagnostics.push({
|
|
4972
|
+
code: "DF_STYLE_CONFLICT_UNRESOLVED",
|
|
4973
|
+
severity: w.severity,
|
|
4974
|
+
message: w.message,
|
|
4975
|
+
nodeId
|
|
4976
|
+
});
|
|
4977
|
+
}
|
|
4978
|
+
return ctx.normalizer.normalizeStyleMap(res.styles);
|
|
4979
|
+
};
|
|
4980
|
+
const splitTokens = (raw) => raw.split(/\s+/).filter((t) => t.length > 0);
|
|
4981
|
+
const appendChild = (node, parentId, out) => {
|
|
4982
|
+
const name = node.nodeName;
|
|
4983
|
+
if (name === "#text") {
|
|
4984
|
+
const value = node.value ?? "";
|
|
4985
|
+
const id = doc.alloc.next();
|
|
4986
|
+
const loc = node.sourceCodeLocation ?? null;
|
|
4987
|
+
doc.nodes.set(
|
|
4988
|
+
id,
|
|
4989
|
+
createText(id, value, {
|
|
4990
|
+
parent: parentId,
|
|
4991
|
+
span: loc ? span(loc.startOffset, loc.endOffset) : null,
|
|
4992
|
+
collapsible: /^\s*$/.test(value)
|
|
4993
|
+
})
|
|
4994
|
+
);
|
|
4995
|
+
out.push(id);
|
|
4996
|
+
return;
|
|
4997
|
+
}
|
|
4998
|
+
if (name === "#comment") {
|
|
4999
|
+
const id = doc.alloc.next();
|
|
5000
|
+
const loc = node.sourceCodeLocation ?? null;
|
|
5001
|
+
doc.nodes.set(
|
|
5002
|
+
id,
|
|
5003
|
+
createComment(id, node.data ?? "", {
|
|
5004
|
+
parent: parentId,
|
|
5005
|
+
span: loc ? span(loc.startOffset, loc.endOffset) : null
|
|
5006
|
+
})
|
|
5007
|
+
);
|
|
5008
|
+
out.push(id);
|
|
5009
|
+
return;
|
|
5010
|
+
}
|
|
5011
|
+
if (name === "#documentType") return;
|
|
5012
|
+
if (name.startsWith("#")) {
|
|
5013
|
+
for (const c of node.childNodes ?? []) appendChild(c, parentId, out);
|
|
5014
|
+
return;
|
|
5015
|
+
}
|
|
5016
|
+
out.push(buildElement(node, parentId));
|
|
5017
|
+
};
|
|
5018
|
+
const buildElement = (node, parentId) => {
|
|
5019
|
+
const id = doc.alloc.next();
|
|
5020
|
+
const tag = (node.tagName ?? node.nodeName).toLowerCase();
|
|
5021
|
+
const loc = node.sourceCodeLocation ?? null;
|
|
5022
|
+
const attrsArr = node.attrs ?? [];
|
|
5023
|
+
const opaqueSubtree = isOpaqueSubtreeTag(tag);
|
|
5024
|
+
const synthetic = loc == null;
|
|
5025
|
+
const opaque2 = opaqueSubtree || synthetic || elementIsOpaque(attrsArr);
|
|
5026
|
+
const meta = defaultMeta();
|
|
5027
|
+
meta.hasEventHandlers = hasEventHandler(attrsArr);
|
|
5028
|
+
meta.safetyFloor = opaque2 ? 0 : 3;
|
|
5029
|
+
let classes = emptyClassList();
|
|
5030
|
+
let classTokens = [];
|
|
5031
|
+
const entries = /* @__PURE__ */ new Map();
|
|
5032
|
+
const order = [];
|
|
5033
|
+
for (const a of attrsArr) {
|
|
5034
|
+
if (a.name.toLowerCase() === "class") {
|
|
5035
|
+
classTokens = splitTokens(a.value);
|
|
5036
|
+
const valueSpan = classValueSpan(loc, code);
|
|
5037
|
+
const clAttr = attrsLocOf(loc)?.["class"];
|
|
5038
|
+
const seg = {
|
|
5039
|
+
kind: "static",
|
|
5040
|
+
span: valueSpan ?? void 0,
|
|
5041
|
+
tokens: classTokens.map((value) => ({ value }))
|
|
5042
|
+
};
|
|
5043
|
+
classes = {
|
|
5044
|
+
form: "string-literal",
|
|
5045
|
+
segments: [seg],
|
|
5046
|
+
valueSpan,
|
|
5047
|
+
attrSpan: clAttr ? span(clAttr.startOffset, clAttr.endOffset) : void 0,
|
|
5048
|
+
hasDynamic: false,
|
|
5049
|
+
opaque: false,
|
|
5050
|
+
rewritable: valueSpan != null
|
|
5051
|
+
};
|
|
5052
|
+
continue;
|
|
5053
|
+
}
|
|
5054
|
+
const v = a.value;
|
|
5055
|
+
entries.set(a.name, { kind: "static", value: v === "" ? true : v });
|
|
5056
|
+
order.push(a.name);
|
|
5057
|
+
}
|
|
5058
|
+
const attrs = { entries, spreads: [], order };
|
|
5059
|
+
const computed2 = resolveComputed(classTokens, tag, id);
|
|
5060
|
+
const children = [];
|
|
5061
|
+
if (!opaqueSubtree) {
|
|
5062
|
+
for (const c of node.childNodes ?? []) appendChild(c, id, children);
|
|
5063
|
+
}
|
|
5064
|
+
const el = createElement(id, {
|
|
5065
|
+
tag,
|
|
5066
|
+
namespace: "html",
|
|
5067
|
+
isComponent: false,
|
|
5068
|
+
selfClosing: loc ? loc.endTag == null : false,
|
|
5069
|
+
classes,
|
|
5070
|
+
computed: computed2,
|
|
5071
|
+
attrs,
|
|
5072
|
+
children,
|
|
5073
|
+
parent: parentId,
|
|
5074
|
+
span: loc ? span(loc.startOffset, loc.endOffset) : null,
|
|
5075
|
+
meta
|
|
5076
|
+
});
|
|
5077
|
+
doc.nodes.set(id, el);
|
|
5078
|
+
if (loc) {
|
|
5079
|
+
backref.set(id, {
|
|
5080
|
+
nodeId: id,
|
|
5081
|
+
span: span(loc.startOffset, loc.endOffset),
|
|
5082
|
+
openTagSpan: loc.startTag ? span(loc.startTag.startOffset, loc.startTag.endOffset) : null,
|
|
5083
|
+
closeTagSpan: loc.endTag ? span(loc.endTag.startOffset, loc.endTag.endOffset) : null,
|
|
5084
|
+
innerSpan: null,
|
|
5085
|
+
selfClosing: loc.endTag == null
|
|
5086
|
+
});
|
|
5087
|
+
}
|
|
5088
|
+
return id;
|
|
5089
|
+
};
|
|
5090
|
+
const rootFrag = doc.nodes.get(doc.root);
|
|
5091
|
+
appendChild(document2, doc.root, rootFrag.children);
|
|
5092
|
+
return { doc, diagnostics };
|
|
5093
|
+
}
|
|
5094
|
+
|
|
5095
|
+
// ../frontend-html/src/index.ts
|
|
5096
|
+
var htmlFrontend = {
|
|
5097
|
+
name: "html",
|
|
5098
|
+
langs: HTML_LANGS,
|
|
5099
|
+
canParse(id, code) {
|
|
5100
|
+
return looksLikeHtml(id, code);
|
|
5101
|
+
},
|
|
5102
|
+
parse(code, ctx) {
|
|
5103
|
+
return doParse(code, ctx);
|
|
5104
|
+
}
|
|
5105
|
+
};
|
|
5106
|
+
function createHtmlFrontend() {
|
|
5107
|
+
return htmlFrontend;
|
|
5108
|
+
}
|
|
5109
|
+
var htmlBackend = {
|
|
5110
|
+
name: "html",
|
|
5111
|
+
langs: HTML_LANGS,
|
|
5112
|
+
print(doc, _plan, _ctx) {
|
|
5113
|
+
return { code: doPrint(doc), map: null, edits: [], diagnostics: [] };
|
|
5114
|
+
}
|
|
5115
|
+
};
|
|
5116
|
+
function createHtmlBackend() {
|
|
5117
|
+
return htmlBackend;
|
|
5118
|
+
}
|
|
5119
|
+
|
|
4627
5120
|
// ../frontend-jsx/src/frontend-ast.ts
|
|
4628
5121
|
var import_traverse = __toESM(require("@babel/traverse"), 1);
|
|
4629
5122
|
var traverse = typeof import_traverse.default === "function" ? import_traverse.default : import_traverse.default.default;
|
|
4630
5123
|
var JSX_LANGS = ["jsx", "tsx"];
|
|
4631
|
-
var
|
|
5124
|
+
var FILE_ID2 = 1;
|
|
4632
5125
|
function jsxName(node) {
|
|
4633
5126
|
switch (node.type) {
|
|
4634
5127
|
case "JSXIdentifier":
|
|
@@ -4752,7 +5245,7 @@ function looksLikeJsx(id, code) {
|
|
|
4752
5245
|
|
|
4753
5246
|
// ../frontend-jsx/src/frontend-parse.ts
|
|
4754
5247
|
var import_parser = require("@babel/parser");
|
|
4755
|
-
function
|
|
5248
|
+
function doParse2(code, ctx) {
|
|
4756
5249
|
const diagnostics = [];
|
|
4757
5250
|
const doc = createDocument("jsx");
|
|
4758
5251
|
const backref = doc.backref;
|
|
@@ -4762,7 +5255,7 @@ function doParse(code, ctx) {
|
|
|
4762
5255
|
});
|
|
4763
5256
|
const eol = code.includes("\r\n") ? "\r\n" : "\n";
|
|
4764
5257
|
const sourceFile = {
|
|
4765
|
-
id:
|
|
5258
|
+
id: FILE_ID2,
|
|
4766
5259
|
path: ctx.id,
|
|
4767
5260
|
text: code,
|
|
4768
5261
|
frontend: "jsx",
|
|
@@ -4770,23 +5263,23 @@ function doParse(code, ctx) {
|
|
|
4770
5263
|
indentUnit: " ",
|
|
4771
5264
|
native: ast
|
|
4772
5265
|
};
|
|
4773
|
-
doc.sources.set(
|
|
5266
|
+
doc.sources.set(FILE_ID2, sourceFile);
|
|
4774
5267
|
const spanOf = (node) => {
|
|
4775
5268
|
if (node.start == null || node.end == null) return null;
|
|
4776
|
-
const
|
|
4777
|
-
file:
|
|
5269
|
+
const span2 = {
|
|
5270
|
+
file: FILE_ID2,
|
|
4778
5271
|
start: node.start,
|
|
4779
5272
|
end: node.end,
|
|
4780
5273
|
startLoc: node.loc ? { line: node.loc.start.line, column: node.loc.start.column } : void 0,
|
|
4781
5274
|
endLoc: node.loc ? { line: node.loc.end.line, column: node.loc.end.column } : void 0
|
|
4782
5275
|
};
|
|
4783
|
-
return
|
|
5276
|
+
return span2;
|
|
4784
5277
|
};
|
|
4785
5278
|
const sliceOf = (node) => node.start == null || node.end == null ? "" : code.slice(node.start, node.end);
|
|
4786
5279
|
const internExpr = (node, spread) => {
|
|
4787
5280
|
const payload = { text: sliceOf(node), spread };
|
|
4788
5281
|
return doc.exprs.intern({
|
|
4789
|
-
span: spanOf(node) ?? { file:
|
|
5282
|
+
span: spanOf(node) ?? { file: FILE_ID2, start: 0, end: 0 },
|
|
4790
5283
|
kind: exprKind(node),
|
|
4791
5284
|
payload
|
|
4792
5285
|
});
|
|
@@ -4832,7 +5325,7 @@ function doParse(code, ctx) {
|
|
|
4832
5325
|
}
|
|
4833
5326
|
return emptyClassList();
|
|
4834
5327
|
};
|
|
4835
|
-
const
|
|
5328
|
+
const staticTokensOf4 = (classes) => {
|
|
4836
5329
|
const out = [];
|
|
4837
5330
|
for (const seg of classes.segments) {
|
|
4838
5331
|
if (seg.kind === "static") for (const t of seg.tokens) out.push(t.value);
|
|
@@ -4910,7 +5403,7 @@ function doParse(code, ctx) {
|
|
|
4910
5403
|
doc.nodes.set(id, createFragment(id, { children, parent: parentId, span: spanOf(node) }));
|
|
4911
5404
|
backref.set(id, {
|
|
4912
5405
|
nodeId: id,
|
|
4913
|
-
span: spanOf(node) ?? { file:
|
|
5406
|
+
span: spanOf(node) ?? { file: FILE_ID2, start: 0, end: 0 },
|
|
4914
5407
|
openTagSpan: spanOf(node.openingFragment),
|
|
4915
5408
|
closeTagSpan: spanOf(node.closingFragment),
|
|
4916
5409
|
innerSpan: null,
|
|
@@ -4959,7 +5452,7 @@ function doParse(code, ctx) {
|
|
|
4959
5452
|
}
|
|
4960
5453
|
let computed2 = emptyStyleMap();
|
|
4961
5454
|
if (!classes.hasDynamic) {
|
|
4962
|
-
const tokens =
|
|
5455
|
+
const tokens = staticTokensOf4(classes);
|
|
4963
5456
|
if (tokens.length > 0) {
|
|
4964
5457
|
const res = ctx.resolver.resolve({
|
|
4965
5458
|
classes: tokens,
|
|
@@ -4992,13 +5485,13 @@ function doParse(code, ctx) {
|
|
|
4992
5485
|
});
|
|
4993
5486
|
doc.nodes.set(id, el);
|
|
4994
5487
|
const inner = children.length > 0 ? spanOf(node.children[0]) && spanOf(node.children.at(-1)) ? {
|
|
4995
|
-
file:
|
|
5488
|
+
file: FILE_ID2,
|
|
4996
5489
|
start: spanOf(node.children[0]).start,
|
|
4997
5490
|
end: spanOf(node.children.at(-1)).end
|
|
4998
5491
|
} : null : null;
|
|
4999
5492
|
backref.set(id, {
|
|
5000
5493
|
nodeId: id,
|
|
5001
|
-
span: spanOf(node) ?? { file:
|
|
5494
|
+
span: spanOf(node) ?? { file: FILE_ID2, start: 0, end: 0 },
|
|
5002
5495
|
openTagSpan: spanOf(opening),
|
|
5003
5496
|
closeTagSpan: node.closingElement ? spanOf(node.closingElement) : null,
|
|
5004
5497
|
innerSpan: inner,
|
|
@@ -5033,7 +5526,7 @@ var jsxFrontend = {
|
|
|
5033
5526
|
return looksLikeJsx(id, code);
|
|
5034
5527
|
},
|
|
5035
5528
|
parse(code, ctx) {
|
|
5036
|
-
return
|
|
5529
|
+
return doParse2(code, ctx);
|
|
5037
5530
|
}
|
|
5038
5531
|
};
|
|
5039
5532
|
function createJsxFrontend() {
|
|
@@ -5041,7 +5534,7 @@ function createJsxFrontend() {
|
|
|
5041
5534
|
}
|
|
5042
5535
|
|
|
5043
5536
|
// ../frontend-jsx/src/backend.ts
|
|
5044
|
-
var
|
|
5537
|
+
var import_magic_string2 = __toESM(require("magic-string"), 1);
|
|
5045
5538
|
var JSX_LANGS2 = ["jsx", "tsx"];
|
|
5046
5539
|
function exprText(doc, ref) {
|
|
5047
5540
|
const rec = doc.exprs.get(ref);
|
|
@@ -5055,20 +5548,20 @@ function exprText(doc, ref) {
|
|
|
5055
5548
|
}
|
|
5056
5549
|
return { text: "", spread: false };
|
|
5057
5550
|
}
|
|
5058
|
-
function
|
|
5551
|
+
function staticTokensOf3(classes) {
|
|
5059
5552
|
const out = [];
|
|
5060
5553
|
for (const seg of classes.segments) {
|
|
5061
5554
|
if (seg.kind === "static") for (const t of seg.tokens) out.push(t.value);
|
|
5062
5555
|
}
|
|
5063
5556
|
return out;
|
|
5064
5557
|
}
|
|
5065
|
-
function
|
|
5558
|
+
function primarySource2(doc) {
|
|
5066
5559
|
for (const sf of doc.sources.values()) {
|
|
5067
5560
|
if (typeof sf.text === "string" && sf.text.length > 0) return sf;
|
|
5068
5561
|
}
|
|
5069
5562
|
return null;
|
|
5070
5563
|
}
|
|
5071
|
-
function
|
|
5564
|
+
function collectKept2(doc) {
|
|
5072
5565
|
const out = [];
|
|
5073
5566
|
const seen = /* @__PURE__ */ new Set();
|
|
5074
5567
|
const visit = (id) => {
|
|
@@ -5082,15 +5575,15 @@ function collectKept(doc) {
|
|
|
5082
5575
|
visit(doc.root);
|
|
5083
5576
|
return out;
|
|
5084
5577
|
}
|
|
5085
|
-
function
|
|
5578
|
+
function strictlyContains2(a, b) {
|
|
5086
5579
|
if (a.file !== b.file) return false;
|
|
5087
5580
|
if (a.start <= b.start && b.end <= a.end) return !(a.start === b.start && a.end === b.end);
|
|
5088
5581
|
return false;
|
|
5089
5582
|
}
|
|
5090
|
-
function
|
|
5583
|
+
function editClasses2(ms, doc, sf, el) {
|
|
5091
5584
|
const classes = el.classes;
|
|
5092
5585
|
if (classes.hasDynamic || classes.opaque) return false;
|
|
5093
|
-
const tokens =
|
|
5586
|
+
const tokens = staticTokensOf3(classes);
|
|
5094
5587
|
const valueSpan = classes.valueSpan;
|
|
5095
5588
|
if (valueSpan && valueSpan.file === sf.id) {
|
|
5096
5589
|
const current = sf.text.slice(valueSpan.start, valueSpan.end);
|
|
@@ -5154,10 +5647,10 @@ function transferKeyOnUnwrap(ms, doc, sf, region, kept) {
|
|
|
5154
5647
|
const inside = [];
|
|
5155
5648
|
for (const n of kept) {
|
|
5156
5649
|
if (n.kind !== "element" || !n.span || n.span.file !== sf.id) continue;
|
|
5157
|
-
if (
|
|
5650
|
+
if (strictlyContains2(region.span, n.span)) inside.push(n);
|
|
5158
5651
|
}
|
|
5159
5652
|
const maximal = inside.filter(
|
|
5160
|
-
(n) => !inside.some((o) => o !== n && o.span && n.span &&
|
|
5653
|
+
(n) => !inside.some((o) => o !== n && o.span && n.span && strictlyContains2(o.span, n.span))
|
|
5161
5654
|
);
|
|
5162
5655
|
if (maximal.length !== 1) return;
|
|
5163
5656
|
const child = maximal[0];
|
|
@@ -5166,25 +5659,25 @@ function transferKeyOnUnwrap(ms, doc, sf, region, kept) {
|
|
|
5166
5659
|
if (extractKeyAttr(sf.text.slice(childOpen.start, childOpen.end))) return;
|
|
5167
5660
|
ms.appendLeft(childOpen.start + 1 + child.tag.length, ` ${keyAttr}`);
|
|
5168
5661
|
}
|
|
5169
|
-
function
|
|
5170
|
-
const sf =
|
|
5662
|
+
function surgicalPrint2(doc) {
|
|
5663
|
+
const sf = primarySource2(doc);
|
|
5171
5664
|
if (!sf) return null;
|
|
5172
|
-
const ms = new
|
|
5173
|
-
const kept =
|
|
5665
|
+
const ms = new import_magic_string2.default(sf.text);
|
|
5666
|
+
const kept = collectKept2(doc);
|
|
5174
5667
|
const keptSpans = [];
|
|
5175
5668
|
for (const n of kept) if (n.span && n.span.file === sf.id) keptSpans.push(n.span);
|
|
5176
5669
|
const removed = [];
|
|
5177
|
-
for (const id of
|
|
5670
|
+
for (const id of backrefIds2(doc)) {
|
|
5178
5671
|
if (doc.nodes.has(id)) continue;
|
|
5179
5672
|
const back = doc.backref.get(id);
|
|
5180
5673
|
if (!back || back.span.file !== sf.id) continue;
|
|
5181
|
-
const unwrapped = keptSpans.some((k) =>
|
|
5674
|
+
const unwrapped = keptSpans.some((k) => strictlyContains2(back.span, k));
|
|
5182
5675
|
removed.push({ backref: back, unwrapped });
|
|
5183
5676
|
}
|
|
5184
5677
|
const fullRemovals = removed.filter((r) => !r.unwrapped).map((r) => r.backref.span);
|
|
5185
5678
|
for (const r of removed) {
|
|
5186
|
-
const
|
|
5187
|
-
const coveredByFull = fullRemovals.some((f) => f !==
|
|
5679
|
+
const span2 = r.backref.span;
|
|
5680
|
+
const coveredByFull = fullRemovals.some((f) => f !== span2 && strictlyContains2(f, span2));
|
|
5188
5681
|
if (coveredByFull) continue;
|
|
5189
5682
|
if (r.unwrapped) {
|
|
5190
5683
|
transferKeyOnUnwrap(ms, doc, sf, r.backref, kept);
|
|
@@ -5195,15 +5688,15 @@ function surgicalPrint(doc) {
|
|
|
5195
5688
|
ms.remove(close.start, close.end);
|
|
5196
5689
|
}
|
|
5197
5690
|
} else {
|
|
5198
|
-
ms.remove(
|
|
5691
|
+
ms.remove(span2.start, span2.end);
|
|
5199
5692
|
}
|
|
5200
5693
|
}
|
|
5201
5694
|
for (const n of kept) {
|
|
5202
|
-
if (n.kind === "element")
|
|
5695
|
+
if (n.kind === "element") editClasses2(ms, doc, sf, n);
|
|
5203
5696
|
}
|
|
5204
5697
|
return ms.toString();
|
|
5205
5698
|
}
|
|
5206
|
-
function
|
|
5699
|
+
function backrefIds2(doc) {
|
|
5207
5700
|
const out = [];
|
|
5208
5701
|
const max = doc.alloc.peek;
|
|
5209
5702
|
for (let i = 1; i < max; i += 1) {
|
|
@@ -5218,7 +5711,7 @@ function classText(doc, classes) {
|
|
|
5218
5711
|
if (dynamic && dynamic.kind === "dynamic") {
|
|
5219
5712
|
return `className={${exprText(doc, dynamic.expr).text}}`;
|
|
5220
5713
|
}
|
|
5221
|
-
const tokens =
|
|
5714
|
+
const tokens = staticTokensOf3(classes);
|
|
5222
5715
|
return `className="${tokens.join(" ")}"`;
|
|
5223
5716
|
}
|
|
5224
5717
|
function attrText(doc, name, value) {
|
|
@@ -5271,15 +5764,15 @@ function rePrint(doc) {
|
|
|
5271
5764
|
if (!root || root.kind !== "fragment") return printNode(doc, doc.root);
|
|
5272
5765
|
return root.children.map((c) => printNode(doc, c)).join("");
|
|
5273
5766
|
}
|
|
5274
|
-
function
|
|
5275
|
-
const surgical =
|
|
5767
|
+
function doPrint2(doc) {
|
|
5768
|
+
const surgical = surgicalPrint2(doc);
|
|
5276
5769
|
return surgical ?? rePrint(doc);
|
|
5277
5770
|
}
|
|
5278
5771
|
var jsxBackend = {
|
|
5279
5772
|
name: "babel-jsx",
|
|
5280
5773
|
langs: JSX_LANGS2,
|
|
5281
5774
|
print(doc, _plan, _ctx) {
|
|
5282
|
-
const code =
|
|
5775
|
+
const code = doPrint2(doc);
|
|
5283
5776
|
return { code, map: null, edits: [], diagnostics: [] };
|
|
5284
5777
|
}
|
|
5285
5778
|
};
|
|
@@ -5294,6 +5787,11 @@ function jsxKindOf(id) {
|
|
|
5294
5787
|
if (clean.endsWith(".jsx")) return "jsx";
|
|
5295
5788
|
return null;
|
|
5296
5789
|
}
|
|
5790
|
+
function htmlKindOf(id) {
|
|
5791
|
+
const clean = (id.split("?", 1)[0] ?? id).toLowerCase();
|
|
5792
|
+
if (clean.endsWith(".html") || clean.endsWith(".htm")) return "html";
|
|
5793
|
+
return null;
|
|
5794
|
+
}
|
|
5297
5795
|
function eolOf2(doc) {
|
|
5298
5796
|
for (const src of doc.sources.values()) return src.eol;
|
|
5299
5797
|
return "\n";
|
|
@@ -5361,9 +5859,51 @@ function runJsxPipeline(code, id, kind, resolver, patterns, safety) {
|
|
|
5361
5859
|
const { doc: optimized } = runPasses(doc, passes, ctx);
|
|
5362
5860
|
return finishPipeline(optimized, id, resolver);
|
|
5363
5861
|
}
|
|
5862
|
+
function prepareHtml(code, id, resolver, patterns, safety, gate) {
|
|
5863
|
+
const parsed = createHtmlFrontend().parse(code, {
|
|
5864
|
+
id,
|
|
5865
|
+
kind: "html",
|
|
5866
|
+
resolver,
|
|
5867
|
+
normalizer,
|
|
5868
|
+
config: {},
|
|
5869
|
+
onDiagnostic: () => {
|
|
5870
|
+
}
|
|
5871
|
+
});
|
|
5872
|
+
const doc = parsed.doc;
|
|
5873
|
+
const ctx = {
|
|
5874
|
+
doc,
|
|
5875
|
+
safetyCeiling: safety,
|
|
5876
|
+
normalizer,
|
|
5877
|
+
selectors: buildSelectorIndex(doc, resolver),
|
|
5878
|
+
resolver,
|
|
5879
|
+
gate
|
|
5880
|
+
};
|
|
5881
|
+
return { doc, ctx, passes: buildPasses(patterns) };
|
|
5882
|
+
}
|
|
5883
|
+
function finishHtmlPipeline(optimized, id, resolver) {
|
|
5884
|
+
syncClassesFromComputed(optimized, resolver, normalizer);
|
|
5885
|
+
const printed = createHtmlBackend().print(
|
|
5886
|
+
optimized,
|
|
5887
|
+
{ moduleId: id, ops: [], provenance: /* @__PURE__ */ new Map() },
|
|
5888
|
+
{
|
|
5889
|
+
normalizer,
|
|
5890
|
+
resolver,
|
|
5891
|
+
sink: createSyntheticSink(),
|
|
5892
|
+
eol: eolOf2(optimized),
|
|
5893
|
+
onDiagnostic: () => {
|
|
5894
|
+
}
|
|
5895
|
+
}
|
|
5896
|
+
);
|
|
5897
|
+
return printed.code;
|
|
5898
|
+
}
|
|
5899
|
+
function runHtmlPipeline(code, id, resolver, patterns, safety) {
|
|
5900
|
+
const { doc, ctx, passes } = prepareHtml(code, id, resolver, patterns, safety, "provably-safe");
|
|
5901
|
+
const { doc: optimized } = runPasses(doc, passes, ctx);
|
|
5902
|
+
return finishHtmlPipeline(optimized, id, resolver);
|
|
5903
|
+
}
|
|
5364
5904
|
|
|
5365
5905
|
// src/index.ts
|
|
5366
|
-
var DEFAULT_INCLUDE = [".jsx", ".tsx", ".html"];
|
|
5906
|
+
var DEFAULT_INCLUDE = [".jsx", ".tsx", ".html", ".htm"];
|
|
5367
5907
|
function resolveOptions(options) {
|
|
5368
5908
|
return {
|
|
5369
5909
|
provider: options.provider ?? "auto",
|
|
@@ -5399,9 +5939,15 @@ function createDomflax(options = {}) {
|
|
|
5399
5939
|
transform(code, id) {
|
|
5400
5940
|
if (!isSupported(id, resolved.include)) return { code, map: null };
|
|
5401
5941
|
const kind = jsxKindOf(id);
|
|
5402
|
-
if (kind
|
|
5403
|
-
|
|
5404
|
-
|
|
5942
|
+
if (kind !== null) {
|
|
5943
|
+
const out = runJsxPipeline(code, id, kind, getResolver(), patterns, resolved.safety);
|
|
5944
|
+
return { code: out, map: null };
|
|
5945
|
+
}
|
|
5946
|
+
if (htmlKindOf(id) !== null) {
|
|
5947
|
+
const out = runHtmlPipeline(code, id, getResolver(), patterns, resolved.safety);
|
|
5948
|
+
return { code: out, map: null };
|
|
5949
|
+
}
|
|
5950
|
+
return { code, map: null };
|
|
5405
5951
|
}
|
|
5406
5952
|
};
|
|
5407
5953
|
}
|