Difference between revisions of "Module:Autolink"
Dinoguy1000 (talk | contribs) (complete rewrite from sandbox, featuring many fixed bugs and proper multilink support) |
Dinoguy1000 (talk | contribs) (from sandbox: don't format SMW annotations if they're included in the input) |
||
Line 79: | Line 79: | ||
local post = line | local post = line | ||
while post:find( '[[', 1, true ) do | while post:find( '[[', 1, true ) do | ||
− | local pre, target, txt = post:match( '^([^%[]*)%[%[%s*([^|%]]+)%s*|?%s*([^%]]-)%s*%]%]' ) | + | local pre, annotation, target, txt |
− | table.insert( prettified_line, ('%s%s'):format( pre and pre:gsub( '""', '"' ) or '', prettify_link( target, txt ) ) ) | + | if post:match( '^[^%[]*%[%[[^|%]]+::' ) then |
+ | -- don't format SMW annotations | ||
+ | pre, annotation = post:match( '^([^%[]*)(%[%[[^%]]+%]%])' ) | ||
+ | else | ||
+ | pre, target, txt = post:match( '^([^%[]*)%[%[%s*([^|%]]+)%s*|?%s*([^%]]-)%s*%]%]' ) | ||
+ | end | ||
+ | table.insert( prettified_line, ('%s%s'):format( pre and pre:gsub( '""', '"' ) or '', target and prettify_link( target, txt ) or annotation ) ) | ||
post = post:match( '%]%](.*)$' ) | post = post:match( '%]%](.*)$' ) | ||
end | end |
Revision as of 11:47, 1 May 2023
--
-- implements {{Autolink}}, {{Unlink}}, and {{Formatted link}}
--
local p = {}
-- removes all special formatting from a string
local function unprettify( s )
return s:gsub( '""', '' )
:gsub( "'''?", '' )
:gsub( '##', ' ' )
:gsub( ' ', ' ' )
end
-- formats a link
local function prettify_link( target, txt )
if not target or target == '' then
return ''
end
if not txt or txt == '' then
txt = target
end
local plain_target = unprettify( target )
local prettified_txt = txt:gsub( '""', '"' ):gsub( '##', '<>' ):gsub( '([^&])#', '%1 § ' ):gsub( '<>', '#' )
local link = ''
if plain_target == prettified_txt then
-- no formatting
link = ('[[%s]]'):format( plain_target )
else
local start, _end = prettified_txt:find( plain_target, 1, true )
if start then
-- only formatting is on the link boundaries (`''Foo Bar''`)
link = ('%s[[%s]]%s'):format( prettified_txt:sub( 1, start - 1 ), plain_target, prettified_txt:sub( _end + 1 ) )
else
-- formatting within the link (`''Foo Bar'' (Quux)`)
link = ('[[%s|%s]]'):format( plain_target, prettified_txt )
end
end
return link
end
-- there's several things this doesn't do that it probably could/should:
-- * supporting mixed lists (currently it assumes that whatever list type is used by the first item is the same as all other items)
-- ** similarly, supporting sublists
-- * allowing multiple items to be linked/formatted via multiple parameters, instead of just via a list in the first parameter
function p.link( frame )
if frame == mw.getCurrentFrame() then
args = frame:getParent().args
else
args = frame
end
-- the gsub() is a dumb hack for the encoded apostrophe test case(s)
local items = args[1] and args[1]:gsub( '&', '&' ) or ''
-- remove any empty lines/list items from the input
local lines = {}
for item in mw.text.gsplit( items, '\n' ) do
item = mw.text.trim( item:match( '^[*#;:]?(.-)$' ) )
if item ~= '' then
table.insert( lines, item )
end
end
-- 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 = {}
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, txt
if post:match( '^[^%[]*%[%[[^|%]]+::' ) then
-- don't format SMW annotations
pre, annotation = post:match( '^([^%[]*)(%[%[[^%]]+%]%])' )
else
pre, target, txt = post:match( '^([^%[]*)%[%[%s*([^|%]]+)%s*|?%s*([^%]]-)%s*%]%]' )
end
table.insert( prettified_line, ('%s%s'):format( pre and pre:gsub( '""', '"' ) or '', target and prettify_link( target, txt ) or annotation ) )
post = post:match( '%]%](.*)$' )
end
result = ('%s%s'):format( table.concat( prettified_line ), post:gsub( '""', '"' ) )
else
result = prettify_link( line )
end
table.insert( prettified_lines, ('%s%s'):format( listtype, result ) )
end
prettified_lines = table.concat( prettified_lines, '\n' )
:gsub( '%[%[[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]:', '[[:Category:' )
:gsub( '%[%[[Ff][Ii][Ll][Ee]:', '[[:File:' )
:gsub( '%[%[[Ii][Mm][Aa][Gg][Ee]:', '[[:File:' )
return prettified_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 )
if frame == mw.getCurrentFrame() then
txt = frame:getParent().args[1]
else
txt = frame[1]
end
return txt and ( txt:match( '%[%[:?(.-)[|%]]' ) or mw.text.trim( txt ) )
end
return p