@contentful/experience-design-system-extraction 2.34.5-dev-build-4a4b9e84.0 → 2.34.5-dev-build-9dff4380.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.
Files changed (88) hide show
  1. package/dist/package.json +1 -1
  2. package/dist/src/extract/{adapters/astro/extractor.d.ts → astro.d.ts} +1 -1
  3. package/dist/src/extract/{adapters/astro/extractor.js → astro.js} +3 -4
  4. package/dist/src/extract/{adapters/support/file-processing/file-workers.d.ts → file-extraction-workers.d.ts} +13 -1
  5. package/dist/src/extract/{adapters/support/file-processing/file-workers.js → file-extraction-workers.js} +19 -0
  6. package/dist/src/extract/{policies/quality/authorability.d.ts → non-authorable-filter.d.ts} +1 -1
  7. package/dist/src/extract/pipeline.d.ts +7 -0
  8. package/dist/src/extract/{services/component-deduplicator.js → pipeline.js} +137 -13
  9. package/dist/src/extract/{adapters/react/extractor.d.ts → react.d.ts} +1 -1
  10. package/dist/src/extract/{adapters/react/extractor.js → react.js} +353 -9
  11. package/dist/src/extract/scoring.d.ts +12 -0
  12. package/dist/src/extract/{policies/quality/scoring.js → scoring.js} +0 -1
  13. package/dist/src/extract/{policies/quality/source-inspection.d.ts → source-inspection.d.ts} +1 -1
  14. package/dist/src/extract/{policies/quality/source-inspection.js → source-inspection.js} +1 -1
  15. package/dist/src/extract/{adapters/support/resolution/source-location.d.ts → source-line-metadata.d.ts} +1 -1
  16. package/dist/src/extract/{adapters/stencil/extractor.d.ts → stencil.d.ts} +1 -1
  17. package/dist/src/extract/{adapters/stencil/extractor.js → stencil.js} +2 -3
  18. package/dist/src/extract/{evidence/structural-slot-evidence.d.ts → structural-slot-evidence.d.ts} +1 -1
  19. package/dist/src/extract/{evidence/structural-slot-evidence.js → structural-slot-evidence.js} +2 -2
  20. package/dist/src/extract/{adapters/svelte/extractor.d.ts → svelte.d.ts} +1 -2
  21. package/dist/src/extract/{adapters/svelte/extractor.js → svelte.js} +91 -7
  22. package/dist/src/extract/{adapters/support/tsx-shared.d.ts → tsx-shared.d.ts} +1 -1
  23. package/dist/src/extract/{policies/quality/validation.d.ts → validate.d.ts} +1 -1
  24. package/dist/src/extract/{adapters/vue-tsx/extractor.d.ts → vue-tsx.d.ts} +1 -1
  25. package/dist/src/extract/{adapters/vue-tsx/extractor.js → vue-tsx.js} +1 -1
  26. package/dist/src/extract/{adapters/vue/extractor.d.ts → vue.d.ts} +1 -1
  27. package/dist/src/extract/{adapters/vue/extractor.js → vue.js} +3 -4
  28. package/dist/src/extract/{adapters/web-components/extractor.d.ts → web-components.d.ts} +1 -1
  29. package/dist/src/extract/{adapters/web-components/extractor.js → web-components.js} +213 -4
  30. package/dist/src/index.d.ts +21 -25
  31. package/dist/src/index.js +17 -18
  32. package/dist/src/{extract/services/classification-service.d.ts → pre-classify.d.ts} +1 -1
  33. package/dist/src/{extract/model/component.d.ts → types.d.ts} +20 -0
  34. package/package.json +1 -1
  35. package/dist/src/extract/adapters/react/function-resolution.d.ts +0 -4
  36. package/dist/src/extract/adapters/react/function-resolution.js +0 -131
  37. package/dist/src/extract/adapters/react/prop-dataflow.d.ts +0 -14
  38. package/dist/src/extract/adapters/react/prop-dataflow.js +0 -220
  39. package/dist/src/extract/adapters/support/file-processing/project-source-files.d.ts +0 -5
  40. package/dist/src/extract/adapters/support/file-processing/project-source-files.js +0 -13
  41. package/dist/src/extract/adapters/support/file-processing/result-normalizer.d.ts +0 -6
  42. package/dist/src/extract/adapters/support/file-processing/result-normalizer.js +0 -6
  43. package/dist/src/extract/adapters/svelte/ast.d.ts +0 -12
  44. package/dist/src/extract/adapters/svelte/ast.js +0 -1
  45. package/dist/src/extract/adapters/svelte/identity.d.ts +0 -1
  46. package/dist/src/extract/adapters/svelte/identity.js +0 -26
  47. package/dist/src/extract/adapters/svelte/slots.d.ts +0 -7
  48. package/dist/src/extract/adapters/svelte/slots.js +0 -63
  49. package/dist/src/extract/adapters/web-components/properties.d.ts +0 -9
  50. package/dist/src/extract/adapters/web-components/properties.js +0 -212
  51. package/dist/src/extract/controller/extract-controller.d.ts +0 -10
  52. package/dist/src/extract/controller/extract-controller.js +0 -56
  53. package/dist/src/extract/model/contract.d.ts +0 -16
  54. package/dist/src/extract/model/contract.js +0 -1
  55. package/dist/src/extract/model/options.d.ts +0 -15
  56. package/dist/src/extract/model/options.js +0 -1
  57. package/dist/src/extract/model/scoring.d.ts +0 -9
  58. package/dist/src/extract/model/scoring.js +0 -1
  59. package/dist/src/extract/policies/quality/scoring.d.ts +0 -5
  60. package/dist/src/extract/services/component-deduplicator.d.ts +0 -2
  61. package/dist/src/extract/services/extraction-pipeline.d.ts +0 -3
  62. package/dist/src/extract/services/extraction-pipeline.js +0 -43
  63. package/dist/src/extract/services/extraction-runner.d.ts +0 -4
  64. package/dist/src/extract/services/extraction-runner.js +0 -21
  65. package/dist/src/extract/services/extraction-service.d.ts +0 -13
  66. package/dist/src/extract/services/extraction-service.js +0 -17
  67. package/dist/src/extract/services/extractor-registry.d.ts +0 -8
  68. package/dist/src/extract/services/extractor-registry.js +0 -68
  69. package/dist/src/extract/services/ports/component-extractor.d.ts +0 -7
  70. package/dist/src/extract/services/ports/component-extractor.js +0 -1
  71. package/dist/src/extract/services/quality-service.d.ts +0 -4
  72. package/dist/src/extract/services/quality-service.js +0 -61
  73. /package/dist/src/extract/{policies/quality/authorability.js → non-authorable-filter.js} +0 -0
  74. /package/dist/src/extract/{evidence/source-evidence.d.ts → parse-imported-names.d.ts} +0 -0
  75. /package/dist/src/extract/{evidence/source-evidence.js → parse-imported-names.js} +0 -0
  76. /package/dist/src/extract/{adapters/support/resolution/local-module.d.ts → resolve-local-module.d.ts} +0 -0
  77. /package/dist/src/extract/{adapters/support/resolution/local-module.js → resolve-local-module.js} +0 -0
  78. /package/dist/src/extract/{adapters/support/resolution/type-property.d.ts → resolve-type-property.d.ts} +0 -0
  79. /package/dist/src/extract/{adapters/support/resolution/type-property.js → resolve-type-property.js} +0 -0
  80. /package/dist/src/extract/{evidence/allowed-components.d.ts → slot-allowed-components.d.ts} +0 -0
  81. /package/dist/src/extract/{evidence/allowed-components.js → slot-allowed-components.js} +0 -0
  82. /package/dist/src/extract/{evidence/slot-evidence.d.ts → slot-detection.d.ts} +0 -0
  83. /package/dist/src/extract/{evidence/slot-evidence.js → slot-detection.js} +0 -0
  84. /package/dist/src/extract/{adapters/support/resolution/source-location.js → source-line-metadata.js} +0 -0
  85. /package/dist/src/extract/{adapters/support/tsx-shared.js → tsx-shared.js} +0 -0
  86. /package/dist/src/extract/{policies/quality/validation.js → validate.js} +0 -0
  87. /package/dist/src/{extract/services/classification-service.js → pre-classify.js} +0 -0
  88. /package/dist/src/{extract/model/component.js → types.js} +0 -0
@@ -1,9 +1,7 @@
1
1
  import { basename, dirname, join, resolve } from 'node:path';
2
2
  import { Project, Node, SyntaxKind } from 'ts-morph';
3
- import { createSortedExtractionResult } from '../support/file-processing/result-normalizer.js';
4
- import { extractProjectSourceFiles } from '../support/file-processing/project-source-files.js';
5
- import { kebabToPascal } from '../support/tsx-shared.js';
6
- import { extractAccessorProperties, extractClassProperties, extractJsDocAttributeProps, extractObservedAttributes, hasShoelaceRuntimeBookkeepingField, mergePropLists, mergeProps, } from './properties.js';
3
+ import { createSortedExtractionResult, extractProjectSourceFiles } from './file-extraction-workers.js';
4
+ import { kebabToPascal } from './tsx-shared.js';
7
5
  function normalizeComponentName(input) {
8
6
  return input.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
9
7
  }
@@ -13,6 +11,9 @@ function camelToKebab(input) {
13
11
  .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
14
12
  .toLowerCase();
15
13
  }
14
+ function kebabToCamel(input) {
15
+ return input.replace(/-([a-z0-9])/gi, (_, char) => char.toUpperCase());
16
+ }
16
17
  function resolveDecoratorInterpolation(node) {
17
18
  if (Node.isIdentifier(node)) {
18
19
  const definitions = node.getDefinitions();
@@ -261,6 +262,214 @@ function extractJsDocSlots(classDecl) {
261
262
  }
262
263
  return mergeSlotLists(slots);
263
264
  }
265
+ function extractObservedAttributes(classDecl) {
266
+ const props = [];
267
+ const getter = classDecl.getGetAccessor('observedAttributes');
268
+ if (!getter || !getter.isStatic())
269
+ return props;
270
+ const body = getter.getBody();
271
+ if (!body)
272
+ return props;
273
+ // Find the return statement containing an array literal
274
+ body.forEachDescendant((node) => {
275
+ if (!Node.isReturnStatement(node))
276
+ return;
277
+ const expression = node.getExpression();
278
+ if (!expression || !Node.isArrayLiteralExpression(expression))
279
+ return;
280
+ for (const element of expression.getElements()) {
281
+ if (Node.isStringLiteral(element)) {
282
+ const attrName = element.getLiteralValue();
283
+ props.push({
284
+ name: attrName,
285
+ type: 'string',
286
+ required: false,
287
+ });
288
+ }
289
+ }
290
+ });
291
+ return props;
292
+ }
293
+ function hasInternalJsDocTag(member) {
294
+ return member.getJsDocs().some((doc) => doc.getTags().some((tag) => tag.getTagName() === 'internal'));
295
+ }
296
+ const NON_PUBLIC_LIT_DECORATORS = new Set(['consume', 'provide', 'query', 'queryAsync', 'state']);
297
+ const INTERNAL_RUNTIME_FIELD_NAMES = new Set(['dir', 'initialReflectedProperties', 'lang']);
298
+ function isNonPublicLitMember(member) {
299
+ return member.getDecorators().some((decorator) => NON_PUBLIC_LIT_DECORATORS.has(decorator.getName()));
300
+ }
301
+ function hasShoelaceRuntimeBookkeepingField(classDecl) {
302
+ return classDecl.getProperties().some((property) => property.getName() === 'initialReflectedProperties');
303
+ }
304
+ function isInternalRuntimeField(name, applyRuntimeFieldDenylist) {
305
+ return applyRuntimeFieldDenylist && INTERNAL_RUNTIME_FIELD_NAMES.has(name);
306
+ }
307
+ function getExplicitLitPropertyAttributeName(property) {
308
+ const decorator = property.getDecorators().find((candidate) => candidate.getName() === 'property');
309
+ const firstArg = decorator?.getArguments()[0];
310
+ if (!firstArg || !Node.isObjectLiteralExpression(firstArg)) {
311
+ return null;
312
+ }
313
+ const attributeProp = firstArg.getProperty('attribute');
314
+ if (!attributeProp || !Node.isPropertyAssignment(attributeProp)) {
315
+ return null;
316
+ }
317
+ const initializer = attributeProp.getInitializer();
318
+ if (!initializer || !Node.isStringLiteral(initializer)) {
319
+ return null;
320
+ }
321
+ return initializer.getLiteralValue();
322
+ }
323
+ function extractClassProperties(classDecl, applyRuntimeFieldDenylist = false) {
324
+ const props = [];
325
+ for (const property of classDecl.getProperties()) {
326
+ if (property.isStatic())
327
+ continue;
328
+ if (hasInternalJsDocTag(property))
329
+ continue;
330
+ if (isNonPublicLitMember(property))
331
+ continue;
332
+ const name = property.getName();
333
+ if (name.startsWith('#') || isInternalRuntimeField(name, applyRuntimeFieldDenylist))
334
+ continue;
335
+ const scope = property.getScope();
336
+ if (scope === 'private' || scope === 'protected')
337
+ continue;
338
+ const initializer = property.getInitializer();
339
+ const hasDecorators = property.getDecorators().length > 0;
340
+ // Skip undecorated arrow-function properties (internal event handlers / callbacks)
341
+ if (!hasDecorators && initializer && Node.isArrowFunction(initializer)) {
342
+ continue;
343
+ }
344
+ // Skip properties initialized with this.attachInternals() (ElementInternals)
345
+ if (initializer &&
346
+ Node.isCallExpression(initializer) &&
347
+ initializer.getExpression().getText() === 'this.attachInternals') {
348
+ continue;
349
+ }
350
+ const typeNode = property.getTypeNode();
351
+ const type = typeNode ? typeNode.getText() : 'any';
352
+ const publicName = name.startsWith('_') && hasDecorators ? getExplicitLitPropertyAttributeName(property) : null;
353
+ let defaultValue;
354
+ if (initializer) {
355
+ if (Node.isStringLiteral(initializer)) {
356
+ defaultValue = initializer.getLiteralValue();
357
+ }
358
+ else {
359
+ defaultValue = initializer.getText();
360
+ }
361
+ }
362
+ props.push({
363
+ name: publicName ? kebabToCamel(publicName) : name,
364
+ type,
365
+ required: false,
366
+ ...(defaultValue !== undefined && { defaultValue }),
367
+ sourceStartLine: property.getStartLineNumber(),
368
+ sourceEndLine: property.getEndLineNumber(),
369
+ });
370
+ }
371
+ return props;
372
+ }
373
+ function extractAccessorProperties(classDecl, applyRuntimeFieldDenylist = false) {
374
+ const props = [];
375
+ const accessors = new Map();
376
+ for (const getter of classDecl.getGetAccessors()) {
377
+ if (getter.isStatic())
378
+ continue;
379
+ if (hasInternalJsDocTag(getter))
380
+ continue;
381
+ if (isNonPublicLitMember(getter))
382
+ continue;
383
+ const name = getter.getName();
384
+ if (name === 'observedAttributes' ||
385
+ name === 'template' ||
386
+ name.startsWith('#') ||
387
+ isInternalRuntimeField(name, applyRuntimeFieldDenylist))
388
+ continue;
389
+ const scope = getter.getScope();
390
+ if (scope === 'private' || scope === 'protected')
391
+ continue;
392
+ const entry = accessors.get(name) ?? {};
393
+ entry.getter = getter;
394
+ accessors.set(name, entry);
395
+ }
396
+ for (const setter of classDecl.getSetAccessors()) {
397
+ if (setter.isStatic())
398
+ continue;
399
+ if (hasInternalJsDocTag(setter))
400
+ continue;
401
+ if (isNonPublicLitMember(setter))
402
+ continue;
403
+ const name = setter.getName();
404
+ if (name === 'observedAttributes' ||
405
+ name === 'template' ||
406
+ name.startsWith('#') ||
407
+ isInternalRuntimeField(name, applyRuntimeFieldDenylist))
408
+ continue;
409
+ const scope = setter.getScope();
410
+ if (scope === 'private' || scope === 'protected')
411
+ continue;
412
+ const entry = accessors.get(name) ?? {};
413
+ entry.setter = setter;
414
+ accessors.set(name, entry);
415
+ }
416
+ for (const [name, { getter, setter }] of accessors) {
417
+ const hasPropertyDecorator = getter?.getDecorators().some((decorator) => decorator.getName() === 'property') ||
418
+ setter?.getDecorators().some((decorator) => decorator.getName() === 'property');
419
+ if (!hasPropertyDecorator && !(getter && setter))
420
+ continue;
421
+ const type = getter?.getReturnTypeNode()?.getText() ?? setter?.getParameters()[0]?.getTypeNode()?.getText() ?? 'any';
422
+ const accessorNode = getter ?? setter;
423
+ props.push({
424
+ name,
425
+ type,
426
+ required: false,
427
+ ...(accessorNode
428
+ ? {
429
+ sourceStartLine: accessorNode.getStartLineNumber(),
430
+ sourceEndLine: accessorNode.getEndLineNumber(),
431
+ }
432
+ : {}),
433
+ });
434
+ }
435
+ return props;
436
+ }
437
+ function extractJsDocAttributeProps(classDecl) {
438
+ const props = [];
439
+ for (const doc of classDecl.getJsDocs()) {
440
+ for (const tag of doc.getTags()) {
441
+ if (tag.getTagName() !== 'attribute')
442
+ continue;
443
+ const tagComment = tag.getCommentText();
444
+ const normalizedComment = Array.isArray(tagComment) ? tagComment.join(' ') : tagComment;
445
+ const match = normalizedComment?.match(/(?:\{([^}]+)\}\s+)?([^\s]+)(?:\s*-\s*([\s\S]*))?/);
446
+ if (!match)
447
+ continue;
448
+ const [, type, name, description] = match;
449
+ if (!name || name.startsWith('#'))
450
+ continue;
451
+ props.push({
452
+ name,
453
+ type: type?.trim() || 'any',
454
+ required: false,
455
+ ...(description ? { description: description.replace(/\s+/g, ' ').trim() } : {}),
456
+ });
457
+ }
458
+ }
459
+ return props;
460
+ }
461
+ function mergePropLists(...propLists) {
462
+ const merged = new Map();
463
+ for (const propList of propLists) {
464
+ for (const prop of propList) {
465
+ merged.set(prop.name, prop);
466
+ }
467
+ }
468
+ return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
469
+ }
470
+ function mergeProps(observed, classProps) {
471
+ return mergePropLists(observed, classProps);
472
+ }
264
473
  function collectHtmlTaggedTemplates(root) {
265
474
  const templates = [];
266
475
  root.forEachDescendant((node) => {
@@ -1,25 +1,21 @@
1
- export type { RawComponentDefinition, RawPropDefinition, RawSlotDefinition, ComponentExtractionResult, ExtractionExclusion, ExtractorProgress, ExtractionValidationIssue, ExtractionValidationIssueCode, } from './extract/model/component.js';
2
- export { stripScoringFields } from './extract/model/component.js';
3
- export type { ExtractorOptions } from './extract/model/options.js';
4
- export type { ComponentExtractor } from './extract/services/ports/component-extractor.js';
5
- export { extractComponents } from './extract/services/extraction-pipeline.js';
6
- export { extractEndpoint } from './extract/controller/extract-controller.js';
7
- export type { ExtractionEndpointProgress, ExtractionEndpointRequest, ExtractionEndpointResponse, } from './extract/model/contract.js';
8
- export { extractReactComponents } from './extract/adapters/react/extractor.js';
9
- export { extractVueComponents } from './extract/adapters/vue/extractor.js';
10
- export { extractVueTsxComponents } from './extract/adapters/vue-tsx/extractor.js';
11
- export { extractStencilComponents } from './extract/adapters/stencil/extractor.js';
12
- export { extractAstroComponents } from './extract/adapters/astro/extractor.js';
13
- export { extractWebComponentDefinitions } from './extract/adapters/web-components/extractor.js';
14
- export { extractSvelteComponents } from './extract/adapters/svelte/extractor.js';
15
- export { extractAllowedComponentsFromTypeText, extractAllowedComponentsFromJsdoc, } from './extract/evidence/allowed-components.js';
16
- export { isNonAuthorableComponent } from './extract/policies/quality/authorability.js';
17
- export { computeExtractionScore, deriveNeedsReview } from './extract/policies/quality/scoring.js';
18
- export type { ExtractionScore, ExtractionScoreOptions, ExtractionConfidence } from './extract/model/scoring.js';
19
- export { inspectComponentSource, describeReviewReasons, describeReviewReason, isDataWrapperReviewReason, HIGH_CONFIDENCE_DATA_FETCH_WRAPPER_REASON, POSSIBLE_DATA_FETCH_WRAPPER_REASON, ZERO_SURFACE_RENDERED_UI_REASON, } from './extract/policies/quality/source-inspection.js';
20
- export type { ComponentSourceInspection } from './extract/policies/quality/source-inspection.js';
21
- export { validateExtractedComponents, shouldExcludeDueToValidation, formatExclusionWarning, formatExcludedComponentLines, } from './extract/policies/quality/validation.js';
22
- export { parseImportedNames } from './extract/evidence/source-evidence.js';
23
- export { CONTENT_NAME_EXCEPTIONS, isReactNodeType, isArrayReactNodeType, shouldBeSlot, } from './extract/evidence/slot-evidence.js';
24
- export { preClassifyProp, preClassifyComponent } from './extract/services/classification-service.js';
25
- export type { PreClassification } from './extract/services/classification-service.js';
1
+ export type { RawComponentDefinition, RawPropDefinition, RawSlotDefinition, ComponentExtractionResult, ExtractionExclusion, ExtractorProgress, ExtractorOptions, ComponentExtractor, ExtractionValidationIssue, ExtractionValidationIssueCode, } from './types.js';
2
+ export { stripScoringFields } from './types.js';
3
+ export { extractComponents } from './extract/pipeline.js';
4
+ export { extractReactComponents } from './extract/react.js';
5
+ export { extractVueComponents } from './extract/vue.js';
6
+ export { extractVueTsxComponents } from './extract/vue-tsx.js';
7
+ export { extractStencilComponents } from './extract/stencil.js';
8
+ export { extractAstroComponents } from './extract/astro.js';
9
+ export { extractWebComponentDefinitions } from './extract/web-components.js';
10
+ export { extractSvelteComponents } from './extract/svelte.js';
11
+ export { extractAllowedComponentsFromTypeText, extractAllowedComponentsFromJsdoc, } from './extract/slot-allowed-components.js';
12
+ export { isNonAuthorableComponent } from './extract/non-authorable-filter.js';
13
+ export { computeExtractionScore, deriveNeedsReview } from './extract/scoring.js';
14
+ export type { ExtractionScore, ExtractionScoreOptions, ExtractionConfidence } from './extract/scoring.js';
15
+ export { inspectComponentSource, describeReviewReasons, describeReviewReason, isDataWrapperReviewReason, HIGH_CONFIDENCE_DATA_FETCH_WRAPPER_REASON, POSSIBLE_DATA_FETCH_WRAPPER_REASON, ZERO_SURFACE_RENDERED_UI_REASON, } from './extract/source-inspection.js';
16
+ export type { ComponentSourceInspection } from './extract/source-inspection.js';
17
+ export { validateExtractedComponents, shouldExcludeDueToValidation, formatExclusionWarning, formatExcludedComponentLines, } from './extract/validate.js';
18
+ export { parseImportedNames } from './extract/parse-imported-names.js';
19
+ export { CONTENT_NAME_EXCEPTIONS, isReactNodeType, isArrayReactNodeType, shouldBeSlot, } from './extract/slot-detection.js';
20
+ export { preClassifyProp, preClassifyComponent } from './pre-classify.js';
21
+ export type { PreClassification } from './pre-classify.js';
package/dist/src/index.js CHANGED
@@ -1,24 +1,23 @@
1
- export { stripScoringFields } from './extract/model/component.js';
1
+ export { stripScoringFields } from './types.js';
2
2
  // Core extraction pipeline
3
- export { extractComponents } from './extract/services/extraction-pipeline.js';
4
- export { extractEndpoint } from './extract/controller/extract-controller.js';
3
+ export { extractComponents } from './extract/pipeline.js';
5
4
  // Framework-specific extractors
6
- export { extractReactComponents } from './extract/adapters/react/extractor.js';
7
- export { extractVueComponents } from './extract/adapters/vue/extractor.js';
8
- export { extractVueTsxComponents } from './extract/adapters/vue-tsx/extractor.js';
9
- export { extractStencilComponents } from './extract/adapters/stencil/extractor.js';
10
- export { extractAstroComponents } from './extract/adapters/astro/extractor.js';
11
- export { extractWebComponentDefinitions } from './extract/adapters/web-components/extractor.js';
12
- export { extractSvelteComponents } from './extract/adapters/svelte/extractor.js';
13
- export { extractAllowedComponentsFromTypeText, extractAllowedComponentsFromJsdoc, } from './extract/evidence/allowed-components.js';
5
+ export { extractReactComponents } from './extract/react.js';
6
+ export { extractVueComponents } from './extract/vue.js';
7
+ export { extractVueTsxComponents } from './extract/vue-tsx.js';
8
+ export { extractStencilComponents } from './extract/stencil.js';
9
+ export { extractAstroComponents } from './extract/astro.js';
10
+ export { extractWebComponentDefinitions } from './extract/web-components.js';
11
+ export { extractSvelteComponents } from './extract/svelte.js';
12
+ export { extractAllowedComponentsFromTypeText, extractAllowedComponentsFromJsdoc, } from './extract/slot-allowed-components.js';
14
13
  // Post-extraction filtering and scoring
15
- export { isNonAuthorableComponent } from './extract/policies/quality/authorability.js';
16
- export { computeExtractionScore, deriveNeedsReview } from './extract/policies/quality/scoring.js';
17
- export { inspectComponentSource, describeReviewReasons, describeReviewReason, isDataWrapperReviewReason, HIGH_CONFIDENCE_DATA_FETCH_WRAPPER_REASON, POSSIBLE_DATA_FETCH_WRAPPER_REASON, ZERO_SURFACE_RENDERED_UI_REASON, } from './extract/policies/quality/source-inspection.js';
14
+ export { isNonAuthorableComponent } from './extract/non-authorable-filter.js';
15
+ export { computeExtractionScore, deriveNeedsReview } from './extract/scoring.js';
16
+ export { inspectComponentSource, describeReviewReasons, describeReviewReason, isDataWrapperReviewReason, HIGH_CONFIDENCE_DATA_FETCH_WRAPPER_REASON, POSSIBLE_DATA_FETCH_WRAPPER_REASON, ZERO_SURFACE_RENDERED_UI_REASON, } from './extract/source-inspection.js';
18
17
  // Validation
19
- export { validateExtractedComponents, shouldExcludeDueToValidation, formatExclusionWarning, formatExcludedComponentLines, } from './extract/policies/quality/validation.js';
20
- export { parseImportedNames } from './extract/evidence/source-evidence.js';
18
+ export { validateExtractedComponents, shouldExcludeDueToValidation, formatExclusionWarning, formatExcludedComponentLines, } from './extract/validate.js';
19
+ export { parseImportedNames } from './extract/parse-imported-names.js';
21
20
  // Slot detection helpers
22
- export { CONTENT_NAME_EXCEPTIONS, isReactNodeType, isArrayReactNodeType, shouldBeSlot, } from './extract/evidence/slot-evidence.js';
21
+ export { CONTENT_NAME_EXCEPTIONS, isReactNodeType, isArrayReactNodeType, shouldBeSlot, } from './extract/slot-detection.js';
23
22
  // Pre-classification
24
- export { preClassifyProp, preClassifyComponent } from './extract/services/classification-service.js';
23
+ export { preClassifyProp, preClassifyComponent } from './pre-classify.js';
@@ -1,4 +1,4 @@
1
- import type { RawPropDefinition, RawComponentDefinition } from '../model/component.js';
1
+ import type { RawPropDefinition, RawComponentDefinition } from './types.js';
2
2
  export interface PreClassification {
3
3
  category: 'content' | 'design' | 'state' | 'exclude';
4
4
  cdfTypeHint?: 'string' | 'enum' | 'richtext' | 'media' | 'boolean';
@@ -76,5 +76,25 @@ export type ExtractorProgress = {
76
76
  filesProcessed: number;
77
77
  componentsFound: number;
78
78
  };
79
+ /**
80
+ * Optional extraction-time settings forwarded from the CLI through the
81
+ * pipeline to each extractor. Only the Svelte extractor currently consumes
82
+ * any of these; other extractors ignore the value.
83
+ */
84
+ export interface ExtractorOptions {
85
+ /**
86
+ * Whether the Svelte extractor should run a retry pass for components whose
87
+ * declared Props type couldn't be resolved on the first pass (cross-package
88
+ * extends, path-alias-only types, etc.). See svelte.ts for the policy.
89
+ */
90
+ resolveUnreachable?: 'auto' | 'always' | 'never';
91
+ /** Absolute project root — used by the retry pass to locate tsconfig.json and node_modules. */
92
+ projectRoot?: string;
93
+ }
94
+ export interface ComponentExtractor {
95
+ name: string;
96
+ fileFilter: (filePath: string) => boolean;
97
+ extract(filePaths: string[], onProgress?: (p: ExtractorProgress) => void, opts?: ExtractorOptions): Promise<ComponentExtractionResult>;
98
+ }
79
99
  /** Strip internal scoring fields before serialising a RawComponentDefinition for display or editing. */
80
100
  export declare function stripScoringFields({ extractionConfidence: _c, reviewReasons: _r, needsReview: _n, ...rest }: RawComponentDefinition): Omit<RawComponentDefinition, 'extractionConfidence' | 'reviewReasons' | 'needsReview'>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-extraction",
3
- "version": "2.34.5-dev-build-4a4b9e84.0",
3
+ "version": "2.34.5-dev-build-9dff4380.0",
4
4
  "description": "Component extraction engine for the Contentful Experience Design System SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,4 +0,0 @@
1
- import { Node, type ArrowFunction, type FunctionDeclaration, type FunctionExpression } from 'ts-morph';
2
- export type FunctionLike = FunctionDeclaration | ArrowFunction | FunctionExpression;
3
- export declare function resolveFunctionNode(decl: Node): FunctionLike | undefined;
4
- export declare function resolveBestFunctionNode(declarations: Node[]): FunctionLike | undefined;
@@ -1,131 +0,0 @@
1
- import { Node, } from 'ts-morph';
2
- import { getNodeDefinitions } from '../support/tsx-shared.js';
3
- export function resolveFunctionNode(decl) {
4
- if (Node.isFunctionDeclaration(decl))
5
- return decl;
6
- if (Node.isArrowFunction(decl))
7
- return decl;
8
- if (Node.isFunctionExpression(decl))
9
- return decl;
10
- if (Node.isVariableDeclaration(decl)) {
11
- const init = decl.getInitializer();
12
- if (init && Node.isArrowFunction(init))
13
- return init;
14
- if (init && Node.isFunctionExpression(init))
15
- return init;
16
- if (init && Node.isCallExpression(init))
17
- return resolveFunctionFromCallExpression(init, new Set());
18
- }
19
- return undefined;
20
- }
21
- export function resolveBestFunctionNode(declarations) {
22
- const candidates = declarations
23
- .map((decl) => resolveFunctionNode(decl))
24
- .filter((candidate) => candidate !== undefined);
25
- const implementation = candidates.find((candidate) => !Node.isFunctionDeclaration(candidate) || candidate.getBody() !== undefined);
26
- return implementation ?? candidates[0];
27
- }
28
- function resolveForwardRefFunction(callExpr) {
29
- if (!Node.isCallExpression(callExpr))
30
- return undefined;
31
- const expressionText = callExpr.getExpression().getText();
32
- if (!/(^|\.)forwardRef$/.test(expressionText))
33
- return undefined;
34
- const firstArg = callExpr.getArguments()[0];
35
- if (!firstArg)
36
- return undefined;
37
- if (Node.isArrowFunction(firstArg))
38
- return firstArg;
39
- if (Node.isFunctionExpression(firstArg))
40
- return firstArg;
41
- if (Node.isIdentifier(firstArg)) {
42
- const declarations = getNodeDefinitions(firstArg).flatMap((definition) => {
43
- const declarationNode = definition.getDeclarationNode();
44
- return declarationNode ? [declarationNode] : [];
45
- });
46
- for (const declaration of declarations) {
47
- const resolved = resolveFunctionNode(declaration);
48
- if (resolved)
49
- return resolved;
50
- }
51
- }
52
- return undefined;
53
- }
54
- function resolveFunctionFromCallExpression(callExpr, seen) {
55
- return resolveForwardRefFunction(callExpr) ?? resolveReturnedFunctionFromFactoryCall(callExpr, seen);
56
- }
57
- function resolveReturnedFunctionFromFactoryCall(callExpr, seen) {
58
- const expression = callExpr.getExpression();
59
- if (!Node.isIdentifier(expression))
60
- return undefined;
61
- for (const definition of getNodeDefinitions(expression)) {
62
- const declaration = definition.getDeclarationNode();
63
- if (!declaration)
64
- continue;
65
- const resolved = resolveReturnedFunctionFromDeclaration(declaration, seen);
66
- if (resolved)
67
- return resolved;
68
- }
69
- return undefined;
70
- }
71
- function resolveReturnedFunctionFromDeclaration(node, seen) {
72
- if (seen.has(node))
73
- return undefined;
74
- seen.add(node);
75
- if (Node.isVariableDeclaration(node)) {
76
- const initializer = node.getInitializer();
77
- if (!initializer)
78
- return undefined;
79
- if (Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer)) {
80
- return resolveReturnedFunctionFromCallable(initializer, seen);
81
- }
82
- if (Node.isCallExpression(initializer)) {
83
- return resolveFunctionFromCallExpression(initializer, seen);
84
- }
85
- return undefined;
86
- }
87
- if (Node.isFunctionDeclaration(node) || Node.isFunctionExpression(node) || Node.isArrowFunction(node)) {
88
- return resolveReturnedFunctionFromCallable(node, seen);
89
- }
90
- return undefined;
91
- }
92
- function resolveReturnedFunctionFromCallable(fn, seen) {
93
- const body = fn.getBody();
94
- if (!body)
95
- return undefined;
96
- if (!Node.isBlock(body)) {
97
- return resolveReturnedFunctionFromExpression(body, seen);
98
- }
99
- for (const statement of body.getStatements()) {
100
- if (!Node.isReturnStatement(statement))
101
- continue;
102
- const expression = statement.getExpression();
103
- if (!expression)
104
- continue;
105
- const resolved = resolveReturnedFunctionFromExpression(expression, seen);
106
- if (resolved)
107
- return resolved;
108
- }
109
- return undefined;
110
- }
111
- function resolveReturnedFunctionFromExpression(node, seen) {
112
- if (Node.isArrowFunction(node) || Node.isFunctionExpression(node))
113
- return node;
114
- if (Node.isParenthesizedExpression(node)) {
115
- return resolveReturnedFunctionFromExpression(node.getExpression(), seen);
116
- }
117
- if (Node.isCallExpression(node)) {
118
- return resolveFunctionFromCallExpression(node, seen);
119
- }
120
- if (Node.isIdentifier(node)) {
121
- for (const definition of getNodeDefinitions(node)) {
122
- const declaration = definition.getDeclarationNode();
123
- if (!declaration)
124
- continue;
125
- const resolved = resolveReturnedFunctionFromDeclaration(declaration, seen);
126
- if (resolved)
127
- return resolved;
128
- }
129
- }
130
- return undefined;
131
- }
@@ -1,14 +0,0 @@
1
- import { type ParameterDeclaration } from 'ts-morph';
2
- import { type FunctionLike } from './function-resolution.js';
3
- export type PropForwardingEdge = {
4
- sourceProp: string;
5
- targetComponentIdentity: string;
6
- targetProp: string;
7
- };
8
- export type PropDataflow = {
9
- intrinsicDomProps: Set<string>;
10
- componentEdges: PropForwardingEdge[];
11
- };
12
- export declare function getComponentIdentity(func: FunctionLike): string;
13
- /** Trace only statically resolvable, component-local prop dataflow into JSX. */
14
- export declare function collectPropDataflow(func: FunctionLike, param: ParameterDeclaration, availablePropNames: Set<string>): PropDataflow;