Greasy Fork镜像 还支持 简体中文。

wiki-reference

Позволяет генерировать ссылки в формате {{Статья}} и {{книга}} для ру-вики

目前為 2015-07-06 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name wiki-reference
  3. // @namespace torvin
  4. // @include https://www.ncbi.nlm.nih.gov/pubmed/*
  5. // @include http://www.ncbi.nlm.nih.gov/pubmed/*
  6. // @include http://adsabs.harvard.edu/abs/*
  7. // @include http://adsabs.harvard.edu/doi/*
  8. // @include http://ufn.ru/ru/articles/*
  9. // @include http://books.google.*/books*
  10. // @include https://books.google.*/books*
  11. // @include http://www.sciencedirect.com/science/article/*
  12. // @include http://gen.lib.rus.ec/scimag/*
  13. // @include http://onlinelibrary.wiley.com/doi/*
  14. // @include http://www.jstor.org/stable/*
  15. // @include http://www.jstor.org/discover/*
  16. // @require https://code.jquery.com/jquery-2.1.1.min.js
  17. // @version 1.6.4
  18. // @description Позволяет генерировать ссылки в формате {{Статья}} и {{книга}} для ру-вики
  19. // @grant GM_xmlhttpRequest
  20. // @grant GM_setClipboard
  21. // ==/UserScript==
  22.  
  23. const templates = {
  24. article: 'Статья',
  25. book: 'книга',
  26. };
  27.  
  28. var Template = function(name) {
  29. var attrs = [];
  30.  
  31. this.add = function(name, value) {
  32. attrs.push({
  33. name: name,
  34. value: value
  35. });
  36. return this;
  37. };
  38.  
  39. var getAttr = function(x) {
  40. return "|" + x.name + (x.value === undefined ? "" : " = " + x.value);
  41. };
  42.  
  43. this.toWiki = function() {
  44. if (attrs.length == 1)
  45. return "{{" + name + getAttr(attrs[0]) + "}}";
  46. else
  47. return "{{" + name + "\n" + attrs.map(function(x) { return " " + getAttr(x)}).join("\n") + "\n}}";
  48. };
  49. };
  50.  
  51. var pubmed = {
  52. 'автор': {
  53. selector: 'Article > AuthorList > Author',
  54. map: function(node) { return [ node.querySelector('LastName'), node.querySelector('Initials') ] },
  55. mapText: function(nodes) { return new Template('nobr').add(nodes[0] + ' ' + nodes[1].replace(/(.)/g, "$1. ").trim()).toWiki() },
  56. },
  57. 'заглавие': {
  58. selector: 'Article > ArticleTitle',
  59. mapText: function(text) { return text.replace(/^(.*?)\.?$/, "$1") },
  60. },
  61. 'издание': {
  62. selector: 'Article > Journal > Title',
  63. },
  64. 'год': {
  65. selector: 'Article > Journal > JournalIssue > PubDate',
  66. mapText: function(text) { return /^\s*(\d{4})/.exec(text)[1] },
  67. },
  68. 'выпуск': {
  69. selector: 'Article > Journal > JournalIssue > Issue',
  70. },
  71. 'том': {
  72. selector: 'Article > Journal > JournalIssue > Volume',
  73. },
  74. 'страницы': {
  75. selector: 'Article > Pagination > MedlinePgn',
  76. },
  77. 'issn': {
  78. selector: 'Article > Journal > ISSN[IssnType=Electronic]',
  79. },
  80. 'doi': {
  81. selector: 'ArticleIdList > ArticleId[IdType=doi]',
  82. },
  83. 'pmid': {
  84. selector: 'ArticleIdList > ArticleId[IdType=pubmed]',
  85. },
  86. 'ссылка': { const: "" },
  87. 'ref': { const: "" },
  88. 'archiveurl': { const: "" },
  89. 'archivedate': { const: "" },
  90. };
  91.  
  92. var getText = function(node) {
  93. return node instanceof Element ? node.textContent : node;
  94. };
  95.  
  96. var ajax = function(params) {
  97. setTimeout(function() {
  98. GM_xmlhttpRequest(params)
  99. }, 0);
  100. }
  101.  
  102. var clone = function(obj) {
  103. var target = {};
  104. for (var i in obj) {
  105. var value = obj[i];
  106. if (value instanceof Function)
  107. ;
  108. else if (typeof value == 'string')
  109. ;
  110. else
  111. value = clone(value);
  112. target[i] = value;
  113. }
  114. return target;
  115. }
  116.  
  117. var getWpFromXml = function(name, rules, xml) {
  118. var article = new Template(name);
  119.  
  120. for(var name in rules) {
  121. var rule = rules[name];
  122. article.add(name, rule.const ||
  123. Array.slice(xml.querySelectorAll(rule.selector)).map(function(node) {
  124. if (rule.map)
  125. node = rule.map(node);
  126. return Array.isArray(node) ? node.map(getText) : getText(node);
  127. }).map(function(item) {
  128. return rule.mapText ? rule.mapText(item) : item;
  129. }).join(rule.separator || ', ')
  130. );
  131. }
  132.  
  133. return article.toWiki();
  134. };
  135.  
  136. var Parser = function(sourceText, index, tokens) {
  137. var _match;
  138. var _isEof;
  139.  
  140. //var _tokenRegex = /(\s*)(\{|\}|,|=|\\\W|\\[\w]+|[^\{\},\\=\s])/g;
  141. var _tokenRegex = new RegExp("(\\s*)(" + tokens.map(function(x) { return x.source || x }).join('|') + ")", 'g');
  142. _tokenRegex.lastIndex = index;
  143.  
  144. var getToken = function() {
  145. if (_isEof)
  146. throw new Error("EOF");
  147.  
  148. var index = _tokenRegex.lastIndex;
  149.  
  150. var res = _tokenRegex.exec(sourceText);
  151. if (!res) {
  152. _isEof = true;
  153. return null;
  154. }
  155. _match = {
  156. match: res[0],
  157. token: res[2],
  158. space: res[1].replace(/\s+/g, ' '),
  159. index: index,
  160. }
  161. }
  162.  
  163. this.matchAny = function() {
  164. var res = _match;
  165. getToken();
  166. return res;
  167. }
  168.  
  169. this.match = function(str) {
  170. if (_match.token !== str)
  171. throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Expected '" + str + "', found '" + _match.token + "'.");
  172. return this.matchAny();
  173. }
  174.  
  175. this.matchIgnoreCase = function(str) {
  176. if (_match.token.toUpperCase() !== str.toUpperCase())
  177. throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Expected '" + str + "', found '" + _match.token + "'.");
  178. return this.matchAny();
  179. }
  180.  
  181. this.matchAnyIgnoreCase = function(strs) {
  182. if (strs.every(function(str) { return _match.token.toUpperCase() !== str.toUpperCase(); }))
  183. throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Expected any of: '" + strs.join("', '") + "', found '" + _match.token + "'.");
  184. return this.matchAny();
  185. }
  186.  
  187. this.matchNot = function(strs) {
  188. if (strs.indexOf(_match.token) != -1)
  189. throw new Error("Parser error at pos " + _tokenRegex.lastIndex + ". Unexpected '" + _match.token + "'.");
  190. return this.matchAny();
  191. }
  192.  
  193. this.index = function() {
  194. return _match.index;
  195. }
  196.  
  197. Object.defineProperty(this, "token", { get: function() { return _match.token; }});
  198.  
  199. getToken();
  200. }
  201.  
  202. var Bibtex = function(sourceText, index, entryTypes) {
  203. var _plainText = /[^\{\},\\=\s]+/;
  204. const _tokens = [
  205. /\{/,
  206. /\}/,
  207. /,/,
  208. /=/,
  209. /@/,
  210. /\\\W/,
  211. /\\[\w]+/,
  212. _plainText,
  213. ];
  214.  
  215. var _parser = new Parser(sourceText, index, _tokens);
  216.  
  217. var entry = function() {
  218. _parser.match("{");
  219. var id = fieldValue();
  220. _parser.match(",");
  221. var f = fields();
  222. _parser.match("}");
  223.  
  224. f.bibcode = id;
  225. return f;
  226. }
  227.  
  228. var comment = function() {
  229. _parser.match("{");
  230. var text = fieldValue();
  231. _parser.match("}");
  232. return { comment: text };
  233. }
  234.  
  235. var type = function() {
  236. _parser.match('@');
  237. var token = _parser.token;
  238. if (entryTypes.length)
  239. _parser.matchAnyIgnoreCase(entryTypes);
  240. else
  241. _parser.matchAny();
  242. return token;
  243. }
  244.  
  245. var fields = function() {
  246. var res = {};
  247. for(;;) {
  248. var f = field();
  249. res[f.name] = f.value;
  250. if (_parser.token !== ",") break;
  251. _parser.match(",");
  252. if (_parser.token === "}") break;
  253. }
  254. return res;
  255. }
  256.  
  257. var quoted = function() {
  258. return _parser.match("{").space + quotedValue() + _parser.match("}").space;
  259. }
  260.  
  261. var diacritics = {
  262. '`': '\u0300',
  263. '\'': '\u0301',
  264. '^': '\u0302',
  265. '~': '\u0303',
  266. '=': '\u0304',
  267. 'u': '\u0306',
  268. '.': '\u0307',
  269. '"': '\u0308',
  270. 'r': '\u030a',
  271. 'H': '\u030b',
  272. 'v': '\u030c',
  273. 'c': '\u0327',
  274. 'k': '\u0328',
  275. 'd': '\u0323',
  276. 'b': '\u0331',
  277. 't': '\u0361',
  278. };
  279.  
  280. var ligatures = {
  281. 'L': '\u0141',
  282. 'l': '\u0142',
  283. 'AA': '\u00c5',
  284. 'aa': '\u00e5',
  285. 'AE': '\u00c6',
  286. 'ae': '\u00e6',
  287. 'O': '\u00d8',
  288. 'o': '\u00f8',
  289. 'OE': '\u0152',
  290. 'oe': '\u0153',
  291. 'i': '\u0131',
  292. 'j': '\u0237',
  293. 'ss': '\u00df',
  294. };
  295.  
  296. var entity = function() {
  297. if (_parser.token[0] != '\\')
  298. throw new Error("Expected entity, found " + _parser.token);
  299.  
  300. var cmd = _parser.matchAny().token.substr(1);
  301.  
  302. var value = ligatures[cmd];
  303. if (value)
  304. return value;
  305.  
  306. value = diacritics[cmd];
  307. if (value)
  308. return fieldValue() + value;
  309.  
  310. return cmd;
  311. }
  312.  
  313. var quotedValue = function() {
  314. var res = "";
  315. for(;;) {
  316. if (_parser.token === "{")
  317. res += quoted();
  318. else if (_parser.token === "}")
  319. break;
  320. else if (_parser.token[0] === '\\')
  321. res += entity();
  322. else
  323. res += _parser.matchAny().match;
  324. }
  325. return res;
  326. }
  327.  
  328. var fieldValue = function() {
  329. var res = "";
  330. for(;;) {
  331. if (_parser.token == "{")
  332. res += quoted();
  333. else if (_parser.token[0] === '\\')
  334. res += entity();
  335. else if (_plainText.test(_parser.token))
  336. res += _parser.matchAny().match;
  337. else
  338. break;
  339. }
  340. return res.trim().replace(/^"?(.*?)"?$/, '$1').replace(/---?/g, '—');
  341.  
  342. }
  343.  
  344. var field = function() {
  345. var name = fieldValue();
  346. _parser.match("=");
  347. var value = fieldValue();
  348.  
  349. return {
  350. name: name,
  351. value: value
  352. }
  353. }
  354.  
  355. if (!entryTypes)
  356. entryTypes = []
  357. else if (typeof entryTypes == 'string' || entryTypes instanceof String)
  358. entryTypes = [ entryTypes ];
  359. var realType = type(entryTypes);
  360.  
  361. if (realType.toLowerCase() == 'comment')
  362. var result = comment();
  363. else
  364. var result = entry();
  365.  
  366. result.type = realType;
  367. result._index = _parser.index();
  368. return result;
  369. }
  370.  
  371. var bibtexBase = {
  372. 'автор': {
  373. selector: 'author',
  374. getAuthors: function(text) {
  375. return text.split(' and ').map(function(name) {
  376. return name.replace(/~/g, ' ').replace(',', '');
  377. });
  378. },
  379. getWiki: function(authors) {
  380. return authors.map(function(name) {
  381. return new Template('nobr').add(name).toWiki()
  382. }).join(', ');
  383. },
  384. map: function(text) {
  385. var me = bibtexBase['автор'];
  386. return me.getWiki(me.getAuthors(text));
  387. },
  388. },
  389. 'заглавие': {
  390. selector: 'title',
  391. map: function(text) {
  392. return text.replace(/^"|"$/g, '')
  393. }
  394. },
  395. 'издание': {
  396. selector: 'journal',
  397. map: function(text) {
  398. return {
  399. aj: 'Astronomical Journal',
  400. actaa: 'Acta Astronomica',
  401. araa: 'Annual Review of Astron and Astrophys',
  402. apj: 'Astrophysical Journal',
  403. apjl: 'Astrophysical Journal, Letters',
  404. apjs: 'Astrophysical Journal, Supplement',
  405. ao: 'Applied Optics',
  406. apss: 'Astrophysics and Space Science',
  407. aap: 'Astronomy and Astrophysics',
  408. aapr: 'Astronomy and Astrophysics Reviews',
  409. aaps: 'Astronomy and Astrophysics, Supplement',
  410. azh: 'Astronomicheskii Zhurnal',
  411. baas: 'Bulletin of the AAS',
  412. caa: 'Chinese Astronomy and Astrophysics',
  413. cjaa: 'Chinese Journal of Astronomy and Astrophysics',
  414. icarus: 'Icarus',
  415. jcap: 'Journal of Cosmology and Astroparticle Physics',
  416. jrasc: 'Journal of the RAS of Canada',
  417. memras: 'Memoirs of the RAS',
  418. mnras: 'Monthly Notices of the RAS',
  419. na: 'New Astronomy',
  420. nar: 'New Astronomy Review',
  421. pra: 'Physical Review A: General Physics',
  422. prb: 'Physical Review B: Solid State',
  423. prc: 'Physical Review C',
  424. prd: 'Physical Review D',
  425. pre: 'Physical Review E',
  426. prl: 'Physical Review Letters',
  427. pasa: 'Publications of the Astron. Soc. of Australia',
  428. pasp: 'Publications of the ASP',
  429. pasj: 'Publications of the ASJ',
  430. rmxaa: 'Revista Mexicana de Astronomia y Astrofisica',
  431. qjras: 'Quarterly Journal of the RAS',
  432. skytel: 'Sky and Telescope',
  433. solphys: 'Solar Physics',
  434. sovast: 'Soviet Astronomy',
  435. ssr: 'Space Science Reviews',
  436. zap: 'Zeitschrift fuer Astrophysik',
  437. nat: 'Nature',
  438. iaucirc: 'IAU Cirulars',
  439. aplett: 'Astrophysics Letters',
  440. apspr: 'Astrophysics Space Physics Research',
  441. bain: 'Bulletin Astronomical Institute of the Netherlands',
  442. fcp: 'Fundamental Cosmic Physics',
  443. gca: 'Geochimica Cosmochimica Acta',
  444. grl: 'Geophysics Research Letters',
  445. jcp: 'Journal of Chemical Physics',
  446. jgr: 'Journal of Geophysics Research',
  447. jqsrt: 'Journal of Quantitiative Spectroscopy and Radiative Transfer',
  448. memsai: 'Mem. Societa Astronomica Italiana',
  449. nphysa: 'Nuclear Physics A',
  450. physrep: 'Physics Reports',
  451. physscr: 'Physica Scripta',
  452. planss: 'Planetary Space Science',
  453. procspie: 'Proceedings of the SPIE',
  454. }[text] || text;
  455. },
  456. },
  457. 'год': {
  458. selector: 'year',
  459. },
  460. 'выпуск': {
  461. selector: 'number',
  462. },
  463. 'том': {
  464. selector: 'volume',
  465. },
  466. 'страницы': {
  467. selector: 'pages',
  468. },
  469. 'издательство': {
  470. selector: 'publisher',
  471. },
  472. 'issn': {
  473. selector: 'issn',
  474. },
  475. 'doi': {
  476. selector: 'doi',
  477. },
  478. 'arxiv': {
  479. selector: 'eprint',
  480. map: function(text) {
  481. const prefix = 'arXiv:';
  482. if (text.indexOf(prefix) == 0)
  483. text = text.substr(prefix.length);
  484. return text;
  485. }
  486. },
  487. 'ссылка': { const: "" },
  488. 'ref': { const: "" },
  489. 'archiveurl': { const: "" },
  490. 'archivedate': { const: "" },
  491. };
  492.  
  493. var adsabsBibcode = (function() {
  494. var bibtex = clone(bibtexBase);
  495. bibtex.bibcode = { selector: 'bibcode' };
  496. return bibtex;
  497. })();
  498.  
  499. var ufnBibtex = (function() {
  500. var bibtex = clone(bibtexBase);
  501.  
  502. var nameRegex = /^(.+) (\S+)$/;
  503. var author = bibtex['автор'];
  504. author.map = function(text) {
  505. return author.getWiki(author.getAuthors(text).map(function(name) {
  506. var match = nameRegex.exec(name);
  507. if (!match) return name;
  508. return match[2] + ' ' + match[1];
  509. }));
  510. }
  511. return bibtex;
  512. })();
  513.  
  514. var googleBibtex = function(url) {
  515. var bibtex = clone(bibtexBase);
  516. bibtex.серия = { 'selector': 'series' };
  517. bibtex.страниц = { const: "" };
  518. bibtex.isbn = { 'selector': 'isbn' };
  519. delete bibtex.ссылка;
  520. delete bibtex.archiveurl;
  521. delete bibtex.archivedate;
  522. delete bibtex.ref;
  523. bibtex.ссылка = { const: url };
  524. bibtex.ref = { const: "" };
  525. return bibtex;
  526. };
  527.  
  528. var sciencedirectBibtex = (function() {
  529. var bibtex = clone(bibtexBase);
  530. bibtex.ссылка = { selector: 'url' };
  531. bibtex.doi.map = function(text) {
  532. var res = /http:\/\/dx\.doi\.org\/(.*)$/.exec(text) || [];
  533. return res[1] || text;
  534. }
  535. bibtex.страницы.map = function(text) {
  536. return text.replace(' - ', '—')
  537. }
  538. return bibtex;
  539. })();
  540.  
  541. var libGenesisBibtex = (function() {
  542. var bibtex = clone(bibtexBase);
  543. bibtex.выпуск = { selector: 'issue' };
  544. bibtex.страницы = { selector: 'page' };
  545. return bibtex;
  546. })();
  547.  
  548. var wileyBibtex = (function() {
  549. var bibtex = clone(bibtexBase);
  550. bibtex.ссылка = { selector: 'url' };
  551. return bibtex;
  552. })();
  553.  
  554. var jstorBibtex = (function() {
  555. var bibtex = clone(bibtexBase);
  556. bibtex.ссылка = { selector: 'url' };
  557. bibtex.выпуск.selector = function(obj) {
  558. return obj['number'] || obj['jstor_issuetitle'];
  559. }
  560. bibtex.страницы.map = function(text) {
  561. return text.replace(/^p?p\. /, "").replace('-', '—');
  562. };
  563. return bibtex;
  564. })();
  565.  
  566. var getWpFromObj = function(name, rules, obj) {
  567. var article = new Template(name);
  568.  
  569. for(var name in rules) {
  570. var rule = rules[name];
  571.  
  572. var value;
  573. if (rule.const !== undefined)
  574. value = rule.const
  575. else {
  576. if (typeof rule.selector === "function")
  577. value = rule.selector(obj);
  578. else
  579. value = obj[rule.selector];
  580. if (!value)continue;
  581. }
  582.  
  583. if (rule.map)
  584. value = rule.map(value, obj);
  585.  
  586. article.add(name, value);
  587. }
  588.  
  589. return article.toWiki();
  590. }
  591.  
  592. var testUrl = function(regex) {
  593. return regex.exec(window.location.href)
  594. }
  595.  
  596. var createWpButton = function(getResult, tag) {
  597. tag = tag || 'a';
  598. return $('<' + tag + '>')
  599. .attr('href', '#')
  600. .text('WP')
  601. .click(function(e) {
  602. e.preventDefault();
  603.  
  604. var promise = $.Deferred();
  605.  
  606. promise.done(function(result) {
  607. showResult(result);
  608. }).fail(function(result) {
  609. alert(result);
  610. });
  611.  
  612. getResult({
  613. resolve: function(result) {
  614. promise.resolve(result)
  615. },
  616. reject: function(result) {
  617. promise.reject(result)
  618. },
  619. });
  620. })
  621. .get(0);
  622. }
  623.  
  624. var showResult = function(text) {
  625. var button;
  626.  
  627. var dialog = $('<div>').css({
  628. 'position': 'fixed',
  629. 'top': 0,
  630. 'left': 0,
  631. 'width': '100%',
  632. 'height': '100%',
  633. 'z-index': 9999999,
  634. }).appendTo(document.body).append(
  635. // dimmer
  636. $('<div>').css({
  637. 'width': '100%',
  638. 'height': '100%',
  639. 'background-color': 'black',
  640. 'opacity': 0.6,
  641. })
  642. ).append(
  643. // dialog container
  644. $('<div>').css({
  645. 'display': 'table',
  646. 'position': 'absolute',
  647. 'top': 0,
  648. 'left': 0,
  649. 'width': '100%',
  650. 'height': '100%',
  651. 'font': '12px sans-serif',
  652. }).append(
  653. $('<div>').css({
  654. 'text-align': 'center',
  655. 'display': 'table-cell',
  656. 'vertical-align': 'middle',
  657. }).append(
  658. // dialog
  659. $('<div>').css({
  660. 'padding': 10,
  661. 'background-color': 'white',
  662. 'display': 'inline-block',
  663. 'max-width': '80%',
  664. }).append(
  665. // text
  666. $('<div>').css({
  667. 'padding': 5,
  668. 'white-space': 'pre-wrap',
  669. 'text-align': 'left',
  670. }).text(text)
  671. ).append(
  672. // buttons
  673. $('<div>').css({
  674. 'text-align': 'right',
  675. 'margin-top': 10,
  676. }).append(
  677. button = $('<button>').text('Copy & close').click(function() {
  678. GM_setClipboard(text);
  679. dialog.remove();
  680. }).focus()
  681. ).append(
  682. $('<button>').text('Cancel').click(function() {
  683. dialog.remove();
  684. })
  685. )
  686. )
  687. )
  688. )
  689. );
  690.  
  691. button.focus();
  692. }
  693.  
  694. var pages = [
  695. // pubmed
  696. {
  697. test: function() {
  698. return testUrl(/\/pubmed\/(\d+)$/);
  699. },
  700. process: function(match) {
  701. var id = match[1];
  702. $('#messagearea').after(
  703. $('<div>').append(
  704. createWpButton(function(promise) {
  705. ajax({
  706. method: "GET",
  707. url: id + '?dopt=Abstract&report=xml&format=text',
  708. onload: function(response) {
  709. var html = new DOMParser().parseFromString(response.responseText, "text/html");
  710. var xml = new DOMParser().parseFromString(html.body.textContent, "text/xml");
  711. promise.resolve(getWpFromXml(templates.article, pubmed, xml));
  712. }
  713. });
  714. })
  715. )
  716. );
  717. },
  718. },
  719. // adsabs
  720. {
  721. test: function() {
  722. return testUrl(/adsabs\.harvard\.edu\/(abs|doi)\/(.*)$/);
  723. },
  724. process: function(match) {
  725. var id = match[2];
  726. var button = createWpButton(function(promise) {
  727. ajax({
  728. method: "GET",
  729. url: '/cgi-bin/nph-bib_query?data_type=BIBTEX&bibcode=' + id,
  730. onload: function(response) {
  731. var index = response.responseText.indexOf('@ARTICLE{');
  732. if (index == -1) {
  733. promise.reject('bibtex not found');
  734. return;
  735. }
  736.  
  737. try {
  738. promise.resolve(getWpFromObj(templates.article, adsabsBibcode, Bibtex(response.responseText, index, 'article')));
  739. } catch(e) {
  740. promise.reject(e + '\n' + e.stack);
  741. }
  742. }
  743. });
  744. }, false);
  745. $('h3').eq(0)
  746. .append(document.createTextNode(' '))
  747. .append(button);
  748. },
  749. },
  750. // ufn
  751. {
  752. test: function() {
  753. return testUrl(/\/ufn\.ru\/ru\/articles\/(\d+\/\d+\/\w+)\//);
  754. },
  755. process: function(match) {
  756. var id = match[1];
  757.  
  758. var button = createWpButton(function(promise) {
  759. ajax({
  760. method: "GET",
  761. url: '/ru/articles/' + id + '/citation/ru/bibtex.html',
  762. onload: function(response) {
  763. var html = new DOMParser().parseFromString(response.responseText, "text/html");
  764.  
  765. var node = html.body.querySelector('.cit_code > pre');
  766. if (!node) {
  767. promise.reject('bibtex not found');
  768. return;
  769. }
  770.  
  771. try {
  772. promise.resolve(getWpFromObj(templates.article, ufnBibtex, Bibtex(node.textContent, 0, 'article')));
  773. } catch(e) {
  774. promise.reject(e + '\n' + e.stack);
  775. }
  776. }
  777. });
  778. });
  779.  
  780. $('#print > table tr > td').next().append(
  781. $('<td>').append(button)
  782. );
  783. },
  784. },
  785. // google books
  786. {
  787. test: function() {
  788. return window.self == window.top && testUrl(/https?:\/\/books\.google\..+\/books.*[?&]id=([^&$]+)/);
  789. },
  790. process: function(match) {
  791. var id = match[1];
  792.  
  793. var button = createWpButton(function(promise) {
  794. ajax({
  795. method: "GET",
  796. url: 'http://books.google.us/books/download/?id=' + id + '&output=bibtex',
  797. onload: function(response) {
  798. try {
  799. promise.resolve(getWpFromObj(templates.book, googleBibtex('http://books.google.com/books?id=' + id), Bibtex(response.responseText, 0, 'book')));
  800. } catch(e) {
  801. promise.reject(e + '\n' + e.stack);
  802. }
  803. }
  804. });
  805. });
  806. $(button).addClass('gb-button').css('margin-left', '4px');
  807. $('.metadata_value > .gb-button:last-child, #gb-get-book-container > *:first-child')
  808. .parent()
  809. .append(button);
  810. },
  811. },
  812. // sciencedirect
  813. {
  814. test: function() {
  815. return testUrl(/sciencedirect\.com\/science\/article\//);
  816. },
  817. process: function() {
  818. var button = createWpButton(function(promise) {
  819. var params = [];
  820. $('form[name=exportCite] input[type=hidden]').each(function(i, hidden) {
  821. params.push(encodeURIComponent($(hidden).attr('name')) + '=' + encodeURIComponent($(hidden).val()));
  822. })
  823. ajax({
  824. method: "GET",
  825. url: $('form[name=exportCite]').attr('action') + params.join('&') + '&citation-type=BIBTEX',
  826. onload: function(response) {
  827. try {
  828. promise.resolve(getWpFromObj(templates.article, sciencedirectBibtex, Bibtex(response.responseText, 0, 'article')));
  829. } catch(e) {
  830. promise.reject(e + '\n' + e.stack);
  831. }
  832. }
  833. });
  834. }, 'input');
  835.  
  836. $('.exportTxt').after($('<div />').append(
  837. $(button).attr('type', 'button').val('WP').css({
  838. 'border-radius': '5px',
  839. 'padding': '3px 5px 3px 24px',
  840. 'border': '1px solid rgb(204, 204, 204)',
  841. 'color': '#0156AA',
  842. 'background': '#FFF',
  843. 'margin-left': '2px',
  844. 'cursor': 'pointer',
  845. 'height': '24px',
  846. 'margin-bottom': '5px',
  847. 'font-weight': 'bold',
  848. })
  849. ));
  850. },
  851. },
  852. // Library Genesis
  853. {
  854. test: function() {
  855. return testUrl(/gen\.lib\.rus\.ec\/scimag\//);
  856. },
  857. process: function() {
  858. var node = document.querySelector('form[name=search]');
  859. while(node && node.nodeName != 'TABLE') {
  860. node = node.nextSibling;
  861. }
  862. var rows = node.querySelectorAll('tr');
  863. for(var i = 0; i < rows.length; i++) {
  864. let anchor = rows[i].querySelector('td:first-child > a');
  865. if (!anchor)
  866. continue;
  867. let doi = anchor.textContent;
  868. var button = createWpButton(function(promise) {
  869. ajax({
  870. method: "GET",
  871. url: 'http://gen.lib.rus.ec/scimag/bibtex.php?doi=' + doi,
  872. onload: function(response) {
  873. var html = new DOMParser().parseFromString(response.responseText, "text/html");
  874. try {
  875. promise.resolve(getWpFromObj(templates.article, libGenesisBibtex, Bibtex(html.querySelector('textarea#bibtext').value, 0, 'article')));
  876. } catch(e) {
  877. promise.reject(e + '\n' + e.stack);
  878. }
  879. }
  880. });
  881. });
  882. rows[i].querySelector('td:last-child').appendChild(button);
  883. button.style.fontWeight = 'bold';
  884. }
  885. }
  886. },
  887. // wiley
  888. {
  889. test: function() {
  890. return testUrl(/onlinelibrary\.wiley\.com\/doi\//)
  891. },
  892. process: function() {
  893. var doi = /^DOI:\s+(.+)$/.exec($('#doi').text().trim());
  894. if (!doi) return;
  895. doi = doi[1];
  896.  
  897. var button = createWpButton(function(promise) {
  898. ajax({
  899. method: 'POST',
  900. url: '/documentcitationdownloadformsubmit',
  901. data: 'doi=' + encodeURIComponent(doi) + '&fileFormat=BIBTEX&hasAbstract=CITATION',
  902. headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  903. onload: function(response) {
  904. try {
  905. var bibtex = Bibtex(response.responseText, 0);
  906. bibtex.url = window.location.href;
  907.  
  908. var template = {
  909. 'article': templates.article,
  910. }[bibtex.type.toLowerCase()];
  911.  
  912. if (!template) {
  913. promise.reject('unknown type: ' + bibtex.type);
  914. return;
  915. }
  916. promise.resolve(getWpFromObj(template, wileyBibtex, bibtex));
  917. } catch(e) {
  918. promise.reject(e + '\n' + e.stack);
  919. }
  920. }
  921. });
  922. });
  923. setTimeout(function() {
  924. $('#toggleAddInfo').append(button);
  925. }, 500);
  926. }
  927. },
  928. // jstor
  929. {
  930. test: function() {
  931. return testUrl(/www\.jstor\.org\/[^\/]+\/(.*?)($|\?)/)
  932. },
  933. process: function(doi) {
  934. doi = decodeURIComponent(doi[1]);
  935. var button = createWpButton(function(promise) {
  936. ajax({
  937. method: 'GET',
  938. url: '/action/downloadSingleCitationSec?userAction=export&format=bibtex&include=abs&singleCitation=true&noDoi=yesDoi&doi=' + doi,
  939. onload: function(response) {
  940. try {
  941. var txt = response.responseText.trim();
  942. const header = 'JSTOR CITATION LIST';
  943.  
  944. var index = txt.indexOf(header);
  945. if (index == -1)
  946. throw new Error('header not found');
  947. index += header.length;
  948.  
  949. while(index < txt.length) {
  950. var bibtex = Bibtex(txt, index, [ 'article', 'comment', 'book' ]);
  951. if (bibtex.type != 'comment')
  952. break;
  953. index = bibtex._index;
  954. }
  955.  
  956. if (!bibtex)
  957. throw new Error('bibtex not found');
  958.  
  959. var template = {
  960. 'article': templates.article,
  961. 'book': templates.book,
  962. }[bibtex.type.toLowerCase()];
  963. promise.resolve(getWpFromObj(template, jstorBibtex, bibtex));
  964. } catch(e) {
  965. promise.reject(e + '\n' + e.stack);
  966. }
  967. }
  968. });
  969. });
  970.  
  971. $('#navSearchContainer').append($(button).css('margin-left', '10px'));
  972. }
  973. },
  974. ];
  975.  
  976. try {
  977. pages.forEach(function(page) {
  978. var res = page.test();
  979. if (res) {
  980. page.process(res);
  981. return false; // break
  982. }
  983. });
  984. } catch(e) {
  985. alert(e + '\n\n' + e.stack);
  986. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址