citeclaw 2.0.2 → 2.0.3
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/package.json +1 -1
- package/scripts/botcite.js +96 -15
package/package.json
CHANGED
package/scripts/botcite.js
CHANGED
|
@@ -28,13 +28,45 @@ const vendoredOfficialStylesDir = path.join( rootDir, 'vendor', 'styles-official
|
|
|
28
28
|
const localDir = path.join( rootDir, '.local' );
|
|
29
29
|
const logDir = path.join( localDir, 'logs' );
|
|
30
30
|
const stateDir = path.join( localDir, 'state' );
|
|
31
|
+
const localTranslatorSourcesDir = path.join( localDir, 'translator-sources' );
|
|
31
32
|
const mergedTranslatorsDir = process.env.LOCAL_TRANSLATORS_DIR ||
|
|
32
33
|
path.join( localDir, 'translators' );
|
|
33
34
|
const stylesRootDir = process.env.LOCAL_STYLES_DIR ||
|
|
34
35
|
path.join( localDir, 'styles' );
|
|
36
|
+
const localStyleSourcesDir = path.join( localDir, 'style-sources' );
|
|
35
37
|
const cslDir = path.join( stylesRootDir, 'csl' );
|
|
36
38
|
const localeDir = path.join( stylesRootDir, 'locales' );
|
|
37
39
|
const defaultStyleSources = [ vendoredOfficialStylesDir, vendoredStylesDir ];
|
|
40
|
+
const defaultStyleGitSources = [
|
|
41
|
+
{
|
|
42
|
+
url: 'https://github.com/citation-style-language/styles.git',
|
|
43
|
+
dir: path.join( localStyleSourcesDir, 'styles-official' )
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
url: 'https://github.com/zotero-chinese/styles.git',
|
|
47
|
+
dir: path.join( localStyleSourcesDir, 'styles' )
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
const defaultTranslatorGitSources = [
|
|
51
|
+
{
|
|
52
|
+
url: 'https://github.com/zotero/translators.git',
|
|
53
|
+
dir: path.join( localTranslatorSourcesDir, 'translators-official' )
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
url: 'https://github.com/l0o0/translators_CN.git',
|
|
57
|
+
dir: path.join( localTranslatorSourcesDir, 'translators_CN' )
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
function resolvedOfficialTranslatorsDir() {
|
|
62
|
+
const fallback = defaultTranslatorGitSources[ 0 ].dir;
|
|
63
|
+
return fileExists( officialTranslatorsDir ) ? officialTranslatorsDir : fallback;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function resolvedCnTranslatorsDir() {
|
|
67
|
+
const fallback = defaultTranslatorGitSources[ 1 ].dir;
|
|
68
|
+
return fileExists( cnTranslatorsDir ) ? cnTranslatorsDir : fallback;
|
|
69
|
+
}
|
|
38
70
|
const defaultPdfFetchIntervalMs = parseInt( process.env.CITOID_LOCAL_FETCH_INTERVAL_MS || '800', 10 );
|
|
39
71
|
const defaultRequestTimeoutMs = parseInt( process.env.CITOID_LOCAL_FETCH_TIMEOUT_MS || '15000', 10 );
|
|
40
72
|
const defaultProbeBodyBytes = parseInt( process.env.CITOID_LOCAL_PROBE_BODY_BYTES || '1572864', 10 );
|
|
@@ -469,13 +501,15 @@ function repoHeadOrMissing( repoPath ) {
|
|
|
469
501
|
|
|
470
502
|
function translatorsNeedSync() {
|
|
471
503
|
const stampPath = path.join( stateDir, 'translators-sync.stamp' );
|
|
504
|
+
const activeOfficialDir = resolvedOfficialTranslatorsDir();
|
|
505
|
+
const activeCnDir = resolvedCnTranslatorsDir();
|
|
472
506
|
const hasMerged = fileExists( mergedTranslatorsDir ) &&
|
|
473
507
|
fs.readdirSync( mergedTranslatorsDir ).some( ( name ) => name.endsWith( '.js' ) );
|
|
474
508
|
if ( !hasMerged ) {
|
|
475
509
|
return true;
|
|
476
510
|
}
|
|
477
511
|
|
|
478
|
-
const currentStamp = `zotero=${ repoHeadOrMissing( path.join( zoteroDir, 'modules', 'translators' ) ) };official=${ repoHeadOrMissing(
|
|
512
|
+
const currentStamp = `zotero=${ repoHeadOrMissing( path.join( zoteroDir, 'modules', 'translators' ) ) };official=${ repoHeadOrMissing( activeOfficialDir ) };cn=${ repoHeadOrMissing( activeCnDir ) }`;
|
|
479
513
|
let previousStamp = '';
|
|
480
514
|
if ( fileExists( stampPath ) ) {
|
|
481
515
|
previousStamp = fs.readFileSync( stampPath, 'utf8' ).trim();
|
|
@@ -485,7 +519,7 @@ function translatorsNeedSync() {
|
|
|
485
519
|
|
|
486
520
|
function writeTranslatorStamp() {
|
|
487
521
|
const stampPath = path.join( stateDir, 'translators-sync.stamp' );
|
|
488
|
-
const stamp = `zotero=${ repoHeadOrMissing( path.join( zoteroDir, 'modules', 'translators' ) ) };official=${ repoHeadOrMissing(
|
|
522
|
+
const stamp = `zotero=${ repoHeadOrMissing( path.join( zoteroDir, 'modules', 'translators' ) ) };official=${ repoHeadOrMissing( resolvedOfficialTranslatorsDir() ) };cn=${ repoHeadOrMissing( resolvedCnTranslatorsDir() ) }`;
|
|
489
523
|
fs.writeFileSync( stampPath, `${ stamp }\n` );
|
|
490
524
|
}
|
|
491
525
|
|
|
@@ -493,6 +527,8 @@ function syncMergedTranslators() {
|
|
|
493
527
|
fs.rmSync( mergedTranslatorsDir, { recursive: true, force: true } );
|
|
494
528
|
fs.mkdirSync( mergedTranslatorsDir, { recursive: true } );
|
|
495
529
|
const zoteroTranslators = path.join( zoteroDir, 'modules', 'translators' );
|
|
530
|
+
const activeOfficialDir = resolvedOfficialTranslatorsDir();
|
|
531
|
+
const activeCnDir = resolvedCnTranslatorsDir();
|
|
496
532
|
if ( fileExists( zoteroTranslators ) ) {
|
|
497
533
|
fs.readdirSync( zoteroTranslators )
|
|
498
534
|
.filter( ( name ) => name.endsWith( '.js' ) )
|
|
@@ -503,22 +539,22 @@ function syncMergedTranslators() {
|
|
|
503
539
|
);
|
|
504
540
|
} );
|
|
505
541
|
}
|
|
506
|
-
if ( fileExists(
|
|
507
|
-
fs.readdirSync(
|
|
542
|
+
if ( fileExists( activeOfficialDir ) ) {
|
|
543
|
+
fs.readdirSync( activeOfficialDir )
|
|
508
544
|
.filter( ( name ) => name.endsWith( '.js' ) )
|
|
509
545
|
.forEach( ( name ) => {
|
|
510
546
|
fs.copyFileSync(
|
|
511
|
-
path.join(
|
|
547
|
+
path.join( activeOfficialDir, name ),
|
|
512
548
|
path.join( mergedTranslatorsDir, name )
|
|
513
549
|
);
|
|
514
550
|
} );
|
|
515
551
|
}
|
|
516
|
-
if ( fileExists(
|
|
517
|
-
fs.readdirSync(
|
|
552
|
+
if ( fileExists( activeCnDir ) ) {
|
|
553
|
+
fs.readdirSync( activeCnDir )
|
|
518
554
|
.filter( ( name ) => name.endsWith( '.js' ) )
|
|
519
555
|
.forEach( ( name ) => {
|
|
520
556
|
fs.copyFileSync(
|
|
521
|
-
path.join(
|
|
557
|
+
path.join( activeCnDir, name ),
|
|
522
558
|
path.join( mergedTranslatorsDir, name )
|
|
523
559
|
);
|
|
524
560
|
} );
|
|
@@ -526,10 +562,39 @@ function syncMergedTranslators() {
|
|
|
526
562
|
writeTranslatorStamp();
|
|
527
563
|
}
|
|
528
564
|
|
|
565
|
+
function ensureDefaultTranslatorSources() {
|
|
566
|
+
const existingOfficial = fileExists( officialTranslatorsDir ) ? officialTranslatorsDir : null;
|
|
567
|
+
const existingCn = fileExists( cnTranslatorsDir ) ? cnTranslatorsDir : null;
|
|
568
|
+
if ( existingOfficial && existingCn ) {
|
|
569
|
+
return {
|
|
570
|
+
officialDir: existingOfficial,
|
|
571
|
+
cnDir: existingCn
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
if ( !commandExists( 'git' ) ) {
|
|
575
|
+
throw new Error(
|
|
576
|
+
'missing translator sources and git is not installed; install git or provide vendored translator directories'
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
fs.mkdirSync( localTranslatorSourcesDir, { recursive: true } );
|
|
580
|
+
defaultTranslatorGitSources.forEach( ( source ) => {
|
|
581
|
+
if ( fileExists( source.dir ) ) {
|
|
582
|
+
runCommandOrThrow( 'git', [ '-C', source.dir, 'pull', '--ff-only' ] );
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
runCommandOrThrow( 'git', [ 'clone', '--depth', '1', source.url, source.dir ] );
|
|
586
|
+
} );
|
|
587
|
+
return {
|
|
588
|
+
officialDir: defaultTranslatorGitSources[ 0 ].dir,
|
|
589
|
+
cnDir: defaultTranslatorGitSources[ 1 ].dir
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
529
593
|
function bootstrapLocalEnvironment() {
|
|
530
594
|
ensureDirs();
|
|
531
595
|
const installer = resolveInstallCommand();
|
|
532
|
-
|
|
596
|
+
const translatorSources = ensureDefaultTranslatorSources();
|
|
597
|
+
if ( !repoReady( zoteroDir ) || !repoReady( translatorSources.cnDir ) || !repoReady( translatorSources.officialDir ) ) {
|
|
533
598
|
throw new Error(
|
|
534
599
|
'missing vendored repos under vendor/. pull the complete repository content.'
|
|
535
600
|
);
|
|
@@ -572,6 +637,27 @@ function ensureStyleRuntime() {
|
|
|
572
637
|
throw new Error( 'Styles are not synced. Run: citeclaw styles sync' );
|
|
573
638
|
}
|
|
574
639
|
|
|
640
|
+
function ensureDefaultStyleSources() {
|
|
641
|
+
const existing = defaultStyleSources.filter( ( sourceDir ) => fileExists( sourceDir ) );
|
|
642
|
+
if ( existing.length ) {
|
|
643
|
+
return existing;
|
|
644
|
+
}
|
|
645
|
+
if ( !commandExists( 'git' ) ) {
|
|
646
|
+
throw new Error(
|
|
647
|
+
'no bundled style sources found in this package, and git is not installed; install git or pass --repo <styles-dir>'
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
fs.mkdirSync( localStyleSourcesDir, { recursive: true } );
|
|
651
|
+
defaultStyleGitSources.forEach( ( source ) => {
|
|
652
|
+
if ( fileExists( source.dir ) ) {
|
|
653
|
+
runCommandOrThrow( 'git', [ '-C', source.dir, 'pull', '--ff-only' ] );
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
runCommandOrThrow( 'git', [ 'clone', '--depth', '1', source.url, source.dir ] );
|
|
657
|
+
} );
|
|
658
|
+
return defaultStyleGitSources.map( ( source ) => source.dir );
|
|
659
|
+
}
|
|
660
|
+
|
|
575
661
|
function walkFiles( dirPath ) {
|
|
576
662
|
const entries = fs.readdirSync( dirPath, { withFileTypes: true } );
|
|
577
663
|
let result = [];
|
|
@@ -1393,16 +1479,11 @@ async function syncStyles( options ) {
|
|
|
1393
1479
|
options.repo :
|
|
1394
1480
|
path.join( rootDir, options.repo || 'vendor/styles' )
|
|
1395
1481
|
] :
|
|
1396
|
-
|
|
1482
|
+
ensureDefaultStyleSources();
|
|
1397
1483
|
const sourceDirs = configuredSourceDirs.filter( ( sourceDir ) => fileExists( sourceDir ) );
|
|
1398
1484
|
if ( options.repo && !sourceDirs.length ) {
|
|
1399
1485
|
throw new Error( `styles source not found: ${ configuredSourceDirs.join( ', ' ) }` );
|
|
1400
1486
|
}
|
|
1401
|
-
if ( !options.repo && !sourceDirs.length ) {
|
|
1402
|
-
throw new Error(
|
|
1403
|
-
'no bundled style sources found in this package; provide --repo <styles-dir> or run from a full source checkout'
|
|
1404
|
-
);
|
|
1405
|
-
}
|
|
1406
1487
|
|
|
1407
1488
|
let copiedCount = 0;
|
|
1408
1489
|
sourceDirs.forEach( ( sourceDir ) => {
|