@lark.js/mvc 0.0.14 → 0.0.16

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.
@@ -54,10 +54,7 @@ var URI_ENT_MAP = {
54
54
  };
55
55
  var URI_ENT_REGEXP = /[!')(*]/g;
56
56
  function encodeURIExtra(v) {
57
- return encodeURIComponent(strSafe(v)).replace(
58
- URI_ENT_REGEXP,
59
- (m) => URI_ENT_MAP[m]
60
- );
57
+ return encodeURIComponent(strSafe(v)).replace(URI_ENT_REGEXP, (m) => URI_ENT_MAP[m]);
61
58
  }
62
59
  var QUOTE_ENT_REGEXP = /['"\\]/g;
63
60
  function encodeQuote(v) {
@@ -0,0 +1,63 @@
1
+ import type {
2
+ FrameApi,
3
+ FrameworkApi,
4
+ StateApi,
5
+ RouterApi,
6
+ CrossSiteConfig,
7
+ ViewTemplate,
8
+ VDomTemplate,
9
+ } from "./types";
10
+ import type { Frame } from "./frame";
11
+ import type { View } from "./view";
12
+ declare global {
13
+ interface Window {
14
+ /** Cross-site configuration injected by build tools */
15
+ crossSites?: CrossSiteConfig[];
16
+ scheduler?: Scheduler;
17
+ }
18
+ interface ImportMeta {
19
+ /** HMR context provided by Vite / webpack dev server. Undefined in production. */
20
+ hot?: {
21
+ accept(cb?: (mod: { default?: unknown } | undefined) => void): void;
22
+ dispose(cb: (data: unknown) => void): void;
23
+ invalidate(): void;
24
+ };
25
+ }
26
+ interface HTMLElement {
27
+ /** Bound frame instance */
28
+ frame?: FrameApi | undefined;
29
+ /** Whether frame is bound to this element (1 = bound) */
30
+ frameBound?: number;
31
+ /** Whether auto-generated ID was assigned */
32
+ autoId?: number;
33
+ /** View rendered flag for selector matching */
34
+ viewRendered?: number;
35
+ /** Range frame ID for event delegation */
36
+ rangeFrameId?: string;
37
+ /** Range element guid for event delegation */
38
+ rangeElementGuid?: number;
39
+ }
40
+
41
+ interface Element {
42
+ /** DOM diff cached compare key flag */
43
+ compareKeyCached?: number | undefined;
44
+ /** DOM diff cached compare key */
45
+ cachedCompareKey?: string | undefined;
46
+ "v-lark"?: string | undefined;
47
+
48
+ // @lark.js/sentry
49
+ "s-lark-ev"?: string | undefined;
50
+ "s-lark-msg"?: string | undefined;
51
+ }
52
+ }
53
+
54
+ // CSS module type declarations
55
+ declare module "*.css" {
56
+ const content: string;
57
+ export default content;
58
+ }
59
+
60
+ declare module "*.html" {
61
+ const template: ViewTemplate | VDomTemplate;
62
+ export default template;
63
+ }
@@ -0,0 +1,63 @@
1
+ import type {
2
+ FrameApi,
3
+ FrameworkApi,
4
+ StateApi,
5
+ RouterApi,
6
+ CrossSiteConfig,
7
+ ViewTemplate,
8
+ VDomTemplate,
9
+ } from "./types";
10
+ import type { Frame } from "./frame";
11
+ import type { View } from "./view";
12
+ declare global {
13
+ interface Window {
14
+ /** Cross-site configuration injected by build tools */
15
+ crossSites?: CrossSiteConfig[];
16
+ scheduler?: Scheduler;
17
+ }
18
+ interface ImportMeta {
19
+ /** HMR context provided by Vite / webpack dev server. Undefined in production. */
20
+ hot?: {
21
+ accept(cb?: (mod: { default?: unknown } | undefined) => void): void;
22
+ dispose(cb: (data: unknown) => void): void;
23
+ invalidate(): void;
24
+ };
25
+ }
26
+ interface HTMLElement {
27
+ /** Bound frame instance */
28
+ frame?: FrameApi | undefined;
29
+ /** Whether frame is bound to this element (1 = bound) */
30
+ frameBound?: number;
31
+ /** Whether auto-generated ID was assigned */
32
+ autoId?: number;
33
+ /** View rendered flag for selector matching */
34
+ viewRendered?: number;
35
+ /** Range frame ID for event delegation */
36
+ rangeFrameId?: string;
37
+ /** Range element guid for event delegation */
38
+ rangeElementGuid?: number;
39
+ }
40
+
41
+ interface Element {
42
+ /** DOM diff cached compare key flag */
43
+ compareKeyCached?: number | undefined;
44
+ /** DOM diff cached compare key */
45
+ cachedCompareKey?: string | undefined;
46
+ "v-lark"?: string | undefined;
47
+
48
+ // @lark.js/sentry
49
+ "s-lark-ev"?: string | undefined;
50
+ "s-lark-msg"?: string | undefined;
51
+ }
52
+ }
53
+
54
+ // CSS module type declarations
55
+ declare module "*.css" {
56
+ const content: string;
57
+ export default content;
58
+ }
59
+
60
+ declare module "*.html" {
61
+ const template: ViewTemplate | VDomTemplate;
62
+ export default template;
63
+ }
package/dist/compiler.cjs CHANGED
@@ -14723,12 +14723,7 @@ function convertArtSyntax(source, debug) {
14723
14723
  } else {
14724
14724
  cleanCode = code.trim();
14725
14725
  }
14726
- const converted = convertArtExpression(
14727
- cleanCode,
14728
- debug,
14729
- lineNo,
14730
- blockStack
14731
- );
14726
+ const converted = convertArtExpression(cleanCode, debug, lineNo, blockStack);
14732
14727
  result.push(converted);
14733
14728
  result.push(rest);
14734
14729
  }
@@ -14973,12 +14968,74 @@ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
14973
14968
  function vdomEscapeStr(s) {
14974
14969
  return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\x1e/g, "\\x1e");
14975
14970
  }
14971
+ function vdomResolveAttrValueIIFE(rawValue, exprStore) {
14972
+ const stmts = [];
14973
+ let remaining = rawValue;
14974
+ while (remaining.length > 0) {
14975
+ const phIdx = remaining.indexOf("\0");
14976
+ const viIdx = remaining.indexOf("");
14977
+ let nextSpecial = -1;
14978
+ let specialType = null;
14979
+ if (phIdx >= 0 && (viIdx < 0 || phIdx <= viIdx)) {
14980
+ nextSpecial = phIdx;
14981
+ specialType = "ph";
14982
+ } else if (viIdx >= 0) {
14983
+ nextSpecial = viIdx;
14984
+ specialType = "vi";
14985
+ }
14986
+ if (nextSpecial === -1) {
14987
+ if (remaining) stmts.push(`$s+='${vdomEscapeStr(remaining)}'`);
14988
+ break;
14989
+ }
14990
+ if (nextSpecial > 0) {
14991
+ stmts.push(`$s+='${vdomEscapeStr(remaining.substring(0, nextSpecial))}'`);
14992
+ }
14993
+ if (specialType === "vi") {
14994
+ stmts.push(`$s+=$viewId`);
14995
+ remaining = remaining.substring(nextSpecial + 1);
14996
+ } else {
14997
+ const closeIdx = remaining.indexOf("\0", nextSpecial + 1);
14998
+ if (closeIdx === -1) {
14999
+ stmts.push(`$s+='${vdomEscapeStr(remaining.substring(nextSpecial))}'`);
15000
+ break;
15001
+ }
15002
+ const idx = parseInt(remaining.substring(nextSpecial + 1, closeIdx), 10);
15003
+ const expr = exprStore[idx];
15004
+ if (expr.op === "=" || expr.op === ":") {
15005
+ stmts.push(`$s+=$strSafe(${expr.content})`);
15006
+ } else if (expr.op === "!") {
15007
+ if (expr.content.startsWith("$encUri(") && expr.content.endsWith(")")) {
15008
+ stmts.push(`$s+=${expr.content}`);
15009
+ } else {
15010
+ stmts.push(`$s+=$strSafe(${expr.content})`);
15011
+ }
15012
+ } else if (expr.op === "@") {
15013
+ stmts.push(`$s+=$refFn($refAlt,${expr.content})`);
15014
+ } else {
15015
+ stmts.push(expr.content);
15016
+ }
15017
+ remaining = remaining.substring(closeIdx + 1);
15018
+ }
15019
+ }
15020
+ const body = stmts.join(";");
15021
+ return `(()=>{let $s='';${body};return $s;})()`;
15022
+ }
14976
15023
  function vdomResolveAttrValue(rawValue, exprStore) {
14977
15024
  const hasPlaceholders = rawValue.includes("\0");
14978
15025
  const hasViewId = rawValue.includes("");
14979
15026
  if (!hasPlaceholders && !hasViewId) {
14980
15027
  return `'${vdomEscapeStr(rawValue)}'`;
14981
15028
  }
15029
+ if (hasPlaceholders) {
15030
+ const codeBlockRegExp = /\x00(\d+)\x00/g;
15031
+ let m;
15032
+ while ((m = codeBlockRegExp.exec(rawValue)) !== null) {
15033
+ const idx = parseInt(m[1], 10);
15034
+ if (exprStore[idx] && exprStore[idx].op === "") {
15035
+ return vdomResolveAttrValueIIFE(rawValue, exprStore);
15036
+ }
15037
+ }
15038
+ }
14982
15039
  const segments = [];
14983
15040
  let remaining = rawValue;
14984
15041
  while (remaining.length > 0) {
@@ -15012,17 +15069,17 @@ function vdomResolveAttrValue(rawValue, exprStore) {
15012
15069
  const idx = parseInt(remaining.substring(nextSpecial + 1, closeIdx));
15013
15070
  const expr = exprStore[idx];
15014
15071
  if (expr.op === "=" || expr.op === ":") {
15015
- segments.push(`$n(${expr.content})`);
15072
+ segments.push(`$strSafe(${expr.content})`);
15016
15073
  } else if (expr.op === "!") {
15017
15074
  if (expr.content.startsWith("$encUri(") && expr.content.endsWith(")")) {
15018
15075
  segments.push(expr.content);
15019
15076
  } else {
15020
- segments.push(`$n(${expr.content})`);
15077
+ segments.push(`$strSafe(${expr.content})`);
15021
15078
  }
15022
15079
  } else if (expr.op === "@") {
15023
15080
  segments.push(`$refFn($refAlt,${expr.content})`);
15024
15081
  } else {
15025
- segments.push(`$n(${expr.content})`);
15082
+ segments.push(`$strSafe(${expr.content})`);
15026
15083
  }
15027
15084
  remaining = remaining.substring(closeIdx + 1);
15028
15085
  }
@@ -15064,14 +15121,7 @@ function compileToVDomFunction(source, debug, file) {
15064
15121
  });
15065
15122
  const rootVar = `$v${varCounter++}`;
15066
15123
  lines.push(`let ${rootVar}=[]`);
15067
- const maxVars = 30;
15068
- const varDecls = [];
15069
- for (let i = 1; i < maxVars; i++) {
15070
- varDecls.push(`$v${i}`);
15071
- }
15072
- lines.push(`let ${varDecls.join(",")}`);
15073
15124
  function allocVar() {
15074
- if (varCounter >= maxVars) return `$v${maxVars - 1}`;
15075
15125
  return `$v${varCounter++}`;
15076
15126
  }
15077
15127
  function emitNode(node, parentVar) {
@@ -15088,7 +15138,7 @@ function compileToVDomFunction(source, debug, file) {
15088
15138
  if (i % 2 === 0) {
15089
15139
  const trimmed = parts[i];
15090
15140
  if (trimmed.trim()) {
15091
- lines.push(`${parentVar}.push($c(0,'${vdomEscapeStr(trimmed)}'))`);
15141
+ lines.push(`${parentVar}.push($vdomCreate(0,'${vdomEscapeStr(trimmed)}'))`);
15092
15142
  }
15093
15143
  } else {
15094
15144
  const idx = parseInt(parts[i]);
@@ -15099,15 +15149,15 @@ function compileToVDomFunction(source, debug, file) {
15099
15149
  }
15100
15150
  function emitExpr(expr, parentVar) {
15101
15151
  if (expr.op === "=" || expr.op === ":") {
15102
- lines.push(`${parentVar}.push($c(0,$n(${expr.content})))`);
15152
+ lines.push(`${parentVar}.push($vdomCreate(0,$strSafe(${expr.content})))`);
15103
15153
  } else if (expr.op === "!") {
15104
15154
  if (expr.content.startsWith("$encUri(") && expr.content.endsWith(")")) {
15105
- lines.push(`${parentVar}.push($c(0,${expr.content}))`);
15155
+ lines.push(`${parentVar}.push($vdomCreate(0,${expr.content},1))`);
15106
15156
  } else {
15107
- lines.push(`${parentVar}.push($c(0,$n(${expr.content})))`);
15157
+ lines.push(`${parentVar}.push($vdomCreate(0,$strSafe(${expr.content}),1))`);
15108
15158
  }
15109
15159
  } else if (expr.op === "@") {
15110
- lines.push(`${parentVar}.push($c(0,$refFn($refAlt,${expr.content})))`);
15160
+ lines.push(`${parentVar}.push($vdomCreate(0,$refFn($refAlt,${expr.content})))`);
15111
15161
  } else if (expr.content) {
15112
15162
  lines.push(expr.content);
15113
15163
  }
@@ -15125,25 +15175,26 @@ function compileToVDomFunction(source, debug, file) {
15125
15175
  }
15126
15176
  const isVoid = VOID_ELEMENTS.has(tagName) && children.length === 0;
15127
15177
  const childrenArg = isVoid ? "1" : childVar;
15128
- lines.push(
15129
- `${parentVar}.push($c('${tagName}',${propsKey},${childrenArg}))`
15130
- );
15178
+ lines.push(`${parentVar}.push($vdomCreate('${tagName}',${propsKey},${childrenArg}))`);
15131
15179
  }
15132
15180
  for (const child of doc.children) {
15133
15181
  emitNode(child, rootVar);
15134
15182
  }
15135
- lines.push(`return $c($viewId,0,${rootVar})`);
15136
- const body = lines.join(";");
15183
+ lines.push(`return $vdomCreate($viewId,0,${rootVar})`);
15184
+ const varDeclStmts = [];
15185
+ for (let i = 1; i < varCounter; i++) varDeclStmts.push(`$v${i}`);
15186
+ const varDecl = varDeclStmts.length ? `let ${varDeclStmts.join(",")};` : "";
15187
+ const body = varDecl + lines.join(";");
15137
15188
  let funcBody = body;
15138
15189
  if (debug) {
15139
15190
  const filePart = file ? `\\r\\n\\tat file:${file}` : "";
15140
- funcBody = `let $dbgExpr,$dbgArt,$dbgLine;try{${body}}catch(ex){let msg='render view error:'+(ex.message||ex);msg+='${filePart}';throw msg;}`;
15191
+ funcBody = `let $dbgExpr,$dbgArt;try{${body}}catch(e){let msg='render error:'+(e.message||e);msg+='${filePart}';throw msg;}`;
15141
15192
  }
15142
15193
  const viewIdRegExp = new RegExp(String.fromCharCode(31), "g");
15143
15194
  funcBody = funcBody.replace(viewIdRegExp, `'+$viewId+'`);
15144
15195
  const refFallback = "if(!$refAlt)$refAlt=$data;";
15145
15196
  const fullSource = `${refFallback}let $splitter='\\x1e'{{VARS}};${funcBody}`;
15146
- return `($data,$viewId,$refAlt,$n,$refFn,$encUri,$encQuote)=>{${fullSource}}`;
15197
+ return `($data,$viewId,$refAlt,$strSafe,$refFn,$encUri,$encQuote)=>{${fullSource}}`;
15147
15198
  }
15148
15199
 
15149
15200
  // src/compiler/extract-global-vars.ts
@@ -15376,9 +15427,6 @@ var BUILTIN_GLOBALS = /* @__PURE__ */ new Set([
15376
15427
  // conversion, for error reporting. Only present in debug mode.
15377
15428
  // e.g. $dbgArt='{{=user.name}}'
15378
15429
  "$dbgArt",
15379
- // Debug: source line number — tracks the current line in the template
15380
- // source, for error reporting. Only present in debug mode.
15381
- "$dbgLine",
15382
15430
  // RefData alias — fallback reference lookup table.
15383
15431
  // Defaults to $data when no explicit $refAlt is provided.
15384
15432
  // Ensures $refFn() does not crash when @ operator is used without refData.
@@ -15462,19 +15510,14 @@ function compileToFunction(source, debug, file) {
15462
15510
  funcSource += source.substring(index, offset).replace(escapeSlashRegExp, "\\$&").replace(escapeBreakReturnRegExp, "\\n");
15463
15511
  index = offset + match.length;
15464
15512
  if (debug) {
15465
- let expr = source.substring(
15466
- index - match.length + 2 + (operate ? 1 : 0),
15467
- index - 2
15468
- );
15513
+ let expr = source.substring(index - match.length + 2 + (operate ? 1 : 0), index - 2);
15469
15514
  const x11 = String.fromCharCode(17);
15470
15515
  const artRegExp = new RegExp(`^'(\\d+)${x11}([^${x11}]+)${x11}'$`);
15471
15516
  const artM = expr.match(artRegExp);
15472
15517
  let art = "";
15473
- let line = -1;
15474
15518
  if (artM) {
15475
15519
  expr = expr.replace(artRegExp, "");
15476
15520
  art = artM[2];
15477
- line = parseInt(artM[1], 10);
15478
15521
  } else {
15479
15522
  expr = expr.replace(escapeSlashRegExp, "\\$&").replace(escapeBreakReturnRegExp, "\\n");
15480
15523
  }
@@ -15489,8 +15532,8 @@ function compileToFunction(source, debug, file) {
15489
15532
  }
15490
15533
  funcSource += `'+($dbgExpr='<%${operate + expr}%>',${content})+'`;
15491
15534
  } else if (content) {
15492
- if (line > -1) {
15493
- funcSource += `';$dbgLine=${line};$dbgArt='${art}';`;
15535
+ if (artM) {
15536
+ funcSource += `';$dbgArt='${art}';`;
15494
15537
  content = "";
15495
15538
  } else {
15496
15539
  funcSource += `';`;
@@ -15529,7 +15572,7 @@ function compileToFunction(source, debug, file) {
15529
15572
  funcSource = funcSource.replace(/\$out\+=''\+/g, "$out+=");
15530
15573
  if (debug) {
15531
15574
  const filePart = file ? `\\r\\n\\tat file:${file}` : "";
15532
- funcSource = `let $dbgExpr,$dbgArt,$dbgLine;try{${funcSource}}catch(ex){let msg='render view error:'+(ex.message||ex);if($dbgArt)msg+='\\r\\n\\tsrc art:{{'+$dbgArt+'}}\\r\\n\\tat line:'+$dbgLine;msg+='\\r\\n\\t'+($dbgArt?'translate to:':'expr:');msg+=$dbgExpr+'${filePart}';throw msg;}`;
15575
+ funcSource = `let $dbgExpr,$dbgArt;try{${funcSource}}catch(e){let msg='render error:'+(e.message||e);if($dbgArt)msg+='\\r\\n\\tsrc art:{{'+$dbgArt+'}};msg+='\\r\\n\\t'+($dbgArt?'translate to:':'expr:');msg+=$dbgExpr+'${filePart}';throw msg;}`;
15533
15576
  }
15534
15577
  const viewIdRegExp = new RegExp(String.fromCharCode(31), "g");
15535
15578
  funcSource = funcSource.replace(viewIdRegExp, `'+$viewId+'`);
@@ -15549,28 +15592,30 @@ async function compileTemplate(source, options = {}) {
15549
15592
  if (virtualDom) {
15550
15593
  const funcBody2 = compileToVDomFunction(finalSource, debug, file);
15551
15594
  const funcWithVars2 = funcBody2.replace("{{VARS}}", () => varDeclarations);
15552
- return `import { vdomCreate as __larkC } from "@lark.js/mvc";
15595
+ return `import { vdomCreate as __larkVdomCreate } from "@lark.js/mvc";
15553
15596
  import { strSafe as __larkStrSafe, encUri as __larkEncUri, encQuote as __larkEncQuote, refFn as __larkRefFn } from "@lark.js/mvc/runtime";
15554
- export default function(data, viewId, refData) {
15597
+ function __larkTemplate(data, viewId, refData) {
15555
15598
  let $data = data || {},
15556
15599
  $viewId = viewId || '',
15557
- $c = __larkC,
15558
- $n = __larkStrSafe;
15600
+ $vdomCreate = __larkVdomCreate,
15601
+ $strSafe = __larkStrSafe;
15559
15602
  return (${funcWithVars2})($data, $viewId, refData,
15560
- $n, __larkRefFn, __larkEncUri, __larkEncQuote
15603
+ $strSafe, __larkRefFn, __larkEncUri, __larkEncQuote
15561
15604
  );
15562
- }`;
15605
+ }
15606
+ export default __larkTemplate;`;
15563
15607
  }
15564
15608
  const funcBody = compileToFunction(finalSource, debug, file);
15565
15609
  const funcWithVars = funcBody.replace("{{VARS}}", () => varDeclarations);
15566
15610
  return `import { encHtml as __larkEncHtml, strSafe as __larkStrSafe, encUri as __larkEncUri, encQuote as __larkEncQuote, refFn as __larkRefFn } from "@lark.js/mvc/runtime";
15567
- export default function(data, viewId, refData) {
15611
+ function __larkTemplate(data, viewId, refData) {
15568
15612
  let $data = data || {},
15569
15613
  $viewId = viewId || '';
15570
15614
  return (${funcWithVars})($data, $viewId, refData,
15571
15615
  __larkEncHtml, __larkStrSafe, __larkEncUri, __larkRefFn, __larkEncQuote
15572
15616
  );
15573
- }`;
15617
+ }
15618
+ export default __larkTemplate;`;
15574
15619
  }
15575
15620
  // Annotate the CommonJS export names for ESM import in node:
15576
15621
  0 && (module.exports = {