@caryhu/codemine-forge 0.0.1-alpha.2 → 0.0.1-alpha.3

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.
@@ -24,6 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.createBrowserBundle = void 0;
27
+ const compiler_sfc_1 = require("@vue/compiler-sfc");
27
28
  const ts = __importStar(require("typescript"));
28
29
  const virtual_file_system_1 = require("../virtual-file-system");
29
30
  const diagnostics_1 = require("./diagnostics");
@@ -324,234 +325,53 @@ function transformPackageModule(importer, filePath, content) {
324
325
  return transformSuccess(transpileScript(importer, source));
325
326
  }
326
327
  function createVueSfcModule(sourcePath, source) {
327
- const scriptSetup = extractVueSfcBlock(source, "script", "setup") ?? "";
328
- const template = extractVueSfcBlock(source, "template") ?? "";
329
- const bindings = collectVueSetupBindings(scriptSetup);
330
- const renderExpression = createVueRenderExpression(template);
331
- const setupReturn = bindings.length === 0
332
- ? "{}"
333
- : `{ ${bindings.map((binding) => `${binding}: ${binding}`).join(", ")} }`;
328
+ const filename = sourcePath;
329
+ const id = `forge-vue-${hashText(sourcePath)}`;
330
+ const parseResult = (0, compiler_sfc_1.parse)(source, { filename });
331
+ if (parseResult.errors.length > 0) {
332
+ throw new Error(formatVueCompilerErrors(parseResult.errors));
333
+ }
334
+ const { descriptor } = parseResult;
335
+ const script = descriptor.script === null && descriptor.scriptSetup === null
336
+ ? undefined
337
+ : (0, compiler_sfc_1.compileScript)(descriptor, {
338
+ genDefaultAs: "__forgeVueDefault",
339
+ id,
340
+ });
341
+ const scriptContent = script?.content ?? "const __forgeVueDefault = {};";
342
+ const template = descriptor.template === null
343
+ ? undefined
344
+ : (0, compiler_sfc_1.compileTemplate)({
345
+ compilerOptions: {
346
+ bindingMetadata: script?.bindings ?? {},
347
+ },
348
+ filename,
349
+ id,
350
+ scoped: descriptor.styles.some((style) => style.scoped),
351
+ source: descriptor.template.content,
352
+ });
353
+ if (template?.errors !== undefined && template.errors.length > 0) {
354
+ throw new Error(formatVueCompilerErrors(template.errors));
355
+ }
356
+ const templateContent = template?.code ?? "function render() { return null; }";
334
357
  return [
335
- 'import { h as __forgeVueH } from "vue";',
336
- scriptSetup,
358
+ scriptContent,
359
+ "",
360
+ templateContent,
337
361
  "",
338
- "const __forgeVueComponent = {",
362
+ "const __forgeVueComponent = Object.assign(__forgeVueDefault, {",
339
363
  ` __file: ${JSON.stringify(sourcePath)},`,
340
- " setup() {",
341
- ` return ${setupReturn};`,
342
- " },",
343
- " render(__forgeVueCtx) {",
344
- ` return ${renderExpression};`,
345
- " },",
346
- "};",
364
+ " render,",
365
+ "});",
347
366
  "",
348
367
  "export default __forgeVueComponent;",
349
368
  "",
350
369
  ].join("\n");
351
370
  }
352
- function extractVueSfcBlock(source, blockName, requiredAttribute) {
353
- const pattern = new RegExp(`<${blockName}\\b([^>]*)>([\\s\\S]*?)<\\/${blockName}>`, "gi");
354
- for (const match of source.matchAll(pattern)) {
355
- const attributes = match[1] ?? "";
356
- if (requiredAttribute !== undefined &&
357
- !new RegExp(`\\b${requiredAttribute}\\b`, "i").test(attributes)) {
358
- continue;
359
- }
360
- return match[2].trim();
361
- }
362
- return undefined;
363
- }
364
- function collectVueSetupBindings(scriptSetup) {
365
- const bindings = new Set();
366
- for (const match of scriptSetup.matchAll(/\bimport\s+(type\s+)?([\s\S]*?)\s+from\s*["'][^"']+["']/g)) {
367
- if (match[1] !== undefined) {
368
- continue;
369
- }
370
- for (const binding of parseImportBindingNames(match[2])) {
371
- bindings.add(binding);
372
- }
373
- }
374
- const declarationPatterns = [
375
- /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)/g,
376
- /\bfunction\s+([A-Za-z_$][\w$]*)/g,
377
- /\bclass\s+([A-Za-z_$][\w$]*)/g,
378
- ];
379
- for (const pattern of declarationPatterns) {
380
- for (const match of scriptSetup.matchAll(pattern)) {
381
- bindings.add(match[1]);
382
- }
383
- }
384
- return Array.from(bindings).sort((left, right) => left.localeCompare(right));
385
- }
386
- function parseImportBindingNames(importClause) {
387
- const bindings = [];
388
- const trimmed = importClause.trim();
389
- if (trimmed.length === 0 || trimmed.startsWith("{")) {
390
- bindings.push(...parseNamedImportBindings(trimmed));
391
- return bindings;
392
- }
393
- const [defaultOrNamespace = "", ...rest] = trimmed.split(",");
394
- const defaultBinding = defaultOrNamespace.trim();
395
- if (defaultBinding.startsWith("* as ")) {
396
- bindings.push(defaultBinding.slice(5).trim());
397
- }
398
- else if (/^[A-Za-z_$][\w$]*$/.test(defaultBinding)) {
399
- bindings.push(defaultBinding);
400
- }
401
- bindings.push(...parseNamedImportBindings(rest.join(",").trim()));
402
- return bindings.filter((binding) => /^[A-Za-z_$][\w$]*$/.test(binding));
403
- }
404
- function parseNamedImportBindings(importClause) {
405
- const namedMatch = importClause.match(/\{([\s\S]*?)\}/);
406
- if (namedMatch === null) {
407
- return [];
408
- }
409
- return namedMatch[1]
410
- .split(",")
411
- .map((part) => part.trim())
412
- .filter((part) => part.length > 0 && !part.startsWith("type "))
413
- .map((part) => {
414
- const aliasMatch = part.match(/\bas\s+([A-Za-z_$][\w$]*)$/);
415
- return aliasMatch?.[1] ?? part;
416
- })
417
- .filter((binding) => /^[A-Za-z_$][\w$]*$/.test(binding));
418
- }
419
- function createVueRenderExpression(template) {
420
- const nodes = parseVueTemplate(template);
421
- const renderedChildren = nodes.map(createVueTemplateNodeExpression);
422
- if (renderedChildren.length === 0) {
423
- return "null";
424
- }
425
- return renderedChildren.length === 1
426
- ? renderedChildren[0]
427
- : `__forgeVueH("div", null, [${renderedChildren.join(", ")}])`;
428
- }
429
- function parseVueTemplate(template) {
430
- const root = {
431
- attributes: [],
432
- children: [],
433
- tagName: "__root__",
434
- };
435
- const stack = [root];
436
- const tokenPattern = /<!--[\s\S]*?-->|<\/?[^>]+>|{{[\s\S]*?}}|[^<{]+|[<{]/g;
437
- for (const match of template.matchAll(tokenPattern)) {
438
- const token = match[0];
439
- const current = stack[stack.length - 1];
440
- if (token.startsWith("<!--")) {
441
- continue;
442
- }
443
- if (token.startsWith("</")) {
444
- if (stack.length > 1) {
445
- stack.pop();
446
- }
447
- continue;
448
- }
449
- if (token.startsWith("<")) {
450
- const element = parseVueTemplateElementToken(token);
451
- if (element === undefined) {
452
- continue;
453
- }
454
- current.children.push({
455
- attributes: element.attributes,
456
- children: element.children,
457
- kind: "element",
458
- tagName: element.tagName,
459
- });
460
- if (!isSelfClosingVueTemplateToken(token)) {
461
- stack.push(element);
462
- }
463
- continue;
464
- }
465
- if (token.startsWith("{{")) {
466
- current.children.push({
467
- expression: token.slice(2, -2).trim(),
468
- kind: "interpolation",
469
- });
470
- continue;
471
- }
472
- if (token.trim().length > 0) {
473
- current.children.push({
474
- kind: "text",
475
- value: token.replace(/\s+/g, " "),
476
- });
477
- }
478
- }
479
- return root.children;
480
- }
481
- function parseVueTemplateElementToken(token) {
482
- const content = token
483
- .slice(1, isSelfClosingVueTemplateToken(token) ? -2 : -1)
484
- .trim();
485
- const tagMatch = content.match(/^([A-Za-z][\w.-]*)/);
486
- if (tagMatch === null) {
487
- return undefined;
488
- }
489
- return {
490
- attributes: parseVueTemplateAttributes(content.slice(tagMatch[0].length)),
491
- children: [],
492
- tagName: tagMatch[1],
493
- };
494
- }
495
- function parseVueTemplateAttributes(source) {
496
- const attributes = [];
497
- const pattern = /([:@A-Za-z_][\w:.-]*)(?:\s*=\s*("[^"]*"|'[^']*'|[^\s"'>/]+))?/g;
498
- for (const match of source.matchAll(pattern)) {
499
- const name = match[1];
500
- if (name.startsWith(":") ||
501
- name.startsWith("@") ||
502
- name.startsWith("v-")) {
503
- continue;
504
- }
505
- const rawValue = match[2];
506
- const value = rawValue === undefined
507
- ? true
508
- : rawValue.replace(/^["']|["']$/g, "");
509
- attributes.push({ name, value });
510
- }
511
- return attributes;
512
- }
513
- function createVueTemplateNodeExpression(node) {
514
- switch (node.kind) {
515
- case "element":
516
- return createVueElementExpression(node);
517
- case "interpolation":
518
- return createVueInterpolationExpression(node.expression);
519
- case "text":
520
- return JSON.stringify(node.value);
521
- }
522
- }
523
- function createVueElementExpression(node) {
524
- const tagExpression = /^[A-Z]/.test(node.tagName)
525
- ? `(__forgeVueCtx[${JSON.stringify(node.tagName)}] ?? ${JSON.stringify(node.tagName)})`
526
- : JSON.stringify(node.tagName);
527
- const propsExpression = createVuePropsExpression(node.attributes);
528
- const children = node.children.map(createVueTemplateNodeExpression);
529
- const childrenExpression = children.length === 0
530
- ? "null"
531
- : children.length === 1
532
- ? children[0]
533
- : `[${children.join(", ")}]`;
534
- return `__forgeVueH(${tagExpression}, ${propsExpression}, ${childrenExpression})`;
535
- }
536
- function createVuePropsExpression(attributes) {
537
- if (attributes.length === 0) {
538
- return "null";
539
- }
540
- return `{ ${attributes
541
- .map((attribute) => {
542
- const value = attribute.value === true ? "true" : JSON.stringify(attribute.value);
543
- return `${JSON.stringify(attribute.name)}: ${value}`;
544
- })
545
- .join(", ")} }`;
546
- }
547
- function createVueInterpolationExpression(expression) {
548
- if (/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(expression)) {
549
- return `String(__forgeVueCtx.${expression} ?? "")`;
550
- }
551
- return "String(\"\")";
552
- }
553
- function isSelfClosingVueTemplateToken(token) {
554
- return /\/\s*>$/.test(token);
371
+ function formatVueCompilerErrors(errors) {
372
+ return errors
373
+ .map((error) => (error instanceof Error ? error.message : String(error)))
374
+ .join("\n");
555
375
  }
556
376
  function createWorkspaceCssModule(sourcePath, css) {
557
377
  return isCssModulePath(sourcePath)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caryhu/codemine-forge",
3
- "version": "0.0.1-alpha.2",
3
+ "version": "0.0.1-alpha.3",
4
4
  "description": "Browser-side runtime layer for Codemine demos.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -18,6 +18,7 @@
18
18
  "access": "public"
19
19
  },
20
20
  "dependencies": {
21
+ "@vue/compiler-sfc": "3.4.0",
21
22
  "esbuild-wasm": "^0.28.1",
22
23
  "typescript": "4.9.5"
23
24
  },