@functional-examples/javascript 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.
@@ -0,0 +1,15 @@
1
+ import type { Extractor } from '@functional-examples/devkit';
2
+ /**
3
+ * Create a JavaScript/TypeScript extractor.
4
+ *
5
+ * This extractor:
6
+ * - Receives pre-filtered candidates (files and directories)
7
+ * - For directories with package.json: treats as multi-file package example
8
+ * - For files with frontmatter: treats as single-file example
9
+ * - Extracts metadata from package.json or frontmatter
10
+ * - Loads raw content into ExampleFile
11
+ * - Respects exclude patterns (default: node_modules, .git, dist, build)
12
+ * - Tracks claimed files for conflict detection
13
+ */
14
+ export declare function createJavaScriptExtractor(): Extractor;
15
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,SAAS,EAIV,MAAM,6BAA6B,CAAC;AAigBrC;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,SAAS,CAqPrD"}
@@ -0,0 +1,589 @@
1
+ import { createMatcher, glob, parseJson, parseYaml, } from '@functional-examples/devkit';
2
+ import dependencyTree from 'dependency-tree';
3
+ import * as fs from 'node:fs/promises';
4
+ import * as path from 'node:path';
5
+ const EXTRACTOR_NAME = 'javascript-extractor';
6
+ /** Default patterns to exclude from file scanning */
7
+ const DEFAULT_EXCLUDE_PATTERNS = [
8
+ '**/node_modules/**',
9
+ '**/.git/**',
10
+ '**/dist/**',
11
+ '**/build/**',
12
+ ];
13
+ /** Default directories to skip when processing directory candidates */
14
+ const DEFAULT_EXCLUDED_DIRS = new Set([
15
+ 'node_modules',
16
+ '.git',
17
+ 'dist',
18
+ 'build',
19
+ ]);
20
+ /** File extensions to scan for JavaScript/TypeScript examples */
21
+ const FILE_PATTERNS = [
22
+ '**/*.ts',
23
+ '**/*.tsx',
24
+ '**/*.js',
25
+ '**/*.jsx',
26
+ '**/*.mjs',
27
+ '**/*.cjs',
28
+ '**/*.mts',
29
+ '**/*.cts',
30
+ ];
31
+ /** File extensions this extractor handles */
32
+ const FILE_EXTENSIONS = [
33
+ '.ts',
34
+ '.tsx',
35
+ '.js',
36
+ '.jsx',
37
+ '.mjs',
38
+ '.cjs',
39
+ '.mts',
40
+ '.cts',
41
+ ];
42
+ /** Pattern matching line comment frontmatter start: // --- */
43
+ const LINE_COMMENT_START = /^[ \t]*\/\/\s*---\s*$/;
44
+ /** Pattern matching line comment frontmatter end: // --- */
45
+ const LINE_COMMENT_END = /^[ \t]*\/\/\s*---\s*$/;
46
+ /** Pattern matching line comment content: // <content> */
47
+ const LINE_COMMENT_CONTENT = /^[ \t]*\/\/\s?(.*)$/;
48
+ /** Pattern matching block comment frontmatter start: /* --- */
49
+ const BLOCK_COMMENT_START = /^[ \t]*\/\*\s*---\s*$/;
50
+ /** Pattern matching block comment frontmatter end: --- */
51
+ const BLOCK_COMMENT_END = /^[ \t]*---\s*\*\/\s*$/;
52
+ /**
53
+ * Try to extract line comment style frontmatter from the start of the file.
54
+ */
55
+ async function extractLineCommentFrontmatter(lines) {
56
+ if (lines.length < 2)
57
+ return null;
58
+ if (!LINE_COMMENT_START.test(lines[0])) {
59
+ return null;
60
+ }
61
+ const yamlLines = [];
62
+ let endIndex = -1;
63
+ for (let i = 1; i < lines.length; i++) {
64
+ const line = lines[i];
65
+ if (LINE_COMMENT_END.test(line)) {
66
+ endIndex = i;
67
+ break;
68
+ }
69
+ const match = line.match(LINE_COMMENT_CONTENT);
70
+ if (match) {
71
+ yamlLines.push(match[1]);
72
+ }
73
+ else {
74
+ return null;
75
+ }
76
+ }
77
+ if (endIndex === -1) {
78
+ return null;
79
+ }
80
+ const yamlContent = yamlLines.join('\n');
81
+ const metadata = yamlContent.trim()
82
+ ? (await parseYaml(yamlContent)) ?? {}
83
+ : {};
84
+ return { metadata };
85
+ }
86
+ /**
87
+ * Try to extract block comment style frontmatter from the start of the file.
88
+ */
89
+ async function extractBlockCommentFrontmatter(lines) {
90
+ if (lines.length < 2)
91
+ return null;
92
+ if (!BLOCK_COMMENT_START.test(lines[0])) {
93
+ return null;
94
+ }
95
+ const yamlLines = [];
96
+ let endIndex = -1;
97
+ for (let i = 1; i < lines.length; i++) {
98
+ const line = lines[i];
99
+ if (BLOCK_COMMENT_END.test(line)) {
100
+ endIndex = i;
101
+ break;
102
+ }
103
+ yamlLines.push(line);
104
+ }
105
+ if (endIndex === -1) {
106
+ return null;
107
+ }
108
+ const yamlContent = yamlLines.join('\n');
109
+ const metadata = yamlContent.trim()
110
+ ? (await parseYaml(yamlContent)) ?? {}
111
+ : {};
112
+ return { metadata };
113
+ }
114
+ /**
115
+ * Extract frontmatter from file content.
116
+ */
117
+ async function extractFrontmatter(content) {
118
+ const lines = content.split('\n');
119
+ const result = (await extractLineCommentFrontmatter(lines)) ??
120
+ (await extractBlockCommentFrontmatter(lines));
121
+ if (!result) {
122
+ return null;
123
+ }
124
+ return result.metadata;
125
+ }
126
+ /**
127
+ * Check if metadata has valid required fields (id and title as strings).
128
+ */
129
+ function hasValidMetadata(metadata) {
130
+ return (typeof metadata.id === 'string' &&
131
+ metadata.id.length > 0 &&
132
+ typeof metadata.title === 'string' &&
133
+ metadata.title.length > 0);
134
+ }
135
+ /**
136
+ * Strip npm scope from package name.
137
+ * @example "@examples/foo" -> "foo"
138
+ * @example "my-package" -> "my-package"
139
+ */
140
+ function stripScope(name) {
141
+ if (name.startsWith('@')) {
142
+ const slashIndex = name.indexOf('/');
143
+ if (slashIndex !== -1) {
144
+ return name.slice(slashIndex + 1);
145
+ }
146
+ }
147
+ return name;
148
+ }
149
+ /**
150
+ * Recursively extract all file paths from exports field.
151
+ * Handles string, object with conditions, and nested export maps.
152
+ */
153
+ function extractExportPaths(exports) {
154
+ if (!exports) {
155
+ return [];
156
+ }
157
+ if (typeof exports === 'string') {
158
+ return [exports];
159
+ }
160
+ if (typeof exports === 'object') {
161
+ const paths = [];
162
+ for (const value of Object.values(exports)) {
163
+ paths.push(...extractExportPaths(value));
164
+ }
165
+ return paths;
166
+ }
167
+ return [];
168
+ }
169
+ /**
170
+ * Check if a file exists.
171
+ */
172
+ async function fileExists(filePath) {
173
+ try {
174
+ const stat = await fs.stat(filePath);
175
+ return stat.isFile();
176
+ }
177
+ catch {
178
+ return false;
179
+ }
180
+ }
181
+ /**
182
+ * Read and parse a package.json file.
183
+ * Returns the parsed package, a parse error, or null if the file can't be read.
184
+ */
185
+ async function readPackageJson(packageJsonPath) {
186
+ let content;
187
+ try {
188
+ content = await fs.readFile(packageJsonPath, 'utf-8');
189
+ }
190
+ catch {
191
+ return null;
192
+ }
193
+ try {
194
+ return { pkg: (await parseJson(content, packageJsonPath)) };
195
+ }
196
+ catch (e) {
197
+ return {
198
+ error: `Failed to parse package.json: ${e.message}`,
199
+ };
200
+ }
201
+ }
202
+ /**
203
+ * Strip the functional-examples key from package.json content for output.
204
+ */
205
+ function stripFunctionalExamplesKey(packageJsonContent) {
206
+ try {
207
+ const pkg = JSON.parse(packageJsonContent);
208
+ delete pkg['functional-examples'];
209
+ return JSON.stringify(pkg, null, 2);
210
+ }
211
+ catch {
212
+ return packageJsonContent;
213
+ }
214
+ }
215
+ /**
216
+ * Use dependency-tree to trace imports from an entry file.
217
+ * Returns absolute paths of all traced dependencies within the example directory.
218
+ */
219
+ function traceDependencies(entryPath, exampleDir) {
220
+ try {
221
+ const tree = dependencyTree({
222
+ filename: entryPath,
223
+ directory: exampleDir,
224
+ nodeModulesConfig: {
225
+ // Don't trace into node_modules
226
+ entry: 'module',
227
+ },
228
+ });
229
+ // Flatten the dependency tree to get all unique file paths
230
+ // Only include files within the example directory
231
+ const files = new Set();
232
+ function collectFiles(node) {
233
+ if (typeof node === 'string') {
234
+ // Only add files within the example directory
235
+ if (node.startsWith(exampleDir) && !node.includes('node_modules')) {
236
+ files.add(node);
237
+ }
238
+ return;
239
+ }
240
+ for (const [filePath, deps] of Object.entries(node)) {
241
+ // Only add files within the example directory
242
+ if (filePath &&
243
+ typeof filePath === 'string' &&
244
+ filePath.startsWith(exampleDir) &&
245
+ !filePath.includes('node_modules')) {
246
+ files.add(filePath);
247
+ }
248
+ if (deps) {
249
+ collectFiles(deps);
250
+ }
251
+ }
252
+ }
253
+ collectFiles(tree);
254
+ return Array.from(files);
255
+ }
256
+ catch {
257
+ // If dependency tracing fails, just return the entry file
258
+ return [entryPath];
259
+ }
260
+ }
261
+ /**
262
+ * Collect files for a multi-file package example.
263
+ */
264
+ async function collectPackageFiles(exampleDir, pkg, options) {
265
+ const collectedFiles = new Set();
266
+ const packageJsonPath = path.join(exampleDir, 'package.json');
267
+ // Always include package.json
268
+ collectedFiles.add(packageJsonPath);
269
+ // Always include README.md if it exists
270
+ for (const readmeName of ['README.md', 'README', 'readme.md']) {
271
+ const readmePath = path.join(exampleDir, readmeName);
272
+ if (await fileExists(readmePath)) {
273
+ collectedFiles.add(readmePath);
274
+ break;
275
+ }
276
+ }
277
+ // Collect entry points to trace
278
+ const entryPoints = [];
279
+ // Add main field
280
+ if (pkg.main) {
281
+ const mainPath = path.resolve(exampleDir, pkg.main);
282
+ if (await fileExists(mainPath)) {
283
+ entryPoints.push(mainPath);
284
+ }
285
+ }
286
+ // Add module field
287
+ if (pkg.module) {
288
+ const modulePath = path.resolve(exampleDir, pkg.module);
289
+ if (await fileExists(modulePath)) {
290
+ entryPoints.push(modulePath);
291
+ }
292
+ }
293
+ // Add types field
294
+ if (pkg.types) {
295
+ const typesPath = path.resolve(exampleDir, pkg.types);
296
+ if (await fileExists(typesPath)) {
297
+ entryPoints.push(typesPath);
298
+ }
299
+ }
300
+ // Add exports field paths
301
+ if (pkg.exports) {
302
+ const exportPaths = extractExportPaths(pkg.exports);
303
+ for (const exportPath of exportPaths) {
304
+ if (exportPath.startsWith('.')) {
305
+ const resolvedPath = path.resolve(exampleDir, exportPath);
306
+ if (await fileExists(resolvedPath)) {
307
+ entryPoints.push(resolvedPath);
308
+ }
309
+ }
310
+ }
311
+ }
312
+ // Trace dependencies from all entry points
313
+ for (const entryPath of entryPoints) {
314
+ const tracedFiles = traceDependencies(entryPath, exampleDir);
315
+ for (const file of tracedFiles) {
316
+ collectedFiles.add(file);
317
+ }
318
+ }
319
+ // Include files from files array using fast-glob
320
+ if (pkg.files && pkg.files.length > 0) {
321
+ try {
322
+ const excludePatterns = [
323
+ ...DEFAULT_EXCLUDE_PATTERNS,
324
+ ...(options.exclude ?? []),
325
+ ];
326
+ const filesFromGlob = await glob(pkg.files, {
327
+ cwd: exampleDir,
328
+ absolute: true,
329
+ ignore: excludePatterns,
330
+ onlyFiles: true,
331
+ });
332
+ for (const file of filesFromGlob) {
333
+ collectedFiles.add(file);
334
+ }
335
+ }
336
+ catch {
337
+ // Ignore glob errors
338
+ }
339
+ }
340
+ // Check if we have any files besides package.json and README
341
+ const sourceFiles = Array.from(collectedFiles).filter((f) => !f.endsWith('package.json') && !f.toLowerCase().includes('readme'));
342
+ if (sourceFiles.length === 0 &&
343
+ entryPoints.length === 0 &&
344
+ (!pkg.files || pkg.files.length === 0)) {
345
+ return {
346
+ files: [],
347
+ error: 'No files could be determined for example. Add main, module, exports, or files field to package.json.',
348
+ };
349
+ }
350
+ return { files: Array.from(collectedFiles) };
351
+ }
352
+ /**
353
+ * Extract metadata from a package.json file per the design doc.
354
+ */
355
+ function extractPackageMetadata(pkg) {
356
+ // name field is required
357
+ if (!pkg.name || typeof pkg.name !== 'string') {
358
+ return null;
359
+ }
360
+ const functionalExamples = pkg['functional-examples'] ?? {};
361
+ const { title: feTitle, ...restFunctionalExamples } = functionalExamples;
362
+ // Strip scope from name for id
363
+ const id = stripScope(pkg.name);
364
+ // Title: functional-examples.title overrides, fallback to name
365
+ const title = typeof feTitle === 'string' ? feTitle : id;
366
+ // Description: direct from package.json
367
+ const description = typeof pkg.description === 'string' ? pkg.description : undefined;
368
+ // Tags: from keywords array
369
+ const tags = Array.isArray(pkg.keywords)
370
+ ? pkg.keywords.filter((k) => typeof k === 'string')
371
+ : undefined;
372
+ // Metadata: spread remaining functional-examples fields
373
+ const metadata = { ...restFunctionalExamples };
374
+ return {
375
+ id,
376
+ title,
377
+ description,
378
+ tags,
379
+ metadata,
380
+ };
381
+ }
382
+ /**
383
+ * Create a JavaScript/TypeScript extractor.
384
+ *
385
+ * This extractor:
386
+ * - Receives pre-filtered candidates (files and directories)
387
+ * - For directories with package.json: treats as multi-file package example
388
+ * - For files with frontmatter: treats as single-file example
389
+ * - Extracts metadata from package.json or frontmatter
390
+ * - Loads raw content into ExampleFile
391
+ * - Respects exclude patterns (default: node_modules, .git, dist, build)
392
+ * - Tracks claimed files for conflict detection
393
+ */
394
+ export function createJavaScriptExtractor() {
395
+ async function tryExtractFromFile(absolutePath, rootPath) {
396
+ let content;
397
+ try {
398
+ content = await fs.readFile(absolutePath, 'utf-8');
399
+ }
400
+ catch {
401
+ return null;
402
+ }
403
+ const metadata = await extractFrontmatter(content);
404
+ if (!metadata || !hasValidMetadata(metadata)) {
405
+ return null;
406
+ }
407
+ const { id, title, description, ...restMetadata } = metadata;
408
+ const relativePath = path.relative(rootPath, absolutePath);
409
+ return {
410
+ id,
411
+ title,
412
+ description: typeof description === 'string' ? description : undefined,
413
+ rootPath: absolutePath,
414
+ files: [{ absolutePath, relativePath, raw: content }],
415
+ metadata: restMetadata,
416
+ extractorName: EXTRACTOR_NAME,
417
+ };
418
+ }
419
+ async function tryExtractFromPackageJson(packageJsonPath, options) {
420
+ const exampleDir = path.dirname(packageJsonPath);
421
+ const readResult = await readPackageJson(packageJsonPath);
422
+ if (!readResult) {
423
+ return null;
424
+ }
425
+ if ('error' in readResult) {
426
+ return {
427
+ error: {
428
+ path: packageJsonPath,
429
+ message: readResult.error,
430
+ },
431
+ };
432
+ }
433
+ const pkg = readResult.pkg;
434
+ const extracted = extractPackageMetadata(pkg);
435
+ if (!extracted) {
436
+ // No valid name field - not a valid package example
437
+ return null;
438
+ }
439
+ const { id, title, description, tags, metadata } = extracted;
440
+ // Collect files for this package example
441
+ const { files: filePaths, error: collectError } = await collectPackageFiles(exampleDir, pkg, options);
442
+ if (collectError) {
443
+ return {
444
+ error: {
445
+ path: packageJsonPath,
446
+ message: collectError,
447
+ },
448
+ };
449
+ }
450
+ // Build ExampleFile array
451
+ const exampleFiles = [];
452
+ for (const filePath of filePaths) {
453
+ try {
454
+ let raw = await fs.readFile(filePath, 'utf-8');
455
+ // Strip functional-examples key from package.json
456
+ if (filePath.endsWith('package.json')) {
457
+ raw = stripFunctionalExamplesKey(raw);
458
+ }
459
+ const relativePath = path.relative(exampleDir, filePath);
460
+ exampleFiles.push({
461
+ absolutePath: filePath,
462
+ relativePath,
463
+ raw,
464
+ });
465
+ }
466
+ catch {
467
+ // Skip files that can't be read
468
+ }
469
+ }
470
+ // Include tags in metadata if present
471
+ const finalMetadata = { ...metadata };
472
+ if (tags && tags.length > 0) {
473
+ finalMetadata.tags = tags;
474
+ }
475
+ const example = {
476
+ id,
477
+ title,
478
+ description,
479
+ rootPath: exampleDir,
480
+ files: exampleFiles,
481
+ metadata: finalMetadata,
482
+ extractorName: EXTRACTOR_NAME,
483
+ };
484
+ return { example, files: filePaths };
485
+ }
486
+ return {
487
+ name: EXTRACTOR_NAME,
488
+ async extract(candidates, options) {
489
+ const examples = [];
490
+ const claimedFiles = new Set();
491
+ const errors = [];
492
+ for (const candidate of candidates) {
493
+ if (options.signal?.aborted)
494
+ break;
495
+ const fullPath = path.join(candidate.parentPath, candidate.name);
496
+ // Handle file candidates
497
+ if (candidate.isFile()) {
498
+ // Check if it's a package.json file - resolve to parent directory
499
+ if (candidate.name === 'package.json') {
500
+ const result = await tryExtractFromPackageJson(fullPath, options);
501
+ if (result) {
502
+ if ('error' in result) {
503
+ errors.push(result.error);
504
+ }
505
+ else {
506
+ examples.push(result.example);
507
+ for (const file of result.files) {
508
+ claimedFiles.add(file);
509
+ }
510
+ }
511
+ }
512
+ continue;
513
+ }
514
+ // Handle regular JS/TS files with frontmatter
515
+ const ext = path.extname(candidate.name);
516
+ if (!FILE_EXTENSIONS.includes(ext))
517
+ continue;
518
+ const example = await tryExtractFromFile(fullPath, options.rootPath);
519
+ if (example) {
520
+ examples.push(example);
521
+ claimedFiles.add(fullPath);
522
+ }
523
+ continue;
524
+ }
525
+ // Handle directory candidates
526
+ if (candidate.isDirectory()) {
527
+ // Skip excluded directories (default ones)
528
+ if (DEFAULT_EXCLUDED_DIRS.has(candidate.name)) {
529
+ continue;
530
+ }
531
+ // Skip directories matching custom exclude patterns
532
+ const excludePatterns = options.exclude ?? [];
533
+ const relativeDirPath = path.relative(options.rootPath, fullPath);
534
+ const pathsToCheck = [
535
+ candidate.name,
536
+ relativeDirPath,
537
+ `${relativeDirPath}/`,
538
+ `${candidate.name}/`,
539
+ ];
540
+ const matchers = await Promise.all(excludePatterns.map((pattern) => createMatcher(pattern)));
541
+ const isExcluded = matchers.some((matcher) => {
542
+ return pathsToCheck.some((p) => matcher(p));
543
+ });
544
+ if (isExcluded) {
545
+ continue;
546
+ }
547
+ // Check for package.json in the directory
548
+ const packageJsonPath = path.join(fullPath, 'package.json');
549
+ if (await fileExists(packageJsonPath)) {
550
+ const result = await tryExtractFromPackageJson(packageJsonPath, options);
551
+ if (result) {
552
+ if ('error' in result) {
553
+ errors.push(result.error);
554
+ }
555
+ else {
556
+ examples.push(result.example);
557
+ for (const file of result.files) {
558
+ claimedFiles.add(file);
559
+ }
560
+ }
561
+ }
562
+ // If package.json was found, don't also scan for single-file examples
563
+ continue;
564
+ }
565
+ // No package.json - fall back to scanning for single-file examples with frontmatter
566
+ const fileExcludePatterns = [
567
+ ...DEFAULT_EXCLUDE_PATTERNS,
568
+ ...(options.exclude ?? []),
569
+ ];
570
+ const files = await glob(FILE_PATTERNS, {
571
+ cwd: fullPath,
572
+ absolute: true,
573
+ ignore: fileExcludePatterns,
574
+ onlyFiles: true,
575
+ });
576
+ for (const filePath of files) {
577
+ const example = await tryExtractFromFile(filePath, options.rootPath);
578
+ if (example) {
579
+ examples.push(example);
580
+ claimedFiles.add(filePath);
581
+ }
582
+ }
583
+ }
584
+ }
585
+ return { examples, errors, claimedFiles };
586
+ },
587
+ };
588
+ }
589
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type FileContentsParser } from '@functional-examples/devkit';
2
+ /**
3
+ * Create a FileContentsParser that extracts YAML frontmatter from JavaScript/TypeScript files.
4
+ *
5
+ * Supports two formats:
6
+ * 1. Line comment style:
7
+ * // ---
8
+ * // title: Example
9
+ * // ---
10
+ *
11
+ * 2. Block comment wrapped style:
12
+ * /* ---
13
+ * title: Example
14
+ * --- *\/
15
+ *
16
+ * Frontmatter must be at the very start of the file (line 1).
17
+ * Extracted metadata is merged into context.metadata.
18
+ * The frontmatter block is stripped from context.parsed.
19
+ */
20
+ export declare function createFrontmatterParser(): FileContentsParser;
21
+ //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,6BAA6B,CAAC;AA+HrC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,IAAI,kBAAkB,CAkC5D"}
@@ -0,0 +1,145 @@
1
+ import { parseYaml, } from '@functional-examples/devkit';
2
+ /** Pattern matching line comment frontmatter start: // --- */
3
+ const LINE_COMMENT_START = /^[ \t]*\/\/\s*---\s*$/;
4
+ /** Pattern matching line comment frontmatter end: // --- */
5
+ const LINE_COMMENT_END = /^[ \t]*\/\/\s*---\s*$/;
6
+ /** Pattern matching line comment content: // <content> */
7
+ const LINE_COMMENT_CONTENT = /^[ \t]*\/\/\s?(.*)$/;
8
+ /** Pattern matching block comment frontmatter start: /* --- */
9
+ const BLOCK_COMMENT_START = /^[ \t]*\/\*\s*---\s*$/;
10
+ /** Pattern matching block comment frontmatter end: --- */
11
+ const BLOCK_COMMENT_END = /^[ \t]*---\s*\*\/\s*$/;
12
+ /**
13
+ * Try to extract line comment style frontmatter from the start of the file.
14
+ * Format:
15
+ * // ---
16
+ * // key: value
17
+ * // ---
18
+ */
19
+ async function extractLineCommentFrontmatter(lines) {
20
+ if (lines.length < 2)
21
+ return null;
22
+ // First line must be // ---
23
+ if (!LINE_COMMENT_START.test(lines[0])) {
24
+ return null;
25
+ }
26
+ // Find closing delimiter
27
+ const yamlLines = [];
28
+ let endIndex = -1;
29
+ for (let i = 1; i < lines.length; i++) {
30
+ const line = lines[i];
31
+ // Check for closing delimiter
32
+ if (LINE_COMMENT_END.test(line)) {
33
+ endIndex = i;
34
+ break;
35
+ }
36
+ // Extract content from line comment
37
+ const match = line.match(LINE_COMMENT_CONTENT);
38
+ if (match) {
39
+ yamlLines.push(match[1]);
40
+ }
41
+ else {
42
+ // Non-comment line before closing delimiter - invalid frontmatter
43
+ return null;
44
+ }
45
+ }
46
+ if (endIndex === -1) {
47
+ // No closing delimiter found
48
+ return null;
49
+ }
50
+ const yamlContent = yamlLines.join('\n');
51
+ const metadata = yamlContent.trim()
52
+ ? (await parseYaml(yamlContent)) ?? {}
53
+ : {};
54
+ return {
55
+ metadata,
56
+ linesConsumed: endIndex + 1,
57
+ };
58
+ }
59
+ /**
60
+ * Try to extract block comment style frontmatter from the start of the file.
61
+ * Format:
62
+ * /* ---
63
+ * key: value
64
+ * --- *\/
65
+ */
66
+ async function extractBlockCommentFrontmatter(lines) {
67
+ if (lines.length < 2)
68
+ return null;
69
+ // First line must be /* ---
70
+ if (!BLOCK_COMMENT_START.test(lines[0])) {
71
+ return null;
72
+ }
73
+ // Find closing delimiter
74
+ const yamlLines = [];
75
+ let endIndex = -1;
76
+ for (let i = 1; i < lines.length; i++) {
77
+ const line = lines[i];
78
+ // Check for closing delimiter
79
+ if (BLOCK_COMMENT_END.test(line)) {
80
+ endIndex = i;
81
+ break;
82
+ }
83
+ // Content lines are raw YAML (no prefix stripping needed)
84
+ yamlLines.push(line);
85
+ }
86
+ if (endIndex === -1) {
87
+ // No closing delimiter found
88
+ return null;
89
+ }
90
+ const yamlContent = yamlLines.join('\n');
91
+ const metadata = yamlContent.trim()
92
+ ? (await parseYaml(yamlContent)) ?? {}
93
+ : {};
94
+ return {
95
+ metadata,
96
+ linesConsumed: endIndex + 1,
97
+ };
98
+ }
99
+ /**
100
+ * Create a FileContentsParser that extracts YAML frontmatter from JavaScript/TypeScript files.
101
+ *
102
+ * Supports two formats:
103
+ * 1. Line comment style:
104
+ * // ---
105
+ * // title: Example
106
+ * // ---
107
+ *
108
+ * 2. Block comment wrapped style:
109
+ * /* ---
110
+ * title: Example
111
+ * --- *\/
112
+ *
113
+ * Frontmatter must be at the very start of the file (line 1).
114
+ * Extracted metadata is merged into context.metadata.
115
+ * The frontmatter block is stripped from context.parsed.
116
+ */
117
+ export function createFrontmatterParser() {
118
+ return {
119
+ name: 'javascript-frontmatter-parser',
120
+ async parse(context) {
121
+ const lines = context.parsed.split('\n');
122
+ // Try line comment style first, then block comment style
123
+ const result = (await extractLineCommentFrontmatter(lines)) ??
124
+ (await extractBlockCommentFrontmatter(lines));
125
+ if (!result) {
126
+ // No frontmatter found, return context unchanged
127
+ return context;
128
+ }
129
+ // Strip frontmatter lines from parsed content
130
+ const remainingLines = lines.slice(result.linesConsumed);
131
+ const parsed = remainingLines.join('\n');
132
+ // Merge extracted metadata with existing metadata
133
+ const metadata = {
134
+ ...context.metadata,
135
+ ...result.metadata,
136
+ };
137
+ return {
138
+ ...context,
139
+ parsed,
140
+ metadata,
141
+ };
142
+ },
143
+ };
144
+ }
145
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,GACV,MAAM,6BAA6B,CAAC;AAErC,8DAA8D;AAC9D,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AACnD,4DAA4D;AAC5D,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AACjD,0DAA0D;AAC1D,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAEnD,+DAA+D;AAC/D,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;AACpD,0DAA0D;AAC1D,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AASlD;;;;;;GAMG;AACH,KAAK,UAAU,6BAA6B,CAC1C,KAAe;IAEf,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAElC,4BAA4B;IAC5B,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yBAAyB;IACzB,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,8BAA8B;QAC9B,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,QAAQ,GAAG,CAAC,CAAC;YACb,MAAM;QACR,CAAC;QAED,oCAAoC;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC/C,IAAI,KAAK,EAAE,CAAC;YACV,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,kEAAkE;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,6BAA6B;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE;QACjC,CAAC,CAAE,CAAC,MAAM,SAAS,CAAC,WAAW,CAAC,CAA6B,IAAI,EAAE;QACnE,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,QAAQ;QACR,aAAa,EAAE,QAAQ,GAAG,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,8BAA8B,CAC3C,KAAe;IAEf,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAElC,4BAA4B;IAC5B,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yBAAyB;IACzB,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,8BAA8B;QAC9B,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,QAAQ,GAAG,CAAC,CAAC;YACb,MAAM;QACR,CAAC;QAED,0DAA0D;QAC1D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,6BAA6B;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE;QACjC,CAAC,CAAE,CAAC,MAAM,SAAS,CAAC,WAAW,CAAC,CAA6B,IAAI,EAAE;QACnE,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,QAAQ;QACR,aAAa,EAAE,QAAQ,GAAG,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,IAAI,EAAE,+BAA+B;QAErC,KAAK,CAAC,KAAK,CAAC,OAAyB;YACnC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEzC,yDAAyD;YACzD,MAAM,MAAM,GACV,CAAC,MAAM,6BAA6B,CAAC,KAAK,CAAC,CAAC;gBAC5C,CAAC,MAAM,8BAA8B,CAAC,KAAK,CAAC,CAAC,CAAC;YAEhD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,iDAAiD;gBACjD,OAAO,OAAO,CAAC;YACjB,CAAC;YAED,8CAA8C;YAC9C,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEzC,kDAAkD;YAClD,MAAM,QAAQ,GAAG;gBACf,GAAG,OAAO,CAAC,QAAQ;gBACnB,GAAG,MAAM,CAAC,QAAQ;aACnB,CAAC;YAEF,OAAO;gBACL,GAAG,OAAO;gBACV,MAAM;gBACN,QAAQ;aACT,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { Plugin } from '@functional-examples/devkit';
2
+ export declare const JAVASCRIPT_EXTENSIONS: readonly [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".mts", ".cts"];
3
+ export { createJavaScriptParser } from './parser.js';
4
+ export { createFrontmatterParser } from './frontmatter.js';
5
+ export { createJavaScriptExtractor } from './extractor.js';
6
+ /**
7
+ * Options for the JavaScript plugin.
8
+ */
9
+ export interface JavaScriptPluginOptions {
10
+ /** Skip frontmatter extraction (default: false) */
11
+ skipFrontmatter?: boolean;
12
+ /** Skip region extraction (default: false) */
13
+ skipRegions?: boolean;
14
+ }
15
+ /**
16
+ * Create a JavaScript/TypeScript plugin for functional-examples.
17
+ *
18
+ * This plugin:
19
+ * - Handles .js, .jsx, .mjs, .cjs, .ts, .tsx, .mts, .cts files
20
+ * - Extracts YAML frontmatter from line/block comments
21
+ * - Extracts code regions from #region/#endregion markers
22
+ * - Provides a single-file extractor for discovering examples
23
+ *
24
+ * The combined parser runs frontmatter parsing FIRST, then region parsing.
25
+ * This ensures frontmatter is stripped before region markers are processed.
26
+ *
27
+ * @param options - Optional plugin configuration
28
+ * @returns A configured JavaScript plugin
29
+ */
30
+ export declare function createJavaScriptPlugin(options?: JavaScriptPluginOptions): Plugin;
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAIP,MAAM,6BAA6B,CAAC;AAKrC,eAAO,MAAM,qBAAqB,yEASxB,CAAC;AAEX,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,mDAAmD;IACnD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA6DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CAsCR"}
package/dist/index.js ADDED
@@ -0,0 +1,120 @@
1
+ import { createJavaScriptParser } from './parser.js';
2
+ import { createFrontmatterParser } from './frontmatter.js';
3
+ import { createJavaScriptExtractor } from './extractor.js';
4
+ export const JAVASCRIPT_EXTENSIONS = [
5
+ '.js',
6
+ '.jsx',
7
+ '.mjs',
8
+ '.cjs',
9
+ '.ts',
10
+ '.tsx',
11
+ '.mts',
12
+ '.cts',
13
+ ];
14
+ export { createJavaScriptParser } from './parser.js';
15
+ export { createFrontmatterParser } from './frontmatter.js';
16
+ export { createJavaScriptExtractor } from './extractor.js';
17
+ /**
18
+ * JSON Schema for JavaScript plugin options.
19
+ */
20
+ const OPTIONS_SCHEMA = JSON.stringify({
21
+ type: 'object',
22
+ properties: {
23
+ skipFrontmatter: {
24
+ type: 'boolean',
25
+ description: 'Skip frontmatter parsing',
26
+ },
27
+ skipRegions: {
28
+ type: 'boolean',
29
+ description: 'Skip region parsing',
30
+ },
31
+ },
32
+ });
33
+ /**
34
+ * JSON Schema for metadata this plugin expects.
35
+ */
36
+ const METADATA_SCHEMA = JSON.stringify({
37
+ type: 'object',
38
+ properties: {
39
+ id: {
40
+ type: 'string',
41
+ description: 'Unique example identifier',
42
+ },
43
+ title: {
44
+ type: 'string',
45
+ description: 'Example title',
46
+ },
47
+ description: {
48
+ type: 'string',
49
+ description: 'Example description',
50
+ },
51
+ },
52
+ required: ['id', 'title'],
53
+ });
54
+ /**
55
+ * Validate metadata extracted by this plugin.
56
+ * Note: id and title are validated by the extractor and are top-level example fields,
57
+ * not part of the metadata object passed here.
58
+ */
59
+ function validateMetadata(metadata) {
60
+ const errors = [];
61
+ // Validate tags array if present
62
+ if (metadata.tags !== undefined) {
63
+ if (!Array.isArray(metadata.tags)) {
64
+ errors.push({ path: 'tags', message: 'must be an array' });
65
+ }
66
+ else if (!metadata.tags.every((t) => typeof t === 'string')) {
67
+ errors.push({ path: 'tags', message: 'must be an array of strings' });
68
+ }
69
+ }
70
+ return { success: errors.length === 0, errors };
71
+ }
72
+ /**
73
+ * Create a JavaScript/TypeScript plugin for functional-examples.
74
+ *
75
+ * This plugin:
76
+ * - Handles .js, .jsx, .mjs, .cjs, .ts, .tsx, .mts, .cts files
77
+ * - Extracts YAML frontmatter from line/block comments
78
+ * - Extracts code regions from #region/#endregion markers
79
+ * - Provides a single-file extractor for discovering examples
80
+ *
81
+ * The combined parser runs frontmatter parsing FIRST, then region parsing.
82
+ * This ensures frontmatter is stripped before region markers are processed.
83
+ *
84
+ * @param options - Optional plugin configuration
85
+ * @returns A configured JavaScript plugin
86
+ */
87
+ export function createJavaScriptPlugin(options) {
88
+ const { skipFrontmatter = false, skipRegions = false } = options ?? {};
89
+ // Create a combined parser that chains frontmatter → regions
90
+ const combinedParser = {
91
+ name: 'javascript-combined-parser',
92
+ async parse(context) {
93
+ let result = context;
94
+ // Run frontmatter parser first (extracts metadata, strips frontmatter)
95
+ if (!skipFrontmatter) {
96
+ result = await createFrontmatterParser().parse(result);
97
+ }
98
+ // Run region parser second (extracts hunks, strips markers)
99
+ if (!skipRegions) {
100
+ result = createJavaScriptParser().parse(result);
101
+ }
102
+ return result;
103
+ },
104
+ };
105
+ return {
106
+ name: 'javascript',
107
+ extensions: [...JAVASCRIPT_EXTENSIONS],
108
+ extractor: createJavaScriptExtractor(),
109
+ fileContentsParser: combinedParser,
110
+ schemas: {
111
+ options: OPTIONS_SCHEMA,
112
+ metadata: METADATA_SCHEMA,
113
+ },
114
+ validators: {
115
+ metadata: validateMetadata,
116
+ },
117
+ _options: options,
118
+ };
119
+ }
120
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { FileContentsParser } from '@functional-examples/devkit';
2
+ /**
3
+ * Create a FileContentsParser for JavaScript/TypeScript files.
4
+ * Handles region extraction and marker stripping.
5
+ */
6
+ export declare function createJavaScriptParser(): FileContentsParser;
7
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,6BAA6B,CAAC;AAcrC;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,kBAAkB,CA2D3D"}
package/dist/parser.js ADDED
@@ -0,0 +1,59 @@
1
+ const LINE_COMMENT_REGION = /^[ \t]*\/\/\s*#region\s+(\S+)\s*$/;
2
+ const LINE_COMMENT_ENDREGION = /^[ \t]*\/\/\s*#endregion(?:\s+(\S+))?\s*$/;
3
+ const BLOCK_COMMENT_REGION = /^[ \t]*\/\*\s*#region\s+(\S+)\s*\*\/\s*$/;
4
+ const BLOCK_COMMENT_ENDREGION = /^[ \t]*\/\*\s*#endregion(?:\s+(\S+))?\s*\*\/\s*$/;
5
+ /**
6
+ * Create a FileContentsParser for JavaScript/TypeScript files.
7
+ * Handles region extraction and marker stripping.
8
+ */
9
+ export function createJavaScriptParser() {
10
+ return {
11
+ name: 'javascript-parser',
12
+ parse(context) {
13
+ const lines = context.parsed.split('\n');
14
+ const hunks = [];
15
+ const outputLines = [];
16
+ const regionStack = [];
17
+ for (let i = 0; i < lines.length; i++) {
18
+ const line = lines[i];
19
+ const lineNum = i + 1;
20
+ // Check for region start
21
+ const startMatch = line.match(LINE_COMMENT_REGION) || line.match(BLOCK_COMMENT_REGION);
22
+ if (startMatch) {
23
+ regionStack.push({
24
+ id: startMatch[1],
25
+ startLine: lineNum,
26
+ lines: [],
27
+ });
28
+ continue; // Don't include marker in output
29
+ }
30
+ // Check for region end
31
+ const endMatch = line.match(LINE_COMMENT_ENDREGION) ||
32
+ line.match(BLOCK_COMMENT_ENDREGION);
33
+ if (endMatch) {
34
+ const current = regionStack.pop();
35
+ if (current) {
36
+ hunks.push({
37
+ id: current.id,
38
+ content: current.lines.join('\n'),
39
+ startLine: current.startLine,
40
+ endLine: lineNum,
41
+ });
42
+ }
43
+ continue; // Don't include marker in output
44
+ }
45
+ // Regular line - add to output and any active regions
46
+ outputLines.push(line);
47
+ for (const region of regionStack) {
48
+ region.lines.push(line);
49
+ }
50
+ }
51
+ return {
52
+ ...context,
53
+ parsed: outputLines.join('\n'),
54
+ hunks,
55
+ };
56
+ },
57
+ };
58
+ }
59
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAMA,MAAM,mBAAmB,GAAG,mCAAmC,CAAC;AAChE,MAAM,sBAAsB,GAAG,2CAA2C,CAAC;AAC3E,MAAM,oBAAoB,GAAG,0CAA0C,CAAC;AACxE,MAAM,uBAAuB,GAC3B,kDAAkD,CAAC;AAQrD;;;GAGG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,EAAE,mBAAmB;QAEzB,KAAK,CAAC,OAAyB;YAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,KAAK,GAAmB,EAAE,CAAC;YACjC,MAAM,WAAW,GAAa,EAAE,CAAC;YACjC,MAAM,WAAW,GAAkB,EAAE,CAAC;YAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;gBAEtB,yBAAyB;gBACzB,MAAM,UAAU,GACd,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;gBAEtE,IAAI,UAAU,EAAE,CAAC;oBACf,WAAW,CAAC,IAAI,CAAC;wBACf,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;wBACjB,SAAS,EAAE,OAAO;wBAClB,KAAK,EAAE,EAAE;qBACV,CAAC,CAAC;oBACH,SAAS,CAAC,iCAAiC;gBAC7C,CAAC;gBAED,uBAAuB;gBACvB,MAAM,QAAQ,GACZ,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC;oBAClC,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;gBAEtC,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;oBAClC,IAAI,OAAO,EAAE,CAAC;wBACZ,KAAK,CAAC,IAAI,CAAC;4BACT,EAAE,EAAE,OAAO,CAAC,EAAE;4BACd,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;4BACjC,SAAS,EAAE,OAAO,CAAC,SAAS;4BAC5B,OAAO,EAAE,OAAO;yBACjB,CAAC,CAAC;oBACL,CAAC;oBACD,SAAS,CAAC,iCAAiC;gBAC7C,CAAC;gBAED,sDAAsD;gBACtD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvB,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;oBACjC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;YAED,OAAO;gBACL,GAAG,OAAO;gBACV,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC9B,KAAK;aACN,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@functional-examples/javascript",
3
+ "version": "0.0.0-alpha.1",
4
+ "description": "JavaScript/TypeScript plugin for functional-examples",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "devDependencies": {
22
+ "typescript": "^5.7.2",
23
+ "vitest": "^1.3.1",
24
+ "@functional-examples/devkit": "0.0.0-alpha.1"
25
+ },
26
+ "dependencies": {
27
+ "dependency-tree": "^11.0.0",
28
+ "picomatch": "^4.0.3",
29
+ "tinyglobby": "^0.2.15",
30
+ "yaml": "^2.7.1",
31
+ "@functional-examples/devkit": "0.0.0-alpha.1"
32
+ },
33
+ "license": "MIT",
34
+ "author": {
35
+ "name": "Craigory Coppola",
36
+ "url": "https://craigory.dev"
37
+ },
38
+ "homepage": "https://craigory.dev/functional-examples",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/AgentEnder/functional-examples.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/AgentEnder/functional-examples/issues"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc -p tsconfig.lib.json",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest"
50
+ }
51
+ }