citeclaw 2.0.7 → 2.0.9
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 +21 -2
- package/package.json +1 -1
- package/scripts/botcite.js +59 -11
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ It is designed for two related jobs:
|
|
|
15
15
|
- an HTTP service compatible with Citoid-style API flows
|
|
16
16
|
- an MCP server mode for agent/tool integrations
|
|
17
17
|
- Zotero automation for query, cite, add, update, notes, dedup, enrichment, and export
|
|
18
|
-
-
|
|
18
|
+
- optional translator/style sync commands for broader coverage and local CSL rendering
|
|
19
19
|
|
|
20
20
|
## Fast Start
|
|
21
21
|
|
|
@@ -120,7 +120,7 @@ Safety defaults:
|
|
|
120
120
|
|
|
121
121
|
## Runtime Sync
|
|
122
122
|
|
|
123
|
-
For npm installs, extra runtime assets can be synced explicitly when you want broader coverage or local style rendering:
|
|
123
|
+
For npm installs, extra runtime assets can be synced explicitly when you want broader translator coverage or local style rendering:
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
126
|
npx citeclaw translators sync
|
|
@@ -131,6 +131,8 @@ Notes:
|
|
|
131
131
|
|
|
132
132
|
- `translators sync` will clone or update the translator sources with `git` when needed
|
|
133
133
|
- `styles sync` will clone or update style repositories with `git` when local CSL styles are unavailable
|
|
134
|
+
- normal `cite` commands can run without manually syncing translators first
|
|
135
|
+
- `cite-style` will fetch style sources on demand if local styles are missing
|
|
134
136
|
- if `git` is not installed, the commands fail with an explicit message
|
|
135
137
|
|
|
136
138
|
## Bibliography Curation
|
|
@@ -163,6 +165,23 @@ Current package metadata and entrypoints live in:
|
|
|
163
165
|
- [package.json](/mnt/e/botcite/package.json)
|
|
164
166
|
- [scripts/citeclaw.js](/mnt/e/botcite/scripts/citeclaw.js)
|
|
165
167
|
|
|
168
|
+
## npm Publishing
|
|
169
|
+
|
|
170
|
+
This repo includes a GitHub Actions workflow for npm publishing:
|
|
171
|
+
|
|
172
|
+
- workflow file: `.github/workflows/npm-publish.yml`
|
|
173
|
+
- trigger: push a tag like `v2.0.8` that matches `package.json`'s `version`
|
|
174
|
+
- required secret: add `NPM_TOKEN` in GitHub repository settings with publish permission for the `citeclaw` package
|
|
175
|
+
|
|
176
|
+
Typical release flow:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
npm version patch
|
|
180
|
+
git push origin master --follow-tags
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The workflow installs dependencies with `npm ci`, checks that the tag matches `package.json`, validates the tarball with `npm pack --dry-run`, and then runs `npm publish --access public --provenance`.
|
|
184
|
+
|
|
166
185
|
## Notes
|
|
167
186
|
|
|
168
187
|
- The npm package name and primary CLI are `citeclaw`.
|
package/package.json
CHANGED
package/scripts/botcite.js
CHANGED
|
@@ -469,6 +469,46 @@ function runCommandOrThrow( command, args, cwd ) {
|
|
|
469
469
|
return result;
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
function styleLocaleUrls( locale ) {
|
|
473
|
+
const fileName = `locales-${ locale }.xml`;
|
|
474
|
+
return [
|
|
475
|
+
`https://raw.githubusercontent.com/citation-style-language/locales/master/${ fileName }`,
|
|
476
|
+
`https://github.com/citation-style-language/locales/raw/master/${ fileName }`,
|
|
477
|
+
`https://cdn.jsdelivr.net/gh/citation-style-language/locales@master/${ fileName }`
|
|
478
|
+
];
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function downloadFileWithCurlFallbacks( urls, dest, label, runner ) {
|
|
482
|
+
const runCommand = runner || runCommandOrThrow;
|
|
483
|
+
const candidates = Array.isArray( urls ) ? urls : [ urls ];
|
|
484
|
+
const targetLabel = label || path.basename( dest );
|
|
485
|
+
const tempDest = `${ dest }.tmp`;
|
|
486
|
+
const failures = [];
|
|
487
|
+
fs.mkdirSync( path.dirname( dest ), { recursive: true } );
|
|
488
|
+
|
|
489
|
+
for ( const url of candidates ) {
|
|
490
|
+
try {
|
|
491
|
+
fs.rmSync( tempDest, { force: true } );
|
|
492
|
+
runCommand( 'curl', [
|
|
493
|
+
'-fsSL',
|
|
494
|
+
'--retry', '3',
|
|
495
|
+
'--retry-delay', '1',
|
|
496
|
+
'--retry-all-errors',
|
|
497
|
+
url,
|
|
498
|
+
'-o', tempDest
|
|
499
|
+
] );
|
|
500
|
+
fs.rmSync( dest, { force: true } );
|
|
501
|
+
fs.renameSync( tempDest, dest );
|
|
502
|
+
return;
|
|
503
|
+
} catch ( error ) {
|
|
504
|
+
failures.push( `${ url }: ${ error.message }` );
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
fs.rmSync( tempDest, { force: true } );
|
|
509
|
+
throw new Error( `failed to download ${ targetLabel }: ${ failures.join( ' | ' ) }` );
|
|
510
|
+
}
|
|
511
|
+
|
|
472
512
|
function resolveInstallCommand() {
|
|
473
513
|
if ( commandExists( 'npm' ) ) {
|
|
474
514
|
return { command: 'npm', args: [ 'install' ] };
|
|
@@ -1504,19 +1544,24 @@ async function runCitationFromPdf( pdfPath, options ) {
|
|
|
1504
1544
|
} );
|
|
1505
1545
|
}
|
|
1506
1546
|
|
|
1507
|
-
function syncStyles( options ) {
|
|
1547
|
+
function syncStyles( options, dependencies ) {
|
|
1548
|
+
const styleOptions = options || {};
|
|
1549
|
+
const hooks = dependencies || {};
|
|
1550
|
+
const downloadFile = hooks.downloadFile || downloadFileWithCurlFallbacks;
|
|
1551
|
+
const downloadUsesCurl = downloadFile === downloadFileWithCurlFallbacks;
|
|
1552
|
+
|
|
1508
1553
|
ensureDirs();
|
|
1509
1554
|
fs.mkdirSync( cslDir, { recursive: true } );
|
|
1510
1555
|
fs.mkdirSync( localeDir, { recursive: true } );
|
|
1511
|
-
const configuredSourceDirs =
|
|
1556
|
+
const configuredSourceDirs = styleOptions.repo ?
|
|
1512
1557
|
[
|
|
1513
|
-
path.isAbsolute(
|
|
1514
|
-
|
|
1515
|
-
path.join( rootDir,
|
|
1558
|
+
path.isAbsolute( styleOptions.repo || '' ) ?
|
|
1559
|
+
styleOptions.repo :
|
|
1560
|
+
path.join( rootDir, styleOptions.repo || 'vendor/styles' )
|
|
1516
1561
|
] :
|
|
1517
1562
|
ensureDefaultStyleSources();
|
|
1518
1563
|
const sourceDirs = configuredSourceDirs.filter( ( sourceDir ) => fileExists( sourceDir ) );
|
|
1519
|
-
if (
|
|
1564
|
+
if ( styleOptions.repo && !sourceDirs.length ) {
|
|
1520
1565
|
throw new Error( `styles source not found: ${ configuredSourceDirs.join( ', ' ) }` );
|
|
1521
1566
|
}
|
|
1522
1567
|
|
|
@@ -1532,13 +1577,12 @@ function syncStyles( options ) {
|
|
|
1532
1577
|
} );
|
|
1533
1578
|
|
|
1534
1579
|
const localeTargets = [ 'en-US', 'zh-CN' ];
|
|
1535
|
-
if ( !commandExists( 'curl' ) ) {
|
|
1580
|
+
if ( downloadUsesCurl && !commandExists( 'curl' ) ) {
|
|
1536
1581
|
throw new Error( 'curl is required for styles sync' );
|
|
1537
1582
|
}
|
|
1538
1583
|
for ( const locale of localeTargets ) {
|
|
1539
|
-
const localeUrl = `https://raw.githubusercontent.com/citation-style-language/locales/master/locales-${ locale }.xml`;
|
|
1540
1584
|
const dest = path.join( localeDir, `locales-${ locale }.xml` );
|
|
1541
|
-
|
|
1585
|
+
downloadFile( styleLocaleUrls( locale ), dest, `locale ${ locale }` );
|
|
1542
1586
|
}
|
|
1543
1587
|
|
|
1544
1588
|
process.stdout.write( `styles synced to ${ cslDir } from ${ sourceDirs.join( ', ' ) } (copied ${ copiedCount } files)\n` );
|
|
@@ -4979,9 +5023,11 @@ function main() {
|
|
|
4979
5023
|
usage();
|
|
4980
5024
|
process.exit( 1 );
|
|
4981
5025
|
}
|
|
4982
|
-
|
|
5026
|
+
try {
|
|
5027
|
+
syncStyles( parsed );
|
|
5028
|
+
} catch ( error ) {
|
|
4983
5029
|
handleCommandError( error, parsed, 'styles', 'sync' );
|
|
4984
|
-
}
|
|
5030
|
+
}
|
|
4985
5031
|
return;
|
|
4986
5032
|
}
|
|
4987
5033
|
|
|
@@ -5140,12 +5186,14 @@ function main() {
|
|
|
5140
5186
|
}
|
|
5141
5187
|
|
|
5142
5188
|
module.exports = {
|
|
5189
|
+
downloadFileWithCurlFallbacks,
|
|
5143
5190
|
detectPdfIdentifierCandidates,
|
|
5144
5191
|
extractBestDoiCandidate,
|
|
5145
5192
|
extractPdfCandidates,
|
|
5146
5193
|
main,
|
|
5147
5194
|
normalizeArxivId,
|
|
5148
5195
|
normalizeDoi,
|
|
5196
|
+
syncStyles,
|
|
5149
5197
|
shouldAttemptPdfOcr
|
|
5150
5198
|
};
|
|
5151
5199
|
|