@statorjs/language-server 0.1.19 → 0.1.21

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.
Files changed (2) hide show
  1. package/dist/server.cjs +128 -14
  2. package/package.json +2 -2
package/dist/server.cjs CHANGED
@@ -44183,8 +44183,38 @@ var elementMarker = (i) => `b${i}`;
44183
44183
  var slotMarker = (i) => `s${i}`;
44184
44184
  var elementMarkerSelector = (marker) => `[${ISLAND_MARKER_ATTR}="${marker}"]`;
44185
44185
 
44186
+ // ../stator/src/compiler/emit-names.ts
44187
+ var TEMPLATE_AUTHOR_GLOBALS = [
44188
+ "read",
44189
+ "each",
44190
+ "when",
44191
+ "match",
44192
+ "defer",
44193
+ "on",
44194
+ "classList",
44195
+ "styleList"
44196
+ ];
44197
+ var TEMPLATE_LOWERING_TARGETS = ["html", "itemBind", "spreadAttrs"];
44198
+ var ISLAND_SHELL_EXTRAS = ["createHtmlFragment", "clientShellAttrs"];
44199
+ var CLIENT_AUTHOR_GLOBALS = [
44200
+ "StatorElement",
44201
+ "use",
44202
+ "machine",
44203
+ "defineElement",
44204
+ "bind",
44205
+ "effect",
44206
+ "dispatch"
44207
+ ];
44208
+ var CLIENT_LOWERING_TARGETS = ["bindSlot", "attrValue", "setAttr"];
44209
+ function importLine(names, from) {
44210
+ return `import { ${names.join(", ")} } from '${from}'`;
44211
+ }
44212
+
44186
44213
  // ../stator/src/compiler/client-emit.ts
44187
- var PRIMITIVES = "import { StatorElement, defineElement, use, machine, bind, bindSlot, effect, dispatch, attrValue, setAttr } from '@statorjs/stator/client'";
44214
+ var PRIMITIVES = importLine(
44215
+ [...CLIENT_AUTHOR_GLOBALS, ...CLIENT_LOWERING_TARGETS],
44216
+ "@statorjs/stator/client"
44217
+ );
44188
44218
  function emitClientModule(input) {
44189
44219
  const { script, element, directives, members } = input;
44190
44220
  const impl = `__${element.className}Impl`;
@@ -45199,7 +45229,18 @@ function isSubjectGlobal(sel) {
45199
45229
  }
45200
45230
 
45201
45231
  // ../stator/src/compiler/compile.ts
45202
- var PRIMITIVES_IMPORT = "import { html, read, each, itemBind, when, match, defer, on, classList, styleList, spreadAttrs } from '@statorjs/stator/template'";
45232
+ var PRIMITIVES_IMPORT = importLine(
45233
+ [...TEMPLATE_AUTHOR_GLOBALS, ...TEMPLATE_LOWERING_TARGETS],
45234
+ "@statorjs/stator/template"
45235
+ );
45236
+ var SHELL_PRIMITIVES_IMPORT = importLine(
45237
+ [
45238
+ ...TEMPLATE_AUTHOR_GLOBALS,
45239
+ ...TEMPLATE_LOWERING_TARGETS.filter((n) => n !== "itemBind"),
45240
+ ...ISLAND_SHELL_EXTRAS
45241
+ ],
45242
+ "@statorjs/stator/template"
45243
+ );
45203
45244
  function compile(source, opts = {}) {
45204
45245
  const { frontmatter, template, styles, scripts, scriptOffsets, templateOffset } = splitStator(source);
45205
45246
  const kind = opts.kind ?? "component";
@@ -45209,11 +45250,14 @@ function compile(source, opts = {}) {
45209
45250
  const script = scripts.join("\n");
45210
45251
  if (script.trim()) {
45211
45252
  if (analyzeScriptClasses(script).length > 0) {
45253
+ const fm2 = processFrontmatter(frontmatter, "island", source, opts.id);
45212
45254
  return compileClient(template, script, {
45213
45255
  hash,
45214
45256
  scopeAttr,
45215
45257
  styles,
45216
- file: opts.id
45258
+ file: opts.id,
45259
+ fm: fm2,
45260
+ source
45217
45261
  });
45218
45262
  }
45219
45263
  throw new CompileError(
@@ -45254,6 +45298,17 @@ function compileClient(template, script, ctx) {
45254
45298
  const tags = /* @__PURE__ */ new Set([root2.tag]);
45255
45299
  analyzeClient(script, tags, { file: ctx.file });
45256
45300
  const cls = classes.find((c) => pascalToKebab(c.name) === root2.tag);
45301
+ if (ctx.fm && cls) {
45302
+ const fenceNames = fenceBindingNames(ctx.fm);
45303
+ for (const field of cls.useFields.keys()) {
45304
+ if (fenceNames.has(field)) {
45305
+ throw new CompileError(
45306
+ `stator: "${field}" is both a fence binding and a use() field \u2014 the template couldn't tell the server value from the client machine. Rename one.`,
45307
+ ctx.source ? locAt(ctx.source, 0, ctx.file) : void 0
45308
+ );
45309
+ }
45310
+ }
45311
+ }
45257
45312
  if (!cls) {
45258
45313
  throw new CompileError(
45259
45314
  `stator: internal \u2014 no exported class matches root <${root2.tag}> after name validation`
@@ -45276,9 +45331,13 @@ function compileClient(template, script, ctx) {
45276
45331
  const attrDecl = `{ ${[...cls.staticAttrs].map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ")} }`;
45277
45332
  const rootScope = ctx.scopeAttr ? ` data-s-${ctx.hash}` : "";
45278
45333
  const serverCode = [
45279
- "import { html, read, each, when, match, defer, on, classList, styleList, spreadAttrs, createHtmlFragment, clientShellAttrs } from '@statorjs/stator/template'",
45334
+ SHELL_PRIMITIVES_IMPORT,
45335
+ ...ctx.fm?.hoisted ? [ctx.fm.hoisted] : [],
45280
45336
  "",
45281
45337
  `export default function (props = {}) {`,
45338
+ // The fence body runs here — per shell render, server only, ahead of
45339
+ // the template so its bindings are in scope for the interpolations.
45340
+ ...ctx.fm?.body ? [ctx.fm.body] : [],
45282
45341
  ` const __inner = ${innerExpr}`,
45283
45342
  ` const __attrs = clientShellAttrs(props, ${attrDecl}, ${JSON.stringify(root2.rootAttrs)})`,
45284
45343
  ` return createHtmlFragment(\`<${root2.tag}\${__attrs}${rootScope}>\` + __inner.html + \`</${root2.tag}>\`)`,
@@ -45376,6 +45435,12 @@ function processFrontmatter(fm, kind, source, file) {
45376
45435
  const repls = [];
45377
45436
  const visit = (n) => {
45378
45437
  if (import_typescript4.default.isCallExpression(n) && isStatorCall(n, "props")) {
45438
+ if (kind === "island") {
45439
+ throw new CompileError(
45440
+ "stator: Stator.props() is not available in an island's fence \u2014 island props are declared by `static attrs` on the element class, and richer values arrive through the hydrate pattern (the shell renders with the props of its use site).",
45441
+ locInFm(n)
45442
+ );
45443
+ }
45379
45444
  if (kind === "route") {
45380
45445
  throw new CompileError(
45381
45446
  "stator: Stator.props() is not available in a route page (a route has no parent props). Use Stator.reads([...]) to access machines.",
@@ -45406,6 +45471,12 @@ function processFrontmatter(fm, kind, source, file) {
45406
45471
  return;
45407
45472
  }
45408
45473
  if (import_typescript4.default.isCallExpression(n) && isStatorCall(n, "forwarded")) {
45474
+ if (kind === "island") {
45475
+ throw new CompileError(
45476
+ "stator: Stator.forwarded() is not available in an island's fence.",
45477
+ locInFm(n)
45478
+ );
45479
+ }
45409
45480
  if (kind === "route") {
45410
45481
  throw new CompileError(
45411
45482
  "stator: Stator.forwarded() is only available in a component \u2014 it reads a directive forwarded from a parent (`<Child on:click={h}/>`), and a route has no parent.",
@@ -45449,6 +45520,38 @@ function processFrontmatter(fm, kind, source, file) {
45449
45520
  pragmas
45450
45521
  };
45451
45522
  }
45523
+ function fenceBindingNames(fm) {
45524
+ const names = /* @__PURE__ */ new Set();
45525
+ const sf = import_typescript4.default.createSourceFile(
45526
+ "fence.ts",
45527
+ `${fm.hoisted}
45528
+ ${fm.body}`,
45529
+ import_typescript4.default.ScriptTarget.Latest,
45530
+ true,
45531
+ import_typescript4.default.ScriptKind.TS
45532
+ );
45533
+ const bind = (n) => {
45534
+ if (import_typescript4.default.isIdentifier(n)) names.add(n.text);
45535
+ else for (const el of n.elements) if (import_typescript4.default.isBindingElement(el)) bind(el.name);
45536
+ };
45537
+ for (const stmt of sf.statements) {
45538
+ if (import_typescript4.default.isImportDeclaration(stmt) && stmt.importClause) {
45539
+ const c = stmt.importClause;
45540
+ if (c.name) names.add(c.name.text);
45541
+ if (c.namedBindings) {
45542
+ if (import_typescript4.default.isNamespaceImport(c.namedBindings)) names.add(c.namedBindings.name.text);
45543
+ else for (const s of c.namedBindings.elements) names.add(s.name.text);
45544
+ }
45545
+ } else if (import_typescript4.default.isVariableStatement(stmt)) {
45546
+ for (const d of stmt.declarationList.declarations) bind(d.name);
45547
+ } else if (import_typescript4.default.isFunctionDeclaration(stmt) && stmt.name) {
45548
+ names.add(stmt.name.text);
45549
+ } else if (import_typescript4.default.isClassDeclaration(stmt) && stmt.name) {
45550
+ names.add(stmt.name.text);
45551
+ }
45552
+ }
45553
+ return names;
45554
+ }
45452
45555
  function emitComponent(fm, htmlExpr, meta) {
45453
45556
  let param = "";
45454
45557
  if (fm.propsType && meta.usesChildren) param = `props: ${fm.propsType} & { children?: any }`;
@@ -45572,16 +45675,8 @@ var import_typescript6 = __toESM(require("typescript"), 1);
45572
45675
 
45573
45676
  // ../stator/src/compiler/virtual-code.ts
45574
45677
  var import_typescript7 = __toESM(require("typescript"), 1);
45575
- var TEMPLATE_GLOBALS = ["read", "each", "when", "match", "defer", "on", "classList", "styleList"];
45576
- var CLIENT_GLOBALS = [
45577
- "StatorElement",
45578
- "use",
45579
- "machine",
45580
- "defineElement",
45581
- "bind",
45582
- "effect",
45583
- "dispatch"
45584
- ];
45678
+ var TEMPLATE_GLOBALS = TEMPLATE_AUTHOR_GLOBALS;
45679
+ var CLIENT_GLOBALS = CLIENT_AUTHOR_GLOBALS;
45585
45680
  function userImportedLocals(code, modulePath) {
45586
45681
  const locals = /* @__PURE__ */ new Set();
45587
45682
  const re = new RegExp(
@@ -45783,6 +45878,25 @@ function buildClientTsx(regions) {
45783
45878
  const mappings = [];
45784
45879
  const userScript = regions.scripts.map((s) => s.content).join("\n");
45785
45880
  let code = injectImports(TEMPLATE_GLOBALS, "@statorjs/stator/template", userScript) + injectImports(CLIENT_GLOBALS, "@statorjs/stator/client", userScript) + AMBIENT_TYPE_IMPORTS + STATOR_AMBIENT;
45881
+ const fm = regions.frontmatter?.content ?? "";
45882
+ if (fm.trim()) {
45883
+ const fmOffset2 = regions.frontmatter?.contentOffset ?? 0;
45884
+ const { hoisted, body } = splitFrontmatter(fm, fmOffset2);
45885
+ for (const seg of hoisted) {
45886
+ if (userScript.includes(seg.text.trim())) continue;
45887
+ push(mappings, seg.sourceOffset, code.length, seg.text.length);
45888
+ code += `${seg.text}
45889
+ `;
45890
+ }
45891
+ code += "function __statorFence(props: Record<string, unknown>) {\n";
45892
+ for (const seg of body) {
45893
+ code += " ";
45894
+ push(mappings, seg.sourceOffset, code.length, seg.text.length);
45895
+ code += `${seg.text}
45896
+ `;
45897
+ }
45898
+ code += "}\nvoid __statorFence\n";
45899
+ }
45786
45900
  for (const script of regions.scripts) {
45787
45901
  push(mappings, script.contentOffset, code.length, script.content.length);
45788
45902
  code += `${script.content}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statorjs/language-server",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Volar-based language server for .stator files.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,7 +33,7 @@
33
33
  "volar-service-typescript": "0.0.71",
34
34
  "vscode-css-languageservice": "^6.3.0",
35
35
  "vscode-uri": "^3.0.8",
36
- "@statorjs/stator": "2.0.1"
36
+ "@statorjs/stator": "2.1.0"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "typescript": "^5.6.0"