├── extra_style_licenses.txt ├── styles_version.txt ├── locales_version.txt ├── .babelrc ├── licenses.txt ├── src ├── tools.js └── index.js ├── .npmignore ├── .gitignore ├── rollup.config.js ├── package.json ├── README.md ├── convert.py ├── LICENSE └── .eslintrc.cjs /extra_style_licenses.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /styles_version.txt: -------------------------------------------------------------------------------- 1 | 8c5439ee7e0689c5afb44e2fff9694eb9d36ec7b 2 | -------------------------------------------------------------------------------- /locales_version.txt: -------------------------------------------------------------------------------- 1 | 606fa26be1d87837c4e607362b28ed58a7576875 2 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["@babel/plugin-syntax-dynamic-import"] 3 | } 4 | -------------------------------------------------------------------------------- /licenses.txt: -------------------------------------------------------------------------------- 1 | The files in this repository on github are licensed under the LGPL V.3 license (See LICENSE). 2 | 3 | On NPM, it is packaged together with other software. Y 4 | ou can find license information about these packages as outlined below: 5 | 6 | citeproc-js: See software_license.txt 7 | citation locales: See locale_licenses.txt 8 | citation styles: See style_licenses.txt 9 | additional citation styles added in this repository: See extra_style_licenses.txt 10 | -------------------------------------------------------------------------------- /src/tools.js: -------------------------------------------------------------------------------- 1 | export function inflateCSLObj(slimObj) { 2 | if (slimObj.name) { 3 | // Already inflated 4 | return slimObj 5 | } 6 | const obj = {} 7 | obj.name = slimObj.n 8 | if (slimObj.a) { 9 | obj.attrs = slimObj.a 10 | } else { 11 | obj.attrs = {} 12 | } 13 | obj.children = [] 14 | if (slimObj.c) { 15 | slimObj.c.forEach(child => { 16 | if (typeof child === 'string') { 17 | obj.children.push(child) 18 | } else { 19 | obj.children.push(inflateCSLObj(child)) 20 | } 21 | }) 22 | } else if (slimObj.n === 'term') { 23 | obj.children.push('') 24 | } 25 | return obj 26 | } 27 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # citeproc-plus specific 64 | styles-master/ 65 | locales-master/ 66 | src/ 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # citeproc-plus specific 64 | locale_licenses.txt 65 | style_licenses.txt 66 | software_license.txt 67 | build/ 68 | dist/ 69 | package-lock.json 70 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import commonjs from '@rollup/plugin-commonjs' 2 | import resolve from '@rollup/plugin-node-resolve' 3 | import babel from '@rollup/plugin-babel' 4 | import replace from '@rollup/plugin-replace' 5 | import rebasePlugin from "rollup-plugin-rebase" 6 | import terser from '@rollup/plugin-terser' 7 | 8 | export default [ 9 | { 10 | input: 'src/index.js', 11 | makeAbsoluteExternalsRelative: true, 12 | plugins: [ 13 | replace({ 14 | delimiters: ['', ''], 15 | preventAssignment: false, 16 | 'CSL.setupXml =': 'const unusedXml =', 17 | 'CSL.setupXml': 'new CSL.XmlJSON', 18 | 'CSL.XmlDOM =': 'let XmlDOM =', 19 | 'CSL.XmlDOM': 'XmlDOM', 20 | 'CSL.parseXml =': 'const parseXml =', 21 | 'CSL.parseXml': 'parseXml' 22 | }), 23 | rebasePlugin({ 24 | assetFolder: 'assets' // See https://github.com/sebastian-software/rollup-plugin-rebase/issues/24 25 | }), 26 | resolve({browser: true}), 27 | commonjs(), 28 | terser() 29 | ], 30 | output: // ES module version, for modern browsers 31 | { 32 | dir: "dist", 33 | format: "es", 34 | sourcemap: true 35 | } 36 | }, 37 | { 38 | input: 'src/index.js', 39 | makeAbsoluteExternalsRelative: true, 40 | plugins: [ 41 | replace({ 42 | delimiters: ['', ''], 43 | preventAssignment: false, 44 | 'CSL.setupXml =': 'const unusedXml =', 45 | 'CSL.setupXml': 'new CSL.XmlJSON', 46 | 'CSL.XmlDOM =': 'let XmlDOM =', 47 | 'CSL.XmlDOM': 'XmlDOM', 48 | 'CSL.parseXml =': 'const parseXml =', 49 | 'CSL.parseXml': 'parseXml' 50 | }), 51 | rebasePlugin({ 52 | assetFolder: 'cjs-assets' // See https://github.com/sebastian-software/rollup-plugin-rebase/issues/24 53 | }), 54 | resolve({browser: true}), 55 | commonjs(), 56 | babel({babelHelpers: 'bundled'}), 57 | terser() 58 | ], 59 | output: // CJS version 60 | { 61 | dir: "dist/cjs", 62 | format: "cjs", 63 | sourcemap: true 64 | } 65 | } 66 | ] 67 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "citeproc-plus", 3 | "version": "0.3.5", 4 | "description": "Citeproc-js + citation styles bundled", 5 | "main": "dist/cjs/index.js", 6 | "module": "dist/index.js", 7 | "type": "module", 8 | "scripts": { 9 | "prebuild": "npm run lint && rm -rf build/ && mkdir build && npm run get_styles_commit && npm run get_styles && npm run get_locales_commit && npm run get_locales && ./convert.py && npm run get_citeproc_license", 10 | "build": "npm run rollup", 11 | "rollup": "rm -rf dist/ && rollup -c", 12 | "prepublishOnly": "npm run build", 13 | "prepare": "npm run build", 14 | "lint": "eslint src/*js", 15 | "test": "echo \"Error: no test specified\" && exit 1", 16 | "get_locales": "cd build && wget -qO- https://github.com/citation-style-language/locales/archive/master.zip | bsdtar -xvf- && cd ..", 17 | "get_locales_commit": "wget -qO- http://api.github.com/repos/citation-style-language/locales/commits/master | jq -r '.sha' > locales_version.txt", 18 | "get_styles": "cd build && wget -qO- https://github.com/citation-style-language/styles/archive/master.zip | bsdtar -xvf- && cd ..", 19 | "get_styles_commit": "wget -qO- http://api.github.com/repos/citation-style-language/styles/commits/master | jq -r '.sha' > styles_version.txt", 20 | "get_citeproc_license": "cp node_modules/citeproc/LICENSE ./software_license.txt" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/fiduswriter/citeproc-plus.git" 25 | }, 26 | "keywords": [ 27 | "citeproc", 28 | "citeproc-js", 29 | "csl", 30 | "citations", 31 | "styles" 32 | ], 33 | "author": "Johannes Wilm", 34 | "license": "LGPL-3.0", 35 | "bugs": { 36 | "url": "https://github.com/fiduswriter/citeproc-plus/issues" 37 | }, 38 | "homepage": "https://github.com/fiduswriter/citeproc-plus#readme", 39 | "devDependencies": { 40 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 41 | "@rollup/plugin-babel": "^6.0.4", 42 | "@rollup/plugin-commonjs": "^25.0.8", 43 | "@rollup/plugin-node-resolve": "^15.3.1", 44 | "@rollup/plugin-replace": "^5.0.7", 45 | "@rollup/plugin-terser": "^0.4.4", 46 | "citeproc": "^2.4.63", 47 | "eslint": "^8.57.1", 48 | "rollup": "^3.29.5", 49 | "rollup-plugin-rebase": "^4.1.1", 50 | "updates": "^15.3.1" 51 | }, 52 | "files": [ 53 | "LICENSE", 54 | "locale_licenses.txt", 55 | "software_licenses.txt", 56 | "licenses.txt", 57 | "dist/*", 58 | "locales_version.txt", 59 | "styles_version.txt" 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # citeproc-plus 2 | 3 | `citeproc-plus` incorporates 2000+ [styles](https://github.com/citation-style-language/styles/) and 50+ [locale](https://github.com/citation-style-language/locales/) files from the [Citation Style Language](https://citationstyles.org/) project, as well as [citeproc-js](https://github.com/Juris-M/citeproc-js), the JavaScript CSL processor library by Frank Bennett. 4 | 5 | This is an **early version** so be aware that the API may change. You can try a demo at https://fiduswriter.github.io/citeproc-plus/. 6 | 7 | This package is meant for those who want to use [citeproc-js](https://github.com/Juris-M/citeproc-js), but don't want to have to deal with retrieving and storing citation styles and localizations from other places on the web. 8 | 9 | How to use 10 | ======= 11 | 12 | 1. Install it from npm together with your other dependencies: 13 | 14 | npm install citeproc-plus --save 15 | 16 | 2. Install a plugin for your bundler to handle resources other than JavaScript files as separate files, for example [Webpack's File Loader](https://github.com/webpack-contrib/file-loader). Configure it so that it handles files with the ending `.csljson`. In the case of Webpack's File Loader, that would be a webpack.config.js with setting such as: 17 | 18 | ```js 19 | module.exports = { 20 | mode: "production", 21 | output: { 22 | publicPath: "dist/", 23 | }, 24 | module: { 25 | rules: [ 26 | { 27 | test: /\.(csljson)$/i, 28 | use: [ 29 | { 30 | loader: 'file-loader', 31 | }, 32 | ], 33 | }, 34 | ], 35 | }, 36 | }; 37 | ``` 38 | 39 | 3. Import `CSL` and `styles` in your app: 40 | 41 | ```js 42 | import {CSL} from "citeproc-plus" 43 | ``` 44 | 45 | 4. Where in citeproc-js you would have called: 46 | 47 | ```js 48 | const citeproc = new CSL.Engine(sys, style, lang, forceLang) 49 | ``` 50 | 51 | Do instead: 52 | 53 | ```js 54 | const csl = new CSL() 55 | 56 | const citeproc = await csl.getEngine( 57 | sys, // required, same as for citeproc-js, but without the retrieveLocale method 58 | styleId, // required, The id of the style to use 59 | lang, // optional, same as for citeproc-js 60 | forceLang // optional, same as for citeproc-js 61 | ) 62 | ``` 63 | 64 | to create a selector of all available styles: 65 | 66 | ```js 67 | csl.getStyles().then( 68 | styles => dom.innerHTML = 69 | `` 74 | ) 75 | ``` 76 | 77 | or if you prefer the `then()`-function, do: 78 | 79 | ```js 80 | const csl = new CSL() 81 | 82 | let citeproc 83 | 84 | csl.getEngine( 85 | sys, // required, same as for citeproc-js, but without the retrieveLocale method 86 | styleId, // required, The id of the style to use 87 | lang, // optional, same as for citeproc-js 88 | forceLang // optional, same as for citeproc-js 89 | ).then( 90 | engine => citeproc = engine 91 | ) 92 | ``` 93 | 94 | Notice that you only need one CSL instance with which you can create any number of citeproc instances with different styles, languages and sys objects connected to them. 95 | Notice also that the method to get an engine is asynchronous as it potentially has to download files from your static files storage. 96 | 97 | 98 | Advanced uses 99 | ======= 100 | 101 | ### JATS ### 102 | 103 | There is an extra style with the styleId `jats` that can be used as part of conversion packages. This style is not listed among the list of styles as it is not meant for human consumption. 104 | 105 | ### Manipulating a style in JavaScript ### 106 | 107 | If instead of the styleId you hand it a preprocessed style object it will use it as well without caching. 108 | 109 | ### Importing CSL ### 110 | 111 | Notice that the styles in this package are not stored in the citation style language (CSL) directly. There is a tool to convert CSL to the JSON of preprocessed style object that is needed [here](https://github.com/Juris-M/citeproc-js/blob/master/tools/makejson.py). 112 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import {inflateCSLObj} from "./tools" 2 | 3 | export class CSL { 4 | 5 | constructor() { 6 | this.styles = {} 7 | this.locales = {} 8 | this.citeproc = false 9 | } 10 | 11 | getStyles() { 12 | return import("../build/styles").then( 13 | ({styles}) => styles 14 | ) 15 | } 16 | 17 | getEngine(originalSys, styleId, lang, forceLang) { 18 | let locale, style 19 | return Promise.all( 20 | [ 21 | this.getCiteproc(), 22 | this.getStyle(styleId).then(styleObj => style = styleObj) 23 | ] 24 | ).then( 25 | () => this.getLocale(style, lang, forceLang).then(localeObj => locale = localeObj) 26 | ).then( 27 | () => { 28 | 29 | /* 30 | * We clone the original sys so that we can add methods to it without destroying the original. 31 | * Sys can be a class instance or a simple object. 32 | */ 33 | 34 | const sys = Object.assign(Object.create(originalSys), originalSys) 35 | sys.retrieveLocale = () => locale 36 | return new this.citeproc.Engine(sys, style, lang, forceLang) 37 | } 38 | ) 39 | 40 | 41 | } 42 | 43 | getEngineSync(originalSys, styleId, lang, forceLang) { 44 | // Attempt to get engine synchronously based on already cached downloads. Returns false if cache is not available. 45 | if (!this.citeproc || !this.styles[styleId]) { 46 | return false 47 | } 48 | const style = this.styles[styleId] 49 | let localeId = forceLang ? forceLang : 50 | style.attrs['default-locale'] ? style.attrs['default-locale'] : 51 | lang ? lang : 52 | 'en-US' 53 | 54 | if (!this.locales[localeId]) { 55 | localeId = 'en-US' 56 | } 57 | if (!this.locales[localeId]) { 58 | return false 59 | } 60 | const locale = this.locales[localeId] 61 | const sys = Object.assign(Object.create(originalSys), originalSys) 62 | sys.retrieveLocale = () => locale 63 | return new this.citeproc.Engine(sys, style, lang, forceLang) 64 | } 65 | 66 | getCiteproc() { 67 | if (this.citeproc) { 68 | return Promise.resolve() 69 | } 70 | return import("citeproc").then( 71 | citeprocModule => this.citeproc = citeprocModule.default 72 | ) 73 | } 74 | 75 | getStyle(styleId) { 76 | if (typeof styleId === 'object') { 77 | 78 | /* 79 | * Advanced usage: The styleId is a style definition itself. 80 | * Return directly without caching. 81 | */ 82 | 83 | return Promise.resolve(styleId) 84 | } 85 | 86 | return import("../build/styles").then( 87 | ({styleLocations}) => { 88 | if (!styleLocations[styleId]) { 89 | styleId = Object.keys(styleLocations).find(() => true) 90 | } 91 | let returnValue 92 | if (this.styles[styleLocations[styleId]]) { 93 | this.styles[styleLocations[styleId]][styleId] = inflateCSLObj(this.styles[styleLocations[styleId]][styleId]) 94 | returnValue = Promise.resolve(this.styles[styleLocations[styleId]][styleId]) 95 | } else { 96 | returnValue = fetch(styleLocations[styleId], {method: "GET"}).then( 97 | response => response.json() 98 | ).then( 99 | json => { 100 | this.styles[styleLocations[styleId]] = json 101 | this.styles[styleLocations[styleId]][styleId] = inflateCSLObj(this.styles[styleLocations[styleId]][styleId]) 102 | return Promise.resolve(this.styles[styleLocations[styleId]][styleId]) 103 | } 104 | ) 105 | } 106 | return returnValue 107 | } 108 | ) 109 | } 110 | 111 | getLocale(style, lang, forceLang) { 112 | let localeId = forceLang ? forceLang : 113 | style.attrs['default-locale'] ? style.attrs['default-locale'] : 114 | lang ? lang : 115 | 'en-US' 116 | 117 | if (this.locales[localeId]) { 118 | return Promise.resolve(this.locales[localeId]) 119 | } 120 | return import("../build/locales").then( 121 | ({locales}) => { 122 | if (!locales[localeId]) { 123 | localeId = 'en-US' 124 | } 125 | return fetch(locales[localeId], {method: "GET"}) 126 | } 127 | ).then( 128 | response => response.json() 129 | ).then( 130 | json => { 131 | this.locales[localeId] = inflateCSLObj(json) 132 | return Promise.resolve(this.locales[localeId]) 133 | } 134 | ) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from xml.dom import minidom 3 | from string import ascii_lowercase 4 | # By Johannes Wilm 5 | # based on https://bitbucket.org/fbennett/citeproc-js/src/default/makejson.py 6 | # by Frank Bennett 7 | # See license info 8 | # https://bitbucket.org/fbennett/citeproc-js/src/default/LICENSE 9 | 10 | UNLISTED_STYLES = [] # styles that should not appear in user facing lists of styles but that are nevertheless valid 11 | 12 | 13 | class XMLWalker: 14 | 15 | def __init__(self, xmlstring): 16 | dom = minidom.parseString(xmlstring).documentElement 17 | self.title_node = dom.getElementsByTagName("title") 18 | if len(self.title_node): 19 | self.title = self.title_node[0].firstChild.nodeValue 20 | else: 21 | self.title = '' 22 | lines = dom.getElementsByTagName("info")[0].toprettyxml().split('\n') 23 | self.license_info = '\n'.join([line for line in lines if line.strip()]) 24 | self.output = self.walk_xml(dom) 25 | 26 | def walk_xml(self, elem): 27 | obj = {} 28 | obj["n"] = elem.nodeName 29 | if elem.attributes: 30 | for key in elem.attributes.keys(): 31 | if key in ["xmlns", "href"]: 32 | pass 33 | else: 34 | if not "a" in obj: 35 | obj["a"] = {} 36 | obj["a"][key] = elem.attributes[key].value 37 | if len(elem.childNodes) > 0: 38 | obj["c"] = [] 39 | for child in elem.childNodes: 40 | if child.nodeName == "#comment": 41 | pass 42 | elif child.nodeName == "#text": 43 | if ( 44 | len(elem.childNodes) == 1 and 45 | elem.nodeName in ["term", "single", "multiple"] 46 | ): 47 | obj["c"].append(child.wholeText) 48 | else: 49 | obj["c"].append(self.walk_xml(child)) 50 | return obj 51 | 52 | 53 | if __name__ == "__main__": 54 | import json 55 | import sys 56 | import os 57 | import shutil 58 | 59 | dirs = ['./build/styles-master/', './src/extra_styles/'] 60 | out_dir = './build/styles/' 61 | out_relative_path = './styles/' 62 | 63 | license_txt = ( 64 | 'These styles are taken from ' 65 | 'https://github.com/citation-style-language/styles/\n' 66 | 'The licenses of the individual styles are licenses as follows: \n\n' 67 | ) 68 | styles_js_preamble = '' 69 | styles = {} 70 | styles_js_body = '' 71 | style_list = [] 72 | if os.path.exists(out_dir): 73 | shutil.rmtree(out_dir) 74 | 75 | os.makedirs(out_dir) 76 | 77 | index = 0 78 | for dir in dirs: 79 | for file in os.listdir(os.fsencode(dir)): 80 | filename = os.fsdecode(file) 81 | if filename.endswith(".csl"): 82 | id = filename[:-4] 83 | 84 | index += 1 85 | if index > 200: 86 | index = 1 87 | js_id = ( 88 | ascii_lowercase[index // 26] + 89 | ascii_lowercase[index % 26] 90 | ) 91 | if js_id == "do": 92 | js_id = "aa" 93 | walker = XMLWalker(open(os.path.join(dir, filename)).read()) 94 | if not js_id in styles: 95 | styles_js_preamble += 'import {} from "{}"\n'.format( 96 | js_id, 97 | os.path.join(out_relative_path, js_id + '.csljson') 98 | ) 99 | styles[js_id] = {} 100 | styles[js_id][id] = walker.output 101 | styles_js_body += ' "{}": {},\n'.format( 102 | id, 103 | js_id 104 | ) 105 | if not id in UNLISTED_STYLES: 106 | title = walker.title.replace('\\', '\\\\').replace('"', '\\"') 107 | style_list.append([ 108 | title, 109 | ' "{}": "{}",\n'.format( 110 | id, 111 | title 112 | ) 113 | ]) 114 | license_txt += '{}\n'.format(id) 115 | license_txt += walker.license_info 116 | license_txt += '\n\n---\n\n' 117 | for style in styles.items(): 118 | id = style[0] 119 | with open(os.path.join(out_dir, id + '.csljson'), 'w') as out_file: 120 | json.dump(style[1], out_file) 121 | 122 | sorted_style_list = sorted(style_list, key=lambda k: k[0]) 123 | styles_js_options = '' 124 | for style in sorted_style_list: 125 | styles_js_options += style[1] 126 | 127 | styles_js = ( 128 | styles_js_preamble + 129 | '\nexport const styleLocations = {\n' + 130 | styles_js_body[:-2] + 131 | '\n}\n' + 132 | '\nexport const styles = {\n' + 133 | styles_js_options[:-2] + 134 | '\n}\n' 135 | ) 136 | with open('build/styles.js', 'w') as out_file: 137 | out_file.write(styles_js) 138 | 139 | with open('style_licenses.txt', 'w') as out_file: 140 | out_file.write(license_txt) 141 | 142 | dir = './build/locales-master/' 143 | out_dir = './build/locales/' 144 | out_relative_path = './locales/' 145 | 146 | license_txt = ( 147 | 'These locales are taken from ' 148 | 'https://github.com/citation-style-language/locales\n' 149 | 'The licenses of the individual locales are licenses as follows: \n\n' 150 | ) 151 | locales_js_preamble = '' 152 | locales_js_body = '' 153 | 154 | if os.path.exists(out_dir): 155 | shutil.rmtree(out_dir) 156 | 157 | os.makedirs(out_dir) 158 | 159 | for file in os.listdir(os.fsencode(dir)): 160 | filename = os.fsdecode(file) 161 | if filename.endswith(".xml"): 162 | id = filename[8:-4] 163 | js_id = id.replace('-', '_') 164 | walker = XMLWalker(open(os.path.join(dir, filename)).read()) 165 | out_file = open(os.path.join(out_dir, id + '.csljson'), 'w') 166 | json.dump(walker.output, out_file) 167 | locales_js_preamble += 'import {} from "{}"\n'.format( 168 | js_id, 169 | os.path.join(out_relative_path, id + '.csljson') 170 | ) 171 | locales_js_body += ' "{}": {},\n'.format( 172 | id, 173 | js_id 174 | ) 175 | license_txt += '{}\n'.format(id) 176 | license_txt += walker.license_info 177 | license_txt += '\n\n---\n\n' 178 | locales_js = ( 179 | locales_js_preamble + 180 | '\nexport const locales = {\n' + 181 | locales_js_body[:-1] + 182 | '}' 183 | ) 184 | with open('build/locales.js', 'w') as out_file: 185 | out_file.write(locales_js) 186 | 187 | with open('locale_licenses.txt', 'w') as out_file: 188 | out_file.write(license_txt) 189 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "globals": { 8 | "Atomics": "readonly", 9 | "SharedArrayBuffer": "readonly" 10 | }, 11 | "parserOptions": { 12 | "ecmaVersion": 2021, 13 | "sourceType": "module" 14 | }, 15 | "rules": { 16 | "accessor-pairs": "error", 17 | "array-bracket-newline": "error", 18 | "array-bracket-spacing": "error", 19 | "array-callback-return": "error", 20 | "array-element-newline": "error", 21 | "arrow-body-style": "error", 22 | "arrow-parens": [ 23 | "error", 24 | "as-needed" 25 | ], 26 | "arrow-spacing": [ 27 | "error", 28 | { 29 | "after": true, 30 | "before": true 31 | } 32 | ], 33 | "block-scoped-var": "error", 34 | "block-spacing": "error", 35 | "brace-style": [ 36 | "error", 37 | "1tbs" 38 | ], 39 | "callback-return": "error", 40 | "camelcase": "off", 41 | "capitalized-comments": "error", 42 | "class-methods-use-this": "off", 43 | "comma-dangle": "off", 44 | "comma-spacing": "off", 45 | "comma-style": [ 46 | "error", 47 | "last" 48 | ], 49 | "complexity": "error", 50 | "computed-property-spacing": [ 51 | "error", 52 | "never" 53 | ], 54 | "consistent-return": "error", 55 | "consistent-this": "error", 56 | "curly": "error", 57 | "default-case": "error", 58 | "dot-location": "error", 59 | "dot-notation": "error", 60 | "eol-last": "off", 61 | "eqeqeq": "error", 62 | "func-call-spacing": "error", 63 | "func-name-matching": "error", 64 | "func-names": "error", 65 | "func-style": [ 66 | "error", 67 | "declaration" 68 | ], 69 | "function-paren-newline": "off", 70 | "generator-star-spacing": "error", 71 | "global-require": "error", 72 | "guard-for-in": "error", 73 | "handle-callback-err": "error", 74 | "id-blacklist": "error", 75 | "id-length": "error", 76 | "id-match": "error", 77 | "implicit-arrow-linebreak": [ 78 | "error", 79 | "beside" 80 | ], 81 | "indent": "off", 82 | "indent-legacy": "error", 83 | "init-declarations": "off", 84 | "jsx-quotes": "error", 85 | "key-spacing": "error", 86 | "keyword-spacing": [ 87 | "error", 88 | { 89 | "after": true, 90 | "before": true 91 | } 92 | ], 93 | "line-comment-position": "error", 94 | "linebreak-style": [ 95 | "error", 96 | "unix" 97 | ], 98 | "lines-around-comment": "error", 99 | "lines-around-directive": "error", 100 | "lines-between-class-members": [ 101 | "error", 102 | "always" 103 | ], 104 | "max-classes-per-file": "error", 105 | "max-depth": "error", 106 | "max-len": "off", 107 | "max-lines": "off", 108 | "max-lines-per-function": "error", 109 | "max-nested-callbacks": "error", 110 | "max-params": "off", 111 | "max-statements": "off", 112 | "max-statements-per-line": "error", 113 | "multiline-comment-style": "error", 114 | "multiline-ternary": "off", 115 | "new-cap": "error", 116 | "new-parens": "error", 117 | "newline-after-var": "off", 118 | "newline-before-return": "off", 119 | "newline-per-chained-call": "off", 120 | "no-alert": "error", 121 | "no-array-constructor": "error", 122 | "no-await-in-loop": "error", 123 | "no-bitwise": "error", 124 | "no-buffer-constructor": "error", 125 | "no-caller": "error", 126 | "no-catch-shadow": "error", 127 | "no-confusing-arrow": "error", 128 | "no-console": "error", 129 | "no-continue": "error", 130 | "no-div-regex": "error", 131 | "no-duplicate-imports": "error", 132 | "no-else-return": "error", 133 | "no-empty-function": "error", 134 | "no-eq-null": "error", 135 | "no-eval": "error", 136 | "no-extend-native": "error", 137 | "no-extra-bind": "error", 138 | "no-extra-label": "error", 139 | "no-extra-parens": "error", 140 | "no-floating-decimal": "error", 141 | "no-implicit-coercion": "error", 142 | "no-implicit-globals": "error", 143 | "no-implied-eval": "error", 144 | "no-inline-comments": "error", 145 | "no-invalid-this": "error", 146 | "no-iterator": "error", 147 | "no-label-var": "error", 148 | "no-labels": "error", 149 | "no-lone-blocks": "error", 150 | "no-lonely-if": "error", 151 | "no-loop-func": "error", 152 | "no-magic-numbers": "error", 153 | "no-mixed-operators": "error", 154 | "no-mixed-requires": "error", 155 | "no-multi-assign": "error", 156 | "no-multi-spaces": "error", 157 | "no-multi-str": "error", 158 | "no-multiple-empty-lines": "error", 159 | "no-native-reassign": "error", 160 | "no-negated-condition": "error", 161 | "no-negated-in-lhs": "error", 162 | "no-nested-ternary": "off", 163 | "no-new": "error", 164 | "no-new-func": "error", 165 | "no-new-object": "error", 166 | "no-new-require": "error", 167 | "no-new-wrappers": "error", 168 | "no-octal-escape": "error", 169 | "no-param-reassign": "off", 170 | "no-path-concat": "error", 171 | "no-plusplus": "error", 172 | "no-process-env": "error", 173 | "no-process-exit": "error", 174 | "no-proto": "error", 175 | "no-restricted-globals": "error", 176 | "no-restricted-imports": "error", 177 | "no-restricted-modules": "error", 178 | "no-restricted-properties": "error", 179 | "no-restricted-syntax": "error", 180 | "no-return-assign": "off", 181 | "no-return-await": "error", 182 | "no-script-url": "error", 183 | "no-self-compare": "error", 184 | "no-sequences": "error", 185 | "no-shadow": "error", 186 | "no-spaced-func": "error", 187 | "no-sync": "error", 188 | "no-tabs": "error", 189 | "no-template-curly-in-string": "error", 190 | "no-ternary": "off", 191 | "no-throw-literal": "error", 192 | "no-trailing-spaces": "error", 193 | "no-undef-init": "error", 194 | "no-undefined": "error", 195 | "no-underscore-dangle": "error", 196 | "no-unmodified-loop-condition": "error", 197 | "no-unneeded-ternary": "error", 198 | "no-unused-expressions": "error", 199 | "no-use-before-define": "error", 200 | "no-useless-call": "error", 201 | "no-useless-computed-key": "error", 202 | "no-useless-concat": "error", 203 | "no-useless-constructor": "error", 204 | "no-useless-rename": "error", 205 | "no-useless-return": "error", 206 | "no-var": "error", 207 | "no-void": "error", 208 | "no-warning-comments": "error", 209 | "no-whitespace-before-property": "error", 210 | "nonblock-statement-body-position": "error", 211 | "object-curly-newline": "off", 212 | "object-curly-spacing": [ 213 | "error", 214 | "never" 215 | ], 216 | "object-shorthand": "off", 217 | "one-var": "off", 218 | "one-var-declaration-per-line": "error", 219 | "operator-assignment": "error", 220 | "operator-linebreak": [ 221 | "error", 222 | "after" 223 | ], 224 | "padded-blocks": "off", 225 | "padding-line-between-statements": "error", 226 | "prefer-arrow-callback": "error", 227 | "prefer-const": "error", 228 | "prefer-destructuring": "error", 229 | "prefer-named-capture-group": "error", 230 | "prefer-numeric-literals": "error", 231 | "prefer-object-spread": "error", 232 | "prefer-promise-reject-errors": "error", 233 | "prefer-reflect": "error", 234 | "prefer-rest-params": "error", 235 | "prefer-spread": "error", 236 | "prefer-template": "error", 237 | "quote-props": "off", 238 | "quotes": "off", 239 | "radix": "error", 240 | "require-await": "error", 241 | "require-jsdoc": "off", 242 | "require-unicode-regexp": "error", 243 | "rest-spread-spacing": "error", 244 | "semi": "off", 245 | "semi-spacing": "error", 246 | "semi-style": "error", 247 | "sort-keys": "off", 248 | "sort-vars": "error", 249 | "space-before-blocks": "error", 250 | "space-before-function-paren": "off", 251 | "space-in-parens": [ 252 | "error", 253 | "never" 254 | ], 255 | "space-infix-ops": "error", 256 | "space-unary-ops": "error", 257 | "spaced-comment": "error", 258 | "strict": "error", 259 | "switch-colon-spacing": "error", 260 | "symbol-description": "error", 261 | "template-curly-spacing": "error", 262 | "template-tag-spacing": "error", 263 | "unicode-bom": [ 264 | "error", 265 | "never" 266 | ], 267 | "valid-jsdoc": "error", 268 | "vars-on-top": "error", 269 | "wrap-iife": "error", 270 | "wrap-regex": "error", 271 | "yield-star-spacing": "error", 272 | "yoda": [ 273 | "error", 274 | "never" 275 | ] 276 | } 277 | }; 278 | --------------------------------------------------------------------------------