@contentful/experience-design-system-cli 2.11.4-dev-build-8f1adf3.0 → 2.11.4-dev-build-a9b4d34.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.11.4-dev-build-8f1adf3.0",
3
+ "version": "2.11.4-dev-build-a9b4d34.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -3,7 +3,7 @@ import { readFile } from 'node:fs/promises';
3
3
  import { existsSync, statSync } from 'node:fs';
4
4
  import os from 'node:os';
5
5
  import { parse as parseSvelte } from 'svelte/compiler';
6
- import { Project, Node } from 'ts-morph';
6
+ import { Project, Node, ScriptTarget, ModuleKind, ts } from 'ts-morph';
7
7
  import { computeExtractionScore, deriveNeedsReview } from './scoring.js';
8
8
  const SVELTE_EXTRACT_CONCURRENCY = Number(process.env['EDS_EXTRACT_CONCURRENCY'] ?? 0) || os.cpus().length;
9
9
  export async function extractSvelteComponents(filePaths, onProgress) {
@@ -226,7 +226,7 @@ async function extractPropsFromCall(ctx) {
226
226
  if (idType === 'Identifier') {
227
227
  // const props: Props = $props(); — no destructure, no defaults, no per-name binding.
228
228
  if (typeMembers) {
229
- return extractFromTypeMembersOnly(typeMembers, ctx.snippetLocals, warnings);
229
+ return extractFromTypeMembersOnly(typeMembers);
230
230
  }
231
231
  warnings.push(`${ctx.filePath}: $props() called without destructuring; cannot extract individual props`);
232
232
  return { props: [], snippetNames: new Set(), snippetSlots: [], warnings };
@@ -290,7 +290,13 @@ async function resolveViaTypeChecker(annotation, instance, moduleScript, filePat
290
290
  const instanceText = sliceScriptContent(source, instance);
291
291
  const synthetic = [moduleText, instanceText, `type __SveltePropsT__ = ${annotationText};`].filter(Boolean).join('\n');
292
292
  const project = new Project({
293
- compilerOptions: { strict: false, target: 99, module: 99, allowJs: true, jsx: 1 },
293
+ compilerOptions: {
294
+ strict: false,
295
+ target: ScriptTarget.ESNext,
296
+ module: ModuleKind.ESNext,
297
+ allowJs: true,
298
+ jsx: ts.JsxEmit.Preserve,
299
+ },
294
300
  useInMemoryFileSystem: false,
295
301
  skipAddingFilesFromTsConfig: true,
296
302
  });
@@ -629,7 +635,7 @@ function extractFromDestructure(propsCall, ctx, typeMembers, warnings) {
629
635
  warnings,
630
636
  };
631
637
  }
632
- function extractFromTypeMembersOnly(typeMembers, _snippetLocals, _warnings) {
638
+ function extractFromTypeMembersOnly(typeMembers) {
633
639
  const props = [];
634
640
  const snippetNames = new Set();
635
641
  const snippetSlots = [];
@@ -759,13 +765,22 @@ function resolveLocalScriptModule(importingFilePath, specifier) {
759
765
  }
760
766
  function readMembersFromExternalFile(filePath, exportName) {
761
767
  const project = new Project({
762
- compilerOptions: { strict: false, target: 99, module: 99, allowJs: true },
768
+ compilerOptions: {
769
+ strict: false,
770
+ target: ScriptTarget.ESNext,
771
+ module: ModuleKind.ESNext,
772
+ allowJs: true,
773
+ },
763
774
  useInMemoryFileSystem: false,
764
775
  skipAddingFilesFromTsConfig: true,
765
776
  });
766
777
  const sf = project.addSourceFileAtPathIfExists(filePath);
767
778
  if (!sf)
768
779
  return null;
780
+ // Collect Snippet locals from the resolved file's own imports so that
781
+ // aliased imports (`import { Snippet as LocalSnippet } from 'svelte'`) are
782
+ // honored. Mirrors collectSnippetImportLocals() but adapted to ts-morph.
783
+ const snippetLocals = collectSnippetLocalsFromSourceFile(sf);
769
784
  // Use getExportedDeclarations() so re-export chains (`export { ... } from './x'`,
770
785
  // `export * from './x'`, named or namespace) resolve transparently. ts-morph
771
786
  // follows them recursively and returns the underlying declaration.
@@ -775,18 +790,39 @@ function readMembersFromExternalFile(filePath, exportName) {
775
790
  return null;
776
791
  for (const decl of decls) {
777
792
  if (Node.isInterfaceDeclaration(decl)) {
778
- return readInterfaceMembers(decl);
793
+ // The declaration may live in a different source file than `sf` if the
794
+ // export chain walked across files; pull snippet locals from that file
795
+ // so aliased imports are recognized.
796
+ const declSf = decl.getSourceFile();
797
+ const declLocals = declSf === sf ? snippetLocals : collectSnippetLocalsFromSourceFile(declSf);
798
+ return readInterfaceMembers(decl, declLocals);
779
799
  }
780
800
  if (Node.isTypeAliasDeclaration(decl)) {
781
801
  const typeNode = decl.getTypeNode();
782
802
  if (typeNode && Node.isTypeLiteral(typeNode)) {
783
- return readTypeLiteralMembers(typeNode);
803
+ const declSf = decl.getSourceFile();
804
+ const declLocals = declSf === sf ? snippetLocals : collectSnippetLocalsFromSourceFile(declSf);
805
+ return readTypeLiteralMembers(typeNode, declLocals);
784
806
  }
785
807
  }
786
808
  }
787
809
  return null;
788
810
  }
789
- function readInterfaceMembers(iface) {
811
+ function collectSnippetLocalsFromSourceFile(sf) {
812
+ const locals = new Set();
813
+ for (const importDecl of sf.getImportDeclarations()) {
814
+ if (importDecl.getModuleSpecifierValue() !== 'svelte')
815
+ continue;
816
+ for (const named of importDecl.getNamedImports()) {
817
+ if (named.getName() === 'Snippet') {
818
+ const aliasNode = named.getAliasNode();
819
+ locals.add(aliasNode ? aliasNode.getText() : named.getName());
820
+ }
821
+ }
822
+ }
823
+ return locals;
824
+ }
825
+ function readInterfaceMembers(iface, snippetLocals) {
790
826
  return iface.getProperties().map((prop) => {
791
827
  const typeNode = prop.getTypeNode();
792
828
  const typeText = typeNode ? typeNode.getText() : prop.getType().getText(prop);
@@ -797,7 +833,7 @@ function readInterfaceMembers(iface) {
797
833
  name: prop.getName(),
798
834
  optional: prop.hasQuestionToken(),
799
835
  typeText,
800
- isSnippet: typeText === 'Snippet' || /^Snippet</.test(typeText),
836
+ isSnippet: isSnippetTypeText(typeText, snippetLocals),
801
837
  ...(allowed ? { allowedValues: allowed } : {}),
802
838
  ...(description ? { description } : {}),
803
839
  line: prop.getStartLineNumber(),
@@ -805,7 +841,7 @@ function readInterfaceMembers(iface) {
805
841
  };
806
842
  });
807
843
  }
808
- function readTypeLiteralMembers(typeNode) {
844
+ function readTypeLiteralMembers(typeNode, snippetLocals) {
809
845
  return typeNode.getMembers().flatMap((m) => {
810
846
  if (!Node.isPropertySignature(m))
811
847
  return [];
@@ -819,7 +855,7 @@ function readTypeLiteralMembers(typeNode) {
819
855
  name: m.getName(),
820
856
  optional: m.hasQuestionToken(),
821
857
  typeText,
822
- isSnippet: typeText === 'Snippet' || /^Snippet</.test(typeText),
858
+ isSnippet: isSnippetTypeText(typeText, snippetLocals),
823
859
  ...(allowed ? { allowedValues: allowed } : {}),
824
860
  ...(description ? { description } : {}),
825
861
  line: m.getStartLineNumber(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.11.4-dev-build-8f1adf3.0",
3
+ "version": "2.11.4-dev-build-a9b4d34.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,7 +37,7 @@
37
37
  "svelte": "^5.56.4",
38
38
  "ts-morph": "^27.0.2",
39
39
  "typescript": "^5.9.3",
40
- "@contentful/experience-design-system-types": "2.11.4-dev-build-8f1adf3.0"
40
+ "@contentful/experience-design-system-types": "2.11.4-dev-build-a9b4d34.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@tsconfig/node24": "^24.0.3",