lens-content-processor 0.1.0 → 0.2.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 (65) hide show
  1. package/dist/cli.js +5 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/flattener/index.js +25 -7
  4. package/dist/flattener/index.js.map +1 -1
  5. package/dist/index.js +23 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/parser/learning-outcome.js +16 -1
  8. package/dist/parser/learning-outcome.js.map +1 -1
  9. package/dist/parser/lens.js +18 -0
  10. package/dist/parser/lens.js.map +1 -1
  11. package/dist/parser/wikilink.d.ts +28 -0
  12. package/dist/parser/wikilink.js +154 -0
  13. package/dist/parser/wikilink.js.map +1 -1
  14. package/package.json +1 -1
  15. package/dist/bundler/article.test.d.ts +0 -1
  16. package/dist/bundler/article.test.js +0 -212
  17. package/dist/bundler/article.test.js.map +0 -1
  18. package/dist/bundler/video.test.d.ts +0 -1
  19. package/dist/bundler/video.test.js +0 -95
  20. package/dist/bundler/video.test.js.map +0 -1
  21. package/dist/cli.test.d.ts +0 -1
  22. package/dist/cli.test.js +0 -45
  23. package/dist/cli.test.js.map +0 -1
  24. package/dist/flattener/index.test.d.ts +0 -1
  25. package/dist/flattener/index.test.js +0 -547
  26. package/dist/flattener/index.test.js.map +0 -1
  27. package/dist/fs/read-vault.test.d.ts +0 -1
  28. package/dist/fs/read-vault.test.js +0 -37
  29. package/dist/fs/read-vault.test.js.map +0 -1
  30. package/dist/parser/course.test.d.ts +0 -1
  31. package/dist/parser/course.test.js +0 -117
  32. package/dist/parser/course.test.js.map +0 -1
  33. package/dist/parser/frontmatter.test.d.ts +0 -1
  34. package/dist/parser/frontmatter.test.js +0 -54
  35. package/dist/parser/frontmatter.test.js.map +0 -1
  36. package/dist/parser/learning-outcome.test.d.ts +0 -1
  37. package/dist/parser/learning-outcome.test.js +0 -75
  38. package/dist/parser/learning-outcome.test.js.map +0 -1
  39. package/dist/parser/lens.test.d.ts +0 -1
  40. package/dist/parser/lens.test.js +0 -453
  41. package/dist/parser/lens.test.js.map +0 -1
  42. package/dist/parser/module.test.d.ts +0 -1
  43. package/dist/parser/module.test.js +0 -99
  44. package/dist/parser/module.test.js.map +0 -1
  45. package/dist/parser/sections.test.d.ts +0 -1
  46. package/dist/parser/sections.test.js +0 -297
  47. package/dist/parser/sections.test.js.map +0 -1
  48. package/dist/parser/wikilink.test.d.ts +0 -1
  49. package/dist/parser/wikilink.test.js +0 -76
  50. package/dist/parser/wikilink.test.js.map +0 -1
  51. package/dist/validator/field-typos.test.d.ts +0 -1
  52. package/dist/validator/field-typos.test.js +0 -41
  53. package/dist/validator/field-typos.test.js.map +0 -1
  54. package/dist/validator/field-values.test.d.ts +0 -1
  55. package/dist/validator/field-values.test.js +0 -45
  56. package/dist/validator/field-values.test.js.map +0 -1
  57. package/dist/validator/segment-fields.test.d.ts +0 -1
  58. package/dist/validator/segment-fields.test.js +0 -73
  59. package/dist/validator/segment-fields.test.js.map +0 -1
  60. package/dist/validator/standalone.test.d.ts +0 -1
  61. package/dist/validator/standalone.test.js +0 -190
  62. package/dist/validator/standalone.test.js.map +0 -1
  63. package/dist/validator/uuid.test.d.ts +0 -1
  64. package/dist/validator/uuid.test.js +0 -229
  65. package/dist/validator/uuid.test.js.map +0 -1
@@ -16,6 +16,14 @@ export function resolveWikilinkPath(linkPath, sourceFile) {
16
16
  // Use Node's path module - normalize handles .. and . segments
17
17
  return normalize(join(dirname(sourceFile), linkPath)).replace(/\\/g, '/');
18
18
  }
19
+ /**
20
+ * Check if a wikilink path contains a relative path indicator (slash).
21
+ * We always expect source:: paths to be relative (e.g., ../Lenses/foo.md),
22
+ * never just a filename (e.g., foo.md).
23
+ */
24
+ export function hasRelativePath(path) {
25
+ return path.includes('/');
26
+ }
19
27
  /**
20
28
  * Find a file in the files Map, trying with and without .md extension.
21
29
  * Returns the key that exists in the map, or null if not found.
@@ -32,4 +40,150 @@ export function findFileWithExtension(path, files) {
32
40
  }
33
41
  return null;
34
42
  }
43
+ /**
44
+ * Calculate the Levenshtein (edit) distance between two strings.
45
+ */
46
+ function levenshtein(a, b) {
47
+ const matrix = [];
48
+ for (let i = 0; i <= b.length; i++) {
49
+ matrix[i] = [i];
50
+ }
51
+ for (let j = 0; j <= a.length; j++) {
52
+ matrix[0][j] = j;
53
+ }
54
+ for (let i = 1; i <= b.length; i++) {
55
+ for (let j = 1; j <= a.length; j++) {
56
+ if (b[i - 1] === a[j - 1]) {
57
+ matrix[i][j] = matrix[i - 1][j - 1];
58
+ }
59
+ else {
60
+ matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
61
+ }
62
+ }
63
+ }
64
+ return matrix[b.length][a.length];
65
+ }
66
+ /**
67
+ * Extract the filename (without extension) from a path.
68
+ */
69
+ function getFilename(path) {
70
+ const parts = path.split('/');
71
+ const filename = parts[parts.length - 1];
72
+ return filename.replace(/\.md$/, '');
73
+ }
74
+ /**
75
+ * Extract the directory from a path.
76
+ */
77
+ function getDirectory(path) {
78
+ const parts = path.split('/');
79
+ if (parts.length > 1) {
80
+ return parts.slice(0, -1).join('/');
81
+ }
82
+ return '';
83
+ }
84
+ /**
85
+ * Check if a directory matches the expected directory.
86
+ * Handles both exact match and nested directories (e.g., "foo/Lenses" matches "Lenses").
87
+ */
88
+ function isInExpectedDir(fileDir, expectedDir) {
89
+ const fileDirLower = fileDir.toLowerCase();
90
+ const expectedDirLower = expectedDir.toLowerCase();
91
+ return fileDirLower === expectedDirLower ||
92
+ fileDirLower.endsWith('/' + expectedDirLower) ||
93
+ fileDirLower.startsWith(expectedDirLower + '/');
94
+ }
95
+ /**
96
+ * Find files with similar names to the not-found path.
97
+ *
98
+ * @param notFoundPath - The path that was not found
99
+ * @param files - Map of all files
100
+ * @param expectedDir - Optional directory to filter by (e.g., "Lenses", "articles")
101
+ * When provided, ONLY matches from this directory are returned.
102
+ * @param maxDistance - Maximum Levenshtein distance to consider (default: 3)
103
+ * @returns Array of similar file paths, sorted by relevance
104
+ */
105
+ export function findSimilarFiles(notFoundPath, files, expectedDir, maxDistance = 3) {
106
+ const searchFilename = getFilename(notFoundPath).toLowerCase();
107
+ const searchDir = getDirectory(notFoundPath).toLowerCase();
108
+ const matchesInExpectedDir = [];
109
+ const matchesInSameDir = [];
110
+ const otherMatches = [];
111
+ for (const filePath of files.keys()) {
112
+ const fileFilename = getFilename(filePath).toLowerCase();
113
+ const fileDir = getDirectory(filePath);
114
+ // Calculate distance on filename
115
+ const distance = levenshtein(searchFilename, fileFilename);
116
+ if (distance <= maxDistance) {
117
+ const match = { path: filePath, distance };
118
+ // Categorize by directory
119
+ if (expectedDir && isInExpectedDir(fileDir, expectedDir)) {
120
+ matchesInExpectedDir.push(match);
121
+ }
122
+ else if (fileDir.toLowerCase() === searchDir) {
123
+ matchesInSameDir.push(match);
124
+ }
125
+ else {
126
+ otherMatches.push(match);
127
+ }
128
+ }
129
+ }
130
+ // Sort each category by distance
131
+ const sortByDistance = (a, b) => a.distance - b.distance;
132
+ matchesInExpectedDir.sort(sortByDistance);
133
+ matchesInSameDir.sort(sortByDistance);
134
+ otherMatches.sort(sortByDistance);
135
+ // When expectedDir is provided, ONLY return matches from that directory
136
+ // This prevents suggesting files from wrong directories
137
+ if (expectedDir && matchesInExpectedDir.length > 0) {
138
+ return matchesInExpectedDir.slice(0, 3).map(m => m.path);
139
+ }
140
+ // If no expected dir or no matches there, try same directory
141
+ if (matchesInSameDir.length > 0) {
142
+ return matchesInSameDir.slice(0, 3).map(m => m.path);
143
+ }
144
+ // If expectedDir was provided but no matches found, don't suggest from wrong directories
145
+ if (expectedDir) {
146
+ return [];
147
+ }
148
+ // Fallback to any matches (only when no expected directory specified)
149
+ return otherMatches.slice(0, 3).map(m => m.path);
150
+ }
151
+ /**
152
+ * Compute relative path from source file to target file.
153
+ * E.g., from "Learning Outcomes/lo1.md" to "Lenses/lens.md" -> "../Lenses/lens.md"
154
+ */
155
+ function computeRelativePath(targetPath, sourceFile) {
156
+ const sourceDir = dirname(sourceFile);
157
+ const sourceParts = sourceDir ? sourceDir.split('/') : [];
158
+ const targetParts = targetPath.split('/');
159
+ // Find common prefix
160
+ let commonLength = 0;
161
+ while (commonLength < sourceParts.length &&
162
+ commonLength < targetParts.length - 1 &&
163
+ sourceParts[commonLength] === targetParts[commonLength]) {
164
+ commonLength++;
165
+ }
166
+ // Build relative path
167
+ const upCount = sourceParts.length - commonLength;
168
+ const ups = Array(upCount).fill('..');
169
+ const remaining = targetParts.slice(commonLength);
170
+ return [...ups, ...remaining].join('/');
171
+ }
172
+ /**
173
+ * Format a "Did you mean...?" suggestion from similar files.
174
+ *
175
+ * @param similarFiles - Array of absolute paths (from vault root)
176
+ * @param sourceFile - The file where the error occurred (to compute relative paths)
177
+ */
178
+ export function formatSuggestion(similarFiles, sourceFile) {
179
+ if (similarFiles.length === 0) {
180
+ return undefined;
181
+ }
182
+ // Convert absolute paths to relative paths from source file
183
+ const relativePaths = similarFiles.map(f => computeRelativePath(f, sourceFile));
184
+ if (relativePaths.length === 1) {
185
+ return `Did you mean '${relativePaths[0]}'?`;
186
+ }
187
+ return `Did you mean one of: ${relativePaths.map(f => `'${f}'`).join(', ')}?`;
188
+ }
35
189
  //# sourceMappingURL=wikilink.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wikilink.js","sourceRoot":"","sources":["../../src/parser/wikilink.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAQhD,qEAAqE;AACrE,MAAM,gBAAgB,GAAG,sCAAsC,CAAC;AAEhE,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;QACrB,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE;QACzB,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,UAAkB;IACtE,+DAA+D;IAC/D,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,KAA0B;IAC5E,wBAAwB;IACxB,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2BAA2B;IAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC;IAC5B,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"wikilink.js","sourceRoot":"","sources":["../../src/parser/wikilink.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lens-content-processor",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Parser and validator for Lens educational content (Markdown modules, lenses, learning outcomes)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- export {};
@@ -1,212 +0,0 @@
1
- // src/bundler/article.test.ts
2
- import { describe, it, expect } from 'vitest';
3
- import { extractArticleExcerpt, bundleArticleWithCollapsed } from './article.js';
4
- describe('extractArticleExcerpt', () => {
5
- it('extracts content between anchors', () => {
6
- const article = `# Article Title
7
-
8
- Some intro text.
9
-
10
- The key insight is that AI alignment requires careful consideration
11
- of human values. This is a complex problem that involves
12
- understanding this concept.
13
-
14
- More content after.
15
- `;
16
- const result = extractArticleExcerpt(article, 'The key insight is', 'understanding this concept.', 'articles/test.md');
17
- expect(result.content).toContain('AI alignment');
18
- expect(result.content).toContain('human values');
19
- expect(result.error).toBeUndefined();
20
- });
21
- it('returns error for missing start anchor', () => {
22
- const article = 'Some content without the anchor.';
23
- const result = extractArticleExcerpt(article, 'nonexistent anchor', 'also missing', 'articles/test.md');
24
- expect(result.error).toBeDefined();
25
- expect(result.error?.message).toContain('not found');
26
- expect(result.error?.suggestion).toContain('anchor');
27
- });
28
- it('returns error for duplicate anchor', () => {
29
- const article = `First occurrence of the phrase here.
30
-
31
- And another occurrence of the phrase here.`;
32
- const result = extractArticleExcerpt(article, 'occurrence of the phrase', 'here', 'articles/test.md');
33
- expect(result.error).toBeDefined();
34
- expect(result.error?.message).toContain('multiple');
35
- });
36
- it('is case-insensitive for matching', () => {
37
- const article = 'THE KEY INSIGHT is important.';
38
- const result = extractArticleExcerpt(article, 'the key insight', 'important.', 'articles/test.md');
39
- expect(result.content).toBeDefined();
40
- expect(result.error).toBeUndefined();
41
- });
42
- describe('special characters in anchors', () => {
43
- it('handles apostrophes in anchor text', () => {
44
- const article = `Introduction here.
45
-
46
- It's important to understand that AI systems don't always behave as expected.
47
-
48
- Conclusion here.`;
49
- const result = extractArticleExcerpt(article, "It's important", "don't always behave", 'articles/test.md');
50
- expect(result.error).toBeUndefined();
51
- expect(result.content).toContain("It's important");
52
- expect(result.content).toContain("don't always");
53
- });
54
- it('handles ampersand in anchor text', () => {
55
- const article = `Introduction here.
56
-
57
- The relationship between safety & alignment is crucial for AI development.
58
-
59
- Conclusion here.`;
60
- const result = extractArticleExcerpt(article, 'safety & alignment', 'AI development', 'articles/test.md');
61
- expect(result.error).toBeUndefined();
62
- expect(result.content).toContain('safety & alignment');
63
- });
64
- it('handles colons in anchor text', () => {
65
- const article = `Introduction here.
66
-
67
- Key point: this is the main argument we need to consider carefully.
68
-
69
- Conclusion here.`;
70
- const result = extractArticleExcerpt(article, 'Key point:', 'consider carefully', 'articles/test.md');
71
- expect(result.error).toBeUndefined();
72
- expect(result.content).toContain('Key point:');
73
- });
74
- it('handles percent signs in anchor text', () => {
75
- const article = `Introduction here.
76
-
77
- The model achieved 95% accuracy on the benchmark test results.
78
-
79
- Conclusion here.`;
80
- const result = extractArticleExcerpt(article, '95% accuracy', 'test results', 'articles/test.md');
81
- expect(result.error).toBeUndefined();
82
- expect(result.content).toContain('95% accuracy');
83
- });
84
- it('handles multiple special characters together', () => {
85
- const article = `Introduction here.
86
-
87
- Here's the key insight: AI systems won't achieve 100% safety & reliability without careful design.
88
-
89
- Conclusion here.`;
90
- const result = extractArticleExcerpt(article, "Here's the key insight:", "100% safety & reliability", 'articles/test.md');
91
- expect(result.error).toBeUndefined();
92
- expect(result.content).toContain("Here's");
93
- expect(result.content).toContain("100%");
94
- expect(result.content).toContain("&");
95
- });
96
- });
97
- });
98
- describe('bundleArticleWithCollapsed', () => {
99
- it('computes collapsed_before for non-first excerpt', () => {
100
- const article = `# Article
101
-
102
- Intro paragraph.
103
-
104
- First important section that we want to show.
105
-
106
- Middle content that gets collapsed.
107
-
108
- Second important section to show.
109
-
110
- Conclusion.
111
- `;
112
- const excerpts = [
113
- { from: 'First important', to: 'want to show.' },
114
- { from: 'Second important', to: 'section to show.' },
115
- ];
116
- const result = bundleArticleWithCollapsed(article, excerpts, 'articles/test.md');
117
- expect(result[0].collapsed_before).toBeUndefined(); // First excerpt has no collapsed_before
118
- expect(result[1].collapsed_before).toContain('Middle content');
119
- });
120
- it('computes collapsed_after for last excerpt', () => {
121
- const article = `Intro.
122
-
123
- Main content here.
124
-
125
- Conclusion paragraph at the end.
126
- `;
127
- const excerpts = [
128
- { from: 'Main content', to: 'content here.' },
129
- ];
130
- const result = bundleArticleWithCollapsed(article, excerpts, 'articles/test.md');
131
- expect(result[0].collapsed_after).toContain('Conclusion paragraph');
132
- });
133
- it('handles adjacent excerpts with no collapsed content', () => {
134
- const article = `First sentence. Second sentence.`;
135
- const excerpts = [
136
- { from: 'First', to: 'sentence.' },
137
- { from: 'Second', to: 'sentence.' },
138
- ];
139
- const result = bundleArticleWithCollapsed(article, excerpts, 'articles/test.md');
140
- // Adjacent excerpts have minimal or no collapsed content
141
- expect(result[0].collapsed_after).toBeUndefined();
142
- expect(result[1].collapsed_before).toBeUndefined();
143
- });
144
- });
145
- describe('extractArticleExcerpt with optional anchors', () => {
146
- const articleWithFrontmatter = `---
147
- title: Test Article
148
- author: John Doe
149
- ---
150
-
151
- Introduction paragraph here.
152
-
153
- Start here with the main content that we want to extract.
154
-
155
- Middle section content.
156
-
157
- End here and this is included.
158
-
159
- Conclusion paragraph at the end.
160
- `;
161
- const articleWithoutFrontmatter = `Introduction paragraph here.
162
-
163
- Start here with the main content that we want to extract.
164
-
165
- Middle section content.
166
-
167
- End here and this is included.
168
-
169
- Conclusion paragraph at the end.
170
- `;
171
- it('extracts from anchor to end of article when toAnchor is undefined', () => {
172
- const result = extractArticleExcerpt(articleWithoutFrontmatter, 'Start here', undefined, 'articles/test.md');
173
- expect(result.error).toBeUndefined();
174
- expect(result.content).toContain('Start here');
175
- expect(result.content).toContain('Middle section');
176
- expect(result.content).toContain('End here');
177
- expect(result.content).toContain('Conclusion paragraph');
178
- });
179
- it('extracts from start of article to anchor when fromAnchor is undefined', () => {
180
- const result = extractArticleExcerpt(articleWithoutFrontmatter, undefined, 'End here and this is included.', 'articles/test.md');
181
- expect(result.error).toBeUndefined();
182
- expect(result.content).toContain('Introduction paragraph');
183
- expect(result.content).toContain('Start here');
184
- expect(result.content).toContain('End here and this is included.');
185
- expect(result.content).not.toContain('Conclusion paragraph');
186
- });
187
- it('extracts entire article when both anchors are undefined', () => {
188
- const result = extractArticleExcerpt(articleWithoutFrontmatter, undefined, undefined, 'articles/test.md');
189
- expect(result.error).toBeUndefined();
190
- expect(result.content).toContain('Introduction paragraph');
191
- expect(result.content).toContain('Conclusion paragraph');
192
- expect(result.content).toBe(articleWithoutFrontmatter.trim());
193
- });
194
- it('strips frontmatter when extracting entire article', () => {
195
- const result = extractArticleExcerpt(articleWithFrontmatter, undefined, undefined, 'articles/test.md');
196
- expect(result.error).toBeUndefined();
197
- expect(result.content).not.toContain('title:');
198
- expect(result.content).not.toContain('author:');
199
- expect(result.content).not.toContain('---');
200
- expect(result.content).toContain('Introduction paragraph');
201
- expect(result.content).toContain('Conclusion paragraph');
202
- });
203
- it('strips frontmatter when extracting from start to anchor', () => {
204
- const result = extractArticleExcerpt(articleWithFrontmatter, undefined, 'Middle section content.', 'articles/test.md');
205
- expect(result.error).toBeUndefined();
206
- expect(result.content).not.toContain('title:');
207
- expect(result.content).not.toContain('---');
208
- expect(result.content).toContain('Introduction paragraph');
209
- expect(result.content).toContain('Middle section content.');
210
- });
211
- });
212
- //# sourceMappingURL=article.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"article.test.js","sourceRoot":"","sources":["../../src/bundler/article.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,95 +0,0 @@
1
- // src/bundler/video.test.ts
2
- import { describe, it, expect } from 'vitest';
3
- import { parseTimestamp, extractVideoExcerpt } from './video.js';
4
- describe('parseTimestamp', () => {
5
- it('converts MM:SS to seconds', () => {
6
- expect(parseTimestamp('1:30')).toBe(90);
7
- expect(parseTimestamp('5:45')).toBe(345);
8
- expect(parseTimestamp('0:00')).toBe(0);
9
- });
10
- it('converts H:MM:SS to seconds', () => {
11
- expect(parseTimestamp('1:30:00')).toBe(5400);
12
- expect(parseTimestamp('2:15:30')).toBe(8130);
13
- });
14
- it('returns null for invalid format', () => {
15
- expect(parseTimestamp('invalid')).toBeNull();
16
- expect(parseTimestamp('abc:def')).toBeNull();
17
- });
18
- });
19
- describe('extractVideoExcerpt', () => {
20
- it('extracts transcript between timestamps and returns seconds', () => {
21
- const transcript = `0:00 - Welcome to this video.
22
- 0:30 - Today we'll discuss AI safety.
23
- 1:30 - The first key point is alignment.
24
- 2:00 - This means ensuring AI does what we want.
25
- 5:45 - Moving on to the next topic.
26
- 6:00 - Let's talk about interpretability.
27
- `;
28
- const result = extractVideoExcerpt(transcript, '1:30', // 90 seconds
29
- '5:45', // 345 seconds
30
- 'video_transcripts/test.md');
31
- expect(result.from).toBe(90); // Seconds as number
32
- expect(result.to).toBe(345); // Seconds as number
33
- expect(result.transcript).toContain('alignment');
34
- expect(result.transcript).toContain('what we want');
35
- expect(result.transcript).not.toContain('Welcome');
36
- expect(result.transcript).not.toContain('interpretability');
37
- });
38
- it('returns error for invalid timestamp format', () => {
39
- const transcript = '0:00 - Content here.';
40
- const result = extractVideoExcerpt(transcript, 'invalid', '1:00', 'video_transcripts/test.md');
41
- expect(result.error).toBeDefined();
42
- expect(result.error?.message).toContain('timestamp');
43
- expect(result.error?.suggestion).toContain('MM:SS');
44
- });
45
- it('returns error when timestamp not found in transcript', () => {
46
- const transcript = '0:00 - Short video.\n0:30 - End.';
47
- const result = extractVideoExcerpt(transcript, '5:00', '10:00', 'video_transcripts/test.md');
48
- expect(result.error).toBeDefined();
49
- expect(result.error?.message).toContain('not found');
50
- });
51
- it('returns error when from timestamp is after to timestamp', () => {
52
- const transcript = `0:00 - Start.
53
- 3:00 - Middle.
54
- 5:00 - End.`;
55
- const result = extractVideoExcerpt(transcript, '5:00', '3:00', 'video.md');
56
- expect(result.error).toBeDefined();
57
- expect(result.error?.message).toContain('after');
58
- });
59
- describe('from 0:00 (start of video)', () => {
60
- it('treats 0:00 as start of video even when no 0:00 marker exists', () => {
61
- // Transcript starts at 0:30, not 0:00
62
- const transcript = `0:30 - First line of dialogue.
63
- 1:00 - Second line continues.
64
- 1:30 - Third line wraps up.
65
- 2:00 - End of section.`;
66
- const result = extractVideoExcerpt(transcript, '0:00', '1:30', 'video.md');
67
- // Should NOT error - 0:00 means "from the start"
68
- expect(result.error).toBeUndefined();
69
- expect(result.from).toBe(0);
70
- expect(result.to).toBe(90);
71
- // Should include lines from start up to (but not including) 1:30
72
- expect(result.transcript).toContain('First line');
73
- expect(result.transcript).toContain('Second line');
74
- expect(result.transcript).not.toContain('Third line');
75
- });
76
- it('handles plain prose transcript with no timestamps at all', () => {
77
- // This is common for transcripts that are just paragraphs of text
78
- const transcript = `This is the first paragraph of the transcript. It contains some interesting content about AI safety.
79
-
80
- This is the second paragraph. It continues discussing the topic.
81
-
82
- This is the third paragraph. It concludes the main points.`;
83
- const result = extractVideoExcerpt(transcript, '0:00', '5:00', 'video.md');
84
- // Should NOT error - include entire content since no timestamps exist
85
- expect(result.error).toBeUndefined();
86
- expect(result.from).toBe(0);
87
- expect(result.to).toBe(300);
88
- // Should include entire transcript
89
- expect(result.transcript).toContain('first paragraph');
90
- expect(result.transcript).toContain('second paragraph');
91
- expect(result.transcript).toContain('third paragraph');
92
- });
93
- });
94
- });
95
- //# sourceMappingURL=video.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"video.test.js","sourceRoot":"","sources":["../../src/bundler/video.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
package/dist/cli.test.js DELETED
@@ -1,45 +0,0 @@
1
- // src/cli.test.ts
2
- import { describe, it, expect } from 'vitest';
3
- import { spawn } from 'child_process';
4
- import { readFile } from 'fs/promises';
5
- import { join } from 'path';
6
- describe('CLI --stdin flag', () => {
7
- it('produces same output as file-based input', async () => {
8
- const fixturePath = join(__dirname, '../fixtures/valid/minimal-module/input');
9
- const expectedPath = join(__dirname, '../fixtures/valid/minimal-module/expected.json');
10
- // Read fixture files into a Map-like object
11
- const { readVaultFiles } = await import('./fs/read-vault.js');
12
- const files = await readVaultFiles(fixturePath);
13
- const filesObject = {};
14
- for (const [path, content] of files.entries()) {
15
- filesObject[path] = content;
16
- }
17
- // Run CLI with --stdin
18
- const result = await new Promise((resolve, reject) => {
19
- const child = spawn('npx', ['tsx', 'src/cli.ts', '--stdin'], {
20
- cwd: join(__dirname, '..'),
21
- stdio: ['pipe', 'pipe', 'pipe'],
22
- });
23
- let stdout = '';
24
- let stderr = '';
25
- child.stdout.on('data', (data) => { stdout += data; });
26
- child.stderr.on('data', (data) => { stderr += data; });
27
- child.on('close', (code) => {
28
- if (code !== 0) {
29
- reject(new Error(`CLI exited with code ${code}: ${stderr}`));
30
- }
31
- else {
32
- resolve(stdout);
33
- }
34
- });
35
- // Write JSON to stdin
36
- child.stdin.write(JSON.stringify(filesObject));
37
- child.stdin.end();
38
- });
39
- // Parse and compare (ignore whitespace differences)
40
- const actual = JSON.parse(result);
41
- const expected = JSON.parse(await readFile(expectedPath, 'utf-8'));
42
- expect(actual).toEqual(expected);
43
- }, 60000); // 60s timeout for subprocess (first run compiles)
44
- });
45
- //# sourceMappingURL=cli.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../src/cli.test.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,wCAAwC,CAAC,CAAC;QAC9E,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,gDAAgD,CAAC,CAAC;QAEvF,4CAA4C;QAC5C,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;QAChD,MAAM,WAAW,GAA2B,EAAE,CAAC;QAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9C,WAAW,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QAC9B,CAAC;QAED,uBAAuB;QACvB,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE;gBAC3D,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;gBAC1B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC;YAEH,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,MAAM,GAAG,EAAE,CAAC;YAEhB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC/D,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,sBAAsB;YACtB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;YAC/C,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QAEnE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,kDAAkD;AAC/D,CAAC,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- export {};