extract-cite 1.0.5 → 1.0.7
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 +16 -1
- package/dist/extract-cite-full.cjs.js +2 -0
- package/dist/extract-cite-full.cjs.js.map +1 -0
- package/dist/extract-cite-full.d.ts +2 -0
- package/dist/extract-cite-full.es.js +2 -0
- package/dist/extract-cite-full.es.js.map +1 -0
- package/dist/extract-cite-src.cjs.js +2 -0
- package/dist/extract-cite-src.cjs.js.map +1 -0
- package/dist/extract-cite-src.es.js +4 -0
- package/dist/extract-cite-src.es.js.map +1 -0
- package/dist/extract-cite.cjs.js +1 -2
- package/dist/extract-cite.d.ts +2 -0
- package/dist/extract-cite.es.js +1 -4
- package/dist/full.d.ts +1 -0
- package/dist/html-to-cite/human-names-db.d.ts +32 -0
- package/dist/index.d.ts +5 -2
- package/package.json +6 -1
- package/src/full.ts +12 -0
- package/src/html-to-cite/human-names-db.ts +74 -0
- package/src/html-to-cite/human-names-recognize.ts +13 -8
- package/src/index.ts +5 -2
- package/dist/extract-cite.cjs.js.map +0 -1
- package/dist/extract-cite.es.js.map +0 -1
package/dist/full.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './index';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Holder for the optional 92k human-names database.
|
|
3
|
+
*
|
|
4
|
+
* The default `extract-cite` entry ships without the ~1 MB names JSON so it
|
|
5
|
+
* stays slim. The database is used only to tell a person's name from an
|
|
6
|
+
* organization's; without it that check falls back to the word heuristics.
|
|
7
|
+
*
|
|
8
|
+
* Get it one of two ways:
|
|
9
|
+
* - import `extract-cite/full`, which bundles the JSON and registers it, or
|
|
10
|
+
* - call `loadHumanNamesDB()` to lazy-load it from a CDN at runtime.
|
|
11
|
+
*/
|
|
12
|
+
/** Lowercase name → 1 (first name) or 2 (last name). */
|
|
13
|
+
export type HumanNamesDB = Record<string, number>;
|
|
14
|
+
/** Published copy of the names JSON, served by jsDelivr from npm. */
|
|
15
|
+
export declare const HUMAN_NAMES_DB_CDN_URL = "https://cdn.jsdelivr.net/npm/extract-cite/src/html-to-cite/human-names-92k.json";
|
|
16
|
+
/** Registers a names database (or `null` to clear it). */
|
|
17
|
+
export declare function setHumanNamesDB(db: HumanNamesDB | null): void;
|
|
18
|
+
/** The registered names database, or `null` when none is loaded. */
|
|
19
|
+
export declare function getHumanNamesDB(): HumanNamesDB | null;
|
|
20
|
+
export interface LoadHumanNamesDBOptions {
|
|
21
|
+
/** Where to fetch the JSON from. Defaults to {@link HUMAN_NAMES_DB_CDN_URL}. */
|
|
22
|
+
url?: string;
|
|
23
|
+
/** Injectable fetch, for tests and non-browser runtimes. */
|
|
24
|
+
fetch?: typeof fetch;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Lazy-loads the names database from a CDN and registers it. Concurrent and
|
|
28
|
+
* repeat calls share one request; once loaded it resolves immediately.
|
|
29
|
+
* Resolves `null` (and leaves the slim fallback in place) if the fetch fails,
|
|
30
|
+
* so a CDN outage never breaks citation extraction.
|
|
31
|
+
*/
|
|
32
|
+
export declare function loadHumanNamesDB(options?: LoadHumanNamesDBOptions): Promise<HumanNamesDB | null>;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* @fileoverview extract-cite: cite any webpage.
|
|
3
3
|
*
|
|
4
4
|
* - `extractCite` reads author, date, title and source straight off the HTML
|
|
5
|
-
* (meta tags, selectors, JSON-LD, URL
|
|
6
|
-
*
|
|
5
|
+
* (meta tags, selectors, JSON-LD, URL). Instant, offline, partial.
|
|
6
|
+
* - This default entry is slim: the 92k human-names database is not bundled.
|
|
7
|
+
* Lazy-load it from a CDN with `loadHumanNamesDB()`, or import
|
|
8
|
+
* `extract-cite/full`, which bundles it.
|
|
7
9
|
* - `extractCiteLLM` then asks a model (OpenRouter by default) to finish the
|
|
8
10
|
* citation, score every part, flag the doubtful ones and read the authors'
|
|
9
11
|
* qualifications, and writes it as APA, MLA, Chicago, Harvard, IEEE and BibTeX.
|
|
@@ -11,4 +13,5 @@
|
|
|
11
13
|
export * from './html-to-cite/extract-cite';
|
|
12
14
|
export * from './html-to-cite/url-to-domain';
|
|
13
15
|
export { extractHumanName } from './html-to-cite/human-names-recognize';
|
|
16
|
+
export * from './html-to-cite/human-names-db';
|
|
14
17
|
export * from './llm';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extract-cite",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"module": "./dist/extract-cite.es.js",
|
|
5
5
|
"description": "Cite any webpage: regex/metadata extraction of author, date, title and source, plus an optional LLM pass (OpenRouter by default) that completes the APA parts, scores confidence per field, flags fields for review, extracts author qualifications, and formats APA, MLA, Chicago, Harvard, IEEE and BibTeX.",
|
|
6
6
|
"author": "vtempest <grokthiscontact@gmail.com>",
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"import": "./dist/extract-cite.es.js",
|
|
19
19
|
"require": "./dist/extract-cite.cjs.js"
|
|
20
20
|
},
|
|
21
|
+
"./full": {
|
|
22
|
+
"types": "./dist/full.d.ts",
|
|
23
|
+
"import": "./dist/extract-cite-full.es.js",
|
|
24
|
+
"require": "./dist/extract-cite-full.cjs.js"
|
|
25
|
+
},
|
|
21
26
|
"./*": {
|
|
22
27
|
"types": "./src/*.ts",
|
|
23
28
|
"import": "./src/*",
|
package/src/full.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview extract-cite/full: the same API as `extract-cite`, with the
|
|
3
|
+
* 92k human-names database bundled and registered on import, so person vs.
|
|
4
|
+
* organization detection works offline without `loadHumanNamesDB()`.
|
|
5
|
+
* Adds ~1 MB; prefer the default slim entry plus lazy loading in browsers.
|
|
6
|
+
*/
|
|
7
|
+
import dataHumanNames from "./html-to-cite/human-names-92k.json";
|
|
8
|
+
import { setHumanNamesDB } from "./html-to-cite/human-names-db";
|
|
9
|
+
|
|
10
|
+
setHumanNamesDB(dataHumanNames as Record<string, number>);
|
|
11
|
+
|
|
12
|
+
export * from "./index";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Holder for the optional 92k human-names database.
|
|
3
|
+
*
|
|
4
|
+
* The default `extract-cite` entry ships without the ~1 MB names JSON so it
|
|
5
|
+
* stays slim. The database is used only to tell a person's name from an
|
|
6
|
+
* organization's; without it that check falls back to the word heuristics.
|
|
7
|
+
*
|
|
8
|
+
* Get it one of two ways:
|
|
9
|
+
* - import `extract-cite/full`, which bundles the JSON and registers it, or
|
|
10
|
+
* - call `loadHumanNamesDB()` to lazy-load it from a CDN at runtime.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Lowercase name → 1 (first name) or 2 (last name). */
|
|
14
|
+
export type HumanNamesDB = Record<string, number>;
|
|
15
|
+
|
|
16
|
+
/** Published copy of the names JSON, served by jsDelivr from npm. */
|
|
17
|
+
export const HUMAN_NAMES_DB_CDN_URL =
|
|
18
|
+
"https://cdn.jsdelivr.net/npm/extract-cite/src/html-to-cite/human-names-92k.json";
|
|
19
|
+
|
|
20
|
+
let namesDB: HumanNamesDB | null = null;
|
|
21
|
+
let loading: Promise<HumanNamesDB | null> | null = null;
|
|
22
|
+
|
|
23
|
+
/** Registers a names database (or `null` to clear it). */
|
|
24
|
+
export function setHumanNamesDB(db: HumanNamesDB | null): void {
|
|
25
|
+
namesDB = db;
|
|
26
|
+
loading = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The registered names database, or `null` when none is loaded. */
|
|
30
|
+
export function getHumanNamesDB(): HumanNamesDB | null {
|
|
31
|
+
return namesDB;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface LoadHumanNamesDBOptions {
|
|
35
|
+
/** Where to fetch the JSON from. Defaults to {@link HUMAN_NAMES_DB_CDN_URL}. */
|
|
36
|
+
url?: string;
|
|
37
|
+
/** Injectable fetch, for tests and non-browser runtimes. */
|
|
38
|
+
fetch?: typeof fetch;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Lazy-loads the names database from a CDN and registers it. Concurrent and
|
|
43
|
+
* repeat calls share one request; once loaded it resolves immediately.
|
|
44
|
+
* Resolves `null` (and leaves the slim fallback in place) if the fetch fails,
|
|
45
|
+
* so a CDN outage never breaks citation extraction.
|
|
46
|
+
*/
|
|
47
|
+
export function loadHumanNamesDB(
|
|
48
|
+
options: LoadHumanNamesDBOptions = {}
|
|
49
|
+
): Promise<HumanNamesDB | null> {
|
|
50
|
+
if (namesDB) return Promise.resolve(namesDB);
|
|
51
|
+
if (loading) return loading;
|
|
52
|
+
|
|
53
|
+
const { url = HUMAN_NAMES_DB_CDN_URL, fetch: fetchImpl = globalThis.fetch } =
|
|
54
|
+
options;
|
|
55
|
+
|
|
56
|
+
const request: Promise<HumanNamesDB | null> = Promise.resolve()
|
|
57
|
+
.then(() => fetchImpl(url))
|
|
58
|
+
.then((res) => {
|
|
59
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
60
|
+
return res.json();
|
|
61
|
+
})
|
|
62
|
+
.then((db: HumanNamesDB) => {
|
|
63
|
+
if (!db || typeof db !== "object") throw new Error("invalid names JSON");
|
|
64
|
+
namesDB = db;
|
|
65
|
+
return db;
|
|
66
|
+
})
|
|
67
|
+
.catch(() => null)
|
|
68
|
+
.finally(() => {
|
|
69
|
+
// A failed load is not cached, so a later call can retry.
|
|
70
|
+
if (loading === request) loading = null;
|
|
71
|
+
});
|
|
72
|
+
loading = request;
|
|
73
|
+
return request;
|
|
74
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Advanced human name recognition and normalization utility.
|
|
3
|
-
* Distinguishes between person names and organizations using
|
|
3
|
+
* Distinguishes between person names and organizations using word heuristics,
|
|
4
|
+
* plus the 92k-entry name database when one is loaded (see human-names-db.ts).
|
|
4
5
|
*/
|
|
5
|
-
import
|
|
6
|
+
import { getHumanNamesDB } from "./human-names-db";
|
|
6
7
|
|
|
7
8
|
// Common organization terms for detection - extended list from provided code
|
|
8
9
|
const TERMS_ORG =
|
|
@@ -381,13 +382,17 @@ function isOrganization(nameString) {
|
|
|
381
382
|
return true;
|
|
382
383
|
}
|
|
383
384
|
|
|
384
|
-
// Check if the name contains any human name parts according to our database
|
|
385
|
+
// Check if the name contains any human name parts according to our database.
|
|
386
|
+
// The slim build has no database loaded, so this check is skipped there.
|
|
387
|
+
// Database keys are lowercase, and so is every word here.
|
|
388
|
+
const dataHumanNames = getHumanNamesDB();
|
|
385
389
|
let hasHumanNamePart = false;
|
|
386
|
-
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
390
|
+
if (dataHumanNames) {
|
|
391
|
+
for (const word of words) {
|
|
392
|
+
if (dataHumanNames[word] === 1 || dataHumanNames[word] === 2) {
|
|
393
|
+
hasHumanNamePart = true;
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
391
396
|
}
|
|
392
397
|
}
|
|
393
398
|
|
package/src/index.ts
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* @fileoverview extract-cite: cite any webpage.
|
|
3
3
|
*
|
|
4
4
|
* - `extractCite` reads author, date, title and source straight off the HTML
|
|
5
|
-
* (meta tags, selectors, JSON-LD, URL
|
|
6
|
-
*
|
|
5
|
+
* (meta tags, selectors, JSON-LD, URL). Instant, offline, partial.
|
|
6
|
+
* - This default entry is slim: the 92k human-names database is not bundled.
|
|
7
|
+
* Lazy-load it from a CDN with `loadHumanNamesDB()`, or import
|
|
8
|
+
* `extract-cite/full`, which bundles it.
|
|
7
9
|
* - `extractCiteLLM` then asks a model (OpenRouter by default) to finish the
|
|
8
10
|
* citation, score every part, flag the doubtful ones and read the authors'
|
|
9
11
|
* qualifications, and writes it as APA, MLA, Chicago, Harvard, IEEE and BibTeX.
|
|
@@ -11,4 +13,5 @@
|
|
|
11
13
|
export * from "./html-to-cite/extract-cite";
|
|
12
14
|
export * from "./html-to-cite/url-to-domain";
|
|
13
15
|
export { extractHumanName } from "./html-to-cite/human-names-recognize";
|
|
16
|
+
export * from "./html-to-cite/human-names-db";
|
|
14
17
|
export * from "./llm";
|