twl-generator 1.1.5 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -134,7 +134,7 @@ All standard Bible book abbreviations are supported:
|
|
|
134
134
|
The generated TSV contains these columns:
|
|
135
135
|
|
|
136
136
|
- **Reference**: Chapter:verse (e.g., "1:1")
|
|
137
|
-
- **ID**: Unique 4-character
|
|
137
|
+
- **ID**: Unique 4-character identifier
|
|
138
138
|
- **Tags**: Article category ("keyterm", "name", or empty)
|
|
139
139
|
- **OrigWords**: The matched text from the source
|
|
140
140
|
- **Occurrence**: Occurrence number for this term in this verse
|
|
@@ -144,7 +144,7 @@ The generated TSV contains these columns:
|
|
|
144
144
|
|
|
145
145
|
## Requirements
|
|
146
146
|
|
|
147
|
-
- **Node.js**: >=
|
|
147
|
+
- **Node.js**: >=18.0.0 (for native fetch support)
|
|
148
148
|
- **Browser**: Modern browser with ES6 modules support
|
|
149
149
|
- **React.js**: >=16.8.0 (for React usage)
|
|
150
150
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "twl-generator",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Generate term-to-article lists from unfoldingWord en_tw archive for Bible books. Works in both Node.js (CLI) and React.js (browser) environments.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -43,11 +43,10 @@
|
|
|
43
43
|
"LICENSE"
|
|
44
44
|
],
|
|
45
45
|
"engines": {
|
|
46
|
-
"node": ">=
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"jszip": "^3.10.1"
|
|
50
|
-
"node-fetch": "^3.3.2"
|
|
49
|
+
"jszip": "^3.10.1"
|
|
51
50
|
},
|
|
52
51
|
"peerDependencies": {
|
|
53
52
|
"react": ">=16.8.0"
|
|
@@ -57,4 +56,4 @@
|
|
|
57
56
|
"optional": true
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
|
-
}
|
|
59
|
+
}
|
|
@@ -7,10 +7,7 @@ const isNode = typeof window === 'undefined' && typeof process !== 'undefined' &
|
|
|
7
7
|
|
|
8
8
|
// Get appropriate fetch implementation
|
|
9
9
|
async function getFetch() {
|
|
10
|
-
|
|
11
|
-
const nodeFetch = await import('node-fetch');
|
|
12
|
-
return nodeFetch.default;
|
|
13
|
-
}
|
|
10
|
+
// Both Node.js 18+ and browsers have native fetch
|
|
14
11
|
return globalThis.fetch;
|
|
15
12
|
}
|
|
16
13
|
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
* import { generateTWTerms } from './utils/zipProcessor.js';
|
|
8
8
|
* const terms = await generateTWTerms();
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
import { BibleBookData } from '../common/books.js';
|
|
10
|
+
import JSZip from "jszip";
|
|
12
11
|
|
|
13
12
|
// Environment detection
|
|
14
13
|
const isNode = typeof process !== 'undefined' && process.versions?.node;
|
|
@@ -21,29 +20,6 @@ const CACHE_VERSION = '1.0';
|
|
|
21
20
|
// In-memory cache for processed terms (per session)
|
|
22
21
|
let processedTermsCache = null;
|
|
23
22
|
|
|
24
|
-
/**
|
|
25
|
-
* Get dependencies dynamically (JSZip works in both environments)
|
|
26
|
-
*/
|
|
27
|
-
async function getDeps() {
|
|
28
|
-
try {
|
|
29
|
-
const jsZipModule = await import('jszip');
|
|
30
|
-
const deps = {
|
|
31
|
-
JSZip: jsZipModule.default
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Add Node.js-specific fetch if needed
|
|
35
|
-
if (isNode) {
|
|
36
|
-
const nodeModule = await import('node-fetch');
|
|
37
|
-
deps.fetch = nodeModule.default;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return deps;
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.error('Failed to load dependencies:', error);
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
23
|
async function getCachedZip() {
|
|
48
24
|
if (isBrowser) {
|
|
49
25
|
// Browser: Use localStorage for ZIP cache
|
|
@@ -135,26 +111,6 @@ async function getCachedTerms() {
|
|
|
135
111
|
} catch (e) { /* ignore cleanup errors */ }
|
|
136
112
|
}
|
|
137
113
|
}
|
|
138
|
-
} else if (isNode) {
|
|
139
|
-
// Node.js file system caching
|
|
140
|
-
try {
|
|
141
|
-
const deps = await getNodeDeps();
|
|
142
|
-
if (!deps) return null;
|
|
143
|
-
|
|
144
|
-
const { fs, path, fileURLToPath } = deps;
|
|
145
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
146
|
-
const __dirname = path.dirname(__filename);
|
|
147
|
-
const CACHE_FILE = path.join(__dirname, '../../article_terms.json');
|
|
148
|
-
|
|
149
|
-
if (fs.existsSync(CACHE_FILE)) {
|
|
150
|
-
const cachedData = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
|
|
151
|
-
console.log('Using cached article terms from article_terms.json');
|
|
152
|
-
memoryCache = cachedData;
|
|
153
|
-
return cachedData;
|
|
154
|
-
}
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.log('File cache corrupted, regenerating...');
|
|
157
|
-
}
|
|
158
114
|
}
|
|
159
115
|
|
|
160
116
|
return null;
|
|
@@ -183,22 +139,6 @@ async function cacheTerms(termMap) {
|
|
|
183
139
|
console.warn('Failed to cache in browser storage:', error.message);
|
|
184
140
|
}
|
|
185
141
|
}
|
|
186
|
-
} else if (isNode) {
|
|
187
|
-
// Node.js file system caching
|
|
188
|
-
try {
|
|
189
|
-
const deps = await getNodeDeps();
|
|
190
|
-
if (!deps) return;
|
|
191
|
-
|
|
192
|
-
const { fs, path, fileURLToPath } = deps;
|
|
193
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
194
|
-
const __dirname = path.dirname(__filename);
|
|
195
|
-
const CACHE_FILE = path.join(__dirname, '../../article_terms.json');
|
|
196
|
-
|
|
197
|
-
fs.writeFileSync(CACHE_FILE, JSON.stringify(termMap, null, 2), 'utf8');
|
|
198
|
-
console.log('Article terms cached to article_terms.json');
|
|
199
|
-
} catch (error) {
|
|
200
|
-
console.warn('Failed to cache article terms to file:', error.message);
|
|
201
|
-
}
|
|
202
142
|
}
|
|
203
143
|
}
|
|
204
144
|
|
|
@@ -206,11 +146,6 @@ async function cacheTerms(termMap) {
|
|
|
206
146
|
* Process ZIP buffer and extract term mappings
|
|
207
147
|
*/
|
|
208
148
|
async function processZipBuffer(zipBuffer) {
|
|
209
|
-
// Use JSZip universally for both Node.js and Browser
|
|
210
|
-
const deps = await getDeps();
|
|
211
|
-
if (!deps) throw new Error('Failed to load dependencies');
|
|
212
|
-
const { JSZip } = deps;
|
|
213
|
-
|
|
214
149
|
const zip = new JSZip();
|
|
215
150
|
const zipData = await zip.loadAsync(zipBuffer);
|
|
216
151
|
|
|
@@ -268,17 +203,7 @@ export async function generateTWTerms() {
|
|
|
268
203
|
// Download fresh ZIP
|
|
269
204
|
console.log('Downloading TW archive...');
|
|
270
205
|
|
|
271
|
-
|
|
272
|
-
if (isBrowser) {
|
|
273
|
-
fetchFn = window.fetch;
|
|
274
|
-
} else {
|
|
275
|
-
const deps = await getDeps();
|
|
276
|
-
fetchFn = deps?.fetch;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
if (!fetchFn) throw new Error('Fetch not available');
|
|
280
|
-
|
|
281
|
-
const res = await fetchFn(ZIP_URL);
|
|
206
|
+
const res = await fetch(ZIP_URL);
|
|
282
207
|
if (!res.ok) throw new Error(`Failed to download ZIP: ${res.status} ${res.statusText}`);
|
|
283
208
|
|
|
284
209
|
zipBuffer = await res.arrayBuffer();
|