one 1.26.0 → 1.26.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/dist/cjs/router/getNormalizedStatePath.cjs +2 -1
- package/dist/cjs/router/getNormalizedStatePath.native.js +2 -1
- package/dist/cjs/router/getNormalizedStatePath.native.js.map +1 -1
- package/dist/cjs/router/getRouteInfo.cjs +6 -2
- package/dist/cjs/router/getRouteInfo.native.js +6 -2
- package/dist/cjs/router/getRouteInfo.native.js.map +1 -1
- package/dist/cjs/router/getRouteInfo.test.cjs +35 -0
- package/dist/cjs/router/getRouteInfo.test.native.js +42 -0
- package/dist/cjs/router/getRouteInfo.test.native.js.map +1 -0
- package/dist/cjs/router/path.cjs +1 -0
- package/dist/cjs/router/path.native.js +1 -0
- package/dist/cjs/router/path.native.js.map +1 -1
- package/dist/cjs/router/routeHmr.native.js +2 -5
- package/dist/cjs/router/routeHmr.native.js.map +1 -1
- package/dist/cjs/router/routeHmr.native.test.cjs +23 -9
- package/dist/cjs/router/routeHmr.native.test.native.js +27 -9
- package/dist/cjs/router/routeHmr.native.test.native.js.map +1 -1
- package/dist/cjs/router/useScreens.cjs +15 -19
- package/dist/cjs/router/useScreens.native.js +15 -19
- package/dist/cjs/router/useScreens.native.js.map +1 -1
- package/dist/cjs/router/useScreens.test.cjs +78 -0
- package/dist/cjs/router/useScreens.test.native.js +88 -1
- package/dist/cjs/router/useScreens.test.native.js.map +1 -1
- package/dist/cjs/router/useViteRoutes.cjs +3 -2
- package/dist/cjs/router/useViteRoutes.native.js +3 -2
- package/dist/cjs/router/useViteRoutes.native.js.map +1 -1
- package/dist/cjs/useFocusEffect.cjs +7 -1
- package/dist/cjs/useFocusEffect.native.js +9 -4
- package/dist/cjs/useFocusEffect.native.js.map +1 -1
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.cjs +7 -1
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.native.js +7 -1
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.test.cjs +15 -0
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.test.native.js +16 -0
- package/dist/cjs/vite/plugins/sourceInspectorPlugin.test.native.js.map +1 -1
- package/dist/esm/router/getNormalizedStatePath.mjs +2 -1
- package/dist/esm/router/getNormalizedStatePath.mjs.map +1 -1
- package/dist/esm/router/getNormalizedStatePath.native.js +2 -1
- package/dist/esm/router/getNormalizedStatePath.native.js.map +1 -1
- package/dist/esm/router/getRouteInfo.mjs +5 -2
- package/dist/esm/router/getRouteInfo.mjs.map +1 -1
- package/dist/esm/router/getRouteInfo.native.js +5 -2
- package/dist/esm/router/getRouteInfo.native.js.map +1 -1
- package/dist/esm/router/getRouteInfo.test.mjs +36 -0
- package/dist/esm/router/getRouteInfo.test.mjs.map +1 -0
- package/dist/esm/router/getRouteInfo.test.native.js +40 -0
- package/dist/esm/router/getRouteInfo.test.native.js.map +1 -0
- package/dist/esm/router/path.mjs +1 -1
- package/dist/esm/router/path.mjs.map +1 -1
- package/dist/esm/router/path.native.js +1 -1
- package/dist/esm/router/path.native.js.map +1 -1
- package/dist/esm/router/routeHmr.native.js +2 -5
- package/dist/esm/router/routeHmr.native.js.map +1 -1
- package/dist/esm/router/routeHmr.native.test.js +21 -11
- package/dist/esm/router/routeHmr.native.test.js.map +1 -1
- package/dist/esm/router/routeHmr.native.test.mjs +23 -9
- package/dist/esm/router/routeHmr.native.test.mjs.map +1 -1
- package/dist/esm/router/routeHmr.native.test.native.js +27 -9
- package/dist/esm/router/routeHmr.native.test.native.js.map +1 -1
- package/dist/esm/router/useScreens.mjs +15 -18
- package/dist/esm/router/useScreens.mjs.map +1 -1
- package/dist/esm/router/useScreens.native.js +15 -18
- package/dist/esm/router/useScreens.native.js.map +1 -1
- package/dist/esm/router/useScreens.test.mjs +76 -0
- package/dist/esm/router/useScreens.test.mjs.map +1 -1
- package/dist/esm/router/useScreens.test.native.js +86 -0
- package/dist/esm/router/useScreens.test.native.js.map +1 -1
- package/dist/esm/router/useViteRoutes.mjs +3 -2
- package/dist/esm/router/useViteRoutes.mjs.map +1 -1
- package/dist/esm/router/useViteRoutes.native.js +3 -2
- package/dist/esm/router/useViteRoutes.native.js.map +1 -1
- package/dist/esm/useFocusEffect.mjs +8 -2
- package/dist/esm/useFocusEffect.mjs.map +1 -1
- package/dist/esm/useFocusEffect.native.js +10 -5
- package/dist/esm/useFocusEffect.native.js.map +1 -1
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js.map +1 -1
- package/dist/esm/vite/plugins/sourceInspectorPlugin.mjs +7 -2
- package/dist/esm/vite/plugins/sourceInspectorPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/sourceInspectorPlugin.native.js +7 -2
- package/dist/esm/vite/plugins/sourceInspectorPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/sourceInspectorPlugin.test.mjs +16 -1
- package/dist/esm/vite/plugins/sourceInspectorPlugin.test.mjs.map +1 -1
- package/dist/esm/vite/plugins/sourceInspectorPlugin.test.native.js +17 -1
- package/dist/esm/vite/plugins/sourceInspectorPlugin.test.native.js.map +1 -1
- package/package.json +11 -11
- package/src/router/getNormalizedStatePath.tsx +2 -1
- package/src/router/getRouteInfo.test.ts +33 -0
- package/src/router/getRouteInfo.ts +5 -2
- package/src/router/path.ts +1 -1
- package/src/router/routeHmr.native.test.ts +23 -11
- package/src/router/routeHmr.native.ts +6 -4
- package/src/router/useScreens.test.tsx +72 -0
- package/src/router/useScreens.tsx +11 -19
- package/src/router/useViteRoutes.tsx +3 -2
- package/src/useFocusEffect.ts +14 -4
- package/src/vite/one.ts +3 -1
- package/src/vite/plugins/sourceInspectorPlugin.test.ts +37 -1
- package/src/vite/plugins/sourceInspectorPlugin.ts +24 -3
- package/types/router/getNormalizedStatePath.d.ts.map +1 -1
- package/types/router/getRouteInfo.d.ts +5 -0
- package/types/router/getRouteInfo.d.ts.map +1 -1
- package/types/router/getRouteInfo.test.d.ts +2 -0
- package/types/router/getRouteInfo.test.d.ts.map +1 -0
- package/types/router/path.d.ts +1 -0
- package/types/router/path.d.ts.map +1 -1
- package/types/router/routeHmr.native.d.ts.map +1 -1
- package/types/router/useScreens.d.ts.map +1 -1
- package/types/router/useViteRoutes.d.ts.map +1 -1
- package/types/useFocusEffect.d.ts.map +1 -1
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/plugins/sourceInspectorPlugin.d.ts +9 -0
- package/types/vite/plugins/sourceInspectorPlugin.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["describe","expect","it","getSourceInspectorPath","resolveEditorFilePath","toBe","fileExists","filePath"],"sources":["../../../../src/vite/plugins/sourceInspectorPlugin.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AAErC,
|
|
1
|
+
{"version":3,"names":["describe","expect","it","getSourceInspectorPath","injectSourceToJsx","resolveEditorFilePath","toBe","fileExists","filePath","out","join","process","cwd","code","toContain","not","toMatch"],"sources":["../../../../src/vite/plugins/sourceInspectorPlugin.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AAErC,SACEC,sBAAA,EACAC,iBAAA,EACAC,qBAAA,QACK;AAEPL,QAAA,CAAS,iCAAiC,MAAM;EAC9CA,QAAA,CAAS,0BAA0B,MAAM;IACvCE,EAAA,CAAG,mDAAmD,MAAM;MAC1DD,MAAA,CAAOE,sBAAA,CAAuB,kCAAkC,OAAO,CAAC,EAAEG,IAAA,CACxE,2BACF;IACF,CAAC;IAEDJ,EAAA,CAAG,gEAAgE,MAAM;MACvED,MAAA,CACEE,sBAAA,CAAuB,wCAAwC,OAAO,CACxE,EAAEG,IAAA,CAAK,sCAAsC;IAC/C,CAAC;EACH,CAAC;EAEDN,QAAA,CAAS,yBAAyB,MAAM;IACtCE,EAAA,CAAG,sDAAsD,MAAM;MAC7D,MAAMK,UAAA,GAAcC,QAAA,IAClBA,QAAA,KAAa;MAEfP,MAAA,CACEI,qBAAA,CAAsB,6BAA6B,SAASE,UAAU,CACxE,EAAED,IAAA,CAAK,gCAAgC;IACzC,CAAC;IAEDJ,EAAA,CAAG,yDAAyD,MAAM;MAChED,MAAA,CACEI,qBAAA,CACE,kCACA,mBACA,MAAM,KACR,CACF,EAAEC,IAAA,CAAK,gCAAgC;IACzC,CAAC;EACH,CAAC;EAEDN,QAAA,CAAS,qBAAqB,MAAM;IAClCE,EAAA,CAAG,4EAA4E,YAAY;MACzF,MAAMO,GAAA,GAAM,MAAML,iBAAA,CAChB,CACE,gCACA,WACA,gBACA,qCACA,2BACA,gDACA,iBACA,0DACA,iBACA,4CACA,YACA,IACF,CAAEM,IAAA,CAAK,IAAI,GACX,GAAGC,OAAA,CAAQC,GAAA,CAAI,CAAC,gBAClB;MACA,MAAMC,IAAA,GAAOJ,GAAA,EAAKI,IAAA,IAAQ;MAC1BZ,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,uBAAuB;MAC9Cb,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,0BAA0B;MACjDb,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,uBAAuB;MAC9Cb,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,kCAAkC;MACzDb,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,iBAAiB;MACxCb,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,iBAAiB;MACxCb,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,8BAA8B;MACrDb,MAAA,CAAOY,IAAI,EAAEC,SAAA,CAAU,sBAAsB;MAC7Cb,MAAA,CAAOY,IAAI,EAAEE,GAAA,CAAIC,OAAA,CAAQ,wEAAwE;IACnG,CAAC;EACH,CAAC;AACH,CAAC","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getSourceInspectorPath, resolveEditorFilePath } from "./sourceInspectorPlugin.native.js";
|
|
2
|
+
import { getSourceInspectorPath, injectSourceToJsx, resolveEditorFilePath } from "./sourceInspectorPlugin.native.js";
|
|
3
3
|
describe("sourceInspectorPlugin helpers", function () {
|
|
4
4
|
describe("getSourceInspectorPath", function () {
|
|
5
5
|
it("keeps project files relative to the current cwd", function () {
|
|
@@ -22,5 +22,21 @@ describe("sourceInspectorPlugin helpers", function () {
|
|
|
22
22
|
})).toBe("/Users/n8/shared/ui/Button.tsx");
|
|
23
23
|
});
|
|
24
24
|
});
|
|
25
|
+
describe("injectSourceToJsx", function () {
|
|
26
|
+
it("tags dom elements and components but leaves custom reconciler tags alone", async function () {
|
|
27
|
+
var _ref;
|
|
28
|
+
var out = await injectSourceToJsx(["export const Scene = () => (", " <div>", " <Canvas>", " <mesh position={[0, 1, 0]}>", " <boxGeometry />", ' <meshStandardMaterial color="red" />', " </mesh>", " <instancedMesh args={[geometry, material, 4]} />", " </Canvas>", ' <svg><linearGradient id="g" /></svg>', " </div>", ")"].join("\n"), `${process.cwd()}/src/Scene.tsx`);
|
|
29
|
+
var code = (_ref = out === null || out === void 0 ? void 0 : out.code) !== null && _ref !== void 0 ? _ref : "";
|
|
30
|
+
expect(code).toContain("<div data-one-source=");
|
|
31
|
+
expect(code).toContain("<Canvas data-one-source=");
|
|
32
|
+
expect(code).toContain("<svg data-one-source=");
|
|
33
|
+
expect(code).toContain("<linearGradient data-one-source=");
|
|
34
|
+
expect(code).toContain("<mesh position=");
|
|
35
|
+
expect(code).toContain("<boxGeometry />");
|
|
36
|
+
expect(code).toContain("<meshStandardMaterial color=");
|
|
37
|
+
expect(code).toContain("<instancedMesh args=");
|
|
38
|
+
expect(code).not.toMatch(/<(mesh|boxGeometry|meshStandardMaterial|instancedMesh) data-one-source/);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
25
41
|
});
|
|
26
42
|
//# sourceMappingURL=sourceInspectorPlugin.test.native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["describe","expect","it","getSourceInspectorPath","resolveEditorFilePath","toBe","fileExists","filePath"],"sources":["../../../../src/vite/plugins/sourceInspectorPlugin.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AAErC,
|
|
1
|
+
{"version":3,"names":["describe","expect","it","getSourceInspectorPath","injectSourceToJsx","resolveEditorFilePath","toBe","fileExists","filePath","_ref","out","join","process","cwd","code","toContain","not","toMatch"],"sources":["../../../../src/vite/plugins/sourceInspectorPlugin.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AAErC,SAAAC,sBAAA,EAAAC,iBAAA,EAAAC,qBAAA;AAAAL,QACE;EACAA,QAAA;IACAE,EAAA;MAAAD,MACK,CAAAE,sBAAA,6CAAAG,IAAA;IAEP;IACEJ,EAAA,+DAAyC;MACvCD,MAAG,CAAAE,sBAAA,uCAAyD,YAAAG,IAAA;IAC1D;EAA0E;EACxEN,QACF;IACFE,EAAC;MAED,IAAGK,UAAA,YAAAA,CAAAC,QAAA;QACD,OAAAA,QAAA;MAAA;MAEAP,MAAE,CAAKI,qBAAA,4BAAsC,WAAAE,UAAA,GAAAD,IAAA;IAC/C,CAAC;IACFJ,EAAA;MAEDD,MAAS,CAAAI,qBAAA,iCAA+B;QACnC;MACD,IAAAC,IAAM,iCACJ;IAEF;EAAA;EACwEN,QACtE,oBAAK;IACTE,EAAC;MAED,IAAGO,IAAA;MACD,IAAAC,GAAA,SAAAN,iBAAA,EACE,yCACE,gBACA,qCACM,EACR,2BACA,8CAAqC,EACxC,iBACF,0DAED,eAAS,EACJ,4CACD,UAAY,EACV,KAAAO,IACE,WAAAC,OAAA,CAAAC,GAAA;MAAA,IACAC,IAAA,IAAAL,IAAA,GAAAC,GAAA,aAAAA,GAAA,uBAAAA,GAAA,CAAAI,IAAA,cAAAL,IAAA,cAAAA,IAAA;MAAAR,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAC,SAAA;MAAAd,MACA,CAAAa,IAAA,EAAAE,GAAA,CAAAC,OAAA;IAAA;EACA;AACS","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "one",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.1",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"setup.mjs",
|
|
@@ -197,18 +197,18 @@
|
|
|
197
197
|
"@react-navigation/routers": "~7.6.4",
|
|
198
198
|
"@cloudflare/vite-plugin": "^1.33.1",
|
|
199
199
|
"@ungap/structured-clone": "^1.2.0",
|
|
200
|
-
"@vxrn/color-scheme": "1.26.
|
|
201
|
-
"@vxrn/compiler": "1.26.
|
|
202
|
-
"@vxrn/resolve": "1.26.
|
|
203
|
-
"@vxrn/tslib-lite": "1.26.
|
|
204
|
-
"@vxrn/use-isomorphic-layout-effect": "1.26.
|
|
205
|
-
"@vxrn/vite-plugin-metro": "1.26.
|
|
200
|
+
"@vxrn/color-scheme": "1.26.1",
|
|
201
|
+
"@vxrn/compiler": "1.26.1",
|
|
202
|
+
"@vxrn/resolve": "1.26.1",
|
|
203
|
+
"@vxrn/tslib-lite": "1.26.1",
|
|
204
|
+
"@vxrn/use-isomorphic-layout-effect": "1.26.1",
|
|
205
|
+
"@vxrn/vite-plugin-metro": "1.26.1",
|
|
206
206
|
"babel-dead-code-elimination": "1.0.10",
|
|
207
207
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
208
208
|
"babel-preset-expo": "~57.0.5",
|
|
209
209
|
"citty": "^0.1.6",
|
|
210
210
|
"core-js": "^3.38.1",
|
|
211
|
-
"create-vxrn": "1.26.
|
|
211
|
+
"create-vxrn": "1.26.1",
|
|
212
212
|
"escape-string-regexp": "^5.0.0",
|
|
213
213
|
"expo-linking": "~57.0.5",
|
|
214
214
|
"expo-modules-core": "~57.0.10",
|
|
@@ -229,7 +229,7 @@
|
|
|
229
229
|
"tsconfig-paths": "^4",
|
|
230
230
|
"use-latest-callback": "^0.2.3",
|
|
231
231
|
"vite": "^8.2.2",
|
|
232
|
-
"vxrn": "1.26.
|
|
232
|
+
"vxrn": "1.26.1",
|
|
233
233
|
"web-streams-polyfill": "^4.3.0",
|
|
234
234
|
"ws": "^8.21.0",
|
|
235
235
|
"xxhashjs": "^0.2.2"
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
"react-native-safe-area-context": ">=5.0.0",
|
|
248
248
|
"react-native-screens": ">=4.0.0",
|
|
249
249
|
"react-native-worklets": ">=0.7.0",
|
|
250
|
-
"sharp": "^0.35.
|
|
250
|
+
"sharp": "^0.35.4"
|
|
251
251
|
},
|
|
252
252
|
"peerDependenciesMeta": {
|
|
253
253
|
"@bottom-tabs/react-navigation": {
|
|
@@ -295,7 +295,7 @@
|
|
|
295
295
|
"react-native": "0.86.2",
|
|
296
296
|
"react-test-renderer": "^19.2.0",
|
|
297
297
|
"rolldown": "^1.2.4",
|
|
298
|
-
"sharp": "^0.35.
|
|
298
|
+
"sharp": "^0.35.4",
|
|
299
299
|
"typescript": "^5.7.3",
|
|
300
300
|
"vitest": "^4.1.0"
|
|
301
301
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { stripBaseUrl } from '../fork/getStateFromPath-mods'
|
|
2
|
+
import { stripPathSuffix } from './path'
|
|
2
3
|
|
|
3
4
|
type SearchParams = Record<string, string | string[]>
|
|
4
5
|
|
|
@@ -21,7 +22,7 @@ export function getNormalizedStatePath(
|
|
|
21
22
|
},
|
|
22
23
|
baseUrl?: string
|
|
23
24
|
): Pick<UrlObject, 'segments' | 'params'> {
|
|
24
|
-
const
|
|
25
|
+
const pathname = stripPathSuffix(statePath)
|
|
25
26
|
return {
|
|
26
27
|
// Strip empty path at the start
|
|
27
28
|
segments: stripBaseUrl(pathname, baseUrl)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { getRouteInfoFromState } from './getRouteInfo'
|
|
3
|
+
|
|
4
|
+
// a hash link (/dev#stack) keeps its hash in the serialized path; route info
|
|
5
|
+
// must still report the bare pathname or the router never sees the pending
|
|
6
|
+
// navigation land and serializes the stale state to history
|
|
7
|
+
describe('getRouteInfoFromState', () => {
|
|
8
|
+
const state = {
|
|
9
|
+
routes: [{ name: 'dev', path: '/dev#stack', params: { '#': 'stack' } }],
|
|
10
|
+
} as any
|
|
11
|
+
|
|
12
|
+
it('drops the hash from pathname and segments', () => {
|
|
13
|
+
const info = getRouteInfoFromState(
|
|
14
|
+
(_state, asPath) => ({
|
|
15
|
+
path: asPath ? '/(site)/dev#stack' : '/dev#stack',
|
|
16
|
+
params: { '#': 'stack' },
|
|
17
|
+
}),
|
|
18
|
+
state
|
|
19
|
+
)
|
|
20
|
+
expect(info.pathname).toBe('/dev')
|
|
21
|
+
expect(info.segments).toEqual(['(site)', 'dev'])
|
|
22
|
+
expect(info.unstable_globalHref).toBe('/dev#stack')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('drops the query and the hash together', () => {
|
|
26
|
+
const info = getRouteInfoFromState(
|
|
27
|
+
() => ({ path: '/dev?x=1#stack', params: { x: '1', '#': 'stack' } }),
|
|
28
|
+
state
|
|
29
|
+
)
|
|
30
|
+
expect(info.pathname).toBe('/dev')
|
|
31
|
+
expect(info.segments).toEqual(['dev'])
|
|
32
|
+
})
|
|
33
|
+
})
|
|
@@ -5,6 +5,7 @@ import type { OneRouter } from '../interfaces/router'
|
|
|
5
5
|
import { getNormalizedStatePath, type UrlObject } from './getNormalizedStatePath'
|
|
6
6
|
import { isIndexPath } from './isIndexPath'
|
|
7
7
|
import { getResolvedLinking } from './linkingConfig'
|
|
8
|
+
import { stripPathSuffix } from './path'
|
|
8
9
|
|
|
9
10
|
export function getRouteInfo(state: OneRouter.ResultState) {
|
|
10
11
|
return getRouteInfoFromState(
|
|
@@ -20,7 +21,7 @@ export function getRouteInfo(state: OneRouter.ResultState) {
|
|
|
20
21
|
)
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
function getRouteInfoFromState(
|
|
24
|
+
export function getRouteInfoFromState(
|
|
24
25
|
getPathFromState: (state: State, asPath: boolean) => { path: string; params: any },
|
|
25
26
|
state: State,
|
|
26
27
|
baseUrl?: string
|
|
@@ -30,7 +31,9 @@ function getRouteInfoFromState(
|
|
|
30
31
|
|
|
31
32
|
return {
|
|
32
33
|
unstable_globalHref: path,
|
|
33
|
-
pathname
|
|
34
|
+
// a hash href serializes as /page#section; the pathname the router compares
|
|
35
|
+
// against pending navigation and the URL must drop the hash as well as the query
|
|
36
|
+
pathname: stripPathSuffix(stripBaseUrl(path, baseUrl)),
|
|
34
37
|
isIndex: isIndexPath(state),
|
|
35
38
|
...getNormalizedStatePath(qualified, baseUrl),
|
|
36
39
|
}
|
package/src/router/path.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { stripBaseUrl } from '../fork/getStateFromPath-mods'
|
|
2
2
|
|
|
3
|
-
function stripPathSuffix(path: string): string {
|
|
3
|
+
export function stripPathSuffix(path: string): string {
|
|
4
4
|
const queryIndex = path.indexOf('?')
|
|
5
5
|
const hashIndex = path.indexOf('#')
|
|
6
6
|
let end = path.length
|
|
@@ -25,35 +25,48 @@ describe('routeHmr.native', () => {
|
|
|
25
25
|
expect(typeof globalThis.__VXRN_ON_MODULE_UPDATED__).toBe('function')
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
-
it('
|
|
28
|
+
it('does not bump the epoch, so Fast Refresh can keep the mounted route', () => {
|
|
29
29
|
const before = routeHmr.getRouteHmrEpoch()
|
|
30
30
|
const listener = vi.fn()
|
|
31
31
|
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
|
|
32
32
|
|
|
33
33
|
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')
|
|
34
|
-
expect(routeHmr.getRouteHmrEpoch()).toBe(before
|
|
35
|
-
expect(listener).
|
|
34
|
+
expect(routeHmr.getRouteHmrEpoch()).toBe(before)
|
|
35
|
+
expect(listener).not.toHaveBeenCalled()
|
|
36
36
|
|
|
37
37
|
unsubscribe()
|
|
38
|
-
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')
|
|
39
|
-
expect(listener).toHaveBeenCalledTimes(1)
|
|
40
38
|
})
|
|
41
39
|
|
|
42
40
|
it('evicts the route cache for the updated file when window.__oneRouteCache is present', () => {
|
|
43
|
-
const clearFile = vi.fn()
|
|
41
|
+
const clearFile = vi.fn(() => true)
|
|
44
42
|
;(globalThis as any).window = { __oneRouteCache: { clearFile } }
|
|
45
43
|
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/_layout.tsx')
|
|
46
44
|
expect(clearFile).toHaveBeenCalledWith('app/_layout.tsx')
|
|
47
45
|
})
|
|
48
46
|
|
|
47
|
+
it('does not bump the epoch for a non-route module either', () => {
|
|
48
|
+
const before = routeHmr.getRouteHmrEpoch()
|
|
49
|
+
const listener = vi.fn()
|
|
50
|
+
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
|
|
51
|
+
;(globalThis as any).window = {
|
|
52
|
+
__oneRouteCache: { clearFile: () => false },
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
globalThis.__VXRN_ON_MODULE_UPDATED__!('features/onboarding/HmrProbeChild.tsx')
|
|
56
|
+
expect(routeHmr.getRouteHmrEpoch()).toBe(before)
|
|
57
|
+
expect(listener).not.toHaveBeenCalled()
|
|
58
|
+
unsubscribe()
|
|
59
|
+
})
|
|
60
|
+
|
|
49
61
|
it('does not throw when window / route cache is absent', () => {
|
|
50
62
|
;(globalThis as any).window = undefined
|
|
51
63
|
expect(() => globalThis.__VXRN_ON_MODULE_UPDATED__!('x.tsx')).not.toThrow()
|
|
52
64
|
})
|
|
53
65
|
|
|
54
|
-
it('
|
|
66
|
+
it('does not throw or bump the epoch when route-cache eviction throws', () => {
|
|
55
67
|
const listener = vi.fn()
|
|
56
68
|
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
|
|
69
|
+
const before = routeHmr.getRouteHmrEpoch()
|
|
57
70
|
;(globalThis as any).window = {
|
|
58
71
|
__oneRouteCache: {
|
|
59
72
|
clearFile() {
|
|
@@ -62,10 +75,9 @@ describe('routeHmr.native', () => {
|
|
|
62
75
|
},
|
|
63
76
|
}
|
|
64
77
|
|
|
65
|
-
expect(() => globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')).toThrow(
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
expect(listener).toHaveBeenCalledOnce()
|
|
78
|
+
expect(() => globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')).not.toThrow()
|
|
79
|
+
expect(routeHmr.getRouteHmrEpoch()).toBe(before)
|
|
80
|
+
expect(listener).not.toHaveBeenCalled()
|
|
69
81
|
unsubscribe()
|
|
70
82
|
})
|
|
71
83
|
})
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// native Fast Refresh for One routes
|
|
2
2
|
//
|
|
3
3
|
// vxrn calls the global hook after committing an updated module. One evicts that
|
|
4
|
-
// route
|
|
4
|
+
// route from the loader cache so the next loadRoute() sees fresh exports. it
|
|
5
|
+
// does not bump the epoch: ScreenComponent re-running loadRoute() would render a
|
|
6
|
+
// new function identity and remount the route, which is what made
|
|
7
|
+
// `generation:1` jump to `generation:2` when a route file was Fast Refreshed.
|
|
5
8
|
|
|
6
9
|
declare global {
|
|
7
10
|
// vxrn's native HMR runtime invokes this (when defined) with each committed
|
|
@@ -29,9 +32,8 @@ if (process.env.NODE_ENV === 'development') {
|
|
|
29
32
|
if (typeof routeCache?.clearFile === 'function') {
|
|
30
33
|
routeCache.clearFile(id)
|
|
31
34
|
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
routeHmrListeners.forEach((listener) => listener())
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('[one] route cache eviction failed', error)
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -137,3 +137,75 @@ describe('route SuspenseFallback', () => {
|
|
|
137
137
|
expect(renderer!.toJSON()).toBeNull()
|
|
138
138
|
})
|
|
139
139
|
})
|
|
140
|
+
|
|
141
|
+
describe('ErrorBoundary route identity', () => {
|
|
142
|
+
it('preserves page state across a re-render when the route exports ErrorBoundary', async () => {
|
|
143
|
+
let mounts = 0
|
|
144
|
+
function Page() {
|
|
145
|
+
const [count, setCount] = React.useState(0)
|
|
146
|
+
React.useEffect(() => {
|
|
147
|
+
mounts += 1
|
|
148
|
+
}, [])
|
|
149
|
+
return (
|
|
150
|
+
<button data-count={count} onClick={() => setCount((value) => value + 1)}>
|
|
151
|
+
{count}
|
|
152
|
+
</button>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
function ErrorBoundary() {
|
|
156
|
+
return <div data-error="1" />
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const node = createRouteNode('spa', 'onboarding', './auth/onboarding.tsx', () => ({
|
|
160
|
+
default: Page,
|
|
161
|
+
ErrorBoundary,
|
|
162
|
+
}))
|
|
163
|
+
const Route = getQualifiedRouteComponent(node)
|
|
164
|
+
|
|
165
|
+
function Harness({ tick }: { tick: number }) {
|
|
166
|
+
return <Route tick={tick} />
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
let renderer: TestRenderer.ReactTestRenderer
|
|
170
|
+
await act(async () => {
|
|
171
|
+
renderer = TestRenderer.create(<Harness tick={0} />)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
const button = renderer!.root.findByType('button')
|
|
175
|
+
expect(button.props['data-count']).toBe(0)
|
|
176
|
+
await act(async () => {
|
|
177
|
+
button.props.onClick()
|
|
178
|
+
})
|
|
179
|
+
expect(renderer!.root.findByType('button').props['data-count']).toBe(1)
|
|
180
|
+
expect(mounts).toBe(1)
|
|
181
|
+
|
|
182
|
+
await act(async () => {
|
|
183
|
+
renderer.update(<Harness tick={1} />)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
expect(renderer!.root.findByType('button').props['data-count']).toBe(1)
|
|
187
|
+
expect(mounts).toBe(1)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
it('still renders the exported ErrorBoundary when the page throws', async () => {
|
|
191
|
+
function Page(): React.ReactNode {
|
|
192
|
+
throw new Error('boom')
|
|
193
|
+
}
|
|
194
|
+
function ErrorBoundary({ error }: { error: Error; retry: () => Promise<void> }) {
|
|
195
|
+
return <div data-caught={error.message} />
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const node = createRouteNode('spa', 'broken', './broken.tsx', () => ({
|
|
199
|
+
default: Page,
|
|
200
|
+
ErrorBoundary,
|
|
201
|
+
}))
|
|
202
|
+
const Route = getQualifiedRouteComponent(node)
|
|
203
|
+
|
|
204
|
+
let renderer: TestRenderer.ReactTestRenderer
|
|
205
|
+
await act(async () => {
|
|
206
|
+
renderer = TestRenderer.create(<Route />)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
expect(renderer!.root.findByProps({ 'data-caught': 'boom' })).toBeTruthy()
|
|
210
|
+
})
|
|
211
|
+
})
|
|
@@ -350,26 +350,16 @@ export function useSortedScreens(
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
function fromImport({ ErrorBoundary, SuspenseFallback, ...component }: LoadedRoute) {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
default: React.forwardRef((props: any, ref: any) => {
|
|
356
|
-
const children = React.createElement(getPageExport(component) || EmptyRoute, {
|
|
357
|
-
...props,
|
|
358
|
-
ref,
|
|
359
|
-
})
|
|
360
|
-
return <Try catch={ErrorBoundary}>{children}</Try>
|
|
361
|
-
}),
|
|
362
|
-
SuspenseFallback,
|
|
363
|
-
}
|
|
364
|
-
}
|
|
353
|
+
// keep ErrorBoundary on the returned module and wrap it in JSX below.
|
|
354
|
+
// a new forwardRef here remounts the route on every ScreenComponent render.
|
|
365
355
|
if (process.env.NODE_ENV !== 'production') {
|
|
366
356
|
const exported = getPageExport(component)
|
|
367
357
|
if (exported && typeof exported === 'object' && Object.keys(exported).length === 0) {
|
|
368
|
-
return { default: EmptyRoute, SuspenseFallback }
|
|
358
|
+
return { default: EmptyRoute, ErrorBoundary, SuspenseFallback }
|
|
369
359
|
}
|
|
370
360
|
}
|
|
371
361
|
|
|
372
|
-
return { default: getPageExport(component), SuspenseFallback }
|
|
362
|
+
return { default: getPageExport(component), ErrorBoundary, SuspenseFallback }
|
|
373
363
|
}
|
|
374
364
|
|
|
375
365
|
function RouteSuspenseFallback({
|
|
@@ -422,9 +412,9 @@ export function getQualifiedRouteComponent(value: RouteNode) {
|
|
|
422
412
|
}, [])
|
|
423
413
|
}
|
|
424
414
|
|
|
425
|
-
// native Fast Refresh: subscribe to the route-hot epoch
|
|
426
|
-
//
|
|
427
|
-
//
|
|
415
|
+
// native Fast Refresh: subscribe to the route-hot epoch. route file patches
|
|
416
|
+
// are applied in place and do not bump it; a bump re-runs loadRoute() and
|
|
417
|
+
// remounts the screen.
|
|
428
418
|
if (
|
|
429
419
|
process.env.NODE_ENV === 'development' &&
|
|
430
420
|
process.env.TAMAGUI_TARGET === 'native'
|
|
@@ -451,7 +441,8 @@ export function getQualifiedRouteComponent(value: RouteNode) {
|
|
|
451
441
|
}
|
|
452
442
|
|
|
453
443
|
const res = fromImport(value.loadRoute())
|
|
454
|
-
const Component =
|
|
444
|
+
const Component = (res.default || EmptyRoute) as React.ComponentType<any>
|
|
445
|
+
const CatchBoundary = res.ErrorBoundary
|
|
455
446
|
const LayoutSuspenseFallback =
|
|
456
447
|
value.type === 'layout' ? res.SuspenseFallback : undefined
|
|
457
448
|
const match =
|
|
@@ -491,9 +482,10 @@ export function getQualifiedRouteComponent(value: RouteNode) {
|
|
|
491
482
|
/>
|
|
492
483
|
)
|
|
493
484
|
} else {
|
|
485
|
+
const page = <Component {...props} {...slotProps} {...loaderDataProps} ref={ref} />
|
|
494
486
|
rendered = (
|
|
495
487
|
<RouteErrorBoundary routeName={value.route}>
|
|
496
|
-
<
|
|
488
|
+
{CatchBoundary ? <Try catch={CatchBoundary}>{page}</Try> : page}
|
|
497
489
|
</RouteErrorBoundary>
|
|
498
490
|
)
|
|
499
491
|
}
|
|
@@ -227,17 +227,18 @@ export function globbedRoutesToRouteContext(
|
|
|
227
227
|
})
|
|
228
228
|
},
|
|
229
229
|
clearFile: (file: string) => {
|
|
230
|
-
hmrVersion++
|
|
231
230
|
const normalizedFile = file.replace(/\\/g, '/').replace(/^\//, '')
|
|
232
231
|
const routeId = moduleKeys.find(
|
|
233
232
|
(key) =>
|
|
234
233
|
routePaths[key].replace(/\\/g, '/').replace(/^\//, '') === normalizedFile
|
|
235
234
|
)
|
|
236
|
-
if (!routeId) return
|
|
235
|
+
if (!routeId) return false
|
|
237
236
|
|
|
237
|
+
hmrVersion++
|
|
238
238
|
delete loadedRoutes[routeId]
|
|
239
239
|
delete promises[routeId]
|
|
240
240
|
delete preloadedModules[routePaths[routeId]]
|
|
241
|
+
return true
|
|
241
242
|
},
|
|
242
243
|
getVersion: () => hmrVersion,
|
|
243
244
|
}
|
package/src/useFocusEffect.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// A fork of `useFocusEffect` that waits for the navigation state to load before
|
|
2
2
|
// running the effect. This is especially useful for native redirects.
|
|
3
3
|
|
|
4
|
-
import { useEffect } from 'react'
|
|
4
|
+
import { useEffect, useRef } from 'react'
|
|
5
5
|
import { useOptionalNavigation } from './link/useLoadedNavigation'
|
|
6
6
|
|
|
7
7
|
type EffectCallback = () => undefined | void | (() => void)
|
|
@@ -30,6 +30,18 @@ type EffectCallback = () => undefined | void | (() => void)
|
|
|
30
30
|
export function useFocusEffect(effect: EffectCallback, deps: any[] = []) {
|
|
31
31
|
const navigation = useOptionalNavigation()
|
|
32
32
|
|
|
33
|
+
const prevDepsRef = useRef(deps)
|
|
34
|
+
const depsCountRef = useRef(0)
|
|
35
|
+
if (
|
|
36
|
+
!Array.isArray(deps) ||
|
|
37
|
+
!Array.isArray(prevDepsRef.current) ||
|
|
38
|
+
prevDepsRef.current.length !== deps.length ||
|
|
39
|
+
prevDepsRef.current.some((d, i) => !Object.is(d, deps[i]))
|
|
40
|
+
) {
|
|
41
|
+
prevDepsRef.current = deps
|
|
42
|
+
depsCountRef.current++
|
|
43
|
+
}
|
|
44
|
+
|
|
33
45
|
useEffect(() => {
|
|
34
46
|
if (!navigation) {
|
|
35
47
|
return
|
|
@@ -102,7 +114,5 @@ export function useFocusEffect(effect: EffectCallback, deps: any[] = []) {
|
|
|
102
114
|
unsubscribeFocus()
|
|
103
115
|
unsubscribeBlur()
|
|
104
116
|
}
|
|
105
|
-
|
|
106
|
-
// would otherwise throw "deps is not iterable" and crash the screen.
|
|
107
|
-
}, [navigation, ...(Array.isArray(deps) ? deps : [])])
|
|
117
|
+
}, [navigation, depsCountRef.current])
|
|
108
118
|
}
|
package/src/vite/one.ts
CHANGED
|
@@ -860,7 +860,9 @@ export function one(options: One.PluginOptions = {}): PluginOption {
|
|
|
860
860
|
// environment, so nothing in `config.plugins` reaches it. one's own plugins
|
|
861
861
|
// go first, then whatever the app opted in through native.bundlerOptions.
|
|
862
862
|
const viteBundlerOptions =
|
|
863
|
-
nativeOptions?.bundler === 'metro'
|
|
863
|
+
nativeOptions?.bundler === 'metro'
|
|
864
|
+
? undefined
|
|
865
|
+
: (nativeOptions?.bundlerOptions as any)
|
|
864
866
|
|
|
865
867
|
globalThis.__vxrnAddNativePlugins = [
|
|
866
868
|
clientTreeShakePlugin({ runtime: 'rolldown', routerRoot }),
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getSourceInspectorPath,
|
|
5
|
+
injectSourceToJsx,
|
|
6
|
+
resolveEditorFilePath,
|
|
7
|
+
} from './sourceInspectorPlugin'
|
|
4
8
|
|
|
5
9
|
describe('sourceInspectorPlugin helpers', () => {
|
|
6
10
|
describe('getSourceInspectorPath', () => {
|
|
@@ -37,4 +41,36 @@ describe('sourceInspectorPlugin helpers', () => {
|
|
|
37
41
|
).toBe('/Users/n8/shared/ui/Button.tsx')
|
|
38
42
|
})
|
|
39
43
|
})
|
|
44
|
+
|
|
45
|
+
describe('injectSourceToJsx', () => {
|
|
46
|
+
it('tags dom elements and components but leaves custom reconciler tags alone', async () => {
|
|
47
|
+
const out = await injectSourceToJsx(
|
|
48
|
+
[
|
|
49
|
+
'export const Scene = () => (',
|
|
50
|
+
' <div>',
|
|
51
|
+
' <Canvas>',
|
|
52
|
+
' <mesh position={[0, 1, 0]}>',
|
|
53
|
+
' <boxGeometry />',
|
|
54
|
+
' <meshStandardMaterial color="red" />',
|
|
55
|
+
' </mesh>',
|
|
56
|
+
' <instancedMesh args={[geometry, material, 4]} />',
|
|
57
|
+
' </Canvas>',
|
|
58
|
+
' <svg><linearGradient id="g" /></svg>',
|
|
59
|
+
' </div>',
|
|
60
|
+
')',
|
|
61
|
+
].join('\n'),
|
|
62
|
+
`${process.cwd()}/src/Scene.tsx`
|
|
63
|
+
)
|
|
64
|
+
const code = out?.code ?? ''
|
|
65
|
+
expect(code).toContain('<div data-one-source=')
|
|
66
|
+
expect(code).toContain('<Canvas data-one-source=')
|
|
67
|
+
expect(code).toContain('<svg data-one-source=')
|
|
68
|
+
expect(code).toContain('<linearGradient data-one-source=')
|
|
69
|
+
expect(code).toContain('<mesh position=')
|
|
70
|
+
expect(code).toContain('<boxGeometry />')
|
|
71
|
+
expect(code).toContain('<meshStandardMaterial color=')
|
|
72
|
+
expect(code).toContain('<instancedMesh args=')
|
|
73
|
+
expect(code).not.toMatch(/<(mesh|boxGeometry|meshStandardMaterial|instancedMesh) data-one-source/)
|
|
74
|
+
})
|
|
75
|
+
})
|
|
40
76
|
})
|
|
@@ -18,6 +18,22 @@ interface JsxLocation {
|
|
|
18
18
|
/**
|
|
19
19
|
* Parse code with oxc and find all JSX opening elements.
|
|
20
20
|
*/
|
|
21
|
+
// lowercase jsx tags are host elements. on the web only real html and svg
|
|
22
|
+
// tags accept a data attribute; other lowercase tags belong to a custom
|
|
23
|
+
// reconciler (react-three-fiber's <mesh>, <group>, <instancedMesh>...) which
|
|
24
|
+
// applies props to plain objects and throws on the dashed attribute.
|
|
25
|
+
const DOM_TAGS = new Set(
|
|
26
|
+
(
|
|
27
|
+
'a abbr address area article aside audio b base bdi bdo blockquote body br button canvas caption cite code col colgroup data datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins kbd label legend li link main map mark menu meta meter nav noscript object ol optgroup option output p picture pre progress q rp rt ruby s samp script search section select slot small source span strong style sub summary sup table tbody td template textarea tfoot th thead time title tr track u ul var video wbr ' +
|
|
28
|
+
'svg animate animateMotion animateTransform circle clipPath defs desc ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter foreignObject g image line linearGradient marker mask metadata mpath path pattern polygon polyline radialGradient rect set stop switch symbol text textPath tspan use view'
|
|
29
|
+
).split(' ')
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
function isHostTag(tagName: string): boolean {
|
|
33
|
+
const first = tagName.charCodeAt(0)
|
|
34
|
+
return first >= 97 && first <= 122 && !tagName.includes('.')
|
|
35
|
+
}
|
|
36
|
+
|
|
21
37
|
async function findJsxElements(code: string, filename: string): Promise<JsxLocation[]> {
|
|
22
38
|
const result = await parse(filename, code)
|
|
23
39
|
|
|
@@ -52,8 +68,13 @@ async function findJsxElements(code: string, filename: string): Promise<JsxLocat
|
|
|
52
68
|
if (node.type === 'JSXOpeningElement' && node.name) {
|
|
53
69
|
const tagName = getJsxName(node.name)
|
|
54
70
|
|
|
55
|
-
// skip Fragment and already-tagged elements
|
|
56
|
-
if (
|
|
71
|
+
// skip Fragment, non-dom host elements, and already-tagged elements
|
|
72
|
+
if (
|
|
73
|
+
tagName &&
|
|
74
|
+
tagName !== 'Fragment' &&
|
|
75
|
+
!tagName.endsWith('.Fragment') &&
|
|
76
|
+
(!isHostTag(tagName) || DOM_TAGS.has(tagName))
|
|
77
|
+
) {
|
|
57
78
|
const hasSourceAttr = node.attributes?.some(
|
|
58
79
|
(attr: any) =>
|
|
59
80
|
attr.type === 'JSXAttribute' && attr.name?.name === 'data-one-source'
|
|
@@ -123,7 +144,7 @@ export function resolveEditorFilePath(
|
|
|
123
144
|
/**
|
|
124
145
|
* Transforms JSX to inject data-one-source attributes using oxc-parser.
|
|
125
146
|
*/
|
|
126
|
-
async function injectSourceToJsx(code: string, id: string): Promise<TransformOut> {
|
|
147
|
+
export async function injectSourceToJsx(code: string, id: string): Promise<TransformOut> {
|
|
127
148
|
const [filePath] = id.split('?')
|
|
128
149
|
if (!filePath) return
|
|
129
150
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNormalizedStatePath.d.ts","sourceRoot":"","sources":["../../src/router/getNormalizedStatePath.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getNormalizedStatePath.d.ts","sourceRoot":"","sources":["../../src/router/getNormalizedStatePath.tsx"],"names":[],"mappings":"AAGA,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;AAErD,MAAM,MAAM,SAAS,GAAG;IACtB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAGD,wBAAgB,sBAAsB,CACpC,EACE,IAAI,EAAE,SAAS,EACf,MAAM,GACP,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,GAAG,CAAA;CACZ,EACD,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,QAAQ,CAAC,CA6BxC"}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import { type State } from '../fork/getPathFromState';
|
|
1
2
|
import type { OneRouter } from '../interfaces/router';
|
|
2
3
|
import { type UrlObject } from './getNormalizedStatePath';
|
|
3
4
|
export declare function getRouteInfo(state: OneRouter.ResultState): UrlObject;
|
|
5
|
+
export declare function getRouteInfoFromState(getPathFromState: (state: State, asPath: boolean) => {
|
|
6
|
+
path: string;
|
|
7
|
+
params: any;
|
|
8
|
+
}, state: State, baseUrl?: string): UrlObject;
|
|
4
9
|
//# sourceMappingURL=getRouteInfo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getRouteInfo.d.ts","sourceRoot":"","sources":["../../src/router/getRouteInfo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getRouteInfo.d.ts","sourceRoot":"","sources":["../../src/router/getRouteInfo.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,KAAK,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAE3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAKjF,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,WAAW,aAYxD;AAED,wBAAgB,qBAAqB,CACnC,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,KAAK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,EAClF,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,GACf,SAAS,CAYX"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getRouteInfo.test.d.ts","sourceRoot":"","sources":["../../src/router/getRouteInfo.test.ts"],"names":[],"mappings":""}
|
package/types/router/path.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function stripPathSuffix(path: string): string;
|
|
1
2
|
export declare function stripTrailingSlash(pathname: string): string;
|
|
2
3
|
export declare function normalizeRoutePathname(pathname: string): string;
|
|
3
4
|
export declare function hasLostDynamicSegment(path: string): boolean;
|