feat: support WRN imports and dynamic public shell

This commit is contained in:
2026-07-21 11:15:06 +05:30
parent 0013c0771d
commit 2ca2d02b22
82 changed files with 959 additions and 174 deletions
+27
View File
@@ -382,6 +382,24 @@ function unescapeSeoValue(value) {
}
function parse(source) {
const lx = new Lexer(source);
const imports = [];
const importPattern = /import\s+(?:type\s+)?(?:[\s\S]*?\s+from\s+)?["'][^"'\r\n]+["']\s*;?/y;
while (true) {
while (/\s/u.test(source[lx.pos] ?? ""))
lx.pos++;
if (source.startsWith("//", lx.pos)) {
while (lx.pos < source.length && source[lx.pos] !== `
`)
lx.pos++;
continue;
}
importPattern.lastIndex = lx.pos;
const statement = importPattern.exec(source);
if (!statement)
break;
imports.push(statement[0].trim());
lx.pos = importPattern.lastIndex;
}
const expect = (type) => {
const t = lx.next();
if (t.type !== type) {
@@ -627,6 +645,7 @@ function parse(source) {
}
return {
type: "page",
imports,
kind,
name,
layout,
@@ -1304,6 +1323,9 @@ function generate(ast) {
return generateComponent(ast);
}
const out = [];
if (ast.imports.length > 0)
out.push(ast.imports.join(`
`));
const ssrBindings = [];
const csrBindings = [];
const helpers = ast.functions.map((body2) => body2.trim()).filter(Boolean).join(`
@@ -1722,6 +1744,9 @@ function renderComponentNode(node, ctx) {
}
function generateComponent(ast) {
const out = [];
if (ast.imports.length > 0)
out.push(ast.imports.join(`
`));
const hasServerEach = viewHasServerEach(ast.view);
if (hasServerEach) {
out.push(`import { Buffer } from "node:buffer";`);
@@ -2192,6 +2217,8 @@ function generateNative(ast) {
import React, { useState } from "react";
import { ActivityIndicator, FlatList, Image, Pressable, SafeAreaView, ScrollView, StyleSheet, Text, TextInput, View } from "react-native";
import { useRouter } from "expo-router";
${ast.imports.join(`
`)}
${typeSource}
+7
View File
@@ -3,6 +3,13 @@
const vscode = require("vscode");
const BLOCK_COMPLETIONS = [
{
label: "import",
detail: "WRN server module import",
documentation:
"Import a package or module before the page, component, or layout declaration for server rendering.",
snippet: 'import { ${1:appUrl} } from "${2:@wrnexus/helpers}";\n\n$0',
},
{
label: "page",
detail: "WRN page",
+12
View File
@@ -89,6 +89,7 @@ function stripComments(source) {
function maskLeadingTrivia(source) {
const masked = [...source];
let offset = 0;
const importPattern = /import\s+(?:type\s+)?(?:[\s\S]*?\s+from\s+)?["'][^"'\r\n]+["']\s*;?/y;
while (offset < source.length) {
if (/\s/u.test(source[offset])) {
@@ -96,6 +97,17 @@ function maskLeadingTrivia(source) {
continue;
}
importPattern.lastIndex = offset;
const importStatement = importPattern.exec(source);
if (importStatement) {
const end = importPattern.lastIndex;
while (offset < end) {
if (source[offset] !== "\n" && source[offset] !== "\r") masked[offset] = " ";
offset += 1;
}
continue;
}
if (!source.startsWith("//", offset)) break;
while (offset < source.length && source[offset] !== "\n") {
+14
View File
@@ -326,6 +326,20 @@ function formatWrn(source, options = {}) {
previousWasBlank = false;
if (/^import\b/.test(value)) {
const importLines = [value];
while (
!/(?:\bfrom\s+)?["'][^"']+["']\s*;?$/.test(importLines[importLines.length - 1]) &&
index + 1 < inputLines.length
) {
index += 1;
importLines.push(inputLines[index].trim());
}
output.push(importLines[0], ...importLines.slice(1).map((line) => `${unit}${line}`));
index += 1;
continue;
}
if (isMultilineOpeningTagStart(value)) {
const collected = collectOpeningTag(inputLines, index);