@retorquere/bibtex-parser 11.0.0 → 12.0.0

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.
@@ -0,0 +1,122 @@
1
+ import type { InitInput, InitOutput, SyncInitInput } from './bibtex_parser.js'
2
+
3
+ export type { InitInput, InitOutput, SyncInitInput }
4
+ export { initSync } from './bibtex_parser.js'
5
+ export { default as init } from './bibtex_parser.js'
6
+ export { default } from './bibtex_parser.js'
7
+
8
+ export type ParseMode = 'creatorlist' | 'title' | 'verbatim' | 'richtext' | 'literallist' | 'literal' | 'verbatimlist'
9
+
10
+ export interface Creator {
11
+ name?: string
12
+ lastName?: string
13
+ firstName?: string
14
+ prefix?: string
15
+ suffix?: string
16
+ initial?: string
17
+ useprefix?: boolean
18
+ juniorcomma?: boolean
19
+ }
20
+
21
+ export type FieldValue = string | string[] | Creator[]
22
+
23
+ export interface Entry {
24
+ type: string
25
+ key: string
26
+ fields: Record<string, FieldValue>
27
+ mode: Record<string, ParseMode>
28
+ crossref?: Record<string, { parent: string; field: string }>
29
+ input: string
30
+ }
31
+
32
+ export interface ParseError {
33
+ error: string
34
+ input?: string
35
+ }
36
+
37
+ export interface JabRefGroup {
38
+ name: string
39
+ entries: string[]
40
+ groups: JabRefGroup[]
41
+ }
42
+
43
+ export interface JabRefMetadata {
44
+ root: JabRefGroup[]
45
+ groups: Record<string, JabRefGroup>
46
+ fileDirectory?: string
47
+ groupsversion?: number
48
+ databaseType?: string
49
+ }
50
+
51
+ export interface Library {
52
+ errors: ParseError[]
53
+ entries: Entry[]
54
+ comments: string[]
55
+ strings: Record<string, string>
56
+ preamble: string[]
57
+ jabref: JabRefMetadata
58
+ }
59
+
60
+ export interface SentenceCaseOptions {
61
+ guess?: boolean
62
+ subSentence?: boolean
63
+ preserveQuoted?: boolean
64
+ }
65
+
66
+ export interface Token {
67
+ type: 'word' | 'domain' | 'whitespace' | 'number' | 'email' | 'handle' | 'website' | 'markup' | 'other' | 'punctuation'
68
+ subtype: '' | 'preposition' | 'acronym' | 'contraction' | 'ordinal' | 'word' | 'end' | 'colon' | 'ellipsis'
69
+ text: string
70
+ start: number
71
+ end: number
72
+ shape: string
73
+ sentenceStart: boolean
74
+ subSentenceStart: boolean
75
+ hyphenated?: Token[]
76
+ }
77
+
78
+ export interface Options {
79
+ english?: string[] | boolean
80
+ languageAsLangid?: boolean
81
+ sentenceCase?: false | SentenceCaseOptions
82
+ caseProtection?: 'as-needed' | 'strict' | boolean
83
+ unsupported?: 'ignore' | 'keep' | 'throw'
84
+ verbatimFields?: (string | RegExp)[]
85
+ removeOuterBraces?: string[]
86
+ fieldMode?: Record<string, ParseMode>
87
+ raw?: boolean
88
+ strings?: Record<string, string> | string
89
+ applyCrossRef?: boolean
90
+ }
91
+
92
+ export interface ParserOptions {
93
+ maxEntries?: number
94
+ strings?: Record<string, string> | string
95
+ stringsSource?: string
96
+ }
97
+
98
+ export interface VerbatimEntry {
99
+ input: string
100
+ type: string
101
+ key: string
102
+ fields: Record<string, string>
103
+ }
104
+
105
+ export interface VerbatimLibrary {
106
+ entries: VerbatimEntry[]
107
+ strings: Record<string, string>
108
+ comments: string[]
109
+ errors: ParseError[]
110
+ preambles: string[]
111
+ }
112
+
113
+ export function parseVerbatim(input: string, options?: ParserOptions): VerbatimLibrary
114
+ export function parseNormalized(input: string, options?: Options): Library
115
+ export function parse(input: string, options?: Options): Library
116
+ export function parseAsync(input: string, options?: Options): Promise<Library>
117
+ export function toSentenceCase(input: string, options?: {
118
+ preserveQuoted?: boolean
119
+ subSentenceCapitalization?: boolean
120
+ guess?: boolean
121
+ }): string
122
+ export function tokenize(input: string, markup?: RegExp): Token[]
@@ -0,0 +1,122 @@
1
+ import init, {
2
+ initSync,
3
+ parseNormalized as parseNormalizedWasm,
4
+ parseVerbatim as parseVerbatimWasm,
5
+ tokenize as tokenizeWasm,
6
+ toSentenceCase as toSentenceCaseWasm,
7
+ } from './bibtex_parser.js'
8
+
9
+ export { init, initSync }
10
+ export default init
11
+
12
+ const english = [
13
+ '', 'american', 'british', 'canadian', 'english', 'australian', 'newzealand',
14
+ 'usenglish', 'ukenglish', 'en', 'eng', 'en-au', 'en-bz', 'en-ca', 'en-cb',
15
+ 'en-gb', 'en-ie', 'en-jm', 'en-nz', 'en-ph', 'en-tt', 'en-us', 'en-za', 'en-zw', 'anglais',
16
+ ]
17
+
18
+ function rustOptions(options = {}) {
19
+ const rust = Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined))
20
+
21
+ if (rust.unsupported !== undefined && typeof rust.unsupported !== 'string') {
22
+ throw new TypeError('unsupported must be ignore, keep, or throw')
23
+ }
24
+ if (rust.unsupported !== undefined && !['ignore', 'keep', 'throw'].includes(rust.unsupported)) {
25
+ throw new TypeError('unsupported must be ignore, keep, or throw')
26
+ }
27
+
28
+ if (typeof rust.strings === 'string') {
29
+ rust.stringsSource = rust.strings
30
+ delete rust.strings
31
+ }
32
+ else if (!rust.strings) {
33
+ delete rust.strings
34
+ }
35
+ if (typeof rust.english === 'boolean') {
36
+ rust.english = rust.english ? english : []
37
+ }
38
+ else if (Array.isArray(rust.english)) {
39
+ const configured = rust.english
40
+ rust.english = [...english]
41
+ configured.forEach((language, index) => {
42
+ rust.english[index] = language
43
+ })
44
+ }
45
+ if (rust.sentenceCase === false) {
46
+ rust.english = []
47
+ rust.sentenceCase = { guess: false, subSentence: false, preserveQuoted: false }
48
+ }
49
+ if (rust.caseProtection === false) rust.caseProtection = 'off'
50
+ if (rust.caseProtection === true) rust.caseProtection = 'as-needed'
51
+ if (Array.isArray(rust.verbatimFields)) {
52
+ rust.verbatimFields = rust.verbatimFields.filter(field => typeof field === 'string')
53
+ }
54
+ if (rust.unsupported === 'ignore') rust.ignoreUnsupported = true
55
+ delete rust.unsupported
56
+ return rust
57
+ }
58
+
59
+ function library(result) {
60
+ if (Array.isArray(result.preambles)) {
61
+ result.preamble = result.preambles
62
+ delete result.preambles
63
+ }
64
+ return result
65
+ }
66
+
67
+ function throwOnUnsupported(result) {
68
+ const unsupported = result.errors.find(error => error.error.startsWith('unhandled macro ') || error.error.startsWith('unhandled environment '))
69
+ if (unsupported) throw new Error(unsupported.error)
70
+ return result
71
+ }
72
+
73
+ export function parseVerbatim(input, options = {}) {
74
+ const result = parseVerbatimWasm(input, rustOptions(options))
75
+ delete result.jabref
76
+ return result
77
+ }
78
+
79
+ export function parseNormalized(input, options = {}) {
80
+ const selectors = options.verbatimFields || []
81
+ const patterns = selectors.filter(selector => selector instanceof RegExp)
82
+ let normalizedOptions = options
83
+ if (patterns.length) {
84
+ const exactFields = new Set(selectors.filter(selector => typeof selector === 'string'))
85
+ const raw = parseVerbatimWasm(input, rustOptions({
86
+ ...options,
87
+ verbatimFields: [...exactFields],
88
+ }))
89
+ for (const entry of raw.entries) {
90
+ for (const field of Object.keys(entry.fields)) {
91
+ if (patterns.some(pattern => field.match(new RegExp(
92
+ pattern.source,
93
+ pattern.flags.includes('i') ? pattern.flags : `${pattern.flags}i`,
94
+ )))) {
95
+ exactFields.add(field)
96
+ }
97
+ }
98
+ }
99
+ normalizedOptions = { ...options, verbatimFields: [...exactFields] }
100
+ }
101
+ const result = library(parseNormalizedWasm(input, rustOptions(normalizedOptions)))
102
+ if (options.unsupported === 'throw') return throwOnUnsupported(result)
103
+ return result
104
+ }
105
+
106
+ export function parse(input, options = {}) {
107
+ return parseNormalized(input, options)
108
+ }
109
+
110
+ export async function parseAsync(input, options = {}) {
111
+ return parseNormalized(input, options)
112
+ }
113
+
114
+ export function toSentenceCase(input, options = {}) {
115
+ return toSentenceCaseWasm(input, options)
116
+ }
117
+
118
+ export function tokenize(input, markup) {
119
+ if (!(markup instanceof RegExp)) return tokenizeWasm(input)
120
+ const masked = input.replace(markup, match => '\u2060'.repeat(match.length))
121
+ return tokenizeWasm(masked)
122
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retorquere/bibtex-parser",
3
- "version": "11.0.0",
3
+ "version": "12.0.0",
4
4
  "description": "BibTeX parser",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -16,7 +16,12 @@
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "default": "./dist/cjs/index.js"
18
18
  }
19
- }
19
+ },
20
+ "./wasm": {
21
+ "types": "./dist/wasm/index.d.ts",
22
+ "import": "./dist/wasm/index.js"
23
+ },
24
+ "./wasm/bibtex_parser_bg.wasm": "./dist/wasm/bibtex_parser_bg.wasm"
20
25
  },
21
26
  "typings": "./index.d.ts",
22
27
  "scripts": {
@@ -27,10 +32,13 @@
27
32
  "build:esm": "rm -rf dist/esm && esbuild *.ts --outdir=dist/esm --format=esm --sourcemap --target=es2020 --loader:.ts=ts",
28
33
  "build:cjs": "rm -rf dist/cjs && esbuild *.ts --outdir=dist/cjs --format=cjs --sourcemap --target=node16 --loader:.ts=ts",
29
34
  "build:types": "rm -rf dist/esm dist/types && tsc -d -p tsconfig.esm.json",
35
+ "build:ts": "npm run build:types && npm run build:cjs && npm run build:esm",
36
+ "build:wasm": "node rust/build-wasm.mjs",
30
37
  "prebuild": "rm -rf dist && mkdir -p dist/data && cp data/*.json dist/data && ./build/abbr.py && ./build/prepositions.py",
31
- "build": "npm run build:types && npm run build:cjs && npm run build:esm",
38
+ "build": "npm run build:ts && npm run build:wasm",
32
39
  "pretest": "npm start",
33
40
  "test": "node test/run.js",
41
+ "test:package": "npm run build && node --test test/package.test.js",
34
42
  "minitest": "./build/crossref.py && npm run build && node i.js",
35
43
  "list": "tar tvf $(npm pack)",
36
44
  "prepublishOnly": "npm start",
@@ -41,6 +49,7 @@
41
49
  "predocs": "npm start",
42
50
  "docs": "typedoc --tsconfig tsconfig.cjs.json",
43
51
  "modules": "git submodule update --init --recursive",
52
+ "wasm:test": "npm run build:wasm && node --test test/wasm.js test/rust-wasm-parity.test.js",
44
53
  "ncu": "./build/submodules.py && ./build/crossref.py && ncu -u && npm i && git add package.json package-lock.json && npm audit fix && git commit -m ncu"
45
54
  },
46
55
  "repository": {