Phase 3 expand machine catalogs

This commit is contained in:
2026-07-11 22:10:34 -05:00
parent afeb2c4d3b
commit 564eaea5a0
7 changed files with 271 additions and 15 deletions
+7 -1
View File
@@ -2,10 +2,16 @@
## Current
- Added generated human-facing resource docs for Gitea and future ChristIT.com catalog work.
- Expanded machine catalogs so ChristIT.com and apps can read rich resource metadata directly from JSON.
## 0.1.3 - 2026-07-12
- Phase 3 machine catalog foundation: expanded aggregate and per-resource JSON catalogs with schema version, resource identity, translation metadata, contributors, features, attachments, source/license details, package paths, checksums, and file sizes.
## 0.1.2 - 2026-07-12
- Added generated human-facing resource docs for Gitea and future ChristIT.com catalog work.
- 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
+8
View File
@@ -99,6 +99,14 @@ Attachment metadata should identify:
- Build/import scripts should fail when required source, license, checksum, or package metadata is missing.
- The public catalog must not silently disagree with the source manifest.
## Machine Catalogs
- `packages/json/catalog.json` is the machine-readable index for ChristIT.com, Libre Study, GracePress Bible Tooltip, and future consumers.
- Per-resource package catalogs, such as `packages/json/<resource-id>/catalog.json`, should carry the full resource metadata needed to render a public detail page without scraping Markdown.
- Machine catalogs should include schema version, project name, resource id, resource type, title, abbreviation, language, script, canon, translation/edition metadata, contributors, features, attachments, source, license, display summary, package paths, counts, file checksums, and source check metadata.
- Markdown docs are a human-readable projection of the same metadata. They must not become a separate truth source.
- Public ChristIT.com pages and app/plugin package discovery should read machine catalogs first, then link to Markdown docs for explanation.
## Update Workflow
- Update checks must be mechanical and repeatable.
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "libre-bible-data",
"version": "0.1.2",
"version": "0.1.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "libre-bible-data",
"version": "0.1.2",
"version": "0.1.3",
"dependencies": {
"adm-zip": "^0.5.16"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "libre-bible-data",
"version": "0.1.2",
"version": "0.1.3",
"private": true,
"type": "module",
"scripts": {
+121 -1
View File
@@ -1,15 +1,51 @@
{
"generated_at": "2026-07-12T02:51:51.354Z",
"schema_version": "librebible.index-catalog.v1",
"project": "LibreBible",
"generated_at": "2026-07-12T03:10:02.881Z",
"resources": [
{
"id": "kjv-eng-kjv2006",
"resource_type": "translation",
"title": "King James (Authorized) Version",
"short_title": "King James Version",
"abbreviation": "KJV",
"alternate_ids": [
"ENGKJV",
"eng-kjv2006"
],
"language": {
"code": "eng",
"name": "English",
"dialect": "archaic British"
},
"script": "Latn",
"canon": {
"scope": "protocanon",
"notes": "eBible describes this package as protocanon only."
},
"translation": {
"base_title": "King James Version",
"edition": "1769 standardized text with Strong's numbers added",
"translation_year": 1611,
"edition_year": 1769,
"source_text_basis": "Authorized Version / King James Version standardized text of 1769",
"tradition": "Protestant",
"public_description": "The King James Version or Authorized Version of the Holy Bible, using the standardized text of 1769, protocanon only, with Strong's numbers added."
},
"contributors": [
{
"name": "King James Version translators",
"role": "translation"
},
{
"name": "CrossWire Bible Society",
"role": "source text provider"
},
{
"name": "eBible.org",
"role": "publisher and package provider"
}
],
"features": [
{
"id": "bible-text",
@@ -43,6 +79,64 @@
"embedded": false
}
],
"attachments": {
"included": [
{
"id": "kjv-eng-kjv2006-strongs-links",
"resource_type": "concordance_links",
"label": "Strong's links",
"relationship": "word-to-strongs",
"anchor_types": [
"verse",
"word",
"strongs_number"
],
"languages": [
"hebrew",
"aramaic",
"greek"
],
"systems": [
"strongs"
],
"source": "Embedded in the eBible USFM package.",
"package": "packages/json/kjv-eng-kjv2006/strongs-links.jsonl"
}
],
"supported_future_types": [
"study_notes",
"commentary",
"cross_references",
"morphology",
"lemma_links",
"lexicon",
"dictionary",
"maps",
"timeline",
"media"
]
},
"source": {
"provider": "eBible.org",
"url": "https://ebible.org/find/show.php?id=eng-kjv2006",
"download_url": "https://ebible.org/Scriptures/eng-kjv2006_usfm.zip",
"format": "usfm-zip",
"upstream_id": "eng-kjv2006",
"upstream_last_updated": "2026-05-16",
"available_formats": [
"browser",
"mobile-html",
"epub",
"pdf",
"sword",
"plain-text",
"vpl-sql",
"browser-bible",
"usfx",
"usfm",
"xetex"
]
},
"license": {
"name": "Public Domain",
"redistribution": true,
@@ -54,11 +148,37 @@
],
"restricted_notes": "Printing this translation in the United Kingdom or importing printed copies into the UK may require permission from the Crown patent holders."
},
"catalog_display": {
"primary_features": [
"Bible text",
"Strong's-linked words",
"USFM source"
],
"summary": "Public-domain KJV package based on the 1769 standardized text, with Strong's numbers embedded in the source USFM."
},
"package_path": "packages/json/kjv-eng-kjv2006/catalog.json",
"source_manifest_path": "sources/kjv-eng-kjv2006.json",
"detail_doc_path": "docs/resources/kjv-eng-kjv2006.md",
"counts": {
"books": 66,
"verses": 31102,
"strongs_links": 348884
},
"files": {
"verses_jsonl": {
"path": "verses.jsonl",
"bytes": 8700726,
"sha256": "e3102f854a99c4788ed259ec61cb93fea830845c0788c8c0929bc77e9db6ca10"
},
"strongs_jsonl": {
"path": "strongs-links.jsonl",
"bytes": 62690394,
"sha256": "fa9702224776509275ea17fb245cb72150f1c262c4fbe44c7161e8e83866c779"
}
},
"checks": {
"expected_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
"last_checked_at": "2026-07-12T02:18:30Z"
}
}
]
+88 -1
View File
@@ -1,12 +1,48 @@
{
"schema_version": "librebible.resource-catalog.v1",
"project": "LibreBible",
"id": "kjv-eng-kjv2006",
"resource_type": "translation",
"title": "King James (Authorized) Version",
"short_title": "King James Version",
"abbreviation": "KJV",
"alternate_ids": [
"ENGKJV",
"eng-kjv2006"
],
"language": {
"code": "eng",
"name": "English",
"dialect": "archaic British"
},
"script": "Latn",
"canon": {
"scope": "protocanon",
"notes": "eBible describes this package as protocanon only."
},
"translation": {
"base_title": "King James Version",
"edition": "1769 standardized text with Strong's numbers added",
"translation_year": 1611,
"edition_year": 1769,
"source_text_basis": "Authorized Version / King James Version standardized text of 1769",
"tradition": "Protestant",
"public_description": "The King James Version or Authorized Version of the Holy Bible, using the standardized text of 1769, protocanon only, with Strong's numbers added."
},
"contributors": [
{
"name": "King James Version translators",
"role": "translation"
},
{
"name": "CrossWire Bible Society",
"role": "source text provider"
},
{
"name": "eBible.org",
"role": "publisher and package provider"
}
],
"features": [
{
"id": "bible-text",
@@ -40,6 +76,43 @@
"embedded": false
}
],
"attachments": {
"included": [
{
"id": "kjv-eng-kjv2006-strongs-links",
"resource_type": "concordance_links",
"label": "Strong's links",
"relationship": "word-to-strongs",
"anchor_types": [
"verse",
"word",
"strongs_number"
],
"languages": [
"hebrew",
"aramaic",
"greek"
],
"systems": [
"strongs"
],
"source": "Embedded in the eBible USFM package.",
"package": "packages/json/kjv-eng-kjv2006/strongs-links.jsonl"
}
],
"supported_future_types": [
"study_notes",
"commentary",
"cross_references",
"morphology",
"lemma_links",
"lexicon",
"dictionary",
"maps",
"timeline",
"media"
]
},
"source": {
"provider": "eBible.org",
"url": "https://ebible.org/find/show.php?id=eng-kjv2006",
@@ -72,12 +145,24 @@
],
"restricted_notes": "Printing this translation in the United Kingdom or importing printed copies into the UK may require permission from the Crown patent holders."
},
"catalog_display": {
"primary_features": [
"Bible text",
"Strong's-linked words",
"USFM source"
],
"summary": "Public-domain KJV package based on the 1769 standardized text, with Strong's numbers embedded in the source USFM."
},
"importer": {
"name": "scripts/import-usfm.js",
"version": "0.1.0"
},
"generated_at": "2026-07-12T02:51:51.354Z",
"generated_at": "2026-07-12T03:10:02.881Z",
"source_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
"checks": {
"expected_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
"last_checked_at": "2026-07-12T02:18:30Z"
},
"counts": {
"books": 66,
"verses": 31102,
@@ -86,10 +171,12 @@
"files": {
"verses_jsonl": {
"path": "verses.jsonl",
"bytes": 8700726,
"sha256": "e3102f854a99c4788ed259ec61cb93fea830845c0788c8c0929bc77e9db6ca10"
},
"strongs_jsonl": {
"path": "strongs-links.jsonl",
"bytes": 62690394,
"sha256": "fa9702224776509275ea17fb245cb72150f1c262c4fbe44c7161e8e83866c779"
}
}
+44 -9
View File
@@ -1,5 +1,5 @@
import AdmZip from 'adm-zip'
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
import path from 'node:path'
import {
cleanUsfmText,
@@ -110,50 +110,85 @@ await writeFile(
'utf8',
)
const versesPackage = await packageFile(outputDir, 'verses.jsonl')
const strongsPackage = await packageFile(outputDir, 'strongs-links.jsonl')
const catalog = {
schema_version: 'librebible.resource-catalog.v1',
project: manifest.project_name ?? 'LibreBible',
id: manifest.id,
resource_type: manifest.resource_type,
title: manifest.title,
short_title: manifest.short_title,
abbreviation: manifest.abbreviation,
alternate_ids: manifest.alternate_ids ?? [],
language: manifest.language,
script: manifest.script,
canon: manifest.canon,
translation: manifest.translation,
contributors: manifest.contributors ?? [],
features: manifest.features,
attachments: manifest.attachments,
source: manifest.source,
license: manifest.license,
catalog_display: manifest.catalog_display,
importer: manifest.importer,
generated_at: new Date().toISOString(),
source_sha256: archiveSha,
checks: manifest.checks,
counts: {
books: new Set(verses.map((verse) => verse.book_id)).size,
verses: verses.length,
strongs_links: strongsLinks.length,
},
files: {
verses_jsonl: {
path: 'verses.jsonl',
sha256: await sha256File(path.join(outputDir, 'verses.jsonl')),
},
strongs_jsonl: {
path: 'strongs-links.jsonl',
sha256: await sha256File(path.join(outputDir, 'strongs-links.jsonl')),
},
verses_jsonl: versesPackage,
strongs_jsonl: strongsPackage,
},
}
await writeJson(path.join(outputDir, 'catalog.json'), catalog)
await writeJson(path.join(root, 'packages', 'json', 'catalog.json'), {
schema_version: 'librebible.index-catalog.v1',
project: manifest.project_name ?? 'LibreBible',
generated_at: catalog.generated_at,
resources: [
{
id: catalog.id,
resource_type: catalog.resource_type,
title: catalog.title,
short_title: catalog.short_title,
abbreviation: catalog.abbreviation,
alternate_ids: catalog.alternate_ids,
language: catalog.language,
script: catalog.script,
canon: catalog.canon,
translation: catalog.translation,
contributors: catalog.contributors,
features: catalog.features,
attachments: catalog.attachments,
source: catalog.source,
license: catalog.license,
catalog_display: catalog.catalog_display,
package_path: `packages/json/${catalog.id}/catalog.json`,
source_manifest_path: `sources/${path.basename(manifestPath)}`,
detail_doc_path: `docs/resources/${catalog.id}.md`,
counts: catalog.counts,
files: catalog.files,
checks: catalog.checks,
},
],
})
console.log(`${manifest.id}: imported ${catalog.counts.verses} verses`)
console.log(`${manifest.id}: imported ${catalog.counts.strongs_links} Strong's links`)
async function packageFile(outputDir, fileName) {
const filePath = path.join(outputDir, fileName)
const fileStat = await stat(filePath)
return {
path: fileName,
bytes: fileStat.size,
sha256: await sha256File(filePath),
}
}