@pyreon/compiler 0.23.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +357 -5
- package/lib/types/index.d.ts +94 -1
- package/package.json +12 -12
- package/src/index.ts +2 -0
- package/src/jsx.ts +320 -3
- package/src/lpih.ts +270 -0
- package/src/pyreon-intercept.ts +9 -1
- package/src/tests/collapse-bail-census.test.ts +101 -16
- package/src/tests/dynamic-collapse-detector.test.ts +164 -0
- package/src/tests/dynamic-collapse-emit.test.ts +192 -0
- package/src/tests/dynamic-collapse-scan.test.ts +111 -0
- package/src/tests/lpih.test.ts +404 -0
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"6eb92b25-1","name":"defer-inline.ts"},{"uid":"6eb92b25-3","name":"event-names.ts"},{"uid":"6eb92b25-5","name":"load-native.ts"},{"uid":"6eb92b25-7","name":"jsx.ts"},{"uid":"6eb92b25-9","name":"pyreon-intercept.ts"},{"uid":"6eb92b25-11","name":"reactivity-lens.ts"},{"uid":"6eb92b25-13","name":"lpih.ts"},{"uid":"6eb92b25-15","name":"project-scanner.ts"},{"uid":"6eb92b25-17","name":"react-intercept.ts"},{"uid":"6eb92b25-19","name":"test-audit.ts"},{"uid":"6eb92b25-21","name":"island-audit.ts"},{"uid":"6eb92b25-23","name":"ssg-audit.ts"},{"uid":"6eb92b25-25","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"6eb92b25-1":{"renderedLength":15789,"gzipLength":5000,"brotliLength":0,"metaUid":"6eb92b25-0"},"6eb92b25-3":{"renderedLength":2941,"gzipLength":1335,"brotliLength":0,"metaUid":"6eb92b25-2"},"6eb92b25-5":{"renderedLength":3959,"gzipLength":1744,"brotliLength":0,"metaUid":"6eb92b25-4"},"6eb92b25-7":{"renderedLength":75616,"gzipLength":18800,"brotliLength":0,"metaUid":"6eb92b25-6"},"6eb92b25-9":{"renderedLength":29341,"gzipLength":9289,"brotliLength":0,"metaUid":"6eb92b25-8"},"6eb92b25-11":{"renderedLength":4373,"gzipLength":2130,"brotliLength":0,"metaUid":"6eb92b25-10"},"6eb92b25-13":{"renderedLength":5266,"gzipLength":2166,"brotliLength":0,"metaUid":"6eb92b25-12"},"6eb92b25-15":{"renderedLength":4762,"gzipLength":1730,"brotliLength":0,"metaUid":"6eb92b25-14"},"6eb92b25-17":{"renderedLength":28896,"gzipLength":7322,"brotliLength":0,"metaUid":"6eb92b25-16"},"6eb92b25-19":{"renderedLength":13167,"gzipLength":5060,"brotliLength":0,"metaUid":"6eb92b25-18"},"6eb92b25-21":{"renderedLength":18208,"gzipLength":6051,"brotliLength":0,"metaUid":"6eb92b25-20"},"6eb92b25-23":{"renderedLength":12773,"gzipLength":4183,"brotliLength":0,"metaUid":"6eb92b25-22"},"6eb92b25-25":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"6eb92b25-24"}},"nodeMetas":{"6eb92b25-0":{"id":"/src/defer-inline.ts","moduleParts":{"index.js":"6eb92b25-1"},"imported":[{"uid":"6eb92b25-26"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-2":{"id":"/src/event-names.ts","moduleParts":{"index.js":"6eb92b25-3"},"imported":[],"importedBy":[{"uid":"6eb92b25-6"}]},"6eb92b25-4":{"id":"/src/load-native.ts","moduleParts":{"index.js":"6eb92b25-5"},"imported":[{"uid":"6eb92b25-31"},{"uid":"6eb92b25-32"},{"uid":"6eb92b25-29"}],"importedBy":[{"uid":"6eb92b25-6"}]},"6eb92b25-6":{"id":"/src/jsx.ts","moduleParts":{"index.js":"6eb92b25-7"},"imported":[{"uid":"6eb92b25-27"},{"uid":"6eb92b25-26"},{"uid":"6eb92b25-2"},{"uid":"6eb92b25-4"}],"importedBy":[{"uid":"6eb92b25-24"},{"uid":"6eb92b25-10"}]},"6eb92b25-8":{"id":"/src/pyreon-intercept.ts","moduleParts":{"index.js":"6eb92b25-9"},"imported":[{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"},{"uid":"6eb92b25-10"}]},"6eb92b25-10":{"id":"/src/reactivity-lens.ts","moduleParts":{"index.js":"6eb92b25-11"},"imported":[{"uid":"6eb92b25-6"},{"uid":"6eb92b25-8"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-12":{"id":"/src/lpih.ts","moduleParts":{"index.js":"6eb92b25-13"},"imported":[],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-14":{"id":"/src/project-scanner.ts","moduleParts":{"index.js":"6eb92b25-15"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-16":{"id":"/src/react-intercept.ts","moduleParts":{"index.js":"6eb92b25-17"},"imported":[{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-18":{"id":"/src/test-audit.ts","moduleParts":{"index.js":"6eb92b25-19"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-20":{"id":"/src/island-audit.ts","moduleParts":{"index.js":"6eb92b25-21"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"},{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-22":{"id":"/src/ssg-audit.ts","moduleParts":{"index.js":"6eb92b25-23"},"imported":[{"uid":"6eb92b25-28"},{"uid":"6eb92b25-29"},{"uid":"6eb92b25-30"}],"importedBy":[{"uid":"6eb92b25-24"}]},"6eb92b25-24":{"id":"/src/index.ts","moduleParts":{"index.js":"6eb92b25-25"},"imported":[{"uid":"6eb92b25-0"},{"uid":"6eb92b25-6"},{"uid":"6eb92b25-10"},{"uid":"6eb92b25-12"},{"uid":"6eb92b25-14"},{"uid":"6eb92b25-16"},{"uid":"6eb92b25-8"},{"uid":"6eb92b25-18"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"}],"importedBy":[],"isEntry":true},"6eb92b25-26":{"id":"oxc-parser","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-0"},{"uid":"6eb92b25-6"}]},"6eb92b25-27":{"id":"magic-string","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-6"}]},"6eb92b25-28":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-14"},{"uid":"6eb92b25-18"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"}]},"6eb92b25-29":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-14"},{"uid":"6eb92b25-18"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"},{"uid":"6eb92b25-4"}]},"6eb92b25-30":{"id":"typescript","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-16"},{"uid":"6eb92b25-8"},{"uid":"6eb92b25-20"},{"uid":"6eb92b25-22"}]},"6eb92b25-31":{"id":"node:module","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-4"}]},"6eb92b25-32":{"id":"node:url","moduleParts":{},"imported":[],"importedBy":[{"uid":"6eb92b25-4"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -785,6 +785,23 @@ function scanCollapsibleSites(code, filename, collapsibleSources) {
|
|
|
785
785
|
childrenText: site.childrenText,
|
|
786
786
|
key: rocketstyleCollapseKey(tag, site.props, site.childrenText)
|
|
787
787
|
});
|
|
788
|
+
else {
|
|
789
|
+
const dyn = detectDynamicCollapsibleShape(node, tag);
|
|
790
|
+
if (dyn) for (const value of [dyn.dynamicProp.valueTruthy, dyn.dynamicProp.valueFalsy]) {
|
|
791
|
+
const expandedProps = {
|
|
792
|
+
...dyn.props,
|
|
793
|
+
[dyn.dynamicProp.name]: value
|
|
794
|
+
};
|
|
795
|
+
out.push({
|
|
796
|
+
componentName: tag,
|
|
797
|
+
source: imp.source,
|
|
798
|
+
importedName: imp.imported,
|
|
799
|
+
props: expandedProps,
|
|
800
|
+
childrenText: dyn.childrenText,
|
|
801
|
+
key: rocketstyleCollapseKey(tag, expandedProps, dyn.childrenText)
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
}
|
|
788
805
|
}
|
|
789
806
|
}
|
|
790
807
|
for (const k in node) {
|
|
@@ -880,6 +897,104 @@ function detectPartialCollapsibleShape(node, _tag) {
|
|
|
880
897
|
handlers
|
|
881
898
|
};
|
|
882
899
|
}
|
|
900
|
+
/**
|
|
901
|
+
* Dynamic-prop partial-collapse detector — PR 2 of the dynamic-prop
|
|
902
|
+
* partial-collapse build (`.claude/plans/open-work-2026-q3.md` → #1
|
|
903
|
+
* dynamic-prop bucket = 15.3% of all real-corpus sites; the next-bigger
|
|
904
|
+
* bite after the `on*`-handler partial-collapse).
|
|
905
|
+
*
|
|
906
|
+
* Mirrors `detectPartialCollapsibleShape`'s "extend the bail catalogue
|
|
907
|
+
* with ONE relaxation" pattern (see that detector's docstring + `PR 1`
|
|
908
|
+
* `_rsCollapseDyn` runtime helper, PR #765). The single relaxation: a
|
|
909
|
+
* `JSXExpressionContainer` wrapping a `ConditionalExpression` whose
|
|
910
|
+
* `consequent` AND `alternate` are BOTH `StringLiteral` is acceptable as
|
|
911
|
+
* a "ternary-of-two-literals" dynamic prop — captured as a {@link DynamicCollapsibleProp}
|
|
912
|
+
* with the cond source span + the two literal values.
|
|
913
|
+
*
|
|
914
|
+
* Constraint: **AT MOST ONE** such dynamic prop per site. Multiple
|
|
915
|
+
* ternaries would compound into a 2^N value-set per site at build time
|
|
916
|
+
* and an N-axis dispatcher at runtime — that's a separable scope
|
|
917
|
+
* (potential PR 5+), NOT this PR. Sites with 2+ ternaries bail (return
|
|
918
|
+
* null), keeping the normal mount; same conservative shape as the rest
|
|
919
|
+
* of the detector family.
|
|
920
|
+
*
|
|
921
|
+
* Constraint: the FULL `on*`-handler relaxation is also folded in — a
|
|
922
|
+
* site can have ONE ternary AND `on*` handlers in the same call. This
|
|
923
|
+
* matches the real-corpus shape (a Button with `state={cond ? 'a' : 'b'}`
|
|
924
|
+
* almost always also has an `onClick`). The two relaxations compose
|
|
925
|
+
* cleanly because they're orthogonal at the resolver layer (handlers
|
|
926
|
+
* don't change rendered CSS; the ternary picks among pre-resolved
|
|
927
|
+
* classes). PR 3's emit will use `_rsCollapseDyn` when handlers are
|
|
928
|
+
* absent and a future combined helper when both are present — for THIS
|
|
929
|
+
* PR (detector-only) the structure carries both so PR 3 can dispatch.
|
|
930
|
+
*
|
|
931
|
+
* Every OTHER non-literal shape still bails (spread, non-handler
|
|
932
|
+
* non-ternary `{expr}` prop, multi-literal ternary anywhere, computed-
|
|
933
|
+
* expression ternary, element/expression child, boolean attr) —
|
|
934
|
+
* conservative by construction, exactly like the rest of the family.
|
|
935
|
+
* Returns `null` when there are ZERO ternaries so the on*-only path
|
|
936
|
+
* (`detectPartialCollapsibleShape`) and the full-collapse path
|
|
937
|
+
* (`detectCollapsibleShape`) stay byte-unchanged and no detector both
|
|
938
|
+
* claims the same site.
|
|
939
|
+
*
|
|
940
|
+
* A consistency test (PR 3) will lock this catalogue against the
|
|
941
|
+
* plugin scan, mirroring the `detectCollapsibleShape` ↔ `scanCollapsibleSites`
|
|
942
|
+
* + `detectPartialCollapsibleShape` ↔ scan invariants — keys cannot drift.
|
|
943
|
+
*/
|
|
944
|
+
function detectDynamicCollapsibleShape(node, _tag) {
|
|
945
|
+
const props = {};
|
|
946
|
+
const handlers = [];
|
|
947
|
+
const dynamicProps = [];
|
|
948
|
+
for (const attr of jsxAttrs(node)) {
|
|
949
|
+
if (attr.type !== "JSXAttribute") return null;
|
|
950
|
+
const nm = attr.name?.type === "JSXIdentifier" ? attr.name.name : null;
|
|
951
|
+
if (!nm) return null;
|
|
952
|
+
const v = attr.value;
|
|
953
|
+
if (!v) return null;
|
|
954
|
+
if (v.type === "StringLiteral" || v.type === "Literal" && typeof v.value === "string") {
|
|
955
|
+
props[nm] = String(v.value);
|
|
956
|
+
continue;
|
|
957
|
+
}
|
|
958
|
+
if (v.type === "JSXExpressionContainer" && v.expression && typeof v.expression.start === "number" && typeof v.expression.end === "number") {
|
|
959
|
+
if (/^on[A-Z]/.test(nm)) {
|
|
960
|
+
handlers.push({
|
|
961
|
+
name: nm,
|
|
962
|
+
exprStart: v.expression.start,
|
|
963
|
+
exprEnd: v.expression.end
|
|
964
|
+
});
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
const expr = v.expression;
|
|
968
|
+
if (expr.type === "ConditionalExpression" && expr.test && typeof expr.test.start === "number" && typeof expr.test.end === "number" && expr.consequent && expr.alternate) {
|
|
969
|
+
const isLitStr = (n) => {
|
|
970
|
+
const x = n;
|
|
971
|
+
return x?.type === "StringLiteral" || x?.type === "Literal" && typeof x.value === "string";
|
|
972
|
+
};
|
|
973
|
+
if (isLitStr(expr.consequent) && isLitStr(expr.alternate)) {
|
|
974
|
+
dynamicProps.push({
|
|
975
|
+
name: nm,
|
|
976
|
+
condStart: expr.test.start,
|
|
977
|
+
condEnd: expr.test.end,
|
|
978
|
+
valueTruthy: String(expr.consequent.value),
|
|
979
|
+
valueFalsy: String(expr.alternate.value)
|
|
980
|
+
});
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
return null;
|
|
986
|
+
}
|
|
987
|
+
let childrenText = "";
|
|
988
|
+
for (const c of jsxChildren(node)) if (c.type === "JSXText") childrenText += c.value ?? "";
|
|
989
|
+
else return null;
|
|
990
|
+
if (dynamicProps.length !== 1) return null;
|
|
991
|
+
return {
|
|
992
|
+
props,
|
|
993
|
+
childrenText: childrenText.trim(),
|
|
994
|
+
handlers,
|
|
995
|
+
dynamicProp: dynamicProps[0]
|
|
996
|
+
};
|
|
997
|
+
}
|
|
883
998
|
function transformJSX(code, filename = "input.tsx", options = {}) {
|
|
884
999
|
if (options.collapseRocketstyle) return transformJSX_JS(code, filename, options);
|
|
885
1000
|
if (nativeTransformJsx) try {
|
|
@@ -975,6 +1090,8 @@ function transformJSX_JS(code, filename = "input.tsx", options = {}) {
|
|
|
975
1090
|
let needsMountSlotImportGlobal = false;
|
|
976
1091
|
let needsCollapse = false;
|
|
977
1092
|
let needsCollapseH = false;
|
|
1093
|
+
let needsCollapseDyn = false;
|
|
1094
|
+
let needsCollapseDynH = false;
|
|
978
1095
|
const collapseRuleKeys = /* @__PURE__ */ new Set();
|
|
979
1096
|
const collapseRules = [];
|
|
980
1097
|
/**
|
|
@@ -997,7 +1114,7 @@ function transformJSX_JS(code, filename = "input.tsx", options = {}) {
|
|
|
997
1114
|
if (!tag || tag.charAt(0) === tag.charAt(0).toLowerCase()) return false;
|
|
998
1115
|
if (!cfg.candidates.has(tag)) return false;
|
|
999
1116
|
const shape = detectCollapsibleShape(node, tag);
|
|
1000
|
-
if (!shape) return tryPartialCollapse(node, tag);
|
|
1117
|
+
if (!shape) return tryPartialCollapse(node, tag) || tryDynamicCollapse(node, tag);
|
|
1001
1118
|
const { props, childrenText } = shape;
|
|
1002
1119
|
const key = rocketstyleCollapseKey(tag, props, childrenText);
|
|
1003
1120
|
const site = cfg.sites.get(key);
|
|
@@ -1069,6 +1186,103 @@ function transformJSX_JS(code, filename = "input.tsx", options = {}) {
|
|
|
1069
1186
|
}
|
|
1070
1187
|
return true;
|
|
1071
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* PR 3 of the dynamic-prop partial-collapse build (open-work #1
|
|
1191
|
+
* dynamic-prop bucket = 15.3% of all real-corpus sites; the
|
|
1192
|
+
* next-bigger bite after the just-shipped `on*`-handler partial).
|
|
1193
|
+
* The dynamic-prop fallback `tryRocketstyleCollapse` defers to when
|
|
1194
|
+
* BOTH the full and the on*-handler-partial paths bail.
|
|
1195
|
+
*
|
|
1196
|
+
* Same site-resolution contract as the full path — the dynamic prop
|
|
1197
|
+
* is replaced with EACH literal value to compute TWO keys; the
|
|
1198
|
+
* resolver pre-renders both via the existing SSR pipeline; if both
|
|
1199
|
+
* lookups succeed AND the structural template is byte-identical
|
|
1200
|
+
* across values, emit `__rsCollapseDyn(html, [classes...], () =>
|
|
1201
|
+
* cond ? 0 : 1, () => __pyrMode() === "dark")` — the PR 1 runtime
|
|
1202
|
+
* helper (#765) dispatches across `(value × mode)` with a stride-2
|
|
1203
|
+
* value-major class layout.
|
|
1204
|
+
*
|
|
1205
|
+
* Conservative discipline:
|
|
1206
|
+
* - Either expanded key missing from sites map ⇒ bail (an
|
|
1207
|
+
* intermittent resolver failure on one value mustn't half-collapse)
|
|
1208
|
+
* - Divergent template HTML across values ⇒ bail (the dispatcher
|
|
1209
|
+
* assumes a shared template; deriveCollapseDyn cannot be done
|
|
1210
|
+
* across values that produce structurally different markup —
|
|
1211
|
+
* this is the cross-value parallel of `deriveCollapse`'s
|
|
1212
|
+
* light↔dark template-divergence bail)
|
|
1213
|
+
*
|
|
1214
|
+
* Handler-combined sites: when the detected dynamic site has `on*`
|
|
1215
|
+
* handlers (the most common real-corpus shape — bail-census measured
|
|
1216
|
+
* the no-handler subset at 0.2% of all sites; handler-combined is
|
|
1217
|
+
* the bulk of the 15.4% dynamic-prop bucket), emit
|
|
1218
|
+
* `__rsCollapseDynH(...)` (PR A: runtime helper) instead of
|
|
1219
|
+
* `__rsCollapseDyn(...)`. Handlers are orthogonal to the SSR-
|
|
1220
|
+
* resolved styler class (the resolver pre-renders both values
|
|
1221
|
+
* identically regardless of handlers); the union helper just
|
|
1222
|
+
* re-attaches them through the same canonical `_bindEvent` path
|
|
1223
|
+
* `tryPartialCollapse` uses.
|
|
1224
|
+
*
|
|
1225
|
+
* Rule injection unions the rule sets across both values (each value
|
|
1226
|
+
* may inject distinct CSS rules — e.g. `state="primary"` and
|
|
1227
|
+
* `state="secondary"` produce different background-color rules); the
|
|
1228
|
+
* union is the byte-set the dispatcher will need at runtime regardless
|
|
1229
|
+
* of which value the cond resolves to. Idempotent by per-value
|
|
1230
|
+
* `ruleKey` so a re-resolve / HMR is a no-op.
|
|
1231
|
+
*/
|
|
1232
|
+
function tryDynamicCollapse(node, tag) {
|
|
1233
|
+
const cfg = options.collapseRocketstyle;
|
|
1234
|
+
if (!cfg) return false;
|
|
1235
|
+
const dyn = detectDynamicCollapsibleShape(node, tag);
|
|
1236
|
+
if (!dyn) return false;
|
|
1237
|
+
const { props, childrenText, dynamicProp, handlers } = dyn;
|
|
1238
|
+
const truthyProps = {
|
|
1239
|
+
...props,
|
|
1240
|
+
[dynamicProp.name]: dynamicProp.valueTruthy
|
|
1241
|
+
};
|
|
1242
|
+
const falsyProps = {
|
|
1243
|
+
...props,
|
|
1244
|
+
[dynamicProp.name]: dynamicProp.valueFalsy
|
|
1245
|
+
};
|
|
1246
|
+
const truthyKey = rocketstyleCollapseKey(tag, truthyProps, childrenText);
|
|
1247
|
+
const falsyKey = rocketstyleCollapseKey(tag, falsyProps, childrenText);
|
|
1248
|
+
const truthySite = cfg.sites.get(truthyKey);
|
|
1249
|
+
const falsySite = cfg.sites.get(falsyKey);
|
|
1250
|
+
if (!truthySite || !falsySite) return false;
|
|
1251
|
+
if (truthySite.templateHtml !== falsySite.templateHtml) return false;
|
|
1252
|
+
const classes = [
|
|
1253
|
+
truthySite.lightClass,
|
|
1254
|
+
truthySite.darkClass,
|
|
1255
|
+
falsySite.lightClass,
|
|
1256
|
+
falsySite.darkClass
|
|
1257
|
+
];
|
|
1258
|
+
const condSrc = code.slice(dynamicProp.condStart, dynamicProp.condEnd);
|
|
1259
|
+
let call;
|
|
1260
|
+
if (handlers.length > 0) {
|
|
1261
|
+
const handlerObj = `{ ${handlers.map((h) => `${JSON.stringify(h.name)}: (${code.slice(h.exprStart, h.exprEnd)})`).join(", ")} }`;
|
|
1262
|
+
call = `__rsCollapseDynH(${JSON.stringify(truthySite.templateHtml)}, ${JSON.stringify(classes)}, () => (${condSrc}) ? 0 : 1, () => __pyrMode() === "dark", ${handlerObj})`;
|
|
1263
|
+
needsCollapseDynH = true;
|
|
1264
|
+
} else {
|
|
1265
|
+
call = `__rsCollapseDyn(${JSON.stringify(truthySite.templateHtml)}, ${JSON.stringify(classes)}, () => (${condSrc}) ? 0 : 1, () => __pyrMode() === "dark")`;
|
|
1266
|
+
needsCollapseDyn = true;
|
|
1267
|
+
}
|
|
1268
|
+
const start = node.start;
|
|
1269
|
+
const end = node.end;
|
|
1270
|
+
const parent = findParent(node);
|
|
1271
|
+
const needsBraces = parent && (parent.type === "JSXElement" || parent.type === "JSXFragment");
|
|
1272
|
+
replacements.push({
|
|
1273
|
+
start,
|
|
1274
|
+
end,
|
|
1275
|
+
text: needsBraces ? `{${call}}` : call
|
|
1276
|
+
});
|
|
1277
|
+
for (const site of [truthySite, falsySite]) if (!collapseRuleKeys.has(site.ruleKey)) {
|
|
1278
|
+
collapseRuleKeys.add(site.ruleKey);
|
|
1279
|
+
collapseRules.push({
|
|
1280
|
+
ruleKey: site.ruleKey,
|
|
1281
|
+
rules: site.rules
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
return true;
|
|
1285
|
+
}
|
|
1072
1286
|
function maybeHoist(node) {
|
|
1073
1287
|
if ((node.type === "JSXElement" || node.type === "JSXFragment") && isStaticJSXNode(node)) {
|
|
1074
1288
|
const name = `_$h${hoistIdx++}`;
|
|
@@ -1612,12 +1826,17 @@ function transformJSX_JS(code, filename = "input.tsx", options = {}) {
|
|
|
1612
1826
|
if (needsWrapSpreadImport) coreImports.push("_wrapSpread");
|
|
1613
1827
|
preamble = `import { ${coreImports.join(", ")} } from "@pyreon/core";\n` + preamble;
|
|
1614
1828
|
}
|
|
1615
|
-
if (needsCollapse) {
|
|
1829
|
+
if (needsCollapse || needsCollapseDyn || needsCollapseDynH) {
|
|
1616
1830
|
const cfg = options.collapseRocketstyle;
|
|
1617
1831
|
const rd = cfg.runtimeDomSource ?? "@pyreon/runtime-dom";
|
|
1618
1832
|
const st = cfg.stylerSource ?? "@pyreon/styler";
|
|
1619
1833
|
const inj = collapseRules.map((r) => `__rsSheet.injectRules(${JSON.stringify(r.rules)},${JSON.stringify(r.ruleKey)});`).join("");
|
|
1620
|
-
|
|
1834
|
+
const rdImports = [];
|
|
1835
|
+
if (needsCollapse) rdImports.push("_rsCollapse as __rsCollapse");
|
|
1836
|
+
if (needsCollapseH) rdImports.push("_rsCollapseH as __rsCollapseH");
|
|
1837
|
+
if (needsCollapseDyn) rdImports.push("_rsCollapseDyn as __rsCollapseDyn");
|
|
1838
|
+
if (needsCollapseDynH) rdImports.push("_rsCollapseDynH as __rsCollapseDynH");
|
|
1839
|
+
preamble = `import { ${rdImports.join(", ")} } from "${rd}";\nimport { sheet as __rsSheet } from "${st}";\nimport { ${cfg.mode.name} as __pyrMode } from "${cfg.mode.source}";\n${inj}\n` + preamble;
|
|
1621
1840
|
}
|
|
1622
1841
|
if (preamble) s.prepend(preamble);
|
|
1623
1842
|
const output = s.toString();
|
|
@@ -2807,7 +3026,7 @@ function detectPyreonPatterns(code, filename = "input.tsx") {
|
|
|
2807
3026
|
}
|
|
2808
3027
|
/** Fast regex pre-filter — returns true if the code is worth a full AST walk. */
|
|
2809
3028
|
function hasPyreonPatterns(code) {
|
|
2810
|
-
return /\bFor\b[^=]*\beach\s*=/.test(code) || /\btypeof\s+process\b/.test(code) || /\.theme\s*\(\s*\{\s*\}\s*\)/.test(code) || /\b(?:add|remove)EventListener\s*\(/.test(code) || /\bDate\.now\s*\(/.test(code) && /\bMath\.random\s*\(/.test(code) || /on[A-Z]\w
|
|
3029
|
+
return /\bFor\b[^=]*\beach\s*=/.test(code) || /\btypeof\s+process\b/.test(code) || /\.theme\s*\(\s*\{\s*\}\s*\)/.test(code) || /\b(?:add|remove)EventListener\s*\(/.test(code) || /\bDate\.now\s*\(/.test(code) && /\bMath\.random\s*\(/.test(code) || /on[A-Z]\w{0,60}\s*=\s*\{\s*undefined\s*\}/.test(code) || /=\s*\(\s*\{[^}]{1,500}\}\s*[:)]/.test(code) || /\b(?:const|let|var)\s+\{[^}]{0,500}\}\s*=\s*[A-Za-z_$]/.test(code) || /\b(?:signal|computed)\s*[<(]/.test(code) || /\bif\s*\([^)]{1,500}\)[\s{]{0,20}return\s+null\b/.test(code) || /\bas\s+unknown\s+as\s+VNodeChild\b/.test(code) || /\b(?:useQuery|useInfiniteQuery|useQueries|useSuspenseQuery)\s*\(\s*\{/.test(code) || /\bisland\s*\(/.test(code) && /\bhydrate\s*:\s*['"]never['"]/.test(code);
|
|
2811
3030
|
}
|
|
2812
3031
|
|
|
2813
3032
|
//#endregion
|
|
@@ -2940,6 +3159,139 @@ function formatReactivityLens(code, result) {
|
|
|
2940
3159
|
return out.join("\n");
|
|
2941
3160
|
}
|
|
2942
3161
|
|
|
3162
|
+
//#endregion
|
|
3163
|
+
//#region src/lpih.ts
|
|
3164
|
+
/**
|
|
3165
|
+
* Threshold below which the rate suffix is omitted. A long-dormant node
|
|
3166
|
+
* decays toward 0; showing "0/s" or "0.001/s" is noise. The 0.5 cutoff
|
|
3167
|
+
* means "less than once every 2 seconds at steady state" — at that
|
|
3168
|
+
* rate, the cumulative count is the more useful signal.
|
|
3169
|
+
*
|
|
3170
|
+
* @internal — exported for tests + tunability.
|
|
3171
|
+
*/
|
|
3172
|
+
const _LPIH_RATE_VISIBLE_THRESHOLD = .5;
|
|
3173
|
+
function _formatRate(rate1s) {
|
|
3174
|
+
if (rate1s < .5) return "";
|
|
3175
|
+
return rate1s < 10 ? ` (${rate1s.toFixed(1)}/s)` : ` (${Math.round(rate1s)}/s)`;
|
|
3176
|
+
}
|
|
3177
|
+
const DEFAULT_FORMAT = (detail, fire) => {
|
|
3178
|
+
const kindLabel = fire.kind ? `${fire.kind} ` : "";
|
|
3179
|
+
const rate = typeof fire.rate1s === "number" ? _formatRate(fire.rate1s) : "";
|
|
3180
|
+
return `${detail} — ${kindLabel}fired ${fire.count}×${rate}`;
|
|
3181
|
+
};
|
|
3182
|
+
/**
|
|
3183
|
+
* Merge runtime fire data onto static reactivity findings. Pure function,
|
|
3184
|
+
* deterministic, input not mutated.
|
|
3185
|
+
*
|
|
3186
|
+
* Matching rules:
|
|
3187
|
+
* - Only fires whose normalized `file` matches the analyzed source file
|
|
3188
|
+
* are considered (cross-file fires are silently skipped).
|
|
3189
|
+
* - Line-level matching only (column is ignored). V8 stack columns
|
|
3190
|
+
* differ from compiler-emitted span columns by 1+ chars in practice,
|
|
3191
|
+
* and the user-visible affordance is "this signal at this line is
|
|
3192
|
+
* firing" — line precision is sufficient.
|
|
3193
|
+
* - Multiple fires at the same `line` are summed; latest `lastFire`
|
|
3194
|
+
* and corresponding `kind` win.
|
|
3195
|
+
* - Findings of kind `footgun`, `hoisted-static`, or `static-text` are
|
|
3196
|
+
* passed through unchanged — they're not runtime-active reactive
|
|
3197
|
+
* reads, so a fire count at their location is unrelated to them.
|
|
3198
|
+
*/
|
|
3199
|
+
function mergeFireDataIntoFindings(findings, fires, sourceFile, options = {}) {
|
|
3200
|
+
if (fires.length === 0) return findings;
|
|
3201
|
+
const norm = options.normalizeFile ?? ((p) => p);
|
|
3202
|
+
const format = options.formatDetail ?? DEFAULT_FORMAT;
|
|
3203
|
+
const targetFile = norm(sourceFile);
|
|
3204
|
+
const byLine = /* @__PURE__ */ new Map();
|
|
3205
|
+
for (const f of fires) {
|
|
3206
|
+
if (norm(f.file) !== targetFile) continue;
|
|
3207
|
+
const existing = byLine.get(f.line);
|
|
3208
|
+
if (existing) {
|
|
3209
|
+
existing.count += f.count;
|
|
3210
|
+
if (typeof f.rate1s === "number") existing.rate1s = (existing.rate1s ?? 0) + f.rate1s;
|
|
3211
|
+
if ((f.lastFire ?? -Infinity) > (existing.lastFire ?? -Infinity)) {
|
|
3212
|
+
existing.lastFire = f.lastFire;
|
|
3213
|
+
existing.kind = f.kind ?? existing.kind;
|
|
3214
|
+
}
|
|
3215
|
+
} else byLine.set(f.line, { ...f });
|
|
3216
|
+
}
|
|
3217
|
+
if (byLine.size === 0) return findings;
|
|
3218
|
+
return findings.map((finding) => {
|
|
3219
|
+
if (finding.kind === "footgun" || finding.kind === "hoisted-static" || finding.kind === "static-text") return finding;
|
|
3220
|
+
const fire = byLine.get(finding.line);
|
|
3221
|
+
if (!fire) return finding;
|
|
3222
|
+
return {
|
|
3223
|
+
...finding,
|
|
3224
|
+
detail: format(finding.detail, fire)
|
|
3225
|
+
};
|
|
3226
|
+
});
|
|
3227
|
+
}
|
|
3228
|
+
/**
|
|
3229
|
+
* Synthesize "creation-site" inlay-hint findings directly from fire data.
|
|
3230
|
+
*
|
|
3231
|
+
* `analyzeReactivity()` produces findings at REACTIVE READ sites (JSX
|
|
3232
|
+
* expressions). But the runtime captures fires at CREATION sites
|
|
3233
|
+
* (`signal(0)`, `computed(...)`, `effect(...)`). These are usually
|
|
3234
|
+
* different source lines — so the merge function above only helps when
|
|
3235
|
+
* they happen to coincide.
|
|
3236
|
+
*
|
|
3237
|
+
* The simpler, more useful editor surface is: show fire counts AT THE
|
|
3238
|
+
* CREATION LINE. The user writes `const count = signal(0)` and sees
|
|
3239
|
+
* `(signal fired 129×)` as ghost text on that line, the same way
|
|
3240
|
+
* TypeScript shows the inferred type.
|
|
3241
|
+
*
|
|
3242
|
+
* This function turns each fire datum into a synthetic finding the LSP
|
|
3243
|
+
* can serve as an inlay hint. No static analysis required — pure runtime
|
|
3244
|
+
* data → editor hint.
|
|
3245
|
+
*
|
|
3246
|
+
* Returns findings sorted by (line, column). Files that don't match
|
|
3247
|
+
* `sourceFile` (after normalization) are skipped.
|
|
3248
|
+
*
|
|
3249
|
+
* @example
|
|
3250
|
+
* import { firesToCreationSiteFindings } from '@pyreon/compiler'
|
|
3251
|
+
* import { getFireSummaries } from '@pyreon/reactivity'
|
|
3252
|
+
*
|
|
3253
|
+
* const fires = getFireSummaries().map(s => ({
|
|
3254
|
+
* file: s.loc.file, line: s.loc.line, count: s.count, kind: s.kind,
|
|
3255
|
+
* }))
|
|
3256
|
+
* const findings = firesToCreationSiteFindings(fires, 'app.tsx')
|
|
3257
|
+
* // [{ kind: 'live-fire', line: 5, detail: 'signal fired 129×', ... }]
|
|
3258
|
+
*/
|
|
3259
|
+
function firesToCreationSiteFindings(fires, sourceFile, options = {}) {
|
|
3260
|
+
if (fires.length === 0) return [];
|
|
3261
|
+
const norm = options.normalizeFile ?? ((p) => p);
|
|
3262
|
+
const targetFile = norm(sourceFile);
|
|
3263
|
+
const byLine = /* @__PURE__ */ new Map();
|
|
3264
|
+
for (const f of fires) {
|
|
3265
|
+
if (norm(f.file) !== targetFile) continue;
|
|
3266
|
+
const existing = byLine.get(f.line);
|
|
3267
|
+
if (existing) {
|
|
3268
|
+
existing.count += f.count;
|
|
3269
|
+
if (typeof f.rate1s === "number") existing.rate1s = (existing.rate1s ?? 0) + f.rate1s;
|
|
3270
|
+
if ((f.lastFire ?? -Infinity) > (existing.lastFire ?? -Infinity)) {
|
|
3271
|
+
existing.lastFire = f.lastFire;
|
|
3272
|
+
existing.kind = f.kind ?? existing.kind;
|
|
3273
|
+
}
|
|
3274
|
+
} else byLine.set(f.line, { ...f });
|
|
3275
|
+
}
|
|
3276
|
+
const format = options.formatDetail ?? ((_, fire) => {
|
|
3277
|
+
const kindLabel = fire.kind ?? "node";
|
|
3278
|
+
const rate = typeof fire.rate1s === "number" ? _formatRate(fire.rate1s) : "";
|
|
3279
|
+
return `${kindLabel} fired ${fire.count}×${rate}`;
|
|
3280
|
+
});
|
|
3281
|
+
const LIVE_KIND = "live-fire";
|
|
3282
|
+
const out = [];
|
|
3283
|
+
for (const [line, fire] of byLine) out.push({
|
|
3284
|
+
kind: LIVE_KIND,
|
|
3285
|
+
line,
|
|
3286
|
+
column: 0,
|
|
3287
|
+
endLine: line,
|
|
3288
|
+
endColumn: 9999,
|
|
3289
|
+
detail: format("", fire)
|
|
3290
|
+
});
|
|
3291
|
+
out.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
3292
|
+
return out;
|
|
3293
|
+
}
|
|
3294
|
+
|
|
2943
3295
|
//#endregion
|
|
2944
3296
|
//#region src/project-scanner.ts
|
|
2945
3297
|
/**
|
|
@@ -4891,5 +5243,5 @@ function formatSsgAudit(result, _options = {}) {
|
|
|
4891
5243
|
}
|
|
4892
5244
|
|
|
4893
5245
|
//#endregion
|
|
4894
|
-
export { analyzeReactivity, auditIslands, auditSsg, auditTestEnvironment, detectPyreonPatterns, detectReactPatterns, diagnoseError, formatIslandAudit, formatReactivityLens, formatSsgAudit, formatTestAudit, generateContext, hasPyreonPatterns, hasReactPatterns, migrateReactCode, rocketstyleCollapseKey, scanCollapsibleSites, transformDeferInline, transformJSX, transformJSX_JS };
|
|
5246
|
+
export { analyzeReactivity, auditIslands, auditSsg, auditTestEnvironment, detectPyreonPatterns, detectReactPatterns, diagnoseError, firesToCreationSiteFindings, formatIslandAudit, formatReactivityLens, formatSsgAudit, formatTestAudit, generateContext, hasPyreonPatterns, hasReactPatterns, mergeFireDataIntoFindings, migrateReactCode, rocketstyleCollapseKey, scanCollapsibleSites, transformDeferInline, transformJSX, transformJSX_JS };
|
|
4895
5247
|
//# sourceMappingURL=index.js.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -419,6 +419,99 @@ declare function analyzeReactivity(code: string, filename?: string, options?: {
|
|
|
419
419
|
*/
|
|
420
420
|
declare function formatReactivityLens(code: string, result: AnalyzeReactivityResult): string;
|
|
421
421
|
//#endregion
|
|
422
|
+
//#region src/lpih.d.ts
|
|
423
|
+
/**
|
|
424
|
+
* Runtime fire data carried into the merge function. Shape mirrors
|
|
425
|
+
* `@pyreon/reactivity`'s `FireSummary` but is duplicated here to keep
|
|
426
|
+
* `@pyreon/compiler` free of a runtime-package import. The consumer
|
|
427
|
+
* adapts the shape at the call site.
|
|
428
|
+
*/
|
|
429
|
+
interface LPIHFireDatum {
|
|
430
|
+
/** Source file path captured from `new Error().stack`. */
|
|
431
|
+
file: string;
|
|
432
|
+
/** 1-based line number (V8 stack format). */
|
|
433
|
+
line: number;
|
|
434
|
+
/** Total fires recorded at this location. */
|
|
435
|
+
count: number;
|
|
436
|
+
/** `performance.now()` of most recent fire, or null. */
|
|
437
|
+
lastFire?: number | null | undefined;
|
|
438
|
+
/** Node kind that fired (signal / derived / effect). */
|
|
439
|
+
kind?: 'signal' | 'derived' | 'effect' | undefined;
|
|
440
|
+
/**
|
|
441
|
+
* Exponentially-decayed fire rate, fires/sec (1s time constant). 0
|
|
442
|
+
* when the node has been idle longer than several time constants.
|
|
443
|
+
* Used by the default formatter to add a "12/s" suffix when active.
|
|
444
|
+
* See `@pyreon/reactivity`'s `FireSummary.rate1s` for the math.
|
|
445
|
+
*/
|
|
446
|
+
rate1s?: number | undefined;
|
|
447
|
+
}
|
|
448
|
+
/** Options for `mergeFireDataIntoFindings`. */
|
|
449
|
+
interface LPIHMergeOptions {
|
|
450
|
+
/**
|
|
451
|
+
* Optional file-path normalizer. Used for both the analyzed source
|
|
452
|
+
* file and each fire's `file` field. Useful when fires come from
|
|
453
|
+
* runtime stacks (absolute paths) but the source file is identified
|
|
454
|
+
* relative (e.g. workspace-rooted). Defaults to identity.
|
|
455
|
+
*/
|
|
456
|
+
normalizeFile?: (path: string) => string;
|
|
457
|
+
/**
|
|
458
|
+
* Optional formatter for the enriched detail. Receives the original
|
|
459
|
+
* detail + the matched fire datum. Defaults to:
|
|
460
|
+
* `${detail} — ${kind ? kind + ' ' : ''}fired ${count}×`
|
|
461
|
+
*/
|
|
462
|
+
formatDetail?: (detail: string, fire: LPIHFireDatum) => string;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Merge runtime fire data onto static reactivity findings. Pure function,
|
|
466
|
+
* deterministic, input not mutated.
|
|
467
|
+
*
|
|
468
|
+
* Matching rules:
|
|
469
|
+
* - Only fires whose normalized `file` matches the analyzed source file
|
|
470
|
+
* are considered (cross-file fires are silently skipped).
|
|
471
|
+
* - Line-level matching only (column is ignored). V8 stack columns
|
|
472
|
+
* differ from compiler-emitted span columns by 1+ chars in practice,
|
|
473
|
+
* and the user-visible affordance is "this signal at this line is
|
|
474
|
+
* firing" — line precision is sufficient.
|
|
475
|
+
* - Multiple fires at the same `line` are summed; latest `lastFire`
|
|
476
|
+
* and corresponding `kind` win.
|
|
477
|
+
* - Findings of kind `footgun`, `hoisted-static`, or `static-text` are
|
|
478
|
+
* passed through unchanged — they're not runtime-active reactive
|
|
479
|
+
* reads, so a fire count at their location is unrelated to them.
|
|
480
|
+
*/
|
|
481
|
+
declare function mergeFireDataIntoFindings(findings: ReactivityFinding[], fires: readonly LPIHFireDatum[], sourceFile: string, options?: LPIHMergeOptions): ReactivityFinding[];
|
|
482
|
+
/**
|
|
483
|
+
* Synthesize "creation-site" inlay-hint findings directly from fire data.
|
|
484
|
+
*
|
|
485
|
+
* `analyzeReactivity()` produces findings at REACTIVE READ sites (JSX
|
|
486
|
+
* expressions). But the runtime captures fires at CREATION sites
|
|
487
|
+
* (`signal(0)`, `computed(...)`, `effect(...)`). These are usually
|
|
488
|
+
* different source lines — so the merge function above only helps when
|
|
489
|
+
* they happen to coincide.
|
|
490
|
+
*
|
|
491
|
+
* The simpler, more useful editor surface is: show fire counts AT THE
|
|
492
|
+
* CREATION LINE. The user writes `const count = signal(0)` and sees
|
|
493
|
+
* `(signal fired 129×)` as ghost text on that line, the same way
|
|
494
|
+
* TypeScript shows the inferred type.
|
|
495
|
+
*
|
|
496
|
+
* This function turns each fire datum into a synthetic finding the LSP
|
|
497
|
+
* can serve as an inlay hint. No static analysis required — pure runtime
|
|
498
|
+
* data → editor hint.
|
|
499
|
+
*
|
|
500
|
+
* Returns findings sorted by (line, column). Files that don't match
|
|
501
|
+
* `sourceFile` (after normalization) are skipped.
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* import { firesToCreationSiteFindings } from '@pyreon/compiler'
|
|
505
|
+
* import { getFireSummaries } from '@pyreon/reactivity'
|
|
506
|
+
*
|
|
507
|
+
* const fires = getFireSummaries().map(s => ({
|
|
508
|
+
* file: s.loc.file, line: s.loc.line, count: s.count, kind: s.kind,
|
|
509
|
+
* }))
|
|
510
|
+
* const findings = firesToCreationSiteFindings(fires, 'app.tsx')
|
|
511
|
+
* // [{ kind: 'live-fire', line: 5, detail: 'signal fired 129×', ... }]
|
|
512
|
+
*/
|
|
513
|
+
declare function firesToCreationSiteFindings(fires: readonly LPIHFireDatum[], sourceFile: string, options?: LPIHMergeOptions): ReactivityFinding[];
|
|
514
|
+
//#endregion
|
|
422
515
|
//#region src/project-scanner.d.ts
|
|
423
516
|
/**
|
|
424
517
|
* Project scanner — extracts route, component, and island information from source files.
|
|
@@ -642,5 +735,5 @@ interface SsgAuditFormatOptions {
|
|
|
642
735
|
}
|
|
643
736
|
declare function formatSsgAudit(result: SsgAuditResult, _options?: SsgAuditFormatOptions): string;
|
|
644
737
|
//#endregion
|
|
645
|
-
export { type AnalyzeReactivityResult, type AuditFormatOptions, type AuditRisk, type CollapsibleSite, type CompilerWarning, type ComponentInfo, type DeferInlineResult, type DeferInlineWarning, type ErrorDiagnosis, type IslandAuditFormatOptions, type IslandAuditResult, type IslandFinding, type IslandFindingCode, type IslandInfo, type IslandLocation, type MigrationChange, type MigrationResult, type ProjectContext, type PyreonDiagnostic, type PyreonDiagnosticCode, type ReactDiagnostic, type ReactDiagnosticCode, type ReactivityFinding, type ReactivityFindingKind, type ReactivityKind, type ReactivitySpan, type RouteInfo, type SsgAuditFormatOptions, type SsgAuditResult, type SsgFinding, type SsgFindingCode, type SsgLocation, type TestAuditEntry, type TestAuditResult, type TransformResult, analyzeReactivity, auditIslands, auditSsg, auditTestEnvironment, detectPyreonPatterns, detectReactPatterns, diagnoseError, formatIslandAudit, formatReactivityLens, formatSsgAudit, formatTestAudit, generateContext, hasPyreonPatterns, hasReactPatterns, migrateReactCode, rocketstyleCollapseKey, scanCollapsibleSites, transformDeferInline, transformJSX, transformJSX_JS };
|
|
738
|
+
export { type AnalyzeReactivityResult, type AuditFormatOptions, type AuditRisk, type CollapsibleSite, type CompilerWarning, type ComponentInfo, type DeferInlineResult, type DeferInlineWarning, type ErrorDiagnosis, type IslandAuditFormatOptions, type IslandAuditResult, type IslandFinding, type IslandFindingCode, type IslandInfo, type IslandLocation, type LPIHFireDatum, type LPIHMergeOptions, type MigrationChange, type MigrationResult, type ProjectContext, type PyreonDiagnostic, type PyreonDiagnosticCode, type ReactDiagnostic, type ReactDiagnosticCode, type ReactivityFinding, type ReactivityFindingKind, type ReactivityKind, type ReactivitySpan, type RouteInfo, type SsgAuditFormatOptions, type SsgAuditResult, type SsgFinding, type SsgFindingCode, type SsgLocation, type TestAuditEntry, type TestAuditResult, type TransformResult, analyzeReactivity, auditIslands, auditSsg, auditTestEnvironment, detectPyreonPatterns, detectReactPatterns, diagnoseError, firesToCreationSiteFindings, formatIslandAudit, formatReactivityLens, formatSsgAudit, formatTestAudit, generateContext, hasPyreonPatterns, hasReactPatterns, mergeFireDataIntoFindings, migrateReactCode, rocketstyleCollapseKey, scanCollapsibleSites, transformDeferInline, transformJSX, transformJSX_JS };
|
|
646
739
|
//# sourceMappingURL=index2.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.1",
|
|
4
4
|
"description": "Template and JSX compiler for Pyreon",
|
|
5
5
|
"homepage": "https://github.com/pyreon/pyreon/tree/main/packages/compiler#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -48,20 +48,20 @@
|
|
|
48
48
|
"oxc-parser": "^0.129.0"
|
|
49
49
|
},
|
|
50
50
|
"optionalDependencies": {
|
|
51
|
-
"@pyreon/compiler-darwin-arm64": "^0.
|
|
52
|
-
"@pyreon/compiler-darwin-x64": "^0.
|
|
53
|
-
"@pyreon/compiler-linux-arm64-gnu": "^0.
|
|
54
|
-
"@pyreon/compiler-linux-arm64-musl": "^0.
|
|
55
|
-
"@pyreon/compiler-linux-x64-gnu": "^0.
|
|
56
|
-
"@pyreon/compiler-linux-x64-musl": "^0.
|
|
57
|
-
"@pyreon/compiler-win32-x64-msvc": "^0.
|
|
51
|
+
"@pyreon/compiler-darwin-arm64": "^0.24.1",
|
|
52
|
+
"@pyreon/compiler-darwin-x64": "^0.24.1",
|
|
53
|
+
"@pyreon/compiler-linux-arm64-gnu": "^0.24.1",
|
|
54
|
+
"@pyreon/compiler-linux-arm64-musl": "^0.24.1",
|
|
55
|
+
"@pyreon/compiler-linux-x64-gnu": "^0.24.1",
|
|
56
|
+
"@pyreon/compiler-linux-x64-musl": "^0.24.1",
|
|
57
|
+
"@pyreon/compiler-win32-x64-msvc": "^0.24.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@pyreon/core": "^0.
|
|
60
|
+
"@pyreon/core": "^0.24.1",
|
|
61
61
|
"@pyreon/manifest": "0.13.1",
|
|
62
|
-
"@pyreon/reactivity": "^0.
|
|
63
|
-
"@pyreon/runtime-dom": "^0.
|
|
64
|
-
"@pyreon/test-utils": "^0.13.
|
|
62
|
+
"@pyreon/reactivity": "^0.24.1",
|
|
63
|
+
"@pyreon/runtime-dom": "^0.24.1",
|
|
64
|
+
"@pyreon/test-utils": "^0.13.11",
|
|
65
65
|
"happy-dom": "^20.8.3"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,8 @@ export type {
|
|
|
16
16
|
ReactivityFindingKind,
|
|
17
17
|
} from './reactivity-lens'
|
|
18
18
|
export { analyzeReactivity, formatReactivityLens } from './reactivity-lens'
|
|
19
|
+
export type { LPIHFireDatum, LPIHMergeOptions } from './lpih'
|
|
20
|
+
export { firesToCreationSiteFindings, mergeFireDataIntoFindings } from './lpih'
|
|
19
21
|
export type { ComponentInfo, IslandInfo, ProjectContext, RouteInfo } from './project-scanner'
|
|
20
22
|
export { generateContext } from './project-scanner'
|
|
21
23
|
export type {
|