Giter Site home page Giter Site logo

juris-m / citeproc-js Goto Github PK

View Code? Open in Web Editor NEW
286.0 25.0 82.0 106.96 MB

A JavaScript implementation of the Citation Style Language (CSL) https://citeproc-js.readthedocs.io

License: Other

Python 1.21% Shell 0.31% HTML 0.97% JavaScript 97.42% CSS 0.07% Batchfile 0.01%

citeproc-js's Introduction

citeproc-js

A JavaScript implementation of the Citation Style Language

Authors

Frank Bennett

image

About

The Citation Style Language (CSL) is an XML grammar for expressing the detailed requirements of a citation style. A CSL processor is a tool that generates citations and bibliographies by applying CSL style rules to bibliographic data.

The citeproc-js CSL processor is over a decade in service, a fact that shows through in ways both good and bad. On the downside, the code base is not pretty, and can serve as a solid illustration of the burden of technical debt (in case you need one of those for your computer science class). On the upside, though, citeproc-js passes a suite of over 1,300 integration tests with flying colors. When run in CSL-M mode1 it can handle multilingual and legal content with a flexibility and precision unrivaled by any other tool at any price. And it has been quite heavily field-tested, as the citation formatter driving word processor integration in both Mendeley and Zotero.

More important than fleeting badges of popularity, though, is the CSL standard. Developers can take comfort in the technical strength of the CSL Specification, and the existence of other processors under active development. CSL is the modern way to handle bibliographic projects, and citeproc-js is a convenient way to take advantage of it.

Submitting bug reports

If you think you have found a processor bug, you can help track it down by submitting a test item or items that expose the error. To submit an item, join the public Jurism Test Submission group <https://www.zotero.org/groups/2339078/jurism_test_submissions>, sync, create a collection named for the style that shows the error, drop the item into it, jot a description of the problem in the Abstract field, and sync again.

For errors not associated with a particular style or item, file reports on the citeproc-js GitHub tracker <https://github.com/juris-m/citeproc-js/issues>.

Building the processor

The processor files citeproc.js and citeproc_commonjs.js` are built automatically when tests are run (see below).

Running Tests

The processor is supported by a little over 1,300 test fixtures, which can be run from a git clone of this repository after installing the Citeproc Test Runner. The system requirements (apart from git itself) are:

git

Needed to fetch a clone of the citeproc-js repository on GitHub.

node.js

Any recent-ish version should work. Version 7 is used for automated testing.

mocha

Install Mocha globally with npm install --global mocha.

java

This is used to perform schema validation. Browser extension is not required, a basic command-line install is all you need.

Once the system requirements are set up, install the test runner with the following command:

npm install -g citeproc-test-runner

You can now run the full suite of integration tests from the citeproc-js directory with the following command:

cslrun -a

You can review the full set of options by runningcslrun -h. For more information on running tests, see the citeproc-js Manual or the README of the Citeproc Test Runner

Repository Content

The processor itself is contained in a single file. Two copies are in the repository: citeproc_commonjs.js (an ES6 module); and citeproc.js (a raw bundle of JavaScript). The former is probably what you will want for most purposes today.

The following command will pull the sources of the processor and supporting files:

git clone --recursive https://github.com/Juris-M/citeproc-js.git

Directories of the repository contain a number of tools used for development and testing:

src

Processor source files. These are bundled into the two processor copies by the test script cslrun, distributed separately in the citeproc-test-runner package via npm (see below for details).

csl-schemata

The RelaxNG schemata for CSL and CSL-M. These are used to validate style code. The schemata are not used directly by the processor at runtime.

demo

Contains a simple example of processor configuration in a Web environment. Can be viewed by running a local webserver in the directory.

docs

Source files for the citeproc-js manual on ReadTheDocs.

fixtures/local

Integration test fixtures specific to the citeproc-js processor or to the CSL-M grammar variant.

fixtures/std

Standard CSL integration tests from the Citation Style Language repository.

fixtures/styles

Style-level tests. For more information, see the citeproc-js Manual or the README of the Citeproc Test Runner

juris-modules

Jurisdiction modules. These are used to CSL-M mode to render legal citations in country-specific forms.

locale

The standard locale files from the CSL project.

tools

An assortment of scripts that are used, or have been used at some point, in the maintenance of citeproc-js.



2019.03.27
FB

  1. CSL-M is set of private extensions to official CSL used by the Jurism reference manager, a variant of Zotero. For more information, see the citeproc-js Manual

citeproc-js's People

Contributors

adam-vessey avatar ailintom avatar bwiernik avatar denismaier avatar dependabot[bot] avatar dsifford avatar dstillman avatar fbennett avatar fbennetttest avatar fcheslack avatar georgd avatar hubgit avatar johanneswilm avatar klortho avatar krassowski avatar larsgw avatar mdmower avatar michel-kraemer avatar miguelsm avatar retorquere avatar rmzelle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

citeproc-js's Issues

page-range-format parsing problem (en-dash vs hyphen)

There appears to be an issue processing the page-range-format when page ranges are defined using en-dash.

For example:

With page-range-format set to 'chicago',

111-125 in the Zotero pages field produces 111–25 in MS Word (the expected behavior).

However, 111–125 (note the en dash) in the Zotero pages field produces 111–125 in MS Word.

This is true for locators as well (a hyphen processes correctly, an en-dash does not).

I apologize the title is not more descriptive and if this is not the correct place for this issue. I think the problem is somewhere in the citeproc-js code, however.

The issue sounds like the issue here: https://forums.zotero.org/discussion/33793?page=1#Item_13

Which was fixed in 1.0.526. However, using the en_US local, it is still occurring.

Bugs for Creators entered through Extra cheater syntax

I've found some bugs with how citeproc-js seems to handle creator names entered using the Zotero Extra field and the cheater syntax.

If I enter a name like this:
{:editor: Book | Editor}

citeproc-js picks it up and recognizes that it is an editor, but three things don't work.

First, the "initialize-with" parameter for names isn't respected--["initialize-with"=". "] renders as:
(Book, Editor, Ed.) in apa.csl

Second, names entered via Extra don't seem to work correctly for parameters. For example, if a Report lacks an author, but has an editor in Extra, the citation renders as:
(1999). Title. Place: Publisher.

Interesting, what seems to be happening is that citeproc-js recognizes that there is an editor, but doesn't actually render the contexts. If I remove the editor from Extra, it renders as:
Title. (1999). Place: Publisher.

If there is both an editor and a translate in Extra (with the same name--so they should collapse), it renders as:
(1999). Title. (Translate, First, Trans.) Place: Publisher.

Third, collapsing of editor and translator doesn't work if one of the two names is defined through cheater syntax, but the other is not. (e.g., if Translator is entered into proper Zotero fields, but Editor is entered in Extra, they won't collapse into "Ed. & Trans.")--if both are in Extra, it works as expected.

Citation only, no wrapped html -- How do I make this happen?

In the demo, the response object returned from makeBibliography is an array of html..

<div class="csl-entry"> <div class="csl-left-margin">1. </div><div class="csl-right-inline">Knuth DE. <i>Digital Typography</i>. Center for the Study of Language and Information; 1998.</div> </div>

How do I get it to return JUST the inner formatting? I want to handle the presentation myself.

This is what I want:

Knuth DE. <i>Digital Typography</i>. Center for the Study of Language and Information; 1998.

Any help is apprecitated! Thanks

Question regarding test coverage for citeproc-js implementation

Hi Frank,

Hopefully a simple question for ya: Are you aware of somebody that I may be able to get in touch with that has a list of citation styles (preferably as small as possible) that cover every different format option for bibliographies? (If you are aware of this, even better!)

In other words, I want to make sure my bibliography formatter is working properly based on the properties it receives from the 0-index of the output of the makeBibliography method.

(hopefully that makes sense).

Thanks in advance.

Seasons and season ranges

When used from Zotero/LO, citeproc-js parses issued: 2013-13 and issued: 2013-13/2014-16 in the Extra field as expected, i.e., as “Spring 2013” and “Spring 2013–Winter 2014” – expected, that is, if you happen to know that citeproc-js uses the pseudo months 13 to 16 to represent seasons.

I would like to suggest accepting the somewhat more standardized season codes used by ISO 8601/EDTF, i.e., 21 to 24 as well (or instead of 13 to 16), so that issued: 2013-21 and issued: 2013-21/2014-24 could be used, too.

Bluebook style has no bibliographies

We use citeproc-js to format citations and bibliographies. When the bluebook styles are set, it seems no bibliographies are included. From http://csl.mendeley.com/ no layout structures can be found under the bibliography section of bluebook styles (Bluebook Inline, Bluebook Law Review and Bluebook Law Review 2). Is it expected behaviour for these styles?

New output format

I add a new output format to the processor by adding it to CSL.Output.Formats, but I'm having an issue escaping URLs. From the looks of it, the URLs I produce through '@URL/true' are put through text_escape. Is there a way to prevent this? URLs need a non-standard escaping for markdown.

In-text citation range processing fails under certain (very reproducible) circumstances.

I traced this issue and can confirm it is an issue with citeproc-js proper, rather than my implementation.

Specifically, it's a failure within CSL.Output.Queue.prototype.renderBlobs


Note: This is observed with AMA format, but likely can also be observed in others that use the same style of in-text citations.

Expected behavior

If I have a single document with a range of citations from 1-3 and I re-cite the reference at position 3 before the range of citations, citation 3 should be shifted to location 1, but the range should not be affected.

Example:
This....

New citation here.

Old range here. 1-3

Should be this after inserting citation # 3 at the end of line 1...

New citation here. 1

Old range here. 1-3

Actual behavior

gif

In other words, this is actually what happens....

Before

New citation here.

Old range here. 1-3

After

New citation here. 1

Old range here. 2,3,1

Hope you're doing well, Frank. 😄

Title case for hyphenated words

With the current version of propachi installed, the following title (with language="en"):
Closing the scientist–practitioner gap: studies from 2016 with significant practical utility

is rendered as this in Title Case:
Closing the Scientist–practitioner Gap: Studies from 2016 with Significant Practical Utility

In English, the part following the hyphen is generally expected to follow the same capitalization rules as any other word (i.e., treat the hyphen like a space).

(Am I correct there @adam3smith ?)

Multiple requests to retrieveLocale

I'm working on integrating citeproc-js with OJS 3, an open-source journal publishing platform. We want to use it to display a citation for a published article, and allow users to generate a citation in one of a handful of formats the journal manager might enable.

One of my goals is to minimise the performance impact of loading the citation on an end-user-facing page. To do this, I load the locale and default style with the initial payload, and bootstrap the first render of a citation from XML files loaded into a global var. So my citeprocSys retrieves locale and item data from an existing object, rather than fetching it on-demand:

var citeprocSys = {
	retrieveLocale: function(lang) {
		if (typeof pkpCSL.locales[lang] !== 'undefined' ) {
			return pkpCSL.locales[lang];
		}
		return false;
	},
	retrieveItem: function(id) {
		return pkpCSL.items[id];
	}
};

This works because only a single language will be available per page request, so we don't need to load in all the XML every time.

One issue I've found with this is that citeproc.js fetches an en-US locale every time, regardless of what language is requested, even if the requested language file exists.

https://github.com/Juris-M/citeproc-js/blob/master/src/util_locale.js#L40-L49

I wonder if it would be possible to fetch the fallback locales only when the requested locale is not available. retrieveLocale could then return false when a locale is not available. This would prevent retrieveLocale from getting called multiple times when unnecessary.

The code for that could look like this:

    localexmlraw = this.sys.retrieveLocale(langspec.best);
    if (localexmlraw) {
        this.localeSet(CSL.setupXml(localexmlraw), langspec.best, langspec.best);
    } else {
        if (!localexmlraw && langspec.base !== langspec.best) {
            localexmlraw = this.sys.retrieveLocale(langspec.base);
            if (localexmlraw) {
                this.localeSet(CSL.setupXml(localexmlraw), langspec.base, langspec.best);
            }
        } else if (!localexmlraw && langspec.best !== "en-US") {
            localexmlraw = this.sys.retrieveLocale("en-US");
            if (localexmlraw) {
                this.localeSet(CSL.setupXml(localexmlraw), "en-US", langspec.best);
            }
        }
    }

I don't know the implications of making a change like this, as I don't have a good grasp of the full system yet. But I wondered if this was a change you might look positively upon. If so, I'd be happy to issue a pull request.

Deprecated HTML element used

Hi Frank,

I'm just now realizing that citeproc is still using the <i> element to indicate italic, or emphasized, text. This has been partially deprecated in HTML5. It's recommended to now use the <em> element for that. Technically speaking, it should really be the <cite> element, but because the purpose of the element is to apply italicized formatting for the wrapped text, I think <em> would be the best bet moving forward.

Here's what MDN says...

In earlier versions of the HTML specification, the <i> tag was merely a presentational element used to display text in italics, much like the <b> tag was used to display text in bold letters. This is no longer true, as these tags now define semantics rather than typographic appearance. The <i> tag should represent a range of text with a different semantic meaning whose typical typographic representation is italicized. This means a browser will typically still display its contents in italic type, but is, by definition, no longer required to.

Use this element only when there is not a more appropriate semantic element. For example:

  • Use <em> to indicate emphasis or stress.
  • Use <strong> to indicate importance.
  • Use <mark> to indicate relevance.
  • Use <cite> to mark the name of a work, such as a book, play, or song.
  • Use <dfn> to mark the defining instance of a term.

Double-encoded angle brackets in HTML

[
    {
        "id": "http://zotero.org/users/local/0rmqTjvx/items/ABCD2345",
        "type": "webpage",
        "title": "Zotero Quick Start Guide",
        "URL": "http://zotero.org/support/quick_start_guide",
        "author": [
            {
                "literal": "Center for History and New Media"
            }
        ]
    }
]

Citing with https://www.zotero.org/styles/universite-libre-de-bruxelles-histoire?source=1

Rendered HTML from 1.1.74:

CENTER FOR HISTORY AND NEW MEDIA, « Zotero Quick Start Guide », s.d., [En ligne]. &lt;http://zotero.org/support/quick_start_guide&gt;. .

i.e., markup is [En ligne]. &amp;lt;http://zotero.

Correct in 1.1.60

citeproc_with_e4x syntax errors on load

In tests/runners/rhino-bundled.js
the command
load("./citeproc_with_e4x.js");
is failing with this output

js: "./citeproc_with_e4x.js", line 14488: missing ; after for-loop initializer
js:         for (var key of Object.keys(_nestingData)) {
js: .......................^
js: "./citeproc_with_e4x.js", line 14489: missing ; before statement
js:             if (_nestingData[key].type === "quote") {
js: ....................................................^
js: "./citeproc_with_e4x.js", line 14493: invalid return
js:         return ret;
js: ..............^
js: "./citeproc_with_e4x.js", line 14494: syntax error
js:     }();
js: ....^
js: "./citeproc_with_e4x.js", line 14497: missing ; after for-loop initializer
js:         for (var key of Object.keys(_nestingData)) {
js: .......................^
js: "./citeproc_with_e4x.js", line 14498: missing ; before statement
js:             if (_nestingData[key].type === "nocase") continue;
js: .............................................................^
js: "./citeproc_with_e4x.js", line 14505: invalid return
js:         return ret;
js: ..............^
js: "./citeproc_with_e4x.js", line 14506: syntax error
js:     }();
js: ....^
js: "./citeproc_with_e4x.js", line 14520: missing ; after for-loop initializer
js:         for (var key of Object.keys(_nestingData)) {
js: .......................^
js: "./citeproc_with_e4x.js", line 14521: missing ; before statement
js:             if (_nestingData[opener].type !== "quote" || !_nestingData[opener]) {
js: ................................................................................^
js: "./citeproc_with_e4x.js", line 14522: syntax error
js:                 openers.push(key);
js: ........................^
js: "./citeproc_with_e4x.js", line 14524: syntax error
js:         }
js: ........^
js: "./citeproc_with_e4x.js", line 14527: invalid return
js:         return ret;
js: ..............^
js: "./citeproc_with_e4x.js", line 14528: syntax error
js:     }
js: ....^
js: "./citeproc_with_e4x.js", line 14531: missing ; after for-loop initializer
js:         for (var key of Object.keys(_nestingData)) {
js: .......................^
js: "./citeproc_with_e4x.js", line 14534: invalid return
js:         return ret;
js: ..............^
js: "./citeproc_with_e4x.js", line 14535: syntax error
js:     }()
js: ....^
js: "./citeproc_with_e4x.js", line 14544: missing ; after for-loop initializer
js:         for (var closer of Object.keys(vals)) {
js: ..........................^
js: "./citeproc_with_e4x.js", line 14545: syntax error
js:             closers.push(closer);
js: ....................^
js: "./citeproc_with_e4x.js", line 14548: invalid return
js:         return {
js: ..............^
js: "./citeproc_with_e4x.js", line 14550: missing ; before statement
js:             splitAll: new RegExp("(?:" + all + ")", "g"),
js: .....................^
js: "./citeproc_with_e4x.js", line 14551: syntax error
js:             open: new RegExp("(^(?:" + openers.map(function(str){return str.replace("(", "\\(")}).join("|") + ")$)"),
js: .................^
js: "./citeproc_with_e4x.js", line 14552: syntax error
js:             close: new RegExp("(^(?:" + closers.join("|") + ")$)"),
js: ..................^
js: "./citeproc_with_e4x.js", line 14554: syntax error
js:     }();
js: ......^
js: "./citeproc_with_e4x.js", line 14868: syntax error
js: }
js: ^
js: "./citeproc_with_e4x.js", line 14869: syntax error
js: CSL.Output.Formatters = new function () {
js: ....^
js: "./citeproc_with_e4x.js", line 14870: syntax error
js:     this.passthrough = passthrough;
js: .........^
js: "./citeproc_with_e4x.js", line 15166: syntax error
js: }
js: ^
js: "./citeproc_with_e4x.js", line 15167: syntax error
js: CSL.Output.Formats = function () {};
js: ....^
Testing with rhino: UTF-8
477 tests to run in 41 groups
------------------------------------------------------------
GROUP "std.plural" has 2 tests to run
ReferenceError: "CSL" is not defined.
	ERROR IN:
		 (function () {var test = new StdRhinoTest("plural_AffiliationSpoofingIsPluralWithNames", "rhino");doh.assertEqual(test.result, test.run());})
org.mozilla.javascript.EcmaError: ReferenceError: "CSL" is not defined.
	at org.mozilla.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3785)
	at org.mozilla.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3763)
	at org.mozilla.javascript.ScriptRuntime.notFoundError(ScriptRuntime.java:3848)
	at org.mozilla.javascript.ScriptRuntime.nameOrFunction(ScriptRuntime.java:1847)
	at org.mozilla.javascript.ScriptRuntime.name(ScriptRuntime.java:1786)
	at org.mozilla.javascript.gen.__src_test_runner_js_3._c_anonymous_1(Unknown Source)
	at org.mozilla.javascript.gen.__src_test_runner_js_3.call(Unknown Source)
	at org.mozilla.javascript.BaseFunction.construct(BaseFunction.java:369)
	at org.mozilla.javascript.ScriptRuntime.newObject(ScriptRuntime.java:2440)
	at org.mozilla.javascript.gen.____tests_bundled_plural_js_9._c_anonymous_1(Unknown Source)
	at org.mozilla.javascript.gen.____tests_bundled_plural_js_9.call(Unknown Source)
	at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:66)
	at org.mozilla.javascript.gen.____dojo_util_doh_runner_js_5._c_anonymous_62(Unknown Source)
	at org.mozilla.javascript.gen.____dojo_util_doh_runner_js_5.call(Unknown Source)
	at org.mozilla.javascript.optimizer.OptRuntime.call2(OptRuntime.java:76)
	at org.mozilla.javascript.gen.____dojo_util_doh_runner_js_5._c_anonymous_69(Unknown Source)
	at org.mozilla.javascript.gen.____dojo_util_doh_runner_js_5.call(Unknown Source)
	at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:66)
	at org.mozilla.javascript.gen.____dojo_util_doh_runner_js_5._c_anonymous_74(Unknown Source)
	at org.mozilla.javascript.gen.____dojo_util_doh_runner_js_5.call(Unknown Source)
	at org.mozilla.javascript.optimizer.OptRuntime.callProp0(OptRuntime.java:119)
	at org.mozilla.javascript.gen.__tests_runners_run_js_4._c_script_0(Unknown Source)
	at org.mozilla.javascript.gen.__tests_runners_run_js_4.call(Unknown Source)
	at org.mozilla.javascript.gen.__tests_runners_run_js_4.exec(Unknown Source)
	at org.mozilla.javascript.tools.shell.Main.evaluateScript(Main.java:654)
	at org.mozilla.javascript.tools.shell.Main.processFileSecure(Main.java:552)
	at org.mozilla.javascript.tools.shell.Main.processFile(Main.java:507)
	at org.mozilla.javascript.tools.shell.Global.load(Global.java:282)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:161)
	at org.mozilla.javascript.FunctionObject.call(FunctionObject.java:413)
	at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:97)
	at org.mozilla.javascript.gen.tests_runners_rhino_bundled_js_1._c_script_0(Unknown Source)
	at org.mozilla.javascript.gen.tests_runners_rhino_bundled_js_1.call(Unknown Source)
	at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:426)
	at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3178)
	at org.mozilla.javascript.gen.tests_runners_rhino_bundled_js_1.call(Unknown Source)
	at org.mozilla.javascript.gen.tests_runners_rhino_bundled_js_1.exec(Unknown Source)
	at org.mozilla.javascript.tools.shell.Main.evaluateScript(Main.java:654)
	at org.mozilla.javascript.tools.shell.Main.processFileSecure(Main.java:552)
	at org.mozilla.javascript.tools.shell.Main.processFile(Main.java:507)
	at org.mozilla.javascript.tools.shell.Main.processSource(Main.java:499)
	at org.mozilla.javascript.tools.shell.Main.processFiles(Main.java:215)
	at org.mozilla.javascript.tools.shell.Main$IProxy.run(Main.java:134)
	at org.mozilla.javascript.Context.call(Context.java:521)
	at org.mozilla.javascript.ContextFactory.call(ContextFactory.java:535)
	at org.mozilla.javascript.tools.shell.Main.exec(Main.java:198)
	at org.mozilla.javascript.tools.shell.Main.main(Main.java:174)

Locale seems to always default to `en-US`, even when supplied with a "locale getter" function

Hi there.

I can't seem to get any other locale other than en-US. To my knowledge, I'm supplying the CSL.engine with the correct functions to retrieve the locale, but it just isn't happening.

Here is the relevant code from my repo:

declare var CSL;

export class CSLPreprocessor {

    public citeprocSys: Citeproc.SystemObj;
    public citations: { [id: string]: CSL.Data };

    /**
     * Constructor for the CSLPreprossor class.
     * @param  {string}  locale  The current user's locale string.
     * @param  {{[id: string]:CSL.Data}}  citations  An object of CSL.Data.
     *   Note, the object key MUST match the `id` param within the object.
     * @param  {string}   style  The user's selected style string.
     * @param  {Function} callback  Callback function
     * @return {void}
     */
    constructor(locale: string, citations: { [id: string]: CSL.Data }, style: string, callback: Function) {

        this.citations = citations;

        let p1 = new Promise((resolve, reject) => {
            this.getLocale(locale, (data: string) => {
                resolve({
                    retrieveLocale: (lang) => data,
                    retrieveItem: (id: string | number) => this.citations[id],
                });
            });
        });

        p1.then((data: Citeproc.SystemObj) => {
            this.citeprocSys = data;
            this.getProcessor(style, data, callback);
        });

    }

    /**
     * Retrieves the locale rules for CSL using HTTP and passes it to a callback function.
     * @param {string}   locale   The user's locale.
     * @param {Function} callback Callback function.
     */
    getLocale(locale: string, callback: Function): void {
        let req = new XMLHttpRequest();

        let cslLocale = this.locales[locale];
        if (typeof cslLocale === 'boolean') {
            locale = 'en-US';
        }
        else {
            locale = cslLocale;
        }

        req.onreadystatechange = () => {
            if (req.readyState === 4) {
                callback(req.responseText);
            }
        };

        req.open("GET", `https://raw.githubusercontent.com/citation-style-language/locales/8c976408d3cb287d0cecb29f97752ec3a28db9e5/locales-${locale}.xml`);
        req.send(null);
    }

    /**
     * Retrieves the CSL style rules for the selected style using HTTP. When the
     *   style instructions are received, a CSL.Engine is created and passed to
     *   the callback function.
     * @param  {string}   styleID  The style ID for the style of interest (no .csl extension)
     * @param  {Function} callback Callback function.
     */
    getProcessor(styleID: string, data: Citeproc.SystemObj, callback: Function): void {
        let req = new XMLHttpRequest();
        req.open('GET', `https://raw.githubusercontent.com/citation-style-language/styles/master/${styleID}.csl`);

        req.onreadystatechange = () => {
            if (req.readyState === 4) {
                let citeproc = new CSL.Engine(data, req.responseText);
                callback(citeproc);
            }
        }

        req.send(null);
    }

    /**
     * Receives the response object from `getProcessor`, makes the bibliography,
     *   removes outer HTML, pushes it to an array, and returns the array.
     * @param  {Object}   citeproc The citeproc engine.
     * @return {string[]}          Array of citations to be served.
     */
    prepare(citeproc): string[] {
        citeproc.updateItems(Object.keys(this.citations));
        let bib = citeproc.makeBibliography();

        let data = [];
        bib[1].forEach(ref => {
            data.push(this.trimHTML(ref));
        });
        return data;
    }

    /**
     * Removes outer HTML formatting served from citeproc, sparing inner `<i>` tags.
     * @param  {string} ref The reference payload from citeproc.
     * @return {string}     A formatted reference string without outer HTML.
     */
    trimHTML(ref: string): string {
        return ref
            .replace(/<(?!(i|\/i|a|\/a)).+?>/g, '')
            .trim()
            .replace(/^\d+\.\s?/, '');
    }

    /**
     * This object converts the locale names in wordpress (keys) to the locales
     *   in CSL (values). If CSL doesn't have a locale for a given WordPress locale,
     *   then false is used (which will default to en-US).
     */
    private locales: {[wp: string]:string|boolean} = {
        'af': 'af-ZA',
        'ak': false,
        'am': false,
        'ar': 'ar',
        'arq': 'ar',
        'art_xemoji': 'ar',
        'ary': 'ar',
        'as': 'en-US',
        'az_TR': 'tr-TR',
        'az': 'tr-TR',
        'azb': 'en-US',
        'ba': false,
        'bal': false,
        'bcc': false,
        'bel': false,
        'bg_BG': 'bg-BG',
        'bn_BD': 'en-US',
        'bo': false,
        'bre': false,
        'bs_BA': false,
        'ca': 'ca-AD',
        'ceb': false,
        'ckb': false,
        'co': false,
        'cs_CZ': 'cs-CZ',
        'cy': 'cy-GB',
        'da_DK': 'da-DK',
        'de_CH': 'de-CH',
        'de_DE': 'de-DE',
        'dv': false,
        'dzo': false,
        'el': 'el-GR',
        'en_AU': 'en-US',
        'en_CA': 'en-US',
        'en_GB': 'en-GB',
        'en_NZ': 'en-US',
        'en_US': 'en-US',
        'en_ZA': 'en-US',
        'eo': false,
        'es_AR': 'es-ES',
        'es_CL': 'es-CL',
        'es_CO': 'es-CL',
        'es_ES': 'es-ES',
        'es_GT': 'es-ES',
        'es_MX': 'es-MX',
        'es_PE': 'es-CL',
        'es_PR': 'es-CL',
        'es_VE': 'es-CL',
        'et': 'et-ET',
        'eu': 'eu',
        'fa_AF': 'fa-IR',
        'fa_IR': 'fa-IR',
        'fi': 'fi-FI',
        'fo': false,
        'fr_BE': 'fr-FR',
        'fr_CA': 'fr-CA',
        'fr_FR': 'fr-FR',
        'frp': false,
        'fuc': false,
        'fur': false,
        'fy': false,
        'ga': false,
        'gd': false,
        'gl_ES': false,
        'gn': false,
        'gsw': 'de-CH',
        'gu': false,
        'haw_US': 'en-US',
        'haz': false,
        'he_IL': 'he-IL',
        'hi_IN': false,
        'hr': 'hr-HR',
        'hu_HU': 'hu-HU',
        'hy': false,
        'id_ID': 'id-ID',
        'ido': false,
        'is_IS': 'is-IS',
        'it_IT': 'it-IT',
        'ja': 'ja-JP',
        'jv_ID': false,
        'ka_GE': false,
        'kab': false,
        'kal': false,
        'kin': false,
        'kk': false,
        'km': 'km-KH',
        'kn': false,
        'ko_KR': 'ko-KR',
        'ky_KY': false,
        'lb_LU': 'lt-LT',
        'li': false,
        'lin': false,
        'lo': false,
        'lt_LT': 'lt-LT',
        'lv': 'lv-LV',
        'me_ME': false,
        'mg_MG': false,
        'mk_MK': false,
        'ml_IN': false,
        'mn': 'mn-MN',
        'mr': false,
        'mri': false,
        'ms_MY': false,
        'my_MM': false,
        'nb_NO': 'nb-NO',
        'ne_NP': false,
        'nl_BE': 'nl-NL',
        'nl_NL': 'nl-NL',
        'nn_NO': 'nn-NO',
        'oci': false,
        'ory': false,
        'os': false,
        'pa_IN': false,
        'pl_PL': 'pl-PL',
        'ps': false,
        'pt_BR': 'pt-PR',
        'pt_PT': 'pt-PT',
        'rhg': false,
        'ro_RO': 'ro-RO',
        'roh': false,
        'ru_RU': 'ru-RU',
        'rue': false,
        'rup_MK': false,
        'sa_IN': false,
        'sah': false,
        'si_LK': false,
        'sk_SK': 'sk-SK',
        'sl_SI': 'sl-SI',
        'snd': false,
        'so_SO': false,
        'sq': false,
        'sr_RS': 'sr-RS',
        'srd': false,
        'su_ID': false,
        'sv_SE': 'sv-SE',
        'sw': false,
        'szl': false,
        'ta_IN': false,
        'ta_LK': false,
        'tah': false,
        'te': false,
        'tg': false,
        'th': 'th-TH',
        'tir': false,
        'tl': false,
        'tr_TR': 'tr-TR',
        'tt_RU': false,
        'tuk': false,
        'twd': false,
        'tzm': false,
        'ug_CN': false,
        'uk': 'uk-UA',
        'ur': false,
        'uz_UZ': false,
        'vi': 'vi-VN',
        'wa': false,
        'xmf': false,
        'yor': false,
        'zh_CN': 'zh-CN',
        'zh_HK': 'zh-CN',
        'zh_TW': 'zh-TW',
    }


}

Any tips would be much appreciated. Thank you in advance!

TypeError: Cannot read property 'before' of undefined

When I run citeproc-js with node.js for the cslEditor, it throws the above error for a subset of styles, e.g. ambio.csl

This is starting at version 1.1.142 and is true for all versions since. 1.1.141 works fine

Any thoughts?

Negative year date parsing

Currently, Zotero doesn't properly parse negative years (it just strips the negative sign and returns a positive year). I tried to use the recently updated date override method with the Propachi plugin (with citeproc-js .136). The processor correctly receives the negative year. However, the year is rendered as a simple negative number, rather than correctly displaying the BCE abbreviation.

e.g., with issued: -323 in the Extra field, the reference renders as:
Smith, J. (-323) Title.

Is there a way to get citeproc-js to properly render negative years?

_this._getCiteproc is not a function inside a web worker

I'm using Citeproc installed via yarn (version 2.1.181) and everything works fine in a usual use case. However, when I try creating a bibliography inside a web worker (to reduce the strain of the main thread), I get the following error when calling processor.appendCitationCluster({ data }): _this._getCiteproc is not a function.

I caught the error inside a try catch block and even managed to call processor.makeBibliography() afterwards and it returned a correct array, but without any citation items inside.

This might not be due to Citeproc itself since it works outside web workers, but maybe you know where does the difference come from and how to make it work inside a web worker. Thanks!

LANG_BASES does not account for pubmed languages.

If CSL is parsed directly from the PubMed API, the language field of the CSL will be non-standard.

Possibly consider adding a check for these languages as well: https://www.nlm.nih.gov/bsd/language_table.html

In my use case, I have an object containing all the non-standard languages and locales from both PubMed and WordPress to make this conversion (below), but others might not have something like this.

If false is returned from the lookup, my script defaults to en-US.

/**
 * This object converts the locale names in wordpress or PubMed (keys) to the locales
 *   in CSL (values). If CSL doesn't have a locale for a given WordPress locale,
 *   then false is used (which will default to en-US).
 */
export const localeConversions = {
    'af': 'af-ZA',
    'afr': 'af-ZA',
    'ak': false,
    'alb': false,
    'am': false,
    'amh': false,
    'ar': 'ar-AR',
    'ara': 'ar-AR',
    'arm': false,
    'arq': 'ar-AR',
    'art_xemoji': 'ar-AR',
    'ary': 'ar-AR',
    'as': 'en-US',
    'az_TR': 'tr-TR',
    'az': 'tr-TR',
    'azb': 'en-US',
    'ba': false,
    'bal': false,
    'bcc': false,
    'bel': false,
    'ben': false,
    'bg_BG': 'bg-BG',
    'bn_BD': 'en-US',
    'bo': false,
    'bos': false,
    'bre': false,
    'bs_BA': false,
    'bul': 'bg-BG',
    'ca': 'ca-AD',
    'cat': 'ca-AD',
    'ceb': false,
    'chi': 'zh-CN',
    'ckb': false,
    'co': false,
    'cs_CZ': 'cs-CZ',
    'cy': 'cy-GB',
    'cze': 'cs-CZ',
    'da_DK': 'da-DK',
    'dan': 'da-DK',
    'de_CH': 'de-CH',
    'de_DE': 'de-DE',
    'dut': 'nl-NL',
    'dv': false,
    'dzo': false,
    'el': 'el-GR',
    'en_AU': 'en-US',
    'en_CA': 'en-US',
    'en_GB': 'en-GB',
    'en_NZ': 'en-US',
    'en_US': 'en-US',
    'en-US': 'en-US',
    'en_ZA': 'en-US',
    'eng': 'en-US',
    'eo': false,
    'epo': false,
    'es_AR': 'es-ES',
    'es_CL': 'es-CL',
    'es_CO': 'es-CL',
    'es_ES': 'es-ES',
    'es_GT': 'es-ES',
    'es_MX': 'es-MX',
    'es_PE': 'es-CL',
    'es_PR': 'es-CL',
    'es_VE': 'es-CL',
    'est': 'et-ET',
    'et': 'et-ET',
    'eu': 'eu',
    'fa_AF': 'fa-IR',
    'fa_IR': 'fa-IR',
    'fi': 'fi-FI',
    'fin': 'fi-FI',
    'fo': false,
    'fr_BE': 'fr-FR',
    'fr_CA': 'fr-CA',
    'fr_FR': 'fr-FR',
    'fre': 'fr-FR',
    'frp': false,
    'fuc': false,
    'fur': false,
    'fy': false,
    'ga': false,
    'gd': false,
    'geo': false,
    'ger': 'de-DE',
    'gl_ES': false,
    'gla': false,
    'gn': false,
    'gre': 'el-GR',
    'gsw': 'de-CH',
    'gu': false,
    'haw_US': 'en-US',
    'haz': false,
    'he_IL': 'he-IL',
    'heb': 'he-IL',
    'hi_IN': false,
    'hin': false,
    'hr': 'hr-HR',
    'hrv': 'hr-HR',
    'hu_HU': 'hu-HU',
    'hun': 'hu-HU',
    'hy': false,
    'ice': 'is-IS',
    'id_ID': 'id-ID',
    'ido': false,
    'ind': 'id-ID',
    'is_IS': 'is-IS',
    'it_IT': 'it-IT',
    'ita': 'it-IT',
    'ja': 'ja-JP',
    'jpn': 'ja-JP',
    'jv_ID': false,
    'ka_GE': false,
    'kab': false,
    'kal': false,
    'kin': false,
    'kk': false,
    'km': 'km-KH',
    'kn': false,
    'ko_KR': 'ko-KR',
    'kor': 'ko-KR',
    'ky_KY': false,
    'lat': false,
    'lav': 'lv-LV',
    'lit': 'lt-LT',
    'lb_LU': 'lt-LT',
    'li': false,
    'lin': false,
    'lo': false,
    'lt_LT': 'lt-LT',
    'lv': 'lv-LV',
    'mac': false,
    'mao': false,
    'may': false,
    'mul': false,
    'me_ME': false,
    'mg_MG': false,
    'mk_MK': false,
    'ml_IN': false,
    'mn': 'mn-MN',
    'mr': false,
    'mri': false,
    'ms_MY': false,
    'my_MM': false,
    'nb_NO': 'nb-NO',
    'ne_NP': false,
    'nl_BE': 'nl-NL',
    'nl_NL': 'nl-NL',
    'nn_NO': 'nn-NO',
    'nor': 'nn-NO',
    'oci': false,
    'ory': false,
    'os': false,
    'pa_IN': false,
    'per': 'fa-IR',
    'pl_PL': 'pl-PL',
    'pol': 'pl-PL',
    'por': 'pt-PT',
    'ps': false,
    'pt_BR': 'pt-PR',
    'pt_PT': 'pt-PT',
    'rhg': false,
    'ro_RO': 'ro-RO',
    'roh': false,
    'ru_RU': 'ru-RU',
    'rum': 'ro-RO',
    'rue': false,
    'rus': 'ru-RU',
    'rup_MK': false,
    'sa_IN': false,
    'sah': false,
    'san': false,
    'si_LK': false,
    'sk_SK': 'sk-SK',
    'sl_SI': 'sl-SI',
    'slo': 'sk-SK',
    'slv': 'sl-SI',
    'snd': false,
    'so_SO': false,
    'spa': 'es-ES',
    'sq': false,
    'sr_RS': 'sr-RS',
    'srd': false,
    'srp': 'sr-RS',
    'su_ID': false,
    'sv_SE': 'sv-SE',
    'sw': false,
    'swe': 'sv-SE',
    'szl': false,
    'ta_IN': false,
    'ta_LK': false,
    'tah': false,
    'te': false,
    'tg': false,
    'th': 'th-TH',
    'tha': 'th-TH',
    'tir': false,
    'tl': false,
    'tr_TR': 'tr-TR',
    'tt_RU': false,
    'tuk': false,
    'tur': 'tr-TR',
    'twd': false,
    'tzm': false,
    'ug_CN': false,
    'uk': 'uk-UA',
    'ukr': 'uk-UA',
    'und': false,
    'ur': false,
    'urd': false,
    'uz_UZ': false,
    'vi': 'vi-VN',
    'vie': 'vi-VN',
    'wa': false,
    'wel': false,
    'xmf': false,
    'yor': false,
    'zh_CN': 'zh-CN',
    'zh_HK': 'zh-CN',
    'zh_TW': 'zh-TW',
};

Q: What is embedBibliographyEntry() for?

I've searched the web with Google for embedBibliographyEntry, and looked at every mention of it in the citeproc code... I'm not sure what it's supposed to be used for. I made a slot for it in the \ztbibItemText macro that my "bbl" output format produces for the zotero-texmacs-integration, thinking that maybe it will need that someday... but if it's not really anything it needs, then maybe I should just remove that extraneous argument? It's always blank right now because embedBibliographyEntry is not defined anywhere.

TitleCaser errors out (full disclosure: BBT uses it in possibly inappropriate ways)

So, the full disclosure first: BBT uses the titlecaser outside the scope of the citation processor running, so it's fully possible that I'm calling it with an illegitimate state, thereby causing the breakage. I've called the citeproc titlecaser in this way for a long time though, and it has always worked before.

Here's what I'm actually doing:

var makeRegExp, state, titleCase;

makeRegExp = function(lst) {
  return new RegExp('(?:(?:[?!:]*\\s+|-|^)(?:' + lst.slice().join('|') + ')(?=[!?:]*\\s+|-|$))', 'g');
};

state = {
  opt: {
    lang: 'en'
  },
  locale: {
    en: {
      opts: {
        'skip-words': CSL.SKIP_WORDS,
        'skip-words-regexp': makeRegExp(CSL.SKIP_WORDS)
      }
    }
  }
};

titleCase = function(text) {
  return CSL.Output.Formatters.title(state, text);
};

console.log(titleCase("/ ' '"));

This has always worked splendidly for me, but with this particular string it errors out with

var origChar = config.doppel.origStrings[quotePos+1].slice(0, 1);
TypeError: Cannot read property 'slice' of undefined

here: https://github.com/Juris-M/citeproc-js/blob/master/citeproc.js#L14984

I've inspected (what I think is ) the relevant state of the function at that point when it breaks, and I see this:

CSL: {"config.doppel.origStrings":["","","",""],"quotePos":2,"config.quoteState":[{"opener":" \"","closer":"'","positions":2}],"i":0}

While I have zero clues on what doppelString is doing, if I replace

var quotePos = config.quoteState[i].pos;

with

var quotePos = (typeof config.quoteState[i].pos == "number") ? config.quoteState[i].pos : config.quoteState[i].positions;

all my tests pass.

(as an aside, it'd be very useful to me if makeRegExp were exposed as a method)

Wild Idea: Thinking about forking and rewriting this in TypeScript

I've come to the conclusion that the only way I'll really be able to understand all of this is if I go through it line-by-line and read it.

That realization led me to the idea of rewriting this in Typescript.

Benefits:

  1. Future-proofing.
  2. Optimization + pruning of dead APIs.
  3. Readable documentation (possibly using typedoc) so future users can quickly skim to what they need clarification on.
  4. Code can be broken into modules (each with their own concern), and then compiled and minified to a single file (better readability).
  5. Simultaneously build node packages that can be published and consumed on npm. (I'm aware of this one, but I think a separate one, specific to React applications would be desired. Or angular. Or <insert-popular-javascript-framework-here>)

Would you be interested in teaming up on this? This would obviously be a spare time thing and really wouldn't have any due dates.

Feel free to call me a madman.

wrap_url_and_doi mishandles DOIs in URLs

When a style shows a DOI as part of a URL, the embedded DOI gets wrapped instead of the outer URL.

<div class="csl-entry">Mueen Ahmed, K., &amp; Al Dhubaib, B. (2011). Zotero: A bibliographic assistant to researcher. <i>Journal of Pharmacology and Pharmacotherapeutics</i>, <i>2</i>(4), 303. https://doi.org/<a href="https://doi.org/10.4103/0976-500X.85940">10.4103/0976-500X.85940</a></div>

Issue with civil law case law title in single citation

Transferring zotero/zotero#893 here.

Hi,

When you cite two (or more) "civil law case law" in a single citation, except for the first, court name and date are omitted.

Individual Citations :
CJCE, 31 mai 1978, C-102/77, Hoffmann-La Roche / Centrafarm, Rec. 1978.1139.
CJCE, 17 octobre 1990, C-10/89, CNL-SUCAL / HAG (HAG II), Rec. 1990.I‑3711.
(FYI: court, date, docket number, short title, reporter reporter volume.first page.)

Single Citation :
CJCE, 31 mai 1978, C-102/77, Hoffmann-La Roche / Centrafarm, Rec. 1978.1139; CNL-SUCAL / HAG (HAG II), Rec. 1990.I‑3711.

Should be :
CJCE, 31 mai 1978, C-102/77, Hoffmann-La Roche / Centrafarm, Rec. 1978.1139; CJCE, 17 octobre 1990, C-10/89, CNL-SUCAL / HAG (HAG II), Rec. 1990.I‑3711.

I think the issue is with citeproc.js around lines 4197-4203 [edit: now around 5224-5225].

I know there is a hook with for case. Multiple citations of a case law items with the same title will be merged into one.

I guess the issue is that every "civil law case law" has technically an identical title : ""/false.
(reminder: civil Law format, in Zotero at least, is created by omitting the title field in favour of the short title field)

A fix would be for citeproc to first check if there is any title at all...

Thank you.

More capitalization problems

With current Propachi installed, this container-title formats wrong:

Ones, D. S., B. M. Wiernik, S. Dilchert and R. M. Klein (2017), ‘Types and definitions of employee green behavior: more than conservation’, in V. Wells, D. Gregory-Smith, and D. Manika (eds), Research Handbook on Employee pro-Environmental Behaviour, Cheltenham, United Kingdom: Edward Elgar.

[Bug] hangingindent is ostensiblty the wrong type

Hello again 😄

I'm playing around with index-0 of makeBibliography() and I came across something using Chicago Manual of Style 16th edition (author-date).

According to the CSL spec, hangingindent must be a boolean value. However, I'm being given a number. Specifically, the number 2.

Here's that value directly from the visual CSL editor:

image

And here's the value I'm getting from makeBibliography():

image

Is this a bug?

[Serious Bug]: processCitationCluster returns invalid HTML IDs.

Hi Frank,

Starting about an hour ago, processCitationCluster has started regularly returning HTML IDs that begin with an integer. This causes a meltdown of my plugin because it depends on valid HTML selectors.

Can you please consider changing your ID generator to one that returns HTML IDs that begin with a character?

Here's the one I use for reference:

export function generateID(): string {
    return String.fromCharCode(97 + Math.floor(Math.random() * 26)) + Math.round(Math.random() * Date.now()).toString(30); // tslint:disable-line
}

Title Caser errors

These two titles don't title-case properly:

  1. "Using Google Flu Trends data in forecasting influenza-like-illness related ED visits in Omaha, Nebraska" (Influenza-like-Illness) doesn't capitalize "like")
  2. "Using networks to combine “big data” and traditional surveillance to improve influenza predictions" ("big" is not capitalized)

HTML escaped in citeproc-js output when using citation marks

This seems to be similar to #26 . When using this title:

<span class="nocase">"PIAAC-Longitudinal (PIAAC-L) 2015"</span>

we get this output in AAA style:

&#60;span class="nocase"&#62;"PIAAC-Longitudinal (PIAAC-L) 2015"&#60;/span&#62;.

(using citeproc 2.0.2 on npm)

A generic way of suppressing an attribute

I looked at the code and found there is a property "suppress-author" in citationItem that can suppress author attribute. But Is there a generic way to suppress a attribute, e.g. title, publisher and so on? If the answer is no, is there a plan of doing it?

Workflow for asynchronous locale loading

Hello,

I was wondering whether there are any plans for better async locale loading support. This would make a lot of sense in a scenario where citeproc-js is used in a website. Since support for synchronous XHR request support has been dropped in modern browsers, to use citeproc-js one has to either pre-load all locale xml files or parse the style file and figure out which locales will be needed before instantiating the CSL engine.

Ideally, the definition of sys.retrieveLocale() would change to either support a callback function as the second parameter or to handle promise return values. Depending on how citeproc-js works, this may not be the best strategy and require an asyncification of the whole API.

An alternative solution is to expose required locales after instantiating the CSL engine with a style XML, such that the API user can load the relevant locale files asynchronously before making additional calls like makeBibliography().

en-US locale is required

When only providing non-en-US locale(s), under otherwise normal conditions, citeproc-js throws an error (this one):

require('isomorphic-fetch')

const CSL = require('citeproc')

const lang = 'en-GB'
const json = [
  {
    "author": [
      {
        "given": "Happy",
        "family": "Larry"
      }
    ],
    "title": "A Lovely Title",
    "type": "article-journal",
    "label": "id",
    "id": "id"
  }
]

const template = await (await fetch('https://cdn.rawgit.com/citation-style-language/styles/master/apa.csl')).text()
const locale = await (await fetch(`https://cdn.rawgit.com/citation-style-language/locales/master/locales-${lang}.xml`)).text()
const locales = {[lang]: locale}

const retrieveLocale = lang => locales[lang]
const retrieveItem = id => json.find(item => item.id === id)

const engine = new CSL.Engine({
  retrieveItem,
  retrieveLocale
}, template, lang, true)

engine.updateItems(['id'])

engine.makeBibliography()
citeproc-js error: unable to parse CSL style or locale object

https://runkit.com/larsgw/citeproc-js-en-us-locale-required

[Bug] group as implicit conditional and choose conditional

group as implicit conditional and choose conditional do not always work together as expected. The MWE below produces output for, say, an entry type chapter with no container-title when the variables called by a group (in this case: container-title) are empty.

<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" version="1.0" class="note" default-locale="de-DE" demote-non-dropping-particle="sort-only">
  <info>
    <title>Minimal working example (MWE)</title>
    <category citation-format="note"/>
    <id>http://www.tillheilmann.info/mwe</id>
    <link href="http://www.tillheilmann.info/" rel="documentation"/>
    <updated>2017-08-01T17:51:31+01:00</updated>
  </info>
  <macro name="X">
    <text variable="container-title"/>
  </macro>
  <macro name="Y">
    <choose>
      <if variable="container-title">
	<text variable="container-title"/>
      </if>
    </choose>
  </macro>
  <citation>
    <layout>
      <group>
	<text value="A"/>
	<text variable="container-title"/>
      </group>
      <group>
      	<text value="B"/>
      	<choose>
      	  <if variable="container-title">
      	    <text variable="container-title"/>
      	  </if>
      	</choose>
      </group>
      <choose>
	<if variable="container-title">
	  <group>
	    <text value="C"/>
	    <text variable="container-title"/>
	  </group>
	</if>
      </choose>
      <group>
	<text value="D"/>
	<text macro="X"/>
      </group>
      <group>
	<text value="E"/>
	<text macro="Y"/>
      </group>
      <choose>
	<if type="chapter">
	  <group>
	    <text value="F"/>
	    <text macro="X"/>
	  </group>
	</if>
      </choose>
      <choose>
	<if type="chapter">
	  <group>
	    <text value="G"/>
	    <text macro="Y"/>
	  </group>
	</if>
      </choose>
    </layout>
  </citation>
</style>

CSL.Engine.prototype.dateParseArray does not properly handle empty strings

for (var i = 0, ilen = dp.length; i < ilen; i += 1) {
for (var j = 0, jlen = CSL.DATE_PARTS.length; j < jlen; j += 1) {
if ("undefined" === typeof dp[i][j]) {
ret[(CSL.DATE_PARTS[j] + exts[i])] = dp[i][j];
} else {
ret[(CSL.DATE_PARTS[j] + exts[i])] = parseInt(dp[i][j], 10);
}
}
}

I just noticed this today. Not sure how long this has been an issue.

The gist: If given a date-parts array with the following shape, the parser resolves to NaN for the empty strings.

const dateparts = [
  '2018',
  '',
  '',
];

My suggestions:

Quick fix: Instead of just checking to see if the value is undefined (which should not be done using typeof to begin with), consider checking the result of parseInt.

So, for example:

if (!isNaN(parseInt(dp[i][j], 10)) {
// A parsable number
} else {
// Not a parsable number
}

Better fix: The function itself is extraordinarily complex for what it does. So perhaps consider rewriting it to something a bit simpler? The cyclomatic complexity of this function is way way way way too large. It took me 5 mins just to be able to understand what's going on in the function which is problem and should not happen.

Thanks in advance.

small-caps not working in some styles

In some styles this

<span style="font-variant: small-caps;">Here</span>

turns into this:

&#60;span Style=“font-Variant:small-caps;”&#62;Here&#60;/span&#62;

(For example AAA style, works fine in APA).

CSL-JSON date field format

The spec of CSL and the citeproc-js docs seem to be conflicting on this matter:

csl

What the schema seems to specify: (Note that the schema "is not yet fully normative, and care must be taken to ensure compatibility with other tools built around CSL-JSON.")

"archived": {
     "date-parts": [[ 2005, 4, 12 ]]
}
"issued": {
     "date-parts": [[ 2000, 3, 15 ], [2000, 3, 17]]
}

citeproc-js

Examples from citeproc-js docs:

"archived": [
     {
             "date-parts": [ 2005, 4, 12 ]
     }
],
"issued": [
     {
             "date-parts": [[ 2000, 3, 15 ], [2000, 3, 17]]
     }
]

Other specs

Edit

A lot of these standards don't have the double array in the first csl spec format example, and I strongly recommend that somewhat hybrid format.

[Bug] - Setting undefined values to Item causes reproducible uncaught exceptions to be thrown

There are two specific locations that set item fields to undefined when those specific fields aren't available.

The first is here: https://github.com/Juris-M/citeproc-js/blob/master/citeproc.js#L2849

The second is here: https://github.com/Juris-M/citeproc-js/blob/master/citeproc.js#L2897

This causes very reproducible instances of uncaught exceptions being thrown, specifically at this location: https://github.com/Juris-M/citeproc-js/blob/master/citeproc.js#L10667

Error message is: "Cannot set property 'top' of undefined"

I think the check is backwards, no? Any thoughts?

Multiple uppercase letters for author name

I'm encountering this unusual name format:
Osman-Gani || AAhad M.

(Note the double uppercase letter at the start of AAhad.)

Is there a way to prevent the processor from re-formatting this as:
Aahad
?

console.log() lines in 1.1.161

1.1.161 introduced a couple stray console.log() lines, which broke output for some items in the Zotero beta:

console.log("XX10: " + this.Item.id + " " + JSON.stringify(value));

(The commit also incorrectly calls this release 1.1.166 and left the version number in citeproc.js as 1.1.160.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.