Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
332 lines (283 sloc) 9.1 KB
{
"translatorID": "0a61e167-de9a-4f93-a68a-628b48855909",
"translatorType": 8,
"label": "Crossref REST",
"creator": "Martynas Bagdonas",
"target": "",
"minVersion": "5.0.0",
"maxVersion": null,
"priority": 90,
"inRepository": true,
"browserSupport": "gcsibv",
"lastUpdated": "2018-06-16 12:00:00"
}
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2018
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
// Based on CrossRef.js (by Simon Kornblith), which uses OpenURL API
// This translator uses the newer REST API
// https://github.com/Crossref/rest-api-doc
// https://github.com/Crossref/rest-api-doc/blob/master/api_format.md
// REST API documentation not always reflect the actual API
// and some fields are undocumented.
// All Crossref item types can be retrieved at http://api.crossref.org/types
function removeUnsupportedMarkup(text) {
let markupRE = /<(\/?)(\w+)[^<>]*>/gi;
let supportedMarkup = ['i', 'b', 'sub', 'sup', 'sc'];
let transformMarkup = {
'scp': {
open: '<span style="font-variant:small-caps;">',
close: '</span>'
}
};
return text.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, '$1') // Remove CDATA markup
.replace(markupRE, function (m, close, name) {
name = name.toLowerCase();
if (supportedMarkup.includes(name)) {
return (close ? '</' : '<') + name + '>';
}
let newMarkup = transformMarkup[name.toLowerCase()];
if (newMarkup) {
return close ? newMarkup.close : newMarkup.open;
}
return '';
});
}
function fixAuthorCapitalization(string) {
// Try to use capitalization function from Zotero Utilities,
// because the current one doesn't support unicode names.
// Can't fix this either because ZU.XRegExp.replace is
// malfunctioning when calling from translators.
if (ZU.capitalizeName) return ZU.capitalizeName(string);
if (typeof string === "string" && string.toUpperCase() === string) {
string = string.toLowerCase().replace(/\b[a-z]/g, function (m) {
return m[0].toUpperCase();
});
}
return string;
}
function parseCreators(result, item, typeOverrideMap) {
let types = ['author', 'editor', 'chair', 'translator'];
for (let i = 0; i < types.length; i++) {
let type = types[i];
if (result[type]) {
let creatorType = null;
if (typeOverrideMap && typeOverrideMap[type] !== undefined) {
creatorType = typeOverrideMap[type];
}
else if (type === "author" || type === "editor" || type === "translator") {
creatorType = type;
}
else {
creatorType = "contributor";
}
if (!creatorType) continue;
for (let j = 0; j < result[type].length; j++) {
let creator = {};
creator.creatorType = creatorType;
if (result[type].name) { // Organization
creator.fieldMode = 1;
creator.lastName = result[type][j].name;
}
else {
creator.firstName = fixAuthorCapitalization(result[type][j].given);
creator.lastName = fixAuthorCapitalization(result[type][j].family);
if (!creator.firstName) creator.fieldMode = 1;
}
item.creators.push(creator);
}
}
}
}
function processCrossref(json) {
json = JSON.parse(json);
for (let i = 0; i < json.message.items.length; i++) {
let result = json.message.items[i];
let item = null;
// Journal article
if (['journal-article'].includes(result.type)) {
item = new Zotero.Item("journalArticle");
if (result['container-title']) item.publicationTitle = result['container-title'][0];
if (result['short-container-title']
&& result['short-container-title'][0] !== result['container-title'][0]) {
item.journalAbbreviation = result['short-container-title'][0];
}
item.volume = result.volume;
item.issue = result.issue;
if (result.ISBN) item.ISBN = result.ISBN[0];
if (result.ISSN) item.ISSN = result.ISSN[0];
}
// Book
else if (['book', 'book-series', 'book-set', 'book-track', 'monograph', 'reference-book']
.includes(result.type)) {
item = new Zotero.Item("book");
item.publisher = result.publisher;
item.place = result['publisher-location'];
if (result.ISBN) item.ISBN = result.ISBN[0];
}
// Book section
else if (['book-chapter', 'book-part', 'book-section', 'reference-entry']
.includes(result.type)) {
item = new Zotero.Item("bookSection");
item.publisher = result.publisher;
item.place = result['publisher-location'];
if (result.ISBN) item.ISBN = result.ISBN[0];
}
// Report
else if (['dataset', 'posted-content', 'report', 'report-series', 'standard']
.includes(result.type)) {
item = new Zotero.Item("report");
item.institution = result.publisher;
item.place = result['publisher-location'];
item.seriesTitle = result['container-title'];
}
// Conference paper
else if (['proceedings-article'].includes(result.type)) {
item = new Zotero.Item("conferencePaper");
item.proceedingsTitle = result['container-title'];
item.publisher = result.publisher;
if (result.event) {
item.conferenceName = result.event.name;
item.place = result.event.location;
}
if (result.ISBN) item.ISBN = result.ISBN[0];
}
// Thesis
else if (['dissertation'].includes(result.type)) {
item = new Zotero.Item("thesis");
item.university = result.publisher;
item.place = result['publisher-location'];
}
else {
return;
}
// edited-book, standard-series - ignore, because Crossref has zero results for this type
// component, journal, journal-issue, journal-volume, other, proceedings - ignore,
// because Zotero doesn't have equivalent item types.
item.abstractNote = result.abstract;
parseCreators(result, item);
// Contains the earliest of: published-online, published-print, content-created
let pubDate = result['issued'];
if (pubDate && pubDate['date-parts'][0]) {
let year = pubDate['date-parts'][0][0];
let month = pubDate['date-parts'][0][1];
let day = pubDate['date-parts'][0][2];
if (year) {
if (month) {
if (day) {
item.date = year + "-" + month + "-" + day;
}
else {
item.date = month + "/" + year;
}
}
else {
item.date = year;
}
}
}
item.pages = result.page;
if (result.DOI) {
if (ZU.fieldIsValidForType('DOI', item.itemType)) {
item.DOI = result.DOI;
}
// add DOI to extra for unsupprted items
else {
if (item.extra) {
item.extra += '\nDOI: ' + result.DOI;
}
else {
item.extra = 'DOI: ' + result.DOI;
}
}
}
// result.URL is always http://dx.doi.org/..
if (result.link && result.link.URL) item.url = result.link.URL;
if (result.title && result.title[0]) {
item.title = result.title[0];
if (result.subtitle && result.subtitle[0]) {
// Don't duplicate subtitle if it already exists in title
if (item.title.toLowerCase().indexOf(result.subtitle[0].toLowerCase()) < 0) {
item.title += ': ' + result.subtitle[0];
}
}
item.title = removeUnsupportedMarkup(item.title);
}
// Check if there are potential issues with character encoding and try to fix it
// e.g. 10.1057/9780230391116.0016 (en dash in title is presented as <control><control>â)
for (let field in item) {
if (typeof item[field] !== 'string') continue;
// Check for control characters that should never be in strings from Crossref
if (/[\u007F-\u009F]/.test(item[field])) {
item[field] = decodeURIComponent(escape(item[field]));
}
item[field] = ZU.unescapeHTML(item[field]);
}
item.libraryCatalog = 'Crossref';
item.complete();
}
}
function detectSearch(item) {
return false;
}
function doSearch(item) {
// Reduce network traffic by selecting only required fields
let selectedFields = [
'type',
'container-title',
'short-container-title',
'volume',
'issue',
'ISBN',
'ISSN',
'publisher',
'publisher-location',
'event',
'abstract',
'issued',
'page',
'DOI',
'link',
'title',
'subtitle',
'author',
'editor',
'chair',
'translator'
];
let query = null;
if (item.DOI) {
if (Array.isArray(item.DOI)) {
query = '?filter=doi:' + item.DOI.map(x => ZU.cleanDOI(x)).filter(x => x).join(',doi:');
} else {
query = '?filter=doi:' + ZU.cleanDOI(item.DOI);
}
}
else if (item.query) {
query = '?query.bibliographic=' + encodeURIComponent(item.query);
}
else return;
query += '&select=' + selectedFields.join(',');
if (Z.getHiddenPref('CrossrefREST.email')) {
query += '&mailto=' + Z.getHiddenPref('CrossrefREST.email');
}
ZU.doGet('https://api.crossref.org/works/' + query, function (responseText) {
processCrossref(responseText);
});
}
/** BEGIN TEST CASES **/
var testCases = [];
/** END TEST CASES **/
You can’t perform that action at this time.