2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

Module:组字

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索
Template-info.svg 模块文档  [创建] [刷新]
local p={}

p.parse=function(frame)
	local parseTable=mw.loadData("Module:组字/ParseTable")
	
	local function buildTree(str, index)
		-- 递归下降
		index=index or 1
		str=str or ""
		if mw.ustring.len(str) < index then return nil, index end
		local chr=mw.ustring.sub(str, index, index)
		local data={}
		data.head=chr
		if parseTable[chr] then
			data.body={}
			local nexti=index+1
			for i=1,parseTable[chr].length do
				data.body[i], nexti=buildTree(str, nexti)
				if not data.body[i] then break end
			end
			return data, nexti
		else
			return data, index+1
		end
	end
	
	local function setSize(tree, x, y, width, height)
		-- 计算尺寸
		if type(tree)~="table" then return end
		tree.x=x
		tree.y=y
		tree.width=width
		tree.height=height
		if not tree.body then return end
		local szt=parseTable[tree.head]
		if not szt then return end
		for i=1,szt.length do
			setSize(tree.body[i], szt.x[i]*width+x, szt.y[i]*height+y, szt.width[i]*width, szt.height[i]*height)
		end
	end
	
	local function plainize(tree)
		local arr={}
		if type(tree)~="table" then return end
		if tree.body then
			for i=1,#(tree.body) do
				local sarr=plainize(tree.body[i])
				for k,v in ipairs(sarr) do
					table.insert(arr, v)
				end
			end
		elseif not parseTable[tree.head] then
			table.insert(arr, {
				text=tree.head,
				width=tree.width,
				height=tree.height,
				left=tree.x,
				top=tree.y,
			})
		end
		return arr
	end
	
	local function make_text(text, unit, gw, gh)
		local ts=mw.html.create("span")
		if type(text)~="table" then return ts end
		ts:css("display", "inline-block")
		ts:css("position", "absolute")
		ts:css("top", tostring(text.top) .. unit)
		ts:css("left", tostring(text.left) .. unit)
		ts:css("width", tostring(gw) .. unit)
		ts:css("height", tostring(gh) .. unit)
		ts:css("transform", "scale(" .. tostring(text.width/gw) .. "," .. tostring(text.height/gh) .. ")" )
		ts:css("transform-origin", "0% 0%")
		ts:addClass("combination-text")
		ts:wikitext(text.text)
		return ts
	end
	
	local function make_frame(texts, width, height, unit)
		if type(texts)~="table" then return end
		local text=mw.html.create("span")
		text:css("display", "inline-block")
		--text:css("overflow", "hidden")
		text:css("position", "relative")
		text:css("width", tostring(width) .. unit)
		text:css("height", tostring(height) .. unit)
		--text:css("top", tostring(height*5/6) .. unit)
		--text:css("left", tostring(width/12) .. unit)
		text:css("font-size", tostring((height+width)/2) .. unit)
		--local place=mw.html.create("span")
		--place:css("display", "inline-block")
		--place:css("position", "absolute")
		--place:css("z-index", "-1")
		--text:node(place)
		for k,v in ipairs(texts) do
			text:node(make_text(v, unit, width, height))
		end
		return text
	end
	
	local function emit_html(tree, unit)
		local arr=plainize(tree)
		return tostring(make_frame(arr, tree.width, tree.height, unit))
	end

	local str=frame.args[1]
	if not str then return end
	local size=tonumber(frame.args[2]) or 24
	local unit=frame.args[3] or "px"
	local chrdata=buildTree(str, 1)
	setSize(chrdata, 0, 0, size, size)
	--do return mw.dumpObject(plainize(chrdata)) end
	return emit_html(chrdata, unit)
end

return p