You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
7.6 KiB

7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
6 years ago
6 years ago
5 years ago
5 years ago
7 years ago
5 years ago
5 years ago
7 years ago
5 years ago
5 years ago
5 years ago
7 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
  1. var wikidata = require('./wikidata')
  2. var cache = {}
  3. var loadClash = {}
  4. function stripLinks (dom) {
  5. var as = dom.getElementsByTagName('a')
  6. as = Array.prototype.slice.call(as)
  7. as.forEach(function (current) {
  8. while (current.firstChild) {
  9. current.parentNode.insertBefore(current.firstChild, current)
  10. }
  11. current.parentNode.removeChild(current)
  12. })
  13. }
  14. function prepare (div) {
  15. var i
  16. var contents = div.getElementsByTagName('div')
  17. for (i = 0; i < contents.length; i++) {
  18. if (contents[i].id === 'mw-content-text') {
  19. var content = contents[i]
  20. break
  21. }
  22. }
  23. if (!content) {
  24. return null
  25. }
  26. var p = content.firstChild.firstChild
  27. while (p && (p.tagName !== 'P' || p.className !== '' || p.textContent.match(/^\s*$/))) {
  28. p = p.nextSibling
  29. }
  30. if (!p) {
  31. return null
  32. }
  33. stripLinks(p)
  34. // first image
  35. var imgs = content.getElementsByTagName('img')
  36. for (i = 0; i < imgs.length; i++) {
  37. var img = imgs[i]
  38. // ignore icons
  39. if (img.width <= 64 && img.height <= 64) {
  40. continue
  41. }
  42. img.removeAttribute('width')
  43. img.removeAttribute('height')
  44. p.insertBefore(img, p.firstChild)
  45. break
  46. }
  47. return p.innerHTML
  48. }
  49. function get (value, callback) {
  50. var cacheId = options.data_lang + ':' + value
  51. if (cacheId in cache) {
  52. return callback(null, cache[cacheId])
  53. }
  54. if (cacheId in loadClash) {
  55. loadClash[cacheId].push(callback)
  56. return
  57. }
  58. loadClash[cacheId] = []
  59. ajax('wikipedia',
  60. {
  61. page: value,
  62. lang: options.data_lang
  63. },
  64. function (result) {
  65. if (!result.content) {
  66. return callback(new Error('error'), null)
  67. }
  68. cache[cacheId] = result
  69. callback(null, result)
  70. loadClash[cacheId].forEach(function (d) {
  71. d(null, result)
  72. })
  73. delete loadClash[cacheId]
  74. }
  75. )
  76. }
  77. function getAbstract (value, callback) {
  78. get(value,
  79. function (err, result) {
  80. var text = null
  81. if (result) {
  82. var div = document.createElement('div')
  83. div.innerHTML = result.content
  84. text = prepare(div)
  85. text += ' <a target="_blank" href="' + result.languages[result.language] + '">' + lang('more') + '</a>'
  86. }
  87. callback(err, text)
  88. }
  89. )
  90. }
  91. register_hook('show-details', function (data, category, dom, callback) {
  92. var ob = data.object
  93. var found = 0
  94. var foundPrefixes = []
  95. var finished = 0
  96. var errs = []
  97. var h, k, m
  98. var div = document.createElement('div')
  99. div.className = 'wikipedia'
  100. if ('wikipedia' in ob.tags) {
  101. foundPrefixes.push('')
  102. ob.tags.wikipedia.split(/;/g).forEach(value => {
  103. value = value.trim()
  104. found++
  105. showWikipedia(value, div, done)
  106. })
  107. }
  108. for (k in ob.tags) {
  109. m = k.match(/^(.*):wikipedia$/)
  110. if (m) {
  111. let prefix = m[1]
  112. h = document.createElement('h4')
  113. h.appendChild(document.createTextNode(lang('tag:' + prefix)))
  114. div.appendChild(h)
  115. foundPrefixes.push(prefix)
  116. ob.tags[k].split(/;/g).forEach(value => {
  117. value = value.trim()
  118. found++
  119. showWikipedia(value, div, done)
  120. })
  121. }
  122. m = k.match(/^((.*):)?wikipedia:(.*)$/)
  123. if (m) {
  124. let prefix = m[1]
  125. if (typeof prefix === 'undefined' && foundPrefixes.indexOf('') !== -1) {
  126. continue
  127. }
  128. if (foundPrefixes.indexOf(prefix) !== -1) {
  129. continue
  130. }
  131. if (prefix) {
  132. h = document.createElement('h4')
  133. h.appendChild(document.createTextNode(lang('tag:' + prefix)))
  134. div.appendChild(h)
  135. }
  136. foundPrefixes.push(prefix)
  137. ;(m[3] + ':' + ob.tags[k]).split(/;/g).forEach(value => {
  138. found++
  139. showWikipedia(value, div, done)
  140. })
  141. }
  142. }
  143. if (ob.tags.wikidata && foundPrefixes.indexOf('') === -1) {
  144. foundPrefixes.push('')
  145. ob.tags.wikidata.split(/;/g).forEach(value => {
  146. value = value.trim()
  147. found++
  148. wikidata.load(value, function (err, result) {
  149. var x
  150. if (err) {
  151. return done(err)
  152. }
  153. if (!result.sitelinks) {
  154. return done(new Error('No Wikipedia links defined for Wikidata'))
  155. }
  156. if (options.data_lang + 'wiki' in result.sitelinks) {
  157. x = result.sitelinks[options.data_lang + 'wiki']
  158. return showWikipedia(options.data_lang + ':' + x.title, div, done)
  159. }
  160. for (k in result.sitelinks) {
  161. if (k === 'commonswiki') {
  162. continue
  163. }
  164. x = result.sitelinks[k]
  165. m = k.match(/^(.*)wiki$/)
  166. return showWikipedia(m[1] + ':' + x.title, div, done)
  167. }
  168. done()
  169. })
  170. })
  171. }
  172. for (k in ob.tags) {
  173. m = k.match(/^(.*):wikidata$/)
  174. if (m) {
  175. let prefix = m[1]
  176. found++
  177. if (foundPrefixes.indexOf(prefix) !== -1) {
  178. continue
  179. }
  180. foundPrefixes.push(prefix)
  181. h = document.createElement('h4')
  182. h.appendChild(document.createTextNode(lang('tag:' + prefix)))
  183. div.appendChild(h)
  184. ob.tags[k].split(/;/g).forEach(value => {
  185. value = value.trim()
  186. wikidata.load(value, (err, result) => {
  187. var x
  188. if (err) {
  189. return done(err)
  190. }
  191. if (!result.sitelinks) {
  192. return done()
  193. }
  194. if (options.data_lang + 'wiki' in result.sitelinks) {
  195. x = result.sitelinks[options.data_lang + 'wiki']
  196. return showWikipedia(options.data_lang + ':' + x.title, div, done)
  197. }
  198. for (k in result.sitelinks) {
  199. if (k === 'commonswiki') {
  200. continue
  201. }
  202. x = result.sitelinks[k]
  203. m = k.match(/^(.*)wiki$/)
  204. return showWikipedia(m[1] + ':' + x.title, div, done)
  205. }
  206. done()
  207. })
  208. })
  209. }
  210. }
  211. if (found) {
  212. h = document.createElement('h3')
  213. h.appendChild(document.createTextNode(lang('tag:wikipedia')))
  214. dom.appendChild(h)
  215. dom.appendChild(div)
  216. }
  217. function done (err) {
  218. finished++
  219. if (err) {
  220. errs.push(err)
  221. }
  222. if (found === finished) {
  223. callback(errs.length ? errs : null)
  224. }
  225. }
  226. })
  227. function showWikipedia (tagValue, dom, callback) {
  228. var block = document.createElement('div')
  229. block.className = 'loading'
  230. dom.appendChild(block)
  231. var l = document.createElement('div')
  232. l.innerHTML = '<i class="fa fa-spinner fa-pulse fa-fw"></i><span class="sr-only">Loading...</span>'
  233. l.className = 'loadingIndicator'
  234. block.appendChild(l)
  235. getAbstract(tagValue, function (err, text) {
  236. if (!text) {
  237. block.appendChild(document.createTextNode(lang('wikipedia:no-url-parse')))
  238. }
  239. var div = document.createElement('div')
  240. div.innerHTML = text
  241. block.appendChild(div)
  242. block.removeChild(l)
  243. block.className = 'clearfix'
  244. callback(err)
  245. })
  246. }
  247. function getImages (tagValue, callback) {
  248. var i
  249. get(tagValue, function (err, result) {
  250. if (err) {
  251. return callback(err, null)
  252. }
  253. var div = document.createElement('div')
  254. div.innerHTML = result.content
  255. var imgs = div.getElementsByTagName('img')
  256. var ret = []
  257. for (i = 0; i < imgs.length; i++) {
  258. var img = imgs[i]
  259. // ignore icons
  260. if (img.width <= 64 && img.height <= 64) {
  261. continue
  262. }
  263. img.removeAttribute('width')
  264. img.removeAttribute('height')
  265. var m = img.src.match(/^https?:\/\/upload.wikimedia.org\/wikipedia\/commons\/thumb\/\w+\/\w+\/([^/]+)/)
  266. if (m) {
  267. var file = decodeURIComponent(m[1]).replace(/_/g, ' ')
  268. ret.push({
  269. id: file,
  270. width: img.getAttribute('data-file-width'),
  271. height: img.getAttribute('data-file-height')
  272. })
  273. }
  274. }
  275. callback(null, ret)
  276. })
  277. }
  278. module.exports = {
  279. getImages: getImages
  280. }