Skip to content

Commit d9eb351

Browse files
committed
Add README project index generation
Add automatic generation and updating of a Projects section in the repository README. scripts/generate.js: introduce constants for generated section markers, buildProjectDirectoryUrl, generateRootProjectIndex and updateRootReadme to insert or replace a generated list of project links; call updateRootReadme from main using listProjectDirectories. Also refactor generateProjectReadme to use encoded manifest URLs and markdown-style links for project READMEs. Update README.md to include the generated Projects section and convert example-project/README.md links to markdown format so they match the generated output.
1 parent 9dd4cbb commit d9eb351

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ This repository is designed for low-friction manifest creation:
2929
└── .github/workflows/generate-manifests.yml
3030
```
3131

32+
<!-- GENERATED_PROJECT_LINKS_START -->
33+
## Projects
34+
35+
- [example-project](./projects/example-project/)
36+
<!-- GENERATED_PROJECT_LINKS_END -->
37+
3238
## Project Inputs
3339

3440
Each project lives in `projects/{project-name}`.

projects/example-project/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ This project is generated by repository scripts.
1212
- WARNING.md
1313

1414
## Links
15-
- Manifest: https://CenterForDigitalHumanities.github.io/Github-Manifests/projects/example-project/manifest.json
16-
- Images folder: ./images/
17-
- Mirador: https://projectmirador.org/embed/?iiif-content=https://CenterForDigitalHumanities.github.io/Github-Manifests/projects/example-project/manifest.json
18-
- Universal Viewer: https://uv-v3.netlify.app/#?manifest=https://CenterForDigitalHumanities.github.io/Github-Manifests/projects/example-project/manifest.json
19-
- TPEN3 Import: https://app.t-pen.org/project/import?manifest=https%3A%2F%2FCenterForDigitalHumanities.github.io%2FGithub-Manifests%2Fprojects%2Fexample-project%2Fmanifest.json
15+
- [Manifest](https://CenterForDigitalHumanities.github.io/Github-Manifests/projects/example-project/manifest.json)
16+
- [Images folder](./images/)
17+
- [Mirador](https://projectmirador.org/embed/?iiif-content=https%3A%2F%2FCenterForDigitalHumanities.github.io%2FGithub-Manifests%2Fprojects%2Fexample-project%2Fmanifest.json)
18+
- [Universal Viewer](https://uv-v3.netlify.app/#?manifest=https%3A%2F%2FCenterForDigitalHumanities.github.io%2FGithub-Manifests%2Fprojects%2Fexample-project%2Fmanifest.json)
19+
- [TPEN3 Import](https://app.t-pen.org/project/import?manifest=https%3A%2F%2FCenterForDigitalHumanities.github.io%2FGithub-Manifests%2Fprojects%2Fexample-project%2Fmanifest.json)
2020

2121
## TPEN3
2222
Use the TPEN3 import link above to create a new project directly from this manifest.

scripts/generate.js

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import {
2626
writeText
2727
} from "./utils.js"
2828

29+
const ROOT_PROJECT_INDEX_START = "<!-- GENERATED_PROJECT_LINKS_START -->"
30+
const ROOT_PROJECT_INDEX_END = "<!-- GENERATED_PROJECT_LINKS_END -->"
31+
2932
function createWarning(code, message, details = {}) {
3033
return {
3134
code,
@@ -132,6 +135,10 @@ function buildImageUrl(siteBaseUrl, projectName, imageRelativePath) {
132135
return `${siteBaseUrl}/projects/${projectName}/${toPosixPath(imageRelativePath)}`
133136
}
134137

138+
function buildProjectDirectoryUrl(projectName) {
139+
return `./projects/${projectName}/`
140+
}
141+
135142
function normalizeTopLevelFields(info, warnings) {
136143
const out = {}
137144

@@ -669,9 +676,45 @@ function buildManifest({ projectName, siteBaseUrl, info, resources, warnings })
669676
}
670677

671678
function generateProjectReadme(projectName, manifestUrl) {
672-
const tpenImportUrl = `https://app.t-pen.org/project/import?manifest=${encodeURIComponent(manifestUrl)}`
679+
const encodedManifestUrl = encodeURIComponent(manifestUrl)
680+
const miradorUrl = `https://projectmirador.org/embed/?iiif-content=${encodedManifestUrl}`
681+
const universalViewerUrl = `https://uv-v3.netlify.app/#?manifest=${encodedManifestUrl}`
682+
const tpenImportUrl = `https://app.t-pen.org/project/import?manifest=${encodedManifestUrl}`
683+
684+
return `# ${projectName}\n\nThis project is generated by repository scripts.\n\n## Inputs\n- Add local images in images/\n- Add external references using .lnk files in images/ (one HTTP(S) URL per file)\n- Optional advanced configuration in info.yml\n\n## Generated Outputs\n- manifest.json\n- WARNING.md\n\n## Links\n- [Manifest.json](${manifestUrl})\n- [Images folder](./images/)\n- [Mirador Viewer](${miradorUrl})\n- [Universal Viewer](${universalViewerUrl})\n- [TPEN3 Create Project](${tpenImportUrl})\n\n## TPEN3\nUse the TPEN3 import link above to create a new project directly from this manifest.\n\n> This file is regenerated when manifest generation runs. Put durable custom metadata in info.yml.\n`
685+
}
686+
687+
function generateRootProjectIndex(projectNames) {
688+
const items = projectNames
689+
.map((projectName) => `- [${projectName}](${buildProjectDirectoryUrl(projectName)})`)
690+
.join("\n")
673691

674-
return `# ${projectName}\n\nThis project is generated by repository scripts.\n\n## Inputs\n- Add local images in images/\n- Add external references using .lnk files in images/ (one HTTP(S) URL per file)\n- Optional advanced configuration in info.yml\n\n## Generated Outputs\n- manifest.json\n- WARNING.md\n\n## Links\n- Manifest: ${manifestUrl}\n- Images folder: ./images/\n- Mirador: https://projectmirador.org/embed/?iiif-content=${manifestUrl}\n- Universal Viewer: https://uv-v3.netlify.app/#?manifest=${manifestUrl}\n- TPEN3 Import: ${tpenImportUrl}\n\n## TPEN3\nUse the TPEN3 import link above to create a new project directly from this manifest.\n\n> This file is regenerated when manifest generation runs. Put durable custom metadata in info.yml.\n`
692+
return `${ROOT_PROJECT_INDEX_START}\n## Projects\n\n${items}\n${ROOT_PROJECT_INDEX_END}`
693+
}
694+
695+
async function updateRootReadme(projectNames) {
696+
const readmePath = path.join(repoRoot, "README.md")
697+
const readme = await fs.readFile(readmePath, "utf8")
698+
const generatedSection = generateRootProjectIndex(projectNames)
699+
const existingSectionPattern = new RegExp(
700+
`${ROOT_PROJECT_INDEX_START}[\\s\\S]*?${ROOT_PROJECT_INDEX_END}`,
701+
"m"
702+
)
703+
704+
if (existingSectionPattern.test(readme)) {
705+
const updatedReadme = readme.replace(existingSectionPattern, generatedSection)
706+
await writeText(readmePath, updatedReadme)
707+
return
708+
}
709+
710+
const insertionMarker = "## Project Inputs"
711+
const insertionIndex = readme.indexOf(insertionMarker)
712+
if (insertionIndex === -1) {
713+
throw new Error("Could not find '## Project Inputs' section in README.md to insert project links.")
714+
}
715+
716+
const updatedReadme = `${readme.slice(0, insertionIndex)}${generatedSection}\n\n${readme.slice(insertionIndex)}`
717+
await writeText(readmePath, updatedReadme)
675718
}
676719

677720
function generateWarningsMarkdown(projectName, warnings) {
@@ -765,6 +808,9 @@ async function main() {
765808
results.push(result)
766809
}
767810

811+
const allProjectNames = await listProjectDirectories(projectsRoot)
812+
await updateRootReadme(allProjectNames)
813+
768814
for (const result of results) {
769815
console.log(`Generated ${result.projectName} (warnings: ${result.warningCount})`)
770816
}

0 commit comments

Comments
 (0)