Phase 2 generate resource docs
This commit is contained in:
+8
-2
@@ -2,12 +2,18 @@
|
|||||||
|
|
||||||
## Current
|
## Current
|
||||||
|
|
||||||
|
- Added generated human-facing resource docs for Gitea and future ChristIT.com catalog work.
|
||||||
|
|
||||||
|
## 0.1.2 - 2026-07-12
|
||||||
|
|
||||||
|
- Phase 2 generated public docs: added a docs generator that writes `RESOURCE_INDEX.md` and per-resource detail pages from source manifests and generated package catalogs.
|
||||||
|
|
||||||
|
## 0.1.1 - 2026-07-12
|
||||||
|
|
||||||
- Enriched the KJV source manifest with translation, edition, contributor, feature, attachment, license, and catalog-display metadata.
|
- Enriched the KJV source manifest with translation, edition, contributor, feature, attachment, license, and catalog-display metadata.
|
||||||
- Recorded the reusable manifest convention for future Bible translations and study resources.
|
- Recorded the reusable manifest convention for future Bible translations and study resources.
|
||||||
- Adopted the convention that each named implementation phase bumps the repo version and is committed locally and remotely.
|
- Adopted the convention that each named implementation phase bumps the repo version and is committed locally and remotely.
|
||||||
|
|
||||||
## 0.1.1 - 2026-07-12
|
|
||||||
|
|
||||||
- Phase 1 metadata foundation: expanded the KJV manifest and manifest documentation so future translations can describe editions, source text basis, contributors, concordance links, study notes, commentaries, maps, and other attachments.
|
- Phase 1 metadata foundation: expanded the KJV manifest and manifest documentation so future translations can describe editions, source text basis, contributors, concordance links, study notes, commentaries, maps, and other attachments.
|
||||||
|
|
||||||
## 0.1.0 - 2026-07-12
|
## 0.1.0 - 2026-07-12
|
||||||
|
|||||||
@@ -20,6 +20,13 @@ npm run import:kjv
|
|||||||
|
|
||||||
Generated packages land under `packages/json/<resource-id>/`.
|
Generated packages land under `packages/json/<resource-id>/`.
|
||||||
|
|
||||||
|
## Resource Index
|
||||||
|
|
||||||
|
Generated human-facing resource docs:
|
||||||
|
|
||||||
|
- `RESOURCE_INDEX.md`
|
||||||
|
- `docs/resources/kjv-eng-kjv2006.md`
|
||||||
|
|
||||||
## Repo Rules
|
## Repo Rules
|
||||||
|
|
||||||
- Every hosted text needs a source manifest.
|
- Every hosted text needs a source manifest.
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# LibreBible Resource Index
|
||||||
|
|
||||||
|
This file is generated from source manifests and package catalogs. Edit `sources/*.json`, package generators, or catalog scripts instead of hand-editing this index.
|
||||||
|
|
||||||
|
## Available Resources
|
||||||
|
|
||||||
|
| Resource | Type | Language | Date / Edition | Source | License | Features | Attachments | Counts | Detail |
|
||||||
|
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| [King James (Authorized) Version](docs/resources/kjv-eng-kjv2006.md) | translation | English (eng) - archaic British | 1611; 1769 edition | eBible.org | Public Domain (redistributable) | Bible text, Strong's-linked words, USFM source | Strong's links, future: study_notes, future: commentary, future: cross_references, future: morphology, future: lemma_links, future: lexicon, future: dictionary, future: maps, future: timeline, future: media | 66 books, 31102 verses, 348884 Strong's links | [Details](docs/resources/kjv-eng-kjv2006.md) |
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# King James (Authorized) Version
|
||||||
|
|
||||||
|
Public-domain KJV package based on the 1769 standardized text, with Strong's numbers embedded in the source USFM.
|
||||||
|
|
||||||
|
## Identity
|
||||||
|
|
||||||
|
- Resource ID: `kjv-eng-kjv2006`
|
||||||
|
- Type: translation
|
||||||
|
- Abbreviation: KJV
|
||||||
|
- Short title: King James Version
|
||||||
|
- Alternate IDs: ENGKJV, eng-kjv2006
|
||||||
|
- Language: English (eng) - archaic British
|
||||||
|
- Canon: protocanon
|
||||||
|
|
||||||
|
## Translation
|
||||||
|
|
||||||
|
- Base title: King James Version
|
||||||
|
- Translation year: 1611
|
||||||
|
- Edition: 1769 standardized text with Strong's numbers added
|
||||||
|
- Edition year: 1769
|
||||||
|
- Source text basis: Authorized Version / King James Version standardized text of 1769
|
||||||
|
- Tradition: Protestant
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
- Provider: eBible.org
|
||||||
|
- Upstream ID: eng-kjv2006
|
||||||
|
- Upstream page: https://ebible.org/find/show.php?id=eng-kjv2006
|
||||||
|
- Download URL: https://ebible.org/Scriptures/eng-kjv2006_usfm.zip
|
||||||
|
- Source format: usfm-zip
|
||||||
|
- Upstream last updated: 2026-05-16
|
||||||
|
- Available upstream formats: browser, mobile-html, epub, pdf, sword, plain-text, vpl-sql, browser-bible, usfx, usfm, xetex
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
- Name: Public Domain
|
||||||
|
- Redistribution allowed: Yes
|
||||||
|
- License/source URL: https://ebible.org/find/show.php?id=eng-kjv2006
|
||||||
|
- Attribution: This free text is provided courtesy of CrossWire Bible Society and eBible.org.
|
||||||
|
- Jurisdiction notes: eBible states this work is firmly public domain outside the United Kingdom; UK printing/import may be restricted by Crown letters patent.
|
||||||
|
- Restrictions: Printing this translation in the United Kingdom or importing printed copies into the UK may require permission from the Crown patent holders.
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
- King James Version translators: translation
|
||||||
|
- CrossWire Bible Society: source text provider
|
||||||
|
- eBible.org: publisher and package provider
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Bible text: translation_text; languages: eng; embedded
|
||||||
|
- Strong's-linked words: concordance_links; languages: hebrew, aramaic, greek; systems: strongs; embedded; package: packages/json/kjv-eng-kjv2006/strongs-links.jsonl
|
||||||
|
- USFM source: source_format; format: usfm
|
||||||
|
|
||||||
|
## Attachments
|
||||||
|
|
||||||
|
Included:
|
||||||
|
- Strong's links: concordance_links; word-to-strongs; anchors: verse, word, strongs_number; languages: hebrew, aramaic, greek; systems: strongs; package: packages/json/kjv-eng-kjv2006/strongs-links.jsonl
|
||||||
|
|
||||||
|
Supported future attachment types:
|
||||||
|
- study_notes
|
||||||
|
- commentary
|
||||||
|
- cross_references
|
||||||
|
- morphology
|
||||||
|
- lemma_links
|
||||||
|
- lexicon
|
||||||
|
- dictionary
|
||||||
|
- maps
|
||||||
|
- timeline
|
||||||
|
- media
|
||||||
|
|
||||||
|
## Generated Package
|
||||||
|
|
||||||
|
- Package catalog: packages/json/kjv-eng-kjv2006/catalog.json
|
||||||
|
- Verses JSONL: packages/json/kjv-eng-kjv2006/verses.jsonl
|
||||||
|
- Strong's links JSONL: packages/json/kjv-eng-kjv2006/strongs-links.jsonl
|
||||||
|
- Source SHA-256: 4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d
|
||||||
|
- Last checked: 2026-07-12T02:18:30Z
|
||||||
|
|
||||||
|
## Counts
|
||||||
|
|
||||||
|
- Books: 66
|
||||||
|
- Verses: 31102
|
||||||
|
- Strong's links: 348884
|
||||||
|
|
||||||
|
## Package Checksums
|
||||||
|
|
||||||
|
- verses_jsonl: `verses.jsonl` (e3102f854a99c4788ed259ec61cb93fea830845c0788c8c0929bc77e9db6ca10)
|
||||||
|
- strongs_jsonl: `strongs-links.jsonl` (fa9702224776509275ea17fb245cb72150f1c262c4fbe44c7161e8e83866c779)
|
||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "libre-bible-data",
|
"name": "libre-bible-data",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "libre-bible-data",
|
"name": "libre-bible-data",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"adm-zip": "^0.5.16"
|
"adm-zip": "^0.5.16"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "libre-bible-data",
|
"name": "libre-bible-data",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"check": "node scripts/check-sources.js",
|
"check": "node scripts/check-sources.js",
|
||||||
|
"docs": "node scripts/generate-docs.js",
|
||||||
"import:kjv": "node scripts/import-usfm.js sources/kjv-eng-kjv2006.json",
|
"import:kjv": "node scripts/import-usfm.js sources/kjv-eng-kjv2006.json",
|
||||||
"build": "npm run check && npm run import:kjv"
|
"build": "npm run check && npm run import:kjv && npm run docs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"adm-zip": "^0.5.16"
|
"adm-zip": "^0.5.16"
|
||||||
|
|||||||
@@ -0,0 +1,269 @@
|
|||||||
|
import { mkdir, readdir, writeFile } from 'node:fs/promises'
|
||||||
|
import path from 'node:path'
|
||||||
|
import { readJson } from './lib.js'
|
||||||
|
|
||||||
|
const root = process.cwd()
|
||||||
|
const sourcesDir = path.join(root, 'sources')
|
||||||
|
const docsResourcesDir = path.join(root, 'docs', 'resources')
|
||||||
|
|
||||||
|
const sourceFiles = (await readdir(sourcesDir))
|
||||||
|
.filter((file) => file.endsWith('.json'))
|
||||||
|
.sort((a, b) => a.localeCompare(b))
|
||||||
|
|
||||||
|
const resources = []
|
||||||
|
|
||||||
|
for (const file of sourceFiles) {
|
||||||
|
const manifest = await readJson(path.join(sourcesDir, file))
|
||||||
|
const packageCatalogPath = path.join(root, 'packages', 'json', manifest.id, 'catalog.json')
|
||||||
|
let packageCatalog = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
packageCatalog = await readJson(packageCatalogPath)
|
||||||
|
} catch {
|
||||||
|
packageCatalog = null
|
||||||
|
}
|
||||||
|
|
||||||
|
resources.push({ manifest, packageCatalog })
|
||||||
|
}
|
||||||
|
|
||||||
|
await mkdir(docsResourcesDir, { recursive: true })
|
||||||
|
|
||||||
|
const index = [
|
||||||
|
'# LibreBible Resource Index',
|
||||||
|
'',
|
||||||
|
'This file is generated from source manifests and package catalogs. Edit `sources/*.json`, package generators, or catalog scripts instead of hand-editing this index.',
|
||||||
|
'',
|
||||||
|
'## Available Resources',
|
||||||
|
'',
|
||||||
|
'| Resource | Type | Language | Date / Edition | Source | License | Features | Attachments | Counts | Detail |',
|
||||||
|
'| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |',
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const resource of resources) {
|
||||||
|
const { manifest, packageCatalog } = resource
|
||||||
|
const detailPath = `docs/resources/${manifest.id}.md`
|
||||||
|
index.push(
|
||||||
|
[
|
||||||
|
link(manifest.title, detailPath),
|
||||||
|
manifest.resource_type ?? 'resource',
|
||||||
|
languageLabel(manifest),
|
||||||
|
editionLabel(manifest),
|
||||||
|
sourceLabel(manifest),
|
||||||
|
licenseLabel(manifest),
|
||||||
|
featureLabels(manifest).join(', ') || 'None listed',
|
||||||
|
attachmentLabels(manifest).join(', ') || 'None listed',
|
||||||
|
countsLabel(packageCatalog),
|
||||||
|
link('Details', detailPath),
|
||||||
|
].join(' | ').replace(/^/, '| ').replace(/$/, ' |'),
|
||||||
|
)
|
||||||
|
|
||||||
|
await writeFile(
|
||||||
|
path.join(docsResourcesDir, `${manifest.id}.md`),
|
||||||
|
`${resourceDetailMarkdown(manifest, packageCatalog)}\n`,
|
||||||
|
'utf8',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeFile(path.join(root, 'RESOURCE_INDEX.md'), `${index.join('\n')}\n`, 'utf8')
|
||||||
|
|
||||||
|
console.log(`Generated RESOURCE_INDEX.md and ${resources.length} resource detail page(s).`)
|
||||||
|
|
||||||
|
function resourceDetailMarkdown(manifest, packageCatalog) {
|
||||||
|
const lines = [
|
||||||
|
`# ${manifest.title}`,
|
||||||
|
'',
|
||||||
|
manifest.catalog_display?.summary ?? manifest.translation?.public_description ?? '',
|
||||||
|
'',
|
||||||
|
'## Identity',
|
||||||
|
'',
|
||||||
|
`- Resource ID: \`${manifest.id}\``,
|
||||||
|
`- Type: ${manifest.resource_type ?? 'resource'}`,
|
||||||
|
`- Abbreviation: ${manifest.abbreviation ?? 'n/a'}`,
|
||||||
|
`- Short title: ${manifest.short_title ?? manifest.title}`,
|
||||||
|
`- Alternate IDs: ${formatList(manifest.alternate_ids)}`,
|
||||||
|
`- Language: ${languageLabel(manifest)}`,
|
||||||
|
`- Canon: ${manifest.canon?.scope ?? 'n/a'}`,
|
||||||
|
'',
|
||||||
|
'## Translation',
|
||||||
|
'',
|
||||||
|
`- Base title: ${manifest.translation?.base_title ?? 'n/a'}`,
|
||||||
|
`- Translation year: ${manifest.translation?.translation_year ?? 'n/a'}`,
|
||||||
|
`- Edition: ${manifest.translation?.edition ?? 'n/a'}`,
|
||||||
|
`- Edition year: ${manifest.translation?.edition_year ?? 'n/a'}`,
|
||||||
|
`- Source text basis: ${manifest.translation?.source_text_basis ?? 'n/a'}`,
|
||||||
|
`- Tradition: ${manifest.translation?.tradition ?? 'n/a'}`,
|
||||||
|
'',
|
||||||
|
'## Source',
|
||||||
|
'',
|
||||||
|
`- Provider: ${manifest.source?.provider ?? 'n/a'}`,
|
||||||
|
`- Upstream ID: ${manifest.source?.upstream_id ?? 'n/a'}`,
|
||||||
|
`- Upstream page: ${manifest.source?.url ?? 'n/a'}`,
|
||||||
|
`- Download URL: ${manifest.source?.download_url ?? 'n/a'}`,
|
||||||
|
`- Source format: ${manifest.source?.format ?? 'n/a'}`,
|
||||||
|
`- Upstream last updated: ${manifest.source?.upstream_last_updated ?? 'n/a'}`,
|
||||||
|
`- Available upstream formats: ${formatList(manifest.source?.available_formats)}`,
|
||||||
|
'',
|
||||||
|
'## License',
|
||||||
|
'',
|
||||||
|
`- Name: ${manifest.license?.name ?? 'n/a'}`,
|
||||||
|
`- Redistribution allowed: ${manifest.license?.redistribution === true ? 'Yes' : 'No or unknown'}`,
|
||||||
|
`- License/source URL: ${manifest.license?.source_license_url ?? 'n/a'}`,
|
||||||
|
`- Attribution: ${manifest.license?.attribution ?? 'n/a'}`,
|
||||||
|
`- Jurisdiction notes: ${manifest.license?.jurisdiction_notes ?? 'n/a'}`,
|
||||||
|
`- Restrictions: ${manifest.license?.restricted_notes ?? 'n/a'}`,
|
||||||
|
'',
|
||||||
|
'## Contributors',
|
||||||
|
'',
|
||||||
|
...contributorsList(manifest),
|
||||||
|
'',
|
||||||
|
'## Features',
|
||||||
|
'',
|
||||||
|
...featuresList(manifest),
|
||||||
|
'',
|
||||||
|
'## Attachments',
|
||||||
|
'',
|
||||||
|
...attachmentsList(manifest),
|
||||||
|
'',
|
||||||
|
'## Generated Package',
|
||||||
|
'',
|
||||||
|
`- Package catalog: ${manifest.packages?.json_catalog ?? 'n/a'}`,
|
||||||
|
`- Verses JSONL: ${manifest.packages?.verses_jsonl ?? 'n/a'}`,
|
||||||
|
`- Strong\'s links JSONL: ${manifest.packages?.strongs_jsonl ?? 'n/a'}`,
|
||||||
|
`- Source SHA-256: ${packageCatalog?.source_sha256 ?? manifest.checks?.expected_sha256 ?? 'n/a'}`,
|
||||||
|
`- Last checked: ${manifest.checks?.last_checked_at ?? 'n/a'}`,
|
||||||
|
'',
|
||||||
|
'## Counts',
|
||||||
|
'',
|
||||||
|
`- Books: ${packageCatalog?.counts?.books ?? 'n/a'}`,
|
||||||
|
`- Verses: ${packageCatalog?.counts?.verses ?? 'n/a'}`,
|
||||||
|
`- Strong\'s links: ${packageCatalog?.counts?.strongs_links ?? 'n/a'}`,
|
||||||
|
'',
|
||||||
|
'## Package Checksums',
|
||||||
|
'',
|
||||||
|
...packageFilesList(packageCatalog),
|
||||||
|
]
|
||||||
|
|
||||||
|
return lines.filter((line, index, all) => !(line === '' && all[index - 1] === '')).join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
function languageLabel(manifest) {
|
||||||
|
if (typeof manifest.language === 'string') return manifest.language
|
||||||
|
const parts = [
|
||||||
|
manifest.language?.name,
|
||||||
|
manifest.language?.code ? `(${manifest.language.code})` : null,
|
||||||
|
manifest.language?.dialect ? `- ${manifest.language.dialect}` : null,
|
||||||
|
]
|
||||||
|
return parts.filter(Boolean).join(' ') || 'n/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
function editionLabel(manifest) {
|
||||||
|
const translationYear = manifest.translation?.translation_year
|
||||||
|
const editionYear = manifest.translation?.edition_year
|
||||||
|
const edition = manifest.translation?.edition
|
||||||
|
|
||||||
|
if (translationYear && editionYear) return `${translationYear}; ${editionYear} edition`
|
||||||
|
if (editionYear) return `${editionYear} edition`
|
||||||
|
return edition ?? 'n/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
function sourceLabel(manifest) {
|
||||||
|
return manifest.source?.provider ?? 'n/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
function licenseLabel(manifest) {
|
||||||
|
const name = manifest.license?.name ?? 'n/a'
|
||||||
|
const redistribution = manifest.license?.redistribution === true ? 'redistributable' : 'restricted/unknown'
|
||||||
|
return `${name} (${redistribution})`
|
||||||
|
}
|
||||||
|
|
||||||
|
function featureLabels(manifest) {
|
||||||
|
return (manifest.features ?? []).map((feature) => feature.label ?? feature.id ?? feature.type).filter(Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachmentLabels(manifest) {
|
||||||
|
return [
|
||||||
|
...(manifest.attachments?.included ?? []).map((attachment) => attachment.label ?? attachment.id),
|
||||||
|
...(manifest.attachments?.supported_future_types ?? []).map((type) => `future: ${type}`),
|
||||||
|
].filter(Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
function countsLabel(packageCatalog) {
|
||||||
|
if (!packageCatalog?.counts) return 'n/a'
|
||||||
|
const counts = packageCatalog.counts
|
||||||
|
const parts = [
|
||||||
|
counts.books != null ? `${counts.books} books` : null,
|
||||||
|
counts.verses != null ? `${counts.verses} verses` : null,
|
||||||
|
counts.strongs_links != null ? `${counts.strongs_links} Strong's links` : null,
|
||||||
|
]
|
||||||
|
return parts.filter(Boolean).join(', ')
|
||||||
|
}
|
||||||
|
|
||||||
|
function contributorsList(manifest) {
|
||||||
|
const contributors = manifest.contributors ?? []
|
||||||
|
if (contributors.length === 0) return ['- None listed.']
|
||||||
|
return contributors.map((contributor) => `- ${contributor.name}: ${contributor.role}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function featuresList(manifest) {
|
||||||
|
const features = manifest.features ?? []
|
||||||
|
if (features.length === 0) return ['- None listed.']
|
||||||
|
return features.map((feature) => {
|
||||||
|
const details = [
|
||||||
|
feature.type,
|
||||||
|
feature.languages?.length ? `languages: ${feature.languages.join(', ')}` : null,
|
||||||
|
feature.systems?.length ? `systems: ${feature.systems.join(', ')}` : null,
|
||||||
|
feature.format ? `format: ${feature.format}` : null,
|
||||||
|
feature.embedded === true ? 'embedded' : null,
|
||||||
|
feature.package ? `package: ${feature.package}` : null,
|
||||||
|
].filter(Boolean)
|
||||||
|
return `- ${feature.label ?? feature.id}: ${details.join('; ') || 'listed'}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachmentsList(manifest) {
|
||||||
|
const included = manifest.attachments?.included ?? []
|
||||||
|
const future = manifest.attachments?.supported_future_types ?? []
|
||||||
|
const lines = []
|
||||||
|
|
||||||
|
if (included.length > 0) {
|
||||||
|
lines.push('Included:')
|
||||||
|
for (const attachment of included) {
|
||||||
|
lines.push(
|
||||||
|
`- ${attachment.label ?? attachment.id}: ${[
|
||||||
|
attachment.resource_type,
|
||||||
|
attachment.relationship,
|
||||||
|
attachment.anchor_types?.length ? `anchors: ${attachment.anchor_types.join(', ')}` : null,
|
||||||
|
attachment.languages?.length ? `languages: ${attachment.languages.join(', ')}` : null,
|
||||||
|
attachment.systems?.length ? `systems: ${attachment.systems.join(', ')}` : null,
|
||||||
|
attachment.package ? `package: ${attachment.package}` : null,
|
||||||
|
].filter(Boolean).join('; ')}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lines.push('- No included attachments listed.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (future.length > 0) {
|
||||||
|
lines.push('')
|
||||||
|
lines.push('Supported future attachment types:')
|
||||||
|
for (const type of future) {
|
||||||
|
lines.push(`- ${type}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
function packageFilesList(packageCatalog) {
|
||||||
|
const files = packageCatalog?.files
|
||||||
|
if (!files) return ['- No package file checksums listed.']
|
||||||
|
return Object.entries(files).map(([key, value]) => `- ${key}: \`${value.path}\` (${value.sha256})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatList(values) {
|
||||||
|
return values?.length ? values.join(', ') : 'n/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
function link(label, href) {
|
||||||
|
return `[${label}](${href})`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user