Zeile 1: |
Zeile 1: |
− | local WLink = { suite = "WLink", | + | local WLink = { suite = "WLink", |
− | serial = "2017-01-25" }; | + | serial = "2020-07-01", |
| + | item = 19363224, |
| + | globals = { URLutil = 10859193 } }; |
| + | |
| --[=[ | | --[=[ |
| ansiPercent() | | ansiPercent() |
Zeile 6: |
Zeile 9: |
| getArticleBase() | | getArticleBase() |
| getBaseTitle() | | getBaseTitle() |
| + | getEscapedTitle() |
| getExtension() | | getExtension() |
| getFile() | | getFile() |
| getFragment() | | getFragment() |
| getLanguage() | | getLanguage() |
| + | getLinktextProblem() |
| getNamespace() | | getNamespace() |
| + | getNamespaced() |
| getPlain() | | getPlain() |
| getProject() | | getProject() |
| getTarget() | | getTarget() |
| + | getTalkPage() |
| getTargetPage() | | getTargetPage() |
| getTitle() | | getTitle() |
| getWeblink() | | getWeblink() |
| + | getWikilink() |
| isBracketedLink() | | isBracketedLink() |
| isBracketedURL() | | isBracketedURL() |
Zeile 24: |
Zeile 32: |
| isInterwiki() | | isInterwiki() |
| isMedia() | | isMedia() |
| + | isTalkPage() |
| isTitledLink() | | isTitledLink() |
| isValidLink() | | isValidLink() |
| + | isValidLinktext() |
| isWikilink() | | isWikilink() |
| + | pageLink() |
| + | pageTarget() |
| wikilink() | | wikilink() |
| failsafe() | | failsafe() |
Zeile 34: |
Zeile 46: |
| | | |
| -- local globals | | -- local globals |
− | local URLutil = false; | + | local URLutil = false; |
| + | local Failsafe = WLink; |
| + | local GlobalMod = WLink; |
| + | |
| + | |
| + | |
| + | local htmlInline = { b = true, |
| + | bdi = true, |
| + | bdo = true, |
| + | big = true, |
| + | code = true, |
| + | em = true, |
| + | i = true, |
| + | kbd = true, |
| + | s = true, |
| + | samp = true, |
| + | small = true, |
| + | span = true, |
| + | strong = true, |
| + | style = true, |
| + | sub = true, |
| + | sup = true, |
| + | tt = true, |
| + | var = true }; |
| + | |
| + | |
| + | |
| + | local foreignModule = function ( access, advanced, append, alt, alert ) |
| + | -- Fetch global module |
| + | -- Precondition: |
| + | -- access -- string, with name of base module |
| + | -- advanced -- true, for require(); else mw.loadData() |
| + | -- append -- string, with subpage part, if any; or false |
| + | -- alt -- number, of wikidata item of root; or false |
| + | -- alert -- true, for throwing error on data problem |
| + | -- Postcondition: |
| + | -- Returns whatever, probably table |
| + | -- 2020-01-01 |
| + | local storage = access; |
| + | local finer = function () |
| + | if append then |
| + | storage = string.format( "%s/%s", |
| + | storage, |
| + | append ); |
| + | end |
| + | end |
| + | local fun, lucky, r, suited; |
| + | if advanced then |
| + | fun = require; |
| + | else |
| + | fun = mw.loadData; |
| + | end |
| + | GlobalMod.globalModules = GlobalMod.globalModules or { }; |
| + | suited = GlobalMod.globalModules[ access ]; |
| + | if not suited then |
| + | finer(); |
| + | lucky, r = pcall( fun, "Module:" .. storage ); |
| + | end |
| + | if not lucky then |
| + | if not suited and |
| + | type( alt ) == "number" and |
| + | alt > 0 then |
| + | suited = string.format( "Q%d", alt ); |
| + | suited = mw.wikibase.getSitelink( suited ); |
| + | GlobalMod.globalModules[ access ] = suited or true; |
| + | end |
| + | if type( suited ) == "string" then |
| + | storage = suited; |
| + | finer(); |
| + | lucky, r = pcall( fun, storage ); |
| + | end |
| + | if not lucky and alert then |
| + | error( "Missing or invalid page: " .. storage ); |
| + | end |
| + | end |
| + | return r; |
| + | end -- foreignModule() |
| | | |
| | | |
Zeile 44: |
Zeile 132: |
| -- Throws error, if not available | | -- Throws error, if not available |
| if not URLutil then | | if not URLutil then |
− | local lucky, util = pcall( require, "Module:URLutil" ); | + | local util = foreignModule( "URLutil", |
− | if lucky then | + | true, |
− | if type( util ) == "table" then
| + | false, |
− | URLutil = util.URLutil();
| + | WLink.globals.URLutil ); |
− | end
| + | if type( util ) == "table" then |
| + | URLutil = util.URLutil(); |
| + | else |
| util = "library URLutil invalid"; | | util = "library URLutil invalid"; |
| end | | end |
Zeile 57: |
Zeile 147: |
| return URLutil; | | return URLutil; |
| end -- utilURL() | | end -- utilURL() |
| + | |
| + | |
| + | |
| + | local cleanWikilink = function ( access ) |
| + | -- Refine wikilink spacing and decode |
| + | -- Precondition: |
| + | -- access -- string, with presumable link |
| + | -- Postcondition: |
| + | -- Returns string, with pretty target |
| + | local r; |
| + | if not WLink.lrm then |
| + | WLink.lrm = mw.ustring.char( 0x200E ); |
| + | WLink.rlm = mw.ustring.char( 0x200F ); |
| + | end |
| + | r = access:gsub( "_", " " ) |
| + | :gsub( " ", " " ) |
| + | :gsub( " ", " " ) |
| + | :gsub( " ", " " ) |
| + | :gsub( " ", " " ) |
| + | :gsub( "‎", "" ) |
| + | :gsub( "‏", "" ) |
| + | :gsub( WLink.lrm, "" ) |
| + | :gsub( WLink.rlm, "" ) |
| + | :gsub( "%s+", " " ); |
| + | r = mw.text.decode( r ); |
| + | return r; |
| + | end -- cleanWikilink() |
| | | |
| | | |
Zeile 187: |
Zeile 304: |
| r1 = false; | | r1 = false; |
| else | | else |
− | r1 = r1:gsub( "_", " " ) | + | r1 = cleanWikilink( r1 ); |
− | :gsub( " ", " " )
| |
− | :gsub( " ", " " )
| |
− | :gsub( " ", " " )
| |
− | :gsub( " ", " " )
| |
− | :gsub( " +", " " );
| |
− | r1 = mw.text.decode( r1 );
| |
| end | | end |
| end | | end |
Zeile 201: |
Zeile 312: |
| | | |
| | | |
− | local prefix = function ( ask, ahead ) | + | local farming = function ( already ) |
| + | -- Retrieve wikifarm project information |
| + | -- Precondition: |
| + | -- already -- table, with wikilink components |
| + | -- Postcondition: |
| + | -- Returns table, with wikilink components extended |
| + | local r = already; |
| + | if not r.project then |
| + | local codes = { mediawiki = "mw", |
| + | wikibooks = "b", |
| + | wikidata = "d", |
| + | wikinews = "n", |
| + | wikipedia = "w", |
| + | wikiquote = "q", |
| + | wikisource = "s", |
| + | wikiversity = "v", |
| + | wikivoyage = "voy", |
| + | wiktionary = "wikt" }; |
| + | local server = mw.site.server:gsub( "([/.])m%.", |
| + | "%1" ) |
| + | :gsub( "%.beta%.wmflabs%.org$", |
| + | ".org" ); |
| + | local site = server:match( "[/.](%l+)%.org$" ); |
| + | r.project = codes[ site ]; |
| + | if r.project then |
| + | if not r.lang and |
| + | r.project ~= "mw" and r.project ~= "d" then |
| + | r.lang = server:match( "//(%l+)%." ); |
| + | end |
| + | else |
| + | site = server:match( "//(%l+)%.wikimedia%.org$" ); |
| + | if site == "commons" or site == "meta" then |
| + | r.project = site; |
| + | end |
| + | end |
| + | end |
| + | if r.project and r.ns and |
| + | ( r.project == "commons" or |
| + | r.project == "d" or |
| + | r.project == "meta" or |
| + | r.project == "mw" ) then |
| + | r.language = true; |
| + | end |
| + | return r; |
| + | end -- farming() |
| + | |
| + | |
| + | |
| + | local prefix = function ( ask ) |
| -- Interprete prefix of language or project type | | -- Interprete prefix of language or project type |
| -- Precondition: | | -- Precondition: |
| -- ask -- string, with presumable prefix | | -- ask -- string, with presumable prefix |
− | -- ahead -- true, if first segment
| |
| -- Postcondition: | | -- Postcondition: |
| -- Returns string,string or nil | | -- Returns string,string or nil |
Zeile 240: |
Zeile 398: |
| }; | | }; |
| local s = mw.text.trim( ask ); | | local s = mw.text.trim( ask ); |
− | if s == "" then | + | if s ~= "" then |
− | if ahead then
| |
− | r1 = "lead";
| |
− | r2 = true;
| |
− | end
| |
− | else
| |
| local p; | | local p; |
| s = s:lower(); | | s = s:lower(); |
Zeile 324: |
Zeile 477: |
| end | | end |
| else | | else |
− | s = string.format( "%%%2X", k ); | + | s = string.format( "%%%02X", k ); |
| end | | end |
| r = string.format( "%s%s%s", | | r = string.format( "%s%s%s", |
Zeile 337: |
Zeile 490: |
| | | |
| | | |
− | function WLink.formatURL( adjust ) | + | function WLink.formatURL( adjust, assure ) |
| -- Create bracketed link, if not yet | | -- Create bracketed link, if not yet |
| -- Precondition: | | -- Precondition: |
| -- adjust -- string, with URL or domain/path or bracketed link | | -- adjust -- string, with URL or domain/path or bracketed link |
| + | -- assure -- boolean, true for secure HTTP |
| -- Postcondition: | | -- Postcondition: |
| -- Returns string, with bracketed link | | -- Returns string, with bracketed link |
Zeile 354: |
Zeile 508: |
| host = URLutil.getHost( adjust ); | | host = URLutil.getHost( adjust ); |
| if not host then | | if not host then |
− | url = "http://" .. adjust; | + | url = "://" .. adjust; |
| + | if assure then |
| + | url = "s" .. url; |
| + | end |
| + | url = "http" .. url; |
| host = URLutil.getHost( url ); | | host = URLutil.getHost( url ); |
| end | | end |
Zeile 434: |
Zeile 592: |
| return r; | | return r; |
| end -- WLink.getBaseTitle() | | end -- WLink.getBaseTitle() |
| + | |
| + | |
| + | |
| + | function WLink.getEscapedTitle( attempt ) |
| + | -- Retrieve escaped link title |
| + | -- Precondition: |
| + | -- attempt -- string, with presumable link title |
| + | -- Postcondition: |
| + | -- Returns string, with suitable link title |
| + | local s = mw.text.trim( attempt ); |
| + | return s:gsub( "\n", " " ) |
| + | :gsub( "%[", "[" ) |
| + | :gsub( "%]", "]" ) |
| + | :gsub( "|", "|" ); |
| + | end -- WLink.getEscapedTitle() |
| | | |
| | | |
Zeile 484: |
Zeile 657: |
| r = find( "file" ); | | r = find( "file" ); |
| if not r then | | if not r then |
− | local trsl = mw.site.namespaces[6]; | + | local trsl = mw.site.namespaces[ 6 ]; |
| r = find( trsl.name ); | | r = find( trsl.name ); |
| if not r then | | if not r then |
Zeile 559: |
Zeile 732: |
| return r; | | return r; |
| end -- WLink.getLanguage() | | end -- WLink.getLanguage() |
| + | |
| + | |
| + | |
| + | function WLink.getLinktextProblem( attempt ) |
| + | -- Which problem has this presumable link text? |
| + | -- Precondition: |
| + | -- attempt -- string, with presumable linktext |
| + | -- Postcondition: |
| + | -- Returns string, with error message, or false |
| + | local r; |
| + | if attempt:find( "]", 1, true ) then |
| + | r = "]"; |
| + | elseif mw.text.unstripNoWiki( attempt ) ~= attempt then |
| + | r = "<nowiki>"; |
| + | elseif attempt:find( "\n", 1, true ) then |
| + | r = "\n"; |
| + | elseif mw.text.unstrip( attempt ) ~= attempt then |
| + | if not WLink.stripREF then |
| + | WLink.stripREF = string.format( "%c%c%c%c%s%c%c%c%c", |
| + | 127, 39, 34, 96, |
| + | "UNIQ%-+ref%-%x+%-QINU", |
| + | 96, 34, 39, 127 ); |
| + | end |
| + | if mw.ustring.find( attempt, WLink.stripREF ) then |
| + | r = "<ref>"; |
| + | end |
| + | end |
| + | if not r then |
| + | local i = attempt:find( "<", 1, true ); |
| + | if i then |
| + | local s = mw.ustring.lower( attempt:sub( i ) ); |
| + | local sign = true; |
| + | local skip; |
| + | while sign and not r do |
| + | skip, sign = s:match( "^([^<]*< *)(%l[%l%d]*)[ /]*.*>" ); |
| + | if sign then |
| + | if htmlInline[ sign ] then |
| + | i = skip:len() + sign:len() + 1; |
| + | s = s:sub( i ); |
| + | else |
| + | r = string.format( "<%s>", sign ); |
| + | end |
| + | end |
| + | end -- while sign and not r |
| + | end |
| + | if not r then |
| + | local s = attempt .. " "; |
| + | if s:find( "ISBN ", 1, true ) then |
| + | r = s:match( "(ISBN %d[%-%d]+[%dxX])%W" ); |
| + | end |
| + | if not r then |
| + | if s:find( "PMID ", 1, true ) then |
| + | r = s:match( "(PMID [1-9]%d*)%W" ); |
| + | end |
| + | if not r then |
| + | if s:find( "RFC ", 1, true ) then |
| + | r = s:match( "(RFC [1-9]%d?%d?%d?)%W" ); |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
| + | return r or false; |
| + | end -- WLink.getLinktextProblem() |
| | | |
| | | |
Zeile 579: |
Zeile 816: |
| return r; | | return r; |
| end -- WLink.getNamespace() | | end -- WLink.getNamespace() |
| + | |
| + | |
| + | |
| + | function WLink.getNamespaced( area, attempt ) |
| + | -- Retrieve page in namespace |
| + | -- Precondition: |
| + | -- area -- string or number, with some namespace spec |
| + | -- attempt -- string, with wikilink or page title or page name |
| + | -- Postcondition: |
| + | -- Returns page prefixed by namespace, |
| + | -- false if invalid |
| + | local r = false; |
| + | local s = type( area ); |
| + | local room; |
| + | if s == "string" then |
| + | room = mw.site.namespaces[ tonumber( area ) or area ]; |
| + | elseif s == "number" then |
| + | room = mw.site.namespaces[ area ]; |
| + | end |
| + | if room then |
| + | local m; |
| + | s, m = WLink.getTarget( attempt ); |
| + | if not s then |
| + | s = attempt; |
| + | elseif m ~= 2 then |
| + | s = false; |
| + | end |
| + | if s then |
| + | local w = WLink.wikilink( s ); |
| + | if w and not w.lang and not w.project and |
| + | ( not w.ns or w.ns == room.id ) then |
| + | r = string.format( "%s:%s", |
| + | room.name, w.title ); |
| + | end |
| + | end |
| + | end |
| + | return r; |
| + | end -- WLink.getNamespaced() |
| | | |
| | | |
Zeile 605: |
Zeile 880: |
| if k > 1 then | | if k > 1 then |
| n = n - k; | | n = n - k; |
− | i = j + k; | + | i = j + k + 1; |
| j = i - 1; | | j = i - 1; |
| suffix = r:sub( j ); | | suffix = r:sub( j ); |
Zeile 653: |
Zeile 928: |
| break; -- while true | | break; -- while true |
| end | | end |
− | end -- while true | + | end -- while true |
| return r; | | return r; |
| end -- WLink.getPlain() | | end -- WLink.getPlain() |
Zeile 676: |
Zeile 951: |
| return r; | | return r; |
| end -- WLink.getProject() | | end -- WLink.getProject() |
| + | |
| + | |
| + | |
| + | function WLink.getTalkPage( attempt ) |
| + | -- Retrieve talk page name for attempt, or that page name itself |
| + | -- Precondition: |
| + | -- attempt -- string, with presumable link somewhere |
| + | -- Postcondition: |
| + | -- Returns string or false |
| + | local r = false; |
| + | local s, m = WLink.getTarget( attempt ); |
| + | if m ~= 2 and attempt then |
| + | s = mw.text.trim( attempt ); |
| + | end |
| + | if s and s ~= "" then |
| + | local w = mw.title.new( s ); |
| + | if w then |
| + | w = w.talkPageTitle; |
| + | if w then |
| + | r = w.prefixedText; |
| + | end |
| + | end |
| + | end |
| + | return r; |
| + | end -- WLink.getTalkPage() |
| | | |
| | | |
Zeile 788: |
Zeile 1.088: |
| end | | end |
| if URLutil.isResourceURL( attempt ) then | | if URLutil.isResourceURL( attempt ) then |
− | local site = URLutil.getAuthority( attempt ); | + | local site = URLutil.getAuthority( attempt ); |
| + | local service = attempt; |
| local show; | | local show; |
| if #attempt == #site then | | if #attempt == #site then |
Zeile 795: |
Zeile 1.096: |
| show = URLutil.getTop3domain( "//" .. site ); | | show = URLutil.getTop3domain( "//" .. site ); |
| if show then | | if show then |
− | local scan = "[%./](%a+)(%.%l%l%.)(%a+)$"; | + | local scan = "[%./](%a[%a%%%-]*%a)(%.%l%l%.)(%a+)$"; |
| local search = "." .. show; | | local search = "." .. show; |
| local s1, s2, s3 = search:match( scan ); | | local s1, s2, s3 = search:match( scan ); |
| if s2 then | | if s2 then |
| if not second:find( s2, 1, true ) then | | if not second:find( s2, 1, true ) then |
− | show = string.format( "%s.%s", s2, s3 ); | + | show = string.format( "%s%s", s2:sub( 2 ), s3 ); |
| end | | end |
| else | | else |
Zeile 812: |
Zeile 1.113: |
| end | | end |
| end | | end |
− | r = string.format( "[%s %s]", attempt, show ); | + | if not service:match( "^[a-z:]*//.+/" ) then |
| + | service = service .. "/"; |
| + | end |
| + | r = string.format( "[%s %s]", service, show ); |
| else | | else |
| r = attempt; | | r = attempt; |
Zeile 818: |
Zeile 1.122: |
| return r; | | return r; |
| end -- WLink.getWeblink() | | end -- WLink.getWeblink() |
| + | |
| + | |
| + | |
| + | function WLink.getWikilink( attempt, appear ) |
| + | -- Retrieve bracketed link from text |
| + | -- Precondition: |
| + | -- attempt -- string, with current target, or plain |
| + | -- appear -- string, with link title, or nil |
| + | -- Postcondition: |
| + | -- Returns string, with first detected link target |
| + | -- false if nothing found |
| + | local r = WLink.pageTarget( attempt ); |
| + | if r then |
| + | if appear then |
| + | local show = WLink.getEscapedTitle( appear ); |
| + | if show ~= r and show ~= "" then |
| + | r = string.format( "%s|%s", r, show ); |
| + | end |
| + | end |
| + | r = string.format( "[[%s]]", r ); |
| + | end |
| + | return r; |
| + | end -- WLink.getWikilink() |
| | | |
| | | |
Zeile 951: |
Zeile 1.278: |
| return r; | | return r; |
| end -- WLink.isMedia() | | end -- WLink.isMedia() |
| + | |
| + | |
| + | |
| + | function WLink.isTalkPage( attempt ) |
| + | -- Does attempt describe a talk page? |
| + | -- Precondition: |
| + | -- attempt -- string, with presumable link somewhere |
| + | -- Postcondition: |
| + | -- Returns boolean |
| + | local r = false; |
| + | local s, m = WLink.getTarget( attempt ); |
| + | if m ~= 2 and attempt then |
| + | s = mw.text.trim( attempt ); |
| + | end |
| + | if s and s ~= "" then |
| + | local w = mw.title.new( s ); |
| + | if w then |
| + | r = w.isTalkPage; |
| + | end |
| + | end |
| + | return r; |
| + | end -- WLink.isTalkPage() |
| | | |
| | | |
Zeile 990: |
Zeile 1.339: |
| -- Postcondition: | | -- Postcondition: |
| -- Returns boolean | | -- Returns boolean |
− | local s, r = WLink.getTarget( attempt ); | + | local u, r = WLink.getTarget( attempt ); |
| if r then | | if r then |
− | r = true; | + | if r < 2 then |
| + | if u:find( "''", 1, true ) then |
| + | r = false; |
| + | else |
| + | r = true; |
| + | end |
| + | else |
| + | r = true; |
| + | end |
| end | | end |
| return r; | | return r; |
| end -- WLink.isValidLink() | | end -- WLink.isValidLink() |
| + | |
| + | |
| + | |
| + | function WLink.isValidLinktext( attempt, allow ) |
| + | -- Is attempt a plain inline text? |
| + | -- Precondition: |
| + | -- attempt -- string, with presumable linktext |
| + | -- allow -- boolean or nil, if multiline permitted |
| + | -- Postcondition: |
| + | -- Returns boolean |
| + | local s; |
| + | if allow and s:find( "\n", 1, true ) then |
| + | s = attempt:gsub( "\n", " " ); |
| + | else |
| + | s = attempt; |
| + | end |
| + | return not WLink.getLinktextProblem( s ); |
| + | end -- WLink.isValidLinktext() |
| | | |
| | | |
Zeile 1.008: |
Zeile 1.383: |
| return ( m == 2 ); | | return ( m == 2 ); |
| end -- WLink.isWikilink() | | end -- WLink.isWikilink() |
| + | |
| + | |
| + | |
| + | function WLink.pageLink( attempt, appear, assure ) |
| + | -- Create safely standardized wikilink target of a page |
| + | -- attempt -- string, with presumable link |
| + | -- appear -- string or true or nil, with link title |
| + | -- assure -- string or nil, shield against wiki template syntax |
| + | -- "URL" or "WIKI" |
| + | -- Postcondition: |
| + | -- Returns string with link target |
| + | local r = WLink.pageTarget( attempt, assure ); |
| + | if appear then |
| + | local show; |
| + | if type( appear ) == "string" then |
| + | show = appear; |
| + | else |
| + | show = attempt; |
| + | end |
| + | r = string.format( "%s|%s", r, show ); |
| + | end |
| + | return r; |
| + | end -- WLink.pageLink() |
| + | |
| + | |
| + | |
| + | function WLink.pageTarget( attempt, assure ) |
| + | -- Create standardized wikilink target of a page |
| + | -- Precondition: |
| + | -- attempt -- string, with presumable link |
| + | -- expected to be enclosed in "[[" "]]" |
| + | -- else wikilink |
| + | -- table, of assignments with { type, value } |
| + | -- type is one of "lead", |
| + | -- "project", "lang", |
| + | -- "ns", "space", "title" |
| + | -- assure -- string or nil, shield against wiki template syntax |
| + | -- "URL" or "WIKI" |
| + | -- Postcondition: |
| + | -- Returns string with link target |
| + | local p = type( attempt ); |
| + | local s = assure; |
| + | local r; |
| + | if p == "string" then |
| + | p = WLink.wikilink( attempt ); |
| + | elseif p == "table" then |
| + | p = attempt; |
| + | else |
| + | p = false; |
| + | end |
| + | if p then |
| + | local site = p.project; |
| + | local slang = p.lang; |
| + | local lead; |
| + | if p.title:sub( 1, 1 ) == "#" then |
| + | p.title = mw.title.getCurrentTitle().text + p.title; |
| + | end |
| + | if p.ns then |
| + | if not slang then |
| + | p = farming( p ); |
| + | end |
| + | if p.lang and |
| + | p.lang ~= mw.language.getContentLanguage():getCode() then |
| + | p.language = true; |
| + | end |
| + | if p.language then |
| + | p.space = mw.site.namespaces[ p.ns ].canonicalName; |
| + | end |
| + | lead = ( p.ns == 6 or p.ns == 14 ); |
| + | end |
| + | if slang then |
| + | lead = true; |
| + | end |
| + | if s == "WIKI" then |
| + | if not site and |
| + | ( lead or |
| + | ( not p.space and |
| + | p.title and p.title:match( "^[*;]" ) ) ) then |
| + | p = farming( p ); |
| + | site = p.project; |
| + | slang = p.lang; |
| + | end |
| + | s = false; |
| + | end |
| + | if site then |
| + | r = site .. ":"; |
| + | elseif lead then |
| + | r = ":"; |
| + | else |
| + | r = ""; |
| + | end |
| + | if slang then |
| + | r = string.format( "%s%s:", r, slang ); |
| + | end |
| + | if p.space then |
| + | r = string.format( "%s%s:", r, p.space ); |
| + | end |
| + | if p.title then |
| + | r = r .. p.title; |
| + | end |
| + | if r == "" then |
| + | r = false; |
| + | end |
| + | end |
| + | if not r then |
| + | p = { lang = mw.language.getContentLanguage():getCode() }; |
| + | if s == "WIKI" then |
| + | r = WLink.pageTarget( p, s ); |
| + | s = false; |
| + | else |
| + | r = string.format( ":%s:", p.lang ); |
| + | end |
| + | end |
| + | if s == "URL" and r:match( "^[*#;:]" ) then |
| + | r = mw.uri.encode( r:sub( 1, 1 ) ) .. r:sub( 2 ); |
| + | end |
| + | return r; |
| + | end -- WLink.pageTarget() |
| | | |
| | | |
Zeile 1.019: |
Zeile 1.512: |
| -- Postcondition: | | -- Postcondition: |
| -- Returns table or false | | -- Returns table or false |
− | -- table of assignments with { type, value} | + | -- table of assignments with { type, value } |
| -- type is one of "lead", | | -- type is one of "lead", |
| -- "project", "lang", | | -- "project", "lang", |
| -- "ns", "space", "title" | | -- "ns", "space", "title" |
| -- false if nothing found | | -- false if nothing found |
− | local s = contentWikilink( attempt ); | + | local s = contentWikilink( attempt or "" ); |
− | local got, n, r; | + | local got, i, n, r; |
| if not s then | | if not s then |
| s = attempt; | | s = attempt; |
| + | end |
| + | if s:find( "%", 1, true ) then |
| + | s = mw.uri.decode( s, "PATH" ); |
| end | | end |
| i = s:find( "|", 1, true ); | | i = s:find( "|", 1, true ); |
Zeile 1.040: |
Zeile 1.536: |
| local j, k, o, v; | | local j, k, o, v; |
| r = { title = "" }; | | r = { title = "" }; |
| + | while ( got[ 1 ] == "" ) do |
| + | r.lead = true; |
| + | table.remove( got, 1 ); |
| + | n = n - 1; |
| + | end -- while got[ 1 ] == "" |
| if n > 4 then | | if n > 4 then |
| k = 4; | | k = 4; |
| + | elseif n > 1 then |
| + | k = n - 1; |
| else | | else |
− | k = n - 1; | + | k = 1; |
| end | | end |
| j = k; | | j = k; |
Zeile 1.049: |
Zeile 1.552: |
| s = mw.text.trim( got[ i ] ); | | s = mw.text.trim( got[ i ] ); |
| if s ~= "" then | | if s ~= "" then |
− | o = mw.site.namespaces[ mw.text.trim( got[ i ] ) ]; | + | o = mw.site.namespaces[ s ]; |
| if o then | | if o then |
| r.ns = o.id; | | r.ns = o.id; |
Zeile 1.060: |
Zeile 1.563: |
| end -- for i | | end -- for i |
| for i = 1, j do | | for i = 1, j do |
− | o, v = prefix( got[ i ], ( i == 1 ) ); | + | o, v = prefix( got[ i ] ); |
| if o then | | if o then |
| if r[ o ] then | | if r[ o ] then |
Zeile 1.066: |
Zeile 1.569: |
| break; -- for i | | break; -- for i |
| else | | else |
| + | if i >= k then |
| + | k = i + 1; |
| + | end |
| r[ o ] = v; | | r[ o ] = v; |
| end | | end |
| else | | else |
| + | if i == 1 and r.ns then |
| + | r.ns = false; |
| + | r.space = false; |
| + | end |
| k = i; | | k = i; |
| break; -- for i | | break; -- for i |
| end | | end |
| end -- for i | | end -- for i |
− | for i = k, n do | + | if k > 0 then |
− | r.title = r.title .. got[ i ];
| + | for i = k, n do |
− | if i < n then
| + | r.title = r.title .. got[ i ]; |
− | r.title = r.title .. ":";
| + | if i < n then |
− | end
| + | r.title = r.title .. ":"; |
− | end -- for i
| + | end |
| + | end -- for i |
| + | end |
| end | | end |
| + | r.title = cleanWikilink( r.title ); |
| if r.lead and | | if r.lead and |
− | ( r.project or not r.title or | + | ( r.project or |
| ( not r.lang and r.ns ~= 6 and r.ns ~= 14 ) ) then | | ( not r.lang and r.ns ~= 6 and r.ns ~= 14 ) ) then |
| r.lead = false; | | r.lead = false; |
Zeile 1.090: |
Zeile 1.603: |
| | | |
| | | |
− | function WLink.failsafe( assert )
| + | Failsafe.failsafe = function ( atleast ) |
| -- Retrieve versioning and check for compliance | | -- Retrieve versioning and check for compliance |
| -- Precondition: | | -- Precondition: |
− | -- assert -- string, with required version, or false | + | -- atleast -- string, with required version or "wikidata" or "~" |
| + | -- or false |
| -- Postcondition: | | -- Postcondition: |
− | -- Returns string with appropriate version, or false | + | -- Returns string -- with queried version, also if problem |
| + | -- false -- if appropriate |
| + | local last = ( atleast == "~" ); |
| + | local since = atleast; |
| local r; | | local r; |
− | if assert and assert > WLink.serial then | + | if last or since == "wikidata" then |
− | r = false;
| + | local item = Failsafe.item; |
− | else | + | since = false; |
− | r = WLink.serial; | + | if type( item ) == "number" and item > 0 then |
| + | local ent = mw.wikibase.getEntity( string.format( "Q%d", |
| + | item ) ); |
| + | if type( ent ) == "table" then |
| + | local vsn = ent:formatPropertyValues( "P348" ); |
| + | if type( vsn ) == "table" and |
| + | type( vsn.value ) == "string" and |
| + | vsn.value ~= "" then |
| + | if last and vsn.value == Failsafe.serial then |
| + | r = false; |
| + | else |
| + | r = vsn.value; |
| + | end |
| + | end |
| + | end |
| + | end |
| + | end |
| + | if type( r ) == "nil" then |
| + | if not since or since <= Failsafe.serial then |
| + | r = Failsafe.serial; |
| + | else |
| + | r = false; |
| + | end |
| end | | end |
− | return r | + | return r; |
− | end -- WLink.failsafe() | + | end -- Failsafe.failsafe() |
| | | |
| | | |
Zeile 1.119: |
Zeile 1.658: |
| local s = false; | | local s = false; |
| local r = false; | | local r = false; |
− | local space; | + | local safe, space; |
| for k, v in pairs( frame.args ) do | | for k, v in pairs( frame.args ) do |
| if k == 1 then | | if k == 1 then |
Zeile 1.127: |
Zeile 1.666: |
| s = mw.text.trim( v ); | | s = mw.text.trim( v ); |
| end | | end |
− | elseif action == "ansiPercent" and k == "space" then | + | elseif ( k == 2 and |
| + | ( action == "getNamespaced" or |
| + | action == "getWikilink" or |
| + | action == "pageLink" ) ) or |
| + | ( k == "space" and action == "ansiPercent" ) then |
| + | v = mw.text.trim( v ); |
| if v ~= "" then | | if v ~= "" then |
| space = v; | | space = v; |
| end | | end |
| + | elseif k == "safe" and action == "pageLink" then |
| + | v = mw.text.trim( v ); |
| + | if v ~= "" then |
| + | safe = v; |
| + | end |
| + | elseif k == "lines" and action == "isValidLinktext" then |
| + | space = ( k == "1" ); |
| elseif k ~= "template" then | | elseif k ~= "template" then |
| lucky = false; | | lucky = false; |
Zeile 1.143: |
Zeile 1.694: |
| if lucky then | | if lucky then |
| if s or lone then | | if s or lone then |
− | lucky, r = pcall( WLink[ action ], s, space ); | + | lucky, r = pcall( WLink[ action ], s, space, safe ); |
| else | | else |
| r = "Parameter missing"; | | r = "Parameter missing"; |
Zeile 1.158: |
Zeile 1.709: |
| end | | end |
| else | | else |
− | r = string.format( "<span class=\"error\">%s</span>", r ); | + | local e = mw.html.create( "span" ); |
| + | r = tostring( e:addClass( "error" ) |
| + | :wikitext( r ) ); |
| end | | end |
| return r; | | return r; |
Zeile 1.179: |
Zeile 1.732: |
| p.getBaseTitle = function ( frame ) | | p.getBaseTitle = function ( frame ) |
| return Template( frame, "getBaseTitle" ); | | return Template( frame, "getBaseTitle" ); |
| + | end |
| + | p.getEscapedTitle = function ( frame ) |
| + | return Template( frame, "getEscapedTitle" ); |
| end | | end |
| p.getExtension = function ( frame ) | | p.getExtension = function ( frame ) |
Zeile 1.194: |
Zeile 1.750: |
| p.getLanguage = function ( frame ) | | p.getLanguage = function ( frame ) |
| return Template( frame, "getLanguage" ); | | return Template( frame, "getLanguage" ); |
| + | end |
| + | p.getLinktextProblem = function ( frame ) |
| + | return Template( frame, "getLinktextProblem" ); |
| end | | end |
| p.getNamespace = function ( frame ) | | p.getNamespace = function ( frame ) |
| return tostring( Template( frame, "getNamespace" ) ); | | return tostring( Template( frame, "getNamespace" ) ); |
| + | end |
| + | p.getNamespaced = function ( frame ) |
| + | return tostring( Template( frame, "getNamespaced" ) ); |
| end | | end |
| p.getPlain = function ( frame ) | | p.getPlain = function ( frame ) |
Zeile 1.203: |
Zeile 1.765: |
| p.getProject = function ( frame ) | | p.getProject = function ( frame ) |
| return Template( frame, "getProject" ); | | return Template( frame, "getProject" ); |
| + | end |
| + | p.getTalkPage = function ( frame ) |
| + | return Template( frame, "getTalkPage" ); |
| end | | end |
| p.getTarget = function ( frame ) | | p.getTarget = function ( frame ) |
Zeile 1.215: |
Zeile 1.780: |
| p.getWeblink = function ( frame ) | | p.getWeblink = function ( frame ) |
| return Template( frame, "getWeblink" ); | | return Template( frame, "getWeblink" ); |
| + | end |
| + | p.getWikilink = function ( frame ) |
| + | return Template( frame, "getWikilink" ); |
| end | | end |
| p.isBracketedLink = function ( frame ) | | p.isBracketedLink = function ( frame ) |
Zeile 1.236: |
Zeile 1.804: |
| p.isMedia = function ( frame ) | | p.isMedia = function ( frame ) |
| return Template( frame, "isMedia" ); | | return Template( frame, "isMedia" ); |
| + | end |
| + | p.isTalkPage = function ( frame ) |
| + | return Template( frame, "isTalkPage" ); |
| end | | end |
| p.isTitledLink = function ( frame ) | | p.isTitledLink = function ( frame ) |
Zeile 1.242: |
Zeile 1.813: |
| p.isValidLink = function ( frame ) | | p.isValidLink = function ( frame ) |
| return Template( frame, "isValidLink" ); | | return Template( frame, "isValidLink" ); |
| + | end |
| + | p.isValidLinktext = function ( frame ) |
| + | return Template( frame, "isValidLinktext" ); |
| end | | end |
| p.isWeblink = function ( frame ) | | p.isWeblink = function ( frame ) |
Zeile 1.248: |
Zeile 1.822: |
| p.isWikilink = function ( frame ) | | p.isWikilink = function ( frame ) |
| return Template( frame, "isWikilink" ); | | return Template( frame, "isWikilink" ); |
| + | end |
| + | p.pageLink = function ( frame ) |
| + | return Template( frame, "pageLink" ); |
| end | | end |
| p.failsafe = function ( frame ) | | p.failsafe = function ( frame ) |
Zeile 1.263: |
Zeile 1.840: |
| end | | end |
| end | | end |
− | return WLink.failsafe( since ) or ""; | + | return Failsafe.failsafe( since ) or ""; |
− | end | + | end -- p.failsafe |
| p.WLink = function () | | p.WLink = function () |
| return WLink; | | return WLink; |