@flowview/astro 0.1.4 → 0.1.5
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 +198 -182
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { parse } from "@astrojs/compiler/sync";
|
|
3
2
|
import { createHash } from "crypto";
|
|
4
3
|
import { relative, sep } from "path";
|
|
5
4
|
import flowviewVite, {
|
|
@@ -7,166 +6,19 @@ import flowviewVite, {
|
|
|
7
6
|
resolveCompilerPath
|
|
8
7
|
} from "@flowview/vite";
|
|
9
8
|
import MagicString from "magic-string";
|
|
9
|
+
|
|
10
|
+
// src/embedded-regions.ts
|
|
11
|
+
import { parse } from "@astrojs/compiler/sync";
|
|
10
12
|
var FlowviewAstroError = class extends Error {
|
|
11
13
|
constructor(message, filename, offset, code) {
|
|
12
14
|
super(message);
|
|
13
15
|
this.filename = filename;
|
|
14
16
|
this.name = "FlowviewAstroError";
|
|
15
|
-
|
|
16
|
-
this.loc = { line, column };
|
|
17
|
+
this.loc = lineAndColumn(code, offset);
|
|
17
18
|
}
|
|
18
19
|
filename;
|
|
19
20
|
loc;
|
|
20
21
|
};
|
|
21
|
-
var VIRTUAL_PREFIX = "virtual:flowview-astro/";
|
|
22
|
-
var RESOLVED_VIRTUAL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
23
|
-
function flowview(options = {}) {
|
|
24
|
-
return {
|
|
25
|
-
name: "@flowview/astro",
|
|
26
|
-
hooks: {
|
|
27
|
-
"astro:config:setup": ({ updateConfig }) => {
|
|
28
|
-
updateConfig({
|
|
29
|
-
vite: {
|
|
30
|
-
plugins: [flowviewVite(options), flowviewAstroPlugin(options)]
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
function flowviewAstroPlugin(options) {
|
|
38
|
-
const runtimeImport = options.runtimeImport ?? "@flowview/runtime";
|
|
39
|
-
const compilerPath = resolveCompilerPath(options.compilerPath);
|
|
40
|
-
const virtualModules = /* @__PURE__ */ new Map();
|
|
41
|
-
const virtualIdsByFile = /* @__PURE__ */ new Map();
|
|
42
|
-
let projectRoot = process.cwd();
|
|
43
|
-
return {
|
|
44
|
-
name: "@flowview/astro:embedded",
|
|
45
|
-
enforce: "pre",
|
|
46
|
-
configResolved(config) {
|
|
47
|
-
projectRoot = config.root;
|
|
48
|
-
const plugins = config.plugins;
|
|
49
|
-
const ownIndex = plugins.findIndex(
|
|
50
|
-
(plugin) => plugin.name === "@flowview/astro:embedded"
|
|
51
|
-
);
|
|
52
|
-
const astroIndex = plugins.findIndex(
|
|
53
|
-
(plugin) => plugin.name === "astro:build"
|
|
54
|
-
);
|
|
55
|
-
const eventsIndex = plugins.findIndex(
|
|
56
|
-
(plugin) => plugin.name === "@flowview/astro-events:transform"
|
|
57
|
-
);
|
|
58
|
-
if (ownIndex > astroIndex && astroIndex !== -1) {
|
|
59
|
-
const [plugin] = plugins.splice(ownIndex, 1);
|
|
60
|
-
if (plugin) plugins.splice(astroIndex, 0, plugin);
|
|
61
|
-
}
|
|
62
|
-
const updatedOwnIndex = plugins.findIndex(
|
|
63
|
-
(plugin) => plugin.name === "@flowview/astro:embedded"
|
|
64
|
-
);
|
|
65
|
-
const updatedEventsIndex = plugins.findIndex(
|
|
66
|
-
(plugin) => plugin.name === "@flowview/astro-events:transform"
|
|
67
|
-
);
|
|
68
|
-
if (eventsIndex !== -1 && updatedEventsIndex !== -1 && updatedOwnIndex !== -1 && updatedOwnIndex < updatedEventsIndex) {
|
|
69
|
-
const [plugin] = plugins.splice(updatedOwnIndex, 1);
|
|
70
|
-
if (plugin) plugins.splice(updatedEventsIndex, 0, plugin);
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
resolveId(id) {
|
|
74
|
-
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
75
|
-
return RESOLVED_VIRTUAL_PREFIX + id.slice(VIRTUAL_PREFIX.length);
|
|
76
|
-
}
|
|
77
|
-
return null;
|
|
78
|
-
},
|
|
79
|
-
async load(id) {
|
|
80
|
-
if (!id.startsWith(RESOLVED_VIRTUAL_PREFIX)) return null;
|
|
81
|
-
const publicId = VIRTUAL_PREFIX + id.slice(RESOLVED_VIRTUAL_PREFIX.length);
|
|
82
|
-
const template = virtualModules.get(publicId);
|
|
83
|
-
if (template === void 0) {
|
|
84
|
-
throw new Error(`Missing flowview virtual module: ${publicId}`);
|
|
85
|
-
}
|
|
86
|
-
const { code, map } = await compileFlowview(template.source, {
|
|
87
|
-
filename: template.filename,
|
|
88
|
-
lineOffset: template.lineOffset,
|
|
89
|
-
runtimeImport,
|
|
90
|
-
compilerPath,
|
|
91
|
-
sourceMapFilename: template.sourceMapFilename,
|
|
92
|
-
sourceMapSourceContent: template.hostSource,
|
|
93
|
-
sourceMapColumnOffset: template.columnOffset
|
|
94
|
-
});
|
|
95
|
-
return { code, map };
|
|
96
|
-
},
|
|
97
|
-
transform: {
|
|
98
|
-
order: "pre",
|
|
99
|
-
handler(code, id) {
|
|
100
|
-
const cleanId = stripQuery(id);
|
|
101
|
-
if (!cleanId.endsWith(".astro") || !code.includes("flowview")) {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
try {
|
|
105
|
-
return transformAstroSource(
|
|
106
|
-
code,
|
|
107
|
-
cleanId,
|
|
108
|
-
virtualModules,
|
|
109
|
-
virtualIdsByFile,
|
|
110
|
-
projectRoot
|
|
111
|
-
);
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (error instanceof FlowviewAstroError) {
|
|
114
|
-
const locatedError = {
|
|
115
|
-
message: error.message,
|
|
116
|
-
id: cleanId,
|
|
117
|
-
loc: error.loc
|
|
118
|
-
};
|
|
119
|
-
if (typeof this.error === "function") {
|
|
120
|
-
this.error(locatedError);
|
|
121
|
-
}
|
|
122
|
-
throw locatedError;
|
|
123
|
-
}
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
function transformAstroSource(code, filename, virtualModules, virtualIdsByFile, projectRoot) {
|
|
131
|
-
const templates = findEmbeddedTemplates(code, filename);
|
|
132
|
-
if (templates.length === 0) return null;
|
|
133
|
-
const fileHash = createHash("sha256").update(filename).digest("hex").slice(0, 12);
|
|
134
|
-
const imports = [];
|
|
135
|
-
const previousIds = virtualIdsByFile.get(filename);
|
|
136
|
-
previousIds?.forEach((id) => virtualModules.delete(id));
|
|
137
|
-
const currentIds = /* @__PURE__ */ new Set();
|
|
138
|
-
const transformed = new MagicString(code);
|
|
139
|
-
templates.forEach((template, index) => {
|
|
140
|
-
const renderName = `__flowviewRender${index}`;
|
|
141
|
-
const contentHash = createHash("sha256").update(template.source).digest("hex").slice(0, 12);
|
|
142
|
-
const virtualId = `${VIRTUAL_PREFIX}${fileHash}/${index}-${contentHash}.js`;
|
|
143
|
-
virtualModules.set(virtualId, {
|
|
144
|
-
source: template.source,
|
|
145
|
-
filename,
|
|
146
|
-
lineOffset: template.lineOffset,
|
|
147
|
-
columnOffset: template.columnOffset,
|
|
148
|
-
hostSource: code,
|
|
149
|
-
sourceMapFilename: relative(projectRoot, filename).split(sep).join("/")
|
|
150
|
-
});
|
|
151
|
-
currentIds.add(virtualId);
|
|
152
|
-
imports.push(`import { render as ${renderName} } from "${virtualId}";`);
|
|
153
|
-
transformed.overwrite(
|
|
154
|
-
template.start,
|
|
155
|
-
template.end,
|
|
156
|
-
`<Fragment set:html={${renderName}(${template.contextExpression})} />`
|
|
157
|
-
);
|
|
158
|
-
});
|
|
159
|
-
virtualIdsByFile.set(filename, currentIds);
|
|
160
|
-
injectFrontmatter(transformed, code, imports.join("\n"));
|
|
161
|
-
return {
|
|
162
|
-
code: transformed.toString(),
|
|
163
|
-
map: transformed.generateMap({
|
|
164
|
-
source: filename,
|
|
165
|
-
includeContent: true,
|
|
166
|
-
hires: true
|
|
167
|
-
})
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
22
|
function findEmbeddedTemplates(code, filename) {
|
|
171
23
|
const { ast } = parse(code, { position: true });
|
|
172
24
|
const templates = [];
|
|
@@ -176,7 +28,10 @@ function findEmbeddedTemplates(code, filename) {
|
|
|
176
28
|
(attribute) => attribute.name === "flowview"
|
|
177
29
|
);
|
|
178
30
|
if (!flowviewAttribute) return true;
|
|
179
|
-
const firstKnownOffset =
|
|
31
|
+
const firstKnownOffset = toCodeUnitOffset(
|
|
32
|
+
code,
|
|
33
|
+
flowviewAttribute.position?.start.offset ?? node.position?.start.offset ?? 0
|
|
34
|
+
);
|
|
180
35
|
const openStart = code.lastIndexOf("<", firstKnownOffset);
|
|
181
36
|
const openEnd = findTagEnd(code, openStart);
|
|
182
37
|
if (openStart === -1 || openEnd === -1) {
|
|
@@ -230,6 +85,7 @@ function findEmbeddedTemplates(code, filename) {
|
|
|
230
85
|
source: code.slice(openEnd + 1, closeStart),
|
|
231
86
|
contextExpression,
|
|
232
87
|
start: openStart,
|
|
88
|
+
bodyStart: openEnd + 1,
|
|
233
89
|
end: closeTagEnd + 1,
|
|
234
90
|
lineOffset: countNewlines(code, 0, openEnd + 1),
|
|
235
91
|
columnOffset: openEnd + 1 - (code.lastIndexOf("\n", openEnd) + 1)
|
|
@@ -317,34 +173,6 @@ function findTagEnd(code, start) {
|
|
|
317
173
|
}
|
|
318
174
|
return -1;
|
|
319
175
|
}
|
|
320
|
-
function injectFrontmatter(transformed, original, content) {
|
|
321
|
-
const closingFence = findFrontmatterClose(original);
|
|
322
|
-
if (closingFence !== -1) {
|
|
323
|
-
transformed.appendLeft(closingFence, `${content}
|
|
324
|
-
`);
|
|
325
|
-
} else {
|
|
326
|
-
transformed.prepend(`---
|
|
327
|
-
${content}
|
|
328
|
-
---
|
|
329
|
-
|
|
330
|
-
`);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
function findFrontmatterClose(code) {
|
|
334
|
-
const firstLineEnd = code.indexOf("\n");
|
|
335
|
-
if (firstLineEnd === -1 || code.slice(0, firstLineEnd).trim() !== "---") {
|
|
336
|
-
return -1;
|
|
337
|
-
}
|
|
338
|
-
let lineStart = firstLineEnd + 1;
|
|
339
|
-
while (lineStart <= code.length) {
|
|
340
|
-
const lineEnd = code.indexOf("\n", lineStart);
|
|
341
|
-
const end = lineEnd === -1 ? code.length : lineEnd;
|
|
342
|
-
if (code.slice(lineStart, end).trim() === "---") return lineStart;
|
|
343
|
-
if (lineEnd === -1) break;
|
|
344
|
-
lineStart = lineEnd + 1;
|
|
345
|
-
}
|
|
346
|
-
return -1;
|
|
347
|
-
}
|
|
348
176
|
function isTagNameBoundary(character) {
|
|
349
177
|
return character === void 0 || /[\s/>]/.test(character);
|
|
350
178
|
}
|
|
@@ -368,15 +196,203 @@ function lineAndColumn(source, offset) {
|
|
|
368
196
|
}
|
|
369
197
|
return { line, column };
|
|
370
198
|
}
|
|
199
|
+
function toCodeUnitOffset(source, byteOffset) {
|
|
200
|
+
let bytes = 0;
|
|
201
|
+
let units = 0;
|
|
202
|
+
for (const character of source) {
|
|
203
|
+
if (bytes >= byteOffset) break;
|
|
204
|
+
bytes += Buffer.byteLength(character, "utf8");
|
|
205
|
+
units += character.length;
|
|
206
|
+
}
|
|
207
|
+
return units;
|
|
208
|
+
}
|
|
371
209
|
function startsWithIgnoreCase(value, prefix, start = 0) {
|
|
372
210
|
return value.slice(start, start + prefix.length).toLowerCase() === prefix.toLowerCase();
|
|
373
211
|
}
|
|
374
212
|
function findCaseInsensitive(value, search, start = 0) {
|
|
375
213
|
const lowerSearch = search.toLowerCase();
|
|
376
214
|
for (let index = start; index <= value.length - search.length; index += 1) {
|
|
377
|
-
if (value.slice(index, index + search.length).toLowerCase() === lowerSearch)
|
|
215
|
+
if (value.slice(index, index + search.length).toLowerCase() === lowerSearch)
|
|
378
216
|
return index;
|
|
217
|
+
}
|
|
218
|
+
return -1;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/index.ts
|
|
222
|
+
var VIRTUAL_PREFIX = "virtual:flowview-astro/";
|
|
223
|
+
var RESOLVED_VIRTUAL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
224
|
+
function flowview(options = {}) {
|
|
225
|
+
return {
|
|
226
|
+
name: "@flowview/astro",
|
|
227
|
+
hooks: {
|
|
228
|
+
"astro:config:setup": ({ updateConfig }) => {
|
|
229
|
+
updateConfig({
|
|
230
|
+
vite: {
|
|
231
|
+
plugins: [flowviewVite(options), flowviewAstroPlugin(options)]
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function flowviewAstroPlugin(options) {
|
|
239
|
+
const runtimeImport = options.runtimeImport ?? "@flowview/runtime";
|
|
240
|
+
const compilerPath = resolveCompilerPath(options.compilerPath);
|
|
241
|
+
const virtualModules = /* @__PURE__ */ new Map();
|
|
242
|
+
const virtualIdsByFile = /* @__PURE__ */ new Map();
|
|
243
|
+
let projectRoot = process.cwd();
|
|
244
|
+
return {
|
|
245
|
+
name: "@flowview/astro:embedded",
|
|
246
|
+
enforce: "pre",
|
|
247
|
+
configResolved(config) {
|
|
248
|
+
projectRoot = config.root;
|
|
249
|
+
const plugins = config.plugins;
|
|
250
|
+
const ownIndex = plugins.findIndex(
|
|
251
|
+
(plugin) => plugin.name === "@flowview/astro:embedded"
|
|
252
|
+
);
|
|
253
|
+
const astroIndex = plugins.findIndex(
|
|
254
|
+
(plugin) => plugin.name === "astro:build"
|
|
255
|
+
);
|
|
256
|
+
const eventsIndex = plugins.findIndex(
|
|
257
|
+
(plugin) => plugin.name === "@flowview/astro-events:transform"
|
|
258
|
+
);
|
|
259
|
+
if (ownIndex > astroIndex && astroIndex !== -1) {
|
|
260
|
+
const [plugin] = plugins.splice(ownIndex, 1);
|
|
261
|
+
if (plugin) plugins.splice(astroIndex, 0, plugin);
|
|
262
|
+
}
|
|
263
|
+
const updatedOwnIndex = plugins.findIndex(
|
|
264
|
+
(plugin) => plugin.name === "@flowview/astro:embedded"
|
|
265
|
+
);
|
|
266
|
+
const updatedEventsIndex = plugins.findIndex(
|
|
267
|
+
(plugin) => plugin.name === "@flowview/astro-events:transform"
|
|
268
|
+
);
|
|
269
|
+
if (eventsIndex !== -1 && updatedEventsIndex !== -1 && updatedOwnIndex !== -1 && updatedOwnIndex < updatedEventsIndex) {
|
|
270
|
+
const [plugin] = plugins.splice(updatedOwnIndex, 1);
|
|
271
|
+
if (plugin) plugins.splice(updatedEventsIndex, 0, plugin);
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
resolveId(id) {
|
|
275
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
276
|
+
return RESOLVED_VIRTUAL_PREFIX + id.slice(VIRTUAL_PREFIX.length);
|
|
277
|
+
}
|
|
278
|
+
return null;
|
|
279
|
+
},
|
|
280
|
+
async load(id) {
|
|
281
|
+
if (!id.startsWith(RESOLVED_VIRTUAL_PREFIX)) return null;
|
|
282
|
+
const publicId = VIRTUAL_PREFIX + id.slice(RESOLVED_VIRTUAL_PREFIX.length);
|
|
283
|
+
const template = virtualModules.get(publicId);
|
|
284
|
+
if (template === void 0) {
|
|
285
|
+
throw new Error(`Missing flowview virtual module: ${publicId}`);
|
|
286
|
+
}
|
|
287
|
+
const { code, map } = await compileFlowview(template.source, {
|
|
288
|
+
filename: template.filename,
|
|
289
|
+
lineOffset: template.lineOffset,
|
|
290
|
+
runtimeImport,
|
|
291
|
+
compilerPath,
|
|
292
|
+
sourceMapFilename: template.sourceMapFilename,
|
|
293
|
+
sourceMapSourceContent: template.hostSource,
|
|
294
|
+
sourceMapColumnOffset: template.columnOffset
|
|
295
|
+
});
|
|
296
|
+
return { code, map };
|
|
297
|
+
},
|
|
298
|
+
transform: {
|
|
299
|
+
order: "pre",
|
|
300
|
+
handler(code, id) {
|
|
301
|
+
const cleanId = stripQuery(id);
|
|
302
|
+
if (!cleanId.endsWith(".astro") || !code.includes("flowview")) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
return transformAstroSource(
|
|
307
|
+
code,
|
|
308
|
+
cleanId,
|
|
309
|
+
virtualModules,
|
|
310
|
+
virtualIdsByFile,
|
|
311
|
+
projectRoot
|
|
312
|
+
);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
if (error instanceof FlowviewAstroError) {
|
|
315
|
+
const locatedError = {
|
|
316
|
+
message: error.message,
|
|
317
|
+
id: cleanId,
|
|
318
|
+
loc: error.loc
|
|
319
|
+
};
|
|
320
|
+
if (typeof this.error === "function") {
|
|
321
|
+
this.error(locatedError);
|
|
322
|
+
}
|
|
323
|
+
throw locatedError;
|
|
324
|
+
}
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
379
328
|
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function transformAstroSource(code, filename, virtualModules, virtualIdsByFile, projectRoot) {
|
|
332
|
+
const templates = findEmbeddedTemplates(code, filename);
|
|
333
|
+
if (templates.length === 0) return null;
|
|
334
|
+
const fileHash = createHash("sha256").update(filename).digest("hex").slice(0, 12);
|
|
335
|
+
const imports = [];
|
|
336
|
+
const previousIds = virtualIdsByFile.get(filename);
|
|
337
|
+
previousIds?.forEach((id) => virtualModules.delete(id));
|
|
338
|
+
const currentIds = /* @__PURE__ */ new Set();
|
|
339
|
+
const transformed = new MagicString(code);
|
|
340
|
+
templates.forEach((template, index) => {
|
|
341
|
+
const renderName = `__flowviewRender${index}`;
|
|
342
|
+
const contentHash = createHash("sha256").update(template.source).digest("hex").slice(0, 12);
|
|
343
|
+
const virtualId = `${VIRTUAL_PREFIX}${fileHash}/${index}-${contentHash}.js`;
|
|
344
|
+
virtualModules.set(virtualId, {
|
|
345
|
+
source: template.source,
|
|
346
|
+
filename,
|
|
347
|
+
lineOffset: template.lineOffset,
|
|
348
|
+
columnOffset: template.columnOffset,
|
|
349
|
+
hostSource: code,
|
|
350
|
+
sourceMapFilename: relative(projectRoot, filename).split(sep).join("/")
|
|
351
|
+
});
|
|
352
|
+
currentIds.add(virtualId);
|
|
353
|
+
imports.push(`import { render as ${renderName} } from "${virtualId}";`);
|
|
354
|
+
transformed.overwrite(
|
|
355
|
+
template.start,
|
|
356
|
+
template.end,
|
|
357
|
+
`<Fragment set:html={${renderName}(${template.contextExpression})} />`
|
|
358
|
+
);
|
|
359
|
+
});
|
|
360
|
+
virtualIdsByFile.set(filename, currentIds);
|
|
361
|
+
injectFrontmatter(transformed, code, imports.join("\n"));
|
|
362
|
+
return {
|
|
363
|
+
code: transformed.toString(),
|
|
364
|
+
map: transformed.generateMap({
|
|
365
|
+
source: filename,
|
|
366
|
+
includeContent: true,
|
|
367
|
+
hires: true
|
|
368
|
+
})
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
function injectFrontmatter(transformed, original, content) {
|
|
372
|
+
const closingFence = findFrontmatterClose(original);
|
|
373
|
+
if (closingFence !== -1) {
|
|
374
|
+
transformed.appendLeft(closingFence, `${content}
|
|
375
|
+
`);
|
|
376
|
+
} else {
|
|
377
|
+
transformed.prepend(`---
|
|
378
|
+
${content}
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function findFrontmatterClose(code) {
|
|
385
|
+
const firstLineEnd = code.indexOf("\n");
|
|
386
|
+
if (firstLineEnd === -1 || code.slice(0, firstLineEnd).trim() !== "---") {
|
|
387
|
+
return -1;
|
|
388
|
+
}
|
|
389
|
+
let lineStart = firstLineEnd + 1;
|
|
390
|
+
while (lineStart <= code.length) {
|
|
391
|
+
const lineEnd = code.indexOf("\n", lineStart);
|
|
392
|
+
const end = lineEnd === -1 ? code.length : lineEnd;
|
|
393
|
+
if (code.slice(lineStart, end).trim() === "---") return lineStart;
|
|
394
|
+
if (lineEnd === -1) break;
|
|
395
|
+
lineStart = lineEnd + 1;
|
|
380
396
|
}
|
|
381
397
|
return -1;
|
|
382
398
|
}
|
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 { 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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/embedded-regions.ts"],"sourcesContent":["import { 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\";\nimport {\n findEmbeddedTemplates,\n FlowviewAstroError,\n type EmbeddedTemplate,\n} from \"./embedded-regions.js\";\n\nexport interface FlowviewAstroOptions extends FlowviewViteOptions {}\n\ninterface VirtualTemplate {\n source: string;\n filename: string;\n lineOffset: number;\n columnOffset: number;\n hostSource: string;\n sourceMapFilename: string;\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 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 stripQuery(id: string): string {\n return id.split(\"?\", 1)[0] ?? id;\n}\n","import { parse } from \"@astrojs/compiler/sync\";\nimport type {\n Node as AstroNode,\n ParentLikeNode,\n TagLikeNode,\n} from \"@astrojs/compiler/types\";\n\nexport interface EmbeddedTemplate {\n source: string;\n contextExpression: string;\n start: number;\n bodyStart: number;\n end: number;\n lineOffset: number;\n columnOffset: number;\n}\n\nexport class 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 this.loc = lineAndColumn(code, offset);\n }\n}\n\n/** Find embedded FlowView templates using the same Astro AST and wrapper checks as the transform. */\nexport function 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 = toCodeUnitOffset(\n code,\n flowviewAttribute.position?.start.offset ??\n node.position?.start.offset ??\n 0,\n );\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 bodyStart: openEnd + 1,\n end: closeTagEnd + 1,\n lineOffset: countNewlines(code, 0, openEnd + 1),\n columnOffset: openEnd + 1 - (code.lastIndexOf(\"\\n\", openEnd) + 1),\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 while (cursor < code.length) {\n const tagStart = code.indexOf(\"<\", cursor);\n if (tagStart === -1) return -1;\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 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 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 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 cursor = tagStart + 1;\n }\n return -1;\n}\n\nfunction findTagEnd(code: string, start: number): number {\n let quote: string | null = null;\n let braceDepth = 0;\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 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(source: string, offset: 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 toCodeUnitOffset(source: string, byteOffset: number): number {\n let bytes = 0;\n let units = 0;\n for (const character of source) {\n if (bytes >= byteOffset) break;\n bytes += Buffer.byteLength(character, \"utf8\");\n units += character.length;\n }\n return units;\n}\n\nfunction startsWithIgnoreCase(value: string, prefix: string, start = 0) {\n return (\n value.slice(start, start + prefix.length).toLowerCase() ===\n prefix.toLowerCase()\n );\n}\n\nfunction findCaseInsensitive(value: string, search: string, start = 0) {\n const lowerSearch = search.toLowerCase();\n for (let index = start; index <= value.length - search.length; index += 1) {\n if (value.slice(index, index + search.length).toLowerCase() === lowerSearch)\n return index;\n }\n return -1;\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
|
+
"version": "0.1.5",
|
|
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/
|
|
40
|
-
"@flowview/
|
|
39
|
+
"@flowview/runtime": "^0.2.1",
|
|
40
|
+
"@flowview/vite": "^0.1.4"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^26.0.0",
|