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.
432 lines
9.6 KiB
432 lines
9.6 KiB
const async = require('async')
|
|
const OverpassLayer = require('overpass-layer')
|
|
|
|
var wikidata = require('./wikidata')
|
|
const displayBlock = require('./displayBlock')
|
|
|
|
var cache = {}
|
|
var getAbstractCache = {}
|
|
var loadClash = {}
|
|
|
|
function stripLinks (dom) {
|
|
var as = dom.getElementsByTagName('a')
|
|
as = Array.prototype.slice.call(as)
|
|
|
|
as.forEach(function (current) {
|
|
while (current.firstChild) {
|
|
current.parentNode.insertBefore(current.firstChild, current)
|
|
}
|
|
|
|
current.parentNode.removeChild(current)
|
|
})
|
|
}
|
|
|
|
function prepare (div) {
|
|
var i
|
|
|
|
var contents = div.getElementsByTagName('div')
|
|
for (i = 0; i < contents.length; i++) {
|
|
if (contents[i].id === 'mw-content-text') {
|
|
var content = contents[i]
|
|
break
|
|
}
|
|
}
|
|
|
|
if (!content) {
|
|
return null
|
|
}
|
|
|
|
var p = content.firstChild.firstChild
|
|
while (p && (p.tagName !== 'P' || p.className !== '' || p.textContent.match(/^\s*$/) || p.querySelector('span#coordinates'))) {
|
|
p = p.nextSibling
|
|
}
|
|
|
|
if (!p) {
|
|
return null
|
|
}
|
|
|
|
stripLinks(p)
|
|
|
|
// first image
|
|
var imgs = content.getElementsByTagName('img')
|
|
for (i = 0; i < imgs.length; i++) {
|
|
var img = imgs[i]
|
|
|
|
// ignore icons
|
|
if (img.width <= 64 && img.height <= 64) {
|
|
continue
|
|
}
|
|
|
|
img.removeAttribute('width')
|
|
img.removeAttribute('height')
|
|
p.insertBefore(img, p.firstChild)
|
|
|
|
break
|
|
}
|
|
|
|
return p.innerHTML
|
|
}
|
|
|
|
function get (value, callback) {
|
|
var cacheId = options.data_lang + ':' + value
|
|
if (cacheId in cache) {
|
|
return callback(null, cache[cacheId])
|
|
}
|
|
|
|
if (cacheId in loadClash) {
|
|
loadClash[cacheId].push(callback)
|
|
return
|
|
}
|
|
loadClash[cacheId] = []
|
|
|
|
ajax('wikipedia',
|
|
{
|
|
page: value,
|
|
lang: options.data_lang
|
|
},
|
|
function (result) {
|
|
if (!result.content) {
|
|
return callback(new Error('error'), null)
|
|
}
|
|
|
|
cache[cacheId] = result
|
|
|
|
callback(null, result)
|
|
|
|
loadClash[cacheId].forEach(function (d) {
|
|
d(null, result)
|
|
})
|
|
delete loadClash[cacheId]
|
|
}
|
|
)
|
|
}
|
|
|
|
function getAbstract (value, callback) {
|
|
const cacheId = options.data_lang + ':' + value
|
|
if (cacheId in getAbstractCache) {
|
|
callback(null, getAbstractCache[cacheId])
|
|
return getAbstractCache[cacheId]
|
|
}
|
|
|
|
get(value,
|
|
function (err, result) {
|
|
var text = null
|
|
|
|
if (result) {
|
|
var div = document.createElement('div')
|
|
div.innerHTML = result.content
|
|
|
|
text = prepare(div)
|
|
text += ' <a target="_blank" href="' + result.languages[result.language] + '">' + lang('more') + '</a>'
|
|
}
|
|
|
|
getAbstractCache[cacheId] = text
|
|
|
|
callback(err, text)
|
|
}
|
|
)
|
|
}
|
|
|
|
function updateDomWikipedia (dom, callback) {
|
|
const wikipediaQueries = dom.querySelectorAll('.wikipedia')
|
|
async.each(
|
|
wikipediaQueries,
|
|
(div, done) => {
|
|
if (div.hasAttribute('data-done')) {
|
|
return done()
|
|
}
|
|
|
|
getAbstract(div.getAttribute('data-id'),
|
|
(err, result) => {
|
|
if (result) {
|
|
div.innerHTML = result
|
|
div.setAttribute('data-done', 'true')
|
|
}
|
|
done()
|
|
}
|
|
)
|
|
},
|
|
() => {
|
|
callback()
|
|
}
|
|
)
|
|
}
|
|
|
|
register_hook('show-popup', function (data, category, dom, callback) {
|
|
updateDomWikipedia(dom, () => updateDomWikipedia(dom, () => {}))
|
|
callback()
|
|
})
|
|
|
|
register_hook('show-details', function (data, category, dom, callback) {
|
|
var ob = data.object
|
|
var found = 0
|
|
var foundPrefixes = []
|
|
var finished = 0
|
|
var errs = []
|
|
var h, k, m
|
|
var div = document.createElement('div')
|
|
div.className = 'wikipedia'
|
|
|
|
const mainBlock = document.createElement('div')
|
|
div.appendChild(mainBlock)
|
|
|
|
if ('wikipedia' in ob.tags) {
|
|
foundPrefixes.push('')
|
|
|
|
ob.tags.wikipedia.split(/;/g).forEach(value => {
|
|
value = value.trim()
|
|
|
|
found++
|
|
showWikipedia(value, mainBlock, done)
|
|
})
|
|
}
|
|
|
|
for (k in ob.tags) {
|
|
m = k.match(/^(.*):wikipedia$/)
|
|
if (m) {
|
|
let prefix = m[1]
|
|
|
|
const block = document.createElement('div')
|
|
div.appendChild(block)
|
|
|
|
h = document.createElement('h4')
|
|
h.appendChild(document.createTextNode(lang('tag:' + prefix)))
|
|
block.appendChild(h)
|
|
|
|
foundPrefixes.push(prefix)
|
|
|
|
ob.tags[k].split(/;/g).forEach(value => {
|
|
value = value.trim()
|
|
|
|
found++
|
|
showWikipedia(value, block, done)
|
|
})
|
|
}
|
|
|
|
m = k.match(/^((.*):)?wikipedia:(.*)$/)
|
|
if (m) {
|
|
let prefix = m[1]
|
|
|
|
if (typeof prefix === 'undefined' && foundPrefixes.indexOf('') !== -1) {
|
|
continue
|
|
}
|
|
if (foundPrefixes.indexOf(prefix) !== -1) {
|
|
continue
|
|
}
|
|
|
|
let block = mainBlock
|
|
if (prefix) {
|
|
block = document.createElement('div')
|
|
div.appendChild(block)
|
|
|
|
h = document.createElement('h4')
|
|
h.appendChild(document.createTextNode(lang('tag:' + prefix)))
|
|
block.appendChild(h)
|
|
}
|
|
|
|
foundPrefixes.push(prefix)
|
|
|
|
;(m[3] + ':' + ob.tags[k]).split(/;/g).forEach(value => {
|
|
found++
|
|
showWikipedia(value, block, done)
|
|
})
|
|
}
|
|
}
|
|
|
|
if (ob.tags.wikidata && foundPrefixes.indexOf('') === -1) {
|
|
foundPrefixes.push('')
|
|
|
|
ob.tags.wikidata.split(/;/g).forEach(value => {
|
|
value = value.trim()
|
|
|
|
found++
|
|
|
|
wikidata.load(value, function (err, result) {
|
|
var x
|
|
|
|
if (err) {
|
|
return done(err)
|
|
}
|
|
|
|
if (!result.sitelinks) {
|
|
return done(new Error('No Wikipedia links defined for Wikidata'))
|
|
}
|
|
|
|
if (options.data_lang + 'wiki' in result.sitelinks) {
|
|
x = result.sitelinks[options.data_lang + 'wiki']
|
|
return showWikipedia(options.data_lang + ':' + x.title, mainBlock, done)
|
|
}
|
|
|
|
for (k in result.sitelinks) {
|
|
if (k === 'commonswiki') {
|
|
continue
|
|
}
|
|
|
|
x = result.sitelinks[k]
|
|
m = k.match(/^(.*)wiki$/)
|
|
return showWikipedia(m[1] + ':' + x.title, mainBlock, done)
|
|
}
|
|
|
|
done()
|
|
})
|
|
})
|
|
}
|
|
|
|
for (k in ob.tags) {
|
|
m = k.match(/^(.*):wikidata$/)
|
|
if (m) {
|
|
let prefix = m[1]
|
|
found++
|
|
if (foundPrefixes.indexOf(prefix) !== -1) {
|
|
continue
|
|
}
|
|
foundPrefixes.push(prefix)
|
|
|
|
const block = document.createElement('div')
|
|
div.appendChild(block)
|
|
|
|
h = document.createElement('h4')
|
|
h.appendChild(document.createTextNode(lang('tag:' + prefix)))
|
|
block.appendChild(h)
|
|
|
|
ob.tags[k].split(/;/g).forEach(value => {
|
|
value = value.trim()
|
|
|
|
wikidata.load(value, (err, result) => {
|
|
var x
|
|
|
|
if (err) {
|
|
return done(err)
|
|
}
|
|
|
|
if (!result.sitelinks) {
|
|
return done()
|
|
}
|
|
|
|
if (options.data_lang + 'wiki' in result.sitelinks) {
|
|
x = result.sitelinks[options.data_lang + 'wiki']
|
|
return showWikipedia(options.data_lang + ':' + x.title, block, done)
|
|
}
|
|
|
|
for (k in result.sitelinks) {
|
|
if (k === 'commonswiki') {
|
|
continue
|
|
}
|
|
|
|
x = result.sitelinks[k]
|
|
m = k.match(/^(.*)wiki$/)
|
|
return showWikipedia(m[1] + ':' + x.title, block, done)
|
|
}
|
|
|
|
done()
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
displayBlock({
|
|
dom,
|
|
title: lang('tag:wikipedia'),
|
|
content: div,
|
|
order: 1
|
|
})
|
|
} else {
|
|
callback()
|
|
}
|
|
|
|
function done (err) {
|
|
finished++
|
|
|
|
if (err) {
|
|
errs.push(err)
|
|
}
|
|
|
|
if (found === finished) {
|
|
callback(errs.length ? errs : null)
|
|
}
|
|
}
|
|
})
|
|
|
|
function showWikipedia (tagValue, dom, callback) {
|
|
var block = document.createElement('div')
|
|
block.className = 'loading'
|
|
dom.appendChild(block)
|
|
|
|
var l = document.createElement('div')
|
|
l.innerHTML = '<i class="fa fa-spinner fa-pulse fa-fw"></i><span class="sr-only">Loading...</span>'
|
|
l.className = 'loadingIndicator'
|
|
block.appendChild(l)
|
|
|
|
getAbstract(tagValue, function (err, text) {
|
|
if (!text) {
|
|
block.appendChild(document.createTextNode(lang('wikipedia:no-url-parse')))
|
|
}
|
|
|
|
var div = document.createElement('div')
|
|
div.innerHTML = text
|
|
block.appendChild(div)
|
|
|
|
block.removeChild(l)
|
|
block.className = 'clearfix'
|
|
|
|
callback(err)
|
|
})
|
|
}
|
|
|
|
function getImages (tagValue, callback) {
|
|
var i
|
|
|
|
get(tagValue, function (err, result) {
|
|
if (err) {
|
|
return callback(err, null)
|
|
}
|
|
|
|
var div = document.createElement('div')
|
|
div.innerHTML = result.content
|
|
|
|
var imgs = div.getElementsByTagName('img')
|
|
var ret = []
|
|
|
|
for (i = 0; i < imgs.length; i++) {
|
|
var img = imgs[i]
|
|
|
|
// ignore icons
|
|
if (img.width <= 64 && img.height <= 64) {
|
|
continue
|
|
}
|
|
|
|
img.removeAttribute('width')
|
|
img.removeAttribute('height')
|
|
|
|
var m = img.src.match(/^https?:\/\/upload.wikimedia.org\/wikipedia\/commons\/thumb\/\w+\/\w+\/([^/]+)/)
|
|
if (m) {
|
|
var file = decodeURIComponent(m[1]).replace(/_/g, ' ')
|
|
ret.push({
|
|
id: file,
|
|
width: img.getAttribute('data-file-width'),
|
|
height: img.getAttribute('data-file-height')
|
|
})
|
|
}
|
|
}
|
|
|
|
callback(null, ret)
|
|
})
|
|
}
|
|
|
|
module.exports = {
|
|
getImages: getImages
|
|
}
|
|
|
|
OverpassLayer.twig.extendFilter('wikipediaAbstract', function (value, param) {
|
|
let result
|
|
const cacheId = options.data_lang + ':' + value
|
|
if (cacheId in getAbstractCache) {
|
|
const text = getAbstractCache[cacheId]
|
|
result = '<div class="wikipedia" data-id="' + value + '" data-done="true">' + text + '</div>'
|
|
} else {
|
|
result = '<div class="wikipedia" data-id="' + value + '"><a href="https://wikidata.org/wiki/' + value + '">' + value + '</a></div>'
|
|
}
|
|
|
|
return OverpassLayer.twig.filters.raw(result)
|
|
})
|