@buoy-design/scanners 0.2.1 → 0.2.26

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 (109) hide show
  1. package/dist/design-systems/index.d.ts +6 -0
  2. package/dist/design-systems/index.d.ts.map +1 -0
  3. package/dist/design-systems/index.js +6 -0
  4. package/dist/design-systems/index.js.map +1 -0
  5. package/dist/design-systems/library-detector.d.ts +53 -0
  6. package/dist/design-systems/library-detector.d.ts.map +1 -0
  7. package/dist/design-systems/library-detector.js +183 -0
  8. package/dist/design-systems/library-detector.js.map +1 -0
  9. package/dist/extractors/css-in-js.d.ts +20 -0
  10. package/dist/extractors/css-in-js.d.ts.map +1 -0
  11. package/dist/extractors/css-in-js.js +284 -0
  12. package/dist/extractors/css-in-js.js.map +1 -0
  13. package/dist/extractors/html-style.d.ts +1 -1
  14. package/dist/extractors/html-style.d.ts.map +1 -1
  15. package/dist/extractors/index.d.ts +1 -0
  16. package/dist/extractors/index.d.ts.map +1 -1
  17. package/dist/extractors/index.js +1 -0
  18. package/dist/extractors/index.js.map +1 -1
  19. package/dist/figma/client.d.ts +4 -0
  20. package/dist/figma/client.d.ts.map +1 -1
  21. package/dist/figma/client.js.map +1 -1
  22. package/dist/figma/component-scanner.d.ts +67 -1
  23. package/dist/figma/component-scanner.d.ts.map +1 -1
  24. package/dist/figma/component-scanner.js +162 -1
  25. package/dist/figma/component-scanner.js.map +1 -1
  26. package/dist/figma/index.d.ts +1 -1
  27. package/dist/figma/index.d.ts.map +1 -1
  28. package/dist/figma/index.js.map +1 -1
  29. package/dist/git/angular-scanner.d.ts +78 -1
  30. package/dist/git/angular-scanner.d.ts.map +1 -1
  31. package/dist/git/angular-scanner.js +249 -6
  32. package/dist/git/angular-scanner.js.map +1 -1
  33. package/dist/git/index.d.ts +4 -3
  34. package/dist/git/index.d.ts.map +1 -1
  35. package/dist/git/index.js +1 -0
  36. package/dist/git/index.js.map +1 -1
  37. package/dist/git/nextjs-scanner.d.ts +190 -0
  38. package/dist/git/nextjs-scanner.d.ts.map +1 -0
  39. package/dist/git/nextjs-scanner.js +979 -0
  40. package/dist/git/nextjs-scanner.js.map +1 -0
  41. package/dist/git/react-scanner.d.ts +74 -1
  42. package/dist/git/react-scanner.d.ts.map +1 -1
  43. package/dist/git/react-scanner.js +174 -5
  44. package/dist/git/react-scanner.js.map +1 -1
  45. package/dist/git/token-scanner.d.ts.map +1 -1
  46. package/dist/git/token-scanner.js +24 -2
  47. package/dist/git/token-scanner.js.map +1 -1
  48. package/dist/git/vue-scanner.d.ts +43 -1
  49. package/dist/git/vue-scanner.d.ts.map +1 -1
  50. package/dist/git/vue-scanner.js +130 -4
  51. package/dist/git/vue-scanner.js.map +1 -1
  52. package/dist/index.d.ts +2 -1
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +6 -2
  55. package/dist/index.js.map +1 -1
  56. package/dist/signals/extractors/arbitrary-value.d.ts +7 -0
  57. package/dist/signals/extractors/arbitrary-value.d.ts.map +1 -0
  58. package/dist/signals/extractors/arbitrary-value.js +57 -0
  59. package/dist/signals/extractors/arbitrary-value.js.map +1 -0
  60. package/dist/signals/extractors/breakpoint.d.ts +6 -0
  61. package/dist/signals/extractors/breakpoint.d.ts.map +1 -0
  62. package/dist/signals/extractors/breakpoint.js +41 -0
  63. package/dist/signals/extractors/breakpoint.js.map +1 -0
  64. package/dist/signals/extractors/index.d.ts +7 -0
  65. package/dist/signals/extractors/index.d.ts.map +1 -1
  66. package/dist/signals/extractors/index.js +7 -0
  67. package/dist/signals/extractors/index.js.map +1 -1
  68. package/dist/signals/extractors/inline-style.d.ts +6 -0
  69. package/dist/signals/extractors/inline-style.d.ts.map +1 -0
  70. package/dist/signals/extractors/inline-style.js +60 -0
  71. package/dist/signals/extractors/inline-style.js.map +1 -0
  72. package/dist/signals/extractors/radius.d.ts +3 -0
  73. package/dist/signals/extractors/radius.d.ts.map +1 -0
  74. package/dist/signals/extractors/radius.js +32 -0
  75. package/dist/signals/extractors/radius.js.map +1 -0
  76. package/dist/signals/extractors/shadow.d.ts +3 -0
  77. package/dist/signals/extractors/shadow.d.ts.map +1 -0
  78. package/dist/signals/extractors/shadow.js +41 -0
  79. package/dist/signals/extractors/shadow.js.map +1 -0
  80. package/dist/signals/extractors/sizing.d.ts +6 -0
  81. package/dist/signals/extractors/sizing.d.ts.map +1 -0
  82. package/dist/signals/extractors/sizing.js +60 -0
  83. package/dist/signals/extractors/sizing.js.map +1 -0
  84. package/dist/signals/extractors/z-index.d.ts +3 -0
  85. package/dist/signals/extractors/z-index.d.ts.map +1 -0
  86. package/dist/signals/extractors/z-index.js +30 -0
  87. package/dist/signals/extractors/z-index.js.map +1 -0
  88. package/dist/signals/scanner-integration.d.ts.map +1 -1
  89. package/dist/signals/scanner-integration.js +35 -0
  90. package/dist/signals/scanner-integration.js.map +1 -1
  91. package/dist/signals/types.d.ts +4 -4
  92. package/dist/signals/types.d.ts.map +1 -1
  93. package/dist/signals/types.js +4 -0
  94. package/dist/signals/types.js.map +1 -1
  95. package/dist/storybook/extractor.d.ts +106 -1
  96. package/dist/storybook/extractor.d.ts.map +1 -1
  97. package/dist/storybook/extractor.js +325 -5
  98. package/dist/storybook/extractor.js.map +1 -1
  99. package/dist/storybook/index.d.ts +1 -1
  100. package/dist/storybook/index.d.ts.map +1 -1
  101. package/dist/storybook/index.js.map +1 -1
  102. package/dist/tailwind/index.d.ts +1 -1
  103. package/dist/tailwind/index.d.ts.map +1 -1
  104. package/dist/tailwind/index.js.map +1 -1
  105. package/dist/tailwind/scanner.d.ts +32 -0
  106. package/dist/tailwind/scanner.d.ts.map +1 -1
  107. package/dist/tailwind/scanner.js +105 -0
  108. package/dist/tailwind/scanner.js.map +1 -1
  109. package/package.json +2 -2
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  /**
3
3
  * Signal types representing atomic facts extracted from code
4
4
  */
5
- export declare const SignalTypeSchema: z.ZodEnum<["color-value", "spacing-value", "font-size", "font-family", "font-weight", "radius-value", "shadow-value", "breakpoint", "token-definition", "token-usage", "component-def", "component-usage", "prop-pattern", "class-pattern"]>;
5
+ export declare const SignalTypeSchema: z.ZodEnum<["color-value", "spacing-value", "font-size", "font-family", "font-weight", "radius-value", "shadow-value", "breakpoint", "z-index", "sizing-value", "inline-style", "arbitrary-value", "token-definition", "token-usage", "component-def", "component-usage", "prop-pattern", "class-pattern"]>;
6
6
  export type SignalType = z.infer<typeof SignalTypeSchema>;
7
7
  /**
8
8
  * Source location for a signal
@@ -64,7 +64,7 @@ export type SignalContext = z.infer<typeof SignalContextSchema>;
64
64
  */
65
65
  export declare const RawSignalSchema: z.ZodObject<{
66
66
  id: z.ZodString;
67
- type: z.ZodEnum<["color-value", "spacing-value", "font-size", "font-family", "font-weight", "radius-value", "shadow-value", "breakpoint", "token-definition", "token-usage", "component-def", "component-usage", "prop-pattern", "class-pattern"]>;
67
+ type: z.ZodEnum<["color-value", "spacing-value", "font-size", "font-family", "font-weight", "radius-value", "shadow-value", "breakpoint", "z-index", "sizing-value", "inline-style", "arbitrary-value", "token-definition", "token-usage", "component-def", "component-usage", "prop-pattern", "class-pattern"]>;
68
68
  value: z.ZodUnknown;
69
69
  location: z.ZodObject<{
70
70
  path: z.ZodString;
@@ -100,7 +100,7 @@ export declare const RawSignalSchema: z.ZodObject<{
100
100
  }>;
101
101
  metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;
102
102
  }, "strip", z.ZodTypeAny, {
103
- type: "color-value" | "spacing-value" | "font-size" | "font-family" | "font-weight" | "radius-value" | "shadow-value" | "breakpoint" | "token-definition" | "token-usage" | "component-def" | "component-usage" | "prop-pattern" | "class-pattern";
103
+ type: "color-value" | "spacing-value" | "font-size" | "font-family" | "font-weight" | "radius-value" | "shadow-value" | "breakpoint" | "z-index" | "sizing-value" | "inline-style" | "arbitrary-value" | "token-definition" | "token-usage" | "component-def" | "component-usage" | "prop-pattern" | "class-pattern";
104
104
  id: string;
105
105
  location: {
106
106
  path: string;
@@ -117,7 +117,7 @@ export declare const RawSignalSchema: z.ZodObject<{
117
117
  metadata: Record<string, unknown>;
118
118
  value?: unknown;
119
119
  }, {
120
- type: "color-value" | "spacing-value" | "font-size" | "font-family" | "font-weight" | "radius-value" | "shadow-value" | "breakpoint" | "token-definition" | "token-usage" | "component-def" | "component-usage" | "prop-pattern" | "class-pattern";
120
+ type: "color-value" | "spacing-value" | "font-size" | "font-family" | "font-weight" | "radius-value" | "shadow-value" | "breakpoint" | "z-index" | "sizing-value" | "inline-style" | "arbitrary-value" | "token-definition" | "token-usage" | "component-def" | "component-usage" | "prop-pattern" | "class-pattern";
121
121
  id: string;
122
122
  location: {
123
123
  path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/signals/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,gBAAgB,8OAmB3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;EAK/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,cAAc,qHAczB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,eAAe,+FAQf,CAAC;AAEd,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,WAAW,8CAItB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;EAK9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAO1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,MAAM,CAKR"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/signals/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,gBAAgB,4SAuB3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;EAK/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,cAAc,qHAczB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,eAAe,+FAQf,CAAC;AAEd,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,WAAW,8CAItB,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;EAK9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAO1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,MAAM,CAKR"}
@@ -12,6 +12,10 @@ export const SignalTypeSchema = z.enum([
12
12
  'radius-value',
13
13
  'shadow-value',
14
14
  'breakpoint',
15
+ 'z-index',
16
+ 'sizing-value',
17
+ 'inline-style',
18
+ 'arbitrary-value',
15
19
  // Token signals
16
20
  'token-definition',
17
21
  'token-usage',
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/signals/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,sBAAsB;IACtB,aAAa;IACb,eAAe;IACf,WAAW;IACX,aAAa;IACb,aAAa;IACb,cAAc;IACd,cAAc;IACd,YAAY;IACZ,gBAAgB;IAChB,kBAAkB;IAClB,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,iBAAiB;IACjB,kBAAkB;IAClB,cAAc;IACd,eAAe;CAChB,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC;IACnC,KAAK;IACL,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,MAAM;IACN,UAAU;CACX,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC;IACpC,OAAO;IACP,KAAK;IACL,QAAQ;IACR,SAAS;IACT,UAAU;IACV,SAAS;IACT,KAAK;CACN,CAAC,CAAC,QAAQ,EAAE,CAAC;AAId;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC;IAChC,QAAQ;IACR,WAAW;IACX,QAAQ;CACT,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,QAAQ,EAAE,cAAc;IACxB,SAAS,EAAE,eAAe;IAC1B,KAAK,EAAE,WAAW;IAClB,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE;CACzB,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;IAClB,QAAQ,EAAE,oBAAoB;IAC9B,OAAO,EAAE,mBAAmB;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;CAChC,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAgB,EAChB,IAAY,EACZ,IAAY,EACZ,KAAc;IAEd,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ;QACzC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QACpB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/B,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/signals/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,sBAAsB;IACtB,aAAa;IACb,eAAe;IACf,WAAW;IACX,aAAa;IACb,aAAa;IACb,cAAc;IACd,cAAc;IACd,YAAY;IACZ,SAAS;IACT,cAAc;IACd,cAAc;IACd,iBAAiB;IACjB,gBAAgB;IAChB,kBAAkB;IAClB,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,iBAAiB;IACjB,kBAAkB;IAClB,cAAc;IACd,eAAe;CAChB,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC;IACnC,KAAK;IACL,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,QAAQ;IACR,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,MAAM;IACN,UAAU;CACX,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC;IACpC,OAAO;IACP,KAAK;IACL,QAAQ;IACR,SAAS;IACT,UAAU;IACV,SAAS;IACT,KAAK;CACN,CAAC,CAAC,QAAQ,EAAE,CAAC;AAId;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC;IAChC,QAAQ;IACR,WAAW;IACX,QAAQ;CACT,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,QAAQ,EAAE,cAAc;IACxB,SAAS,EAAE,eAAe;IAC1B,KAAK,EAAE,WAAW;IAClB,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE;CACzB,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;IAClB,QAAQ,EAAE,oBAAoB;IAC9B,OAAO,EAAE,mBAAmB;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;CAChC,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAgB,EAChB,IAAY,EACZ,IAAY,EACZ,KAAc;IAEd,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ;QACzC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QACpB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/B,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;AAChD,CAAC"}
@@ -13,22 +13,103 @@ export interface StoryFileScannerConfig extends ScannerConfig {
13
13
  include?: string[];
14
14
  /** Patterns to exclude */
15
15
  exclude?: string[];
16
+ /** Whether to scan MDX files (default: true) */
17
+ scanMdx?: boolean;
18
+ /** Whether to validate story args against prop types (default: false) */
19
+ validateArgs?: boolean;
20
+ }
21
+ /**
22
+ * MDX story information
23
+ */
24
+ export interface MdxStoryInfo {
25
+ /** File path */
26
+ file: string;
27
+ /** Title extracted from Meta */
28
+ title?: string;
29
+ /** Component referenced in Meta */
30
+ component?: string;
31
+ /** Story names found in the MDX */
32
+ stories: string[];
33
+ /** Whether it uses Canvas blocks */
34
+ hasCanvas: boolean;
35
+ /** Whether it uses Story blocks */
36
+ hasStoryBlocks: boolean;
37
+ /** Whether it has prose documentation */
38
+ hasDocumentation: boolean;
39
+ }
40
+ /**
41
+ * Args validation issue found in a story
42
+ */
43
+ export interface ArgsValidationIssue {
44
+ /** Story name where the issue was found */
45
+ storyName: string;
46
+ /** Property name with the issue */
47
+ propName: string;
48
+ /** Type of validation issue */
49
+ issueType: 'type-mismatch' | 'missing-required' | 'unknown-prop' | 'invalid-option';
50
+ /** Description of the issue */
51
+ message: string;
52
+ /** Expected type (for type mismatches) */
53
+ expectedType?: string;
54
+ /** Actual type found */
55
+ actualType?: string;
56
+ /** Value that caused the issue */
57
+ actualValue?: unknown;
58
+ }
59
+ /**
60
+ * Validation result for a story file
61
+ */
62
+ export interface StoryArgsValidation {
63
+ /** File path of the story */
64
+ file: string;
65
+ /** Component name */
66
+ componentName: string;
67
+ /** Issues found */
68
+ issues: ArgsValidationIssue[];
69
+ /** Total args validated */
70
+ argsValidated: number;
71
+ /** Whether all args are valid */
72
+ isValid: boolean;
16
73
  }
17
74
  /**
18
75
  * Scans .stories.{ts,tsx,js,jsx} files to extract component metadata.
19
76
  * This scanner parses Component Story Format (CSF) files directly from source code.
20
77
  */
78
+ /**
79
+ * Extended scan result with MDX info
80
+ */
81
+ export interface StoryFileScanResult extends ScanResult<Component> {
82
+ /** MDX story files found */
83
+ mdxStories: MdxStoryInfo[];
84
+ /** Components with stories */
85
+ documentedComponents: string[];
86
+ /** Total story count */
87
+ storyCount: number;
88
+ /** Args validation results (when validateArgs is enabled) */
89
+ argsValidation?: StoryArgsValidation[];
90
+ }
21
91
  export declare class StoryFileScanner extends Scanner<Component, StoryFileScannerConfig> {
22
92
  /** Default file patterns for story files */
23
93
  private static readonly DEFAULT_PATTERNS;
94
+ /** MDX file patterns */
95
+ private static readonly MDX_PATTERNS;
24
96
  constructor(config: StoryFileScannerConfig);
25
- scan(): Promise<ScanResult<Component>>;
97
+ private parsedMetas;
98
+ scan(): Promise<StoryFileScanResult>;
26
99
  getSourceType(): string;
27
100
  /**
28
101
  * Get story patterns from .storybook/main.ts config file
29
102
  */
30
103
  getStoryPatternsFromConfig(): Promise<string[]>;
31
104
  private extractStoriesPatterns;
105
+ /**
106
+ * Scan MDX story files
107
+ */
108
+ private scanMdxFiles;
109
+ /**
110
+ * Parse an MDX file for story information
111
+ */
112
+ private parseMdxFile;
32
113
  private parseStoryFile;
33
114
  private extractMeta;
34
115
  /**
@@ -85,6 +166,30 @@ export declare class StoryFileScanner extends Scanner<Component, StoryFileScanne
85
166
  private extractComponentName;
86
167
  private getComponentNameFromTitle;
87
168
  private createStoryId;
169
+ /**
170
+ * Validate all story args against their argTypes
171
+ */
172
+ private validateAllStoryArgs;
173
+ /**
174
+ * Validate args for a single story file
175
+ */
176
+ private validateStoryArgs;
177
+ /**
178
+ * Get the expected type string from an argType
179
+ */
180
+ private getExpectedType;
181
+ /**
182
+ * Map Storybook control types to basic types
183
+ */
184
+ private controlToType;
185
+ /**
186
+ * Get the actual type of a value
187
+ */
188
+ private getActualType;
189
+ /**
190
+ * Check if a value is compatible with an expected type
191
+ */
192
+ private isTypeCompatible;
88
193
  }
89
194
  /**
90
195
  * Scans Storybook static builds (index.json/stories.json) or running servers.
@@ -1 +1 @@
1
- {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/storybook/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAwB,MAAM,oBAAoB,CAAC;AAC9F,OAAO,KAAK,EAAE,SAAS,EAAmC,MAAM,mBAAmB,CAAC;AAOpF,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAiBD,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC3D,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAwCD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,OAAO,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAC9E,4CAA4C;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAKtC;gBAEU,MAAM,EAAE,sBAAsB;IAQpC,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAO5C,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACG,0BAA0B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAqBrD,OAAO,CAAC,sBAAsB;YA+BhB,cAAc;IA+H5B,OAAO,CAAC,WAAW;IA2CnB;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAwClB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAuCjC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA8E9B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA+ChC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4D5B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,eAAe;IA8FvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA0B9B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAsC/B,OAAO,CAAC,aAAa;IA8CrB,OAAO,CAAC,oBAAoB;IAuG5B,OAAO,CAAC,iBAAiB;IAsEzB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,wBAAwB;IA0BhC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA4B5B,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,aAAa;CAKtB;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,OAAO,CAAC,SAAS,EAAE,sBAAsB,CAAC;IACxE,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IA0B5C,aAAa,IAAI,MAAM;IAIvB,OAAO,CAAC,eAAe;YAiBT,iBAAiB;IA8C/B,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,iBAAiB;IAsDzB,OAAO,CAAC,eAAe;CAIxB"}
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/storybook/extractor.ts"],"names":[],"mappings":"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"}
@@ -12,10 +12,6 @@ const STORY_SCANNER_EXCLUDES = [
12
12
  '**/.next/**',
13
13
  '**/coverage/**',
14
14
  ];
15
- /**
16
- * Scans .stories.{ts,tsx,js,jsx} files to extract component metadata.
17
- * This scanner parses Component Story Format (CSF) files directly from source code.
18
- */
19
15
  export class StoryFileScanner extends Scanner {
20
16
  /** Default file patterns for story files */
21
17
  static DEFAULT_PATTERNS = [
@@ -24,15 +20,46 @@ export class StoryFileScanner extends Scanner {
24
20
  '**/*.stories.jsx',
25
21
  '**/*.stories.js',
26
22
  ];
23
+ /** MDX file patterns */
24
+ static MDX_PATTERNS = [
25
+ '**/*.stories.mdx',
26
+ '**/*.mdx',
27
+ ];
27
28
  constructor(config) {
28
29
  // Override exclude patterns to not exclude story files
29
30
  super({
30
31
  ...config,
32
+ scanMdx: config.scanMdx !== false,
31
33
  exclude: config.exclude ?? STORY_SCANNER_EXCLUDES,
32
34
  });
33
35
  }
36
+ // Store parsed meta for validation
37
+ parsedMetas = new Map();
34
38
  async scan() {
35
- return this.runScan((file) => this.parseStoryFile(file), StoryFileScanner.DEFAULT_PATTERNS);
39
+ // Clear the metas map for each scan
40
+ this.parsedMetas.clear();
41
+ const baseResult = await this.runScan((file) => this.parseStoryFile(file), StoryFileScanner.DEFAULT_PATTERNS);
42
+ // Scan MDX files if enabled
43
+ let mdxStories = [];
44
+ if (this.config.scanMdx !== false) {
45
+ mdxStories = await this.scanMdxFiles();
46
+ }
47
+ // Calculate documented components
48
+ const documentedComponents = baseResult.items.map(c => c.name);
49
+ // Calculate total story count
50
+ const storyCount = baseResult.items.reduce((sum, c) => sum + c.variants.length, 0) + mdxStories.reduce((sum, m) => sum + m.stories.length, 0);
51
+ // Validate args if enabled
52
+ let argsValidation;
53
+ if (this.config.validateArgs) {
54
+ argsValidation = this.validateAllStoryArgs();
55
+ }
56
+ return {
57
+ ...baseResult,
58
+ mdxStories,
59
+ documentedComponents,
60
+ storyCount,
61
+ argsValidation,
62
+ };
36
63
  }
37
64
  getSourceType() {
38
65
  return 'storybook';
@@ -80,6 +107,102 @@ export class StoryFileScanner extends Scanner {
80
107
  ts.forEachChild(sourceFile, visit);
81
108
  return patterns;
82
109
  }
110
+ /**
111
+ * Scan MDX story files
112
+ */
113
+ async scanMdxFiles() {
114
+ const mdxStories = [];
115
+ const { glob } = await import('glob');
116
+ for (const pattern of StoryFileScanner.MDX_PATTERNS) {
117
+ try {
118
+ const files = await glob(pattern, {
119
+ cwd: this.config.projectRoot,
120
+ ignore: this.config.exclude || STORY_SCANNER_EXCLUDES,
121
+ absolute: true,
122
+ });
123
+ for (const file of files) {
124
+ try {
125
+ const content = await readFile(file, 'utf-8');
126
+ const relativePath = relative(this.config.projectRoot, file);
127
+ const mdxInfo = this.parseMdxFile(content, relativePath);
128
+ if (mdxInfo) {
129
+ mdxStories.push(mdxInfo);
130
+ }
131
+ }
132
+ catch {
133
+ // Continue on read errors
134
+ }
135
+ }
136
+ }
137
+ catch {
138
+ // Continue to next pattern
139
+ }
140
+ }
141
+ return mdxStories;
142
+ }
143
+ /**
144
+ * Parse an MDX file for story information
145
+ */
146
+ parseMdxFile(content, filePath) {
147
+ const info = {
148
+ file: filePath,
149
+ stories: [],
150
+ hasCanvas: false,
151
+ hasStoryBlocks: false,
152
+ hasDocumentation: false,
153
+ };
154
+ // Check for Meta component (required for story MDX)
155
+ const metaMatch = content.match(/<Meta\s+([^>]+)>/);
156
+ if (metaMatch) {
157
+ const metaProps = metaMatch[1];
158
+ // Extract title
159
+ const titleMatch = metaProps.match(/title\s*=\s*["']([^"']+)["']/);
160
+ if (titleMatch) {
161
+ info.title = titleMatch[1];
162
+ }
163
+ // Extract component (either as string or JSX reference)
164
+ const componentMatch = metaProps.match(/component\s*=\s*\{?([A-Za-z]+)\}?/);
165
+ if (componentMatch) {
166
+ info.component = componentMatch[1];
167
+ }
168
+ }
169
+ // Check for Canvas blocks
170
+ if (/<Canvas\s*[^>]*>/.test(content)) {
171
+ info.hasCanvas = true;
172
+ }
173
+ // Check for Story blocks and extract names
174
+ const storyRegex = /<Story\s+(?:[^>]*?)name\s*=\s*["']([^"']+)["'](?:[^>]*?)>/g;
175
+ let storyMatch;
176
+ while ((storyMatch = storyRegex.exec(content)) !== null) {
177
+ info.stories.push(storyMatch[1]);
178
+ info.hasStoryBlocks = true;
179
+ }
180
+ // Also check for export const story pattern in MDX2
181
+ const exportStoryRegex = /export\s+const\s+([A-Z][a-zA-Z0-9]*)\s*=/g;
182
+ while ((storyMatch = exportStoryRegex.exec(content)) !== null) {
183
+ const storyName = storyMatch[1];
184
+ if (!info.stories.includes(storyName)) {
185
+ info.stories.push(storyName);
186
+ }
187
+ }
188
+ // Check for prose documentation (markdown content outside of code blocks)
189
+ // Simple heuristic: if there's text content that's not in JSX or code blocks
190
+ const proseContent = content
191
+ .replace(/<[^>]+>/g, '') // Remove JSX tags
192
+ .replace(/```[\s\S]*?```/g, '') // Remove code blocks
193
+ .replace(/`[^`]+`/g, '') // Remove inline code
194
+ .replace(/import\s+.+;?/g, '') // Remove imports
195
+ .replace(/export\s+.+;?/g, '') // Remove exports
196
+ .trim();
197
+ if (proseContent.length > 50) {
198
+ info.hasDocumentation = true;
199
+ }
200
+ // Only return if this looks like a story MDX (has Meta, Canvas, or Story blocks)
201
+ if (info.title || info.component || info.hasCanvas || info.hasStoryBlocks || info.stories.length > 0) {
202
+ return info;
203
+ }
204
+ return null;
205
+ }
83
206
  async parseStoryFile(filePath) {
84
207
  const content = await readFile(filePath, 'utf-8');
85
208
  const isTypeScript = filePath.endsWith('.tsx') || filePath.endsWith('.ts');
@@ -185,6 +308,13 @@ export class StoryFileScanner extends Scanner {
185
308
  },
186
309
  scannedAt: new Date(),
187
310
  };
311
+ // Store meta for validation
312
+ this.parsedMetas.set(relativePath, {
313
+ meta,
314
+ variants,
315
+ file: relativePath,
316
+ componentName,
317
+ });
188
318
  return [component];
189
319
  }
190
320
  extractMeta(sourceFile, relativePath) {
@@ -687,6 +817,26 @@ export class StoryFileScanner extends Scanner {
687
817
  }
688
818
  }
689
819
  }
820
+ // Parse type: { name: 'string', required: true }
821
+ if (argPropName === 'type' && ts.isObjectLiteralExpression(argProp.initializer)) {
822
+ argInfo.type = { name: '' };
823
+ for (const typeProp of argProp.initializer.properties) {
824
+ if (!ts.isPropertyAssignment(typeProp) || !typeProp.name)
825
+ continue;
826
+ const typePropName = typeProp.name.getText(sourceFile);
827
+ if (typePropName === 'name' && ts.isStringLiteral(typeProp.initializer)) {
828
+ argInfo.type.name = typeProp.initializer.text;
829
+ }
830
+ if (typePropName === 'required') {
831
+ if (typeProp.initializer.kind === ts.SyntaxKind.TrueKeyword) {
832
+ argInfo.type.required = true;
833
+ }
834
+ else if (typeProp.initializer.kind === ts.SyntaxKind.FalseKeyword) {
835
+ argInfo.type.required = false;
836
+ }
837
+ }
838
+ }
839
+ }
690
840
  }
691
841
  }
692
842
  argTypes[argName] = argInfo;
@@ -938,6 +1088,176 @@ export class StoryFileScanner extends Scanner {
938
1088
  const normalizedName = storyName.toLowerCase().replace(/[^a-z0-9]+/g, '-');
939
1089
  return `${normalizedTitle}--${normalizedName}`;
940
1090
  }
1091
+ /**
1092
+ * Validate all story args against their argTypes
1093
+ */
1094
+ validateAllStoryArgs() {
1095
+ const validations = [];
1096
+ for (const [, data] of this.parsedMetas) {
1097
+ const validation = this.validateStoryArgs(data);
1098
+ validations.push(validation);
1099
+ }
1100
+ return validations;
1101
+ }
1102
+ /**
1103
+ * Validate args for a single story file
1104
+ */
1105
+ validateStoryArgs(data) {
1106
+ const issues = [];
1107
+ let argsValidated = 0;
1108
+ const { meta, variants, file, componentName } = data;
1109
+ const argTypes = meta.argTypes || {};
1110
+ for (const variant of variants) {
1111
+ if (!variant.args)
1112
+ continue;
1113
+ for (const [propName, value] of Object.entries(variant.args)) {
1114
+ argsValidated++;
1115
+ // Check if prop is defined in argTypes
1116
+ const argType = argTypes[propName];
1117
+ if (!argType) {
1118
+ // Unknown prop - might be intentional but worth noting
1119
+ issues.push({
1120
+ storyName: variant.name,
1121
+ propName,
1122
+ issueType: 'unknown-prop',
1123
+ message: `Prop '${propName}' is not defined in argTypes`,
1124
+ actualValue: value,
1125
+ });
1126
+ continue;
1127
+ }
1128
+ // Check type if defined
1129
+ const expectedType = this.getExpectedType(argType);
1130
+ if (expectedType) {
1131
+ const actualType = this.getActualType(value);
1132
+ const isValid = this.isTypeCompatible(expectedType, actualType, value);
1133
+ if (!isValid) {
1134
+ issues.push({
1135
+ storyName: variant.name,
1136
+ propName,
1137
+ issueType: 'type-mismatch',
1138
+ message: `Type mismatch for '${propName}': expected ${expectedType}, got ${actualType}`,
1139
+ expectedType,
1140
+ actualType,
1141
+ actualValue: value,
1142
+ });
1143
+ }
1144
+ }
1145
+ // Check options constraint
1146
+ if (argType.options && argType.options.length > 0) {
1147
+ if (typeof value === 'string' && !argType.options.includes(value)) {
1148
+ issues.push({
1149
+ storyName: variant.name,
1150
+ propName,
1151
+ issueType: 'invalid-option',
1152
+ message: `Invalid option for '${propName}': '${value}' is not in [${argType.options.join(', ')}]`,
1153
+ actualValue: value,
1154
+ });
1155
+ }
1156
+ }
1157
+ }
1158
+ // Check for missing required props
1159
+ for (const [propName, argType] of Object.entries(argTypes)) {
1160
+ if (argType.type?.required && (!variant.args || !(propName in variant.args))) {
1161
+ issues.push({
1162
+ storyName: variant.name,
1163
+ propName,
1164
+ issueType: 'missing-required',
1165
+ message: `Required prop '${propName}' is missing in story '${variant.name}'`,
1166
+ });
1167
+ }
1168
+ }
1169
+ }
1170
+ return {
1171
+ file,
1172
+ componentName,
1173
+ issues,
1174
+ argsValidated,
1175
+ isValid: issues.length === 0,
1176
+ };
1177
+ }
1178
+ /**
1179
+ * Get the expected type string from an argType
1180
+ */
1181
+ getExpectedType(argType) {
1182
+ // Check explicit type
1183
+ if (argType.type?.name) {
1184
+ return argType.type.name;
1185
+ }
1186
+ // Infer from control
1187
+ if (argType.control) {
1188
+ if (typeof argType.control === 'string') {
1189
+ return this.controlToType(argType.control);
1190
+ }
1191
+ if (typeof argType.control === 'object' && argType.control.type) {
1192
+ return this.controlToType(argType.control.type);
1193
+ }
1194
+ }
1195
+ // Infer from options
1196
+ if (argType.options && argType.options.length > 0) {
1197
+ return 'string';
1198
+ }
1199
+ return undefined;
1200
+ }
1201
+ /**
1202
+ * Map Storybook control types to basic types
1203
+ */
1204
+ controlToType(control) {
1205
+ switch (control) {
1206
+ case 'text':
1207
+ case 'color':
1208
+ case 'date':
1209
+ case 'select':
1210
+ case 'radio':
1211
+ return 'string';
1212
+ case 'number':
1213
+ case 'range':
1214
+ return 'number';
1215
+ case 'boolean':
1216
+ return 'boolean';
1217
+ case 'object':
1218
+ return 'object';
1219
+ case 'array':
1220
+ return 'array';
1221
+ case 'file':
1222
+ return 'object';
1223
+ default:
1224
+ return control;
1225
+ }
1226
+ }
1227
+ /**
1228
+ * Get the actual type of a value
1229
+ */
1230
+ getActualType(value) {
1231
+ if (value === null)
1232
+ return 'null';
1233
+ if (value === undefined)
1234
+ return 'undefined';
1235
+ if (Array.isArray(value))
1236
+ return 'array';
1237
+ return typeof value;
1238
+ }
1239
+ /**
1240
+ * Check if a value is compatible with an expected type
1241
+ */
1242
+ isTypeCompatible(expectedType, actualType, value) {
1243
+ // Direct type match
1244
+ if (expectedType === actualType)
1245
+ return true;
1246
+ // Allow string for enum types (quoted union types)
1247
+ if (expectedType.includes("'") && actualType === 'string')
1248
+ return true;
1249
+ // Allow number coercion
1250
+ if (expectedType === 'number' && actualType === 'string') {
1251
+ return !isNaN(Number(value));
1252
+ }
1253
+ // Allow any for object types
1254
+ if (expectedType === 'object' && actualType === 'object')
1255
+ return true;
1256
+ // Allow function references (string in AST parsed form)
1257
+ if (expectedType === 'function' && actualType === 'string')
1258
+ return true;
1259
+ return false;
1260
+ }
941
1261
  }
942
1262
  /**
943
1263
  * Scans Storybook static builds (index.json/stories.json) or running servers.