vvCiteWeb

Заполняет вики-шаблон Cite web для текущей страницы.

  1. // ==UserScript==
  2. // @description Заполняет вики-шаблон Cite web для текущей страницы.
  3. // @exclude https://ru.wikipedia.org/*
  4. // @exclude https://commons.wikimedia.org/*
  5. // @exclude http://books.google.com/*
  6. // @exclude http://books.google.ru/*
  7. // @grant GM_xmlhttpRequest
  8. // @icon http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/32/Actions-insert-link-icon.png
  9. // @match http://*/*
  10. // @match https://*/*
  11. // @name vvCiteWeb
  12. // @namespace https://ru.wikipedia.org/wiki/User:Neolexx
  13. // @run-at document-end
  14. // @version 2.0
  15. // ==/UserScript==
  16. /*
  17. * "THE BEER-WARE LICENSE" (Revision 42):
  18. * Neolexx wrote this file. As long as you retain this notice you can do
  19. * whatever you want with this stuff. If we meet some day, and you think
  20. * this stuff is worth it, you can buy me a beer in return.
  21. *
  22. * Icon by Oxygen Team, GNU LGPL https://www.gnu.org/licenses/lgpl.html
  23. */
  24. 'use strict';
  25. void(function(){
  26. if ( (typeof window != 'object') || (window.top != window.self) ) {return;}
  27. if ( /wikipedia.org/.test(document.location.hostname) ) {return;}
  28. var fontStyle = 'margin:4px;white-space:nowrap;font:normal normal normal 14px Arial,sans-serif;';
  29. var voidValue = 'добавить';
  30. var languageList = {
  31. 'ru' : 'русский',
  32. 'en' : 'английский',
  33. 'be' : 'белорусский',
  34. 'de' : 'немецкий',
  35. 'uk' : 'украинский',
  36. 'fr' : 'французский',
  37. 'jp' : 'японский'
  38. }
  39. var publisherList = {
  40. 'lenta.ru' : 'Лента.Ру',
  41. 'ria.ru' : 'РИА Новости',
  42. 'regnum.ru' : 'ИА REGNUM',
  43. 'rosbalt.ru' : 'Росбалт',
  44. 'km.ru' : 'KM.RU',
  45. 'cnn.com' : 'CNN',
  46. 'foxnews.com' : 'FOX News',
  47. 'bbc.com' : 'BBC',
  48. 'theguardian.com' : 'Guardian',
  49. 'nytimes.com' : 'New York Times',
  50. 'wsj.com' : 'Wall Street Journal'
  51. }
  52. var jsonData = null;
  53. var isoDate, isoTimestamp, pageUrl = '';
  54. var nodeText = ( 'innerText' in document.body )? 'innerText' : 'textContent';
  55. var Container = document.createElement('DIV');
  56. Container.style.position = 'fixed';
  57. Container.style.zIndex = '1001';
  58. Container.style.left = '0';
  59. Container.style.top = '0';
  60. Container.style.width = '34px';
  61. Container.style.height = '34px';
  62. Container.style.margin = '0';
  63. Container.style.padding = '1px';
  64. Container.style.overflow = 'hidden';
  65. Container.style.backgroundColor = '#FFFFFF';
  66. Container.style.backgroundImage =
  67. 'url(http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/32/Actions-insert-link-icon.png)';
  68. Container.style.backgroundRepeat = 'no-repeat';
  69. Container.style.cursor = 'pointer';
  70. document.body.appendChild(Container).addEventListener('click', vvCiteWeb, true, false);
  71. function vvCiteWeb(evt) {
  72. evt.stopPropagation();
  73. evt.preventDefault();
  74. Container.removeEventListener('click', vvCiteWeb, true);
  75. Container.style.width = '300px';
  76. Container.style.height = 'auto';
  77. Container.style.border = '1px solid silver';
  78. Container.style.margin = '2px';
  79. Container.style.padding = '5px 10px';
  80. Container.style.overflowX = 'auto';
  81. Container.style.overflowY = 'visible';
  82. Container.style.backgroundImage = 'none';
  83. Container.style.backgroundRepeat = 'initial';
  84. Container.style.cursor = 'auto';
  85. window.setTimeout(fillData, 1);
  86. }
  87. function fillData() {
  88. getDatePoint();
  89. pageUrl = getTemplateSafeString(document.location.href);
  90. Container.innerHTML = ''.concat(
  91. '<table border="0" cellspacing="0" cellpadding="0"><tbody>',
  92. getSelectableDataRow('vvLanguage', 'Язык', languageList, getSourceLanguage()),
  93. getStaticDataRow('vvArchive', 'Архивная копия', 'проверяется...'),
  94. getStaticDataRow('vvArchiveDate', 'Дата архивации:', 'проверяется...'),
  95. getEditableDataRow('vvPublisher', 'Издание / сайт', getSourcePublisher()),
  96. getEditableDataRow('vvTitle', 'Заглавие', getSourceTitle()),
  97. getEditableDataRow('vvAuthor', 'Автор(ы)', voidValue, 'Фамилия И. О. через запятую'),
  98. getEditableDataRow('vvDate', 'Дата публикации', voidValue, 'В формате ГГГГ-ММ-ДД'),
  99. getEditableDataRow('vvQuote', 'Цитата', voidValue, 'Краткая цитата без кавычек'),
  100. '</tbody></table>',
  101. '<p style="margin-top:5px;">',
  102. '<button style="width:90%;" type="button" id="vvGet1">Шаблон одной строкой</button></p>',
  103. '<p style="margin-top:5px;">',
  104. '<button style="width:90%;" type="button" id="vvGet2">Шаблон c pretty-print</button></p>'
  105. );
  106. window.setTimeout(checkArchiveCopy, 1);
  107. }
  108. function getDatePoint() {
  109. var now = new Date();
  110. var yyyy = now.getUTCFullYear();
  111. var m = now.getUTCMonth() + 1;
  112. var mm = m < 10 ? '0'+m : m;
  113. var d = now.getUTCDate();
  114. var dd = d < 10 ? '0'+d : d;
  115. var h = now.getUTCHours();
  116. var hh = h < 10 ? '0'+h : h;
  117. var n = now.getUTCMinutes();
  118. var mn = n < 10 ? '0'+n : n;
  119. var s = now.getUTCSeconds();
  120. var ss = s < 10 ? '0'+s : s;
  121. isoDate = ''.concat(yyyy, '-', mm, '-', dd);
  122. isoTimestamp = ''.concat(yyyy,mm,dd,hh,mn,ss);
  123. }
  124. function getSourceTitle() {
  125. var title;
  126. var header = _('H1');
  127. if ( header != null ) {
  128. title = getTemplateSafeString(header[nodeText].trim()) || '?';
  129. }
  130. else if ( !!document.title ) {
  131. title = document.title.trim() || '?';
  132. }
  133. else {
  134. title = '?';
  135. }
  136. return title;
  137. }
  138. function getSourceLanguage() {
  139. var l = _('HTML').getAttribute('lang') || _('HTML').getAttribute('xml:lang') || '';
  140. var lng;
  141. if ( !!l.length ) {
  142. lng = l.substr(0,2).toLowerCase();
  143. }
  144. else if ( !/[\u0400-\u04FF]/.test(getSourceTitle()) ) {
  145. lng = 'en'; // an educated guess...
  146. }
  147. else {
  148. lng = 'ru';
  149. }
  150. return lng;
  151. }
  152. function getSourcePublisher() {
  153. var domain = document.location.hostname.match(/\w+\.\w+$/);
  154. return (domain in publisherList)? publisherList[domain] : voidValue;
  155. }
  156. function getStaticDataRow(id, label, defaultValue) {
  157. return '<tr><td>'.concat(getLabel(label),
  158. '</td><td>', getKeyValueDivider(), '</td><td>',
  159. getStaticField(id, defaultValue),
  160. '</td></tr>'
  161. );
  162. }
  163. function getEditableDataRow(id, label, defaultValue, promptMessage) {
  164. return '<tr><td>'.concat(getLabel(label),
  165. '</td><td>', getKeyValueDivider(), '</td><td>',
  166. getEditableField(id, defaultValue, promptMessage||label),
  167. '</td></tr>'
  168. );
  169. }
  170. function getSelectableDataRow(id, label, values, def) {
  171. return '<tr><td>'.concat(getLabel(label),
  172. '</td><td>', getKeyValueDivider(), '</td><td>',
  173. getSelectableField(id, values, def),
  174. '</td></tr>'
  175. );
  176. }
  177. function getKeyValueDivider() {
  178. return '<var'.concat(' style="', fontStyle,
  179. 'color:black;cursor:default;">=</var>'
  180. );
  181. }
  182. function getLabel(label) {
  183. return '<dfn'.concat(' style="', fontStyle,
  184. 'color:black;cursor:default;">',
  185. label, '</dfn>'
  186. );
  187. }
  188. function getStaticField(id, defaultValue) {
  189. return '<var id="'.concat(id, '" style="', fontStyle,
  190. 'color:black;cursor:default;">',
  191. defaultValue, '</var>'
  192. );
  193. }
  194. function getEditableField(id, defaultValue, promptMessage) {
  195. return '<var id="'.concat(id, '" style="',
  196. fontStyle, 'color:#0645AD;cursor:pointer;" ',
  197. 'onmouseover="this.style.textDecoration=\'underline\';" ',
  198. 'onmouseout="this.style.textDecoration=\'none\';" ',
  199. 'onclick="',
  200. 'var t = ( \'innerText\' in document.body )? \'innerText\' : \'textContent\';',
  201. 'var txt = window.prompt(\'', extend_prompt(), '\',',
  202. 'this[t]==\'', voidValue, '\'?\'\'\:this[t]);',
  203. 'if ( !!txt && !!txt.trim() ) {this[t] = txt.trim();}">',
  204. defaultValue, '</var>'
  205. );
  206. function extend_prompt() {
  207. var w = 150;
  208. var len = promptMessage.length;
  209. if ( len >= w-2) {
  210. return promptMessage;
  211. }
  212. else {
  213. var ext = Math.round((w-len)/2);
  214. return (new Array(ext).join('\u00A0')).concat(
  215. promptMessage, (new Array(ext).join('\u00A0'))
  216. )
  217. }
  218. }
  219. }
  220. function getSelectableField(id, values, def) {
  221. var sel = '<select id="'.concat(id, '" style="', fontStyle, '">');
  222. for (var k in values) {
  223. sel+= '<option value="'.concat(
  224. k, '"', k==def?' selected>':'>', values[k], '</option>'
  225. );
  226. }
  227. return sel + '</select>';
  228. }
  229. function checkArchiveCopy() {
  230. if ( typeof GM_xmlhttpRequest == 'undefined' ) {
  231. alert('Вызовы между доменами запрещены.');
  232. return;
  233. }
  234. GM_xmlhttpRequest({
  235. method: 'GET',
  236. url : 'https://archive.org/wayback/available?url='.concat(
  237. pageUrl, '&timestamp=', isoTimestamp
  238. ),
  239. onload: function(que) {
  240. jsonData = JSON.parse(que.responseText);
  241. if ( !!jsonData.archived_snapshots.closest ) {
  242. $('vvArchive').innerHTML = '<a href="'.concat(
  243. jsonData.archived_snapshots.closest.url,
  244. '" target="_blank" title="проверить" style="',
  245. fontStyle, 'color:#0645AD;text-decoration:underline;">',
  246. jsonData.archived_snapshots.closest.url, '</a>'
  247. );
  248. var s = jsonData.archived_snapshots.closest.timestamp;
  249. $('vvArchiveDate')[nodeText] = ''+s.substr(0,4)+'-'+s.substr(4,2)+'-'+s.substr(6,2);
  250. }
  251. else {
  252. $('vvArchive').innerHTML = '<var '.concat(
  253. 'style="', fontStyle, 'color:black;cursor:default;">нет</var>\u00A0',
  254. '<a href="https://web.archive.org/save/', pageUrl,
  255. '" target="_blank" style="',
  256. fontStyle, 'color:#0645AD;text-decoration:underline;">',
  257. 'создать вручную</a>'
  258. );
  259. $('vvArchiveDate')[nodeText] = 'нет';
  260. }
  261. }
  262. });
  263. $('vvGet1').onclick = getSingleLineSource;
  264. $('vvGet2').onclick = getPrettyPrintSource;
  265. }
  266. function getSingleLineSource() {
  267. var out = '{{cite web';
  268. out+= '|url='+pageUrl+'\n';
  269. out+= '|title='+$('vvTitle')[nodeText];
  270. if ( $('vvAuthor')[nodeText] != voidValue ) {
  271. out+= '|author='+$('vvAuthor')[nodeText];
  272. }
  273. if ( $('vvQuote')[nodeText] != voidValue ) {
  274. out+= '|quote'+$('vvQuote')[nodeText];
  275. }
  276. if ( $('vvDate')[nodeText] != voidValue ) {
  277. out+= '|date='+$('vvDate')[nodeText];
  278. }
  279. if ( $('vvPublisher')[nodeText] != voidValue ) {
  280. out+= '|publisher'+$('vvPublisher')[nodeText];
  281. }
  282. out+= '|accessdate='+isoDate;
  283. if ( $('vvLanguage').options[$('vvLanguage').selectedIndex].value != 'ru' ) {
  284. out+= '|language='+$('vvLanguage').options[$('vvLanguage').selectedIndex].value;
  285. }
  286. out+= '|deadlink=';
  287. if ( $('vvArchiveDate')[nodeText] != 'нет' ) {
  288. out+= '|archiveurl='+$('vvArchive')[nodeText];
  289. out+= '|archivedate='+$('vvArchiveDate')[nodeText]+'\n';
  290. }
  291. out+= '}}';
  292. Container.innerHTML = '<form action="" onsubmit="return false">'.concat(
  293. '<textarea cols="32" rows="12" onclick="this.select();">',
  294. out, '</textarea></form>'
  295. );
  296. }
  297. function getPrettyPrintSource() {
  298. var out = '{{cite web\n';
  299. out+= ' |url = '+pageUrl+'\n';
  300. out+= ' |title = '+$('vvTitle')[nodeText]+'\n';
  301. if ( $('vvAuthor')[nodeText] != voidValue ) {
  302. out+= ' |author = '+$('vvAuthor')[nodeText]+'\n';
  303. }
  304. if ( $('vvQuote')[nodeText] != voidValue ) {
  305. out+= ' |quote = '+$('vvQuote')[nodeText]+'\n';
  306. }
  307. if ( $('vvDate')[nodeText] != voidValue ) {
  308. out+= ' |date = '+$('vvDate')[nodeText]+'\n';
  309. }
  310. if ( $('vvPublisher')[nodeText] != voidValue ) {
  311. out+= ' |publisher = '+$('vvPublisher')[nodeText]+'\n';
  312. }
  313. out+= ' |accessdate = '+isoDate+'\n';
  314. if ( $('vvLanguage').options[$('vvLanguage').selectedIndex].value != 'ru' ) {
  315. out+= ' |language = '+$('vvLanguage').options[$('vvLanguage').selectedIndex].value+'\n';
  316. }
  317. out+= ' |deadlink = \n';
  318. if ( $('vvArchiveDate')[nodeText] != 'нет' ) {
  319. out+= ' |archiveurl = '+$('vvArchive')[nodeText]+'\n';
  320. out+= ' |archivedate = '+$('vvArchiveDate')[nodeText]+'\n';
  321. }
  322. out+= '}}';
  323. Container.innerHTML = '<form action="" onsubmit="return false">'.concat(
  324. '<textarea cols="32" rows="12" onclick="this.select();">',
  325. out, '</textarea></form>'
  326. );
  327. }
  328. function getTemplateSafeString(str) {
  329. return str.
  330. replace(/\n/g, ' ');
  331. replace(/\|/g, '%7C').
  332. replace(/\{/g, '%7B').
  333. replace(/\[/g, '%5B');
  334. }
  335. function _(tag) {
  336. try {
  337. return document.getElementsByTagName(tag)[0];
  338. }
  339. catch(e) {
  340. return null;
  341. }
  342. }
  343. function $(id) {
  344. return document.getElementById(id);
  345. }
  346. })()