functional-examples 0.0.0-alpha.1

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 (202) hide show
  1. package/README.md +148 -0
  2. package/dist/cli/commands/generate.d.ts +10 -0
  3. package/dist/cli/commands/generate.d.ts.map +1 -0
  4. package/dist/cli/commands/generate.js +64 -0
  5. package/dist/cli/commands/generate.js.map +1 -0
  6. package/dist/cli/commands/init.d.ts +14 -0
  7. package/dist/cli/commands/init.d.ts.map +1 -0
  8. package/dist/cli/commands/init.js +95 -0
  9. package/dist/cli/commands/init.js.map +1 -0
  10. package/dist/cli/commands/scan.d.ts +20 -0
  11. package/dist/cli/commands/scan.d.ts.map +1 -0
  12. package/dist/cli/commands/scan.js +182 -0
  13. package/dist/cli/commands/scan.js.map +1 -0
  14. package/dist/cli/commands/validate.d.ts +10 -0
  15. package/dist/cli/commands/validate.d.ts.map +1 -0
  16. package/dist/cli/commands/validate.js +65 -0
  17. package/dist/cli/commands/validate.js.map +1 -0
  18. package/dist/cli/index.d.ts +88 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +43 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/cli/plugin-commands.d.ts +17 -0
  23. package/dist/cli/plugin-commands.d.ts.map +1 -0
  24. package/dist/cli/plugin-commands.js +45 -0
  25. package/dist/cli/plugin-commands.js.map +1 -0
  26. package/dist/config/index.d.ts +11 -0
  27. package/dist/config/index.d.ts.map +1 -0
  28. package/dist/config/index.js +9 -0
  29. package/dist/config/index.js.map +1 -0
  30. package/dist/config/index.spec.d.ts +5 -0
  31. package/dist/config/index.spec.d.ts.map +1 -0
  32. package/dist/config/index.spec.js +142 -0
  33. package/dist/config/index.spec.js.map +1 -0
  34. package/dist/config/loader.d.ts +7 -0
  35. package/dist/config/loader.d.ts.map +1 -0
  36. package/dist/config/loader.js +85 -0
  37. package/dist/config/loader.js.map +1 -0
  38. package/dist/config/merger.d.ts +27 -0
  39. package/dist/config/merger.d.ts.map +1 -0
  40. package/dist/config/merger.js +41 -0
  41. package/dist/config/merger.js.map +1 -0
  42. package/dist/config/resolver.d.ts +28 -0
  43. package/dist/config/resolver.d.ts.map +1 -0
  44. package/dist/config/resolver.js +165 -0
  45. package/dist/config/resolver.js.map +1 -0
  46. package/dist/config/schema.d.ts +53 -0
  47. package/dist/config/schema.d.ts.map +1 -0
  48. package/dist/config/schema.js +42 -0
  49. package/dist/config/schema.js.map +1 -0
  50. package/dist/config/types.d.ts +17 -0
  51. package/dist/config/types.d.ts.map +1 -0
  52. package/dist/config/types.js +5 -0
  53. package/dist/config/types.js.map +1 -0
  54. package/dist/config/validator.d.ts +6 -0
  55. package/dist/config/validator.d.ts.map +1 -0
  56. package/dist/config/validator.js +17 -0
  57. package/dist/config/validator.js.map +1 -0
  58. package/dist/extractors/index.d.ts +9 -0
  59. package/dist/extractors/index.d.ts.map +1 -0
  60. package/dist/extractors/index.js +9 -0
  61. package/dist/extractors/index.js.map +1 -0
  62. package/dist/extractors/loader.d.ts +19 -0
  63. package/dist/extractors/loader.d.ts.map +1 -0
  64. package/dist/extractors/loader.js +120 -0
  65. package/dist/extractors/loader.js.map +1 -0
  66. package/dist/extractors/meta-yml-fn.d.ts +19 -0
  67. package/dist/extractors/meta-yml-fn.d.ts.map +1 -0
  68. package/dist/extractors/meta-yml-fn.js +66 -0
  69. package/dist/extractors/meta-yml-fn.js.map +1 -0
  70. package/dist/extractors/meta-yml.d.ts +24 -0
  71. package/dist/extractors/meta-yml.d.ts.map +1 -0
  72. package/dist/extractors/meta-yml.js +65 -0
  73. package/dist/extractors/meta-yml.js.map +1 -0
  74. package/dist/extractors/registry.d.ts +58 -0
  75. package/dist/extractors/registry.d.ts.map +1 -0
  76. package/dist/extractors/registry.js +114 -0
  77. package/dist/extractors/registry.js.map +1 -0
  78. package/dist/extractors/registry.spec.d.ts +2 -0
  79. package/dist/extractors/registry.spec.d.ts.map +1 -0
  80. package/dist/extractors/registry.spec.js +102 -0
  81. package/dist/extractors/registry.spec.js.map +1 -0
  82. package/dist/extractors/types.d.ts +34 -0
  83. package/dist/extractors/types.d.ts.map +1 -0
  84. package/dist/extractors/types.js +8 -0
  85. package/dist/extractors/types.js.map +1 -0
  86. package/dist/extractors/yaml-frontmatter-fn.d.ts +18 -0
  87. package/dist/extractors/yaml-frontmatter-fn.d.ts.map +1 -0
  88. package/dist/extractors/yaml-frontmatter-fn.js +73 -0
  89. package/dist/extractors/yaml-frontmatter-fn.js.map +1 -0
  90. package/dist/extractors/yaml-frontmatter.d.ts +22 -0
  91. package/dist/extractors/yaml-frontmatter.d.ts.map +1 -0
  92. package/dist/extractors/yaml-frontmatter.js +83 -0
  93. package/dist/extractors/yaml-frontmatter.js.map +1 -0
  94. package/dist/extractors/yaml-frontmatter.spec.d.ts +2 -0
  95. package/dist/extractors/yaml-frontmatter.spec.d.ts.map +1 -0
  96. package/dist/extractors/yaml-frontmatter.spec.js +134 -0
  97. package/dist/extractors/yaml-frontmatter.spec.js.map +1 -0
  98. package/dist/files/index.d.ts +5 -0
  99. package/dist/files/index.d.ts.map +1 -0
  100. package/dist/files/index.js +5 -0
  101. package/dist/files/index.js.map +1 -0
  102. package/dist/files/reader.d.ts +50 -0
  103. package/dist/files/reader.d.ts.map +1 -0
  104. package/dist/files/reader.js +62 -0
  105. package/dist/files/reader.js.map +1 -0
  106. package/dist/index.d.ts +29 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +22 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/plugins/index.d.ts +4 -0
  111. package/dist/plugins/index.d.ts.map +1 -0
  112. package/dist/plugins/index.js +4 -0
  113. package/dist/plugins/index.js.map +1 -0
  114. package/dist/plugins/pipeline.d.ts +11 -0
  115. package/dist/plugins/pipeline.d.ts.map +1 -0
  116. package/dist/plugins/pipeline.js +24 -0
  117. package/dist/plugins/pipeline.js.map +1 -0
  118. package/dist/plugins/registry.d.ts +57 -0
  119. package/dist/plugins/registry.d.ts.map +1 -0
  120. package/dist/plugins/registry.js +93 -0
  121. package/dist/plugins/registry.js.map +1 -0
  122. package/dist/plugins/validation.d.ts +64 -0
  123. package/dist/plugins/validation.d.ts.map +1 -0
  124. package/dist/plugins/validation.js +55 -0
  125. package/dist/plugins/validation.js.map +1 -0
  126. package/dist/regions/index.d.ts +7 -0
  127. package/dist/regions/index.d.ts.map +1 -0
  128. package/dist/regions/index.js +6 -0
  129. package/dist/regions/index.js.map +1 -0
  130. package/dist/regions/languages.d.ts +15 -0
  131. package/dist/regions/languages.d.ts.map +1 -0
  132. package/dist/regions/languages.js +182 -0
  133. package/dist/regions/languages.js.map +1 -0
  134. package/dist/regions/parser.d.ts +63 -0
  135. package/dist/regions/parser.d.ts.map +1 -0
  136. package/dist/regions/parser.js +175 -0
  137. package/dist/regions/parser.js.map +1 -0
  138. package/dist/regions/parser.spec.d.ts +2 -0
  139. package/dist/regions/parser.spec.d.ts.map +1 -0
  140. package/dist/regions/parser.spec.js +190 -0
  141. package/dist/regions/parser.spec.js.map +1 -0
  142. package/dist/regions/types.d.ts +37 -0
  143. package/dist/regions/types.d.ts.map +1 -0
  144. package/dist/regions/types.js +5 -0
  145. package/dist/regions/types.js.map +1 -0
  146. package/dist/scanner/candidates.d.ts +24 -0
  147. package/dist/scanner/candidates.d.ts.map +1 -0
  148. package/dist/scanner/candidates.js +83 -0
  149. package/dist/scanner/candidates.js.map +1 -0
  150. package/dist/scanner/index.d.ts +8 -0
  151. package/dist/scanner/index.d.ts.map +1 -0
  152. package/dist/scanner/index.js +6 -0
  153. package/dist/scanner/index.js.map +1 -0
  154. package/dist/scanner/scan.d.ts +40 -0
  155. package/dist/scanner/scan.d.ts.map +1 -0
  156. package/dist/scanner/scan.js +44 -0
  157. package/dist/scanner/scan.js.map +1 -0
  158. package/dist/scanner/scanner.d.ts +29 -0
  159. package/dist/scanner/scanner.d.ts.map +1 -0
  160. package/dist/scanner/scanner.js +296 -0
  161. package/dist/scanner/scanner.js.map +1 -0
  162. package/dist/scanner/scanner.spec.d.ts +2 -0
  163. package/dist/scanner/scanner.spec.d.ts.map +1 -0
  164. package/dist/scanner/scanner.spec.js +262 -0
  165. package/dist/scanner/scanner.spec.js.map +1 -0
  166. package/dist/scanner/types.d.ts +43 -0
  167. package/dist/scanner/types.d.ts.map +1 -0
  168. package/dist/scanner/types.js +5 -0
  169. package/dist/scanner/types.js.map +1 -0
  170. package/dist/schema/index.d.ts +4 -0
  171. package/dist/schema/index.d.ts.map +1 -0
  172. package/dist/schema/index.js +4 -0
  173. package/dist/schema/index.js.map +1 -0
  174. package/dist/schema/merger.d.ts +35 -0
  175. package/dist/schema/merger.d.ts.map +1 -0
  176. package/dist/schema/merger.js +161 -0
  177. package/dist/schema/merger.js.map +1 -0
  178. package/dist/schema/typegen.d.ts +13 -0
  179. package/dist/schema/typegen.d.ts.map +1 -0
  180. package/dist/schema/typegen.js +125 -0
  181. package/dist/schema/typegen.js.map +1 -0
  182. package/dist/schema/validator.d.ts +7 -0
  183. package/dist/schema/validator.d.ts.map +1 -0
  184. package/dist/schema/validator.js +32 -0
  185. package/dist/schema/validator.js.map +1 -0
  186. package/dist/types/default-map.d.ts +21 -0
  187. package/dist/types/default-map.d.ts.map +1 -0
  188. package/dist/types/default-map.js +32 -0
  189. package/dist/types/default-map.js.map +1 -0
  190. package/dist/types/extended-iterable.d.ts +197 -0
  191. package/dist/types/extended-iterable.d.ts.map +1 -0
  192. package/dist/types/extended-iterable.js +769 -0
  193. package/dist/types/extended-iterable.js.map +1 -0
  194. package/dist/types/guards.d.ts +2 -0
  195. package/dist/types/guards.d.ts.map +1 -0
  196. package/dist/types/guards.js +2 -0
  197. package/dist/types/guards.js.map +1 -0
  198. package/dist/types/index.d.ts +11 -0
  199. package/dist/types/index.d.ts.map +1 -0
  200. package/dist/types/index.js +10 -0
  201. package/dist/types/index.js.map +1 -0
  202. package/package.json +61 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * meta.yml extractor for directory-based examples.
3
+ *
4
+ * Expected structure:
5
+ * ```
6
+ * examples/
7
+ * my-example/
8
+ * meta.yml
9
+ * main.ts
10
+ * helper.ts
11
+ * ```
12
+ */
13
+ import YAML from 'yaml';
14
+ import fs from 'node:fs/promises';
15
+ import path from 'node:path';
16
+ /**
17
+ * Extractor for directory-based examples with meta.yml.
18
+ * Used by isolated-workers pattern.
19
+ */
20
+ export class MetaYmlExtractor {
21
+ name = 'meta-yml';
22
+ canExtract(context) {
23
+ // Must be a directory with meta.yml
24
+ return context.isDirectory && (context.entries?.includes('meta.yml') ?? false);
25
+ }
26
+ async extract(context) {
27
+ const metaPath = path.join(context.path, 'meta.yml');
28
+ const metaContent = await fs.readFile(metaPath, 'utf-8');
29
+ const parsed = YAML.parse(metaContent);
30
+ // Generate ID from directory name if not provided
31
+ const dirName = path.basename(context.path);
32
+ const metadata = {
33
+ id: dirName,
34
+ title: dirName,
35
+ ...parsed,
36
+ };
37
+ // Collect all files except meta.yml and any content file
38
+ const contentFileName = parsed.contentFile ?? 'content.md';
39
+ const excludedFiles = new Set(['meta.yml', contentFileName]);
40
+ const files = [];
41
+ await this.collectFiles(context.path, context.path, excludedFiles, files);
42
+ return {
43
+ metadata,
44
+ files,
45
+ };
46
+ }
47
+ async collectFiles(rootPath, currentPath, excludedFiles, collected) {
48
+ const entries = await fs.readdir(currentPath, { withFileTypes: true });
49
+ for (const entry of entries) {
50
+ const fullPath = path.join(currentPath, entry.name);
51
+ const relativePath = path.relative(rootPath, fullPath);
52
+ if (entry.isDirectory()) {
53
+ await this.collectFiles(rootPath, fullPath, excludedFiles, collected);
54
+ }
55
+ else if (!excludedFiles.has(entry.name)) {
56
+ const contents = await fs.readFile(fullPath, 'utf-8');
57
+ collected.push({
58
+ path: relativePath,
59
+ contents,
60
+ });
61
+ }
62
+ }
63
+ }
64
+ }
65
+ //# sourceMappingURL=meta-yml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-yml.js","sourceRoot":"","sources":["../../src/extractors/meta-yml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAG,UAAU,CAAC;IAE3B,UAAU,CAAC,OAA0B;QACnC,oCAAoC;QACpC,OAAO,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAA0B;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAA4B,CAAC;QAElE,kDAAkD;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG;YACf,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,GAAG,MAAM;SACV,CAAC;QAEF,yDAAyD;QACzD,MAAM,eAAe,GAAI,MAAmC,CAAC,WAAW,IAAI,YAAY,CAAC;QACzF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;QAE7D,MAAM,KAAK,GAAkB,EAAE,CAAC;QAChC,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;QAE1E,OAAO;YACL,QAAQ;YACR,KAAK;SACN,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,YAAY,CACxB,QAAgB,EAChB,WAAmB,EACnB,aAA0B,EAC1B,SAAwB;QAExB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAEvE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAEvD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;YACxE,CAAC;iBAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACtD,SAAS,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,YAAY;oBAClB,QAAQ;iBACT,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Registry for metadata extractors (function-based with lazy loading)
3
+ */
4
+ import type { BaseMetadata } from '../types/index.js';
5
+ import type { ExtractionContext, ExtractedMetadata, MetadataExtractorFunction } from './types.js';
6
+ /**
7
+ * Registry that holds metadata extractors and dispatches extraction requests.
8
+ * Extractors are tried in registration order; first match wins.
9
+ */
10
+ export declare class ExtractorRegistry<TMetadata extends BaseMetadata = BaseMetadata> {
11
+ private entries;
12
+ private loadedExtractors;
13
+ /**
14
+ * Register a new extractor (immediate loading)
15
+ */
16
+ register(extractor: MetadataExtractorFunction<TMetadata>): this;
17
+ /**
18
+ * Register a lazy extractor reference (loaded on first use)
19
+ */
20
+ registerLazy(ref: string | {
21
+ module: string;
22
+ }, basePath?: string): this;
23
+ /**
24
+ * Get all registered extractors (immediate only)
25
+ */
26
+ getExtractors(): readonly MetadataExtractorFunction<TMetadata>[];
27
+ /**
28
+ * Find first extractor that can handle given context
29
+ */
30
+ findExtractor(context: ExtractionContext): Promise<MetadataExtractorFunction<TMetadata> | undefined>;
31
+ /**
32
+ * Extract metadata using first matching extractor
33
+ */
34
+ extract(context: ExtractionContext): Promise<ExtractedMetadata<TMetadata>>;
35
+ /**
36
+ * Clear module cache (for testing or config reload)
37
+ */
38
+ clearCache(): void;
39
+ /**
40
+ * Get extractor from entry, loading lazily if needed
41
+ */
42
+ private getExtractorForEntry;
43
+ /**
44
+ * Check if extractor can handle context
45
+ */
46
+ private checkCanExtract;
47
+ /**
48
+ * Perform extraction using extractor
49
+ */
50
+ private performExtract;
51
+ }
52
+ /**
53
+ * Create a registry with default extractors:
54
+ * - MetaYmlExtractor (for directory-based examples with meta.yml)
55
+ * - YamlFrontmatterExtractor (for single-file examples with YAML frontmatter)
56
+ */
57
+ export declare function createDefaultRegistry(): ExtractorRegistry;
58
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/extractors/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAqBpB;;;GAGG;AACH,qBAAa,iBAAiB,CAAC,SAAS,SAAS,YAAY,GAAG,YAAY;IAC1E,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,gBAAgB,CACZ;IAEZ;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAAG,IAAI;IAK/D;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAKvE;;OAEG;IACH,aAAa,IAAI,SAAS,yBAAyB,CAAC,SAAS,CAAC,EAAE;IAYhE;;OAEG;IACG,aAAa,CACjB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,yBAAyB,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAW5D;;OAEG;IACG,OAAO,CACX,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAYxC;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;YACW,oBAAoB;IA0BlC;;OAEG;YACW,eAAe;IAc7B;;OAEG;YACW,cAAc;CAM7B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,iBAAiB,CAIzD"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Registry for metadata extractors (function-based with lazy loading)
3
+ */
4
+ import { createYamlFrontmatterExtractor } from './yaml-frontmatter-fn.js';
5
+ import { createMetaYmlExtractor } from './meta-yml-fn.js';
6
+ import { loadExtractor, clearCache } from './loader.js';
7
+ /**
8
+ * Registry that holds metadata extractors and dispatches extraction requests.
9
+ * Extractors are tried in registration order; first match wins.
10
+ */
11
+ export class ExtractorRegistry {
12
+ entries = [];
13
+ loadedExtractors = new Map();
14
+ /**
15
+ * Register a new extractor (immediate loading)
16
+ */
17
+ register(extractor) {
18
+ this.entries.push({ type: 'immediate', extractor });
19
+ return this;
20
+ }
21
+ /**
22
+ * Register a lazy extractor reference (loaded on first use)
23
+ */
24
+ registerLazy(ref, basePath) {
25
+ this.entries.push({ type: 'lazy', ref, basePath });
26
+ return this;
27
+ }
28
+ /**
29
+ * Get all registered extractors (immediate only)
30
+ */
31
+ getExtractors() {
32
+ const immediateEntries = this.entries.filter((entry) => entry.type === 'immediate');
33
+ return immediateEntries.map((e) => e.extractor);
34
+ }
35
+ /**
36
+ * Find first extractor that can handle given context
37
+ */
38
+ async findExtractor(context) {
39
+ for (const entry of this.entries) {
40
+ const extractor = await this.getExtractorForEntry(entry, context);
41
+ if (!extractor)
42
+ continue;
43
+ const canExtract = await this.checkCanExtract(extractor, context);
44
+ if (canExtract)
45
+ return extractor;
46
+ }
47
+ return undefined;
48
+ }
49
+ /**
50
+ * Extract metadata using first matching extractor
51
+ */
52
+ async extract(context) {
53
+ const extractor = await this.findExtractor(context);
54
+ if (!extractor) {
55
+ throw new Error(`No extractor found for ${context.isDirectory ? 'directory' : 'file'}: ${context.path}`);
56
+ }
57
+ return await this.performExtract(extractor, context);
58
+ }
59
+ /**
60
+ * Clear module cache (for testing or config reload)
61
+ */
62
+ clearCache() {
63
+ this.loadedExtractors.clear();
64
+ clearCache();
65
+ }
66
+ /**
67
+ * Get extractor from entry, loading lazily if needed
68
+ */
69
+ async getExtractorForEntry(entry, _context) {
70
+ if (entry.type === 'immediate') {
71
+ return entry.extractor;
72
+ }
73
+ const cacheKey = typeof entry.ref === 'string' ? entry.ref : entry.ref.module;
74
+ if (this.loadedExtractors.has(cacheKey)) {
75
+ return this.loadedExtractors.get(cacheKey);
76
+ }
77
+ try {
78
+ const extractor = (await loadExtractor(entry.ref, entry.basePath || process.cwd()));
79
+ this.loadedExtractors.set(cacheKey, extractor);
80
+ return extractor;
81
+ }
82
+ catch (error) {
83
+ return undefined;
84
+ }
85
+ }
86
+ /**
87
+ * Check if extractor can handle context
88
+ */
89
+ async checkCanExtract(extractor, context) {
90
+ if ('canExtract' in extractor &&
91
+ typeof extractor.canExtract === 'function') {
92
+ const result = extractor.canExtract(context);
93
+ return result instanceof Promise ? await result : result;
94
+ }
95
+ return true;
96
+ }
97
+ /**
98
+ * Perform extraction using extractor
99
+ */
100
+ async performExtract(extractor, context) {
101
+ return extractor(context);
102
+ }
103
+ }
104
+ /**
105
+ * Create a registry with default extractors:
106
+ * - MetaYmlExtractor (for directory-based examples with meta.yml)
107
+ * - YamlFrontmatterExtractor (for single-file examples with YAML frontmatter)
108
+ */
109
+ export function createDefaultRegistry() {
110
+ return new ExtractorRegistry()
111
+ .register(createMetaYmlExtractor())
112
+ .register(createYamlFrontmatterExtractor());
113
+ }
114
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/extractors/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=registry.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.spec.d.ts","sourceRoot":"","sources":["../../src/extractors/registry.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ExtractorRegistry, createDefaultRegistry } from './registry.js';
3
+ /**
4
+ * Helper to create a mock extractor for testing
5
+ */
6
+ function createMockExtractor(name, canExtract, metadata) {
7
+ const fn = () => Promise.resolve({ metadata, files: [] });
8
+ fn.name = name;
9
+ fn.canExtract = () => canExtract;
10
+ return fn;
11
+ }
12
+ describe('ExtractorRegistry', () => {
13
+ describe('register', () => {
14
+ it('allows chaining registrations', () => {
15
+ const registry = new ExtractorRegistry();
16
+ const extractor1 = createMockExtractor('test1', false, {
17
+ id: '1',
18
+ title: '1',
19
+ });
20
+ const extractor2 = createMockExtractor('test2', false, {
21
+ id: '2',
22
+ title: '2',
23
+ });
24
+ const result = registry.register(extractor1).register(extractor2);
25
+ expect(result).toBe(registry);
26
+ expect(registry.getExtractors()).toHaveLength(2);
27
+ });
28
+ });
29
+ describe('findExtractor', () => {
30
+ it('returns first matching extractor', async () => {
31
+ const registry = new ExtractorRegistry();
32
+ const extractor1 = createMockExtractor('never-matches', false, {
33
+ id: '1',
34
+ title: '1',
35
+ });
36
+ const extractor2 = createMockExtractor('always-matches', true, {
37
+ id: '2',
38
+ title: '2',
39
+ });
40
+ registry.register(extractor1).register(extractor2);
41
+ const context = { path: '/test', isDirectory: false };
42
+ const found = await registry.findExtractor(context);
43
+ expect(found?.name).toBe('always-matches');
44
+ });
45
+ it('returns undefined when no extractor matches', async () => {
46
+ const registry = new ExtractorRegistry();
47
+ const extractor = createMockExtractor('never-matches', false, {
48
+ id: '1',
49
+ title: '1',
50
+ });
51
+ registry.register(extractor);
52
+ const context = { path: '/test', isDirectory: false };
53
+ const found = await registry.findExtractor(context);
54
+ expect(found).toBeUndefined();
55
+ });
56
+ });
57
+ describe('extract', () => {
58
+ it('uses first matching extractor', async () => {
59
+ const registry = new ExtractorRegistry();
60
+ const fn = () => Promise.resolve({
61
+ metadata: { id: 'test-id', title: 'Test Title' },
62
+ files: [{ path: 'test.ts', contents: 'code' }],
63
+ });
64
+ fn.name = 'test';
65
+ fn.canExtract = () => true;
66
+ registry.register(fn);
67
+ const context = { path: '/test', isDirectory: false };
68
+ const result = await registry.extract(context);
69
+ expect(result.metadata.id).toBe('test-id');
70
+ expect(result.metadata.title).toBe('Test Title');
71
+ });
72
+ it('throws when no extractor matches', async () => {
73
+ const registry = new ExtractorRegistry();
74
+ const context = { path: '/test', isDirectory: false };
75
+ await expect(registry.extract(context)).rejects.toThrow('No extractor found for file: /test');
76
+ });
77
+ it('throws with directory message for directories', async () => {
78
+ const registry = new ExtractorRegistry();
79
+ const context = { path: '/test', isDirectory: true };
80
+ await expect(registry.extract(context)).rejects.toThrow('No extractor found for directory: /test');
81
+ });
82
+ });
83
+ describe('createDefaultRegistry', () => {
84
+ it('includes meta-yml extractor', () => {
85
+ const registry = createDefaultRegistry();
86
+ const extractors = registry.getExtractors();
87
+ expect(extractors.some((e) => e.name === 'meta-yml')).toBe(true);
88
+ });
89
+ it('includes yaml-frontmatter extractor', () => {
90
+ const registry = createDefaultRegistry();
91
+ const extractors = registry.getExtractors();
92
+ expect(extractors.some((e) => e.name === 'yaml-frontmatter')).toBe(true);
93
+ });
94
+ it('prioritizes meta-yml over yaml-frontmatter', () => {
95
+ const registry = createDefaultRegistry();
96
+ const extractors = registry.getExtractors();
97
+ const names = extractors.map((e) => e.name);
98
+ expect(names.indexOf('meta-yml')).toBeLessThan(names.indexOf('yaml-frontmatter'));
99
+ });
100
+ });
101
+ });
102
+ //# sourceMappingURL=registry.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.spec.js","sourceRoot":"","sources":["../../src/extractors/registry.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Types for metadata extraction system (legacy)
3
+ *
4
+ * Note: The main extractor types are now in ../types/index.ts.
5
+ * These types remain for backward compatibility during transition.
6
+ */
7
+ import type { BaseMetadata, ExampleFile } from '../types/index.js';
8
+ /**
9
+ * Context provided to extractors for metadata extraction (legacy)
10
+ * @deprecated Use the new Extractor interface from ../types/index.js
11
+ */
12
+ export interface ExtractionContext {
13
+ /** Absolute path to file or directory being examined */
14
+ path: string;
15
+ /** Whether this is a directory */
16
+ isDirectory: boolean;
17
+ /** File contents (for single-file examples) */
18
+ content?: string;
19
+ /** Directory entries (for directory-based examples) */
20
+ entries?: string[];
21
+ }
22
+ /**
23
+ * Result of metadata extraction (legacy)
24
+ * @deprecated Use ExtractorResult from ../types/index.js
25
+ */
26
+ export interface ExtractedMetadata<TMetadata extends BaseMetadata = BaseMetadata> {
27
+ /** The extracted metadata */
28
+ metadata: TMetadata;
29
+ /** Files belonging to this example */
30
+ files: ExampleFile[];
31
+ /** Content with metadata removed (for frontmatter extraction) */
32
+ strippedContent?: string;
33
+ }
34
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/extractors/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB,CAChC,SAAS,SAAS,YAAY,GAAG,YAAY;IAE7C,6BAA6B;IAC7B,QAAQ,EAAE,SAAS,CAAC;IACpB,sCAAsC;IACtC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Types for metadata extraction system (legacy)
3
+ *
4
+ * Note: The main extractor types are now in ../types/index.ts.
5
+ * These types remain for backward compatibility during transition.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/extractors/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * YAML frontmatter extractor for single-file examples (function-based).
3
+ *
4
+ * Supports frontmatter in comment blocks:
5
+ * ```typescript
6
+ * // ---
7
+ * // title: Example Title
8
+ * // description: What this demonstrates
9
+ * // ---
10
+ * ```
11
+ */
12
+ import type { MetadataExtractorFunction } from './types.js';
13
+ import type { BaseMetadata } from '../types/index.js';
14
+ /**
15
+ * Extractor for YAML frontmatter in single-file examples.
16
+ */
17
+ export declare function createYamlFrontmatterExtractor<TMetadata extends BaseMetadata = BaseMetadata>(): MetadataExtractorFunction<TMetadata>;
18
+ //# sourceMappingURL=yaml-frontmatter-fn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-frontmatter-fn.d.ts","sourceRoot":"","sources":["../../src/extractors/yaml-frontmatter-fn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOtD;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,SAAS,SAAS,YAAY,GAAG,YAAY,KAC1C,yBAAyB,CAAC,SAAS,CAAC,CA4DxC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * YAML frontmatter extractor for single-file examples (function-based).
3
+ *
4
+ * Supports frontmatter in comment blocks:
5
+ * ```typescript
6
+ * // ---
7
+ * // title: Example Title
8
+ * // description: What this demonstrates
9
+ * // ---
10
+ * ```
11
+ */
12
+ import YAML from 'yaml';
13
+ import path from 'node:path';
14
+ /** Pattern to detect frontmatter start */
15
+ const FRONTMATTER_START = /^\/\/\s*---\s*$/;
16
+ /** Pattern to detect frontmatter end */
17
+ const FRONTMATTER_END = /^\/\/\s*---\s*$/;
18
+ /**
19
+ * Extractor for YAML frontmatter in single-file examples.
20
+ */
21
+ export function createYamlFrontmatterExtractor() {
22
+ const extractor = async (context) => {
23
+ if (context.isDirectory || !context.content) {
24
+ return undefined;
25
+ }
26
+ const lines = context.content.split('\n');
27
+ const firstLine = lines[0]?.trimEnd();
28
+ if (!firstLine || !FRONTMATTER_START.test(firstLine)) {
29
+ return undefined;
30
+ }
31
+ const frontmatterLines = [];
32
+ let lineIndex = 1;
33
+ while (lineIndex < lines.length) {
34
+ const line = lines[lineIndex].trimEnd();
35
+ if (FRONTMATTER_END.test(line)) {
36
+ lineIndex++;
37
+ break;
38
+ }
39
+ frontmatterLines.push(line.replace(/^\/\/\s?/, ''));
40
+ lineIndex++;
41
+ }
42
+ const yamlContent = frontmatterLines.join('\n');
43
+ const parsed = YAML.parse(yamlContent);
44
+ const filename = path.basename(context.path);
45
+ const defaultId = filename.replace(/\.[^.]+$/, '').replace(/\//g, '-');
46
+ const metadata = {
47
+ id: defaultId,
48
+ title: defaultId,
49
+ ...parsed,
50
+ };
51
+ const strippedContent = lines.slice(lineIndex).join('\n');
52
+ return {
53
+ metadata,
54
+ files: [
55
+ {
56
+ path: path.basename(context.path),
57
+ contents: strippedContent,
58
+ },
59
+ ],
60
+ strippedContent,
61
+ };
62
+ };
63
+ extractor.name = 'yaml-frontmatter';
64
+ extractor.canExtract = (context) => {
65
+ if (context.isDirectory || !context.content)
66
+ return false;
67
+ const lines = context.content.split('\n');
68
+ const firstLine = lines[0]?.trimEnd();
69
+ return FRONTMATTER_START.test(firstLine ?? '');
70
+ };
71
+ return extractor;
72
+ }
73
+ //# sourceMappingURL=yaml-frontmatter-fn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-frontmatter-fn.js","sourceRoot":"","sources":["../../src/extractors/yaml-frontmatter-fn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,0CAA0C;AAC1C,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAC5C,wCAAwC;AACxC,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAE1C;;GAEG;AACH,MAAM,UAAU,8BAA8B;IAG5C,MAAM,SAAS,GAAyC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxE,IAAI,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC5C,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACrD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,gBAAgB,GAAa,EAAE,CAAC;QACtC,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,OAAO,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/B,SAAS,EAAE,CAAC;gBACZ,MAAM;YACR,CAAC;YACD,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;YACpD,SAAS,EAAE,CAAC;QACd,CAAC;QAED,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAA4B,CAAC;QAElE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAEvE,MAAM,QAAQ,GAAG;YACf,EAAE,EAAE,SAAS;YACb,KAAK,EAAE,SAAS;YAChB,GAAG,MAAM;SACG,CAAC;QAEf,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE1D,OAAO;YACL,QAAQ;YACR,KAAK,EAAE;gBACL;oBACE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;oBACjC,QAAQ,EAAE,eAAe;iBAC1B;aACF;YACD,eAAe;SAChB,CAAC;IACJ,CAAC,CAAC;IAEF,SAAS,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACpC,SAAS,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QACtC,OAAO,iBAAiB,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * YAML frontmatter extractor for single-file examples.
3
+ *
4
+ * Supports frontmatter in comment blocks:
5
+ * ```typescript
6
+ * // ---
7
+ * // title: Example Title
8
+ * // description: What this demonstrates
9
+ * // ---
10
+ * ```
11
+ */
12
+ import type { MetadataExtractor, ExtractionContext, ExtractedMetadata } from './types.js';
13
+ /**
14
+ * Extractor for YAML frontmatter in single-file examples.
15
+ * Used by cli-forge and flexibench patterns.
16
+ */
17
+ export declare class YamlFrontmatterExtractor implements MetadataExtractor {
18
+ readonly name = "yaml-frontmatter";
19
+ canExtract(context: ExtractionContext): boolean;
20
+ extract(context: ExtractionContext): Promise<ExtractedMetadata>;
21
+ }
22
+ //# sourceMappingURL=yaml-frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-frontmatter.d.ts","sourceRoot":"","sources":["../../src/extractors/yaml-frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAQ1F;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,QAAQ,CAAC,IAAI,sBAAsB;IAEnC,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAYzC,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAwDtE"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * YAML frontmatter extractor for single-file examples.
3
+ *
4
+ * Supports frontmatter in comment blocks:
5
+ * ```typescript
6
+ * // ---
7
+ * // title: Example Title
8
+ * // description: What this demonstrates
9
+ * // ---
10
+ * ```
11
+ */
12
+ import YAML from 'yaml';
13
+ import path from 'node:path';
14
+ /** Pattern to detect frontmatter start */
15
+ const FRONTMATTER_START = /^\/\/\s*---\s*$/;
16
+ /** Pattern to detect frontmatter end */
17
+ const FRONTMATTER_END = /^\/\/\s*---\s*$/;
18
+ /**
19
+ * Extractor for YAML frontmatter in single-file examples.
20
+ * Used by cli-forge and flexibench patterns.
21
+ */
22
+ export class YamlFrontmatterExtractor {
23
+ name = 'yaml-frontmatter';
24
+ canExtract(context) {
25
+ // Only works on files with content
26
+ if (context.isDirectory || !context.content) {
27
+ return false;
28
+ }
29
+ // Check if first non-empty line is frontmatter start
30
+ const lines = context.content.split('\n');
31
+ const firstLine = lines[0]?.trimEnd();
32
+ return FRONTMATTER_START.test(firstLine ?? '');
33
+ }
34
+ async extract(context) {
35
+ if (!context.content) {
36
+ throw new Error('No content provided for frontmatter extraction');
37
+ }
38
+ const lines = context.content.split('\n');
39
+ const frontmatterLines = [];
40
+ let lineIndex = 0;
41
+ // Skip the opening ---
42
+ const firstLine = lines[lineIndex]?.trimEnd();
43
+ if (!firstLine || !FRONTMATTER_START.test(firstLine)) {
44
+ throw new Error('Content does not start with frontmatter marker');
45
+ }
46
+ lineIndex++;
47
+ // Collect frontmatter lines until closing ---
48
+ while (lineIndex < lines.length) {
49
+ const line = lines[lineIndex].trimEnd();
50
+ if (FRONTMATTER_END.test(line)) {
51
+ lineIndex++;
52
+ break;
53
+ }
54
+ // Strip the leading // and optional space
55
+ frontmatterLines.push(line.replace(/^\/\/\s?/, ''));
56
+ lineIndex++;
57
+ }
58
+ // Parse YAML
59
+ const yamlContent = frontmatterLines.join('\n');
60
+ const parsed = YAML.parse(yamlContent);
61
+ // Generate ID from filename if not provided
62
+ const filename = path.basename(context.path);
63
+ const defaultId = filename.replace(/\.[^.]+$/, '').replace(/\//g, '-');
64
+ const metadata = {
65
+ id: defaultId,
66
+ title: defaultId,
67
+ ...parsed,
68
+ };
69
+ // Content after frontmatter
70
+ const strippedContent = lines.slice(lineIndex).join('\n');
71
+ return {
72
+ metadata,
73
+ files: [
74
+ {
75
+ path: path.basename(context.path),
76
+ contents: strippedContent,
77
+ },
78
+ ],
79
+ strippedContent,
80
+ };
81
+ }
82
+ }
83
+ //# sourceMappingURL=yaml-frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-frontmatter.js","sourceRoot":"","sources":["../../src/extractors/yaml-frontmatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=yaml-frontmatter.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-frontmatter.spec.d.ts","sourceRoot":"","sources":["../../src/extractors/yaml-frontmatter.spec.ts"],"names":[],"mappings":""}