@sigx/lynx-plugin 0.4.1 → 0.4.3
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 +5 -5
- package/dist/icons.d.ts +25 -5
- package/dist/icons.js +81 -6
- package/dist/log-server.d.ts +0 -0
- package/dist/log-server.js +0 -0
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -11,10 +11,10 @@ npm install -D @sigx/lynx-plugin
|
|
|
11
11
|
```ts
|
|
12
12
|
// rspeedy.config.ts (or rspack.config.ts)
|
|
13
13
|
import { defineConfig } from '@lynx-js/rspeedy';
|
|
14
|
-
import {
|
|
14
|
+
import { pluginSigxLynx } from '@sigx/lynx-plugin';
|
|
15
15
|
|
|
16
16
|
export default defineConfig({
|
|
17
|
-
plugins: [
|
|
17
|
+
plugins: [pluginSigxLynx()],
|
|
18
18
|
});
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -37,7 +37,7 @@ export default defineConfig({
|
|
|
37
37
|
|
|
38
38
|
Listing them as separate entries in webpack isn't sufficient because the chunk graph can evaluate user code before the bootstrap chain. Prepending side-effect imports per-file forces the dep-graph order.
|
|
39
39
|
|
|
40
|
-
4. **Cross-package worklet pickup.** The worklet rules run on every JS/TS file in the BG / MT layers, including `node_modules` and pre-built `dist/`.
|
|
40
|
+
4. **Cross-package worklet pickup.** The worklet rules run on every JS/TS file in the BG / MT layers, including `node_modules` and pre-built `dist/`. Any package shipping `'main thread'` directives in its dist (`@sigx/lynx-motion`, `@sigx/lynx-navigation`, `@sigx/lynx-gestures`, future additions) is picked up automatically — no allowlist or opt-in flag. See [CONTRIBUTING.md](https://github.com/signalxjs/lynx/blob/main/CONTRIBUTING.md#lynx-plugin-internals-cross-package-worklet-pickup) for the loader-branching details.
|
|
41
41
|
|
|
42
42
|
## Worklet author quick reference
|
|
43
43
|
|
|
@@ -54,12 +54,12 @@ Mark an event handler as MT-thread by adding the directive as the first statemen
|
|
|
54
54
|
|
|
55
55
|
The plugin handles the rest — the handler body lives in the MT bundle, the BG bundle keeps a `{_wkltId, _c}` placeholder, and Lynx native dispatches the touch event directly to the MT thread.
|
|
56
56
|
|
|
57
|
-
For higher-level abstractions (drag, tap, swipe, animations), see [`@sigx/gestures`](
|
|
57
|
+
For higher-level abstractions (drag, tap, swipe, animations), see [`@sigx/lynx-gestures`](https://github.com/signalxjs/lynx/tree/main/packages/lynx-gestures).
|
|
58
58
|
|
|
59
59
|
## Limitations
|
|
60
60
|
|
|
61
61
|
- **Custom worklet bodies require `'main thread'` directives.** Worklets aren't auto-detected from JSX shape; the directive is the marker.
|
|
62
|
-
- **Variables declared inside a worklet body are MT-locals.** They can't cross the bridge via `runOnBackground` closure capture — pass them as arguments instead. See `@sigx/gestures` README, "Performance notes."
|
|
62
|
+
- **Variables declared inside a worklet body are MT-locals.** They can't cross the bridge via `runOnBackground` closure capture — pass them as arguments instead. See `@sigx/lynx-gestures` README, "Performance notes."
|
|
63
63
|
- **Mappers for `useAnimatedStyle` ship as MT-side code.** Custom mappers must be registered from a MT-side module via `registerMapper(name, fn)` — BG-side `useAnimatedStyle` only carries the *name* across the build pipeline.
|
|
64
64
|
|
|
65
65
|
## License
|
package/dist/icons.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* 1. Loads `signalx.config.ts` and reads the `iconSets: [...]` field.
|
|
7
7
|
* 2. Statically scans every `.tsx` / `.jsx` / `.ts` / `.js` file under the
|
|
8
|
-
* project root for
|
|
8
|
+
* project root for icon usages (see `scanContent` for the exact patterns).
|
|
9
9
|
* 3. Dynamically imports each adapter package (e.g. `@sigx/lynx-icons-fa-free`)
|
|
10
10
|
* and resolves the used glyphs to `{ codepoint, svg }` records.
|
|
11
11
|
* 4. Writes three generated files into `node_modules/.cache/sigx-lynx-icons/`
|
|
@@ -18,13 +18,33 @@
|
|
|
18
18
|
*
|
|
19
19
|
* The scanner is a one-shot regex pass at plugin start — adding a new icon
|
|
20
20
|
* during `pnpm dev` requires a dev-server restart in v1. A real SWC-AST
|
|
21
|
-
* Rspack loader is the planned upgrade
|
|
21
|
+
* Rspack loader is the planned upgrade and would obviate the regex
|
|
22
|
+
* patterns by inspecting the JSX tree directly.
|
|
23
|
+
*
|
|
24
|
+
* **Patterns the scanner picks up (regex-based; not exhaustive):**
|
|
25
|
+
* - `<Icon set="X" name="Y" />` — both attribute orders
|
|
26
|
+
* - `<FaSolidIcon name="Y" />` / `<FaRegularIcon name="Y" />`
|
|
27
|
+
* / `<FaBrandIcon name="Y" />` / `<LucideIcon name="Y" />` — pinned
|
|
28
|
+
* components whose set id is hardcoded in their implementations. The
|
|
29
|
+
* set id mapping is in `PINNED_COMPONENTS` below.
|
|
30
|
+
* - `{ set: 'X', name: 'Y' }` — `IconSpec` object literals anywhere
|
|
31
|
+
* (prop value, const declaration, function argument). Both key orders.
|
|
32
|
+
*
|
|
33
|
+
* **What still needs `include: [...]` in signalx.config.ts:**
|
|
34
|
+
* - Dynamic names: `<Icon set="fas" name={someVar} />` or
|
|
35
|
+
* `<FaSolidIcon name={someVar} />` — the scanner only matches literal
|
|
36
|
+
* string attributes. JSON-driven UIs and runtime-computed icon names
|
|
37
|
+
* need explicit force-includes (or `include: ['*']` for the whole catalog).
|
|
38
|
+
* - User-defined pinned components — only the four built-in adapter
|
|
39
|
+
* pinned components are known to the scanner. A consumer who writes
|
|
40
|
+
* their own `<MyIcon name="…">` wrapper needs `include`.
|
|
41
|
+
* - Spread props: `<Icon {...spec} />`. Niche; use `include` if needed.
|
|
22
42
|
*/
|
|
23
43
|
import type { RsbuildPluginAPI } from '@rsbuild/core';
|
|
24
44
|
/**
|
|
25
|
-
* Extract
|
|
26
|
-
*
|
|
27
|
-
* calls this once per file from {@link scanProject}.
|
|
45
|
+
* Extract icon usages from a single source string. See the file-level
|
|
46
|
+
* JSDoc for the complete pattern list. Exported for unit testing — the
|
|
47
|
+
* prod path calls this once per file from {@link scanProject}.
|
|
28
48
|
*/
|
|
29
49
|
export declare function scanContent(content: string): Array<{
|
|
30
50
|
set: string;
|
package/dist/icons.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* 1. Loads `signalx.config.ts` and reads the `iconSets: [...]` field.
|
|
7
7
|
* 2. Statically scans every `.tsx` / `.jsx` / `.ts` / `.js` file under the
|
|
8
|
-
* project root for
|
|
8
|
+
* project root for icon usages (see `scanContent` for the exact patterns).
|
|
9
9
|
* 3. Dynamically imports each adapter package (e.g. `@sigx/lynx-icons-fa-free`)
|
|
10
10
|
* and resolves the used glyphs to `{ codepoint, svg }` records.
|
|
11
11
|
* 4. Writes three generated files into `node_modules/.cache/sigx-lynx-icons/`
|
|
@@ -18,7 +18,27 @@
|
|
|
18
18
|
*
|
|
19
19
|
* The scanner is a one-shot regex pass at plugin start — adding a new icon
|
|
20
20
|
* during `pnpm dev` requires a dev-server restart in v1. A real SWC-AST
|
|
21
|
-
* Rspack loader is the planned upgrade
|
|
21
|
+
* Rspack loader is the planned upgrade and would obviate the regex
|
|
22
|
+
* patterns by inspecting the JSX tree directly.
|
|
23
|
+
*
|
|
24
|
+
* **Patterns the scanner picks up (regex-based; not exhaustive):**
|
|
25
|
+
* - `<Icon set="X" name="Y" />` — both attribute orders
|
|
26
|
+
* - `<FaSolidIcon name="Y" />` / `<FaRegularIcon name="Y" />`
|
|
27
|
+
* / `<FaBrandIcon name="Y" />` / `<LucideIcon name="Y" />` — pinned
|
|
28
|
+
* components whose set id is hardcoded in their implementations. The
|
|
29
|
+
* set id mapping is in `PINNED_COMPONENTS` below.
|
|
30
|
+
* - `{ set: 'X', name: 'Y' }` — `IconSpec` object literals anywhere
|
|
31
|
+
* (prop value, const declaration, function argument). Both key orders.
|
|
32
|
+
*
|
|
33
|
+
* **What still needs `include: [...]` in signalx.config.ts:**
|
|
34
|
+
* - Dynamic names: `<Icon set="fas" name={someVar} />` or
|
|
35
|
+
* `<FaSolidIcon name={someVar} />` — the scanner only matches literal
|
|
36
|
+
* string attributes. JSON-driven UIs and runtime-computed icon names
|
|
37
|
+
* need explicit force-includes (or `include: ['*']` for the whole catalog).
|
|
38
|
+
* - User-defined pinned components — only the four built-in adapter
|
|
39
|
+
* pinned components are known to the scanner. A consumer who writes
|
|
40
|
+
* their own `<MyIcon name="…">` wrapper needs `include`.
|
|
41
|
+
* - Spread props: `<Icon {...spec} />`. Niche; use `include` if needed.
|
|
22
42
|
*/
|
|
23
43
|
import { createRequire } from 'node:module';
|
|
24
44
|
import { promises as fs, existsSync } from 'node:fs';
|
|
@@ -26,6 +46,39 @@ import { join } from 'node:path';
|
|
|
26
46
|
import { pathToFileURL } from 'node:url';
|
|
27
47
|
const SCAN_REGEX_SET_FIRST = /<Icon\s+[^>]*?\bset\s*=\s*["']([\w-]+)["'][^>]*?\bname\s*=\s*["']([\w-]+)["']/g;
|
|
28
48
|
const SCAN_REGEX_NAME_FIRST = /<Icon\s+[^>]*?\bname\s*=\s*["']([\w-]+)["'][^>]*?\bset\s*=\s*["']([\w-]+)["']/g;
|
|
49
|
+
/**
|
|
50
|
+
* Known pinned per-set components exported by the workspace's adapter
|
|
51
|
+
* packages — `@sigx/lynx-icons-fa-free/components` and
|
|
52
|
+
* `@sigx/lynx-icons-lucide/components`. Each hardcodes its `set` id to
|
|
53
|
+
* the conventional value documented in the adapter's README; the
|
|
54
|
+
* scanner mirrors that mapping so `<FaSolidIcon name="user" />` is
|
|
55
|
+
* recognized as `set="fas", name="user"`.
|
|
56
|
+
*
|
|
57
|
+
* Consumers using non-conventional set ids in their config fall back
|
|
58
|
+
* to generic `<Icon>` (the pinned component wouldn't find its set at
|
|
59
|
+
* runtime either). New adapter packages adding pinned components add
|
|
60
|
+
* their entries here; the eventual SWC-AST loader replaces this with
|
|
61
|
+
* a per-package manifest.
|
|
62
|
+
*/
|
|
63
|
+
const PINNED_COMPONENTS = {
|
|
64
|
+
FaSolidIcon: 'fas',
|
|
65
|
+
FaRegularIcon: 'far',
|
|
66
|
+
FaBrandIcon: 'fab',
|
|
67
|
+
LucideIcon: 'lucide',
|
|
68
|
+
};
|
|
69
|
+
const PINNED_COMPONENT_NAMES = Object.keys(PINNED_COMPONENTS).join('|');
|
|
70
|
+
const SCAN_REGEX_PINNED = new RegExp(`<(${PINNED_COMPONENT_NAMES})\\s+[^>]*?\\bname\\s*=\\s*["']([\\w-]+)["']`, 'g');
|
|
71
|
+
/**
|
|
72
|
+
* `IconSpec` object literal matchers — `{ set: 'X', name: 'Y' }` in
|
|
73
|
+
* either key order. Used for `<Tabs.Screen icon={{…}}>`, `<NavHeader
|
|
74
|
+
* backIcon={{…}}>`, `const spec = {…}` const declarations, function
|
|
75
|
+
* arguments, etc. Word-boundary anchored on the *first* key to avoid
|
|
76
|
+
* matching mid-identifier (e.g. `someset:`). False positives — any
|
|
77
|
+
* code object with both `set` and `name` string-valued keys — are
|
|
78
|
+
* harmless: the extra glyph just ships in the bundle.
|
|
79
|
+
*/
|
|
80
|
+
const SCAN_REGEX_SPEC_SET_FIRST = /\bset\s*:\s*["']([\w-]+)["']\s*,\s*name\s*:\s*["']([\w-]+)["']/g;
|
|
81
|
+
const SCAN_REGEX_SPEC_NAME_FIRST = /\bname\s*:\s*["']([\w-]+)["']\s*,\s*set\s*:\s*["']([\w-]+)["']/g;
|
|
29
82
|
/** Directories to skip when walking the project. */
|
|
30
83
|
const SKIP_DIRS = new Set(['node_modules', 'dist', 'ios', 'android', 'Pods', '.git', '.cache', '.rspeedy']);
|
|
31
84
|
/** File extensions worth scanning. */
|
|
@@ -64,13 +117,23 @@ function addUsage(used, set, name) {
|
|
|
64
117
|
bucket.add(name);
|
|
65
118
|
}
|
|
66
119
|
/**
|
|
67
|
-
* Extract
|
|
68
|
-
*
|
|
69
|
-
* calls this once per file from {@link scanProject}.
|
|
120
|
+
* Extract icon usages from a single source string. See the file-level
|
|
121
|
+
* JSDoc for the complete pattern list. Exported for unit testing — the
|
|
122
|
+
* prod path calls this once per file from {@link scanProject}.
|
|
70
123
|
*/
|
|
71
124
|
export function scanContent(content) {
|
|
72
|
-
|
|
125
|
+
// Fast-path skip: a file with none of these markers can't possibly
|
|
126
|
+
// contain an icon usage we'd match. `set:` covers both attribute and
|
|
127
|
+
// object-literal forms; the pinned-component prefixes are listed for
|
|
128
|
+
// the JSX form.
|
|
129
|
+
if (!content.includes('<Icon')
|
|
130
|
+
&& !content.includes('<FaSolidIcon')
|
|
131
|
+
&& !content.includes('<FaRegularIcon')
|
|
132
|
+
&& !content.includes('<FaBrandIcon')
|
|
133
|
+
&& !content.includes('<LucideIcon')
|
|
134
|
+
&& !content.includes('set:')) {
|
|
73
135
|
return [];
|
|
136
|
+
}
|
|
74
137
|
const seen = new Set();
|
|
75
138
|
const out = [];
|
|
76
139
|
const push = (set, name) => {
|
|
@@ -80,10 +143,22 @@ export function scanContent(content) {
|
|
|
80
143
|
seen.add(key);
|
|
81
144
|
out.push({ set, name });
|
|
82
145
|
};
|
|
146
|
+
// <Icon set="X" name="Y" /> — either attribute order.
|
|
83
147
|
for (const m of content.matchAll(SCAN_REGEX_SET_FIRST))
|
|
84
148
|
push(m[1], m[2]);
|
|
85
149
|
for (const m of content.matchAll(SCAN_REGEX_NAME_FIRST))
|
|
86
150
|
push(m[2], m[1]);
|
|
151
|
+
// <FaSolidIcon name="Y" /> etc. — set id resolved from PINNED_COMPONENTS.
|
|
152
|
+
for (const m of content.matchAll(SCAN_REGEX_PINNED)) {
|
|
153
|
+
const set = PINNED_COMPONENTS[m[1]];
|
|
154
|
+
if (set)
|
|
155
|
+
push(set, m[2]);
|
|
156
|
+
}
|
|
157
|
+
// { set: 'X', name: 'Y' } — IconSpec object literal, either key order.
|
|
158
|
+
for (const m of content.matchAll(SCAN_REGEX_SPEC_SET_FIRST))
|
|
159
|
+
push(m[1], m[2]);
|
|
160
|
+
for (const m of content.matchAll(SCAN_REGEX_SPEC_NAME_FIRST))
|
|
161
|
+
push(m[2], m[1]);
|
|
87
162
|
return out;
|
|
88
163
|
}
|
|
89
164
|
async function scanProject(cwd) {
|
package/dist/log-server.d.ts
CHANGED
|
Binary file
|
package/dist/log-server.js
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigx/lynx-plugin",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Rspack/Rspeedy plugin for SignalX Lynx dual-thread rendering",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@lynx-js/react": "^0.121.0",
|
|
37
|
-
"ws": "^8.
|
|
38
|
-
"@sigx/lynx-runtime-internal": "0.4.
|
|
37
|
+
"ws": "^8.20.1",
|
|
38
|
+
"@sigx/lynx-runtime-internal": "0.4.3"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@rspack/core": ">=1.0.0",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"@lynx-js/template-webpack-plugin": ">=0.1.0",
|
|
45
45
|
"@lynx-js/runtime-wrapper-webpack-plugin": ">=0.1.0",
|
|
46
46
|
"@lynx-js/webpack-dev-transport": ">=0.1.0",
|
|
47
|
-
"@sigx/lynx-cli": "^0.4.
|
|
48
|
-
"@sigx/lynx-icons": "^0.4.
|
|
47
|
+
"@sigx/lynx-cli": "^0.4.3",
|
|
48
|
+
"@sigx/lynx-icons": "^0.4.3"
|
|
49
49
|
},
|
|
50
50
|
"peerDependenciesMeta": {
|
|
51
51
|
"@rspack/core": {
|
|
@@ -72,12 +72,12 @@
|
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@rsbuild/core": "^1.7.5",
|
|
75
|
-
"@types/node": "^25.
|
|
75
|
+
"@types/node": "^25.9.1",
|
|
76
76
|
"@types/ws": "^8.5.13",
|
|
77
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
77
|
+
"@typescript/native-preview": "7.0.0-dev.20260521.1",
|
|
78
78
|
"typescript": "^6.0.3",
|
|
79
|
-
"@sigx/lynx-icons": "0.4.
|
|
80
|
-
"@sigx/lynx-cli": "0.4.
|
|
79
|
+
"@sigx/lynx-icons": "0.4.3",
|
|
80
|
+
"@sigx/lynx-cli": "0.4.3"
|
|
81
81
|
},
|
|
82
82
|
"publishConfig": {
|
|
83
83
|
"access": "public"
|