-
Notifications
You must be signed in to change notification settings - Fork 3
autodoc: ensure unique example storage with duplicate titles
#71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: autodoc
Are you sure you want to change the base?
Changes from all commits
e8b7d79
773afe2
26ad661
60ddc25
2509522
5a2d94c
c003f87
d873c74
ebe6d1e
280cc3c
a84c064
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -234,14 +234,15 @@ export function getCodeBlock( | |
| export function getExampleInfo( | ||
| sourcePath: string, | ||
| inferFallback: (content: string, path: string) => string, | ||
| ): Record<string, ExampleInfo> | undefined { | ||
| ): ExampleInfo | undefined { | ||
| const content = fs.readFileSync(sourcePath, "utf-8"); | ||
|
|
||
| if (/<!--\s*jspsych-autodoc:ignore\s*-->/.test(content)) return undefined; | ||
|
|
||
| let title: string; | ||
|
|
||
| const sentinelMatch = content.match(/<!--\s*jspsych-autodoc:title\s+(.+?)\s*-->/); | ||
| const hasCustomTitle = !!sentinelMatch; | ||
| if (sentinelMatch) { | ||
| title = sentinelMatch[1].trim(); | ||
| } else { | ||
|
|
@@ -250,9 +251,7 @@ export function getExampleInfo( | |
| title = titleTagMatch[1].trim(); | ||
| } | ||
|
|
||
| return { | ||
| [title]: { path: sourcePath, code: getCodeBlock(content, sourcePath, inferFallback) }, | ||
| }; | ||
| return { title, hasCustomTitle, path: sourcePath, displayPath: sourcePath, code: getCodeBlock(content, sourcePath, inferFallback) }; | ||
| } | ||
|
|
||
| /** Collects example info from a directory or single HTML file. */ | ||
|
|
@@ -266,14 +265,18 @@ export function collectExamples( | |
|
|
||
| const stat = fs.statSync(examplePath); | ||
| const htmlFiles: string[] = []; | ||
| let isDirectory = false; | ||
|
|
||
| if (stat.isDirectory()) { | ||
| htmlFiles.push( | ||
| ...fs | ||
| .readdirSync(examplePath) | ||
| .filter((f) => f.endsWith(".html")) | ||
| .map((f) => path.join(examplePath, f)), | ||
| ); | ||
| isDirectory = true; | ||
| const collectHtml = (dir: string) => { | ||
| for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { | ||
| const full = path.join(dir, entry.name); | ||
| if (entry.isDirectory()) collectHtml(full); | ||
| else if (entry.name.endsWith(".html")) htmlFiles.push(full); | ||
| } | ||
| }; | ||
| collectHtml(examplePath); | ||
| } else if (stat.isFile()) { | ||
| if (!examplePath.endsWith(".html")) { | ||
| throw new Error(`Example file must be an HTML file: ${examplePath}`); | ||
|
|
@@ -284,9 +287,30 @@ export function collectExamples( | |
| } | ||
|
|
||
| const result: Record<string, ExampleInfo> = {}; | ||
| const titleCounts = new Map<string, number>(); | ||
| for (const file of htmlFiles) { | ||
| const exampleInfo = getExampleInfo(file, inferFallback); | ||
| if (exampleInfo) Object.assign(result, exampleInfo); | ||
| try { | ||
| const info = getExampleInfo(file, inferFallback); | ||
| if (info) { | ||
| info.displayPath = isDirectory ? path.relative(examplePath, info.path) : path.basename(info.path); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure if this ensures if paths could persist across OSes, thinking about windows using backslash (darn windows..), consider either using |
||
| if (info.hasCustomTitle) { | ||
| const baseTitle = info.title; | ||
| const count = titleCounts.get(baseTitle) ?? 0; | ||
| titleCounts.set(baseTitle, count + 1); | ||
| if (count > 0) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it looks like this might not work for titles "Hello", "Hello (2)", "Hello", the paths are stored separately so it won't be clobbered but it will result in duplicate section headers once rendered out. not sure if worth doing this edge case because it's not even that big of a deal, just flagging it |
||
| info.title = `${baseTitle} (${count + 1})`; | ||
| console.warn(`Warning: duplicate example title "${baseTitle}" in ${file}, renamed to "${info.title}"`); | ||
| } | ||
| } | ||
| result[info.path] = info; | ||
| } | ||
| } catch (e) { | ||
| if (htmlFiles.length > 1) { | ||
| console.warn(`Warning: skipping ${file}: ${e instanceof Error ? e.message : e}`); | ||
| } else { | ||
| throw e; | ||
| } | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>TestExtension Example</title> | ||
| </head> | ||
| <body> | ||
| <script> | ||
| // jspsych-autodoc:start | ||
| const trial = { type: jsPsychTestPlugin, stimulus: "path1" }; | ||
| // jspsych-autodoc:end | ||
| </script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>TestExtension Example</title> | ||
| </head> | ||
| <body> | ||
| <script> | ||
| // jspsych-autodoc:start | ||
| const trial = { type: jsPsychTestPlugin, stimulus: "path2" }; | ||
| // jspsych-autodoc:end | ||
| </script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <!-- jspsych-autodoc:title my example --> | ||
| </head> | ||
| <body> | ||
| <script> | ||
| // jspsych-autodoc:start | ||
| const trial = { type: jsPsychTestPlugin, stimulus: "file a" }; | ||
| // jspsych-autodoc:end | ||
| </script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <!-- jspsych-autodoc:title my example --> | ||
| </head> | ||
| <body> | ||
| <script> | ||
| // jspsych-autodoc:start | ||
| const trial = { type: jsPsychTestPlugin, stimulus: "file b" }; | ||
| // jspsych-autodoc:end | ||
| </script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>My Example</title> | ||
| </head> | ||
| <body> | ||
| <script> | ||
| // jspsych-autodoc:start | ||
| const trial = { type: jsPsychTestPlugin, stimulus: "file a" }; | ||
| // jspsych-autodoc:end | ||
| </script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>My Example</title> | ||
| </head> | ||
| <body> | ||
| <script> | ||
| // jspsych-autodoc:start | ||
| const trial = { type: jsPsychTestPlugin, stimulus: "file b" }; | ||
| // jspsych-autodoc:end | ||
| </script> | ||
| </body> | ||
| </html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from what I understand,
fs.readdirSyncis unsorted (implementation differs across OSes) so whichever one of shared titles becoming the secondary one might get flipped. would be good to sort the array before looping over it