跳转到内容

Module:Inline annotation combinable

維基文庫,自由的圖書館

-- lua module creating inline annotations that span multiple lines
require('strict')

local p = {} --p stands for package

local getArgs = require('Module:Arguments').getArgs
local error_message = require('Module:Error')['error']
local if_vertical = require('Module:If vertical')._main
local getTemplatesByName = require('Module:Transcluder more').getTemplatesByName
local getTemplateParameterByName = require('Module:Transcluder more').getTemplateParameterByName
local aliases = {'Iac'}
-- Helper function to parse a min-max range or number of page
-- Modified from Module:Transcluder: https://en.wikipedia.org/wiki/Module:Transcluder
-- Authors of Module:Transcluder: User:Sophivorus, User:Certes & others
-- License of Module:Transcluder: CC-BY-SA-3.0

local function parsePage(value)
	local first_page = 0
	local last_page = 0

	if type(value) == 'number' then
		first_page = value
		last_page = value

	elseif type(value) == 'string' then
		local range = mw.text.trim(value)
			local min, max = mw.ustring.match(range, '^(%d+)%s*[-–—]%s*(%d+)$') -- '3-5' to min=3 max=5
			if not max then min, max = string.match(range, '^((%d+))$') end -- '1' to min=1 max=1
			if max then
				first_page = min
				last_page = max
			end
		end
	return first_page, last_page
end

-- main function
function p.main(frame)
	local args = getArgs(frame, {
	trim = true,
	removeBlanks = false
	})
	return p._main(args)
end

-- function to create the annotations
function p._main(args)
	-- decide the writing direction
	local direction = if_vertical({'v','h'})
	local new_line_if_vertical = if_vertical({'<br>',''})

	-- line number
	--local parameter_count = 0
	--for i,line in ipairs(args) do
	--	parameter_count = parameter_count + 1
	--end
	--local line_number = math.floor((parameter_count + 1)/ 2) 
	
	local numbered_args = {}
	for i, v in pairs(args) do 
		numbered_args[i] = v 
	end
	-- transclusion
	local file_name = args.file
	local frame = mw.getCurrentFrame()
	local page_title = mw.title.getCurrentTitle()
	if file_name and not page_title:inNamespace(104) then
		local pages = args.pages or ''
		if pages == '' then
			error('參數錯誤:缺少嵌入的頁碼')
		end
		local first_page, last_page = parsePage(pages)
		local frame = mw.getCurrentFrame()
		-- transclusion by getTemplatesByName
		for i = first_page, last_page do
			local remote_title_name = 'Page:' .. file_name .. '/' .. i
			local remote_title = mw.title.new(remote_title_name)
			local remote_text = remote_title:getContent()
			local transcluder_text = getTemplateParameterByName(remote_text, 'Inline annotation combinable', 1, aliases) --only the first iac template on each page is transcluded
			if #transcluder_text > 0 then
				for j, parameter in ipairs(transcluder_text[1]) do
					local processed_text = frame:preprocess(parameter)
					table.insert(numbered_args, processed_text)
				end
			end
		end
	end	
	-- search for empty arguments
	local regroup = false
	if direction == 'h' then
		-- regroup only in a horizontal context
		for i,line in ipairs(numbered_args) do
			if (numbered_args[i] == '') then
				regroup = true
				break
			end
		end
	end

	-- color
	local color = args.color or ''
	-- classes
	local class = args.class or ''

	-- container
	local annotation_box = mw.html.create( 'span' )
	annotation_box:attr( 'class', 'wst-iac' )
	if color ~= '' then
		annotation_box:css( 'color', color )
	end
	if class ~= '' then
		class = mw.ustring.gsub(class, '%s', '')
		annotation_box:addClass('wst-iac-s-' .. class )
	end

	-- left delimiter
	local left_delimiter = annotation_box:tag('span')
	left_delimiter:attr('class', 'wst-iac-delimiter')
	left_delimiter:wikitext('〖')

	-- regroup
	local text_arg = {}
	local group_count = 0;
	if regroup then
		local part = {}
		local is_first_break = true
		for i,line in ipairs(numbered_args) do
			if (numbered_args[i] == '' and is_first_break) then
				local row_text = table.concat(part)
				table.insert(text_arg, row_text)
				group_count = group_count + 1
				part = {}
				is_first_break = false
			else
				table.insert(part, numbered_args[i])
			end
		end
		if #part > 0 then
			local row_text = table.concat(part)
			table.insert(text_arg, row_text)
			group_count = group_count + 1
		end
	else
		local has_first_part = false
		for k,line in ipairs(numbered_args) do
			if (numbered_args[k] ~= '') then
				if has_first_part then
					has_first_part = false
					if #text_arg > 0 then
						text_arg[#text_arg] = text_arg[#text_arg] .. numbered_args[k]
					else
						table.insert(text_arg, numbered_args[k])
						group_count = group_count + 1
					end
				else
					table.insert(text_arg, numbered_args[k])
					group_count = group_count + 1
				end
			else
				has_first_part = true
			end
		end
	end
	local line_number = math.floor((group_count + 1)/ 2) 

	-- annotations by row
	for i = 1, line_number do
		local new_line = annotation_box:tag('span')
		new_line:attr( 'class', 'wst-iac-line' )
		local rowA = new_line:tag('span')
		rowA:attr( 'class', 'wst-iac-row' )		
		rowA:wikitext(text_arg[2 * i - 1])
		local rowB = new_line:tag('span')
		rowB:attr( 'class', 'wst-iac-row' )	
		if i ~= line_number or text_arg[2 * i] then
			rowB:wikitext(text_arg[2 * i])
		end
		--<br>between lines
		if i ~= line_number then
			annotation_box:wikitext(new_line_if_vertical)
		end

	end
	

	-- right delimiter
	local right_delimiter = annotation_box:tag('span')
	right_delimiter:attr('class', 'wst-iac-delimiter')
	right_delimiter:wikitext('〗')

	local full_annotation = tostring( annotation_box )
	--error(full_annotation)
	return full_annotation
end

return p