Module:Attached KML: Difference between revisions
Appearance
Content deleted Content added
fix sites[1] |
fix typo |
||
(17 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
-- Note: Originally written on English Wikipedia as [[w:en:Module:Attached_KML]] |
-- Note: Originally written on English Wikipedia as [[w:en:Module:Attached_KML]] |
||
-- ##### Localisation (L10n) settings ##### |
-- ##### Localisation (L10n) settings ##### |
||
local L10n = { |
local L10n = { |
||
-- Template parameter names |
|||
-- |
-- (replace values in quotes with local parameter names) |
||
para = { |
|||
-- (replace values in quotes with local parameter names) |
|||
display = "display", |
|||
L10n.para = { |
|||
from = "from", |
|||
header = "header", |
|||
title = "title", |
|||
wikidata = "wikidata", |
|||
demo = "demo", |
|||
demo = "demo", |
|||
} |
|||
-- Other strings |
|||
L10n.str = { |
|||
inline = "inline", -- used with display parameter: (|display=inline) or (|display=title) or (|display=inline,title) or (|display=title,inline) |
|||
title = "title", -- (as above) |
|||
dsep = ",", -- separator between inline and title (comma in the example above in the above) |
|||
kml_prefix = "Template:Attached KML/", -- local KML files are stored as subpages of this location |
|||
default_title = "Route map", -- default title for links at top of page, when title parameter not used in transclusion |
|||
default_header = "", -- default header for links in inline box, when header parameter not used in transclusion |
|||
edit = "edit", -- text to display for link to edit KML file |
|||
help = "help", -- text to display for help page link |
|||
help_location = "Help:Attached KML", -- page to link to for help page link |
|||
err_prepend = "Attached KML", -- text to prepend to the error messages, when shown at top of page (display=title) |
|||
err = { -- error messages |
|||
malformed_qid = "Error: malformed item id in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code>", -- item id doesn't match pattern (number with Q prefix) |
|||
bad_qid = "Error: item specified on Wikidata, or in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code>, is not a KML file <small>(P31→Q26267864 not found)</small>", -- item doesn't have a P31→Q26267864 statement |
|||
no_item = "Error: item specified in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code> not found on Wikidata", -- item not found on wikidata |
|||
bad_from = "Error: KML file not found, check <code><nowiki>|" .. L10n.para.from .. "=</nowiki></code>", -- KML specified by from parameter doesn't exist |
|||
no_kml = "Error: KML file not found", -- no KML file found |
|||
}, |
}, |
||
-- Other configuration settings |
|||
cat = { -- tracking categories: full wikimarkup required, or set to the empty string ("") to not to track the condition |
|||
config = { |
|||
wikidata_kml = "[[Category:Articles using KML from Wikidata]]", -- tracks mainspace articles using KML from Wikidata |
|||
-- controls the format used for inline display, can be set to "box" (default) or "line" |
|||
local_kml = "[[Category:Articles using KML not from Wikidata]]", -- tracks mainspace articles not using KML from Wikidata |
|||
-- "box" example: https://en.wikipedia.org/wiki/Template:Attached_KML |
|||
error_mqid = "[[Category:Attached KML errors|M]]", -- tracks malformed_qid error |
|||
-- "line" example: https://sv.wikipedia.org/wiki/Mall:KML |
|||
error_badqid = "[[Category:Attached KML errors|W]]", -- tracks bad_qid error |
|||
inline_format = "box", |
|||
error_noitem = "[[Category:Attached KML errors|N]]", -- tracks no_item error |
|||
error_from = "[[Category:Attached KML errors|F]]", -- tracks bad_from error |
|||
error_nokml = "[[Category:Attached KML errors|K]]", -- tracks no_kml error |
|||
}, |
}, |
||
-- Other strings |
|||
str = { |
|||
inline = "inline", -- used with display parameter: (|display=inline) or (|display=title) or (|display=inline,title) or (|display=title,inline) |
|||
title = "title", -- (as above) |
|||
dsep = ",", -- separator between inline and title (comma in the example above) |
|||
kml_prefix = "Template:Attached KML/", -- local KML files are stored as subpages of this location |
|||
default_title = "Route map", -- default title for links at top of page, when title parameter not used in transclusion |
|||
default_header = "", -- default header for links in inline box, when header parameter not used in transclusion |
|||
kml_file = "KML file", -- text to display for link to raw KML file |
|||
edit = "edit", -- text to display for link to edit KML file |
|||
help = "help", -- text to display for help page link |
|||
help_location = "Help:Attached KML", -- page to link to for help page link |
|||
err_prepend = "Attached KML", -- text to prepend to the error messages, when shown at top of page (display=title) |
|||
cat = { -- tracking categories: full wikimarkup required, or set to the empty string ("") to not to track the condition |
|||
wikidata_kml = "[[Category:Articles using KML from Wikidata]]", -- tracks mainspace articles using KML from Wikidata |
|||
local_kml = "[[Category:Articles using KML not from Wikidata]]", -- tracks mainspace articles not using KML from Wikidata |
|||
error_mqid = "[[Category:Attached KML errors|M]]", -- tracks malformed_qid error |
|||
error_badqid = "[[Category:Attached KML errors|W]]", -- tracks bad_qid error |
|||
error_noitem = "[[Category:Attached KML errors|N]]", -- tracks no_item error |
|||
error_from = "[[Category:Attached KML errors|F]]", -- tracks bad_from error |
|||
error_nokml = "[[Category:Attached KML errors|K]]", -- tracks no_kml error |
|||
}, |
|||
line = { -- these strings are only needed if using 'inline_format = "line"' configuration |
|||
start = "", -- wikitext to display at start of line, may include image markup, should start with a space |
|||
separator = "", -- text to display between links to external mapping providers, should include spaces |
|||
}, |
|||
} |
|||
} |
|||
L10n.str.err = { -- error messages |
|||
malformed_qid = "Error: malformed item id in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code>", -- item id doesn't match pattern (number with Q prefix) |
|||
bad_qid = "Error: item specified on Wikidata, or in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code>, is not a KML file <small>(P31→Q26267864 not found)</small>", -- item doesn't have a P31→Q26267864 statement |
|||
no_item = "Error: item specified in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code> not found on Wikidata", -- item not found on wikidata |
|||
bad_from = "Error: KML file not found, check <code><nowiki>|" .. L10n.para.from .. "=</nowiki></code>", -- KML specified by from parameter doesn't exist |
|||
no_kml = "Error: KML file not found", -- no KML file found |
|||
} |
} |
||
-- Masks for external mapping providers, in the form: |
-- Masks for external mapping providers, in the form: |
||
-- externalLinkMasks[index-number] = { short = "short-label", long = "long-label", link = "url" }' |
-- externalLinkMasks[index-number] = { short = "short-label", long = "long-label", link = "url" }' |
||
-- The short label is used for the title links; the long label is used for the inline links |
|||
-- Links in the output will be ordered by index-number |
-- Links in the output will be ordered by index-number |
||
-- Instead of kml file's raw url or encoded raw url, use __KML_URL__ or __KML_URL_E__ |
-- Instead of kml file's raw url or encoded raw url, use __KML_URL__ or __KML_URL_E__ |
||
local externalLinks = {} |
local externalLinks = {} |
||
externalLinks[1] = { |
--externalLinks[1] = { |
||
-- short = "Bing", |
|||
-- long = "Display on Bing Maps", |
|||
-- link = "http://www.bing.com/maps/?mapurl=__KML_URL__" |
|||
} |
--} |
||
externalLinks[2] = { |
|||
short = "Google", |
|||
long = "Display on Google Maps", |
|||
link = "https://tools.wmflabs.org/wp-world/googlmaps-proxy.php?page=__KML_URL_E__&output=classic" |
|||
} |
|||
-- #### End of L10n settings #### |
-- #### End of L10n settings #### |
||
Line 64: | Line 72: | ||
-- Table of available wikis, in the order that they are to be searched for kml files |
-- Table of available wikis, in the order that they are to be searched for kml files |
||
-- (once a kml file is found, further sites are not checked) |
-- (once a kml file is found, further sites are not checked) |
||
local sites = { |
local sites = { |
||
{ |
|||
sites[1] = { mw.ustring.match( mw.site.server, "%w." ) .. mw.ustring.gsub( mw.ustring.lower(mw.site.siteName), "[mp]edia", ""), mw.ustring.sub(mw.site.server, 3), "" } -- local wiki (listed first so local files can override files on other wikis) |
|||
mw.ustring.match( mw.site.server, "%w+" ) .. mw.ustring.gsub( mw.ustring.lower(mw.site.siteName), "[mp]edia", ""), |
|||
sites[2] = { "commonswiki", "commons.wikimedia.org", "c:" } -- Commons would be a logical central repository for KML files (but has no files as of August 2016) |
|||
mw.ustring.sub(mw.site.server, 3), |
|||
sites[3] = { "enwiki", "en.wikipedia.org", "w:en:" } -- largest source of KML files (as of August 2016) |
|||
"" |
|||
sites[4] = { "bnwiki", "bn.wikipedia.org", "w:bn:" } -- other sites with a KML template, listed in alphabetical order |
|||
}, -- local wiki (listed first so local files can override files on other wikis) |
|||
sites[5] = { "cswiki", "cs.wikipedia.org", "w:cs:" } |
|||
{ "commonswiki", "commons.wikimedia.org", "c:" }, -- Commons would be a logical central repository for KML files (but has no files as of August 2016) |
|||
sites[6] = { "fawiki", "fa.wikipedia.org", "w:fa:" } |
|||
{ "enwiki", "en.wikipedia.org", "w:en:" }, -- largest source of KML files (as of August 2016) |
|||
{ "bnwiki", "bn.wikipedia.org", "w:bn:" }, -- other sites with a KML template, listed in alphabetical order |
|||
{ "cswiki", "cs.wikipedia.org", "w:cs:" }, |
|||
{ "fawiki", "fa.wikipedia.org", "w:fa:" }, |
|||
{ "frwiki", "fr.wikipedia.org", "w:fr:" }, |
|||
{ "jawiki", "ja.wikipedia.org", "w:ja:" }, |
|||
{ "mlwiki", "ml.wikipedia.org", "w:ml:" }, |
|||
--Parameter for cleaned-up parent.args (whitespace trimmed, blanks removed) |
|||
{ "svwiki", "sv.wikipedia.org", "w:sv:" }, |
|||
local Args = {} |
|||
{ "zhwiki", "zh.wikipedia.org", "w:zh:" }, |
|||
} |
|||
local p = {} |
local p = {} |
||
function |
local function setCleanArgs(argsTable) |
||
local parent = frame.getParent(frame) |
|||
Args = setCleanArgs(parent.args) |
|||
local qid = Args[L10n.para.wikidata] or nil |
|||
-- get KML file url |
|||
local wikiUrl, wikiTitle, wikiLink, trackingWikitext, kmlError |
|||
if not (Args[L10n.para.from]) then |
|||
if not qid then |
|||
wikiUrl, wikiLink, siteindex, kmlError = getUrlFromWikidata() |
|||
elseif mw.ustring.find( qid, "^Q%d+" ) then |
|||
wikiUrl, wikiLink, siteindex, kmlError = getUrlFromQid(qid) |
|||
else |
|||
kmlError = makeError(L10n.str.err.malformed_qid, L10n.str.cat.error_mqid) |
|||
end |
|||
end |
|||
if not (wikiUrl) then |
|||
wikiLink = Args[L10n.para.from] or tostring(mw.title.getCurrentTitle()) |
|||
wikiTitle = mw.title.new( L10n.str.kml_prefix .. wikiLink ) |
|||
if not (wikiTitle.exists) and not (kmlError) then |
|||
if Args[L10n.para.from] then |
|||
kmlError = makeError(L10n.str.err.bad_from, L10n.str.cat.error_from) |
|||
else |
|||
kmlError = makeError(L10n.str.err.no_kml, L10n.str.cat.error_nokml) |
|||
end |
|||
end |
|||
wikiUrl = wikiTitle:fullUrl("action=raw","https") |
|||
siteindex = 1 |
|||
trackingWikitext = mw.ustring.format( "<div title=\"KML & Wikidata\" style=\"display:none;\">KML is not from Wikidata</div>{{#ifeq:{{NAMESPACE}}|{{ns:0}}|%s}}", L10n.str.cat.local_kml ) |
|||
else |
|||
trackingWikitext = mw.ustring.format( "<div title=\"KML & Wikidata\" style=\"display:none;\">KML is from Wikidata</div>{{#ifeq:{{NAMESPACE}}|{{ns:0}}|%s}}", L10n.str.cat.wikidata_kml ) |
|||
end |
|||
-- replace __KML_URL__ or __KML_URL_E__ with actual values |
|||
local encodedWikiUrl = mw.uri.encode(wikiUrl, "PATH") |
|||
for i, v in ipairs( externalLinks ) do |
|||
local el1 = safeReplace( v.link, "__KML_URL__", wikiUrl ) |
|||
local el2 = safeReplace( el1, "__KML_URL_E__", encodedWikiUrl ) |
|||
externalLinks[i]["link"] = el2 |
|||
end |
|||
-- suppress errors and categories if demo parameter is set |
|||
if Args[L10n.para.demo] then |
|||
kmlError = nil |
|||
trackingWikitext = "" |
|||
end |
|||
local wikitext = "" |
|||
if Args[L10n.para.display] then |
|||
local display = mw.text.split(Args[L10n.para.display], L10n.str.dsep) |
|||
if display[1] == L10n.str.title or display[2] == L10n.str.title then |
|||
wikitext = makeTitleWikitext(Args[L10n.para.title] or L10n.str.default_title, kmlError) |
|||
end |
|||
if display[1] == L10n.str.inline or display[2] == L10n.str.inline or (display[1] ~= L10n.str.title and display[2] ~= L10n.str.title) then |
|||
local inlineWikitext = makeInlineWikitext(Args[L10n.para.header] or L10n.str.default_header, wikiUrl, kmlError) |
|||
wikitext = wikitext .. inlineWikitext |
|||
end |
|||
else |
|||
wikitext = makeInlineWikitext(Args[L10n.para.header] or L10n.str.default_header, wikiUrl, kmlError) |
|||
end |
|||
wikitext = wikitext .. makeKmldataDiv(wikiLink, siteindex) .. trackingWikitext |
|||
return frame:preprocess( wikitext ) |
|||
end |
|||
function setCleanArgs(argsTable) |
|||
local cleanArgs = {} |
local cleanArgs = {} |
||
for key, val in pairs(argsTable) do |
for key, val in pairs(argsTable) do |
||
Line 164: | Line 107: | ||
end |
end |
||
function safeReplace(string, pattern, replacement) |
local function safeReplace(string, pattern, replacement) |
||
-- avoids "Lua error: invalid capture index" that occurs with string.gsub when the replacement contains one or more literal % character |
-- avoids "Lua error: invalid capture index" that occurs with string.gsub when the replacement contains one or more literal % character |
||
local nonpattern_parts = mw.text.split( string, pattern ) |
local nonpattern_parts = mw.text.split( string, pattern ) |
||
Line 170: | Line 113: | ||
end |
end |
||
local function makeTitleWikitext(titletext, err) |
|||
if err and L10n.str.err_prepend then |
|||
function makeTitleWikitext(titletext, err) |
|||
err = mw.ustring.gsub( err, ">", ">" .. L10n.str.err_prepend .. " ", 1 ) |
|||
end |
|||
local titleLinks = {} |
local titleLinks = {} |
||
Line 178: | Line 122: | ||
titleLinks[i] = mw.ustring.format( "[%s %s]", v.link , v.short) |
titleLinks[i] = mw.ustring.format( "[%s %s]", v.link , v.short) |
||
end |
end |
||
return mw.getCurrentFrame():extensionTag{ |
|||
return mw.ustring.format( "<span style=\"font-size: small;\"><span id=\"coordinates\">\'\'\'%s\'\'\': %s</span></span>", titletext, err or table.concat(titleLinks, " / ") ) |
|||
name = 'indicator', |
|||
args = { name = 'attached-kml' }, |
|||
content = mw.ustring.format( |
|||
"<span id=\"coordinates\">\'\'\'%s\'\'\': %s</span>", |
|||
titletext, |
|||
err or table.concat(titleLinks, " / ") |
|||
) |
|||
} |
|||
end |
end |
||
local function makeInlineWikitext(headertext, url, err) |
|||
function makeInlineWikitext(headertext, url, err) |
|||
local inlineLinks = {} |
local inlineLinks = {} |
||
for i, v in ipairs( externalLinks ) do |
for i, v in ipairs( externalLinks ) do |
||
inlineLinks[i] = mw.ustring.format( |
inlineLinks[i] = mw.ustring.format("[%s %s]", v.link , v.long) |
||
end |
end |
||
local editUrl = mw.ustring.gsub( url, "action=raw", "action=edit" ) |
local editUrl = mw.ustring.gsub( url, "action=raw", "action=edit" ) |
||
Line 195: | Line 146: | ||
end |
end |
||
if L10n.config.inline_format == "line" then |
|||
return mw.ustring.format( "<table class=\"metadata mbox-small\" style=\"border:1px solid #aaa;background-color:#f9f9f9;font-size: 88%%; line-height: 1.5em\"><tr><td style=\"width:1px\"></td><td class=\"mbox-text plainlist\">%s<span class=\"%s\">\'\'\'[%s KML file]\'\'\' ([%s %s] • [[%s|%s]])</span>\n<ul><li>%s</li></ul></td></tr></table>", headertext, wiki_link_class, url, editUrl, L10n.str.edit, L10n.str.help_location, L10n.str.help, err or table.concat(inlineLinks, "</li><li>") ) |
|||
return mw.ustring.format( |
|||
"<li>%s%s%s (<span class=\"%s\">[%s %s] <span style=\"font-size:85%%;\">([%s %s] • [[%s|%s]])</span></span>)</li>", |
|||
headertext, L10n.str.line.start, |
|||
err or table.concat(inlineLinks, L10n.str.line.separator), |
|||
wiki_link_class, url, L10n.str.kml_file, editUrl, L10n.str.edit, |
|||
L10n.str.help_location, L10n.str.help |
|||
) |
|||
end |
|||
local text = mw.ustring.format( |
|||
'%s<span class="%s">\'\'\'[%s %s]\'\'\' ([%s %s] • [[%s|%s]])</span>', |
|||
headertext, wiki_link_class, url, L10n.str.kml_file, editUrl, |
|||
L10n.str.edit, L10n.str.help_location, L10n.str.help |
|||
) |
|||
if err or #inlineLinks > 0 then |
|||
text = mw.ustring.format( |
|||
"%s<ul><li>%s</li></ul>", |
|||
text, |
|||
err or table.concat(inlineLinks, "</li><li>") |
|||
) |
|||
end |
|||
return require('Module:Side box')._main({ |
|||
class = 'attached-kml', |
|||
text = text |
|||
}) |
|||
end |
end |
||
function makeKmldataDiv(link, s_index) |
local function makeKmldataDiv(link, s_index) |
||
return |
return mw.ustring.format( |
||
'<div class="kmldata" data-server="%s" title="%s">[[%s%s]][[Category:Pages using gadget WikiMiniAtlas]]</div>', |
|||
sites[s_index][2], link, sites[s_index][3], link |
|||
) |
|||
end |
end |
||
function makeError(msg, cat) |
local function makeError(msg, cat) |
||
return mw.ustring.format( |
|||
return mw.ustring.format( "%s%s%s%s", "<strong class=\"error\" style=\"font-size:100%\">", mw.ustring.gsub( msg, "<code>", "<code class=\"error\" style=\"font-size:inherit;font-weight:normal;border:0\">" ), "</strong>", cat) |
|||
'<strong class="attached-kml-error">%s</strong>%s', |
|||
msg, |
|||
mw.title.getCurrentTitle():inNamespaces(0, 118) and cat or '' |
|||
) |
|||
end |
end |
||
local function getUrlFromQid( kml_qid ) |
|||
local pcall_result, kml_entity = pcall(mw.wikibase.getEntity, kml_qid) |
|||
if not pcall_result then return nil, nil, nil, makeError(L10n.str.err.no_item, L10n.str.cat.error_noitem) end -- Error if entity doesn't exist |
|||
local p31_claim = kml_entity:getBestStatements("P31") -- P31 is property "instance of" |
|||
local has_good_p31 |
|||
for k, v in pairs( p31_claim ) do |
|||
if (p31_claim[k] and p31_claim[k].mainsnak.snaktype == "value" and |
|||
p31_claim[k].mainsnak.datavalue.type == "wikibase-entityid" and |
|||
p31_claim[k].mainsnak.datavalue.value["numeric-id"] == 26267864) then |
|||
has_good_p31 = true |
|||
end |
|||
end |
|||
if not (has_good_p31) then -- Error if item isn't a kml file |
|||
return nil, nil, nil, makeError(L10n.str.err.bad_qid, L10n.str.cat.error_badqid) |
|||
end |
|||
local kml_sitelink |
|||
local kml_siteindex |
|||
local kml_url |
|||
for i, v in ipairs( sites ) do |
|||
kml_sitelink = kml_entity:getSitelink( v[1] ) |
|||
if kml_sitelink then |
|||
kml_url = "https://" .. v[2] .. "/w/index.php?title=" .. mw.uri.encode( kml_sitelink, "WIKI" ) .. "&action=raw" |
|||
kml_siteindex = i |
|||
end |
|||
if kml_url then break end |
|||
end |
|||
return kml_url or nil, kml_sitelink or nil, kml_siteindex or nil, nil |
|||
end |
|||
-- Attempts to get url from linked wikidata items, will return nil if it can't |
|||
local function getUrlFromWikidata() |
|||
local entity = mw.wikibase.getEntityObject() |
local entity = mw.wikibase.getEntityObject() |
||
if not entity then return nil end |
if not entity then return nil end |
||
Line 227: | Line 242: | ||
end |
end |
||
function |
function p.main(frame) |
||
local parent = frame.getParent(frame) |
|||
local pcall_result, kml_entity = pcall(mw.wikibase.getEntity, kml_qid) |
|||
local Args = setCleanArgs(parent.args) |
|||
if not pcall_result then return nil, nil, nil, makeError(L10n.str.err.no_item, L10n.str.cat.error_noitem) end -- Error if entity doesn't exist |
|||
local qid = Args[L10n.para.wikidata] or nil |
|||
local p31_claim = kml_entity:getBestStatements("P31") -- P31 is property "instance of" |
|||
local has_good_p31 |
|||
-- get KML file url |
|||
for k, v in pairs( p31_claim ) do |
|||
local wikiUrl, wikiTitle, wikiLink, trackingWikitext, kmlError |
|||
if (p31_claim[k] and p31_claim[k].mainsnak.snaktype == "value" and p31_claim[k].mainsnak.datavalue.type == "wikibase-entityid" and p31_claim[k].mainsnak.datavalue.value["numeric-id"] == 26267864) then |
|||
if not (Args[L10n.para.from]) then |
|||
has_good_p31 = true |
|||
if not qid then |
|||
wikiUrl, wikiLink, siteindex, kmlError = getUrlFromWikidata() |
|||
elseif mw.ustring.find( qid, "^Q%d+" ) then |
|||
wikiUrl, wikiLink, siteindex, kmlError = getUrlFromQid(qid) |
|||
else |
|||
kmlError = makeError(L10n.str.err.malformed_qid, L10n.str.cat.error_mqid) |
|||
end |
end |
||
end |
end |
||
if not (has_good_p31) then return nil, nil, nil, makeError(L10n.str.err.bad_qid, L10n.str.cat.error_badqid) end -- Error if item isn't a kml file |
|||
if not (wikiUrl) then |
|||
-- FIXME? this smells bad. shouldn't need to make a new title of a to_string |
|||
-- from the current title and then turn it into text form |
|||
wikiLink = Args[L10n.para.from] or mw.title.new(tostring(mw.title.getCurrentTitle())).text |
|||
wikiLink = L10n.str.kml_prefix .. wikiLink |
|||
wikiTitle = mw.title.new( wikiLink ) |
|||
if not (wikiTitle.exists) and not (kmlError) then |
|||
local kml_sitelink |
|||
if Args[L10n.para.from] then |
|||
local kml_siteindex |
|||
kmlError = makeError(L10n.str.err.bad_from, L10n.str.cat.error_from) |
|||
local kml_url |
|||
else |
|||
for i, v in ipairs( sites ) do |
|||
kmlError = makeError(L10n.str.err.no_kml, L10n.str.cat.error_nokml) |
|||
kml_sitelink = kml_entity:getSitelink( v[1] ) |
|||
end |
|||
if kml_sitelink then |
|||
kml_url = "https://" .. v[2] .. "/w/index.php?title=" .. mw.uri.encode( kml_sitelink, "WIKI" ) .. "&action=raw" |
|||
kml_siteindex = i |
|||
end |
end |
||
wikiUrl = wikiTitle:fullUrl("action=raw", "https") |
|||
if kml_url then break end |
|||
siteindex = 1 |
|||
trackingWikitext = mw.ustring.format( |
|||
'<div title="KML & Wikidata" class="attached-kml-wikidata">KML is not from Wikidata</div>%s', |
|||
mw.title.getCurrentTitle():inNamespace(0) and L10n.str.cat.local_kml or '' |
|||
) |
|||
else |
|||
trackingWikitext = mw.ustring.format( |
|||
'<div title="KML & Wikidata" class="attached-kml-wikidata">KML is from Wikidata</div>%s', |
|||
mw.title.getCurrentTitle():inNamespace(0) and L10n.str.cat.wikidata_kml or '' |
|||
) |
|||
end |
end |
||
return kml_url or nil, kml_sitelink or nil, kml_siteindex or nil, nil |
|||
wikiTitle = mw.title.new( wikiLink ) |
|||
if wikiTitle.exists then |
|||
local transclusion = wikiTitle:getContent() -- hack to register the template as transcluded. |
|||
end |
|||
-- replace __KML_URL__ or __KML_URL_E__ with actual values |
|||
local encodedWikiUrl = mw.uri.encode(wikiUrl, "PATH") |
|||
for i, v in ipairs( externalLinks ) do |
|||
local el1 = safeReplace( v.link, "__KML_URL__", wikiUrl ) |
|||
local el2 = safeReplace( el1, "__KML_URL_E__", encodedWikiUrl ) |
|||
externalLinks[i]["link"] = el2 |
|||
end |
|||
-- suppress errors and categories if demo parameter is set |
|||
if Args[L10n.para.demo] then |
|||
kmlError = nil |
|||
trackingWikitext = "" |
|||
end |
|||
local wikitext = "" |
|||
if Args[L10n.para.display] then |
|||
local display = mw.text.split(Args[L10n.para.display], '%s*' .. L10n.str.dsep .. '%s*') |
|||
if display[1] == L10n.str.title or display[2] == L10n.str.title then |
|||
wikitext = makeTitleWikitext(Args[L10n.para.title] or L10n.str.default_title, kmlError) |
|||
end |
|||
if display[1] == L10n.str.inline or display[2] == L10n.str.inline or (display[1] ~= L10n.str.title and display[2] ~= L10n.str.title) then |
|||
local inlineWikitext = makeInlineWikitext(Args[L10n.para.header] or L10n.str.default_header, wikiUrl, kmlError) |
|||
wikitext = wikitext .. inlineWikitext |
|||
end |
|||
else |
|||
wikitext = makeInlineWikitext(Args[L10n.para.header] or L10n.str.default_header, wikiUrl, kmlError) |
|||
end |
|||
wikitext = wikitext .. makeKmldataDiv(wikiLink, siteindex) .. trackingWikitext |
|||
return frame:extensionTag{ |
|||
name = 'templatestyles', args = { src = 'Module:Attached KML/styles.css' } |
|||
} .. frame:preprocess( wikitext ) |
|||
end |
end |
||
Latest revision as of 20:03, 30 May 2024
This Lua module is used on approximately 14,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
This module is rated as beta, and is ready for widespread use. It is still new and should be used with some caution to ensure the results are as expected. |
This module depends on the following other modules: |
This module uses TemplateStyles: |
Usage
On English Wikipedia, this module is called by {{Attached KML}}
. See that template's documentation for usage instructions
Set up on another wiki
- Create template and module
- Import this module to that wiki (or copy the code over, giving attribution in the edit summary). Give the module a name that makes sense in that wiki's language (hereafter referred to as MODULENAME)
- Create a template (which should probably have the same name as the module, but referred to here as TEMPLATENAME) containing the code
<includeonly>{{#invoke:MODULENAME|main}}</includeonly><noinclude>{{TEMPLATENAME|demo=yes}}{{Documentation}}</noinclude>
- On Wikidata, add the template to d:Q6690822 and the module to d:Q26689774
- Localise the module. Edit the top bits of the module, between the comments
-- ##### Localisation (L10n) settings #####
and-- #### End of L10n settings ####
, replacing values between"
"
symbols with local values (as necessary) - Create the categories defined in the module localisation. These should be made hidden categories, either by including a Template:Hidden category (Q5879327) template, or by directly including the
__HIDDENCAT__
magic word. - Add documentation to the template (e.g. by translating Template:Attached KML/doc, adjusting as necessary per any localisations made in the previous step) and to the module (please transfer/translate these instructions so that wikimedians who read your wiki but not the English Wikipedia can also set up the module and template on another wiki).
Tracking categories
- Category:Attached KML errors (5) – tracks errors: malformed_qid, bad_qid, no_item, bad_from, error_nokml
- Category:Articles using KML from Wikidata (9,469) – tracks mainspace articles using KML from Wikidata
- Category:Articles using KML not from Wikidata (4,330) – tracks mainspace articles not using KML from Wikidata
-- Note: Originally written on English Wikipedia as [[w:en:Module:Attached_KML]]
-- ##### Localisation (L10n) settings #####
local L10n = {
-- Template parameter names
-- (replace values in quotes with local parameter names)
para = {
display = "display",
from = "from",
header = "header",
title = "title",
wikidata = "wikidata",
demo = "demo",
},
-- Other configuration settings
config = {
-- controls the format used for inline display, can be set to "box" (default) or "line"
-- "box" example: https://en.wikipedia.org/wiki/Template:Attached_KML
-- "line" example: https://sv.wikipedia.org/wiki/Mall:KML
inline_format = "box",
},
-- Other strings
str = {
inline = "inline", -- used with display parameter: (|display=inline) or (|display=title) or (|display=inline,title) or (|display=title,inline)
title = "title", -- (as above)
dsep = ",", -- separator between inline and title (comma in the example above)
kml_prefix = "Template:Attached KML/", -- local KML files are stored as subpages of this location
default_title = "Route map", -- default title for links at top of page, when title parameter not used in transclusion
default_header = "", -- default header for links in inline box, when header parameter not used in transclusion
kml_file = "KML file", -- text to display for link to raw KML file
edit = "edit", -- text to display for link to edit KML file
help = "help", -- text to display for help page link
help_location = "Help:Attached KML", -- page to link to for help page link
err_prepend = "Attached KML", -- text to prepend to the error messages, when shown at top of page (display=title)
cat = { -- tracking categories: full wikimarkup required, or set to the empty string ("") to not to track the condition
wikidata_kml = "[[Category:Articles using KML from Wikidata]]", -- tracks mainspace articles using KML from Wikidata
local_kml = "[[Category:Articles using KML not from Wikidata]]", -- tracks mainspace articles not using KML from Wikidata
error_mqid = "[[Category:Attached KML errors|M]]", -- tracks malformed_qid error
error_badqid = "[[Category:Attached KML errors|W]]", -- tracks bad_qid error
error_noitem = "[[Category:Attached KML errors|N]]", -- tracks no_item error
error_from = "[[Category:Attached KML errors|F]]", -- tracks bad_from error
error_nokml = "[[Category:Attached KML errors|K]]", -- tracks no_kml error
},
line = { -- these strings are only needed if using 'inline_format = "line"' configuration
start = "", -- wikitext to display at start of line, may include image markup, should start with a space
separator = "", -- text to display between links to external mapping providers, should include spaces
},
}
}
L10n.str.err = { -- error messages
malformed_qid = "Error: malformed item id in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code>", -- item id doesn't match pattern (number with Q prefix)
bad_qid = "Error: item specified on Wikidata, or in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code>, is not a KML file <small>(P31→Q26267864 not found)</small>", -- item doesn't have a P31→Q26267864 statement
no_item = "Error: item specified in <code><nowiki>|" .. L10n.para.wikidata .. "=</nowiki></code> not found on Wikidata", -- item not found on wikidata
bad_from = "Error: KML file not found, check <code><nowiki>|" .. L10n.para.from .. "=</nowiki></code>", -- KML specified by from parameter doesn't exist
no_kml = "Error: KML file not found", -- no KML file found
}
-- Masks for external mapping providers, in the form:
-- externalLinkMasks[index-number] = { short = "short-label", long = "long-label", link = "url" }'
-- The short label is used for the title links; the long label is used for the inline links
-- Links in the output will be ordered by index-number
-- Instead of kml file's raw url or encoded raw url, use __KML_URL__ or __KML_URL_E__
local externalLinks = {}
--externalLinks[1] = {
-- short = "Bing",
-- long = "Display on Bing Maps",
-- link = "http://www.bing.com/maps/?mapurl=__KML_URL__"
--}
-- #### End of L10n settings ####
-- Table of available wikis, in the order that they are to be searched for kml files
-- (once a kml file is found, further sites are not checked)
local sites = {
{
mw.ustring.match( mw.site.server, "%w+" ) .. mw.ustring.gsub( mw.ustring.lower(mw.site.siteName), "[mp]edia", ""),
mw.ustring.sub(mw.site.server, 3),
""
}, -- local wiki (listed first so local files can override files on other wikis)
{ "commonswiki", "commons.wikimedia.org", "c:" }, -- Commons would be a logical central repository for KML files (but has no files as of August 2016)
{ "enwiki", "en.wikipedia.org", "w:en:" }, -- largest source of KML files (as of August 2016)
{ "bnwiki", "bn.wikipedia.org", "w:bn:" }, -- other sites with a KML template, listed in alphabetical order
{ "cswiki", "cs.wikipedia.org", "w:cs:" },
{ "fawiki", "fa.wikipedia.org", "w:fa:" },
{ "frwiki", "fr.wikipedia.org", "w:fr:" },
{ "jawiki", "ja.wikipedia.org", "w:ja:" },
{ "mlwiki", "ml.wikipedia.org", "w:ml:" },
{ "svwiki", "sv.wikipedia.org", "w:sv:" },
{ "zhwiki", "zh.wikipedia.org", "w:zh:" },
}
local p = {}
local function setCleanArgs(argsTable)
local cleanArgs = {}
for key, val in pairs(argsTable) do
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val ~= '' then
cleanArgs[key] = val
end
else
cleanArgs[key] = val
end
end
return cleanArgs
end
local function safeReplace(string, pattern, replacement)
-- avoids "Lua error: invalid capture index" that occurs with string.gsub when the replacement contains one or more literal % character
local nonpattern_parts = mw.text.split( string, pattern )
return table.concat(nonpattern_parts, replacement)
end
local function makeTitleWikitext(titletext, err)
if err and L10n.str.err_prepend then
err = mw.ustring.gsub( err, ">", ">" .. L10n.str.err_prepend .. " ", 1 )
end
local titleLinks = {}
for i, v in ipairs( externalLinks ) do
titleLinks[i] = mw.ustring.format( "[%s %s]", v.link , v.short)
end
return mw.getCurrentFrame():extensionTag{
name = 'indicator',
args = { name = 'attached-kml' },
content = mw.ustring.format(
"<span id=\"coordinates\">\'\'\'%s\'\'\': %s</span>",
titletext,
err or table.concat(titleLinks, " / ")
)
}
end
local function makeInlineWikitext(headertext, url, err)
local inlineLinks = {}
for i, v in ipairs( externalLinks ) do
inlineLinks[i] = mw.ustring.format("[%s %s]", v.link , v.long)
end
local editUrl = mw.ustring.gsub( url, "action=raw", "action=edit" )
local wiki_link_class
if mw.ustring.find( editUrl, mw.site.server, 1, true ) then
wiki_link_class = "plainlinks"
else
wiki_link_class = ""
end
if L10n.config.inline_format == "line" then
return mw.ustring.format(
"<li>%s%s%s (<span class=\"%s\">[%s %s] <span style=\"font-size:85%%;\">([%s %s] • [[%s|%s]])</span></span>)</li>",
headertext, L10n.str.line.start,
err or table.concat(inlineLinks, L10n.str.line.separator),
wiki_link_class, url, L10n.str.kml_file, editUrl, L10n.str.edit,
L10n.str.help_location, L10n.str.help
)
end
local text = mw.ustring.format(
'%s<span class="%s">\'\'\'[%s %s]\'\'\' ([%s %s] • [[%s|%s]])</span>',
headertext, wiki_link_class, url, L10n.str.kml_file, editUrl,
L10n.str.edit, L10n.str.help_location, L10n.str.help
)
if err or #inlineLinks > 0 then
text = mw.ustring.format(
"%s<ul><li>%s</li></ul>",
text,
err or table.concat(inlineLinks, "</li><li>")
)
end
return require('Module:Side box')._main({
class = 'attached-kml',
text = text
})
end
local function makeKmldataDiv(link, s_index)
return mw.ustring.format(
'<div class="kmldata" data-server="%s" title="%s">[[%s%s]][[Category:Pages using gadget WikiMiniAtlas]]</div>',
sites[s_index][2], link, sites[s_index][3], link
)
end
local function makeError(msg, cat)
return mw.ustring.format(
'<strong class="attached-kml-error">%s</strong>%s',
msg,
mw.title.getCurrentTitle():inNamespaces(0, 118) and cat or ''
)
end
local function getUrlFromQid( kml_qid )
local pcall_result, kml_entity = pcall(mw.wikibase.getEntity, kml_qid)
if not pcall_result then return nil, nil, nil, makeError(L10n.str.err.no_item, L10n.str.cat.error_noitem) end -- Error if entity doesn't exist
local p31_claim = kml_entity:getBestStatements("P31") -- P31 is property "instance of"
local has_good_p31
for k, v in pairs( p31_claim ) do
if (p31_claim[k] and p31_claim[k].mainsnak.snaktype == "value" and
p31_claim[k].mainsnak.datavalue.type == "wikibase-entityid" and
p31_claim[k].mainsnak.datavalue.value["numeric-id"] == 26267864) then
has_good_p31 = true
end
end
if not (has_good_p31) then -- Error if item isn't a kml file
return nil, nil, nil, makeError(L10n.str.err.bad_qid, L10n.str.cat.error_badqid)
end
local kml_sitelink
local kml_siteindex
local kml_url
for i, v in ipairs( sites ) do
kml_sitelink = kml_entity:getSitelink( v[1] )
if kml_sitelink then
kml_url = "https://" .. v[2] .. "/w/index.php?title=" .. mw.uri.encode( kml_sitelink, "WIKI" ) .. "&action=raw"
kml_siteindex = i
end
if kml_url then break end
end
return kml_url or nil, kml_sitelink or nil, kml_siteindex or nil, nil
end
-- Attempts to get url from linked wikidata items, will return nil if it can't
local function getUrlFromWikidata()
local entity = mw.wikibase.getEntityObject()
if not entity then return nil end
local kml_claim = entity:getBestStatements("P3096") -- P3096 is property "KML file"
if kml_claim then
-- get the QID of the first value of the property
if (kml_claim[1] and kml_claim[1].mainsnak.snaktype == "value" and kml_claim[1].mainsnak.datavalue.type == "wikibase-entityid") then
local kml_qid = "Q" .. kml_claim[1].mainsnak.datavalue.value["numeric-id"]
return getUrlFromQid( kml_qid )
else
return nil -- TODO: error message
end
else
return nil -- TODO: error message
end
end
function p.main(frame)
local parent = frame.getParent(frame)
local Args = setCleanArgs(parent.args)
local qid = Args[L10n.para.wikidata] or nil
-- get KML file url
local wikiUrl, wikiTitle, wikiLink, trackingWikitext, kmlError
if not (Args[L10n.para.from]) then
if not qid then
wikiUrl, wikiLink, siteindex, kmlError = getUrlFromWikidata()
elseif mw.ustring.find( qid, "^Q%d+" ) then
wikiUrl, wikiLink, siteindex, kmlError = getUrlFromQid(qid)
else
kmlError = makeError(L10n.str.err.malformed_qid, L10n.str.cat.error_mqid)
end
end
if not (wikiUrl) then
-- FIXME? this smells bad. shouldn't need to make a new title of a to_string
-- from the current title and then turn it into text form
wikiLink = Args[L10n.para.from] or mw.title.new(tostring(mw.title.getCurrentTitle())).text
wikiLink = L10n.str.kml_prefix .. wikiLink
wikiTitle = mw.title.new( wikiLink )
if not (wikiTitle.exists) and not (kmlError) then
if Args[L10n.para.from] then
kmlError = makeError(L10n.str.err.bad_from, L10n.str.cat.error_from)
else
kmlError = makeError(L10n.str.err.no_kml, L10n.str.cat.error_nokml)
end
end
wikiUrl = wikiTitle:fullUrl("action=raw", "https")
siteindex = 1
trackingWikitext = mw.ustring.format(
'<div title="KML & Wikidata" class="attached-kml-wikidata">KML is not from Wikidata</div>%s',
mw.title.getCurrentTitle():inNamespace(0) and L10n.str.cat.local_kml or ''
)
else
trackingWikitext = mw.ustring.format(
'<div title="KML & Wikidata" class="attached-kml-wikidata">KML is from Wikidata</div>%s',
mw.title.getCurrentTitle():inNamespace(0) and L10n.str.cat.wikidata_kml or ''
)
end
wikiTitle = mw.title.new( wikiLink )
if wikiTitle.exists then
local transclusion = wikiTitle:getContent() -- hack to register the template as transcluded.
end
-- replace __KML_URL__ or __KML_URL_E__ with actual values
local encodedWikiUrl = mw.uri.encode(wikiUrl, "PATH")
for i, v in ipairs( externalLinks ) do
local el1 = safeReplace( v.link, "__KML_URL__", wikiUrl )
local el2 = safeReplace( el1, "__KML_URL_E__", encodedWikiUrl )
externalLinks[i]["link"] = el2
end
-- suppress errors and categories if demo parameter is set
if Args[L10n.para.demo] then
kmlError = nil
trackingWikitext = ""
end
local wikitext = ""
if Args[L10n.para.display] then
local display = mw.text.split(Args[L10n.para.display], '%s*' .. L10n.str.dsep .. '%s*')
if display[1] == L10n.str.title or display[2] == L10n.str.title then
wikitext = makeTitleWikitext(Args[L10n.para.title] or L10n.str.default_title, kmlError)
end
if display[1] == L10n.str.inline or display[2] == L10n.str.inline or (display[1] ~= L10n.str.title and display[2] ~= L10n.str.title) then
local inlineWikitext = makeInlineWikitext(Args[L10n.para.header] or L10n.str.default_header, wikiUrl, kmlError)
wikitext = wikitext .. inlineWikitext
end
else
wikitext = makeInlineWikitext(Args[L10n.para.header] or L10n.str.default_header, wikiUrl, kmlError)
end
wikitext = wikitext .. makeKmldataDiv(wikiLink, siteindex) .. trackingWikitext
return frame:extensionTag{
name = 'templatestyles', args = { src = 'Module:Attached KML/styles.css' }
} .. frame:preprocess( wikitext )
end
return p