@flowview/astro 0.1.3 → 0.1.4

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/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/index.ts
2
2
  import { parse } from "@astrojs/compiler/sync";
3
3
  import { createHash } from "crypto";
4
+ import { relative, sep } from "path";
4
5
  import flowviewVite, {
5
6
  compileFlowview,
6
7
  resolveCompilerPath
@@ -38,10 +39,12 @@ function flowviewAstroPlugin(options) {
38
39
  const compilerPath = resolveCompilerPath(options.compilerPath);
39
40
  const virtualModules = /* @__PURE__ */ new Map();
40
41
  const virtualIdsByFile = /* @__PURE__ */ new Map();
42
+ let projectRoot = process.cwd();
41
43
  return {
42
44
  name: "@flowview/astro:embedded",
43
45
  enforce: "pre",
44
46
  configResolved(config) {
47
+ projectRoot = config.root;
45
48
  const plugins = config.plugins;
46
49
  const ownIndex = plugins.findIndex(
47
50
  (plugin) => plugin.name === "@flowview/astro:embedded"
@@ -80,13 +83,16 @@ function flowviewAstroPlugin(options) {
80
83
  if (template === void 0) {
81
84
  throw new Error(`Missing flowview virtual module: ${publicId}`);
82
85
  }
83
- const { code } = await compileFlowview(template.source, {
86
+ const { code, map } = await compileFlowview(template.source, {
84
87
  filename: template.filename,
85
88
  lineOffset: template.lineOffset,
86
89
  runtimeImport,
87
- compilerPath
90
+ compilerPath,
91
+ sourceMapFilename: template.sourceMapFilename,
92
+ sourceMapSourceContent: template.hostSource,
93
+ sourceMapColumnOffset: template.columnOffset
88
94
  });
89
- return code;
95
+ return { code, map };
90
96
  },
91
97
  transform: {
92
98
  order: "pre",
@@ -100,7 +106,8 @@ function flowviewAstroPlugin(options) {
100
106
  code,
101
107
  cleanId,
102
108
  virtualModules,
103
- virtualIdsByFile
109
+ virtualIdsByFile,
110
+ projectRoot
104
111
  );
105
112
  } catch (error) {
106
113
  if (error instanceof FlowviewAstroError) {
@@ -120,7 +127,7 @@ function flowviewAstroPlugin(options) {
120
127
  }
121
128
  };
122
129
  }
123
- function transformAstroSource(code, filename, virtualModules, virtualIdsByFile) {
130
+ function transformAstroSource(code, filename, virtualModules, virtualIdsByFile, projectRoot) {
124
131
  const templates = findEmbeddedTemplates(code, filename);
125
132
  if (templates.length === 0) return null;
126
133
  const fileHash = createHash("sha256").update(filename).digest("hex").slice(0, 12);
@@ -136,7 +143,10 @@ function transformAstroSource(code, filename, virtualModules, virtualIdsByFile)
136
143
  virtualModules.set(virtualId, {
137
144
  source: template.source,
138
145
  filename,
139
- lineOffset: template.lineOffset
146
+ lineOffset: template.lineOffset,
147
+ columnOffset: template.columnOffset,
148
+ hostSource: code,
149
+ sourceMapFilename: relative(projectRoot, filename).split(sep).join("/")
140
150
  });
141
151
  currentIds.add(virtualId);
142
152
  imports.push(`import { render as ${renderName} } from "${virtualId}";`);
@@ -221,7 +231,8 @@ function findEmbeddedTemplates(code, filename) {
221
231
  contextExpression,
222
232
  start: openStart,
223
233
  end: closeTagEnd + 1,
224
- lineOffset: countNewlines(code, 0, openEnd + 1)
234
+ lineOffset: countNewlines(code, 0, openEnd + 1),
235
+ columnOffset: openEnd + 1 - (code.lastIndexOf("\n", openEnd) + 1)
225
236
  });
226
237
  return false;
227
238
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { parse } from \"@astrojs/compiler/sync\";\nimport type {\n Node as AstroNode,\n ParentLikeNode,\n TagLikeNode,\n} from \"@astrojs/compiler/types\";\nimport { createHash } from \"node:crypto\";\nimport flowviewVite, {\n compileFlowview,\n resolveCompilerPath,\n type FlowviewViteOptions,\n} from \"@flowview/vite\";\nimport type { AstroIntegration } from \"astro\";\nimport MagicString from \"magic-string\";\nimport type { Plugin } from \"vite\";\n\nexport interface FlowviewAstroOptions extends FlowviewViteOptions {}\n\ninterface EmbeddedTemplate {\n source: string;\n contextExpression: string;\n start: number;\n end: number;\n lineOffset: number;\n}\n\ninterface VirtualTemplate {\n source: string;\n filename: string;\n lineOffset: number;\n}\n\nclass FlowviewAstroError extends Error {\n readonly loc: { line: number; column: number };\n\n constructor(\n message: string,\n readonly filename: string,\n offset: number,\n code: string,\n ) {\n super(message);\n this.name = \"FlowviewAstroError\";\n const { line, column } = lineAndColumn(code, offset);\n this.loc = { line, column };\n }\n}\n\nconst VIRTUAL_PREFIX = \"virtual:flowview-astro/\";\nconst RESOLVED_VIRTUAL_PREFIX = \"\\0\" + VIRTUAL_PREFIX;\n\nexport default function flowview(\n options: FlowviewAstroOptions = {},\n): AstroIntegration {\n return {\n name: \"@flowview/astro\",\n hooks: {\n \"astro:config:setup\": ({ updateConfig }) => {\n updateConfig({\n vite: {\n plugins: [flowviewVite(options), flowviewAstroPlugin(options)],\n },\n });\n },\n },\n };\n}\n\nfunction flowviewAstroPlugin(options: FlowviewAstroOptions): Plugin {\n const runtimeImport = options.runtimeImport ?? \"@flowview/runtime\";\n const compilerPath = resolveCompilerPath(options.compilerPath);\n const virtualModules = new Map<string, VirtualTemplate>();\n const virtualIdsByFile = new Map<string, Set<string>>();\n\n return {\n name: \"@flowview/astro:embedded\",\n enforce: \"pre\",\n\n configResolved(config) {\n const plugins = config.plugins as Plugin[];\n const ownIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro:embedded\",\n );\n const astroIndex = plugins.findIndex(\n (plugin) => plugin.name === \"astro:build\",\n );\n const eventsIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro-events:transform\",\n );\n\n if (ownIndex > astroIndex && astroIndex !== -1) {\n const [plugin] = plugins.splice(ownIndex, 1);\n if (plugin) plugins.splice(astroIndex, 0, plugin);\n }\n const updatedOwnIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro:embedded\",\n );\n const updatedEventsIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro-events:transform\",\n );\n if (\n eventsIndex !== -1 &&\n updatedEventsIndex !== -1 &&\n updatedOwnIndex !== -1 &&\n updatedOwnIndex < updatedEventsIndex\n ) {\n const [plugin] = plugins.splice(updatedOwnIndex, 1);\n if (plugin) plugins.splice(updatedEventsIndex, 0, plugin);\n }\n },\n\n resolveId(id) {\n if (id.startsWith(VIRTUAL_PREFIX)) {\n return RESOLVED_VIRTUAL_PREFIX + id.slice(VIRTUAL_PREFIX.length);\n }\n return null;\n },\n\n async load(id) {\n if (!id.startsWith(RESOLVED_VIRTUAL_PREFIX)) return null;\n\n const publicId =\n VIRTUAL_PREFIX + id.slice(RESOLVED_VIRTUAL_PREFIX.length);\n const template = virtualModules.get(publicId);\n if (template === undefined) {\n throw new Error(`Missing flowview virtual module: ${publicId}`);\n }\n\n const { code } = await compileFlowview(template.source, {\n filename: template.filename,\n lineOffset: template.lineOffset,\n runtimeImport,\n compilerPath,\n });\n return code;\n },\n\n transform: {\n order: \"pre\",\n handler(code, id) {\n const cleanId = stripQuery(id);\n if (!cleanId.endsWith(\".astro\") || !code.includes(\"flowview\")) {\n return null;\n }\n\n try {\n return transformAstroSource(\n code,\n cleanId,\n virtualModules,\n virtualIdsByFile,\n );\n } catch (error) {\n if (error instanceof FlowviewAstroError) {\n const locatedError = {\n message: error.message,\n id: cleanId,\n loc: error.loc,\n };\n if (typeof this.error === \"function\") {\n this.error(locatedError);\n }\n throw locatedError;\n }\n throw error;\n }\n },\n },\n };\n}\n\nfunction transformAstroSource(\n code: string,\n filename: string,\n virtualModules: Map<string, VirtualTemplate>,\n virtualIdsByFile: Map<string, Set<string>>,\n): { code: string; map: ReturnType<MagicString[\"generateMap\"]> } | null {\n const templates = findEmbeddedTemplates(code, filename);\n if (templates.length === 0) return null;\n\n const fileHash = createHash(\"sha256\")\n .update(filename)\n .digest(\"hex\")\n .slice(0, 12);\n const imports: string[] = [];\n const previousIds = virtualIdsByFile.get(filename);\n previousIds?.forEach((id) => virtualModules.delete(id));\n const currentIds = new Set<string>();\n const transformed = new MagicString(code);\n\n templates.forEach((template, index) => {\n const renderName = `__flowviewRender${index}`;\n const contentHash = createHash(\"sha256\")\n .update(template.source)\n .digest(\"hex\")\n .slice(0, 12);\n const virtualId = `${VIRTUAL_PREFIX}${fileHash}/${index}-${contentHash}.js`;\n virtualModules.set(virtualId, {\n source: template.source,\n filename,\n lineOffset: template.lineOffset,\n });\n currentIds.add(virtualId);\n imports.push(`import { render as ${renderName} } from \"${virtualId}\";`);\n transformed.overwrite(\n template.start,\n template.end,\n `<Fragment set:html={${renderName}(${template.contextExpression})} />`,\n );\n });\n\n virtualIdsByFile.set(filename, currentIds);\n injectFrontmatter(transformed, code, imports.join(\"\\n\"));\n\n return {\n code: transformed.toString(),\n map: transformed.generateMap({\n source: filename,\n includeContent: true,\n hires: true,\n }),\n };\n}\n\nfunction findEmbeddedTemplates(\n code: string,\n filename: string,\n): EmbeddedTemplate[] {\n const { ast } = parse(code, { position: true });\n const templates: EmbeddedTemplate[] = [];\n\n visitAstroNodes(ast, (node) => {\n if (!isTagNode(node) || node.name !== \"template\") return true;\n const flowviewAttribute = node.attributes.find(\n (attribute) => attribute.name === \"flowview\",\n );\n if (!flowviewAttribute) return true;\n\n const firstKnownOffset =\n flowviewAttribute.position?.start.offset ??\n node.position?.start.offset ??\n 0;\n const openStart = code.lastIndexOf(\"<\", firstKnownOffset);\n const openEnd = findTagEnd(code, openStart);\n if (openStart === -1 || openEnd === -1) {\n throw new FlowviewAstroError(\n \"flowview embedded template has an invalid opening tag.\",\n filename,\n firstKnownOffset,\n code,\n );\n }\n\n const contextAttribute = node.attributes.find(\n (attribute) => attribute.name === \"context\",\n );\n const flowviewExpression =\n flowviewAttribute.kind === \"expression\"\n ? flowviewAttribute.value.trim()\n : \"\";\n const contextExpression =\n flowviewExpression !== \"\"\n ? flowviewExpression\n : contextAttribute?.kind === \"expression\"\n ? contextAttribute.value.trim()\n : \"\";\n if (!contextExpression) {\n throw new FlowviewAstroError(\n \"flowview embedded templates require a context expression: flowview={...} or context={...}.\",\n filename,\n openStart,\n code,\n );\n }\n if (flowviewExpression !== \"\" && contextAttribute?.kind === \"expression\") {\n throw new FlowviewAstroError(\n \"flowview embedded templates must not combine flowview={...} with context={...}; use one of them.\",\n filename,\n openStart,\n code,\n );\n }\n\n const closeStart = findMatchingTemplateClose(code, openEnd + 1);\n if (closeStart === -1) {\n throw new FlowviewAstroError(\n \"flowview embedded template is missing </template>.\",\n filename,\n openStart,\n code,\n );\n }\n const closeTagEnd = findTagEnd(code, closeStart);\n if (closeTagEnd === -1) {\n throw new FlowviewAstroError(\n \"flowview embedded template has an invalid closing tag.\",\n filename,\n closeStart,\n code,\n );\n }\n\n templates.push({\n source: code.slice(openEnd + 1, closeStart),\n contextExpression,\n start: openStart,\n end: closeTagEnd + 1,\n lineOffset: countNewlines(code, 0, openEnd + 1),\n });\n\n return false;\n });\n\n return templates.sort((left, right) => left.start - right.start);\n}\n\nfunction visitAstroNodes(\n root: ParentLikeNode,\n visitor: (node: AstroNode) => boolean,\n): void {\n for (const child of root.children) {\n const shouldVisitChildren = visitor(child);\n if (shouldVisitChildren && \"children\" in child) {\n visitAstroNodes(child, visitor);\n }\n }\n}\n\nfunction isTagNode(node: AstroNode): node is TagLikeNode {\n return [\"element\", \"component\", \"custom-element\", \"fragment\"].includes(\n node.type,\n );\n}\n\nfunction findMatchingTemplateClose(code: string, start: number): number {\n let cursor = start;\n let depth = 1;\n\n while (cursor < code.length) {\n const tagStart = code.indexOf(\"<\", cursor);\n if (tagStart === -1) return -1;\n\n if (startsWithIgnoreCase(code, \"<!--\", tagStart)) {\n const commentEnd = code.indexOf(\"-->\", tagStart + 4);\n if (commentEnd === -1) return -1;\n cursor = commentEnd + 3;\n continue;\n }\n\n const rawTextTag = [\"script\", \"style\"].find(\n (name) =>\n startsWithIgnoreCase(code, `<${name}`, tagStart) &&\n isTagNameBoundary(code[tagStart + name.length + 1]),\n );\n if (rawTextTag !== undefined) {\n const closeStart = findCaseInsensitive(\n code,\n `</${rawTextTag}>`,\n tagStart + 1,\n );\n if (closeStart === -1) return -1;\n cursor = closeStart + rawTextTag.length + 3;\n continue;\n }\n\n if (\n startsWithIgnoreCase(code, \"<template\", tagStart) &&\n isTagNameBoundary(code[tagStart + \"<template\".length])\n ) {\n const tagEnd = findTagEnd(code, tagStart);\n if (tagEnd === -1) return -1;\n depth += 1;\n cursor = tagEnd + 1;\n continue;\n }\n\n if (\n startsWithIgnoreCase(code, \"</template\", tagStart) &&\n isTagNameBoundary(code[tagStart + \"</template\".length])\n ) {\n const tagEnd = findTagEnd(code, tagStart);\n if (tagEnd === -1) return -1;\n depth -= 1;\n if (depth === 0) return tagStart;\n cursor = tagEnd + 1;\n continue;\n }\n\n cursor = tagStart + 1;\n }\n\n return -1;\n}\n\nfunction findTagEnd(code: string, start: number): number {\n let quote: string | null = null;\n let braceDepth = 0;\n\n for (let index = start; index < code.length; index += 1) {\n const character = code[index];\n if (quote !== null) {\n if (character === \"\\\\\") index += 1;\n else if (character === quote) quote = null;\n continue;\n }\n if (character === '\"' || character === \"'\" || character === \"`\") {\n quote = character;\n } else if (character === \"{\") {\n braceDepth += 1;\n } else if (character === \"}\") {\n braceDepth = Math.max(0, braceDepth - 1);\n } else if (character === \">\" && braceDepth === 0) {\n return index;\n }\n }\n\n return -1;\n}\n\nfunction injectFrontmatter(\n transformed: MagicString,\n original: string,\n content: string,\n): void {\n const closingFence = findFrontmatterClose(original);\n if (closingFence !== -1) {\n transformed.appendLeft(closingFence, `${content}\\n`);\n } else {\n transformed.prepend(`---\\n${content}\\n---\\n\\n`);\n }\n}\n\nfunction findFrontmatterClose(code: string): number {\n const firstLineEnd = code.indexOf(\"\\n\");\n if (firstLineEnd === -1 || code.slice(0, firstLineEnd).trim() !== \"---\") {\n return -1;\n }\n\n let lineStart = firstLineEnd + 1;\n while (lineStart <= code.length) {\n const lineEnd = code.indexOf(\"\\n\", lineStart);\n const end = lineEnd === -1 ? code.length : lineEnd;\n if (code.slice(lineStart, end).trim() === \"---\") return lineStart;\n if (lineEnd === -1) break;\n lineStart = lineEnd + 1;\n }\n\n return -1;\n}\n\nfunction isTagNameBoundary(character: string | undefined): boolean {\n return character === undefined || /[\\s/>]/.test(character);\n}\n\nfunction countNewlines(value: string, start: number, end: number): number {\n let count = 0;\n for (let index = start; index < end; index += 1) {\n if (value[index] === \"\\n\") count += 1;\n }\n return count;\n}\n\nfunction lineAndColumn(\n source: string,\n offset: number,\n): { line: number; column: number } {\n let line = 1;\n let column = 1;\n for (let index = 0; index < offset && index < source.length; index += 1) {\n if (source[index] === \"\\n\") {\n line += 1;\n column = 1;\n } else {\n column += 1;\n }\n }\n return { line, column };\n}\n\nfunction startsWithIgnoreCase(\n value: string,\n prefix: string,\n start = 0,\n): boolean {\n return (\n value.slice(start, start + prefix.length).toLowerCase() ===\n prefix.toLowerCase()\n );\n}\n\nfunction findCaseInsensitive(value: string, search: string, start = 0): number {\n const lowerSearch = search.toLowerCase();\n for (let index = start; index <= value.length - search.length; index += 1) {\n if (\n value.slice(index, index + search.length).toLowerCase() === lowerSearch\n ) {\n return index;\n }\n }\n return -1;\n}\n\nfunction stripQuery(id: string): string {\n return id.split(\"?\", 1)[0] ?? id;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { parse } from \"@astrojs/compiler/sync\";\nimport type {\n Node as AstroNode,\n ParentLikeNode,\n TagLikeNode,\n} from \"@astrojs/compiler/types\";\nimport { createHash } from \"node:crypto\";\nimport { relative, sep } from \"node:path\";\nimport flowviewVite, {\n compileFlowview,\n resolveCompilerPath,\n type FlowviewViteOptions,\n} from \"@flowview/vite\";\nimport type { AstroIntegration } from \"astro\";\nimport MagicString from \"magic-string\";\nimport type { Plugin } from \"vite\";\n\nexport interface FlowviewAstroOptions extends FlowviewViteOptions {}\n\ninterface EmbeddedTemplate {\n source: string;\n contextExpression: string;\n start: number;\n end: number;\n lineOffset: number;\n columnOffset: number;\n}\n\ninterface VirtualTemplate {\n source: string;\n filename: string;\n lineOffset: number;\n columnOffset: number;\n hostSource: string;\n sourceMapFilename: string;\n}\n\nclass FlowviewAstroError extends Error {\n readonly loc: { line: number; column: number };\n\n constructor(\n message: string,\n readonly filename: string,\n offset: number,\n code: string,\n ) {\n super(message);\n this.name = \"FlowviewAstroError\";\n const { line, column } = lineAndColumn(code, offset);\n this.loc = { line, column };\n }\n}\n\nconst VIRTUAL_PREFIX = \"virtual:flowview-astro/\";\nconst RESOLVED_VIRTUAL_PREFIX = \"\\0\" + VIRTUAL_PREFIX;\n\nexport default function flowview(\n options: FlowviewAstroOptions = {},\n): AstroIntegration {\n return {\n name: \"@flowview/astro\",\n hooks: {\n \"astro:config:setup\": ({ updateConfig }) => {\n updateConfig({\n vite: {\n plugins: [flowviewVite(options), flowviewAstroPlugin(options)],\n },\n });\n },\n },\n };\n}\n\nfunction flowviewAstroPlugin(options: FlowviewAstroOptions): Plugin {\n const runtimeImport = options.runtimeImport ?? \"@flowview/runtime\";\n const compilerPath = resolveCompilerPath(options.compilerPath);\n const virtualModules = new Map<string, VirtualTemplate>();\n const virtualIdsByFile = new Map<string, Set<string>>();\n let projectRoot = process.cwd();\n\n return {\n name: \"@flowview/astro:embedded\",\n enforce: \"pre\",\n\n configResolved(config) {\n projectRoot = config.root;\n const plugins = config.plugins as Plugin[];\n const ownIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro:embedded\",\n );\n const astroIndex = plugins.findIndex(\n (plugin) => plugin.name === \"astro:build\",\n );\n const eventsIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro-events:transform\",\n );\n\n if (ownIndex > astroIndex && astroIndex !== -1) {\n const [plugin] = plugins.splice(ownIndex, 1);\n if (plugin) plugins.splice(astroIndex, 0, plugin);\n }\n const updatedOwnIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro:embedded\",\n );\n const updatedEventsIndex = plugins.findIndex(\n (plugin) => plugin.name === \"@flowview/astro-events:transform\",\n );\n if (\n eventsIndex !== -1 &&\n updatedEventsIndex !== -1 &&\n updatedOwnIndex !== -1 &&\n updatedOwnIndex < updatedEventsIndex\n ) {\n const [plugin] = plugins.splice(updatedOwnIndex, 1);\n if (plugin) plugins.splice(updatedEventsIndex, 0, plugin);\n }\n },\n\n resolveId(id) {\n if (id.startsWith(VIRTUAL_PREFIX)) {\n return RESOLVED_VIRTUAL_PREFIX + id.slice(VIRTUAL_PREFIX.length);\n }\n return null;\n },\n\n async load(id) {\n if (!id.startsWith(RESOLVED_VIRTUAL_PREFIX)) return null;\n\n const publicId =\n VIRTUAL_PREFIX + id.slice(RESOLVED_VIRTUAL_PREFIX.length);\n const template = virtualModules.get(publicId);\n if (template === undefined) {\n throw new Error(`Missing flowview virtual module: ${publicId}`);\n }\n\n const { code, map } = await compileFlowview(template.source, {\n filename: template.filename,\n lineOffset: template.lineOffset,\n runtimeImport,\n compilerPath,\n sourceMapFilename: template.sourceMapFilename,\n sourceMapSourceContent: template.hostSource,\n sourceMapColumnOffset: template.columnOffset,\n });\n return { code, map };\n },\n\n transform: {\n order: \"pre\",\n handler(code, id) {\n const cleanId = stripQuery(id);\n if (!cleanId.endsWith(\".astro\") || !code.includes(\"flowview\")) {\n return null;\n }\n\n try {\n return transformAstroSource(\n code,\n cleanId,\n virtualModules,\n virtualIdsByFile,\n projectRoot,\n );\n } catch (error) {\n if (error instanceof FlowviewAstroError) {\n const locatedError = {\n message: error.message,\n id: cleanId,\n loc: error.loc,\n };\n if (typeof this.error === \"function\") {\n this.error(locatedError);\n }\n throw locatedError;\n }\n throw error;\n }\n },\n },\n };\n}\n\nfunction transformAstroSource(\n code: string,\n filename: string,\n virtualModules: Map<string, VirtualTemplate>,\n virtualIdsByFile: Map<string, Set<string>>,\n projectRoot: string,\n): { code: string; map: ReturnType<MagicString[\"generateMap\"]> } | null {\n const templates = findEmbeddedTemplates(code, filename);\n if (templates.length === 0) return null;\n\n const fileHash = createHash(\"sha256\")\n .update(filename)\n .digest(\"hex\")\n .slice(0, 12);\n const imports: string[] = [];\n const previousIds = virtualIdsByFile.get(filename);\n previousIds?.forEach((id) => virtualModules.delete(id));\n const currentIds = new Set<string>();\n const transformed = new MagicString(code);\n\n templates.forEach((template, index) => {\n const renderName = `__flowviewRender${index}`;\n const contentHash = createHash(\"sha256\")\n .update(template.source)\n .digest(\"hex\")\n .slice(0, 12);\n const virtualId = `${VIRTUAL_PREFIX}${fileHash}/${index}-${contentHash}.js`;\n virtualModules.set(virtualId, {\n source: template.source,\n filename,\n lineOffset: template.lineOffset,\n columnOffset: template.columnOffset,\n hostSource: code,\n sourceMapFilename: relative(projectRoot, filename).split(sep).join(\"/\"),\n });\n currentIds.add(virtualId);\n imports.push(`import { render as ${renderName} } from \"${virtualId}\";`);\n transformed.overwrite(\n template.start,\n template.end,\n `<Fragment set:html={${renderName}(${template.contextExpression})} />`,\n );\n });\n\n virtualIdsByFile.set(filename, currentIds);\n injectFrontmatter(transformed, code, imports.join(\"\\n\"));\n\n return {\n code: transformed.toString(),\n map: transformed.generateMap({\n source: filename,\n includeContent: true,\n hires: true,\n }),\n };\n}\n\nfunction findEmbeddedTemplates(\n code: string,\n filename: string,\n): EmbeddedTemplate[] {\n const { ast } = parse(code, { position: true });\n const templates: EmbeddedTemplate[] = [];\n\n visitAstroNodes(ast, (node) => {\n if (!isTagNode(node) || node.name !== \"template\") return true;\n const flowviewAttribute = node.attributes.find(\n (attribute) => attribute.name === \"flowview\",\n );\n if (!flowviewAttribute) return true;\n\n const firstKnownOffset =\n flowviewAttribute.position?.start.offset ??\n node.position?.start.offset ??\n 0;\n const openStart = code.lastIndexOf(\"<\", firstKnownOffset);\n const openEnd = findTagEnd(code, openStart);\n if (openStart === -1 || openEnd === -1) {\n throw new FlowviewAstroError(\n \"flowview embedded template has an invalid opening tag.\",\n filename,\n firstKnownOffset,\n code,\n );\n }\n\n const contextAttribute = node.attributes.find(\n (attribute) => attribute.name === \"context\",\n );\n const flowviewExpression =\n flowviewAttribute.kind === \"expression\"\n ? flowviewAttribute.value.trim()\n : \"\";\n const contextExpression =\n flowviewExpression !== \"\"\n ? flowviewExpression\n : contextAttribute?.kind === \"expression\"\n ? contextAttribute.value.trim()\n : \"\";\n if (!contextExpression) {\n throw new FlowviewAstroError(\n \"flowview embedded templates require a context expression: flowview={...} or context={...}.\",\n filename,\n openStart,\n code,\n );\n }\n if (flowviewExpression !== \"\" && contextAttribute?.kind === \"expression\") {\n throw new FlowviewAstroError(\n \"flowview embedded templates must not combine flowview={...} with context={...}; use one of them.\",\n filename,\n openStart,\n code,\n );\n }\n\n const closeStart = findMatchingTemplateClose(code, openEnd + 1);\n if (closeStart === -1) {\n throw new FlowviewAstroError(\n \"flowview embedded template is missing </template>.\",\n filename,\n openStart,\n code,\n );\n }\n const closeTagEnd = findTagEnd(code, closeStart);\n if (closeTagEnd === -1) {\n throw new FlowviewAstroError(\n \"flowview embedded template has an invalid closing tag.\",\n filename,\n closeStart,\n code,\n );\n }\n\n templates.push({\n source: code.slice(openEnd + 1, closeStart),\n contextExpression,\n start: openStart,\n end: closeTagEnd + 1,\n lineOffset: countNewlines(code, 0, openEnd + 1),\n columnOffset: openEnd + 1 - (code.lastIndexOf(\"\\n\", openEnd) + 1),\n });\n\n return false;\n });\n\n return templates.sort((left, right) => left.start - right.start);\n}\n\nfunction visitAstroNodes(\n root: ParentLikeNode,\n visitor: (node: AstroNode) => boolean,\n): void {\n for (const child of root.children) {\n const shouldVisitChildren = visitor(child);\n if (shouldVisitChildren && \"children\" in child) {\n visitAstroNodes(child, visitor);\n }\n }\n}\n\nfunction isTagNode(node: AstroNode): node is TagLikeNode {\n return [\"element\", \"component\", \"custom-element\", \"fragment\"].includes(\n node.type,\n );\n}\n\nfunction findMatchingTemplateClose(code: string, start: number): number {\n let cursor = start;\n let depth = 1;\n\n while (cursor < code.length) {\n const tagStart = code.indexOf(\"<\", cursor);\n if (tagStart === -1) return -1;\n\n if (startsWithIgnoreCase(code, \"<!--\", tagStart)) {\n const commentEnd = code.indexOf(\"-->\", tagStart + 4);\n if (commentEnd === -1) return -1;\n cursor = commentEnd + 3;\n continue;\n }\n\n const rawTextTag = [\"script\", \"style\"].find(\n (name) =>\n startsWithIgnoreCase(code, `<${name}`, tagStart) &&\n isTagNameBoundary(code[tagStart + name.length + 1]),\n );\n if (rawTextTag !== undefined) {\n const closeStart = findCaseInsensitive(\n code,\n `</${rawTextTag}>`,\n tagStart + 1,\n );\n if (closeStart === -1) return -1;\n cursor = closeStart + rawTextTag.length + 3;\n continue;\n }\n\n if (\n startsWithIgnoreCase(code, \"<template\", tagStart) &&\n isTagNameBoundary(code[tagStart + \"<template\".length])\n ) {\n const tagEnd = findTagEnd(code, tagStart);\n if (tagEnd === -1) return -1;\n depth += 1;\n cursor = tagEnd + 1;\n continue;\n }\n\n if (\n startsWithIgnoreCase(code, \"</template\", tagStart) &&\n isTagNameBoundary(code[tagStart + \"</template\".length])\n ) {\n const tagEnd = findTagEnd(code, tagStart);\n if (tagEnd === -1) return -1;\n depth -= 1;\n if (depth === 0) return tagStart;\n cursor = tagEnd + 1;\n continue;\n }\n\n cursor = tagStart + 1;\n }\n\n return -1;\n}\n\nfunction findTagEnd(code: string, start: number): number {\n let quote: string | null = null;\n let braceDepth = 0;\n\n for (let index = start; index < code.length; index += 1) {\n const character = code[index];\n if (quote !== null) {\n if (character === \"\\\\\") index += 1;\n else if (character === quote) quote = null;\n continue;\n }\n if (character === '\"' || character === \"'\" || character === \"`\") {\n quote = character;\n } else if (character === \"{\") {\n braceDepth += 1;\n } else if (character === \"}\") {\n braceDepth = Math.max(0, braceDepth - 1);\n } else if (character === \">\" && braceDepth === 0) {\n return index;\n }\n }\n\n return -1;\n}\n\nfunction injectFrontmatter(\n transformed: MagicString,\n original: string,\n content: string,\n): void {\n const closingFence = findFrontmatterClose(original);\n if (closingFence !== -1) {\n transformed.appendLeft(closingFence, `${content}\\n`);\n } else {\n transformed.prepend(`---\\n${content}\\n---\\n\\n`);\n }\n}\n\nfunction findFrontmatterClose(code: string): number {\n const firstLineEnd = code.indexOf(\"\\n\");\n if (firstLineEnd === -1 || code.slice(0, firstLineEnd).trim() !== \"---\") {\n return -1;\n }\n\n let lineStart = firstLineEnd + 1;\n while (lineStart <= code.length) {\n const lineEnd = code.indexOf(\"\\n\", lineStart);\n const end = lineEnd === -1 ? code.length : lineEnd;\n if (code.slice(lineStart, end).trim() === \"---\") return lineStart;\n if (lineEnd === -1) break;\n lineStart = lineEnd + 1;\n }\n\n return -1;\n}\n\nfunction isTagNameBoundary(character: string | undefined): boolean {\n return character === undefined || /[\\s/>]/.test(character);\n}\n\nfunction countNewlines(value: string, start: number, end: number): number {\n let count = 0;\n for (let index = start; index < end; index += 1) {\n if (value[index] === \"\\n\") count += 1;\n }\n return count;\n}\n\nfunction lineAndColumn(\n source: string,\n offset: number,\n): { line: number; column: number } {\n let line = 1;\n let column = 1;\n for (let index = 0; index < offset && index < source.length; index += 1) {\n if (source[index] === \"\\n\") {\n line += 1;\n column = 1;\n } else {\n column += 1;\n }\n }\n return { line, column };\n}\n\nfunction startsWithIgnoreCase(\n value: string,\n prefix: string,\n start = 0,\n): boolean {\n return (\n value.slice(start, start + prefix.length).toLowerCase() ===\n prefix.toLowerCase()\n );\n}\n\nfunction findCaseInsensitive(value: string, search: string, start = 0): number {\n const lowerSearch = search.toLowerCase();\n for (let index = start; index <= value.length - search.length; index += 1) {\n if (\n value.slice(index, index + search.length).toLowerCase() === lowerSearch\n ) {\n return index;\n }\n }\n return -1;\n}\n\nfunction stripQuery(id: string): string {\n return id.split(\"?\", 1)[0] ?? id;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowview/astro",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Astro integration for flowview templates.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -36,8 +36,8 @@
36
36
  "dependencies": {
37
37
  "@astrojs/compiler": "^2.13.1",
38
38
  "magic-string": "^0.30.21",
39
- "@flowview/runtime": "^0.2.0",
40
- "@flowview/vite": "^0.1.3"
39
+ "@flowview/vite": "^0.1.4",
40
+ "@flowview/runtime": "^0.2.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^26.0.0",