433 lines
11 KiB
JavaScript
433 lines
11 KiB
JavaScript
|
{
|
|||
|
"translatorID": "3f50aaac-7acc-4350-acd0-59cb77faf620",
|
|||
|
"label": "Wikipedia Citation Templates",
|
|||
|
"creator": "Simon Kornblith",
|
|||
|
"target": "txt",
|
|||
|
"minVersion": "1.0.0b4.r1",
|
|||
|
"maxVersion": "",
|
|||
|
"priority": 100,
|
|||
|
"displayOptions": {
|
|||
|
"exportCharset": "UTF-8"
|
|||
|
},
|
|||
|
"inRepository": true,
|
|||
|
"translatorType": 2,
|
|||
|
"lastUpdated": "2023-11-05 21:29:00"
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
***** BEGIN LICENSE BLOCK *****
|
|||
|
|
|||
|
Copyright © 2017-2019 Simon Kornblith
|
|||
|
|
|||
|
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 *****
|
|||
|
*/
|
|||
|
|
|||
|
var fieldMap = {
|
|||
|
edition: "edition",
|
|||
|
publisher: "publisher",
|
|||
|
doi: "DOI",
|
|||
|
isbn: "ISBN",
|
|||
|
issn: "ISSN",
|
|||
|
conference: "conferenceName",
|
|||
|
volume: "volume",
|
|||
|
issue: "issue",
|
|||
|
pages: "pages",
|
|||
|
number: "episodeNumber"
|
|||
|
};
|
|||
|
|
|||
|
var typeMap = {
|
|||
|
book: "Cite book",
|
|||
|
bookSection: "Cite book",
|
|||
|
journalArticle: "Cite journal",
|
|||
|
magazineArticle: "Cite news",
|
|||
|
newspaperArticle: "Cite news",
|
|||
|
thesis: "Cite paper",
|
|||
|
letter: "Cite",
|
|||
|
manuscript: "Cite book",
|
|||
|
interview: "Cite interview",
|
|||
|
film: "Cite AV media",
|
|||
|
artwork: "Cite",
|
|||
|
webpage: "Cite web",
|
|||
|
report: "Cite conference",
|
|||
|
bill: "Cite",
|
|||
|
hearing: "Cite",
|
|||
|
patent: "Cite",
|
|||
|
statute: "Cite",
|
|||
|
email: "Cite email",
|
|||
|
map: "Cite",
|
|||
|
blogPost: "Cite web",
|
|||
|
instantMessage: "Cite",
|
|||
|
forumPost: "Cite web",
|
|||
|
audioRecording: "Cite",
|
|||
|
presentation: "Cite paper",
|
|||
|
videoRecording: "Cite AV media",
|
|||
|
tvBroadcast: "Cite episode",
|
|||
|
radioBroadcast: "Cite episode",
|
|||
|
podcast: "Cite podcast",
|
|||
|
computerProgram: "Cite",
|
|||
|
conferencePaper: "Cite conference",
|
|||
|
document: "Cite",
|
|||
|
encyclopediaArticle: "Cite encyclopedia",
|
|||
|
dictionaryEntry: "Cite encyclopedia"
|
|||
|
};
|
|||
|
|
|||
|
function formatAuthors(authors, useTypes) {
|
|||
|
var text = "";
|
|||
|
for (var i = 0; i < authors.length; i++) {
|
|||
|
var author = authors[i];
|
|||
|
text += ", ";
|
|||
|
if (author.firstName) text += author.firstName;
|
|||
|
if (author.firstName && author.lastName) text += " ";
|
|||
|
if (author.lastName) text += author.lastName;
|
|||
|
if (useTypes) text += " (" + Zotero.Utilities.getLocalizedCreatorType(author.creatorType) + ")";
|
|||
|
}
|
|||
|
return text.substr(2);
|
|||
|
}
|
|||
|
|
|||
|
function formatFirstAuthor(authors, useTypes) {
|
|||
|
var firstCreator = authors.shift();
|
|||
|
var field = firstCreator.lastName;
|
|||
|
if (firstCreator.lastName && firstCreator.firstName) field += ", ";
|
|||
|
field += firstCreator.firstName;
|
|||
|
if (useTypes) field += " (" + Zotero.Utilities.getLocalizedCreatorType(firstCreator.creatorType) + ")";
|
|||
|
return field;
|
|||
|
}
|
|||
|
|
|||
|
function formatDate(date) {
|
|||
|
date = date.substr(0, date.indexOf(" "));
|
|||
|
if (date.substr(4, 3) == "-00") {
|
|||
|
date = date.substr(0, 4);
|
|||
|
}
|
|||
|
else if (date.substr(7, 3) == "-00") {
|
|||
|
date = date.substr(0, 7);
|
|||
|
}
|
|||
|
return date;
|
|||
|
}
|
|||
|
|
|||
|
function doExport() {
|
|||
|
var first = true;
|
|||
|
let item;
|
|||
|
// eslint-disable-next-line no-cond-assign
|
|||
|
while (item = Zotero.nextItem()) {
|
|||
|
// determine type
|
|||
|
var type = typeMap[item.itemType];
|
|||
|
if (!type) type = "Cite";
|
|||
|
|
|||
|
var properties = {};
|
|||
|
var editors = [];
|
|||
|
var translators = [];
|
|||
|
var interviewers = [];
|
|||
|
for (var wikiField in fieldMap) {
|
|||
|
var zoteroField = fieldMap[wikiField];
|
|||
|
if (item[zoteroField]) properties[wikiField] = item[zoteroField];
|
|||
|
}
|
|||
|
|
|||
|
if (item.creators && item.creators.length) {
|
|||
|
if (type == "Cite episode") {
|
|||
|
// now add additional creators
|
|||
|
properties.credits = formatAuthors(item.creators, true);
|
|||
|
}
|
|||
|
else if (type == "Cite AV media") {
|
|||
|
properties.people = "";
|
|||
|
|
|||
|
// make first creator first, last
|
|||
|
properties.people = formatFirstAuthor(item.creators, true);
|
|||
|
// now add additional creators
|
|||
|
if (item.creators.length) properties.people += ", " + formatAuthors(item.creators, true);
|
|||
|
|
|||
|
// use type
|
|||
|
if (item.type) {
|
|||
|
properties.medium = item.type;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (type == "Cite email") {
|
|||
|
// get rid of non-authors
|
|||
|
for (var i = 0; i < item.creators.length; i++) {
|
|||
|
if (item.creators[i].creatorType != "author") {
|
|||
|
// drop contributors
|
|||
|
item.creators.splice(i--, 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// make first authors first, last
|
|||
|
properties.author = formatFirstAuthor(item.creators);
|
|||
|
// add supplemental authors
|
|||
|
if (item.creators.length) {
|
|||
|
properties.author += ", " + formatAuthors(item.creators);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (type == "Cite interview") {
|
|||
|
// check for an interviewer or translator
|
|||
|
|
|||
|
for (let i = 0; i < item.creators.length; i++) {
|
|||
|
if (item.creators[i].creatorType == "translator") {
|
|||
|
translators.push(item.creators.splice(i--, 1)[0]);
|
|||
|
}
|
|||
|
else if (item.creators[i].creatorType == "interviewer") {
|
|||
|
interviewers.push(item.creators.splice(i--, 1)[0]);
|
|||
|
}
|
|||
|
else if (item.creators[i].creatorType == "contributor") {
|
|||
|
// drop contributors
|
|||
|
item.creators.splice(i--, 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// interviewers
|
|||
|
if (interviewers.length) {
|
|||
|
properties.interviewer = formatAuthors([interviewers.shift()]);
|
|||
|
if (interviewers.length) properties.cointerviewers = formatAuthors(interviewers);
|
|||
|
}
|
|||
|
// translators
|
|||
|
if (translators.length) {
|
|||
|
properties.cointerviewers = (properties.cointerviewers ? properties.cointerviewers + ", " : "");
|
|||
|
properties.cointerviewers += formatAuthors(translators);
|
|||
|
}
|
|||
|
// interviewees
|
|||
|
if (item.creators.length) {
|
|||
|
// take up to 4 interviewees
|
|||
|
let i = 1;
|
|||
|
let interviewee;
|
|||
|
while ((interviewee = item.creators.shift()) && i <= 4) {
|
|||
|
var lastKey = "last";
|
|||
|
var firstKey = "first";
|
|||
|
if (i != 1) {
|
|||
|
lastKey += i;
|
|||
|
firstKey += i;
|
|||
|
}
|
|||
|
properties[lastKey] = interviewee.lastName;
|
|||
|
properties[firstKey] = interviewee.firstName;
|
|||
|
i += 1;
|
|||
|
}
|
|||
|
}
|
|||
|
// medium
|
|||
|
if (item.medium) {
|
|||
|
properties.type = item.medium;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
// check for an editor or translator
|
|||
|
editors = [];
|
|||
|
translators = [];
|
|||
|
for (let i = 0; i < item.creators.length; i++) {
|
|||
|
var creator = item.creators[i];
|
|||
|
if (creator.creatorType == "translator") {
|
|||
|
translators.push(item.creators.splice(i--, 1)[0]);
|
|||
|
}
|
|||
|
else if (creator.creatorType == "editor") {
|
|||
|
editors.push(item.creators.splice(i--, 1)[0]);
|
|||
|
}
|
|||
|
else if (creator.creatorType == "contributor") {
|
|||
|
// drop contributors
|
|||
|
item.creators.splice(i--, 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// editors
|
|||
|
var others = "";
|
|||
|
if (editors.length) {
|
|||
|
var editorText = formatAuthors(editors) + (editors.length == 1 ? " (ed.)" : " (eds.)");
|
|||
|
if (item.itemType == "bookSection" || type == "Cite conference" || type == "Cite encyclopedia") {
|
|||
|
// as per docs, use editor only for chapters
|
|||
|
properties.editors = editorText;
|
|||
|
}
|
|||
|
else {
|
|||
|
others = editorText;
|
|||
|
}
|
|||
|
}
|
|||
|
// translators
|
|||
|
if (translators.length) {
|
|||
|
if (others) others += ", ";
|
|||
|
others += formatAuthors(translators) + " (trans.)";
|
|||
|
}
|
|||
|
|
|||
|
// We need to be certain that these come out in the right order, so
|
|||
|
// deal with it when actually writing output
|
|||
|
if (item.creators.length) {
|
|||
|
properties.authors = item.creators.map(function (c) {
|
|||
|
return {
|
|||
|
last: c.lastName,
|
|||
|
first: c.firstName
|
|||
|
};
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
// attach others
|
|||
|
if (others) {
|
|||
|
properties.others = others;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (item.itemType == "bookSection") {
|
|||
|
properties.title = item.publicationTitle;
|
|||
|
properties.chapter = item.title;
|
|||
|
}
|
|||
|
else {
|
|||
|
properties.title = item.title;
|
|||
|
|
|||
|
if (type == "Cite journal") {
|
|||
|
properties.journal = item.publicationTitle;
|
|||
|
}
|
|||
|
else if (type == "Cite conference") {
|
|||
|
properties.booktitle = item.publicationTitle;
|
|||
|
}
|
|||
|
else if (type == "Cite encyclopedia") {
|
|||
|
properties.encyclopedia = item.publicationTitle;
|
|||
|
}
|
|||
|
else {
|
|||
|
properties.work = item.publicationTitle;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (type == "Cite web" && item.type) {
|
|||
|
properties.format = item.type;
|
|||
|
}
|
|||
|
|
|||
|
if (item.place) {
|
|||
|
if (type == "Cite episode") {
|
|||
|
properties.city = item.place;
|
|||
|
}
|
|||
|
else {
|
|||
|
properties.location = item.place;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (item.series) {
|
|||
|
properties.series = item.series;
|
|||
|
}
|
|||
|
else if (item.seriesTitle) {
|
|||
|
properties.series = item.seriesTitle;
|
|||
|
}
|
|||
|
else if (item.seriesText) {
|
|||
|
properties.series = item.seriesText;
|
|||
|
}
|
|||
|
|
|||
|
// Don't include access date for journals with no URL
|
|||
|
if (item.accessDate && !(item.itemType == 'journalArticle' && !item.url)) {
|
|||
|
properties["access-date"] = formatDate(item.accessDate);
|
|||
|
}
|
|||
|
|
|||
|
if (item.date) {
|
|||
|
if (type == "Cite email") {
|
|||
|
properties.senddate = formatDate(item.date);
|
|||
|
}
|
|||
|
else {
|
|||
|
var date = Zotero.Utilities.strToDate(item.date);
|
|||
|
if (date.year != undefined) {
|
|||
|
var mm = "00";
|
|||
|
if (date.month !== undefined) {
|
|||
|
mm = date.month;
|
|||
|
mm = ZU.lpad(mm + 1, '0', 2);
|
|||
|
}
|
|||
|
|
|||
|
var dd = "00";
|
|||
|
if (date.day !== undefined) {
|
|||
|
dd = ZU.lpad(date.day, '0', 2);
|
|||
|
}
|
|||
|
|
|||
|
var yyyy = ZU.lpad(date.year.toString(), '0', 4);
|
|||
|
date = formatDate(yyyy + '-' + mm + '-' + dd + ' ');
|
|||
|
|
|||
|
if (type == "Cite email") {
|
|||
|
properties.senddate = date;
|
|||
|
}
|
|||
|
else {
|
|||
|
properties.date = date;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (item.runningTime) {
|
|||
|
if (type == "Cite episode") {
|
|||
|
properties.minutes = item.runningTime;
|
|||
|
}
|
|||
|
else {
|
|||
|
properties.time = item.runningTime;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (item.url && item.accessDate) {
|
|||
|
if (item.itemType == "bookSection") {
|
|||
|
properties.chapterurl = item.url;
|
|||
|
}
|
|||
|
else {
|
|||
|
properties.url = item.url;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (properties.pages) {
|
|||
|
properties.pages = properties.pages.replace(/[^0-9]+/, "–"); // separate page numbers with en dash
|
|||
|
}
|
|||
|
|
|||
|
if (item.extra) {
|
|||
|
// automatically fill in PMCID, PMID, and JSTOR fields
|
|||
|
var extraFields = {
|
|||
|
pmid: /^PMID\s*:\s*([0-9]+)/m,
|
|||
|
pmc: /^PMCID\s*:\s*((?:PMC)?[0-9]+)/m
|
|||
|
};
|
|||
|
|
|||
|
for (let f in extraFields) {
|
|||
|
let match = item.extra.match(extraFields[f]);
|
|||
|
if (match) properties[f] = match[1];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (item.url) {
|
|||
|
//try to extract missing fields from URL
|
|||
|
var libraryURLs = {
|
|||
|
pmid: /www\.ncbi\.nlm\.nih\.gov\/pubmed\/([0-9]+)/i,
|
|||
|
pmc: /www\.ncbi\.nlm\.nih\.gov\/pmc\/articles\/((?:PMC)?[0-9]+)/i,
|
|||
|
jstor: /www\.jstor\.org\/stable\/([^?#]+)/i
|
|||
|
};
|
|||
|
|
|||
|
for (let f in libraryURLs) {
|
|||
|
if (properties[f]) continue; //don't overwrite from extra field
|
|||
|
let match = item.url.match(libraryURLs[f]);
|
|||
|
if (match) properties[f] = match[1];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// write out properties
|
|||
|
Zotero.write((first ? "" : "\r\n") + "{{" + type);
|
|||
|
for (var key in properties) {
|
|||
|
if (!properties[key]) continue;
|
|||
|
|
|||
|
if (key == 'authors') {
|
|||
|
var index = properties.authors.length > 1;
|
|||
|
for (let i = 0; i < properties.authors.length; i++) {
|
|||
|
Zotero.write('| last' + (i || index ? i + 1 : '') + ' = ' + properties.authors[i].last);
|
|||
|
if (properties.authors[i].first) {
|
|||
|
Zotero.write('| first' + (i || index ? i + 1 : '') + ' = ' + properties.authors[i].first);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
Zotero.write("| " + key + " = " + escapeWiki(properties[key]));
|
|||
|
}
|
|||
|
}
|
|||
|
Zotero.write("}}");
|
|||
|
|
|||
|
first = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function escapeWiki(markup) {
|
|||
|
return markup.replace('|', '{{!}}');
|
|||
|
}
|