From 4e440188b850392c9bbd83fb9c79cbc14989d045 Mon Sep 17 00:00:00 2001 From: Becky Gilbert Date: Thu, 2 Jul 2026 15:18:14 -0700 Subject: [PATCH 1/3] fix remote git URL construction: files need /blob/, not /tree/; set remoteGitURL to root URL instead of undfined when it is empty (running from repo root) --- packages/new-extension/src/cli.js | 6 +++--- packages/new-multiplayer-adapter/src/cli.js | 6 +++--- packages/new-plugin/src/cli.js | 6 +++--- packages/new-timeline/src/cli.js | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/new-extension/src/cli.js b/packages/new-extension/src/cli.js index 19a48c3..1bb253a 100755 --- a/packages/new-extension/src/cli.js +++ b/packages/new-extension/src/cli.js @@ -58,9 +58,9 @@ async function getRemoteGitUrl() { if (repoRoot) { const currentDir = process.cwd(); const relativePath = path.relative(repoRoot, currentDir); - if (relativePath) { - remoteGitUrl = `${remoteGitRootUrl}/tree/main/${relativePath}`; - } + remoteGitUrl = relativePath + ? `${remoteGitRootUrl}/blob/main/${relativePath}` + : `${remoteGitRootUrl}/blob/main`; return remoteGitUrl; } return ""; diff --git a/packages/new-multiplayer-adapter/src/cli.js b/packages/new-multiplayer-adapter/src/cli.js index d72e9fc..2773956 100755 --- a/packages/new-multiplayer-adapter/src/cli.js +++ b/packages/new-multiplayer-adapter/src/cli.js @@ -71,9 +71,9 @@ async function getRemoteGitUrl() { if (repoRoot) { const currentDir = process.cwd(); const relativePath = path.relative(repoRoot, currentDir); - if (relativePath) { - remoteGitUrl = `${remoteGitRootUrl}/tree/main/${relativePath}`; - } + remoteGitUrl = relativePath + ? `${remoteGitRootUrl}/blob/main/${relativePath}` + : `${remoteGitRootUrl}/blob/main`; return remoteGitUrl; } return ""; diff --git a/packages/new-plugin/src/cli.js b/packages/new-plugin/src/cli.js index 1eaac89..c003edd 100755 --- a/packages/new-plugin/src/cli.js +++ b/packages/new-plugin/src/cli.js @@ -58,9 +58,9 @@ async function getRemoteGitUrl() { if (repoRoot) { const currentDir = process.cwd(); const relativePath = path.relative(repoRoot, currentDir); - if (relativePath) { - remoteGitUrl = `${remoteGitRootUrl}/tree/main/${relativePath}`; - } + remoteGitUrl = relativePath + ? `${remoteGitRootUrl}/blob/main/${relativePath}` + : `${remoteGitRootUrl}/blob/main`; return remoteGitUrl; } return ""; diff --git a/packages/new-timeline/src/cli.js b/packages/new-timeline/src/cli.js index 07d160c..04c9876 100755 --- a/packages/new-timeline/src/cli.js +++ b/packages/new-timeline/src/cli.js @@ -58,9 +58,9 @@ async function getRemoteGitUrl() { if (repoRoot) { const currentDir = process.cwd(); const relativePath = path.relative(repoRoot, currentDir); - if (relativePath) { - remoteGitUrl = `${remoteGitRootUrl}/tree/main/${relativePath}`; - } + remoteGitUrl = relativePath + ? `${remoteGitRootUrl}/blob/main/${relativePath}` + : `${remoteGitRootUrl}/blob/main`; return remoteGitUrl; } return ""; From 08c38221e99fe9d5207d49dfc2c2b895b4b85b65 Mon Sep 17 00:00:00 2001 From: Becky Gilbert Date: Thu, 2 Jul 2026 15:31:14 -0700 Subject: [PATCH 2/3] change prompt: README -> documentation; readmePath -> documentationPath; --readme-path -> --documentation-path --- packages/new-extension/src/cli.js | 28 +++++++++--------- packages/new-multiplayer-adapter/src/cli.js | 32 ++++++++++----------- packages/new-plugin/src/cli.js | 28 +++++++++--------- packages/new-timeline/src/cli.js | 28 +++++++++--------- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/packages/new-extension/src/cli.js b/packages/new-extension/src/cli.js index 1bb253a..b8ecf2a 100755 --- a/packages/new-extension/src/cli.js +++ b/packages/new-extension/src/cli.js @@ -188,16 +188,16 @@ async function runPrompts(cwdInfo) { loop: false, }); - // If not in the jspsych-contrib repository, ask for the path to the README.md file - let readmePath; + // If not in the jspsych-contrib repository, ask for the path to the documentation file + let documentationPath; if (!cwdInfo.isContribRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = await input({ - message: "Enter the path to the README.md file for this extension package [Optional]:", - default: `${getGitHttpsUrl(remoteGitUrl)}/extension-${getHyphenateName(name)}/README.md`, // '/extension-${name}/README.md' if not a Git repository + documentationPath = await input({ + message: "Enter the path to the documentation file for this extension package [Optional]:", + default: getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/extension-${getHyphenateName(name)}/docs/extension-${getHyphenateName(name)}.md` : `docs/extension-${getHyphenateName(name)}.md`, // '/extension-${name}/docs/extension-${name}.md' if not a Git repository }); } else { - readmePath = `https://github.com/jspsych/jspsych-contrib/packages/extension-${getHyphenateName(name)}/README.md`; + documentationPath = `https://github.com/jspsych/jspsych-contrib/blob/main/packages/extension-${getHyphenateName(name)}/docs/extension-${getHyphenateName(name)}.md`; } return { @@ -206,7 +206,7 @@ async function runPrompts(cwdInfo) { author: author, authorUrl: authorUrl, language: language, - readmePath: readmePath, + documentationPath: documentationPath, destDir: cwdInfo.destDir, isContribRepo: cwdInfo.isContribRepo, }; @@ -258,7 +258,7 @@ async function processAnswers(answers) { .pipe(replace("{packageName}", packageName)) .pipe(replace("{gitRootUrl}", gitRootUrl)) .pipe(replace("{gitRootHttpsUrl}", gitRootHttpsUrl)) - .pipe(replace("{documentationUrl}", answers.readmePath)) + .pipe(replace("{documentationUrl}", answers.documentationPath)) .pipe(replace("{packageDir}", packageDir)) .pipe( // npm renames a literal ".gitignore" to ".npmignore" when this package is @@ -344,13 +344,13 @@ async function runWithArgs(cwdInfo, options) { const name = options.name; const language = options.language || 'ts'; - let readmePath = options.readmePath; - if (!readmePath) { + let documentationPath = options.documentationPath; + if (!documentationPath) { if (!cwdInfo.isContribRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = `${getGitHttpsUrl(remoteGitUrl)}/extension-${getHyphenateName(name)}/README.md`; + documentationPath = getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/extension-${getHyphenateName(name)}/docs/extension-${getHyphenateName(name)}.md` : `docs/extension-${getHyphenateName(name)}.md`; } else { - readmePath = `https://github.com/jspsych/jspsych-contrib/packages/extension-${getHyphenateName(name)}/README.md`; + documentationPath = `https://github.com/jspsych/jspsych-contrib/blob/main/packages/extension-${getHyphenateName(name)}/docs/extension-${getHyphenateName(name)}.md`; } } @@ -360,7 +360,7 @@ async function runWithArgs(cwdInfo, options) { author: options.author, authorUrl: options.authorUrl || '', language: language, - readmePath: readmePath, + documentationPath: documentationPath, destDir: cwdInfo.destDir, isContribRepo: cwdInfo.isContribRepo, }; @@ -378,7 +378,7 @@ program .option('--author ', 'Name of the author (required)') .option('--author-url ', 'Profile URL for the author (optional)') .option('--language ', 'Language to use: ts or js (default: ts)', 'ts') - .option('--readme-path ', 'Path to README.md file (optional)') + .option('--documentation-path ', 'Path to the documentation file (optional)') .addHelpText('after', ` Examples: diff --git a/packages/new-multiplayer-adapter/src/cli.js b/packages/new-multiplayer-adapter/src/cli.js index 2773956..cfb90e7 100755 --- a/packages/new-multiplayer-adapter/src/cli.js +++ b/packages/new-multiplayer-adapter/src/cli.js @@ -194,18 +194,18 @@ async function runPrompts(cwdInfo) { message: "Enter a profile URL for the author, e.g. a link to their GitHub profile [Optional]:", }); - // If not in a known monorepo, ask for the path to the README.md file - let readmePath; + // If not in a known monorepo, ask for the path to the documentation file + let documentationPath; if (!cwdInfo.isKnownRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = await input({ - message: "Enter the path to the README.md file for this adapter package [Optional]:", - default: `${getGitHttpsUrl(remoteGitUrl)}/adapter-${getHyphenateName(name)}/README.md`, // '/adapter-${name}/README.md' if not a Git repository + documentationPath = await input({ + message: "Enter the path to the documentation file for this adapter package [Optional]:", + default: getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/adapter-${getHyphenateName(name)}/docs/adapter-${getHyphenateName(name)}.md` : `docs/adapter-${getHyphenateName(name)}.md`, // '/adapter-${name}/docs/adapter-${name}.md' if not a Git repository }); } else { - readmePath = `https://github.com/${ + documentationPath = `https://github.com/${ cwdInfo.repoConfig.repoSlug - }/blob/main/packages/adapter-${getHyphenateName(name)}/README.md`; + }/blob/main/packages/adapter-${getHyphenateName(name)}/docs/adapter-${getHyphenateName(name)}.md`; } return { @@ -213,7 +213,7 @@ async function runPrompts(cwdInfo) { description, author, authorUrl, - readmePath, + documentationPath, destDir: cwdInfo.destDir, isKnownRepo: cwdInfo.isKnownRepo, repoConfig: cwdInfo.repoConfig, @@ -261,7 +261,7 @@ async function processAnswers(answers) { .pipe(replace("{packageName}", packageName)) .pipe(replace("{gitRootUrl}", gitRootUrl)) .pipe(replace("{gitRootHttpsUrl}", gitRootHttpsUrl)) - .pipe(replace("{documentationUrl}", answers.readmePath)) + .pipe(replace("{documentationUrl}", answers.documentationPath)) .pipe(replace("{packageDir}", packageDir)) .pipe( // npm renames a literal ".gitignore" to ".npmignore" when this package is @@ -344,15 +344,15 @@ async function runWithArgs(cwdInfo, options) { const name = options.name; - let readmePath = options.readmePath; - if (!readmePath) { + let documentationPath = options.documentationPath; + if (!documentationPath) { if (!cwdInfo.isKnownRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = `${getGitHttpsUrl(remoteGitUrl)}/adapter-${getHyphenateName(name)}/README.md`; + documentationPath = getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/adapter-${getHyphenateName(name)}/docs/adapter-${getHyphenateName(name)}.md` : `docs/adapter-${getHyphenateName(name)}.md`; } else { - readmePath = `https://github.com/${ + documentationPath = `https://github.com/${ cwdInfo.repoConfig.repoSlug - }/blob/main/packages/adapter-${getHyphenateName(name)}/README.md`; + }/blob/main/packages/adapter-${getHyphenateName(name)}/docs/adapter-${getHyphenateName(name)}.md`; } } @@ -361,7 +361,7 @@ async function runWithArgs(cwdInfo, options) { description: options.description, author: options.author, authorUrl: options.authorUrl || "", - readmePath, + documentationPath, destDir: cwdInfo.destDir, isKnownRepo: cwdInfo.isKnownRepo, repoConfig: cwdInfo.repoConfig, @@ -379,7 +379,7 @@ program .option("--description ", "Brief description of the adapter package (required)") .option("--author ", "Name of the author (required)") .option("--author-url ", "Profile URL for the author (optional)") - .option("--readme-path ", "Path to README.md file (optional)") + .option("--documentation-path ", "Path to the documentation file (optional)") .addHelpText( "after", ` diff --git a/packages/new-plugin/src/cli.js b/packages/new-plugin/src/cli.js index c003edd..daf9b10 100755 --- a/packages/new-plugin/src/cli.js +++ b/packages/new-plugin/src/cli.js @@ -208,16 +208,16 @@ async function runPrompts(cwdInfo) { loop: false, }); - // If not in a known jsPsych monorepo, ask for the path to the README.md file - let readmePath; + // If not in a known jsPsych monorepo, ask for the path to the documentation file + let documentationPath; if (!cwdInfo.isContribRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = await input({ - message: "Enter the path to the README.md file for this plugin package [Optional]:", - default: `${getGitHttpsUrl(remoteGitUrl)}/plugin-${getHyphenateName(name)}/README.md`, // '/plugin-${name}/README.md' if not a Git repository + documentationPath = await input({ + message: "Enter the path to the documentation file for this plugin package [Optional]:", + default: getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/plugin-${getHyphenateName(name)}/docs/plugin-${getHyphenateName(name)}.md` : `docs/plugin-${getHyphenateName(name)}.md`, // '/plugin-${name}/docs/plugin-${name}.md' if not a Git repository }); } else { - readmePath = `https://github.com/${cwdInfo.repoSlug}/packages/plugin-${getHyphenateName(name)}/README.md`; + documentationPath = `https://github.com/${cwdInfo.repoSlug}/blob/main/packages/plugin-${getHyphenateName(name)}/docs/plugin-${getHyphenateName(name)}.md`; } return { @@ -226,7 +226,7 @@ async function runPrompts(cwdInfo) { author: author, authorUrl: authorUrl, language: language, - readmePath: readmePath, + documentationPath: documentationPath, destDir: cwdInfo.destDir, isContribRepo: cwdInfo.isContribRepo, scope: cwdInfo.scope, @@ -274,7 +274,7 @@ async function processAnswers(answers) { .pipe(replace("{packageName}", packageName)) .pipe(replace("{gitRootUrl}", gitRootUrl)) .pipe(replace("{gitRootHttpsUrl}", gitRootHttpsUrl)) - .pipe(replace("{documentationUrl}", answers.readmePath)) + .pipe(replace("{documentationUrl}", answers.documentationPath)) .pipe(replace("{packageDir}", packageDir)) .pipe( // npm renames a literal ".gitignore" to ".npmignore" when this package is @@ -360,13 +360,13 @@ async function runWithArgs(cwdInfo, options) { const name = options.name; const language = options.language || 'ts'; - let readmePath = options.readmePath; - if (!readmePath) { + let documentationPath = options.documentationPath; + if (!documentationPath) { if (!cwdInfo.isContribRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = `${getGitHttpsUrl(remoteGitUrl)}/plugin-${getHyphenateName(name)}/README.md`; + documentationPath = getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/plugin-${getHyphenateName(name)}/docs/plugin-${getHyphenateName(name)}.md` : `docs/plugin-${getHyphenateName(name)}.md`; } else { - readmePath = `https://github.com/${cwdInfo.repoSlug}/packages/plugin-${getHyphenateName(name)}/README.md`; + documentationPath = `https://github.com/${cwdInfo.repoSlug}/blob/main/packages/plugin-${getHyphenateName(name)}/docs/plugin-${getHyphenateName(name)}.md`; } } @@ -376,7 +376,7 @@ async function runWithArgs(cwdInfo, options) { author: options.author, authorUrl: options.authorUrl || '', language: language, - readmePath: readmePath, + documentationPath: documentationPath, destDir: cwdInfo.destDir, isContribRepo: cwdInfo.isContribRepo, scope: cwdInfo.scope, @@ -396,7 +396,7 @@ program .option('--author ', 'Name of the author (required)') .option('--author-url ', 'Profile URL for the author (optional)') .option('--language ', 'Language to use: ts or js (default: ts)', 'ts') - .option('--readme-path ', 'Path to README.md file (optional)') + .option('--documentation-path ', 'Path to the documentation file (optional)') .addHelpText('after', ` Examples: diff --git a/packages/new-timeline/src/cli.js b/packages/new-timeline/src/cli.js index 04c9876..1962e03 100755 --- a/packages/new-timeline/src/cli.js +++ b/packages/new-timeline/src/cli.js @@ -188,16 +188,16 @@ async function runPrompts(cwdInfo) { loop: false, }); - // If not in the jspsych-timelines repository, ask for the path to the README.md file - let readmePath; + // If not in the jspsych-timelines repository, ask for the path to the documentation file + let documentationPath; if (!cwdInfo.isTimelinesRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = await input({ - message: "Enter the path to the README.md file for this timeline package [Optional]:", - default: `${getGitHttpsUrl(remoteGitUrl)}/${getHyphenateName(name)}/README.md`, // '/${name}/README.md' if not a Git repository + documentationPath = await input({ + message: "Enter the path to the documentation file for this timeline package [Optional]:", + default: getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/${getHyphenateName(name)}/docs/${getHyphenateName(name)}.md` : `docs/${getHyphenateName(name)}.md`, // '/${name}/docs/${name}.md' if not a Git repository }); } else { - readmePath = `https://github.com/jspsych/jspsych-timelines/packages/${getHyphenateName(name)}/README.md`; + documentationPath = `https://github.com/jspsych/jspsych-timelines/blob/main/packages/${getHyphenateName(name)}/docs/${getHyphenateName(name)}.md`; } return { @@ -206,7 +206,7 @@ async function runPrompts(cwdInfo) { author: author, authorUrl: authorUrl, language: language, - readmePath: readmePath, + documentationPath: documentationPath, destDir: cwdInfo.destDir, isTimelinesRepo: cwdInfo.isTimelinesRepo, }; @@ -257,7 +257,7 @@ async function processAnswers(answers) { .pipe(replace("{packageName}", packageName)) .pipe(replace("{gitRootUrl}", gitRootUrl)) .pipe(replace("{gitRootHttpsUrl}", gitRootHttpsUrl)) - .pipe(replace("{documentationUrl}", answers.readmePath)) + .pipe(replace("{documentationUrl}", answers.documentationPath)) .pipe(replace("{packageDir}", packageDir)) .pipe( // npm renames a literal ".gitignore" to ".npmignore" when this package is @@ -331,13 +331,13 @@ async function runWithArgs(cwdInfo, options) { const name = options.name; const language = options.language || 'ts'; - let readmePath = options.readmePath; - if (!readmePath) { + let documentationPath = options.documentationPath; + if (!documentationPath) { if (!cwdInfo.isTimelinesRepo) { const remoteGitUrl = await getRemoteGitUrl(); - readmePath = `${getGitHttpsUrl(remoteGitUrl)}/${getHyphenateName(name)}/README.md`; + documentationPath = getGitHttpsUrl(remoteGitUrl) ? `${getGitHttpsUrl(remoteGitUrl)}/${getHyphenateName(name)}/docs/${getHyphenateName(name)}.md` : `docs/${getHyphenateName(name)}.md`; } else { - readmePath = `https://github.com/jspsych/jspsych-timelines/packages/${getHyphenateName(name)}/README.md`; + documentationPath = `https://github.com/jspsych/jspsych-timelines/blob/main/packages/${getHyphenateName(name)}/docs/${getHyphenateName(name)}.md`; } } @@ -347,7 +347,7 @@ async function runWithArgs(cwdInfo, options) { author: options.author, authorUrl: options.authorUrl || '', language: language, - readmePath: readmePath, + documentationPath: documentationPath, destDir: cwdInfo.destDir, isTimelinesRepo: cwdInfo.isTimelinesRepo, }; @@ -365,7 +365,7 @@ program .option('--author ', 'Name of the author (required)') .option('--author-url ', 'Profile URL for the author (optional)') .option('--language ', 'Language to use: ts or js (default: ts)', 'ts') - .option('--readme-path ', 'Path to README.md file (optional)') + .option('--documentation-path ', 'Path to the documentation file (optional)') .addHelpText('after', ` Examples: From 41582a1411a0ff8f12744b7aaade352fb5ff6f6a Mon Sep 17 00:00:00 2001 From: Becky Gilbert Date: Thu, 2 Jul 2026 17:23:58 -0700 Subject: [PATCH 3/3] add changeset --- .changeset/green-llamas-hang.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .changeset/green-llamas-hang.md diff --git a/.changeset/green-llamas-hang.md b/.changeset/green-llamas-hang.md new file mode 100644 index 0000000..906dc46 --- /dev/null +++ b/.changeset/green-llamas-hang.md @@ -0,0 +1,13 @@ +--- +"@jspsych/new-multiplayer-adapter": minor +"@jspsych/new-extension": minor +"@jspsych/new-timeline": minor +"@jspsych/new-plugin": minor +--- + +Fix incorrect/broken documentation links generated in README files for new packages. + +- Documentation link now points to `docs/.md` instead of `README.md` +- Fixed GitHub URL format: use `/blob/main/` instead of `/tree/main/` +- Fixed URL generation when running from a git repository root with a remote: previously the remote URL was ignored and the link was broken; now the full GitHub URL is used +- Renamed `--readme-path` CLI flag to `--documentation-path` and updated the interactive prompt text to reflect its actual purpose (the URL/path to the documentation file, not the README)