// ==UserScript==
// @name wiki-reference
// @namespace torvin
// @include https://www.ncbi.nlm.nih.gov/pubmed/*
// @include http://www.ncbi.nlm.nih.gov/pubmed/*
// @include http://adsabs.harvard.edu/abs/*
// @include http://adsabs.harvard.edu/doi/*
// @include http://ufn.ru/ru/articles/*
// @include http://books.google.*/books*
// @include https://books.google.*/books*
// @include http://www.sciencedirect.com/science/article/*
// @include http://gen.lib.rus.ec/scimag/*
// @include http://onlinelibrary.wiley.com/doi/*
// @include http://www.jstor.org/stable/*
// @include http://www.jstor.org/discover/*
// @include http://projecteuclid.org/euclid.*
// @include https://projecteuclid.org/euclid.*
// @include http://link.springer.com/*
// @include http://www.mathnet.ru/php/archive.phtml*wshow=paper*
// @include http://elibrary.ru/item.asp*
// @require https://code.jquery.com/jquery-2.1.1.min.js
// @version 1.8.8
// @description Позволяет генерировать ссылки в формате {{статья}} и {{книга}} для ру-вики
// @grant GM_xmlhttpRequest
// @grant GM_setClipboard
// ==/UserScript==
const templates = {
article: 'статья',
book: 'книга',
};
const templateAdditionalArgs = {
'статья': [ 'ref', 'archiveurl', 'archivedate' ],
'книга': [ 'ref' ],
};
const refTemplateParamOrder = [
'автор', 'часть', 'ссылка часть', 'заглавие', 'ссылка', 'ответственный',
'издание', 'издательство', 'год', 'серия', 'том', 'номер', 'страницы', 'страниц',
'язык', 'doi', 'bibcode', 'arxiv', 'isbn', 'archiveurl', 'archivedate', 'ref'
];
var Template = function(name) {
var attrs = [];
this.add = function(name, value) {
attrs.push({
name: name,
value: value
});
return this;
};
this.get = function(name) {
return attrs.filter(a => a.name === name).map(a => a.value)[0];
}
this.getParamNames = function() {
return attrs.map(a => a.name);
}
this.getName = function() {
return name;
}
var getAttr = function(x) {
return "|" + x.name + (x.value === undefined ? "" : " = " + x.value);
};
this.toWiki = function() {
if (attrs.length == 1)
return "{{" + name + getAttr(attrs[0]) + "}}";
else
return "{{" + name + "\n" + attrs.map(a => " " + getAttr(a)).join("\n") + "\n}}";
};
};
var getText = function(node) {
return node instanceof Element ? node.textContent : node;
};
var clone = function(obj) {
var target = {};
for (var i in obj) {
var value = obj[i];
if (value instanceof Function)
;
else if (typeof value == 'string')
;
else
value = clone(value);
target[i] = value;
}
return target;
}
var getWpFromXml = function(name, rules, xml) {
var article = new Template(name);
for(var name in rules) {
var rule = rules[name];
article.add(name, rule.const ||
Array.slice(xml.querySelectorAll(rule.selector)).map(function(node) {
if (rule.map)
node = rule.map(node);
return Array.isArray(node) ? node.map(getText) : getText(node);
}).map(function(item) {
return rule.mapText ? rule.mapText(item) : item;
}).join(rule.separator || ', ')
);
}
return getRef(article);
};
var Parser = function(sourceText, index, tokens) {
var _match;
var _isEof;
//var _tokenRegex = /(\s*)(\{|\}|,|=|\\\W|\\[\w]+|[^\{\},\\=\s])/g;
var _tokenRegex = new RegExp("(\\s*)(" + tokens.map(function(x) { return x.source || x }).join('|') + ")", 'g');
_tokenRegex.lastIndex = index;
var getToken = function() {
if (_isEof)
throw new Error("EOF");
var index = _tokenRegex.lastIndex;
var res = _tokenRegex.exec(sourceText);
if (!res) {
_isEof = true;
return null;
}
_match = {
match: res[0],
token: res[2],
space: res[1].replace(/\s+/g, ' '),
index: index,
}
}
this.matchAny = function() {
var res = _match;
getToken();
return res;
}
this.match = function(str) {
if (_match.token !== str)
throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Expected '" + str + "', found '" + _match.token + "'.");
return this.matchAny();
}
this.matchIgnoreCase = function(str) {
if (_match.token.toUpperCase() !== str.toUpperCase())
throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Expected '" + str + "', found '" + _match.token + "'.");
return this.matchAny();
}
this.matchAnyIgnoreCase = function(strs) {
if (strs.every(function(str) { return _match.token.toUpperCase() !== str.toUpperCase(); }))
throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Expected any of: '" + strs.join("', '") + "', found '" + _match.token + "'.");
return this.matchAny();
}
this.matchNot = function(strs) {
if (strs.indexOf(_match.token) != -1)
throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Unexpected '" + _match.token + "'.");
return this.matchAny();
}
this.index = function() {
return _match.index;
}
this.isEof = () => _isEof;
Object.defineProperty(this, "token", { get: function() { return _match.token; }});
getToken();
}
var Bibtex = function(sourceText, index) {
var _plainText = /[^\{\},\\=\s"\$]+/;
const _tokens = [
/\{/,
/\}/,
/"/,
/,/,
/=/,
/@/,
/\$/,
/\\\W/,
/\\[\w]+/,
_plainText,
];
var _parser = new Parser(sourceText, index || 0, _tokens);
var entry = function() {
_parser.match("{");
var id = fieldValue();
_parser.match(",");
var f = fields();
_parser.match("}");
f.bibcode = id;
return f;
}
var comment = function() {
_parser.match("{");
var text = fieldValue();
_parser.match("}");
return { comment: text };
}
var type = function(entryTypes) {
_parser.match('@');
var token = _parser.token;
if (entryTypes.length)
_parser.matchAnyIgnoreCase(entryTypes);
else
_parser.matchAny();
return token;
}
var fields = function() {
var res = {};
for(;;) {
var f = field();
res[f.name] = f.value;
if (_parser.token !== ",") break;
_parser.match(",");
if (_parser.token === "}") break;
}
return res;
}
var quoted = function() {
return _parser.match("{").space + quotedValue() + _parser.match("}").space;
}
var diacritics = {
'`': '\u0300',
'\'': '\u0301',
'^': '\u0302',
'~': '\u0303',
'=': '\u0304',
'u': '\u0306',
'.': '\u0307',
'"': '\u0308',
'r': '\u030a',
'H': '\u030b',
'v': '\u030c',
'c': '\u0327',
'k': '\u0328',
'd': '\u0323',
'b': '\u0331',
't': '\u0361',
};
var ligatures = {
'L': '\u0141',
'l': '\u0142',
'AA': '\u00c5',
'aa': '\u00e5',
'AE': '\u00c6',
'ae': '\u00e6',
'O': '\u00d8',
'o': '\u00f8',
'OE': '\u0152',
'oe': '\u0153',
'i': '\u0131',
'j': '\u0237',
'ss': '\u00df',
};
var entity = function() {
if (_parser.token[0] != '\\')
throw new Error("Expected entity, found " + _parser.token);
var cmd = _parser.matchAny().token.substr(1);
var value = ligatures[cmd];
if (value)
return value;
value = diacritics[cmd];
if (value)
return fieldValue() + value;
return cmd;
}
var quotedValue = function() {
var res = "";
for(;;) {
if (_parser.token === "{")
res += quoted();
else if (_parser.token === "}")
break;
else if (_parser.token[0] === '\\')
res += entity();
else
res += plainText();
}
return res;
}
var plainText = function() {
return _parser.matchAny().match.replace(/---?/g, '—').replace(/~/g, ' ');
}
var fieldValue = function() {
var res = "";
for(;;) {
if (_parser.token == "{")
res += quoted();
else if (_parser.token == '"')
res += doubleQuoted();
else if (_parser.token[0] === '\\')
res += entity();
else if (_parser.token === '$')
res += math();
else if (_plainText.test(_parser.token))
res += plainText();
else
break;
}
return res.trim();
}
var amsFieldValue = function() {
var res = "";
for(;;) {
if (_parser.isEof())
break;
else if (_parser.token == "{")
res += quoted();
else if (_parser.token == '"')
res += doubleQuoted();
else if (_parser.token[0] === '\\')
res += entity();
else if (_parser.token === '$')
res += math();
else
res += plainText();
}
return res.trim();
}
var math = function() {
var before = _parser.match('$').space;
var res = '';
for(;;) {
if (_parser.token === '$')
break;
else
res += _parser.matchAny().match;
}
return before + '<math>' + res + '</math>' + _parser.match('$').space;
}
var doubleQuoted = function() {
return _parser.match('"').space + doubleQuotedValue() + _parser.match('"').space;
}
var doubleQuotedValue = function() {
var res = "";
for(;;) {
if (_parser.isEof())
throw new Error("Unexpected EOF.");
else if (_parser.token == "{")
res += quoted();
else if (_parser.token == '"')
break;
else if (_parser.token[0] === '\\')
res += entity();
else if (_parser.token === '$')
res += math();
else
res += plainText();
}
return res;
}
var field = function() {
var name = fieldValue();
_parser.match("=");
var value = fieldValue();
return {
name: name,
value: value
}
}
this.index = function() {
return _parser.index();
}
this.parse = function(entryTypes) {
if (!entryTypes)
entryTypes = []
else if (typeof entryTypes == 'string' || entryTypes instanceof String)
entryTypes = [ entryTypes ];
var realType = type(entryTypes);
if (realType.toLowerCase() == 'comment')
var result = comment();
else
var result = entry();
result.type = realType;
return result;
}
this.parseAmsFieldValue = function() {
return amsFieldValue();
}
}
var bibtexBase = {
'автор': {
selector: 'author',
map: (text) => authorsToWiki(getAuthors(text)),
},
'заглавие': {
selector: 'title',
map: function(text) {
return text.replace(/^"|"$/g, '')
}
},
'издание': {
selector: 'journal',
map: function(text) {
return {
aj: 'Astronomical Journal',
actaa: 'Acta Astronomica',
araa: 'Annual Review of Astron and Astrophys',
apj: 'Astrophysical Journal',
apjl: 'Astrophysical Journal, Letters',
apjs: 'Astrophysical Journal, Supplement',
ao: 'Applied Optics',
apss: 'Astrophysics and Space Science',
aap: 'Astronomy and Astrophysics',
aapr: 'Astronomy and Astrophysics Reviews',
aaps: 'Astronomy and Astrophysics, Supplement',
azh: 'Astronomicheskii Zhurnal',
baas: 'Bulletin of the AAS',
caa: 'Chinese Astronomy and Astrophysics',
cjaa: 'Chinese Journal of Astronomy and Astrophysics',
icarus: 'Icarus',
jcap: 'Journal of Cosmology and Astroparticle Physics',
jrasc: 'Journal of the RAS of Canada',
memras: 'Memoirs of the RAS',
mnras: 'Monthly Notices of the RAS',
na: 'New Astronomy',
nar: 'New Astronomy Review',
pra: 'Physical Review A: General Physics',
prb: 'Physical Review B: Solid State',
prc: 'Physical Review C',
prd: 'Physical Review D',
pre: 'Physical Review E',
prl: 'Physical Review Letters',
pasa: 'Publications of the Astron. Soc. of Australia',
pasp: 'Publications of the ASP',
pasj: 'Publications of the ASJ',
rmxaa: 'Revista Mexicana de Astronomia y Astrofisica',
qjras: 'Quarterly Journal of the RAS',
skytel: 'Sky and Telescope',
solphys: 'Solar Physics',
sovast: 'Soviet Astronomy',
ssr: 'Space Science Reviews',
zap: 'Zeitschrift fuer Astrophysik',
nat: 'Nature',
iaucirc: 'IAU Cirulars',
aplett: 'Astrophysics Letters',
apspr: 'Astrophysics Space Physics Research',
bain: 'Bulletin Astronomical Institute of the Netherlands',
fcp: 'Fundamental Cosmic Physics',
gca: 'Geochimica Cosmochimica Acta',
grl: 'Geophysics Research Letters',
jcp: 'Journal of Chemical Physics',
jgr: 'Journal of Geophysics Research',
jqsrt: 'Journal of Quantitiative Spectroscopy and Radiative Transfer',
memsai: 'Mem. Societa Astronomica Italiana',
nphysa: 'Nuclear Physics A',
physrep: 'Physics Reports',
physscr: 'Physica Scripta',
planss: 'Planetary Space Science',
procspie: 'Proceedings of the SPIE',
}[text] || text;
},
},
'год': {
selector: 'year',
},
'номер': {
selector: 'number',
},
'том': {
selector: 'volume',
},
'страницы': {
selector: 'pages',
},
'издательство': {
selector: 'publisher',
},
'issn': {
selector: 'issn',
},
'doi': {
selector: 'doi',
},
'arxiv': {
selector: 'eprint',
map: function(text) {
const prefix = 'arXiv:';
if (text.indexOf(prefix) == 0)
text = text.substr(prefix.length);
return text;
}
},
'ссылка': { const: "" },
'язык': { const: "en" },
};
var getAuthors = function(text) {
return text.split(' and ').map(function(name) {
return name.replace(',', '');
});
};
var authorsToWiki = function(authors) {
return authors.map(function(name) {
return new Template('nobr').add(name).toWiki()
}).join(', ');
};
var switchAuthorNameParts = function(name) {
var match = /^(.+) (\S+)$/.exec(name);
if (!match) return name;
return match[2] + ' ' + match[1];
}
var getWpFromObj = function(name, rules, obj) {
var article = new Template(name);
for(var name in rules) {
var rule = rules[name];
var value;
if (rule.const !== undefined)
value = rule.const
else {
if (typeof rule.selector === "function")
value = rule.selector(obj);
else
value = obj[rule.selector];
if (!value)continue;
}
if (rule.map)
value = rule.map(value, obj);
article.add(name, value);
}
return getRef(article);
}
var getRef = function(template) {
// adding additional args
for(var a of templateAdditionalArgs[template.getName()] || []) {
if (template.get(a) === undefined)
template.add(a, '');
}
// ordering
var orderedTemplate = new Template(template.getName());
var names = template.getParamNames();
var getOrder = x => {
var i = refTemplateParamOrder.indexOf(x.toLowerCase());
return i === -1 ? 99999 : i;
}
names.sort((x, y) => getOrder(x) - getOrder(y));
for(var name of names)
orderedTemplate.add(name, template.get(name));
return orderedTemplate.toWiki();
}
var testUrl = function(regex) {
return regex.exec(window.location.href)
}
var createWpButton = function(getResult, tag, param) {
tag = tag || 'a';
return $('<' + tag + '>')
.attr('href', '#')
.text('WP')
.click(function(e) {
e.preventDefault();
var promise = $.Deferred();
promise.done(function(result) {
showResult(result);
}).fail(function(result) {
alert(result);
});
getResult({
resolve: function(result) {
promise.resolve(result)
},
reject: function(result) {
promise.reject(result)
},
}, param);
})
.get(0);
}
var showResult = function(text) {
var button;
var dialog = $('<div>').css({
'position': 'fixed',
'top': 0,
'left': 0,
'width': '100%',
'height': '100%',
'z-index': 9999999,
}).appendTo(document.body).append(
// dimmer
$('<div>').css({
'width': '100%',
'height': '100%',
'background-color': 'black',
'opacity': 0.6,
})
).append(
// dialog container
$('<div>').css({
'display': 'table',
'position': 'absolute',
'top': 0,
'left': 0,
'width': '100%',
'height': '100%',
'font': '12px sans-serif',
}).append(
$('<div>').css({
'text-align': 'center',
'display': 'table-cell',
'vertical-align': 'middle',
}).append(
// dialog
$('<div>').css({
'padding': 10,
'background-color': 'white',
'display': 'inline-block',
'max-width': '80%',
}).append(
// text
$('<div>').css({
'padding': 5,
'white-space': 'pre-wrap',
'text-align': 'left',
}).text(text)
).append(
// buttons
$('<div>').css({
'text-align': 'right',
'margin-top': 10,
}).append(
button = $('<button>').text('Copy & close').click(function() {
GM_setClipboard(text);
dialog.remove();
}).focus()
).append(
$('<button>').text('Cancel').click(function() {
dialog.remove();
})
)
)
)
)
);
button.focus();
};
var getFormData = function(data) {
if (data && typeof(data) !== 'string') {
var params = [];
for(var k in data) {
params.push(encodeURIComponent(k) + '=' + encodeURIComponent(data[k]))
}
data = params.join('&');
}
return data;
}
var ajaxGet = function(url, process) {
var data;
if (!(typeof url === 'string' || url instanceof String)) {
var { url, data } = url;
}
if (data)
url = url + '?' + getFormData(data);
return ajax({
method: 'GET',
url: url,
}, process);
};
var ajaxPost = function({ url, data }, process) {
return ajax({
method: 'POST',
url: url,
data: getFormData(data),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}, process);
};
var ajax = function(params, process) {
var promise = $.Deferred();
params.onload = function(response) {
try {
promise.resolve(process(response.responseText));
} catch(e) {
promise.reject(e + '\n\n' + e.stack);
}
}
setTimeout(function() {
GM_xmlhttpRequest(params)
}, 0);
return promise.promise();
};
var getBibtex = function(params) {
return function(text) {
var bibtex = (params.parse || (t => new Bibtex(t).parse()))(text);
var template = (params.getTemplate && params.getTemplate(bibtex)) || (params.templates || templates)[bibtex.type.toLowerCase()];
if (!template) {
throw new Error('unknown type: ' + bibtex.type);
}
return getWpFromObj(template, params.getRules(bibtex.type), bibtex);
}
};
var getXml = function(params) {
return function(text) {
var xml = params.parse(text);
var template = params.getTemplate(xml);
if (!template) {
throw new Error('unknown type: ' + bibtex.type);
}
return getWpFromXml(template, params.getRules(xml), xml);
}
};
var proecssPage = function(page, res) {
var onButton = function(promise, param) {
try {
$.when(page.act(res, param)).then(promise.resolve, promise.reject);
} catch(e) {
promise.reject(e + '\n\n' + e.stack);
}
};
page.attach(createWpButton.bind(null, onButton));
};
(function(pages) {
try {
for(var page of pages) {
var res = page.test();
if (res) {
proecssPage(page, res);
break;
}
};
} catch(e) {
alert(e + '\n\n' + e.stack);
}
})([
// pubmed
{
test: function() {
return testUrl(/\/pubmed\/(\d+)\/?$/);
},
attach: function(createButton) {
$('#messagearea').after(
$('<div>').append(createButton())
);
},
act: ([,id]) => ajaxGet({
url: id,
data: { dopt: 'Abstract', report: 'xml', format: 'text' },
}, getXml({
parse: function(text) {
var html = new DOMParser().parseFromString(text, "text/html");
return new DOMParser().parseFromString(html.body.textContent, "text/xml");
},
getTemplate: () => templates.article,
getRules: () => ({
'автор': {
selector: 'Article > AuthorList > Author',
map: function(node) {
var name = getText(node.querySelector('CollectiveName'));
if (name) return name;
name = [ node.querySelector('LastName'), node.querySelector('Initials') ].map(getText);
return new Template('nobr').add(name[0] + ' ' + name[1].replace(/(.)/g, "$1. ").trim()).toWiki()
},
},
'заглавие': {
selector: 'Article > ArticleTitle',
mapText: function(text) { return text.replace(/^(.*?)\.?$/, "$1") },
},
'издание': {
selector: 'Article > Journal > Title',
},
'год': {
selector: 'Article > Journal > JournalIssue > PubDate',
mapText: function(text) { return /^\s*(\d{4})/.exec(text)[1] },
},
'номер': {
selector: 'Article > Journal > JournalIssue > Issue',
},
'том': {
selector: 'Article > Journal > JournalIssue > Volume',
},
'страницы': {
selector: 'Article > Pagination > MedlinePgn',
mapText: text => text.replace('-', '—'),
},
'issn': {
selector: 'Article > Journal > ISSN[IssnType=Electronic]',
},
'doi': {
selector: 'ArticleIdList > ArticleId[IdType=doi]',
},
'pmid': {
selector: 'ArticleIdList > ArticleId[IdType=pubmed]',
},
'язык': { const: "en" },
'ссылка': { const: "" },
}),
})),
},
// adsabs
{
test: function() {
return testUrl(/adsabs\.harvard\.edu\/(?:abs|doi)\/(.*)$/);
},
attach: function(createButton) {
$('h3').eq(0)
.append(document.createTextNode(' '))
.append(createButton());
},
act: ([,id]) => ajaxGet({
url: '/cgi-bin/nph-bib_query',
data: { data_type: 'BIBTEX', bibcode: decodeURIComponent(id) },
}, getBibtex({
parse: function(text) {
var index = text.search(/@\w+{/);
if (index == -1)
throw new Error('bibtex not found');
return new Bibtex(text, index).parse([ 'article', 'book', 'inproceedings' ]);
},
getRules: function() {
var bibtex = clone(bibtexBase);
bibtex.bibcode = { selector: 'bibcode' };
bibtex.издание = {
selector: obj => obj['journal'] || obj['booktitle'],
map: bibtex.издание.map,
}
return bibtex;
},
templates: Object.assign({ 'inproceedings': templates.article }, templates),
})),
},
// ufn
{
test: function() {
return testUrl(/\/ufn\.ru\/ru\/articles\/(\d+\/\d+\/\w+)\//);
},
attach: function(createButton) {
$('#print > table tr > td').next().append(
$('<td>').append(createButton())
);
},
act: ([, id]) => ajaxGet('/ru/articles/' + id + '/citation/ru/bibtex.html', getBibtex({
parse: function(text) {
var html = new DOMParser().parseFromString(text, "text/html");
var node = html.body.querySelector('.cit_code > pre');
if (!node)
throw new Error('bibtex not found');
return new Bibtex(node.textContent).parse('article');
},
getRules: function() {
var bibtex = clone(bibtexBase);
var nameRegex = /^(.+) (\S+)$/;
bibtex.автор.map = function(text) {
return authorsToWiki(getAuthors(text).map(switchAuthorNameParts));
}
delete bibtex.издательство;
bibtex.страницы.map = t => t.replace('-', '—');
bibtex.ссылка = { const: 'http://ufn.ru/ru/articles/' + id + '/' };
bibtex.язык = { const: "ru" };
return bibtex;
}
})),
},
// google books
{
test: function() {
return window.self == window.top && testUrl(/https?:\/\/books\.google\..+\/books.*[?&]id=([^&$]+)/);
},
attach: function(createButton) {
var button = $(createButton()).addClass('gb-button').css('margin-left', '4px');
$('.metadata_value > .gb-button:last-child, #gb-get-book-container > *:first-child')
.parent()
.append(button);
},
act: ([, id]) => ajaxGet({
url: 'http://books.google.us/books/download/',
data: { id: id, output: 'bibtex' },
}, getBibtex({
parse: t => new Bibtex(t).parse('book'),
getRules: function() {
var bibtex = clone(bibtexBase);
bibtex.серия = { 'selector': 'series' };
bibtex.страниц = { const: "" };
bibtex.isbn = { 'selector': 'isbn' };
bibtex.ссылка = { const: 'http://books.google.com/books?id=' + id };
return bibtex;
}
})),
},
// sciencedirect
{
test: function() {
return testUrl(/sciencedirect\.com\/science\/article\//);
},
attach: function(createButton) {
$('#articleNav > ul').prepend($('<li />').append(
$(createButton()).attr('type', 'button').val('WP').css({
'vertical-align': 'middle',
'line-height': '40px',
})
));
},
act: function() {
var params = {
'citation-type': 'BIBTEX'
};
$('form[name=exportCite] input[type=hidden]').each(function(i, hidden) {
params[$(hidden).attr('name')] = $(hidden).val();
});
return ajaxPost({
url: $('form[name=exportCite]').attr('action'),
data: params,
}, getBibtex({
parse: t => new Bibtex(t).parse('article'),
getRules: function() {
var bibtex = clone(bibtexBase);
bibtex.ссылка = { selector: 'url' };
bibtex.doi.map = function(text) {
var res = /http:\/\/dx\.doi\.org\/(.*)$/.exec(text) || [];
return res[1] || text;
}
bibtex.страницы.map = function(text) {
return text.replace(' - ', '—')
}
return bibtex;
}
}))
},
},
// Library Genesis
{
test: function() {
return testUrl(/gen\.lib\.rus\.ec\/scimag\//);
},
attach: function(createButton) {
$('a[href^="bibtex.php?"]').each((i, e) => {
var button = createButton('a', $(e).attr('href'));
button.style.fontWeight = 'bold';
$(e).after('<br />', button);
});
},
act: (_, url) => ajaxGet({
url: url,
}, getBibtex({
parse: text => {
var html = new DOMParser().parseFromString(text, "text/html");
return new Bibtex(html.querySelector('textarea#bibtext').value).parse('article');
},
getRules: function() {
var bibtex = clone(bibtexBase);
bibtex.номер = { selector: 'issue' };
bibtex.страницы = { selector: 'page' };
bibtex.язык = { const: '' };
return bibtex;
},
})),
},
// wiley
{
test: function() {
return testUrl(/onlinelibrary\.wiley\.com\/doi\//)
},
attach: function(createButton) {
$('#promosAndTools .titleTools').append($('<li>').append(createButton()));
},
act: function() {
var [, doi] = /^DOI:\s+(.+)$/.exec($('#doi').text().trim());
if (!doi) throw new Error('doi not found');
return ajaxPost({
url: '/documentcitationdownloadformsubmit',
data: { doi: doi, fileFormat: 'BIBTEX', hasAbstract: 'CITATION' },
}, getBibtex({
getRules: function() {
var bibtex = clone(bibtexBase);
bibtex.ссылка = { selector: 'url' };
return bibtex;
}
}))
},
},
// jstor
{
test: function() {
return testUrl(/www\.jstor\.org\/[^\/]+\/(.*?)($|\?)/)
},
attach: function(createButton) {
$('.action-buttons').append($('<li>').append($(createButton()).addClass('button button-jstor')));
},
act: ([, id]) => ajaxGet('/citation/text/' + id, getBibtex({
getRules: function() {
var bibtex = clone(bibtexBase);
bibtex.ссылка = { selector: 'URL' };
bibtex.номер.selector = function(obj) {
return obj['number'] || obj['jstor_issuetitle'];
}
bibtex.страницы.map = function(text) {
return text.replace(/^p?p\. /, "").replace('-', '—');
};
return bibtex;
},
})),
},
// projecteuclid
{
test: function() {
return testUrl(/projecteuclid.org\/(euclid\..*?\/\d+)/);
},
attach: function(createButton) {
$('#export-form').append($(createButton()).addClass('btn export-link-special'))
},
act: ([, id]) => ajaxPost({
url: '/export_citations',
data: { format: "bibtex", delivery: "browser", address: '', h: id },
}, getBibtex({
templates: {
'article': templates.article,
'inbook': templates.book,
},
getRules: function(type) {
var bibtex = clone(bibtexBase);
bibtex.издание = { selector: 'fjournal' };
if (type.toLowerCase() == 'inbook') {
bibtex.место = { selector: 'address' };
bibtex.часть = bibtex.заглавие;
bibtex.заглавие = { selector: 'booktitle' };
bibtex['ссылка часть'] = { selector: 'url' };
delete bibtex.ссылка;
} else {
bibtex.ссылка = { selector: 'url' };
}
return bibtex;
}
})),
},
// springer
{
test: () => testUrl(/\/link\.springer\.com\/([^#]+)/),
attach: function(createButton) {
if ($('#export-citation').length)
$('.other-actions > ul').append($('<li>').append(createButton()));
},
act: ([, id]) => ajaxGet('http://link.springer.com/export-citation/' + id + '.bib', getBibtex({
parse: text => new Bibtex(text.replace(/^@.*?{/, '$&x,')).parse(),
templates: {
'article': templates.article,
'incollection': templates.book,
},
getRules: function(type) {
var bibtex = clone(bibtexBase);
bibtex.страницы.map = t => t.replace('-', '—');
bibtex.ссылка = { const: 'http://link.springer.com/' + id };
if (type == 'incollection') {
bibtex.ответственный = {
selector: 'editor',
map: text => 'Ed. by ' + authorsToWiki(getAuthors(text)),
};
bibtex.серия = { 'selector': 'series' };
bibtex.часть = bibtex.заглавие;
bibtex.заглавие = { selector: 'booktitle' };
bibtex['ссылка часть'] = bibtex.ссылка;
bibtex.ссылка = { const: $('#about-link').attr('href') };
bibtex.isbn = { 'selector': 'isbn' };
} else if (type == 'article') {
delete bibtex.издательство;
}
return bibtex;
}
})),
},
// mathnet
{
test: () => testUrl(/\/www\.mathnet\.ru\//),
attach: function(createButton) {
$('#citPaperAMSBIBID').before(createButton());
},
act: () => getBibtex({
parse: t => {
var transl = false;
var res = {};
for(var line of t.split('\n')) {
if (!line) continue;
var [, key, value] = /^\\(\w+)\s*(.*)$/.exec(line);
if (key === 'transl' || key === 'rtransl') {
transl = true;
continue;
}
if (transl)
key = 'transl_' + key;
if (key == 'by')
value = value.replace(/([^\\]), /g, '$1 and ');
res[key] = new Bibtex(value).parseAmsFieldValue();
}
return res;
},
getTemplate: () => templates.article,
getRules: () => ({
'автор': {
selector: 'by',
map: text => authorsToWiki(getAuthors(text).map(switchAuthorNameParts)),
},
'заглавие': { selector: 'paper' },
'издание': { selector: b => b.journalname || b.jour || b.serial },
'год': { selector: 'yr' },
'номер': { selector: 'issue' },
'том': { selector: 'vol' },
'страницы': { selector: 'pages' },
'издательство': { selector: 'publ' },
'ссылка': { selector: 'mathnet' },
'язык': { const: 'ru' },
'bibcode': {
selector: 'adsnasa',
map: url => /bib_query\?(.*)$/.exec(url)[1],
}
}),
})($('#citPaperAMSBIBID pre').text())
},
// elibrary
{
test: () => testUrl(/elibrary\.ru\/item.asp/),
attach: function(createButton) {
var space = $('.left-panel').eq(0).parents('tr').eq(0).next('tr');
$('<tr>').append(
$('<td>').append(
$('<div>').addClass('left-panel').append(
$(createButton()).css({
fontWeight: 'bold',
color: '#F26C4F',
})
)
)
).insertAfter(space).after(space.clone());
},
act: () => {
var data = {};
const mapping = {
'язык': {
value: v => ({
'русский': 'ru',
'английский': 'en',
}[v] || '')
},
'страницы': {
key: 'pages',
value: v => v.replace('-', '—'),
},
'том': {
key: 'volume'
},
'номер': {
key: 'number'
},
'год': {
key: 'year'
},
'журнал': {
key: 'journal'
},
};
var add = function(key, value) {
var m = mapping[key];
if (!m) {
data[key] = value;
} else {
data[m.key || key] = (m.value && m.value(value)) || value;
}
}
var processRecords = function(e) {
if (e.nodeType == 3) {
var text = $(e).text().trim();
if (text && text[text.length - 1] == ':')
processRecords.key = text.substr(0, text.length - 1).toLowerCase();
} else if ($(e).is('font,a') && processRecords.key !== undefined) {
var value = $(e).text().trim();
add(processRecords.key, value);
processRecords.key = undefined;
}
}
var title = $('tr[valign=middle][align=center] .bigtext').eq(0).parents('table').eq(0);
var tables = title.nextAll('table');
data.title = title.text().trim();
data.author = authorsToWiki(tables.eq(0).find('span b').get().map(e => $(e).text()));
tables.eq(1).find('table td').contents().each((i, e) => processRecords(e));
processRecords(tables.eq(2).find('tr font').contents()[0]);
tables.eq(2).find('tr').eq(1).find('td').eq(1).contents().each((i, e) => processRecords(e));
var bibtex = clone(bibtexBase);
bibtex.автор = { selector: 'author' };
bibtex.язык = { selector: 'язык' };
bibtex.ссылка = { const: location.href };
return getWpFromObj(templates.article, bibtex, data);
},
},
]);