Bước tới nội dung

Mô đun:preparser/core

Từ điển mở Wiktionary
local parent_frame = mw.getCurrentFrame()
local frame_factory = parent_frame:newChild{}

local function getNilParent(self)
	return nil
end

frame_factory.getParent = getNilParent

local function newCallbackParserValue(callback)
	local value = {}
	local cache
	function value:expand()
		if not cache then
			cache = callback()
		end
		return cache
	end
	return value
end

local function getArgument(self, opt)
	local name
	if type(opt) == "table" then
		name = opt.name
	else
		name = opt
	end

	return newCallbackParserValue(
		function ()
			return self.args[name]
		end
		)
end

local function getTitle(self)
	return self.title
end

local function newChild(self, opt)
	if type( opt ) ~= "table" then
		error("frame:newChild: the first parameter must be a table", 2)
	end
	
	local title, args
	if opt.title == nil then
		title = self.title
	else
		title = tostring(opt.title)
	end
	if opt.args == nil then
		args = {}
	elseif type(opt.args) ~= "table" then
		error("frame:newChild: args must be a table", 2)
	end
	
	local parent = self
	local child = frame_factory:newChild{}
	
	child.title = title
	child.args = args
	
	child.getArgument = getArgument
	child.newChild = newChild
	child.getTitle = getTitle
	child.preparse = true
	
	function child:getParent()
		return parent
	end
	
	return child
end

parent_frame.title = parent_frame:getTitle()
parent_frame.getArgument = getArgument
parent_frame.getParent = getNilParent
parent_frame.newChild = newChild
parent_frame.getTitle = getTitle
parent_frame.preparse = true

global_frame = parent_frame:newChild{}
global_frame.langs = {}
global_frame.scripts = {}
local child_frame = global_frame

local function parse()
	local output = {}
	
	local title = mw.title.getCurrentTitle()
	-- Don't preparse pages in the template namespace, because [[Module:templateparser]] can't distinguish {{{arguments}}} from {{templates}} yet.
	if title.namespace == 10 then
		return output
	end
	local content = title:getContent()
	
	local templates = {
		["head"] = {"head", "headword/templates", "head_t", {}},
		["l"] = {"link", "links/templates", "l_term_t", {}},
		["lb"] = {"label", "labels/templates", "show", {}},
		["m"] = {"mention", "links/templates", "l_term_t", {["face"] = "term"}},
		["t"] = {"t", "translations", "show", {}},
		["t+"] = {"t+", "translations", "show", {["interwiki"] = "tpos"}}
	}
	local findTemplates = require("Module:templateparser").findTemplates
	local pe = require("Module:utilities").pattern_escape
	local memo_key = require("Module:preparser").memo_key
	
	local time = os.time()
	if content then
		local function parse_text(text)
			local new_text = text
			for template, args, src, tempstart in findTemplates(text) do
				if os.time() >= time + 4 then
					break
				end
				for i, arg in pairs(args) do
					args[i] = parse_text(arg)
				end
				if templates[template] then
					parent_frame.args = args
					parent_frame.title = "Template:" .. templates[template][1]
					child_frame.args = templates[template][4]
					child_frame.title = "Module:" .. templates[template][2]
					local args_key = memo_key(child_frame, templates[template][3])
					if not output[args_key] then
						local ok, out = pcall(require(child_frame.title)[templates[template][3]], child_frame)
						if ok then
							output[args_key] = out
						end
					end
					if output[args_key] then
						local substring = new_text:sub(tempstart)
						substring = substring:gsub(pe(src), pe(output[args_key]), 1)
						new_text = new_text:sub(1, tempstart - 1) .. substring
					end
				end
			end
			return new_text
		end
		parse_text(content)
	end
	
	return output
end

parent_frame:extensionTag("nowiki", "__PREPARSE START")
local output = parse()
parent_frame:extensionTag("nowiki", "__PREPARSE END")
global_frame = nil
return output