npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@customcommander/ris

v5.1.2

Published

Read/write bibliographic records in RIS format.

Downloads

41

Readme

GitHub Workflow Status npm (scoped) npm bundle size (scoped)

RIS

Read/write bibliographic records in RIS format.

Getting Started

npm i @customcommander/ris

Node.js

const {read} = require('@customcommander/ris');

read(`
TY  - JOUR
TI  - Foo
ER  - 
TY  - BOOK
TI  - Bar
ER  - 
TY  - CHAP
TI  - Baz
ER  - 
`);
//=> [ {TY: ['JOUR'], TI: ['Foo']}
//=> , {TY: ['BOOK'], TI: ['Bar']}
//=> , {TY: ['CHAP'], TI: ['Baz']}]

Browser

<script src="./node_modules/@customcommander/ris/dist/browser.min.js"></script>

<script>
RIS.read(`
TY  - JOUR
TI  - Foo
ER  - 
TY  - BOOK
TI  - Bar
ER  - 
TY  - CHAP
TI  - Baz
ER  - 
`);
//=> [ {TY: ['JOUR'], TI: ['Foo']}
//=> , {TY: ['BOOK'], TI: ['Bar']}
//=> , {TY: ['CHAP'], TI: ['Baz']}]
</script>

Reading RIS

The read function returns an array of objects (one per reference). Each key in an object is named after the corresponding RIS tag and holds the values for each entry for that tag. (Some tags can appear multiple times.)

The function returns null if it cannot parse the content. Please check that the content is correctly formatted as per the RIS specification. If you think this is a bug please raise an issue.

Additional Processing

Some tags like DA or RP have special formatting rules. The parser supports them but won't enforce them meaning that any content that doesn't comply is returned as is.

| Tag | Content (example) | After processing | |:----|:------------------------|:------------------------------------------------------------------------------| | DA | 2020/06/25/ | {"year": "2020", "month": "06", "day": "25", "info": ""} | | DA | /// | {"year": "" , "month": "" , "day": "" , "info": ""} | | DA | /06// | {"year": "" , "month": "06", "day": "" , "info": ""} | | DA | 2020//25/Conf | {"year": "2020", "month": "" , "day": "25", "info": "Conf"} | | RP | IN FILE | {"status": "IN FILE"} | | RP | NOT IN FILE | {"status": "NOT IN FILE"} | | RP | ON REQUEST (06/26/2020) | {"status": "ON REQUEST","date": {"year": "2020", "month": "06", "day": "26"}} |

Writing RIS

The library exposes a write function that takes an input of the same type than the output of the read function.

write([ { "TY": ["JOUR"]
        , "TI": ["Hello World!"]}

      , { "TY": ["JOUR"]
        , "TI": ["Apollo 11"]
        , "DA": [{ "year": "1969"
                 , "month": "07"
                 , "day": "20"
                 , "info": "Moon"}]}]);
// => TY  - JOUR
// => TI  - Hello World!
// => ER  - 
// =>
// => TY  - JOUR
// => TI  - Apollo 11
// => DA  - 1969/07/20/Moon
// => ER  - 
// =>

If the input isn't an array an empty string is returned. Each element is validated first and skipped if not valid so it is possible to get an empty string even with a non-empty array.

Each element must be a key/value pairs object:

  • Each key must be a two-letter capital word. The second letter may be a number.
  • Each value must be an array of at least one non-empty string.

Some keys have additional rules.

TY

This is the only required key. Must be set to an array of exactly one non-empty string e.g.,

{ "TY": [ "JOUR" ] }

DA

Must be set to an array of exactly one element which can be either a non-empty string or an object e.g.,

{ "TY": [ "JOUR" ]
, "DA": [ "1969/07/20/Moon" ] }

// or

{ "TY": [ "JOUR" ]
, "DA": [ { "year":  "<non-empty string>" /* Required. */
          , "month": "<non-empty string>" /* Optional. */
          , "day":   "<non-empty string>" /* Optional. */
          , "info":  "<non-empty string>" /* Optional. */}]}

AU, A1, A2, A3, A4 & TA

In addition to non-empty strings, arrays for these keys can also have objects e.g.,

{ "TY": [ "JOUR" ]
, "AU": [ "Doe, John"
        , { "last_name":  "<non-empty string>" /* Required. */
          , "first_name": "<non-empty string>" /* Optional. */
          , "initials":   "<non-empty string>" /* Optional. */
          , "suffix":     "<non-empty string>" /* Optional. */}]}

RP

Must be set to an array of exactly one element which can be either a non-empty string or an object e.g.,

{ "TY": [ "JOUR" ]
, "RP": ["<non-empy string>"] }

// or

{ "TY": [ "JOUR" ]
, "RP": [{ "status": "<non-empty string>" /* Required. */
         , "year":   "<non-empty string>" /* Optional. */
         , "month":  "<non-empty string>" /* Optional. */
         , "day":    "<non-empty string>" /* Optional. */}] }

ER

This is the only reserved tag. Any value will be ignored.

Mendeley

Generate Mendeley References From RIS

Bibliographic records in RIS format can be converted to Mendeley references:

toMendeley(`
TY  - JOUR
TI  - Mission to the Moon
AU  - Armstrong, Neil
DA  - 1969/07/20
ER  - 
`);
//=> [{ type: 'journal'
//=>  , authors: [{last_name: 'Armstrong', first_name: 'Neil'}]
//=>  , accessed: '1969-07-20'
//=>  , title: 'Mission to the Moon' }]

RIS Conversion Table

The following table shows which RIS fields are supported by the Mendeley Reference Manager.

| RIS Type | RIS Entry | Mendeley | |:---------|:----------|:-----------------------------------| | any | A1 | authors | | any | A2 | editors | | any | A3 | authors | | any | A4 | authors | | any | AB | abstract | | any | AN | identifiers.pmid | | any | AU | authors | | PAT | C6 | patent_legal_status | | any | CY | city | | any | DA | accessed | | any | DO | identifiers.doi | | any | ET | edition | | any | IS | issue | | any | KW | keywords | | any | L1 | websites | | any | L4 | websites | | any | LA | language | | any | LB | tags | | PAT | M1 | patent_application_number | | any | N1 | notes | | any | PB | publisher | | any | PY | year | | any | RN | notes | | any | SE | chapter | | any | SN | identifiers.isbn | | JFULL | SN | identifiers.issn | | JOUR | SN | identifiers.issn | | any | SP | pages | | any | ST | short_title | | any | T2 | source | | any | T3 | series | | any | TA | authors | | any | TI | title | | BILL | TY | type (as bill) | | BOOK | TY | type (as book) | | CASE | TY | type (as case) | | CHAP | TY | type (as book_section) | | COMP | TY | type (as computer_program) | | CONF | TY | type (as conference_proceedings) | | ENCYC | TY | type (as encyclopedia_article) | | GEN | TY | type (as generic) | | HEAR | TY | type (as hearing) | | ICOMM | TY | type (as web_page) | | JFULL | TY | type (as journal) | | JOUR | TY | type (as journal) | | MGZN | TY | type (as magazine_article) | | MPCT | TY | type (as film) | | NEWS | TY | type (as newspaper_article) | | PAT | TY | type (as patent) | | RPRT | TY | type (as report) | | STAT | TY | type (as statute) | | THES | TY | type (as thesis) | | UNPB | TY | type (as working_paper) | | others | TY | type (as generic) | | any | UR | websites | | any | VL | volume | | RPRT | VL | series_number |

Errors

Each Mendeley reference is validated before it is returned so toMendeley can return an empty array.

If the RIS content cannot be parsed toMendeley returns null.

Generate RIS From Mendeley References

It is also possible to generate RIS records from Mendeley references: (using the above table)

fromMendeley([{ type: 'journal'
              , title: 'Moon 69'
              , year: 1969
              , authors: [{last_name: 'Armstrong', first_name: 'Neil'}]
              , identifiers: {doi: 'doi/123'}}]);

//=> TY  - JOUR
//=> TI  - Moon 69
//=> PY  - 1969
//=> AU  - Armstrong, Neil
//=> DO  - doi/123
//=> ER  - 
//=>

Errors

The fromMendeley returns null if the input is not an array or if all elements are not valid Mendeley references. Otherwise invalid elements are ignored.

Development

The following command will:

  1. Compile the grammar.
  2. Test the grammar against the dev.ris file.
  3. Output the result to the standard output.
  4. Write the output to out.txt. (This file is ignored by Git.)
make sample

Further Resources

  1. See my interpretation of the RIS specification.