Restore source-neutral LibreBible catalog
This commit is contained in:
+8
-4
@@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
## Current
|
## Current
|
||||||
|
|
||||||
- Added the CrossWire/SWORD import foundation with module audit tooling, license registry, and pilot commentary/dictionary packages.
|
- Restored LibreBible to a source-neutral public catalog foundation.
|
||||||
|
|
||||||
|
## 0.1.5 - 2026-07-12
|
||||||
|
|
||||||
|
- Removed the external module pilot importer, audit outputs, generated pilot packages, and public catalog entries.
|
||||||
|
- Restored the active catalog to the KJV/eBible foundation while broader free-resource intake is designed around resource metadata, licensing, provenance, and generated packages.
|
||||||
|
- Kept aggregate catalog generation as source-neutral infrastructure.
|
||||||
|
|
||||||
## 0.1.4 - 2026-07-12
|
## 0.1.4 - 2026-07-12
|
||||||
|
|
||||||
- Phase 6 CrossWire/SWORD foundation: added SWORD module inventory/audit tooling, license approval registry, pilot module registry, rawzip checksum tracking, and containerized `mod2imp` imports for approved pilot study-aid modules.
|
- Withdrawn pilot: tested an external module intake path for study aids, then removed it from the public direction in 0.1.5.
|
||||||
- Imported pilot SWORD study-aid packages for Jamieson-Fausset-Brown Commentary and Matthew Henry Concise Commentary after public-domain license approval.
|
|
||||||
- Recorded Strong's Hebrew, Strong's Greek, and Nave's Topical Bible as approved-but-deferred candidates pending a cleaner dictionary exporter.
|
|
||||||
- Added aggregate catalog generation from all per-resource package catalogs so future imports do not overwrite the resource index.
|
- Added aggregate catalog generation from all per-resource package catalogs so future imports do not overwrite the resource index.
|
||||||
|
|
||||||
## 0.1.3 - 2026-07-12
|
## 0.1.3 - 2026-07-12
|
||||||
|
|||||||
@@ -107,16 +107,6 @@ Attachment metadata should identify:
|
|||||||
- Markdown docs are a human-readable projection of the same metadata. They must not become a separate truth source.
|
- 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.
|
- Public ChristIT.com pages and app/plugin package discovery should read machine catalogs first, then link to Markdown docs for explanation.
|
||||||
|
|
||||||
## CrossWire/SWORD Intake
|
|
||||||
|
|
||||||
- Treat CrossWire/SWORD as a source channel, not a blanket license approval.
|
|
||||||
- SWORD modules must pass the local license approval registry before generated content is committed under `packages/json/`.
|
|
||||||
- Preserve original SWORD `.conf` metadata, rawzip URL, rawzip checksum, module version, module date, driver, source type, and license text in audit output or source manifests.
|
|
||||||
- Use `scripts/sword-audit.js` to classify candidate modules before import.
|
|
||||||
- Use `scripts/import-sword.js` for approved pilot modules. It downloads CrossWire rawzip packages, extracts them into `cache/sword/library`, exports content through containerized SWORD utilities, then normalizes the result into JSONL packages.
|
|
||||||
- If Docker or SWORD utilities are unavailable, keep the module in audit/review status and do not hand-parse compressed SWORD binary data.
|
|
||||||
- Duplicate Bible texts from SWORD should not be published when the same edition is already sourced from a better upstream package. SWORD may still be used for comparison, commentaries, dictionaries, lexicons, and study aids.
|
|
||||||
|
|
||||||
## Update Workflow
|
## Update Workflow
|
||||||
|
|
||||||
- Update checks must be mechanical and repeatable.
|
- Update checks must be mechanical and repeatable.
|
||||||
@@ -145,7 +135,6 @@ Initial package targets:
|
|||||||
|
|
||||||
Future package targets may include:
|
Future package targets may include:
|
||||||
|
|
||||||
- SWORD-compatible exports.
|
|
||||||
- OSIS/USFM normalized exports.
|
- OSIS/USFM normalized exports.
|
||||||
- Search indexes.
|
- Search indexes.
|
||||||
- Static web catalogs.
|
- Static web catalogs.
|
||||||
|
|||||||
@@ -16,16 +16,12 @@ The eBible listing identifies it as public domain, describes it as the 1769 King
|
|||||||
npm install
|
npm install
|
||||||
npm run check
|
npm run check
|
||||||
npm run import:kjv
|
npm run import:kjv
|
||||||
npm run sword:audit
|
|
||||||
npm run import:sword
|
|
||||||
npm run catalog
|
npm run catalog
|
||||||
npm run docs
|
npm run docs
|
||||||
```
|
```
|
||||||
|
|
||||||
Generated packages land under `packages/json/<resource-id>/`.
|
Generated packages land under `packages/json/<resource-id>/`.
|
||||||
|
|
||||||
SWORD study-aid imports use CrossWire rawzip packages plus containerized SWORD utilities. Docker Desktop must be running for `npm run import:sword`.
|
|
||||||
|
|
||||||
## Resource Index
|
## Resource Index
|
||||||
|
|
||||||
Generated human-facing resource docs:
|
Generated human-facing resource docs:
|
||||||
|
|||||||
@@ -7,5 +7,3 @@ This file is generated from source manifests and package catalogs. Edit `sources
|
|||||||
| Resource | Type | Language | Date / Edition | Source | License | Features | Attachments | Counts | Detail |
|
| 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) |
|
| [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) |
|
||||||
| [Jamieson Fausset Brown Bible Commentary](docs/resources/sword-jfb.md) | commentary | English (en) | n/a | CrossWire Bible Society | Public Domain (redistributable) | Commentary entries, SWORD source | Commentary entries | 16945 commentary entries | [Details](docs/resources/sword-jfb.md) |
|
|
||||||
| [Matthew Henry's Concise Commentary on the Whole Bible](docs/resources/sword-mhcc.md) | commentary | English (en) | n/a | CrossWire Bible Society | Public Domain (redistributable) | Commentary entries, SWORD source | Commentary entries | 4059 commentary entries | [Details](docs/resources/sword-mhcc.md) |
|
|
||||||
|
|||||||
+1
-2
@@ -86,7 +86,6 @@ Goal: grow beyond KJV while keeping license discipline.
|
|||||||
Priority sources:
|
Priority sources:
|
||||||
|
|
||||||
- eBible.org freely redistributable translations.
|
- eBible.org freely redistributable translations.
|
||||||
- CrossWire/SWORD modules with clear redistribution rights.
|
|
||||||
- unfoldingWord/Door43 resources where licenses permit redistribution.
|
- unfoldingWord/Door43 resources where licenses permit redistribution.
|
||||||
- Open English Bible.
|
- Open English Bible.
|
||||||
- World English Bible.
|
- World English Bible.
|
||||||
@@ -96,7 +95,7 @@ Tasks:
|
|||||||
|
|
||||||
- Add source manifests before adding generated text.
|
- Add source manifests before adding generated text.
|
||||||
- Record upstream license, redistribution, and attribution details before import.
|
- Record upstream license, redistribution, and attribution details before import.
|
||||||
- Add importer support for additional formats as needed: USFM zip, OSIS, SWORD modules, plain text, TSV/CSV, JSON, or XML.
|
- Add importer support for additional formats as needed: USFM zip, OSIS, plain text, TSV/CSV, JSON, XML, image files, or geospatial data.
|
||||||
- Normalize all imported translations into shared package shapes.
|
- Normalize all imported translations into shared package shapes.
|
||||||
- Keep questionable resources as source metadata only until redistribution is clear.
|
- Keep questionable resources as source metadata only until redistribution is clear.
|
||||||
|
|
||||||
|
|||||||
@@ -1,155 +0,0 @@
|
|||||||
{
|
|
||||||
"schema_version": "librebible.sword-module-audit.v1",
|
|
||||||
"generated_at": "2026-07-12T04:31:18.041Z",
|
|
||||||
"repository": {
|
|
||||||
"id": "crosswire-main",
|
|
||||||
"name": "CrossWire Main",
|
|
||||||
"mods_tarball_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d.tar.gz",
|
|
||||||
"package_base_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip"
|
|
||||||
},
|
|
||||||
"catalog_sha256": "92c890b80979ffff7a7580c9092331cdd847f8f9effa98f3ed7e82e317f781b4",
|
|
||||||
"modules": [
|
|
||||||
{
|
|
||||||
"id": "KJV",
|
|
||||||
"intended_resource_type": "translation",
|
|
||||||
"found": true,
|
|
||||||
"title": "King James Version (1769) with Strongs Numbers and Morphology and CatchWords",
|
|
||||||
"abbreviation": "KJV",
|
|
||||||
"lang": "en",
|
|
||||||
"mod_drv": "zText",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"version": "3.1",
|
|
||||||
"sword_version_date": "2023-07-19",
|
|
||||||
"distribution_license": "GPL",
|
|
||||||
"text_source": "https://gitlab.com/crosswire-bible-society/kjv",
|
|
||||||
"package_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/KJV.zip",
|
|
||||||
"license_status": "review",
|
|
||||||
"license_rule": null,
|
|
||||||
"redistribution": false,
|
|
||||||
"commercial_use": null,
|
|
||||||
"share_alike": false,
|
|
||||||
"import_enabled": true,
|
|
||||||
"import_status": "candidate",
|
|
||||||
"review_notes": "No approval rule matched the module license metadata.",
|
|
||||||
"reason": "Baseline Bible text module with Strong's and morphology metadata, useful for comparing against the eBible KJV package."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "JFB",
|
|
||||||
"intended_resource_type": "commentary",
|
|
||||||
"found": true,
|
|
||||||
"title": "Jamieson Fausset Brown Bible Commentary",
|
|
||||||
"abbreviation": "JFB",
|
|
||||||
"lang": "en",
|
|
||||||
"mod_drv": "zCom4",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"version": "3.0",
|
|
||||||
"sword_version_date": "2021-02-15",
|
|
||||||
"distribution_license": "Public Domain",
|
|
||||||
"text_source": "https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt",
|
|
||||||
"package_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/JFB.zip",
|
|
||||||
"license_status": "approved",
|
|
||||||
"license_rule": "public domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"import_enabled": true,
|
|
||||||
"import_status": "candidate",
|
|
||||||
"review_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction.",
|
|
||||||
"reason": "Public-domain whole-Bible commentary candidate."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "MHCC",
|
|
||||||
"intended_resource_type": "commentary",
|
|
||||||
"found": true,
|
|
||||||
"title": "Matthew Henry's Concise Commentary on the Whole Bible",
|
|
||||||
"abbreviation": "MHCC",
|
|
||||||
"lang": "en",
|
|
||||||
"mod_drv": "zCom",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"version": "2.0",
|
|
||||||
"sword_version_date": "2021-02-14",
|
|
||||||
"distribution_license": "Public Domain",
|
|
||||||
"text_source": "https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt",
|
|
||||||
"package_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/MHCC.zip",
|
|
||||||
"license_status": "approved",
|
|
||||||
"license_rule": "public domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"import_enabled": true,
|
|
||||||
"import_status": "candidate",
|
|
||||||
"review_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction.",
|
|
||||||
"reason": "Public-domain concise Matthew Henry commentary candidate."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "StrongsHebrew",
|
|
||||||
"intended_resource_type": "dictionary",
|
|
||||||
"found": true,
|
|
||||||
"title": "Strong's Hebrew Bible Dictionary",
|
|
||||||
"abbreviation": "StrongsHebrew",
|
|
||||||
"lang": "en",
|
|
||||||
"mod_drv": "RawLD",
|
|
||||||
"version": "1.2",
|
|
||||||
"sword_version_date": "2002-01-01",
|
|
||||||
"distribution_license": "Public Domain",
|
|
||||||
"text_source": "http://www.bf.org/",
|
|
||||||
"package_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/StrongsHebrew.zip",
|
|
||||||
"license_status": "approved",
|
|
||||||
"license_rule": "public domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"import_enabled": false,
|
|
||||||
"import_status": "deferred",
|
|
||||||
"review_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction.",
|
|
||||||
"reason": "Strong's Hebrew dictionary candidate. Deferred after containerized mod2imp export timed out during Phase 6; keep in audit queue for a better exporter path."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "StrongsGreek",
|
|
||||||
"intended_resource_type": "dictionary",
|
|
||||||
"found": true,
|
|
||||||
"title": "Strong's Greek Bible Dictionary",
|
|
||||||
"abbreviation": "StrongsGreek",
|
|
||||||
"lang": "en",
|
|
||||||
"mod_drv": "zLD",
|
|
||||||
"source_type": "TEI",
|
|
||||||
"version": "2.0",
|
|
||||||
"distribution_license": "Public Domain",
|
|
||||||
"text_source": "http://www.bf.org/",
|
|
||||||
"package_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/StrongsGreek.zip",
|
|
||||||
"license_status": "approved",
|
|
||||||
"license_rule": "public domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"import_enabled": false,
|
|
||||||
"import_status": "deferred",
|
|
||||||
"review_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction.",
|
|
||||||
"reason": "Strong's Greek dictionary candidate. Deferred after Phase 6 sample inspection showed mojibake in Greek lexical forms from the raw SWORD export path."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Nave",
|
|
||||||
"intended_resource_type": "dictionary",
|
|
||||||
"found": true,
|
|
||||||
"title": "Naveߴs Topical Bible",
|
|
||||||
"abbreviation": "Nave",
|
|
||||||
"lang": "en",
|
|
||||||
"mod_drv": "zLD",
|
|
||||||
"source_type": "TEI",
|
|
||||||
"version": "3.0",
|
|
||||||
"sword_version_date": "2008-11-29",
|
|
||||||
"distribution_license": "Public Domain",
|
|
||||||
"text_source": "https://ccel.org/ccel/n/nave/bible.xml",
|
|
||||||
"package_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/Nave.zip",
|
|
||||||
"license_status": "approved",
|
|
||||||
"license_rule": "public domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"import_enabled": false,
|
|
||||||
"import_status": "deferred",
|
|
||||||
"review_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction.",
|
|
||||||
"reason": "Topical Bible dictionary candidate with public-domain source history. Deferred after containerized mod2imp export timed out during Phase 6; keep in audit queue for a better exporter path."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -23,7 +23,6 @@ Required fields:
|
|||||||
- `source.format`: Upstream source format, such as `usfm-zip`.
|
- `source.format`: Upstream source format, such as `usfm-zip`.
|
||||||
- `source.upstream_id`: Upstream resource id.
|
- `source.upstream_id`: Upstream resource id.
|
||||||
- `source.upstream_last_updated`: Upstream last-updated date when known.
|
- `source.upstream_last_updated`: Upstream last-updated date when known.
|
||||||
- `source.sword`: SWORD-specific metadata when the source is a CrossWire module, including driver, source type, versification, rawzip URL, and original module id.
|
|
||||||
- `license.name`: License or rights label.
|
- `license.name`: License or rights label.
|
||||||
- `license.redistribution`: Whether this repo may redistribute normalized outputs.
|
- `license.redistribution`: Whether this repo may redistribute normalized outputs.
|
||||||
- `license.jurisdiction_notes`: Practical rights notes.
|
- `license.jurisdiction_notes`: Practical rights notes.
|
||||||
|
|||||||
@@ -29,21 +29,20 @@ Public-domain KJV package based on the 1769 standardized text, with Strong's num
|
|||||||
- Download URL: https://ebible.org/Scriptures/eng-kjv2006_usfm.zip
|
- Download URL: https://ebible.org/Scriptures/eng-kjv2006_usfm.zip
|
||||||
- Source format: usfm-zip
|
- Source format: usfm-zip
|
||||||
- Upstream last updated: 2026-05-16
|
- Upstream last updated: 2026-05-16
|
||||||
- Available upstream formats: browser, mobile-html, epub, pdf, sword, plain-text, vpl-sql, browser-bible, usfx, usfm, xetex
|
- Available upstream formats: browser, mobile-html, epub, pdf, plain-text, vpl-sql, browser-bible, usfx, usfm, xetex
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
- Name: Public Domain
|
- Name: Public Domain
|
||||||
- Redistribution allowed: Yes
|
- Redistribution allowed: Yes
|
||||||
- License/source URL: https://ebible.org/find/show.php?id=eng-kjv2006
|
- 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.
|
- Attribution: This free text is provided courtesy of 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.
|
- 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.
|
- Restrictions: Printing this translation in the United Kingdom or importing printed copies into the UK may require permission from the Crown patent holders.
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
- King James Version translators: translation
|
- King James Version translators: translation
|
||||||
- CrossWire Bible Society: source text provider
|
|
||||||
- eBible.org: publisher and package provider
|
- eBible.org: publisher and package provider
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
# Jamieson Fausset Brown Bible Commentary
|
|
||||||
|
|
||||||
Jamieson Fausset Brown Bible Commentary, imported from the CrossWire JFB SWORD module with 16945 commentary entries.
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
|
|
||||||
- Resource ID: `sword-jfb`
|
|
||||||
- Type: commentary
|
|
||||||
- Abbreviation: JFB
|
|
||||||
- Short title: Jamieson Fausset Brown Bible Commentary
|
|
||||||
- Alternate IDs: JFB
|
|
||||||
- Language: English (en)
|
|
||||||
- Canon: KJV
|
|
||||||
|
|
||||||
## Translation
|
|
||||||
|
|
||||||
- Base title: n/a
|
|
||||||
- Translation year: n/a
|
|
||||||
- Edition: n/a
|
|
||||||
- Edition year: n/a
|
|
||||||
- Source text basis: n/a
|
|
||||||
- Tradition: n/a
|
|
||||||
|
|
||||||
## Source
|
|
||||||
|
|
||||||
- Provider: CrossWire Bible Society
|
|
||||||
- Upstream ID: JFB
|
|
||||||
- Upstream page: https://crosswire.org/sword/modules/ModInfo.jsp?modName=JFB
|
|
||||||
- Download URL: https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/JFB.zip
|
|
||||||
- Source format: sword-rawzip
|
|
||||||
- Upstream last updated: 2021-02-15
|
|
||||||
- Available upstream formats: n/a
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
- Name: Public Domain
|
|
||||||
- Redistribution allowed: Yes
|
|
||||||
- License/source URL: https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/jfb.conf
|
|
||||||
- Attribution: Jamieson Fausset Brown Bible Commentary Text source: https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt SWORD module: JFB Provided by CrossWire Bible Society.
|
|
||||||
- Jurisdiction notes: No jurisdiction-specific restriction was found in the SWORD module metadata.
|
|
||||||
- Restrictions: Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction.
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
- Robert Jamieson, A. R. Fausset, and David Brown: commentary authors
|
|
||||||
- CrossWire Bible Society: module provider
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Commentary entries: commentary; languages: eng; embedded; package: packages/json/sword-jfb/commentary.jsonl
|
|
||||||
- SWORD source: source_format; format: OSIS
|
|
||||||
|
|
||||||
## Attachments
|
|
||||||
|
|
||||||
Included:
|
|
||||||
- Commentary entries: commentary; range-to-commentary; anchors: book, chapter, verse, verse_range; languages: eng; package: packages/json/sword-jfb/commentary.jsonl
|
|
||||||
|
|
||||||
## Generated Package
|
|
||||||
|
|
||||||
- Package catalog: packages/json/sword-jfb/catalog.json
|
|
||||||
- Verses JSONL: n/a
|
|
||||||
- Strong's links JSONL: n/a
|
|
||||||
- Entries JSONL: packages/json/sword-jfb/commentary.jsonl
|
|
||||||
- Source SHA-256: a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf
|
|
||||||
- Last checked: 2026-07-12T04:31:19.021Z
|
|
||||||
|
|
||||||
## Counts
|
|
||||||
|
|
||||||
- Books: n/a
|
|
||||||
- Verses: n/a
|
|
||||||
- Strong's links: n/a
|
|
||||||
- Entries: 16945
|
|
||||||
- Commentary entries: 16945
|
|
||||||
- Dictionary entries: n/a
|
|
||||||
|
|
||||||
## Package Checksums
|
|
||||||
|
|
||||||
- commentary_jsonl: `commentary.jsonl` (bf9e2cd40159e0e83f261652b2d4874d9450131575dc6c73d07dc568433a47d9)
|
|
||||||
- source_rawzip: `JFB.zip` (a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf)
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
# Matthew Henry's Concise Commentary on the Whole Bible
|
|
||||||
|
|
||||||
Matthew Henry's Concise Commentary on the Whole Bible, imported from the CrossWire MHCC SWORD module with 4059 commentary entries.
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
|
|
||||||
- Resource ID: `sword-mhcc`
|
|
||||||
- Type: commentary
|
|
||||||
- Abbreviation: MHCC
|
|
||||||
- Short title: Matthew Henry's Concise Commentary on the Whole Bible
|
|
||||||
- Alternate IDs: MHCC
|
|
||||||
- Language: English (en)
|
|
||||||
- Canon: KJV
|
|
||||||
|
|
||||||
## Translation
|
|
||||||
|
|
||||||
- Base title: n/a
|
|
||||||
- Translation year: n/a
|
|
||||||
- Edition: n/a
|
|
||||||
- Edition year: n/a
|
|
||||||
- Source text basis: n/a
|
|
||||||
- Tradition: n/a
|
|
||||||
|
|
||||||
## Source
|
|
||||||
|
|
||||||
- Provider: CrossWire Bible Society
|
|
||||||
- Upstream ID: MHCC
|
|
||||||
- Upstream page: https://crosswire.org/sword/modules/ModInfo.jsp?modName=MHCC
|
|
||||||
- Download URL: https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/MHCC.zip
|
|
||||||
- Source format: sword-rawzip
|
|
||||||
- Upstream last updated: 2021-02-14
|
|
||||||
- Available upstream formats: n/a
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
- Name: Public Domain
|
|
||||||
- Redistribution allowed: Yes
|
|
||||||
- License/source URL: https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/mhcc.conf
|
|
||||||
- Attribution: Matthew Henry's Concise Commentary on the Whole Bible Text source: https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt SWORD module: MHCC Provided by CrossWire Bible Society.
|
|
||||||
- Jurisdiction notes: No jurisdiction-specific restriction was found in the SWORD module metadata.
|
|
||||||
- Restrictions: Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction.
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
- Matthew Henry: commentary author
|
|
||||||
- CrossWire Bible Society: module provider
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Commentary entries: commentary; languages: eng; embedded; package: packages/json/sword-mhcc/commentary.jsonl
|
|
||||||
- SWORD source: source_format; format: OSIS
|
|
||||||
|
|
||||||
## Attachments
|
|
||||||
|
|
||||||
Included:
|
|
||||||
- Commentary entries: commentary; range-to-commentary; anchors: book, chapter, verse, verse_range; languages: eng; package: packages/json/sword-mhcc/commentary.jsonl
|
|
||||||
|
|
||||||
## Generated Package
|
|
||||||
|
|
||||||
- Package catalog: packages/json/sword-mhcc/catalog.json
|
|
||||||
- Verses JSONL: n/a
|
|
||||||
- Strong's links JSONL: n/a
|
|
||||||
- Entries JSONL: packages/json/sword-mhcc/commentary.jsonl
|
|
||||||
- Source SHA-256: fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30
|
|
||||||
- Last checked: 2026-07-12T04:31:19.179Z
|
|
||||||
|
|
||||||
## Counts
|
|
||||||
|
|
||||||
- Books: n/a
|
|
||||||
- Verses: n/a
|
|
||||||
- Strong's links: n/a
|
|
||||||
- Entries: 4059
|
|
||||||
- Commentary entries: 4059
|
|
||||||
- Dictionary entries: n/a
|
|
||||||
|
|
||||||
## Package Checksums
|
|
||||||
|
|
||||||
- commentary_jsonl: `commentary.jsonl` (a7765c9fcf9b72174606623d424ff8d6e08f3cfc18fe3c62e0d38fdf73d8a6ad)
|
|
||||||
- source_rawzip: `MHCC.zip` (fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# CrossWire SWORD Module Audit
|
|
||||||
|
|
||||||
This file is generated from the CrossWire SWORD module catalog and the local LibreBible license approval registry.
|
|
||||||
|
|
||||||
- Repository: CrossWire Main
|
|
||||||
- Catalog URL: https://crosswire.org/ftpmirror/pub/sword/raw/mods.d.tar.gz
|
|
||||||
- Catalog SHA-256: `92c890b80979ffff7a7580c9092331cdd847f8f9effa98f3ed7e82e317f781b4`
|
|
||||||
- Generated: 2026-07-12T04:31:18.041Z
|
|
||||||
|
|
||||||
| Module | Intended Type | SWORD Type | Source Type | License | License Status | Import Status | Package | Notes |
|
|
||||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
||||||
| KJV | translation | zText | OSIS | GPL | review | candidate | [zip](https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/KJV.zip) | No approval rule matched the module license metadata. |
|
|
||||||
| JFB | commentary | zCom4 | OSIS | Public Domain | approved | candidate | [zip](https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/JFB.zip) | Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction. |
|
|
||||||
| MHCC | commentary | zCom | OSIS | Public Domain | approved | candidate | [zip](https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/MHCC.zip) | Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction. |
|
|
||||||
| StrongsHebrew | dictionary | RawLD | n/a | Public Domain | approved | deferred | [zip](https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/StrongsHebrew.zip) | Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction. |
|
|
||||||
| StrongsGreek | dictionary | zLD | TEI | Public Domain | approved | deferred | [zip](https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/StrongsGreek.zip) | Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction. |
|
|
||||||
| Nave | dictionary | zLD | TEI | Public Domain | approved | deferred | [zip](https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/Nave.zip) | Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction. |
|
|
||||||
|
|
||||||
## Next Import Gate
|
|
||||||
|
|
||||||
A SWORD module should not move from this audit into `packages/json/` until its license metadata is approved and the importer can convert the module content into LibreBible package formats with checksums.
|
|
||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "libre-bible-data",
|
"name": "libre-bible-data",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "libre-bible-data",
|
"name": "libre-bible-data",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"adm-zip": "^0.5.16"
|
"adm-zip": "^0.5.16"
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-5
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "libre-bible-data",
|
"name": "libre-bible-data",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -8,10 +8,7 @@
|
|||||||
"docs": "node scripts/generate-docs.js",
|
"docs": "node scripts/generate-docs.js",
|
||||||
"catalog": "node scripts/generate-catalog.js",
|
"catalog": "node scripts/generate-catalog.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",
|
||||||
"sword:audit": "node scripts/sword-audit.js",
|
"build": "npm run check && npm run import:kjv && npm run catalog && npm run docs"
|
||||||
"sword:list": "node scripts/sword-list.js",
|
|
||||||
"import:sword": "node scripts/import-sword.js",
|
|
||||||
"build": "npm run check && npm run import:kjv && npm run sword:audit && npm run import:sword && npm run catalog && npm run docs"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"adm-zip": "^0.5.16"
|
"adm-zip": "^0.5.16"
|
||||||
|
|||||||
+2
-263
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "librebible.index-catalog.v1",
|
"schema_version": "librebible.index-catalog.v1",
|
||||||
"project": "LibreBible",
|
"project": "LibreBible",
|
||||||
"generated_at": "2026-07-12T04:31:19.179Z",
|
"generated_at": "2026-07-12T12:05:53.357Z",
|
||||||
"resources": [
|
"resources": [
|
||||||
{
|
{
|
||||||
"id": "kjv-eng-kjv2006",
|
"id": "kjv-eng-kjv2006",
|
||||||
@@ -37,10 +37,6 @@
|
|||||||
"name": "King James Version translators",
|
"name": "King James Version translators",
|
||||||
"role": "translation"
|
"role": "translation"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "source text provider"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "eBible.org",
|
"name": "eBible.org",
|
||||||
"role": "publisher and package provider"
|
"role": "publisher and package provider"
|
||||||
@@ -128,7 +124,6 @@
|
|||||||
"mobile-html",
|
"mobile-html",
|
||||||
"epub",
|
"epub",
|
||||||
"pdf",
|
"pdf",
|
||||||
"sword",
|
|
||||||
"plain-text",
|
"plain-text",
|
||||||
"vpl-sql",
|
"vpl-sql",
|
||||||
"browser-bible",
|
"browser-bible",
|
||||||
@@ -142,7 +137,7 @@
|
|||||||
"redistribution": true,
|
"redistribution": true,
|
||||||
"jurisdiction_notes": "eBible states this work is firmly public domain outside the United Kingdom; UK printing/import may be restricted by Crown letters patent.",
|
"jurisdiction_notes": "eBible states this work is firmly public domain outside the United Kingdom; UK printing/import may be restricted by Crown letters patent.",
|
||||||
"source_license_url": "https://ebible.org/find/show.php?id=eng-kjv2006",
|
"source_license_url": "https://ebible.org/find/show.php?id=eng-kjv2006",
|
||||||
"attribution": "This free text is provided courtesy of CrossWire Bible Society and eBible.org.",
|
"attribution": "This free text is provided courtesy of eBible.org.",
|
||||||
"public_domain_outside": [
|
"public_domain_outside": [
|
||||||
"United Kingdom"
|
"United Kingdom"
|
||||||
],
|
],
|
||||||
@@ -180,262 +175,6 @@
|
|||||||
"expected_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
|
"expected_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
|
||||||
"last_checked_at": "2026-07-12T02:18:30Z"
|
"last_checked_at": "2026-07-12T02:18:30Z"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-jfb",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"title": "Jamieson Fausset Brown Bible Commentary",
|
|
||||||
"short_title": "Jamieson Fausset Brown Bible Commentary",
|
|
||||||
"abbreviation": "JFB",
|
|
||||||
"alternate_ids": [
|
|
||||||
"JFB"
|
|
||||||
],
|
|
||||||
"language": {
|
|
||||||
"code": "en",
|
|
||||||
"name": "English"
|
|
||||||
},
|
|
||||||
"script": "Latn",
|
|
||||||
"canon": {
|
|
||||||
"scope": "KJV",
|
|
||||||
"notes": "Commentary entries are keyed to SWORD Bible references."
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Robert Jamieson, A. R. Fausset, and David Brown",
|
|
||||||
"role": "commentary authors"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "module provider"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"id": "commentary-entries",
|
|
||||||
"type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"embedded": true,
|
|
||||||
"package": "packages/json/sword-jfb/commentary.jsonl"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-source",
|
|
||||||
"type": "source_format",
|
|
||||||
"label": "SWORD source",
|
|
||||||
"format": "OSIS",
|
|
||||||
"embedded": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attachments": {
|
|
||||||
"included": [
|
|
||||||
{
|
|
||||||
"id": "sword-jfb-commentary",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"relationship": "range-to-commentary",
|
|
||||||
"anchor_types": [
|
|
||||||
"book",
|
|
||||||
"chapter",
|
|
||||||
"verse",
|
|
||||||
"verse_range"
|
|
||||||
],
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"source": "CrossWire SWORD module export.",
|
|
||||||
"package": "packages/json/sword-jfb/commentary.jsonl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source": {
|
|
||||||
"provider": "CrossWire Bible Society",
|
|
||||||
"url": "https://crosswire.org/sword/modules/ModInfo.jsp?modName=JFB",
|
|
||||||
"download_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/JFB.zip",
|
|
||||||
"format": "sword-rawzip",
|
|
||||||
"upstream_id": "JFB",
|
|
||||||
"upstream_last_updated": "2021-02-15",
|
|
||||||
"sword": {
|
|
||||||
"module_id": "JFB",
|
|
||||||
"conf_file": "mods.d/jfb.conf",
|
|
||||||
"mod_drv": "zCom4",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "3.0",
|
|
||||||
"data_path": "./modules/comments/zcom/jfb/",
|
|
||||||
"text_source": "https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"name": "Public Domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"source_license_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/jfb.conf",
|
|
||||||
"attribution": "Jamieson Fausset Brown Bible Commentary Text source: https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt SWORD module: JFB Provided by CrossWire Bible Society.",
|
|
||||||
"jurisdiction_notes": "No jurisdiction-specific restriction was found in the SWORD module metadata.",
|
|
||||||
"restricted_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction."
|
|
||||||
},
|
|
||||||
"catalog_display": {
|
|
||||||
"primary_features": [
|
|
||||||
"Commentary entries",
|
|
||||||
"Verse/range anchors",
|
|
||||||
"SWORD source"
|
|
||||||
],
|
|
||||||
"summary": "Jamieson Fausset Brown Bible Commentary, imported from the CrossWire JFB SWORD module with 16945 commentary entries."
|
|
||||||
},
|
|
||||||
"package_path": "packages/json/sword-jfb/catalog.json",
|
|
||||||
"source_manifest_path": "sources/sword-jfb.json",
|
|
||||||
"detail_doc_path": "docs/resources/sword-jfb.md",
|
|
||||||
"counts": {
|
|
||||||
"entries": 16945,
|
|
||||||
"commentary_entries": 16945
|
|
||||||
},
|
|
||||||
"files": {
|
|
||||||
"commentary_jsonl": {
|
|
||||||
"path": "commentary.jsonl",
|
|
||||||
"bytes": 32753867,
|
|
||||||
"sha256": "bf9e2cd40159e0e83f261652b2d4874d9450131575dc6c73d07dc568433a47d9"
|
|
||||||
},
|
|
||||||
"source_rawzip": {
|
|
||||||
"path": "JFB.zip",
|
|
||||||
"bytes": 5687741,
|
|
||||||
"sha256": "a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"checks": {
|
|
||||||
"expected_sha256": "a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf",
|
|
||||||
"last_checked_at": "2026-07-12T04:31:19.021Z"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-mhcc",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"title": "Matthew Henry's Concise Commentary on the Whole Bible",
|
|
||||||
"short_title": "Matthew Henry's Concise Commentary on the Whole Bible",
|
|
||||||
"abbreviation": "MHCC",
|
|
||||||
"alternate_ids": [
|
|
||||||
"MHCC"
|
|
||||||
],
|
|
||||||
"language": {
|
|
||||||
"code": "en",
|
|
||||||
"name": "English"
|
|
||||||
},
|
|
||||||
"script": "Latn",
|
|
||||||
"canon": {
|
|
||||||
"scope": "KJV",
|
|
||||||
"notes": "Commentary entries are keyed to SWORD Bible references."
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Matthew Henry",
|
|
||||||
"role": "commentary author"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "module provider"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"id": "commentary-entries",
|
|
||||||
"type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"embedded": true,
|
|
||||||
"package": "packages/json/sword-mhcc/commentary.jsonl"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-source",
|
|
||||||
"type": "source_format",
|
|
||||||
"label": "SWORD source",
|
|
||||||
"format": "OSIS",
|
|
||||||
"embedded": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attachments": {
|
|
||||||
"included": [
|
|
||||||
{
|
|
||||||
"id": "sword-mhcc-commentary",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"relationship": "range-to-commentary",
|
|
||||||
"anchor_types": [
|
|
||||||
"book",
|
|
||||||
"chapter",
|
|
||||||
"verse",
|
|
||||||
"verse_range"
|
|
||||||
],
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"source": "CrossWire SWORD module export.",
|
|
||||||
"package": "packages/json/sword-mhcc/commentary.jsonl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source": {
|
|
||||||
"provider": "CrossWire Bible Society",
|
|
||||||
"url": "https://crosswire.org/sword/modules/ModInfo.jsp?modName=MHCC",
|
|
||||||
"download_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/MHCC.zip",
|
|
||||||
"format": "sword-rawzip",
|
|
||||||
"upstream_id": "MHCC",
|
|
||||||
"upstream_last_updated": "2021-02-14",
|
|
||||||
"sword": {
|
|
||||||
"module_id": "MHCC",
|
|
||||||
"conf_file": "mods.d/mhcc.conf",
|
|
||||||
"mod_drv": "zCom",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "2.0",
|
|
||||||
"data_path": "./modules/comments/zcom/mhcc/",
|
|
||||||
"text_source": "https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"name": "Public Domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"source_license_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/mhcc.conf",
|
|
||||||
"attribution": "Matthew Henry's Concise Commentary on the Whole Bible Text source: https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt SWORD module: MHCC Provided by CrossWire Bible Society.",
|
|
||||||
"jurisdiction_notes": "No jurisdiction-specific restriction was found in the SWORD module metadata.",
|
|
||||||
"restricted_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction."
|
|
||||||
},
|
|
||||||
"catalog_display": {
|
|
||||||
"primary_features": [
|
|
||||||
"Commentary entries",
|
|
||||||
"Verse/range anchors",
|
|
||||||
"SWORD source"
|
|
||||||
],
|
|
||||||
"summary": "Matthew Henry's Concise Commentary on the Whole Bible, imported from the CrossWire MHCC SWORD module with 4059 commentary entries."
|
|
||||||
},
|
|
||||||
"package_path": "packages/json/sword-mhcc/catalog.json",
|
|
||||||
"source_manifest_path": "sources/sword-mhcc.json",
|
|
||||||
"detail_doc_path": "docs/resources/sword-mhcc.md",
|
|
||||||
"counts": {
|
|
||||||
"entries": 4059,
|
|
||||||
"commentary_entries": 4059
|
|
||||||
},
|
|
||||||
"files": {
|
|
||||||
"commentary_jsonl": {
|
|
||||||
"path": "commentary.jsonl",
|
|
||||||
"bytes": 10830202,
|
|
||||||
"sha256": "a7765c9fcf9b72174606623d424ff8d6e08f3cfc18fe3c62e0d38fdf73d8a6ad"
|
|
||||||
},
|
|
||||||
"source_rawzip": {
|
|
||||||
"path": "MHCC.zip",
|
|
||||||
"bytes": 1773039,
|
|
||||||
"sha256": "fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"checks": {
|
|
||||||
"expected_sha256": "fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30",
|
|
||||||
"last_checked_at": "2026-07-12T04:31:19.179Z"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,6 @@
|
|||||||
"name": "King James Version translators",
|
"name": "King James Version translators",
|
||||||
"role": "translation"
|
"role": "translation"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "source text provider"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "eBible.org",
|
"name": "eBible.org",
|
||||||
"role": "publisher and package provider"
|
"role": "publisher and package provider"
|
||||||
@@ -125,7 +121,6 @@
|
|||||||
"mobile-html",
|
"mobile-html",
|
||||||
"epub",
|
"epub",
|
||||||
"pdf",
|
"pdf",
|
||||||
"sword",
|
|
||||||
"plain-text",
|
"plain-text",
|
||||||
"vpl-sql",
|
"vpl-sql",
|
||||||
"browser-bible",
|
"browser-bible",
|
||||||
@@ -139,7 +134,7 @@
|
|||||||
"redistribution": true,
|
"redistribution": true,
|
||||||
"jurisdiction_notes": "eBible states this work is firmly public domain outside the United Kingdom; UK printing/import may be restricted by Crown letters patent.",
|
"jurisdiction_notes": "eBible states this work is firmly public domain outside the United Kingdom; UK printing/import may be restricted by Crown letters patent.",
|
||||||
"source_license_url": "https://ebible.org/find/show.php?id=eng-kjv2006",
|
"source_license_url": "https://ebible.org/find/show.php?id=eng-kjv2006",
|
||||||
"attribution": "This free text is provided courtesy of CrossWire Bible Society and eBible.org.",
|
"attribution": "This free text is provided courtesy of eBible.org.",
|
||||||
"public_domain_outside": [
|
"public_domain_outside": [
|
||||||
"United Kingdom"
|
"United Kingdom"
|
||||||
],
|
],
|
||||||
@@ -157,7 +152,7 @@
|
|||||||
"name": "scripts/import-usfm.js",
|
"name": "scripts/import-usfm.js",
|
||||||
"version": "0.1.0"
|
"version": "0.1.0"
|
||||||
},
|
},
|
||||||
"generated_at": "2026-07-12T04:31:17.237Z",
|
"generated_at": "2026-07-12T12:05:53.357Z",
|
||||||
"source_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
|
"source_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
|
||||||
"checks": {
|
"checks": {
|
||||||
"expected_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
|
"expected_sha256": "4ea6952590d070bfa22985aded48a49581e31b568a60aa09e25f73462e700e7d",
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
{
|
|
||||||
"schema_version": "librebible.resource-catalog.v1",
|
|
||||||
"project": "LibreBible",
|
|
||||||
"id": "sword-jfb",
|
|
||||||
"source_manifest_file": "sword-jfb.json",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"title": "Jamieson Fausset Brown Bible Commentary",
|
|
||||||
"short_title": "Jamieson Fausset Brown Bible Commentary",
|
|
||||||
"abbreviation": "JFB",
|
|
||||||
"alternate_ids": [
|
|
||||||
"JFB"
|
|
||||||
],
|
|
||||||
"language": {
|
|
||||||
"code": "en",
|
|
||||||
"name": "English"
|
|
||||||
},
|
|
||||||
"script": "Latn",
|
|
||||||
"canon": {
|
|
||||||
"scope": "KJV",
|
|
||||||
"notes": "Commentary entries are keyed to SWORD Bible references."
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Robert Jamieson, A. R. Fausset, and David Brown",
|
|
||||||
"role": "commentary authors"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "module provider"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"id": "commentary-entries",
|
|
||||||
"type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"embedded": true,
|
|
||||||
"package": "packages/json/sword-jfb/commentary.jsonl"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-source",
|
|
||||||
"type": "source_format",
|
|
||||||
"label": "SWORD source",
|
|
||||||
"format": "OSIS",
|
|
||||||
"embedded": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attachments": {
|
|
||||||
"included": [
|
|
||||||
{
|
|
||||||
"id": "sword-jfb-commentary",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"relationship": "range-to-commentary",
|
|
||||||
"anchor_types": [
|
|
||||||
"book",
|
|
||||||
"chapter",
|
|
||||||
"verse",
|
|
||||||
"verse_range"
|
|
||||||
],
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"source": "CrossWire SWORD module export.",
|
|
||||||
"package": "packages/json/sword-jfb/commentary.jsonl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source": {
|
|
||||||
"provider": "CrossWire Bible Society",
|
|
||||||
"url": "https://crosswire.org/sword/modules/ModInfo.jsp?modName=JFB",
|
|
||||||
"download_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/JFB.zip",
|
|
||||||
"format": "sword-rawzip",
|
|
||||||
"upstream_id": "JFB",
|
|
||||||
"upstream_last_updated": "2021-02-15",
|
|
||||||
"sword": {
|
|
||||||
"module_id": "JFB",
|
|
||||||
"conf_file": "mods.d/jfb.conf",
|
|
||||||
"mod_drv": "zCom4",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "3.0",
|
|
||||||
"data_path": "./modules/comments/zcom/jfb/",
|
|
||||||
"text_source": "https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"name": "Public Domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"source_license_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/jfb.conf",
|
|
||||||
"attribution": "Jamieson Fausset Brown Bible Commentary Text source: https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt SWORD module: JFB Provided by CrossWire Bible Society.",
|
|
||||||
"jurisdiction_notes": "No jurisdiction-specific restriction was found in the SWORD module metadata.",
|
|
||||||
"restricted_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction."
|
|
||||||
},
|
|
||||||
"catalog_display": {
|
|
||||||
"primary_features": [
|
|
||||||
"Commentary entries",
|
|
||||||
"Verse/range anchors",
|
|
||||||
"SWORD source"
|
|
||||||
],
|
|
||||||
"summary": "Jamieson Fausset Brown Bible Commentary, imported from the CrossWire JFB SWORD module with 16945 commentary entries."
|
|
||||||
},
|
|
||||||
"importer": {
|
|
||||||
"name": "scripts/import-sword.js",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"engine": "CrossWire SWORD mod2imp via Docker/Ubuntu libsword-utils"
|
|
||||||
},
|
|
||||||
"generated_at": "2026-07-12T04:31:19.022Z",
|
|
||||||
"source_sha256": "a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf",
|
|
||||||
"checks": {
|
|
||||||
"expected_sha256": "a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf",
|
|
||||||
"last_checked_at": "2026-07-12T04:31:19.021Z"
|
|
||||||
},
|
|
||||||
"counts": {
|
|
||||||
"entries": 16945,
|
|
||||||
"commentary_entries": 16945
|
|
||||||
},
|
|
||||||
"files": {
|
|
||||||
"commentary_jsonl": {
|
|
||||||
"path": "commentary.jsonl",
|
|
||||||
"bytes": 32753867,
|
|
||||||
"sha256": "bf9e2cd40159e0e83f261652b2d4874d9450131575dc6c73d07dc568433a47d9"
|
|
||||||
},
|
|
||||||
"source_rawzip": {
|
|
||||||
"path": "JFB.zip",
|
|
||||||
"bytes": 5687741,
|
|
||||||
"sha256": "a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sword": {
|
|
||||||
"module_id": "JFB",
|
|
||||||
"conf_file": "mods.d/jfb.conf",
|
|
||||||
"mod_drv": "zCom4",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "3.0",
|
|
||||||
"data_path": "./modules/comments/zcom/jfb/",
|
|
||||||
"text_source": "https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt"
|
|
||||||
},
|
|
||||||
"raw_conf_sha256": "8d494870d68cd92203441dc2dd264ba273087388b70d84b703782de346ef3f6f"
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,146 +0,0 @@
|
|||||||
{
|
|
||||||
"schema_version": "librebible.resource-catalog.v1",
|
|
||||||
"project": "LibreBible",
|
|
||||||
"id": "sword-mhcc",
|
|
||||||
"source_manifest_file": "sword-mhcc.json",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"title": "Matthew Henry's Concise Commentary on the Whole Bible",
|
|
||||||
"short_title": "Matthew Henry's Concise Commentary on the Whole Bible",
|
|
||||||
"abbreviation": "MHCC",
|
|
||||||
"alternate_ids": [
|
|
||||||
"MHCC"
|
|
||||||
],
|
|
||||||
"language": {
|
|
||||||
"code": "en",
|
|
||||||
"name": "English"
|
|
||||||
},
|
|
||||||
"script": "Latn",
|
|
||||||
"canon": {
|
|
||||||
"scope": "KJV",
|
|
||||||
"notes": "Commentary entries are keyed to SWORD Bible references."
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Matthew Henry",
|
|
||||||
"role": "commentary author"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "module provider"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"id": "commentary-entries",
|
|
||||||
"type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"embedded": true,
|
|
||||||
"package": "packages/json/sword-mhcc/commentary.jsonl"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-source",
|
|
||||||
"type": "source_format",
|
|
||||||
"label": "SWORD source",
|
|
||||||
"format": "OSIS",
|
|
||||||
"embedded": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attachments": {
|
|
||||||
"included": [
|
|
||||||
{
|
|
||||||
"id": "sword-mhcc-commentary",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"relationship": "range-to-commentary",
|
|
||||||
"anchor_types": [
|
|
||||||
"book",
|
|
||||||
"chapter",
|
|
||||||
"verse",
|
|
||||||
"verse_range"
|
|
||||||
],
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"source": "CrossWire SWORD module export.",
|
|
||||||
"package": "packages/json/sword-mhcc/commentary.jsonl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source": {
|
|
||||||
"provider": "CrossWire Bible Society",
|
|
||||||
"url": "https://crosswire.org/sword/modules/ModInfo.jsp?modName=MHCC",
|
|
||||||
"download_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/MHCC.zip",
|
|
||||||
"format": "sword-rawzip",
|
|
||||||
"upstream_id": "MHCC",
|
|
||||||
"upstream_last_updated": "2021-02-14",
|
|
||||||
"sword": {
|
|
||||||
"module_id": "MHCC",
|
|
||||||
"conf_file": "mods.d/mhcc.conf",
|
|
||||||
"mod_drv": "zCom",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "2.0",
|
|
||||||
"data_path": "./modules/comments/zcom/mhcc/",
|
|
||||||
"text_source": "https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"name": "Public Domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"source_license_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/mhcc.conf",
|
|
||||||
"attribution": "Matthew Henry's Concise Commentary on the Whole Bible Text source: https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt SWORD module: MHCC Provided by CrossWire Bible Society.",
|
|
||||||
"jurisdiction_notes": "No jurisdiction-specific restriction was found in the SWORD module metadata.",
|
|
||||||
"restricted_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction."
|
|
||||||
},
|
|
||||||
"catalog_display": {
|
|
||||||
"primary_features": [
|
|
||||||
"Commentary entries",
|
|
||||||
"Verse/range anchors",
|
|
||||||
"SWORD source"
|
|
||||||
],
|
|
||||||
"summary": "Matthew Henry's Concise Commentary on the Whole Bible, imported from the CrossWire MHCC SWORD module with 4059 commentary entries."
|
|
||||||
},
|
|
||||||
"importer": {
|
|
||||||
"name": "scripts/import-sword.js",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"engine": "CrossWire SWORD mod2imp via Docker/Ubuntu libsword-utils"
|
|
||||||
},
|
|
||||||
"generated_at": "2026-07-12T04:31:19.179Z",
|
|
||||||
"source_sha256": "fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30",
|
|
||||||
"checks": {
|
|
||||||
"expected_sha256": "fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30",
|
|
||||||
"last_checked_at": "2026-07-12T04:31:19.179Z"
|
|
||||||
},
|
|
||||||
"counts": {
|
|
||||||
"entries": 4059,
|
|
||||||
"commentary_entries": 4059
|
|
||||||
},
|
|
||||||
"files": {
|
|
||||||
"commentary_jsonl": {
|
|
||||||
"path": "commentary.jsonl",
|
|
||||||
"bytes": 10830202,
|
|
||||||
"sha256": "a7765c9fcf9b72174606623d424ff8d6e08f3cfc18fe3c62e0d38fdf73d8a6ad"
|
|
||||||
},
|
|
||||||
"source_rawzip": {
|
|
||||||
"path": "MHCC.zip",
|
|
||||||
"bytes": 1773039,
|
|
||||||
"sha256": "fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sword": {
|
|
||||||
"module_id": "MHCC",
|
|
||||||
"conf_file": "mods.d/mhcc.conf",
|
|
||||||
"mod_drv": "zCom",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "2.0",
|
|
||||||
"data_path": "./modules/comments/zcom/mhcc/",
|
|
||||||
"text_source": "https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt"
|
|
||||||
},
|
|
||||||
"raw_conf_sha256": "78d3df89bc6343d67e37a37b106904135a01e3ce15f2a157f9c090fe3eecc676"
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"schema_version": "librebible.sword-pilot-modules.v1",
|
|
||||||
"repository": {
|
|
||||||
"id": "crosswire-main",
|
|
||||||
"name": "CrossWire Main",
|
|
||||||
"mods_tarball_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d.tar.gz",
|
|
||||||
"package_base_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip"
|
|
||||||
},
|
|
||||||
"modules": [
|
|
||||||
{
|
|
||||||
"id": "KJV",
|
|
||||||
"intended_resource_type": "translation",
|
|
||||||
"reason": "Baseline Bible text module with Strong's and morphology metadata, useful for comparing against the eBible KJV package."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "JFB",
|
|
||||||
"intended_resource_type": "commentary",
|
|
||||||
"reason": "Public-domain whole-Bible commentary candidate."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "MHCC",
|
|
||||||
"intended_resource_type": "commentary",
|
|
||||||
"reason": "Public-domain concise Matthew Henry commentary candidate."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "StrongsHebrew",
|
|
||||||
"intended_resource_type": "dictionary",
|
|
||||||
"import_enabled": false,
|
|
||||||
"import_status": "deferred",
|
|
||||||
"reason": "Strong's Hebrew dictionary candidate. Deferred after containerized mod2imp export timed out during Phase 6; keep in audit queue for a better exporter path."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "StrongsGreek",
|
|
||||||
"intended_resource_type": "dictionary",
|
|
||||||
"import_enabled": false,
|
|
||||||
"import_status": "deferred",
|
|
||||||
"reason": "Strong's Greek dictionary candidate. Deferred after Phase 6 sample inspection showed mojibake in Greek lexical forms from the raw SWORD export path."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Nave",
|
|
||||||
"intended_resource_type": "dictionary",
|
|
||||||
"import_enabled": false,
|
|
||||||
"import_status": "deferred",
|
|
||||||
"reason": "Topical Bible dictionary candidate with public-domain source history. Deferred after containerized mod2imp export timed out during Phase 6; keep in audit queue for a better exporter path."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,512 +0,0 @@
|
|||||||
import AdmZip from 'adm-zip'
|
|
||||||
import { execFile } from 'node:child_process'
|
|
||||||
import { createHash } from 'node:crypto'
|
|
||||||
import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
|
|
||||||
import path from 'node:path'
|
|
||||||
import { promisify } from 'node:util'
|
|
||||||
import {
|
|
||||||
classifySwordModule,
|
|
||||||
fetchSwordConfCatalog,
|
|
||||||
loadLicenseApproval,
|
|
||||||
loadSwordPilotModules,
|
|
||||||
swordPackageUrl,
|
|
||||||
} from './sword-lib.js'
|
|
||||||
import { cleanUsfmText, exists, sha256File, writeJson } from './lib.js'
|
|
||||||
|
|
||||||
const execFileAsync = promisify(execFile)
|
|
||||||
const root = process.cwd()
|
|
||||||
const swordCacheDir = path.join(root, 'cache', 'sword')
|
|
||||||
const swordLibraryDir = path.join(swordCacheDir, 'library')
|
|
||||||
const swordExportDir = path.join(swordCacheDir, 'exports')
|
|
||||||
const swordPackageDir = path.join(swordCacheDir, 'packages')
|
|
||||||
|
|
||||||
const pilot = await loadSwordPilotModules()
|
|
||||||
const licenseRegistry = await loadLicenseApproval()
|
|
||||||
const catalog = await fetchSwordConfCatalog(pilot.repository.mods_tarball_url)
|
|
||||||
|
|
||||||
await mkdir(swordLibraryDir, { recursive: true })
|
|
||||||
await mkdir(swordExportDir, { recursive: true })
|
|
||||||
await mkdir(swordPackageDir, { recursive: true })
|
|
||||||
|
|
||||||
const imported = []
|
|
||||||
const skipped = []
|
|
||||||
|
|
||||||
for (const item of pilot.modules) {
|
|
||||||
try {
|
|
||||||
if (item.import_enabled === false) {
|
|
||||||
skipped.push(`${item.id}: import disabled - ${item.import_status ?? 'deferred'}`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const catalogEntry = catalog.modules.get(item.id.toLowerCase())
|
|
||||||
if (!catalogEntry) {
|
|
||||||
skipped.push(`${item.id}: not found in CrossWire catalog`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.intended_resource_type === 'translation') {
|
|
||||||
skipped.push(`${item.id}: skipped duplicate/alternate Bible text pending edition comparison`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const license = classifySwordModule(catalogEntry.conf, licenseRegistry)
|
|
||||||
if (!license.status.startsWith('approved')) {
|
|
||||||
skipped.push(`${item.id}: license status ${license.status}`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const rawzip = await downloadSwordPackage(catalogEntry.module_id)
|
|
||||||
extractSwordPackage(rawzip.package_path)
|
|
||||||
const exportPath = await exportSwordModule(catalogEntry.module_id)
|
|
||||||
const records = await parseImpFile(exportPath, item.intended_resource_type, catalogEntry.conf)
|
|
||||||
const resource = await writeSwordResource(item, catalogEntry, license, rawzip, records)
|
|
||||||
imported.push(resource.id)
|
|
||||||
} catch (error) {
|
|
||||||
skipped.push(`${item.id}: import failed - ${error.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`SWORD import complete: ${imported.length} imported, ${skipped.length} skipped.`)
|
|
||||||
for (const id of imported) console.log(` imported: ${id}`)
|
|
||||||
for (const reason of skipped) console.log(` skipped: ${reason}`)
|
|
||||||
|
|
||||||
async function downloadSwordPackage(moduleId) {
|
|
||||||
const url = swordPackageUrl(moduleId, pilot.repository.package_base_url)
|
|
||||||
const packagePath = path.join(swordPackageDir, `${moduleId}.zip`)
|
|
||||||
|
|
||||||
if (!(await exists(packagePath))) {
|
|
||||||
const response = await fetch(url)
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Unable to download SWORD package ${url}: ${response.status} ${response.statusText}`)
|
|
||||||
}
|
|
||||||
await writeFile(packagePath, Buffer.from(await response.arrayBuffer()))
|
|
||||||
}
|
|
||||||
|
|
||||||
const checksum = await sha256File(packagePath)
|
|
||||||
const fileStat = await stat(packagePath)
|
|
||||||
return {
|
|
||||||
package_url: url,
|
|
||||||
package_path: packagePath,
|
|
||||||
bytes: fileStat.size,
|
|
||||||
sha256: checksum,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractSwordPackage(packagePath) {
|
|
||||||
const archive = new AdmZip(packagePath)
|
|
||||||
archive.extractAllTo(swordLibraryDir, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function exportSwordModule(moduleId) {
|
|
||||||
const outputPath = path.join(swordExportDir, `${moduleId}.imp`)
|
|
||||||
if (await exists(outputPath)) {
|
|
||||||
const outputStat = await stat(outputPath)
|
|
||||||
if (outputStat.size > 0) {
|
|
||||||
return outputPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const shell = [
|
|
||||||
'set -e',
|
|
||||||
'export DEBIAN_FRONTEND=noninteractive',
|
|
||||||
'apt-get update >/dev/null',
|
|
||||||
'apt-get install -y libsword-utils >/dev/null',
|
|
||||||
`SWORD_PATH=/workspace/cache/sword/library mod2imp ${shellQuote(moduleId)} > /workspace/cache/sword/exports/${shellQuote(moduleId)}.imp`,
|
|
||||||
].join('\n')
|
|
||||||
|
|
||||||
await execFileAsync('docker', [
|
|
||||||
'run',
|
|
||||||
'--rm',
|
|
||||||
'-v',
|
|
||||||
`${root}:/workspace`,
|
|
||||||
'-w',
|
|
||||||
'/workspace',
|
|
||||||
'ubuntu:26.04',
|
|
||||||
'bash',
|
|
||||||
'-lc',
|
|
||||||
shell,
|
|
||||||
], {
|
|
||||||
maxBuffer: 20 * 1024 * 1024,
|
|
||||||
timeout: 120_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!(await exists(outputPath))) {
|
|
||||||
throw new Error(`SWORD export did not create ${outputPath}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return outputPath
|
|
||||||
}
|
|
||||||
|
|
||||||
async function parseImpFile(filePath, resourceType, conf) {
|
|
||||||
const text = await readFile(filePath, 'utf8')
|
|
||||||
const records = []
|
|
||||||
let currentKey = null
|
|
||||||
let body = []
|
|
||||||
|
|
||||||
function flush() {
|
|
||||||
if (!currentKey) return
|
|
||||||
const raw = body.join('\n').trim()
|
|
||||||
if (!raw) {
|
|
||||||
currentKey = null
|
|
||||||
body = []
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resourceType === 'commentary') {
|
|
||||||
const record = commentaryRecord(currentKey, raw, conf)
|
|
||||||
if (record) records.push(record)
|
|
||||||
} else {
|
|
||||||
const record = dictionaryRecord(currentKey, raw, conf)
|
|
||||||
if (record) records.push(record)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentKey = null
|
|
||||||
body = []
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const line of text.split(/\r?\n/)) {
|
|
||||||
if (line.startsWith('$$$')) {
|
|
||||||
flush()
|
|
||||||
currentKey = line.slice(3).trim()
|
|
||||||
} else {
|
|
||||||
body.push(line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flush()
|
|
||||||
return records
|
|
||||||
}
|
|
||||||
|
|
||||||
async function writeSwordResource(item, catalogEntry, license, rawzip, records) {
|
|
||||||
const conf = catalogEntry.conf
|
|
||||||
const id = resourceIdFor(catalogEntry.module_id)
|
|
||||||
const outputDir = path.join(root, 'packages', 'json', id)
|
|
||||||
const fileName = item.intended_resource_type === 'commentary' ? 'commentary.jsonl' : 'entries.jsonl'
|
|
||||||
const filePath = path.join(outputDir, fileName)
|
|
||||||
|
|
||||||
await rm(outputDir, { recursive: true, force: true })
|
|
||||||
await mkdir(outputDir, { recursive: true })
|
|
||||||
await writeFile(filePath, `${records.map((record) => JSON.stringify(record)).join('\n')}\n`, 'utf8')
|
|
||||||
|
|
||||||
const packageFile = await describePackageFile(outputDir, fileName)
|
|
||||||
const manifest = sourceManifestFor(item, catalogEntry, license, rawzip, id, fileName, records)
|
|
||||||
const catalog = packageCatalogFor(manifest, catalogEntry, rawzip, records, packageFile)
|
|
||||||
|
|
||||||
await writeJson(path.join(root, 'sources', `${id}.json`), manifest)
|
|
||||||
await writeJson(path.join(outputDir, 'catalog.json'), catalog)
|
|
||||||
|
|
||||||
return { id, records: records.length }
|
|
||||||
}
|
|
||||||
|
|
||||||
function sourceManifestFor(item, catalogEntry, license, rawzip, id, fileName, records) {
|
|
||||||
const conf = catalogEntry.conf
|
|
||||||
const resourceType = item.intended_resource_type
|
|
||||||
const title = conf.Description ?? catalogEntry.module_id
|
|
||||||
const licenseName = conf.DistributionLicense ?? license.rule ?? 'Unknown'
|
|
||||||
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
resource_type: resourceType,
|
|
||||||
project_name: 'LibreBible',
|
|
||||||
title,
|
|
||||||
short_title: title,
|
|
||||||
abbreviation: conf.Abbreviation ?? catalogEntry.module_id,
|
|
||||||
alternate_ids: [catalogEntry.module_id],
|
|
||||||
language: {
|
|
||||||
code: conf.Lang ?? 'en',
|
|
||||||
name: conf.Lang === 'en' || !conf.Lang ? 'English' : conf.Lang,
|
|
||||||
},
|
|
||||||
script: 'Latn',
|
|
||||||
canon: {
|
|
||||||
scope: conf.Versification ?? 'n/a',
|
|
||||||
notes: resourceType === 'commentary' ? 'Commentary entries are keyed to SWORD Bible references.' : 'Dictionary entries are keyed by SWORD lexical keys.',
|
|
||||||
},
|
|
||||||
contributors: contributorsFor(conf, resourceType),
|
|
||||||
features: featuresFor(resourceType, id, fileName, catalogEntry),
|
|
||||||
attachments: attachmentsFor(resourceType, id, fileName),
|
|
||||||
source: {
|
|
||||||
provider: 'CrossWire Bible Society',
|
|
||||||
url: `https://crosswire.org/sword/modules/ModInfo.jsp?modName=${encodeURIComponent(catalogEntry.module_id)}`,
|
|
||||||
download_url: rawzip.package_url,
|
|
||||||
format: 'sword-rawzip',
|
|
||||||
upstream_id: catalogEntry.module_id,
|
|
||||||
upstream_last_updated: conf.SwordVersionDate,
|
|
||||||
sword: {
|
|
||||||
module_id: catalogEntry.module_id,
|
|
||||||
conf_file: catalogEntry.conf_file,
|
|
||||||
mod_drv: conf.ModDrv,
|
|
||||||
source_type: conf.SourceType,
|
|
||||||
versification: conf.Versification,
|
|
||||||
version: conf.Version,
|
|
||||||
data_path: conf.DataPath,
|
|
||||||
text_source: conf.TextSource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
license: {
|
|
||||||
name: licenseName,
|
|
||||||
redistribution: license.redistribution === true,
|
|
||||||
commercial_use: license.commercial_use,
|
|
||||||
share_alike: license.share_alike === true,
|
|
||||||
source_license_url: `https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/${catalogEntry.module_id.toLowerCase()}.conf`,
|
|
||||||
attribution: attributionFor(conf, catalogEntry.module_id),
|
|
||||||
jurisdiction_notes: conf.Copyright ?? 'No jurisdiction-specific restriction was found in the SWORD module metadata.',
|
|
||||||
restricted_notes: license.notes,
|
|
||||||
},
|
|
||||||
checks: {
|
|
||||||
expected_sha256: rawzip.sha256,
|
|
||||||
last_checked_at: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
importer: {
|
|
||||||
name: 'scripts/import-sword.js',
|
|
||||||
version: '0.1.0',
|
|
||||||
engine: 'CrossWire SWORD mod2imp via Docker/Ubuntu libsword-utils',
|
|
||||||
},
|
|
||||||
packages: {
|
|
||||||
json_catalog: `packages/json/${id}/catalog.json`,
|
|
||||||
entries_jsonl: `packages/json/${id}/${fileName}`,
|
|
||||||
},
|
|
||||||
catalog_display: {
|
|
||||||
primary_features: resourceType === 'commentary' ? ['Commentary entries', 'Verse/range anchors', 'SWORD source'] : ['Dictionary entries', 'Lexical anchors', 'SWORD source'],
|
|
||||||
summary: summaryFor(resourceType, title, records.length, catalogEntry.module_id),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function packageCatalogFor(manifest, catalogEntry, rawzip, records, packageFile) {
|
|
||||||
const fileKey = manifest.resource_type === 'commentary' ? 'commentary_jsonl' : 'entries_jsonl'
|
|
||||||
return {
|
|
||||||
schema_version: 'librebible.resource-catalog.v1',
|
|
||||||
project: 'LibreBible',
|
|
||||||
id: manifest.id,
|
|
||||||
source_manifest_file: `${manifest.id}.json`,
|
|
||||||
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,
|
|
||||||
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: rawzip.sha256,
|
|
||||||
checks: manifest.checks,
|
|
||||||
counts: {
|
|
||||||
entries: records.length,
|
|
||||||
commentary_entries: manifest.resource_type === 'commentary' ? records.length : undefined,
|
|
||||||
dictionary_entries: manifest.resource_type === 'dictionary' ? records.length : undefined,
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
[fileKey]: packageFile,
|
|
||||||
source_rawzip: {
|
|
||||||
path: path.basename(rawzip.package_path),
|
|
||||||
bytes: rawzip.bytes,
|
|
||||||
sha256: rawzip.sha256,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sword: manifest.source.sword,
|
|
||||||
raw_conf_sha256: createHash('sha256').update(catalogEntry.conf_text).digest('hex'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function describePackageFile(outputDir, fileName) {
|
|
||||||
const filePath = path.join(outputDir, fileName)
|
|
||||||
const fileStat = await stat(filePath)
|
|
||||||
return {
|
|
||||||
path: fileName,
|
|
||||||
bytes: fileStat.size,
|
|
||||||
sha256: await sha256File(filePath),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function commentaryRecord(key, raw, conf) {
|
|
||||||
const parsed = parseBibleKey(key)
|
|
||||||
const text = stripMarkup(raw)
|
|
||||||
if (!text) return null
|
|
||||||
return {
|
|
||||||
id: stableId(`${conf.module_id}:${key}`),
|
|
||||||
resource_id: resourceIdFor(conf.module_id),
|
|
||||||
module_id: conf.module_id,
|
|
||||||
key,
|
|
||||||
anchor_type: parsed ? 'verse' : 'module_key',
|
|
||||||
reference: parsed?.reference ?? key,
|
|
||||||
book: parsed?.book,
|
|
||||||
chapter: parsed?.chapter,
|
|
||||||
verse: parsed?.verse,
|
|
||||||
raw_markup: raw,
|
|
||||||
text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function dictionaryRecord(key, raw, conf) {
|
|
||||||
const text = stripMarkup(raw)
|
|
||||||
if (!text) return null
|
|
||||||
const prefix = conf.module_id === 'StrongsGreek' ? 'G' : conf.module_id === 'StrongsHebrew' ? 'H' : ''
|
|
||||||
const number = /^\d+$/.test(key) ? Number(key) : null
|
|
||||||
const lexicalKey = prefix && number !== null ? `${prefix}${number}` : key
|
|
||||||
return {
|
|
||||||
id: stableId(`${conf.module_id}:${key}`),
|
|
||||||
resource_id: resourceIdFor(conf.module_id),
|
|
||||||
module_id: conf.module_id,
|
|
||||||
key,
|
|
||||||
lexical_key: lexicalKey,
|
|
||||||
anchor_type: prefix ? 'strongs_number' : 'dictionary_key',
|
|
||||||
raw_markup: raw,
|
|
||||||
text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseBibleKey(key) {
|
|
||||||
const match = /^(.+?)\s+(\d+):(\d+)$/.exec(key)
|
|
||||||
if (!match) return null
|
|
||||||
return {
|
|
||||||
book: match[1],
|
|
||||||
chapter: Number(match[2]),
|
|
||||||
verse: Number(match[3]),
|
|
||||||
reference: key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stripMarkup(raw) {
|
|
||||||
return cleanUsfmText(raw
|
|
||||||
.replace(/<reference[^>]*>(.*?)<\/reference>/gis, '$1')
|
|
||||||
.replace(/<ref[^>]*>(.*?)<\/ref>/gis, '$1')
|
|
||||||
.replace(/<[^>]+>/g, ' ')
|
|
||||||
.replace(/ /g, ' ')
|
|
||||||
.replace(/"/g, '"')
|
|
||||||
.replace(/'/g, "'")
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>'))
|
|
||||||
}
|
|
||||||
|
|
||||||
function resourceIdFor(moduleId) {
|
|
||||||
return `sword-${moduleId.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()}`
|
|
||||||
}
|
|
||||||
|
|
||||||
function stableId(value) {
|
|
||||||
return createHash('sha1').update(value).digest('hex')
|
|
||||||
}
|
|
||||||
|
|
||||||
function featuresFor(resourceType, id, fileName, catalogEntry) {
|
|
||||||
if (resourceType === 'commentary') {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 'commentary-entries',
|
|
||||||
type: 'commentary',
|
|
||||||
label: 'Commentary entries',
|
|
||||||
languages: ['eng'],
|
|
||||||
embedded: true,
|
|
||||||
package: `packages/json/${id}/${fileName}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'sword-source',
|
|
||||||
type: 'source_format',
|
|
||||||
label: 'SWORD source',
|
|
||||||
format: catalogEntry.conf.SourceType ?? catalogEntry.conf.ModDrv,
|
|
||||||
embedded: false,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 'dictionary-entries',
|
|
||||||
type: 'dictionary',
|
|
||||||
label: 'Dictionary entries',
|
|
||||||
languages: ['eng'],
|
|
||||||
systems: catalogEntry.module_id.startsWith('Strongs') ? ['strongs'] : undefined,
|
|
||||||
embedded: true,
|
|
||||||
package: `packages/json/${id}/${fileName}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'sword-source',
|
|
||||||
type: 'source_format',
|
|
||||||
label: 'SWORD source',
|
|
||||||
format: catalogEntry.conf.SourceType ?? catalogEntry.conf.ModDrv,
|
|
||||||
embedded: false,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachmentsFor(resourceType, id, fileName) {
|
|
||||||
if (resourceType === 'commentary') {
|
|
||||||
return {
|
|
||||||
included: [
|
|
||||||
{
|
|
||||||
id: `${id}-commentary`,
|
|
||||||
resource_type: 'commentary',
|
|
||||||
label: 'Commentary entries',
|
|
||||||
relationship: 'range-to-commentary',
|
|
||||||
anchor_types: ['book', 'chapter', 'verse', 'verse_range'],
|
|
||||||
languages: ['eng'],
|
|
||||||
source: 'CrossWire SWORD module export.',
|
|
||||||
package: `packages/json/${id}/${fileName}`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
included: [
|
|
||||||
{
|
|
||||||
id: `${id}-dictionary`,
|
|
||||||
resource_type: 'dictionary',
|
|
||||||
label: 'Dictionary entries',
|
|
||||||
relationship: 'key-to-definition',
|
|
||||||
anchor_types: ['strongs_number', 'topic', 'dictionary_key'],
|
|
||||||
languages: ['eng'],
|
|
||||||
systems: id.includes('strongs') ? ['strongs'] : undefined,
|
|
||||||
source: 'CrossWire SWORD module export.',
|
|
||||||
package: `packages/json/${id}/${fileName}`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function contributorsFor(conf, resourceType) {
|
|
||||||
const contributors = [
|
|
||||||
{
|
|
||||||
name: 'CrossWire Bible Society',
|
|
||||||
role: 'module provider',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
if (resourceType === 'commentary' && /Matthew Henry/i.test(conf.Description ?? '')) {
|
|
||||||
contributors.unshift({ name: 'Matthew Henry', role: 'commentary author' })
|
|
||||||
} else if (resourceType === 'commentary' && /Jamieson/i.test(conf.Description ?? '')) {
|
|
||||||
contributors.unshift({ name: 'Robert Jamieson, A. R. Fausset, and David Brown', role: 'commentary authors' })
|
|
||||||
} else if (/Strong/i.test(conf.Description ?? '')) {
|
|
||||||
contributors.unshift({ name: 'James Strong', role: 'dictionary author' })
|
|
||||||
} else if (/Nave/i.test(conf.Description ?? '')) {
|
|
||||||
contributors.unshift({ name: 'Orville J. Nave', role: 'topical dictionary author' })
|
|
||||||
}
|
|
||||||
|
|
||||||
return contributors
|
|
||||||
}
|
|
||||||
|
|
||||||
function attributionFor(conf, moduleId) {
|
|
||||||
const parts = [
|
|
||||||
conf.Description,
|
|
||||||
conf.TextSource ? `Text source: ${conf.TextSource}` : null,
|
|
||||||
`SWORD module: ${moduleId}`,
|
|
||||||
'Provided by CrossWire Bible Society.',
|
|
||||||
]
|
|
||||||
return parts.filter(Boolean).join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
function summaryFor(resourceType, title, count, moduleId) {
|
|
||||||
return resourceType === 'commentary'
|
|
||||||
? `${title}, imported from the CrossWire ${moduleId} SWORD module with ${count} commentary entries.`
|
|
||||||
: `${title}, imported from the CrossWire ${moduleId} SWORD module with ${count} dictionary entries.`
|
|
||||||
}
|
|
||||||
|
|
||||||
function shellQuote(value) {
|
|
||||||
return `'${String(value).replace(/'/g, `'\\''`)}'`
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import {
|
|
||||||
classifySwordModule,
|
|
||||||
fetchSwordConfCatalog,
|
|
||||||
loadLicenseApproval,
|
|
||||||
loadSwordPilotModules,
|
|
||||||
swordPackageUrl,
|
|
||||||
writeSwordAudit,
|
|
||||||
} from './sword-lib.js'
|
|
||||||
|
|
||||||
const pilot = await loadSwordPilotModules()
|
|
||||||
const licenseRegistry = await loadLicenseApproval()
|
|
||||||
const catalog = await fetchSwordConfCatalog(pilot.repository.mods_tarball_url)
|
|
||||||
|
|
||||||
const modules = []
|
|
||||||
|
|
||||||
for (const item of pilot.modules) {
|
|
||||||
const catalogEntry = catalog.modules.get(item.id.toLowerCase())
|
|
||||||
|
|
||||||
if (!catalogEntry) {
|
|
||||||
modules.push({
|
|
||||||
id: item.id,
|
|
||||||
intended_resource_type: item.intended_resource_type,
|
|
||||||
found: false,
|
|
||||||
license_status: 'missing',
|
|
||||||
review_notes: 'Module was not found in the CrossWire catalog.',
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const conf = catalogEntry.conf
|
|
||||||
const license = classifySwordModule(conf, licenseRegistry)
|
|
||||||
modules.push({
|
|
||||||
id: catalogEntry.module_id,
|
|
||||||
intended_resource_type: item.intended_resource_type,
|
|
||||||
found: true,
|
|
||||||
title: conf.Description ?? catalogEntry.module_id,
|
|
||||||
abbreviation: conf.Abbreviation ?? catalogEntry.module_id,
|
|
||||||
lang: conf.Lang ?? 'n/a',
|
|
||||||
mod_drv: conf.ModDrv,
|
|
||||||
source_type: conf.SourceType,
|
|
||||||
version: conf.Version,
|
|
||||||
sword_version_date: conf.SwordVersionDate,
|
|
||||||
distribution_license: conf.DistributionLicense ?? 'n/a',
|
|
||||||
text_source: conf.TextSource ?? 'n/a',
|
|
||||||
package_url: swordPackageUrl(catalogEntry.module_id, pilot.repository.package_base_url),
|
|
||||||
license_status: license.status,
|
|
||||||
license_rule: license.rule,
|
|
||||||
redistribution: license.redistribution ?? false,
|
|
||||||
commercial_use: license.commercial_use ?? null,
|
|
||||||
share_alike: license.share_alike ?? false,
|
|
||||||
import_enabled: item.import_enabled !== false,
|
|
||||||
import_status: item.import_status ?? (item.import_enabled === false ? 'deferred' : 'candidate'),
|
|
||||||
review_notes: license.notes,
|
|
||||||
reason: item.reason,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const audit = {
|
|
||||||
schema_version: 'librebible.sword-module-audit.v1',
|
|
||||||
generated_at: new Date().toISOString(),
|
|
||||||
repository: pilot.repository,
|
|
||||||
catalog_sha256: catalog.sha256,
|
|
||||||
modules,
|
|
||||||
}
|
|
||||||
|
|
||||||
await writeSwordAudit(audit)
|
|
||||||
|
|
||||||
const approved = modules.filter((module) => module.license_status.startsWith('approved')).length
|
|
||||||
const review = modules.filter((module) => module.license_status === 'review').length
|
|
||||||
const rejected = modules.filter((module) => module.license_status === 'rejected').length
|
|
||||||
|
|
||||||
console.log(`SWORD audit complete: ${modules.length} module(s), ${approved} approved, ${review} review, ${rejected} rejected.`)
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
import { createHash } from 'node:crypto'
|
|
||||||
import { gunzipSync } from 'node:zlib'
|
|
||||||
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
||||||
import path from 'node:path'
|
|
||||||
import { exists, readJson, writeJson } from './lib.js'
|
|
||||||
|
|
||||||
export const swordCacheDir = path.join(process.cwd(), 'cache', 'sword')
|
|
||||||
export const defaultModsTarballUrl = 'https://crosswire.org/ftpmirror/pub/sword/raw/mods.d.tar.gz'
|
|
||||||
export const defaultPackageBaseUrl = 'https://crosswire.org/ftpmirror/pub/sword/packages/rawzip'
|
|
||||||
|
|
||||||
export async function fetchSwordConfCatalog(url = defaultModsTarballUrl) {
|
|
||||||
await mkdir(swordCacheDir, { recursive: true })
|
|
||||||
const tarballPath = path.join(swordCacheDir, 'mods.d.tar.gz')
|
|
||||||
|
|
||||||
if (!(await exists(tarballPath))) {
|
|
||||||
const response = await fetch(url)
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Unable to fetch SWORD module catalog ${url}: ${response.status} ${response.statusText}`)
|
|
||||||
}
|
|
||||||
await writeFile(tarballPath, Buffer.from(await response.arrayBuffer()))
|
|
||||||
}
|
|
||||||
|
|
||||||
const tarball = await readFile(tarballPath)
|
|
||||||
const sha256 = createHash('sha256').update(tarball).digest('hex')
|
|
||||||
const tar = gunzipSync(tarball)
|
|
||||||
const modules = new Map()
|
|
||||||
|
|
||||||
for (const entry of readTarEntries(tar)) {
|
|
||||||
if (!entry.name.endsWith('.conf')) continue
|
|
||||||
const text = entry.content.toString('utf8')
|
|
||||||
const conf = parseSwordConf(text)
|
|
||||||
if (conf.module_id) {
|
|
||||||
modules.set(conf.module_id.toLowerCase(), {
|
|
||||||
module_id: conf.module_id,
|
|
||||||
conf_file: entry.name,
|
|
||||||
conf_text: text,
|
|
||||||
conf,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
source_url: url,
|
|
||||||
tarball_path: tarballPath,
|
|
||||||
sha256,
|
|
||||||
modules,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function loadSwordPilotModules(filePath = path.join(process.cwd(), 'registries', 'sword-pilot-modules.json')) {
|
|
||||||
return readJson(filePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function loadLicenseApproval(filePath = path.join(process.cwd(), 'registries', 'license-approval.json')) {
|
|
||||||
return readJson(filePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function classifySwordModule(conf, licenseRegistry) {
|
|
||||||
const licenseText = [
|
|
||||||
conf.DistributionLicense,
|
|
||||||
conf.Copyright,
|
|
||||||
conf.About,
|
|
||||||
conf.ShortPromo,
|
|
||||||
].filter(Boolean).join('\n').toLowerCase()
|
|
||||||
|
|
||||||
for (const rule of licenseRegistry.rejected ?? []) {
|
|
||||||
if (licenseText.includes(rule.match.toLowerCase())) {
|
|
||||||
return { status: rule.status, rule: rule.match, notes: rule.notes }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const rule of licenseRegistry.approved ?? []) {
|
|
||||||
if (licenseText.includes(rule.match.toLowerCase())) {
|
|
||||||
return {
|
|
||||||
status: rule.status,
|
|
||||||
rule: rule.match,
|
|
||||||
redistribution: rule.redistribution,
|
|
||||||
commercial_use: rule.commercial_use,
|
|
||||||
share_alike: rule.share_alike,
|
|
||||||
notes: rule.notes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const rule of licenseRegistry.review ?? []) {
|
|
||||||
if (licenseText.includes(rule.match.toLowerCase())) {
|
|
||||||
return { status: rule.status, rule: rule.match, notes: rule.notes }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
status: 'review',
|
|
||||||
rule: null,
|
|
||||||
notes: 'No approval rule matched the module license metadata.',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function swordPackageUrl(moduleId, packageBaseUrl = defaultPackageBaseUrl) {
|
|
||||||
return `${packageBaseUrl.replace(/\/$/, '')}/${moduleId}.zip`
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function writeSwordAudit(outputs) {
|
|
||||||
await writeJson(path.join(process.cwd(), 'audits', 'sword', 'module-audit.json'), outputs)
|
|
||||||
await mkdir(path.join(process.cwd(), 'docs'), { recursive: true })
|
|
||||||
await writeFile(path.join(process.cwd(), 'docs', 'sword-module-audit.md'), swordAuditMarkdown(outputs), 'utf8')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseSwordConf(input) {
|
|
||||||
const conf = {}
|
|
||||||
let moduleId = null
|
|
||||||
let currentKey = null
|
|
||||||
|
|
||||||
for (const rawLine of input.split(/\r?\n/)) {
|
|
||||||
const line = rawLine.trim()
|
|
||||||
if (!line || line.startsWith('#')) continue
|
|
||||||
|
|
||||||
const section = /^\[([^\]]+)\]$/.exec(line)
|
|
||||||
if (section) {
|
|
||||||
moduleId = section[1]
|
|
||||||
conf.module_id = moduleId
|
|
||||||
currentKey = null
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const kv = /^([^=]+)=(.*)$/.exec(line)
|
|
||||||
if (kv) {
|
|
||||||
const key = kv[1].trim()
|
|
||||||
const value = cleanSwordValue(kv[2].trim())
|
|
||||||
if (conf[key] === undefined) {
|
|
||||||
conf[key] = value
|
|
||||||
} else if (Array.isArray(conf[key])) {
|
|
||||||
conf[key].push(value)
|
|
||||||
} else {
|
|
||||||
conf[key] = [conf[key], value]
|
|
||||||
}
|
|
||||||
currentKey = key
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentKey && typeof conf[currentKey] === 'string') {
|
|
||||||
conf[currentKey] = `${conf[currentKey]}\n${cleanSwordValue(line)}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanSwordValue(value) {
|
|
||||||
return value.replace(/\\par\s*/g, '\n').replace(/\s+\n/g, '\n').trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
function readTarEntries(buffer) {
|
|
||||||
const entries = []
|
|
||||||
let offset = 0
|
|
||||||
|
|
||||||
while (offset + 512 <= buffer.length) {
|
|
||||||
const header = buffer.subarray(offset, offset + 512)
|
|
||||||
if (header.every((byte) => byte === 0)) break
|
|
||||||
|
|
||||||
const name = readNullTerminated(header.subarray(0, 100))
|
|
||||||
const sizeText = readNullTerminated(header.subarray(124, 136)).trim()
|
|
||||||
const size = Number.parseInt(sizeText || '0', 8)
|
|
||||||
const contentStart = offset + 512
|
|
||||||
const contentEnd = contentStart + size
|
|
||||||
entries.push({
|
|
||||||
name,
|
|
||||||
size,
|
|
||||||
content: buffer.subarray(contentStart, contentEnd),
|
|
||||||
})
|
|
||||||
|
|
||||||
offset = contentStart + Math.ceil(size / 512) * 512
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries
|
|
||||||
}
|
|
||||||
|
|
||||||
function readNullTerminated(buffer) {
|
|
||||||
const zero = buffer.indexOf(0)
|
|
||||||
return buffer.subarray(0, zero === -1 ? buffer.length : zero).toString('utf8')
|
|
||||||
}
|
|
||||||
|
|
||||||
function swordAuditMarkdown(audit) {
|
|
||||||
const lines = [
|
|
||||||
'# CrossWire SWORD Module Audit',
|
|
||||||
'',
|
|
||||||
'This file is generated from the CrossWire SWORD module catalog and the local LibreBible license approval registry.',
|
|
||||||
'',
|
|
||||||
`- Repository: ${audit.repository.name}`,
|
|
||||||
`- Catalog URL: ${audit.repository.mods_tarball_url}`,
|
|
||||||
`- Catalog SHA-256: \`${audit.catalog_sha256}\``,
|
|
||||||
`- Generated: ${audit.generated_at}`,
|
|
||||||
'',
|
|
||||||
'| Module | Intended Type | SWORD Type | Source Type | License | License Status | Import Status | Package | Notes |',
|
|
||||||
'| --- | --- | --- | --- | --- | --- | --- | --- | --- |',
|
|
||||||
]
|
|
||||||
|
|
||||||
for (const module of audit.modules) {
|
|
||||||
lines.push([
|
|
||||||
module.id,
|
|
||||||
module.intended_resource_type,
|
|
||||||
module.mod_drv ?? 'n/a',
|
|
||||||
module.source_type ?? 'n/a',
|
|
||||||
module.distribution_license ?? 'n/a',
|
|
||||||
module.license_status,
|
|
||||||
module.import_status ?? (module.import_enabled === false ? 'deferred' : 'candidate'),
|
|
||||||
module.package_url ? `[zip](${module.package_url})` : 'n/a',
|
|
||||||
module.review_notes.replace(/\|/g, '/'),
|
|
||||||
].join(' | ').replace(/^/, '| ').replace(/$/, ' |'))
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.push('')
|
|
||||||
lines.push('## Next Import Gate')
|
|
||||||
lines.push('')
|
|
||||||
lines.push('A SWORD module should not move from this audit into `packages/json/` until its license metadata is approved and the importer can convert the module content into LibreBible package formats with checksums.')
|
|
||||||
|
|
||||||
return `${lines.join('\n')}\n`
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { fetchSwordConfCatalog } from './sword-lib.js'
|
|
||||||
|
|
||||||
const catalog = await fetchSwordConfCatalog()
|
|
||||||
const modules = [...catalog.modules.values()]
|
|
||||||
.map((entry) => ({
|
|
||||||
id: entry.module_id,
|
|
||||||
description: scalar(entry.conf.Description),
|
|
||||||
mod_drv: scalar(entry.conf.ModDrv),
|
|
||||||
source_type: scalar(entry.conf.SourceType),
|
|
||||||
license: scalar(entry.conf.DistributionLicense),
|
|
||||||
lang: scalar(entry.conf.Lang),
|
|
||||||
}))
|
|
||||||
.sort((a, b) => a.id.localeCompare(b.id))
|
|
||||||
|
|
||||||
for (const module of modules) {
|
|
||||||
console.log([
|
|
||||||
module.id.padEnd(24),
|
|
||||||
module.mod_drv.padEnd(8),
|
|
||||||
module.source_type.padEnd(8),
|
|
||||||
module.lang.padEnd(6),
|
|
||||||
module.license.padEnd(24),
|
|
||||||
module.description,
|
|
||||||
].join(' ').trimEnd())
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`\n${modules.length} SWORD module(s) listed from ${catalog.source_url}`)
|
|
||||||
|
|
||||||
function scalar(value) {
|
|
||||||
if (Array.isArray(value)) return value.join(', ')
|
|
||||||
return value ?? ''
|
|
||||||
}
|
|
||||||
@@ -30,10 +30,6 @@
|
|||||||
"name": "King James Version translators",
|
"name": "King James Version translators",
|
||||||
"role": "translation"
|
"role": "translation"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "source text provider"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "eBible.org",
|
"name": "eBible.org",
|
||||||
"role": "publisher and package provider"
|
"role": "publisher and package provider"
|
||||||
@@ -103,7 +99,6 @@
|
|||||||
"mobile-html",
|
"mobile-html",
|
||||||
"epub",
|
"epub",
|
||||||
"pdf",
|
"pdf",
|
||||||
"sword",
|
|
||||||
"plain-text",
|
"plain-text",
|
||||||
"vpl-sql",
|
"vpl-sql",
|
||||||
"browser-bible",
|
"browser-bible",
|
||||||
@@ -117,7 +112,7 @@
|
|||||||
"redistribution": true,
|
"redistribution": true,
|
||||||
"jurisdiction_notes": "eBible states this work is firmly public domain outside the United Kingdom; UK printing/import may be restricted by Crown letters patent.",
|
"jurisdiction_notes": "eBible states this work is firmly public domain outside the United Kingdom; UK printing/import may be restricted by Crown letters patent.",
|
||||||
"source_license_url": "https://ebible.org/find/show.php?id=eng-kjv2006",
|
"source_license_url": "https://ebible.org/find/show.php?id=eng-kjv2006",
|
||||||
"attribution": "This free text is provided courtesy of CrossWire Bible Society and eBible.org.",
|
"attribution": "This free text is provided courtesy of eBible.org.",
|
||||||
"public_domain_outside": ["United Kingdom"],
|
"public_domain_outside": ["United Kingdom"],
|
||||||
"restricted_notes": "Printing this translation in the United Kingdom or importing printed copies into the UK may require permission from the Crown patent holders."
|
"restricted_notes": "Printing this translation in the United Kingdom or importing printed copies into the UK may require permission from the Crown patent holders."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,119 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "sword-jfb",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"project_name": "LibreBible",
|
|
||||||
"title": "Jamieson Fausset Brown Bible Commentary",
|
|
||||||
"short_title": "Jamieson Fausset Brown Bible Commentary",
|
|
||||||
"abbreviation": "JFB",
|
|
||||||
"alternate_ids": [
|
|
||||||
"JFB"
|
|
||||||
],
|
|
||||||
"language": {
|
|
||||||
"code": "en",
|
|
||||||
"name": "English"
|
|
||||||
},
|
|
||||||
"script": "Latn",
|
|
||||||
"canon": {
|
|
||||||
"scope": "KJV",
|
|
||||||
"notes": "Commentary entries are keyed to SWORD Bible references."
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Robert Jamieson, A. R. Fausset, and David Brown",
|
|
||||||
"role": "commentary authors"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "module provider"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"id": "commentary-entries",
|
|
||||||
"type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"embedded": true,
|
|
||||||
"package": "packages/json/sword-jfb/commentary.jsonl"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-source",
|
|
||||||
"type": "source_format",
|
|
||||||
"label": "SWORD source",
|
|
||||||
"format": "OSIS",
|
|
||||||
"embedded": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attachments": {
|
|
||||||
"included": [
|
|
||||||
{
|
|
||||||
"id": "sword-jfb-commentary",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"relationship": "range-to-commentary",
|
|
||||||
"anchor_types": [
|
|
||||||
"book",
|
|
||||||
"chapter",
|
|
||||||
"verse",
|
|
||||||
"verse_range"
|
|
||||||
],
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"source": "CrossWire SWORD module export.",
|
|
||||||
"package": "packages/json/sword-jfb/commentary.jsonl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source": {
|
|
||||||
"provider": "CrossWire Bible Society",
|
|
||||||
"url": "https://crosswire.org/sword/modules/ModInfo.jsp?modName=JFB",
|
|
||||||
"download_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/JFB.zip",
|
|
||||||
"format": "sword-rawzip",
|
|
||||||
"upstream_id": "JFB",
|
|
||||||
"upstream_last_updated": "2021-02-15",
|
|
||||||
"sword": {
|
|
||||||
"module_id": "JFB",
|
|
||||||
"conf_file": "mods.d/jfb.conf",
|
|
||||||
"mod_drv": "zCom4",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "3.0",
|
|
||||||
"data_path": "./modules/comments/zcom/jfb/",
|
|
||||||
"text_source": "https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"name": "Public Domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"source_license_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/jfb.conf",
|
|
||||||
"attribution": "Jamieson Fausset Brown Bible Commentary Text source: https://ccel.org/ccel/j/jamieson/jfb/cache/jfb.txt SWORD module: JFB Provided by CrossWire Bible Society.",
|
|
||||||
"jurisdiction_notes": "No jurisdiction-specific restriction was found in the SWORD module metadata.",
|
|
||||||
"restricted_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction."
|
|
||||||
},
|
|
||||||
"checks": {
|
|
||||||
"expected_sha256": "a0b44ee84687cf0d8300ea4543cd375be42ab804902e72e448ea5f7d1c60b1bf",
|
|
||||||
"last_checked_at": "2026-07-12T04:31:19.021Z"
|
|
||||||
},
|
|
||||||
"importer": {
|
|
||||||
"name": "scripts/import-sword.js",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"engine": "CrossWire SWORD mod2imp via Docker/Ubuntu libsword-utils"
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"json_catalog": "packages/json/sword-jfb/catalog.json",
|
|
||||||
"entries_jsonl": "packages/json/sword-jfb/commentary.jsonl"
|
|
||||||
},
|
|
||||||
"catalog_display": {
|
|
||||||
"primary_features": [
|
|
||||||
"Commentary entries",
|
|
||||||
"Verse/range anchors",
|
|
||||||
"SWORD source"
|
|
||||||
],
|
|
||||||
"summary": "Jamieson Fausset Brown Bible Commentary, imported from the CrossWire JFB SWORD module with 16945 commentary entries."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "sword-mhcc",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"project_name": "LibreBible",
|
|
||||||
"title": "Matthew Henry's Concise Commentary on the Whole Bible",
|
|
||||||
"short_title": "Matthew Henry's Concise Commentary on the Whole Bible",
|
|
||||||
"abbreviation": "MHCC",
|
|
||||||
"alternate_ids": [
|
|
||||||
"MHCC"
|
|
||||||
],
|
|
||||||
"language": {
|
|
||||||
"code": "en",
|
|
||||||
"name": "English"
|
|
||||||
},
|
|
||||||
"script": "Latn",
|
|
||||||
"canon": {
|
|
||||||
"scope": "KJV",
|
|
||||||
"notes": "Commentary entries are keyed to SWORD Bible references."
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Matthew Henry",
|
|
||||||
"role": "commentary author"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CrossWire Bible Society",
|
|
||||||
"role": "module provider"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"id": "commentary-entries",
|
|
||||||
"type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"embedded": true,
|
|
||||||
"package": "packages/json/sword-mhcc/commentary.jsonl"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "sword-source",
|
|
||||||
"type": "source_format",
|
|
||||||
"label": "SWORD source",
|
|
||||||
"format": "OSIS",
|
|
||||||
"embedded": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attachments": {
|
|
||||||
"included": [
|
|
||||||
{
|
|
||||||
"id": "sword-mhcc-commentary",
|
|
||||||
"resource_type": "commentary",
|
|
||||||
"label": "Commentary entries",
|
|
||||||
"relationship": "range-to-commentary",
|
|
||||||
"anchor_types": [
|
|
||||||
"book",
|
|
||||||
"chapter",
|
|
||||||
"verse",
|
|
||||||
"verse_range"
|
|
||||||
],
|
|
||||||
"languages": [
|
|
||||||
"eng"
|
|
||||||
],
|
|
||||||
"source": "CrossWire SWORD module export.",
|
|
||||||
"package": "packages/json/sword-mhcc/commentary.jsonl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"source": {
|
|
||||||
"provider": "CrossWire Bible Society",
|
|
||||||
"url": "https://crosswire.org/sword/modules/ModInfo.jsp?modName=MHCC",
|
|
||||||
"download_url": "https://crosswire.org/ftpmirror/pub/sword/packages/rawzip/MHCC.zip",
|
|
||||||
"format": "sword-rawzip",
|
|
||||||
"upstream_id": "MHCC",
|
|
||||||
"upstream_last_updated": "2021-02-14",
|
|
||||||
"sword": {
|
|
||||||
"module_id": "MHCC",
|
|
||||||
"conf_file": "mods.d/mhcc.conf",
|
|
||||||
"mod_drv": "zCom",
|
|
||||||
"source_type": "OSIS",
|
|
||||||
"versification": "KJV",
|
|
||||||
"version": "2.0",
|
|
||||||
"data_path": "./modules/comments/zcom/mhcc/",
|
|
||||||
"text_source": "https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"license": {
|
|
||||||
"name": "Public Domain",
|
|
||||||
"redistribution": true,
|
|
||||||
"commercial_use": true,
|
|
||||||
"share_alike": false,
|
|
||||||
"source_license_url": "https://crosswire.org/ftpmirror/pub/sword/raw/mods.d/mhcc.conf",
|
|
||||||
"attribution": "Matthew Henry's Concise Commentary on the Whole Bible Text source: https://ccel.org/ccel/h/henry/mhcc/cache/mhcc.txt SWORD module: MHCC Provided by CrossWire Bible Society.",
|
|
||||||
"jurisdiction_notes": "No jurisdiction-specific restriction was found in the SWORD module metadata.",
|
|
||||||
"restricted_notes": "Public-domain resources may be normalized and redistributed when the upstream module metadata has no extra restriction."
|
|
||||||
},
|
|
||||||
"checks": {
|
|
||||||
"expected_sha256": "fc21726d9f5621c6168ed173442df2a973acad8d1d210ac1fa6c7ead7d3c5f30",
|
|
||||||
"last_checked_at": "2026-07-12T04:31:19.179Z"
|
|
||||||
},
|
|
||||||
"importer": {
|
|
||||||
"name": "scripts/import-sword.js",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"engine": "CrossWire SWORD mod2imp via Docker/Ubuntu libsword-utils"
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"json_catalog": "packages/json/sword-mhcc/catalog.json",
|
|
||||||
"entries_jsonl": "packages/json/sword-mhcc/commentary.jsonl"
|
|
||||||
},
|
|
||||||
"catalog_display": {
|
|
||||||
"primary_features": [
|
|
||||||
"Commentary entries",
|
|
||||||
"Verse/range anchors",
|
|
||||||
"SWORD source"
|
|
||||||
],
|
|
||||||
"summary": "Matthew Henry's Concise Commentary on the Whole Bible, imported from the CrossWire MHCC SWORD module with 4059 commentary entries."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user