- // ==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);
- },
- },
- ]);