Changes

Jump to: navigation, search

Module:Autolink

1,360 bytes added, 5 months ago
some tweaks: clean up globals; slightly optimize unprettify(); slightly more descriptive variable names in prettify_link(); expand ref comment a bit
--
-- implements {{Autolink}} , {{Unlink}}, and {{UnlinkFormatted link}}
--
require('Module:No globals')
local p = {}
-- removes all special formatting from a stringlocal function p.linkunprettify( frame s ) local args = frame return s:getParentgsub('""', '' ).args -- for testing from console :gsub( "'''?", '' ) :gsub( '[# ]##?', ' ' ) -- local args = framelmao -- marker used for {{nolink}} support :gsub(doesn't have to be a zero-width non-joiner ', that's just what I used in the template version' ) local zwnj = '‌' local links, nolink, listmarkup, escape, el, link, text, formatl, formatrend
-- set default to stop errorsformats a link argslocal function prettify_link( target, label ) if not target or target == '' then return '' end if not label or label == '' then label = target end local plain_target = unprettify( target ) local plain_label = unprettify( label ) local prettified_label = label:gsub( '""', '"' ):gsub( '([^&# ])#([^#])', '%1§ %2' ):gsub( '##', '#' ) local link = '' if plain_target == prettified_label then -- no formatting link = ('[[%s] ]'):format( plain_target ) elseif plain_target == plain_label then local start, _end = prettified_label:find( plain_target, 1, true ) if start then -- only formatting is on the link boundaries (`''Foo Bar''`) link = args('%s[[%s]]%s'):format( prettified_label:sub( 1, start - 1 ), plain_target, prettified_label:sub( _end + 1) ) else -- formatting within the link (`''Foo Bar'' (Quux)`) link = ('[[%s|%s] and mw.]'):format( plain_target, prettified_label ) end else if plain_label == prettified_label then -- no formatting link = ('[[%s|%s]]'):format( plain_target, prettified_label ) else local start, _end = prettified_label:find( plain_label, 1, true ) if start then -- only formatting is on the text.trimboundaries ( args`[[Foo Bar Baz|''Foo Bar'']]`) link = ('%s[[%s|%s]]%s'):format( prettified_label:sub( 1, start - 1 ), plain_target, prettified_label:sub( start, _end ), prettified_label:sub( _end + 1) ) else -- formatting within the text (`[[Foo Bar Baz|''Foo'' Bar] ]`) or link = ('[[%s|%s]]'):format( plain_target, prettified_label ) end end end return linkend
links = mw.text.split( args[1], '\n' )  args[2] = #links == 1 and args[2]  nolink = mw.ustring.find( args[1], zwnj ) == 1 listmarkup = #links == 1 and -- there's several things this doesn for i=1, #links t dothat it probably could/should: el = mw.text.trim( links[i] )  -- catch empty string at the start of * supporting mixed lists if el ~= '' then if listmarkup ~= '' then listmarkup = mw.ustring.match( el, '^([*#;:])' currently it assumes that whatever list type is used by the first item is the same as all other items) or '*' el = mw.ustring.gsub( el, '^[-- *#;:]%s*'similarly, '' )supporting sublists end  if mw.ustring.find( el-- * allowing multiple items to be linked/formatted via multiple parameters, zwnj ) or mw.ustring.find( el, '%[%[' ) or nolink theninstead of just via a list in the first parameter el = mw.ustring.gsub( el, '%[%[[Cc]ategory:', '[[:Category:' ) el = mw.ustring.gsub( el, '%[%[[Ff]ile:', '[[:File:' ) el = mw.ustring.gsub( el, '%[%[[Ii]mage:', '[[:Image:' ) links[i] = table.concat( { listmarkup, el }, '' ) else -- * supporting multiline link = el text = args[2] or el formatl = '' formatr = ''  link = mw.ustring.gsubsyntax ( linkprobably most likely from SMW annotations with multiline values, '""', '' ) link = mw.ustring.gsub( link, "'''?", '' though file embeds can have multiline descriptions too -- check for formatting that can * allowing text to be moved out of removed from the link entirely if mw.ustring.findfor display ( text, '^""' ) and mwe.ustringg.findexcluding the dabtag in `Dark Magician ( text, '""$' manga) then formatl = '"' formatr = '"' text = mw.ustring.gsub( text, '""', '' `) else text = mwfunction p.ustring.gsub( text, '""', '"' ) end if mw.ustring.findlink( text, "^'''" frame ) and mw.ustring.find( text, "'''$" ) then formatl local args = formatl .. "'''" formatr = "'''" .. formatr text frame = mw.ustring.gsub( text, "^'''", '' ) text = mw.ustring.gsub( text, "'''$", '' ) end if mw.ustring.findgetCurrentFrame( text, "^''" ) and mw.ustring.findframe:getParent( text, "''$" ) then formatl = formatl .. "''" formatr = "''" .. formatr text = mw.ustring.gsub( text, "^''", '' ) text = mw.ustring.gsub( text, "''$", '' ) end  if mw.ustring.find( link, '^[Cc]ategory:' ) args or mw.ustring.find( link, '^[Ff]ile:' ) or mw.ustring.find( link, '^[Ii]mage:' ) then escape = ':' else escape = '' endframe
if link -- the gsub() is a dumb hack for the encoded apostrophe test case(s) local items == text then linksargs[1] and args[i1] = table.concat:gsub( { listmarkup, formatl, '[[&', escape, link, ']]&', formatr }, ) or '' ) else -- remove any empty lines/list items from the input links[i] local lines = table{} for item in mw.text.concatgsplit( { listmarkup, formatlitems, '[[\n', escape, link, '|', ) do item = mw.text, .trim( item:match( '^[*#;:]]?(.*)$', formatr }, ) ) if item ~= '' then table.insert( lines, item ) end end end end
links -- if there's more than one line, grab the list character (with a fallback if there is none) local listtype = '' if #lines > 1 then listtype = (items:match( '^%s*([*#;:])' ) or '*') .. ' ' end -- format, link, and return local prettified_lines = {} local result = '' for _, line in ipairs( lines ) do if line:find( '[[', 1, true ) then local prettified_line = {} local post = line while post:find( '[[', 1, true ) do local pre, annotation, target, label if post:match( '^[^%[]*%[%[[^|%]]+::' ) then -- don't format SMW annotations pre, annotation = post:match( '^([^%[]*)(%[%[[^%]]+%]%])' ) else pre, target, label = post:match( '^([^%[]*)%[%[ *([^|%]]+) *|? *([^%]]-) *%]%]' ) end table.concatinsert( prettified_line, ('%s%s'):format( pre and pre:gsub( links'""', '\n"' ) or '' , target and prettify_link( target, label ) or annotation ) ) links post = mwpost:match( '%]%](.ustring*)$' ) end result = ('%s%s'):format( table.concat( prettified_line ), post:gsub( links'""', zwnj'"' ) ) elseif line:find( '\127', 1, true ) then -- input is unlinked but has a ref tag -- \127 (DEL) is the start/end character of strip markers -- technically this will match any stripped content, not just ref tags local link, ref = line:match( '^([^\127]+)(\127.*)$' ) links result = mw('%s%s'):format( prettify_link( link ), ref ) else result = prettify_link( line ) end table.textinsert( prettified_lines, ('%s%s'):format( listtype, result ) ) end prettified_lines = table.trimconcat( prettified_lines, '\n' ) :gsub( links '%[%[[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]:', '[[:Category:' ) :gsub( '%[%[[Ff][Ii][Ll][Ee]:', '[[:File:' ) :gsub( '%[%[[Ii][Mm][Aa][Gg][Ee]:', '[[:File:' ) return linksprettified_lines
end
-- returns the target of the first link in text
-- to return the entire text without any links instead, see {{Delink}}
function p.unlink( frame )
local args txt = frame == mw.getCurrentFrame() and frame:getParent().args args[1] = argsor frame[1] or '' return mw.ustring.txt and ( txt:match( args[1], '%[%[:?(.-)[|%]]' ) or mw.text.trim( args[1] txt ) )
end
return p

Navigation menu