@lark.js/mvc 0.0.9 → 0.0.11
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 +10 -32
- package/dist/chunk-RIV4NK3K.js +108 -0
- package/dist/compiler.cjs +733 -193
- package/dist/compiler.d.cts +35 -35
- package/dist/compiler.d.ts +35 -35
- package/dist/compiler.js +730 -193
- package/dist/devtool.cjs +3421 -0
- package/dist/devtool.d.cts +83 -0
- package/dist/devtool.d.ts +83 -0
- package/dist/devtool.js +3333 -0
- package/dist/index.cjs +811 -319
- package/dist/index.d.cts +247 -491
- package/dist/index.d.ts +247 -491
- package/dist/index.js +808 -280
- package/dist/rspack.cjs +15978 -0
- package/dist/rspack.d.cts +122 -0
- package/dist/rspack.d.ts +122 -0
- package/dist/{chunk-3HSA7OHB.js → rspack.js} +809 -193
- package/dist/runtime.cjs +35 -10
- package/dist/runtime.d.cts +22 -13
- package/dist/runtime.d.ts +22 -13
- package/dist/runtime.js +13 -34
- package/dist/vite.cjs +753 -195
- package/dist/vite.d.cts +3 -0
- package/dist/vite.d.ts +3 -0
- package/dist/vite.js +15917 -10
- package/dist/webpack.cjs +798 -201
- package/dist/webpack.d.cts +60 -4
- package/dist/webpack.d.ts +60 -4
- package/dist/webpack.js +15962 -14
- package/package.json +25 -2
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ A TypeScript MVC framework designed for back-office single-page applications and
|
|
|
22
22
|
- Template Syntax
|
|
23
23
|
- Frame and the View Tree
|
|
24
24
|
- Module Federation Micro-Frontend
|
|
25
|
-
- Debugging and
|
|
25
|
+
- Debugging and Devtool Bridge
|
|
26
26
|
- Public API Reference
|
|
27
27
|
- Common Pitfalls
|
|
28
28
|
- Recent API Changes
|
|
@@ -41,7 +41,7 @@ Third, zero runtime dependencies. `@babel/parser` / `@babel/types` are used only
|
|
|
41
41
|
|
|
42
42
|
Fourth, real DOM diff. Templates compile to functions that produce HTML strings, which are parsed into temporary DOM via `document.implementation.createHTMLDocument` and then diffed against the live DOM using keyed comparison. The advantage is that context-sensitive tags like `<table>` / `<select>` / `<svg>` are handled by the native parser. The trade-off is that large templates incur parse overhead, and SSR is not supported.
|
|
43
43
|
|
|
44
|
-
Fifth, debug-friendly. `window.__lark_Debug = true` enables Safeguard Proxy protection against cross-page pollution and accidental writes. `
|
|
44
|
+
Fifth, debug-friendly. `window.__lark_Debug = true` enables Safeguard Proxy protection against cross-page pollution and accidental writes. `installFrameDevtoolBridge` exposes the Frame tree to Devtool via `postMessage`. A set of `window.__lark_*` global shortcuts cover Framework / State / Router / Frame / View and HMR helpers.
|
|
45
45
|
|
|
46
46
|
Not suitable for: projects requiring SSR/streaming rendering, cross-platform needs like React Native, or projects needing off-the-shelf Chrome extension panels. For those, consider the React or Vue ecosystems.
|
|
47
47
|
|
|
@@ -220,7 +220,7 @@ const config: FrameworkConfig = {
|
|
|
220
220
|
Framework.boot(config);
|
|
221
221
|
```
|
|
222
222
|
|
|
223
|
-
`Framework.boot()` executes the following steps in order (order is correctness-sensitive): merge user config (including `routeMode`), inject config into Router (which determines history/hash mode), set EventDelegator's frame getter, subscribe to Router/State `changed` events, mark Framework/Router/State as booted, install the Frame
|
|
223
|
+
`Framework.boot()` executes the following steps in order (order is correctness-sensitive): merge user config (including `routeMode`), inject config into Router (which determines history/hash mode), set EventDelegator's frame getter, subscribe to Router/State `changed` events, mark Framework/Router/State as booted, install the Frame Devtool Bridge, create the root Frame via `Frame.createRoot(config.rootId)`, call `Router._bind()` to bind route events (poptate for history mode, hashchange + popstate for hash mode) and trigger the first `diff()`, and finally mount `defaultView` if Router has not mounted a view. Step seven must precede step eight because the first `diff()` may immediately trigger `CHANGED` followed by `Frame.getRoot()`, and if the root Frame does not exist it degrades to rendering against the wrong element.
|
|
224
224
|
|
|
225
225
|
## Three Data Pipelines: Updater / State / Store
|
|
226
226
|
|
|
@@ -832,7 +832,7 @@ new ModuleFederationPlugin({
|
|
|
832
832
|
|
|
833
833
|
`splitChunks.chunks` must be `"async"`. Using `"all"` extracts `@lark.js/mvc` into a separate vendor chunk, breaking MF shared scope initialization (`ScriptExternalLoadError: Loading script failed`).
|
|
834
834
|
|
|
835
|
-
## Debugging and
|
|
835
|
+
## Debugging and Devtool Bridge
|
|
836
836
|
|
|
837
837
|
### Global Objects
|
|
838
838
|
|
|
@@ -857,15 +857,15 @@ Set `window.__lark_Debug = true` before boot, and the framework wraps `State.get
|
|
|
857
857
|
- Warns when reading data written by another page (potential cross-page pollution).
|
|
858
858
|
- Warns immediately when assigning directly to objects returned by `State.get()` (deduplicated by key); the correct approach is `State.set(patch)` + `State.digest()`.
|
|
859
859
|
|
|
860
|
-
### Frame
|
|
860
|
+
### Frame Devtool Bridge
|
|
861
861
|
|
|
862
|
-
`
|
|
862
|
+
`installFrameDevtoolBridge()` is automatically installed during `Framework.boot`, listening for `window` message events and communicating with Devtool via postMessage:
|
|
863
863
|
|
|
864
|
-
- `
|
|
865
|
-
- `
|
|
866
|
-
- Internally listens to `Frame.on('add' | 'remove')` and automatically pushes `
|
|
864
|
+
- `LARK_DEVTOOL_PING` — responds with `LARK_DEVTOOL_PONG` to confirm this page is a Lark application.
|
|
865
|
+
- `LARK_DEVTOOL_REQUEST_TREE` — responds with `LARK_DEVTOOL_TREE` carrying `SerializedFrameTree`.
|
|
866
|
+
- Internally listens to `Frame.on('add' | 'remove')` and automatically pushes `LARK_DEVTOOL_TREE_DELTA`; JSON.stringify is compared with `lastTreeJson` before pushing to avoid flooding when nothing changed.
|
|
867
867
|
|
|
868
|
-
The `lark-
|
|
868
|
+
The `lark-devtool` sub-project in this repository is the paired Devtool that loads the target application via iframe to display the real-time Frame tree.
|
|
869
869
|
|
|
870
870
|
## Public API Reference
|
|
871
871
|
|
|
@@ -927,28 +927,6 @@ The `lark-visual` sub-project in this repository is the paired visual DevTools t
|
|
|
927
927
|
19. MF view paths use the remote project name as prefix: `v-lark="remote-app/views/home"` triggers async loading via `FrameworkConfig.require` when unregistered; `@lark.js/mvc` must be `singleton: true`.
|
|
928
928
|
20. `splitChunks.chunks` must be `"async"` in MF projects: `"all"` breaks shared scope initialization.
|
|
929
929
|
|
|
930
|
-
## Recent API Changes
|
|
931
|
-
|
|
932
|
-
- Store rewrite (zustand-style):
|
|
933
|
-
- `defineStore(name, (store) => body)` replaced by `create(name, (set, get) => body)`. `defineStore` retained as deprecated alias.
|
|
934
|
-
- `store.key = value` (Proxy write) replaced by `set({ key: value })`.
|
|
935
|
-
- `store.key` reads in actions replaced by `get().key`.
|
|
936
|
-
- `useStore(view)` + `store.observe(view, keys?)` replaced by `bindStore(view, store, selector?)`.
|
|
937
|
-
- `useStore()` (read-only access) replaced by `store.getState()`.
|
|
938
|
-
- `store.observe(undefined, keys, cb)` (internal reaction) replaced by `store.subscribe((state, prev) => ...)`.
|
|
939
|
-
- Removed: `multi()`, `cell()`, `observeCell()`, `cloneStore()`, `getStore()`, `delStore()`, `getUseStore()`, `isStoreActive()`, `createState()`, `shallowSet()`, `lazySet()`, `cloneData()`, `isState()`, `storeMark`, `storeUnmark`, `getPlatform`, `Platform`, `StoreConfig`, `ObservePayload`, `StoreMethods`, `LarkUseStore`, `ReactUseStore`, `NodeUseStore`.
|
|
940
|
-
- Router history mode support:
|
|
941
|
-
- Added `FrameworkConfig.routeMode` (`"history"` default, `"hash"` optional).
|
|
942
|
-
- In history mode, path comes from `window.location.pathname`, params from search query string.
|
|
943
|
-
- Added `useUrlState(view, initialState?)` for URL parameter state sync.
|
|
944
|
-
- `ChangeEvent.keys` changed to `ReadonlySet<string>` (was `Record<string, 1>`). Use `keys.has("foo")` instead of `keys.foo`.
|
|
945
|
-
- `StateInterface.diff()` returns `ReadonlySet<string>`.
|
|
946
|
-
- `Updater.set/digest`, `State.set/digest`, `setData` `excludes?` changed to `ReadonlySet<string>` (was `Set<string>`).
|
|
947
|
-
- `Frame.root(id)` `@deprecated`. Read via `Frame.getRoot()`, create singleton via `Frame.createRoot(id)`, independent mount via `new Frame(id)`.
|
|
948
|
-
- `Updater.parse` no longer evals; only supports safe paths and literals.
|
|
949
|
-
- `mark.ts` no longer writes magic keys to host objects; uses module-level `WeakMap`, works on `Object.freeze`d objects.
|
|
950
|
-
- `Cache.del` immediately removes from `entries` array and `lookup` Map (previously left tombstones until next eviction).
|
|
951
|
-
|
|
952
930
|
## Comparison with Vue 3 / React 19
|
|
953
931
|
|
|
954
932
|
### vs Vue 3
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// src/common.ts
|
|
2
|
+
var globalCounter = 0;
|
|
3
|
+
var SPLITTER = String.fromCharCode(30);
|
|
4
|
+
var RouterEvents = {
|
|
5
|
+
CHANGE: "change",
|
|
6
|
+
CHANGED: "changed",
|
|
7
|
+
PAGE_UNLOAD: "page_unload"
|
|
8
|
+
};
|
|
9
|
+
var LARK_VIEW = "v-lark";
|
|
10
|
+
var EVENT_METHOD_REGEXP = new RegExp(
|
|
11
|
+
`(?:([\\w-]+)${SPLITTER})?([^(]+)\\(([\\s\\S]*?)?\\)`
|
|
12
|
+
);
|
|
13
|
+
var VIEW_EVENT_METHOD_REGEXP = /^(\$?)([\w]*)<(.*?)>(?:<([\w ,]*)>)?$/;
|
|
14
|
+
var URL_TRIM_HASH_REGEXP = /(?:^.*\/\/[^/]+|#.*$)/gi;
|
|
15
|
+
var URL_TRIM_QUERY_REGEXP = /^[^#]*#?!?/;
|
|
16
|
+
var URL_PARAM_REGEXP = /([^=&?/#]+)=?([^&#?]*)/g;
|
|
17
|
+
var IS_URL_PARAMS = /(?!^)=|&/;
|
|
18
|
+
var URL_QUERY_HASH_REGEXP = /[#?].*$/;
|
|
19
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
20
|
+
var MATH_NS = "http://www.w3.org/1998/Math/MathML";
|
|
21
|
+
var TAG_NAME_REGEXP = /<([a-z][^/\0>\x20\t\r\n\f]+)/i;
|
|
22
|
+
var V_TEXT_NODE = 0;
|
|
23
|
+
var VDOM_NS_MAP = {
|
|
24
|
+
svg: SVG_NS,
|
|
25
|
+
math: MATH_NS
|
|
26
|
+
};
|
|
27
|
+
function nextCounter() {
|
|
28
|
+
return ++globalCounter;
|
|
29
|
+
}
|
|
30
|
+
var HTML_ENT_MAP = {
|
|
31
|
+
"&": "amp",
|
|
32
|
+
"<": "lt",
|
|
33
|
+
">": "gt",
|
|
34
|
+
'"': "#34",
|
|
35
|
+
"'": "#39",
|
|
36
|
+
"`": "#96"
|
|
37
|
+
};
|
|
38
|
+
var HTML_ENT_REGEXP = /[&<>"'`]/g;
|
|
39
|
+
function strSafe(v) {
|
|
40
|
+
return String(v == null ? "" : v);
|
|
41
|
+
}
|
|
42
|
+
function encodeHTML(v) {
|
|
43
|
+
return String(v == null ? "" : v).replace(
|
|
44
|
+
HTML_ENT_REGEXP,
|
|
45
|
+
(m) => "&" + HTML_ENT_MAP[m] + ";"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
var URI_ENT_MAP = {
|
|
49
|
+
"!": "%21",
|
|
50
|
+
"'": "%27",
|
|
51
|
+
"(": "%28",
|
|
52
|
+
")": "%29",
|
|
53
|
+
"*": "%2A"
|
|
54
|
+
};
|
|
55
|
+
var URI_ENT_REGEXP = /[!')(*]/g;
|
|
56
|
+
function encodeURIExtra(v) {
|
|
57
|
+
return encodeURIComponent(strSafe(v)).replace(
|
|
58
|
+
URI_ENT_REGEXP,
|
|
59
|
+
(m) => URI_ENT_MAP[m]
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
var QUOTE_ENT_REGEXP = /['"\\]/g;
|
|
63
|
+
function encodeQuote(v) {
|
|
64
|
+
return strSafe(v).replace(QUOTE_ENT_REGEXP, "\\$&");
|
|
65
|
+
}
|
|
66
|
+
function refFn(ref, value, key) {
|
|
67
|
+
const counter = ref[SPLITTER];
|
|
68
|
+
for (let i = counter; --i; ) {
|
|
69
|
+
key = SPLITTER + i;
|
|
70
|
+
if (ref[key] === value) return key;
|
|
71
|
+
}
|
|
72
|
+
key = SPLITTER + ref[SPLITTER]++;
|
|
73
|
+
ref[key] = value;
|
|
74
|
+
return key;
|
|
75
|
+
}
|
|
76
|
+
function isRefToken(s) {
|
|
77
|
+
if (s.length < 2 || s[0] !== SPLITTER) return false;
|
|
78
|
+
for (let i = 1; i < s.length; i++) {
|
|
79
|
+
const c = s.charCodeAt(i);
|
|
80
|
+
if (c < "0".charCodeAt(0) || c > "9".charCodeAt(0)) return false;
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
SPLITTER,
|
|
87
|
+
RouterEvents,
|
|
88
|
+
LARK_VIEW,
|
|
89
|
+
EVENT_METHOD_REGEXP,
|
|
90
|
+
VIEW_EVENT_METHOD_REGEXP,
|
|
91
|
+
URL_TRIM_HASH_REGEXP,
|
|
92
|
+
URL_TRIM_QUERY_REGEXP,
|
|
93
|
+
URL_PARAM_REGEXP,
|
|
94
|
+
IS_URL_PARAMS,
|
|
95
|
+
URL_QUERY_HASH_REGEXP,
|
|
96
|
+
SVG_NS,
|
|
97
|
+
MATH_NS,
|
|
98
|
+
TAG_NAME_REGEXP,
|
|
99
|
+
V_TEXT_NODE,
|
|
100
|
+
VDOM_NS_MAP,
|
|
101
|
+
nextCounter,
|
|
102
|
+
strSafe,
|
|
103
|
+
encodeHTML,
|
|
104
|
+
encodeURIExtra,
|
|
105
|
+
encodeQuote,
|
|
106
|
+
refFn,
|
|
107
|
+
isRefToken
|
|
108
|
+
};
|