release: WRNexusJS 0.3.0

This commit is contained in:
2026-07-22 17:29:08 +05:30
parent 13dfa31d19
commit 07d8fb59d6
145 changed files with 9664 additions and 3881 deletions
File diff suppressed because it is too large Load Diff
+52
View File
@@ -106,6 +106,56 @@ const BLOCK_COMPLETIONS = [
documentation: "Declare reactive state owned by the current component, layout, or page.",
snippet: 'state ${1:name}: ${2:string} = ${3:"value"}',
},
{
label: "runtime",
detail: "WRN execution target",
documentation: "Choose whether this declaration executes on the server, client, or both.",
snippet: 'runtime = "${1|universal,server,client|}"',
},
{
label: "hydrate",
detail: "WRN hydration strategy",
documentation: "Choose when client interactivity is initialized for this declaration.",
snippet: 'hydrate = "${1|load,idle,visible,interaction,none|}"',
},
{
label: "computed",
detail: "Derived reactive values block",
documentation:
"Declare values that are recomputed only when their reactive dependencies change.",
snippet: ["computed {", " ${1:displayName} = ${2:firstName + ' ' + lastName}", "}"].join(
"\n",
),
},
{
label: "effect",
detail: "Reactive side-effect block",
documentation: "Run browser-side code whenever its referenced reactive values change.",
snippet: ["effect {", " ${1:console.log(value)}", "}"].join("\n"),
},
{
label: "security",
detail: "Route security metadata block",
documentation: "Declare authentication, authorization, CSRF, and rate-limit policy metadata.",
snippet: [
"security {",
' auth = "${1|required,optional,public|}"',
' csrf = "${2:true}"',
"}",
].join("\n"),
},
{
label: "load",
detail: "Typed data-loading block",
documentation: "Load data on the server or client with an explicit execution boundary.",
snippet: ["load ${1|server,client|} {", " ${2:return {}}", "}"].join("\n"),
},
{
label: "action",
detail: "Named server action",
documentation: "Declare a callable mutation with an explicit name and arguments.",
snippet: ["action ${1:save}(${2:input}) {", " $0", "}"].join("\n"),
},
{
label: "functions",
detail: "Browser component functions block",
@@ -215,6 +265,8 @@ const CONTEXT_COMPLETIONS = [
["ctx.user", "Authenticated user"],
["ctx.session", "Current session"],
["ctx.locals", "Request-local data"],
["ctx.tenant", "Resolved tenant context"],
["ctx.tracer", "Request tracing interface"],
];
const WATCH_VALUE_COMPLETIONS = [
+100 -33
View File
@@ -11,33 +11,34 @@ const VALID_TOP_LEVEL_KINDS = new Set(["page", "component", "layout"]);
const VALID_LIFECYCLE_HOOKS = new Set(["mount", "update", "unmount"]);
const ROOT_MEMBER_NAMES = [
"layout",
"runtime",
"hydrate",
"client",
"types",
"props",
"state",
"computed",
"effect",
"watch",
"lifecycle",
"view",
"seo",
"security",
"load",
"action",
"api",
"ssr",
"realtime",
"style",
"functions",
];
const VALID_MEMBERS = {
page: new Set([
"layout",
"state",
"types",
"view",
"seo",
"style",
"functions",
"api",
"ssr",
"client",
"realtime",
]),
component: new Set([
"types",
"props",
"state",
"view",
"style",
"functions",
"lifecycle",
"watch",
]),
layout: new Set(["types", "props", "state", "view", "style", "functions", "lifecycle", "watch"]),
page: new Set(ROOT_MEMBER_NAMES),
component: new Set(ROOT_MEMBER_NAMES),
layout: new Set(ROOT_MEMBER_NAMES),
};
function createDiagnostic(
@@ -544,21 +545,87 @@ function findRootMembers(source, bodyStart, bodyEnd) {
end: identifier.end,
});
if (identifier.name === "state" || identifier.name === "layout") {
const assignmentMembers = new Set(["layout", "runtime", "hydrate", "state"]);
if (assignmentMembers.has(identifier.name)) {
skipLine();
continue;
}
if (identifier.name === "watch") {
index = skipWhitespace(source, index, bodyEnd);
if (identifier.name === "client") {
const next = skipWhitespace(source, index, bodyEnd);
const watchedState = readIdentifier(source, index, bodyEnd);
if (watchedState) {
index = watchedState.end;
if (source[next] === "=") {
skipLine();
continue;
}
}
const blockMembers = new Set([
"types",
"props",
"computed",
"effect",
"watch",
"lifecycle",
"view",
"seo",
"security",
"load",
"action",
"api",
"ssr",
"client",
"realtime",
"style",
"functions",
]);
if (blockMembers.has(identifier.name)) {
let cursor = index;
let parenthesisDepth = 0;
let bracketDepth = 0;
let memberQuote = null;
let memberEscaped = false;
while (cursor < bodyEnd) {
const current = source[cursor];
if (memberQuote !== null) {
if (memberEscaped) {
memberEscaped = false;
} else if (current === "\\") {
memberEscaped = true;
} else if (current === memberQuote) {
memberQuote = null;
}
cursor += 1;
continue;
}
if (current === '"' || current === "'") {
memberQuote = current;
cursor += 1;
continue;
}
if (current === "(") parenthesisDepth += 1;
if (current === ")") parenthesisDepth = Math.max(0, parenthesisDepth - 1);
if (current === "[") bracketDepth += 1;
if (current === "]") bracketDepth = Math.max(0, bracketDepth - 1);
if (current === "{" && parenthesisDepth === 0 && bracketDepth === 0) {
index = cursor;
break;
}
cursor += 1;
}
if (cursor >= bodyEnd) index = bodyEnd;
}
continue;
}
+12 -2
View File
@@ -179,11 +179,14 @@ function parseOpeningTag(value) {
const inlineClosing = remainder === `</${tagName}>`;
const closesInRemainder = remainder.startsWith(`</${tagName}>`);
return {
tagName,
attributes,
selfClosing,
inlineClosing,
closesInRemainder,
remainder,
};
}
@@ -202,7 +205,11 @@ function formatOpeningTag(value, unit, depth, printWidth = 100) {
const attributeIndent = unit.repeat(depth + 1);
const normalizedSingleLine = value.replace(/\s+/g, " ").trim();
const normalizedOpening = `<${parsed.tagName}${
parsed.attributes.length ? ` ${parsed.attributes.join(" ")}` : ""
}${parsed.selfClosing ? " /" : ""}>`;
const normalizedSingleLine = `${normalizedOpening}${parsed.remainder}`;
const shouldBreak =
parsed.attributes.length > 1 ||
@@ -212,6 +219,7 @@ function formatOpeningTag(value, unit, depth, printWidth = 100) {
const opensElement =
!parsed.selfClosing &&
!parsed.inlineClosing &&
!parsed.closesInRemainder &&
!VOID_ELEMENTS.has(parsed.tagName.toLowerCase());
if (!shouldBreak) {
@@ -375,7 +383,9 @@ function collectOpeningTag(inputLines, startIndex) {
}
return {
value: collected.join(" "),
// Preserve the fact that the opening tag was already multiline so a
// second formatter pass cannot collapse it back to one line.
value: collected.join("\n"),
endIndex: index,
};
}