refkit-js 0.0.0 → 0.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/LICENSE +187 -187
- package/README.md +71 -2
- package/dist/build.json +4 -0
- package/dist/citation.d.ts +27 -0
- package/dist/citation.js +70 -0
- package/dist/document.d.ts +38 -0
- package/dist/document.js +110 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.js +73 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +8 -0
- package/dist/inputs.d.ts +5 -0
- package/dist/inputs.js +34 -0
- package/dist/library.d.ts +26 -0
- package/dist/library.js +69 -0
- package/dist/node.d.ts +14 -0
- package/dist/node.js +89 -0
- package/dist/raw.d.ts +59 -0
- package/dist/raw.js +191 -0
- package/dist/runtime.d.ts +14 -0
- package/dist/runtime.js +58 -0
- package/dist/tidy.d.ts +5 -0
- package/dist/tidy.js +31 -0
- package/dist/types.d.ts +182 -0
- package/dist/types.js +1 -0
- package/dist/wasm/refkit_js_native.d.ts +142 -0
- package/dist/wasm/refkit_js_native.js +1184 -0
- package/dist/wasm/refkit_js_native_bg.wasm +0 -0
- package/dist/wasm/refkit_js_native_bg.wasm.d.ts +49 -0
- package/dist/wasm/version.d.ts +1 -0
- package/dist/wasm/version.js +1 -0
- package/package.json +60 -8
package/dist/document.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { NativeDocument, NativeStyle, is_bundled_locale, } from "./wasm/refkit_js_native.js";
|
|
2
|
+
import { assertInitialized } from "./runtime.js";
|
|
3
|
+
import { callNative, readNative, MissingReferenceError } from "./errors.js";
|
|
4
|
+
import { object, string } from "./inputs.js";
|
|
5
|
+
import { Library, nativeLibrary } from "./library.js";
|
|
6
|
+
import { Citation, citationsJson } from "./citation.js";
|
|
7
|
+
const styles = new WeakMap();
|
|
8
|
+
const styleSources = new WeakMap();
|
|
9
|
+
export function setStyleSource(style, source) {
|
|
10
|
+
styleSources.set(style, source);
|
|
11
|
+
}
|
|
12
|
+
function nativeStyle(style) {
|
|
13
|
+
const native = styles.get(style);
|
|
14
|
+
if (!native)
|
|
15
|
+
throw new TypeError("style must be a Style");
|
|
16
|
+
return native;
|
|
17
|
+
}
|
|
18
|
+
export class Style {
|
|
19
|
+
constructor(native) {
|
|
20
|
+
styles.set(this, native);
|
|
21
|
+
}
|
|
22
|
+
static load(name) {
|
|
23
|
+
assertInitialized();
|
|
24
|
+
return new Style(callNative(() => NativeStyle.load(string(name, "name"))));
|
|
25
|
+
}
|
|
26
|
+
static fromXml(xml) {
|
|
27
|
+
assertInitialized();
|
|
28
|
+
return new Style(callNative(() => NativeStyle.from_xml(string(xml, "xml"))));
|
|
29
|
+
}
|
|
30
|
+
get id() {
|
|
31
|
+
const id = callNative(() => nativeStyle(this).id);
|
|
32
|
+
return styleSources.get(this) ?? id;
|
|
33
|
+
}
|
|
34
|
+
get title() {
|
|
35
|
+
return callNative(() => nativeStyle(this).title);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class Locale {
|
|
39
|
+
code;
|
|
40
|
+
constructor(code) {
|
|
41
|
+
this.code = code;
|
|
42
|
+
Object.freeze(this);
|
|
43
|
+
}
|
|
44
|
+
static load(code) {
|
|
45
|
+
assertInitialized();
|
|
46
|
+
string(code, "code");
|
|
47
|
+
if (!callNative(() => is_bundled_locale(code)))
|
|
48
|
+
throw new RangeError(`unknown bundled locale ${JSON.stringify(code)}`);
|
|
49
|
+
return new Locale(code);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let renderedDocument;
|
|
53
|
+
export class RenderedDocument {
|
|
54
|
+
citationOrder;
|
|
55
|
+
citations;
|
|
56
|
+
bibliography;
|
|
57
|
+
constructor(data) {
|
|
58
|
+
this.citationOrder = Object.freeze(data.citationOrder);
|
|
59
|
+
this.citations = Object.freeze(data.citations);
|
|
60
|
+
this.bibliography = data.bibliography;
|
|
61
|
+
Object.freeze(this);
|
|
62
|
+
}
|
|
63
|
+
static {
|
|
64
|
+
renderedDocument = (data) => new RenderedDocument(data);
|
|
65
|
+
}
|
|
66
|
+
get(id) {
|
|
67
|
+
string(id, "id");
|
|
68
|
+
if (!Object.hasOwn(this.citations, id))
|
|
69
|
+
throw new MissingReferenceError(`unknown citation id ${JSON.stringify(id)}`);
|
|
70
|
+
return this.citations[id];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export class Document {
|
|
74
|
+
#native;
|
|
75
|
+
constructor(library, style, options = {}) {
|
|
76
|
+
assertInitialized();
|
|
77
|
+
object(options, "options", ["locale"]);
|
|
78
|
+
const locale = options.locale instanceof Locale ? options.locale.code : options.locale;
|
|
79
|
+
if (locale != null)
|
|
80
|
+
string(locale, "locale");
|
|
81
|
+
this.#native = callNative(() => new NativeDocument(nativeLibrary(library), nativeStyle(style), locale ?? undefined));
|
|
82
|
+
}
|
|
83
|
+
render(citations) {
|
|
84
|
+
const input = citationsJson(citations);
|
|
85
|
+
return renderedDocument(readNative(() => this.#native.render(input)));
|
|
86
|
+
}
|
|
87
|
+
citedBibliography(citations) {
|
|
88
|
+
const input = citationsJson(citations);
|
|
89
|
+
return readNative(() => this.#native.cited_bibliography(input));
|
|
90
|
+
}
|
|
91
|
+
fullBibliography() {
|
|
92
|
+
return readNative(() => this.#native.full_bibliography());
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function withDocument(library, options, render) {
|
|
96
|
+
object(options, "options", ["style", "locale"]);
|
|
97
|
+
const style = options.style instanceof Style
|
|
98
|
+
? options.style
|
|
99
|
+
: Style.load(options.style === undefined ? "apa" : options.style);
|
|
100
|
+
const document = new Document(library, style, {
|
|
101
|
+
locale: options.locale === undefined ? "en-US" : options.locale,
|
|
102
|
+
});
|
|
103
|
+
return render(document);
|
|
104
|
+
}
|
|
105
|
+
export function cite(library, citation, options = {}) {
|
|
106
|
+
return withDocument(library, options, (document) => document.render([new Citation("citation", citation)]).get("citation"));
|
|
107
|
+
}
|
|
108
|
+
export function fullBibliography(library, options = {}) {
|
|
109
|
+
return withDocument(library, options, (document) => document.fullBibliography());
|
|
110
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Diagnostic } from "./types.js";
|
|
2
|
+
export declare class RefkitError extends Error {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class ParseError extends RefkitError {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
8
|
+
constructor(message: string, diagnostics?: readonly Diagnostic[]);
|
|
9
|
+
}
|
|
10
|
+
export declare class MissingReferenceError extends RefkitError {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class TidyError extends RefkitError {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class TidySyntaxError extends TidyError {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly line: number;
|
|
19
|
+
readonly column: number;
|
|
20
|
+
readonly byte: number;
|
|
21
|
+
readonly character: string | null;
|
|
22
|
+
constructor(message: string, syntax: {
|
|
23
|
+
line: number;
|
|
24
|
+
column: number;
|
|
25
|
+
byte: number;
|
|
26
|
+
character: string | null;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export declare function callNative<T>(operation: () => T): T;
|
|
30
|
+
export declare function readNative<T>(operation: () => string): T;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export class RefkitError extends Error {
|
|
2
|
+
name = "RefkitError";
|
|
3
|
+
}
|
|
4
|
+
export class ParseError extends RefkitError {
|
|
5
|
+
name = "ParseError";
|
|
6
|
+
diagnostics;
|
|
7
|
+
constructor(message, diagnostics = []) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.diagnostics = diagnostics;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class MissingReferenceError extends RefkitError {
|
|
13
|
+
name = "MissingReferenceError";
|
|
14
|
+
}
|
|
15
|
+
export class TidyError extends RefkitError {
|
|
16
|
+
name = "TidyError";
|
|
17
|
+
}
|
|
18
|
+
export class TidySyntaxError extends TidyError {
|
|
19
|
+
name = "TidySyntaxError";
|
|
20
|
+
line;
|
|
21
|
+
column;
|
|
22
|
+
byte;
|
|
23
|
+
character;
|
|
24
|
+
constructor(message, syntax) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.line = syntax.line;
|
|
27
|
+
this.column = syntax.column;
|
|
28
|
+
this.byte = syntax.byte;
|
|
29
|
+
this.character = syntax.character;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function convertError(error) {
|
|
33
|
+
if (error instanceof Error)
|
|
34
|
+
return error;
|
|
35
|
+
let value;
|
|
36
|
+
try {
|
|
37
|
+
value = JSON.parse(String(error));
|
|
38
|
+
if (typeof value?.message !== "string")
|
|
39
|
+
return new RefkitError(String(error));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return new RefkitError(String(error));
|
|
43
|
+
}
|
|
44
|
+
switch (value.name) {
|
|
45
|
+
case "ParseError":
|
|
46
|
+
return new ParseError(value.message, value.diagnostics);
|
|
47
|
+
case "MissingReferenceError":
|
|
48
|
+
return new MissingReferenceError(value.message);
|
|
49
|
+
case "TidySyntaxError":
|
|
50
|
+
if (value.syntax)
|
|
51
|
+
return new TidySyntaxError(value.message, value.syntax);
|
|
52
|
+
return new TidyError(value.message);
|
|
53
|
+
case "TidyError":
|
|
54
|
+
return new TidyError(value.message);
|
|
55
|
+
case "TypeError":
|
|
56
|
+
return new TypeError(value.message);
|
|
57
|
+
case "RangeError":
|
|
58
|
+
return new RangeError(value.message);
|
|
59
|
+
default:
|
|
60
|
+
return new RefkitError(value.message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function callNative(operation) {
|
|
64
|
+
try {
|
|
65
|
+
return operation();
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw convertError(error);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function readNative(operation) {
|
|
72
|
+
return JSON.parse(callNative(operation));
|
|
73
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { init, getBuildInfo, type BuildInfo, type InitOptions, } from "./runtime.js";
|
|
2
|
+
export { version } from "./wasm/version.js";
|
|
3
|
+
export { RefkitError, ParseError, MissingReferenceError, TidyError, TidySyntaxError, } from "./errors.js";
|
|
4
|
+
export { Library, type ParseOptions, type ProjectOptions } from "./library.js";
|
|
5
|
+
export { Cite, CitationGroup, Citation, type CiteOptions, type CitationOptions, type CitationInput, } from "./citation.js";
|
|
6
|
+
export { Style, Locale, Document, RenderedDocument, cite, fullBibliography, type DocumentOptions, type RenderOptions, } from "./document.js";
|
|
7
|
+
export { BibDocument, BibEntryMap, BibEntry, BibFieldMap, BibField, } from "./raw.js";
|
|
8
|
+
export { tidyBibtex, type TidySettings } from "./tidy.js";
|
|
9
|
+
export type * from "./types.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { init, getBuildInfo, } from "./runtime.js";
|
|
2
|
+
export { version } from "./wasm/version.js";
|
|
3
|
+
export { RefkitError, ParseError, MissingReferenceError, TidyError, TidySyntaxError, } from "./errors.js";
|
|
4
|
+
export { Library } from "./library.js";
|
|
5
|
+
export { Cite, CitationGroup, Citation, } from "./citation.js";
|
|
6
|
+
export { Style, Locale, Document, RenderedDocument, cite, fullBibliography, } from "./document.js";
|
|
7
|
+
export { BibDocument, BibEntryMap, BibEntry, BibFieldMap, BibField, } from "./raw.js";
|
|
8
|
+
export { tidyBibtex } from "./tidy.js";
|
package/dist/inputs.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function string(value: unknown, name: string): string;
|
|
2
|
+
export declare function optionalString(value: unknown, name: string): string | null;
|
|
3
|
+
export declare function iterable<T>(value: Iterable<T>, name: string): T[];
|
|
4
|
+
export declare function strings(value: Iterable<string>, name: string): string[];
|
|
5
|
+
export declare function object(value: unknown, name: string, allowed?: readonly string[]): void;
|
package/dist/inputs.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function string(value, name) {
|
|
2
|
+
if (typeof value !== "string")
|
|
3
|
+
throw new TypeError(`${name} must be a string`);
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
export function optionalString(value, name) {
|
|
7
|
+
return value == null ? null : string(value, name);
|
|
8
|
+
}
|
|
9
|
+
export function iterable(value, name) {
|
|
10
|
+
if (typeof value === "string" ||
|
|
11
|
+
value == null ||
|
|
12
|
+
typeof value[Symbol.iterator] !== "function") {
|
|
13
|
+
throw new TypeError(`${name} must be an iterable of items`);
|
|
14
|
+
}
|
|
15
|
+
return Array.from(value);
|
|
16
|
+
}
|
|
17
|
+
export function strings(value, name) {
|
|
18
|
+
return iterable(value, name).map((item) => string(item, name));
|
|
19
|
+
}
|
|
20
|
+
export function object(value, name, allowed) {
|
|
21
|
+
if (value == null ||
|
|
22
|
+
typeof value !== "object" ||
|
|
23
|
+
Array.isArray(value) ||
|
|
24
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
|
|
25
|
+
throw new TypeError(`${name} must be an options object`);
|
|
26
|
+
}
|
|
27
|
+
if (allowed) {
|
|
28
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
29
|
+
if (typeof key !== "string" || !allowed.includes(key)) {
|
|
30
|
+
throw new TypeError(`unknown ${name} field ${String(key)}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { NativeLibrary } from "./wasm/refkit_js_native.js";
|
|
2
|
+
import type { Diagnostic, Entry, ProjectionField, ProjectionRow, RecoveryPolicy } from "./types.js";
|
|
3
|
+
export interface ParseOptions {
|
|
4
|
+
recovery?: RecoveryPolicy;
|
|
5
|
+
}
|
|
6
|
+
export interface ProjectOptions {
|
|
7
|
+
keys?: Iterable<string> | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function nativeLibrary(library: Library): NativeLibrary;
|
|
10
|
+
export declare function setLibraryDecodingDiagnostic(library: Library, diagnostic: Diagnostic | null): void;
|
|
11
|
+
export declare class Library implements Iterable<Entry> {
|
|
12
|
+
private constructor();
|
|
13
|
+
static parseBibtex(source: string, options?: ParseOptions): Library;
|
|
14
|
+
static parseYaml(source: string): Library;
|
|
15
|
+
get diagnostics(): readonly Diagnostic[];
|
|
16
|
+
get size(): number;
|
|
17
|
+
keys(): string[];
|
|
18
|
+
values(): Entry[];
|
|
19
|
+
get(key: string): Entry | null;
|
|
20
|
+
getMany(keys: Iterable<string>): Entry[];
|
|
21
|
+
has(key: string): boolean;
|
|
22
|
+
isEmpty(): boolean;
|
|
23
|
+
select(selector: string): Entry[];
|
|
24
|
+
project(fields?: Iterable<ProjectionField> | null, options?: ProjectOptions): ProjectionRow[];
|
|
25
|
+
[Symbol.iterator](): Iterator<Entry>;
|
|
26
|
+
}
|
package/dist/library.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { NativeLibrary } from "./wasm/refkit_js_native.js";
|
|
2
|
+
import { assertInitialized } from "./runtime.js";
|
|
3
|
+
import { callNative, readNative } from "./errors.js";
|
|
4
|
+
import { object, string, strings } from "./inputs.js";
|
|
5
|
+
const libraries = new WeakMap();
|
|
6
|
+
const sourceDiagnostics = new WeakMap();
|
|
7
|
+
export function nativeLibrary(library) {
|
|
8
|
+
const native = libraries.get(library);
|
|
9
|
+
if (!native)
|
|
10
|
+
throw new TypeError("library must be a Library");
|
|
11
|
+
return native;
|
|
12
|
+
}
|
|
13
|
+
export function setLibraryDecodingDiagnostic(library, diagnostic) {
|
|
14
|
+
sourceDiagnostics.set(library, diagnostic ? [diagnostic] : []);
|
|
15
|
+
}
|
|
16
|
+
export class Library {
|
|
17
|
+
constructor(native) {
|
|
18
|
+
libraries.set(this, native);
|
|
19
|
+
}
|
|
20
|
+
static parseBibtex(source, options = {}) {
|
|
21
|
+
assertInitialized();
|
|
22
|
+
object(options, "options", ["recovery"]);
|
|
23
|
+
return new Library(callNative(() => NativeLibrary.parse_bibtex(string(source, "source"), string(options.recovery === undefined ? "error" : options.recovery, "recovery"))));
|
|
24
|
+
}
|
|
25
|
+
static parseYaml(source) {
|
|
26
|
+
assertInitialized();
|
|
27
|
+
return new Library(callNative(() => NativeLibrary.parse_yaml(string(source, "source"))));
|
|
28
|
+
}
|
|
29
|
+
get diagnostics() {
|
|
30
|
+
return [
|
|
31
|
+
...structuredClone(sourceDiagnostics.get(this) ?? []),
|
|
32
|
+
...readNative(() => nativeLibrary(this).diagnostics()),
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
get size() {
|
|
36
|
+
return callNative(() => nativeLibrary(this).size);
|
|
37
|
+
}
|
|
38
|
+
keys() {
|
|
39
|
+
return readNative(() => nativeLibrary(this).keys());
|
|
40
|
+
}
|
|
41
|
+
values() {
|
|
42
|
+
return readNative(() => nativeLibrary(this).records());
|
|
43
|
+
}
|
|
44
|
+
get(key) {
|
|
45
|
+
return readNative(() => nativeLibrary(this).get_record(string(key, "key")));
|
|
46
|
+
}
|
|
47
|
+
getMany(keys) {
|
|
48
|
+
const input = JSON.stringify(strings(keys, "keys"));
|
|
49
|
+
return readNative(() => nativeLibrary(this).get_many(input));
|
|
50
|
+
}
|
|
51
|
+
has(key) {
|
|
52
|
+
return this.get(key) !== null;
|
|
53
|
+
}
|
|
54
|
+
isEmpty() {
|
|
55
|
+
return this.size === 0;
|
|
56
|
+
}
|
|
57
|
+
select(selector) {
|
|
58
|
+
return readNative(() => nativeLibrary(this).select_records(string(selector, "selector")));
|
|
59
|
+
}
|
|
60
|
+
project(fields, options = {}) {
|
|
61
|
+
object(options, "options", ["keys"]);
|
|
62
|
+
const fieldsJson = JSON.stringify(fields == null ? null : strings(fields, "fields"));
|
|
63
|
+
const keysJson = JSON.stringify(options.keys == null ? null : strings(options.keys, "keys"));
|
|
64
|
+
return readNative(() => nativeLibrary(this).project(fieldsJson, keysJson));
|
|
65
|
+
}
|
|
66
|
+
[Symbol.iterator]() {
|
|
67
|
+
return this.values()[Symbol.iterator]();
|
|
68
|
+
}
|
|
69
|
+
}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Library, type ParseOptions } from "./library.js";
|
|
2
|
+
import { Style } from "./document.js";
|
|
3
|
+
import { BibDocument } from "./raw.js";
|
|
4
|
+
import type { TidySettings } from "./tidy.js";
|
|
5
|
+
import type { TidyResult } from "./types.js";
|
|
6
|
+
export * from "./index.js";
|
|
7
|
+
export type FilePath = string | URL;
|
|
8
|
+
export interface TidyFileSettings extends TidySettings {
|
|
9
|
+
output?: FilePath | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function readLibrary(path: FilePath, options?: ParseOptions): Promise<Library>;
|
|
12
|
+
export declare function readBibDocument(path: FilePath): Promise<BibDocument>;
|
|
13
|
+
export declare function readStyle(path: FilePath): Promise<Style>;
|
|
14
|
+
export declare function tidyFile(path: FilePath, settings?: TidyFileSettings): Promise<TidyResult>;
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { extname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { decode_bibliography } from "./wasm/refkit_js_native.js";
|
|
6
|
+
import { initializeSync } from "./runtime.js";
|
|
7
|
+
import { readNative, RefkitError } from "./errors.js";
|
|
8
|
+
import { object, string } from "./inputs.js";
|
|
9
|
+
import { Library, setLibraryDecodingDiagnostic, } from "./library.js";
|
|
10
|
+
import { Style, setStyleSource } from "./document.js";
|
|
11
|
+
import { BibDocument, setBibDecodingDiagnostic } from "./raw.js";
|
|
12
|
+
initializeSync(readFileSync(new URL("./wasm/refkit_js_native_bg.wasm", import.meta.url)));
|
|
13
|
+
export * from "./index.js";
|
|
14
|
+
function filePath(path) {
|
|
15
|
+
if (path instanceof URL)
|
|
16
|
+
return fileURLToPath(path);
|
|
17
|
+
if (typeof path !== "string")
|
|
18
|
+
throw new TypeError("path must be a string or file URL");
|
|
19
|
+
return path;
|
|
20
|
+
}
|
|
21
|
+
async function readBytes(path) {
|
|
22
|
+
const name = filePath(path);
|
|
23
|
+
try {
|
|
24
|
+
return await readFile(name);
|
|
25
|
+
}
|
|
26
|
+
catch (cause) {
|
|
27
|
+
throw new RefkitError(`failed to read ${name}: ${String(cause)}`, {
|
|
28
|
+
cause,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function readBibliography(path) {
|
|
33
|
+
const bytes = await readBytes(path);
|
|
34
|
+
return readNative(() => decode_bibliography(bytes));
|
|
35
|
+
}
|
|
36
|
+
export async function readLibrary(path, options = {}) {
|
|
37
|
+
object(options, "options", ["recovery"]);
|
|
38
|
+
const recovery = string(options.recovery === undefined ? "error" : options.recovery, "recovery");
|
|
39
|
+
if (recovery !== "error" && recovery !== "report")
|
|
40
|
+
throw new RangeError("recovery must be 'error' or 'report'");
|
|
41
|
+
const extension = extname(filePath(path)).toLowerCase();
|
|
42
|
+
if (![".bib", ".yaml", ".yml"].includes(extension)) {
|
|
43
|
+
throw new RefkitError(extension
|
|
44
|
+
? `unsupported bibliography extension ${JSON.stringify(extension.slice(1))}`
|
|
45
|
+
: "bibliography path has no extension");
|
|
46
|
+
}
|
|
47
|
+
const source = await readBibliography(path);
|
|
48
|
+
const library = extension === ".bib"
|
|
49
|
+
? Library.parseBibtex(source.text, { recovery })
|
|
50
|
+
: Library.parseYaml(source.text);
|
|
51
|
+
setLibraryDecodingDiagnostic(library, source.diagnostic);
|
|
52
|
+
return library;
|
|
53
|
+
}
|
|
54
|
+
export async function readBibDocument(path) {
|
|
55
|
+
const source = await readBibliography(path);
|
|
56
|
+
const document = BibDocument.parse(source.text);
|
|
57
|
+
setBibDecodingDiagnostic(document, source.diagnostic);
|
|
58
|
+
return document;
|
|
59
|
+
}
|
|
60
|
+
export async function readStyle(path) {
|
|
61
|
+
const bytes = await readBytes(path);
|
|
62
|
+
let xml;
|
|
63
|
+
try {
|
|
64
|
+
xml = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
65
|
+
}
|
|
66
|
+
catch (cause) {
|
|
67
|
+
throw new RefkitError(`failed to read style ${filePath(path)} as UTF-8`, {
|
|
68
|
+
cause,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const style = Style.fromXml(xml);
|
|
72
|
+
setStyleSource(style, filePath(path));
|
|
73
|
+
return style;
|
|
74
|
+
}
|
|
75
|
+
export async function tidyFile(path, settings = {}) {
|
|
76
|
+
object(settings, "settings", ["options", "output"]);
|
|
77
|
+
const output = settings.output == null ? null : filePath(settings.output);
|
|
78
|
+
const document = await readBibDocument(path);
|
|
79
|
+
const result = document.tidy({ options: settings.options ?? null });
|
|
80
|
+
if (output !== null) {
|
|
81
|
+
try {
|
|
82
|
+
await writeFile(output, result.bibtex, "utf8");
|
|
83
|
+
}
|
|
84
|
+
catch (cause) {
|
|
85
|
+
throw new RefkitError(`failed to write BibTeX ${output}: ${String(cause)}`, { cause });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
package/dist/raw.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type TidySettings } from "./tidy.js";
|
|
2
|
+
import type { Diagnostic, RawBlock, RawFailedBlock, RawSpan, TidyResult } from "./types.js";
|
|
3
|
+
export declare function setBibDecodingDiagnostic(document: BibDocument, diagnostic: Diagnostic | null): void;
|
|
4
|
+
export declare class BibDocument {
|
|
5
|
+
#private;
|
|
6
|
+
private constructor();
|
|
7
|
+
static parse(source: string): BibDocument;
|
|
8
|
+
get entries(): BibEntryMap;
|
|
9
|
+
get diagnostics(): readonly Diagnostic[];
|
|
10
|
+
get comments(): string[];
|
|
11
|
+
get preamble(): string;
|
|
12
|
+
get strings(): Record<string, string>;
|
|
13
|
+
get failedBlocks(): RawFailedBlock[];
|
|
14
|
+
get blocks(): RawBlock[];
|
|
15
|
+
toBibtex(): string;
|
|
16
|
+
tidy(settings?: TidySettings): TidyResult;
|
|
17
|
+
}
|
|
18
|
+
export declare class BibEntryMap implements Iterable<BibEntry> {
|
|
19
|
+
#private;
|
|
20
|
+
private constructor();
|
|
21
|
+
uniqueKeys(): string[];
|
|
22
|
+
occurrenceKeys(): string[];
|
|
23
|
+
occurrences(): BibEntry[];
|
|
24
|
+
getAll(key: string): BibEntry[];
|
|
25
|
+
getUnique(key: string): BibEntry | null;
|
|
26
|
+
get size(): number;
|
|
27
|
+
isEmpty(): boolean;
|
|
28
|
+
has(key: string): boolean;
|
|
29
|
+
[Symbol.iterator](): Iterator<BibEntry>;
|
|
30
|
+
}
|
|
31
|
+
export declare class BibEntry {
|
|
32
|
+
#private;
|
|
33
|
+
private constructor();
|
|
34
|
+
get key(): string;
|
|
35
|
+
get kind(): string;
|
|
36
|
+
get span(): RawSpan;
|
|
37
|
+
get fields(): BibFieldMap;
|
|
38
|
+
}
|
|
39
|
+
export declare class BibFieldMap implements Iterable<BibField> {
|
|
40
|
+
#private;
|
|
41
|
+
private constructor();
|
|
42
|
+
uniqueKeys(): string[];
|
|
43
|
+
occurrenceKeys(): string[];
|
|
44
|
+
occurrences(): BibField[];
|
|
45
|
+
getAll(key: string): BibField[];
|
|
46
|
+
getUnique(key: string): BibField | null;
|
|
47
|
+
get size(): number;
|
|
48
|
+
isEmpty(): boolean;
|
|
49
|
+
has(key: string): boolean;
|
|
50
|
+
[Symbol.iterator](): Iterator<BibField>;
|
|
51
|
+
}
|
|
52
|
+
export declare class BibField {
|
|
53
|
+
#private;
|
|
54
|
+
private constructor();
|
|
55
|
+
get name(): string;
|
|
56
|
+
get span(): RawSpan;
|
|
57
|
+
get value(): string;
|
|
58
|
+
set value(value: string);
|
|
59
|
+
}
|