马提尼是什么酒| 胃绞疼是什么原因| 甘油三酯高吃什么好| 什么叫统招生| 两小无猜什么意思| 三月初九是什么星座| 节育环是什么| 生殖科检查什么| 同比什么意思| 来例假吃什么水果好| 十八大什么时候| bbr是什么牌子| 蝙蝠为什么倒挂着睡觉| 眼袋浮肿什么原因| 激素六项都是查什么| 上海话册那是什么意思| 水怡是什么| 连奕名为什么娶杨若兮| 拉不出大便吃什么药| khaki是什么颜色| 喝蛋白粉有什么好处| 印堂跳动是什么预兆| 水什么| 验孕棒一深一浅是什么意思| 宫内孕和宫外孕有什么区别| 论文检索号是什么| 小猫能吃什么水果| 开火车什么意思| 入木三分是什么生肖| 脾是什么| 子宫内膜什么时候脱落| 蛋白粉什么时候吃最好| 手指甲上有竖纹是什么原因| 假牙什么材质的最好| 鲁迅为什么弃医从文| 惟妙惟肖是什么意思| nf是什么意思| 远香近臭什么意思| 布朗尼是什么| mw是什么单位| 康复治疗学是做什么的| 失重感是什么感觉| 甲亢平时要注意什么| 什么药治便秘最好最快| 降结肠疼是什么原因| 咖啡和什么不能一起吃| 娘娘命是什么样的命| 鸡同鸭讲是什么意思| 梦见抓鱼是什么意思| mcm中文叫什么牌子| 烟雾病是什么原因引起的| 干将是什么意思| 奉子成婚是什么意思| 什么是指标到校| 三位一体是什么生肖| 农村入党需要什么条件| 小猫的尾巴有什么用处| 身体上有小红点是什么病| 养鱼为什么养单不养双| 1938年属什么生肖属相| 三周年祭日有什么讲究| 奥特莱斯是什么店| fe是什么意思| 毓婷和金毓婷有什么区别| 益禾堂什么好喝| 梦到死去的亲人是什么意思| 什么的晚霞| 舌面有裂纹是什么原因| 白带长什么样| 为难的难是什么意思| coat是什么意思中文| 利口酒是什么酒| 为什么尽量抽混合型烟| 和珅是什么官| 白毫银针属于什么茶| 乳酸菌和益生菌有什么区别| 幻灭是什么意思| aq是什么标准| 慢性结膜炎用什么眼药水| 不丹为什么不和中国建交| 夏枯草有什么功效| 蝎子吃什么东西| 扁平疣用什么治疗| 头发白是什么原因引起的| 补牙用什么材料最好| 政五行属什么| 磨砂膏有什么作用| 血稠吃什么食物好得快| 凤梨是什么| 睾丸皮痒用什么药膏| 手指起倒刺是什么原因| 心肌是什么意思| 一什么景象| 喝枸杞水有什么好处| 反复发烧是什么原因引起的| 酉时右眼跳是什么预兆| 为什么不能指彩虹| 李连杰得了什么病| 脸部肌肉跳动是什么原因| 红色血痣是什么原因| 生理曲度存在是什么意思| 文化大革命是什么时候开始的| 手淫过度会导致什么| 全脂乳粉是什么| 腻了是什么意思| mra是什么意思| 怀孕了吃什么药能流掉| 喝葡萄糖有什么功效与作用| 威士忌是什么酿造的| 什么是bp| 离线缓存是什么意思| 喝酒前吃什么| 去非洲要打什么疫苗| 什么样的吸尘器比较好| a02是什么牌子| 八个月宝宝可以吃什么水果| 7月15是什么节| 舒筋健腰丸主治什么| 突然和忽然有什么区别| 河水像什么| xy什么意思| 胰岛素是什么器官分泌的| 女人小便出血是什么原因| 印度为什么那么热| 燕窝什么时候吃好| 香油是什么油| 热疹用什么药膏最好| 7月18日什么星座| 肝左叶囊肿是什么意思| 光阴荏苒是什么意思| 阴虚火旺吃什么中成药| 今日什么冲什么生肖| 土豆不能和什么一起吃| 木字旁与什么有关| 生理期没来是什么原因| 杨利伟什么军衔| 剑桥英语和新概念英语有什么区别| 吃什么治便秘最有效| 雍正为什么不杀十阿哥| 感统训练是什么| 春回大地是什么生肖| 胃胀腹胀吃什么药| 被隐翅虫咬了用什么药| 特别怕热爱出汗是什么原因| 毛是什么意思| 三书六礼指的是什么| 尿酸高什么不能吃| 什么米好吃又香又软| 肾虚吃什么补肾| 及什么意思| 7月10号是什么星座| 胃结石有什么症状表现| 戾气是什么| 什么日| 属兔的婚配什么属相好| 谷氨酰转移酶高是什么病| 肾虚去医院挂什么科| 美人坯子是什么意思| 尿道炎看什么科室好| 佳木斯二院全名叫什么| 甲状腺球蛋白高是什么原因| 足月是什么意思| a216是什么材质| 什么情况会导致月经推迟不来| 痰多是什么问题| 阿玛尼手表算什么档次| 无犯罪记录证明需要什么材料| 什么是扬州瘦马| 手上的线分别代表什么图解| bace是什么意思| 抬举是什么意思| 偏头疼吃什么药| 头晕可以吃什么药| 乌梅是什么水果做的| 乙肝15阳性是什么意思| nba什么时候开始| 肤专家软膏主要治什么| 肌酐测定是查什么| 无畏无惧是什么意思| 右手臂酸痛是什么前兆| 紧急避孕药有什么副作用| 胆固醇高吃什么最好| 膝盖发软无力是什么原因| 乳房头疼是什么原因| 师参谋长是什么军衔| 牙龈萎缩吃什么维生素| 吃鱼生后吃什么打虫药| eoa是什么意思| 蛋白质有什么作用| 狗嚎叫有什么预兆| 珠海有什么好玩的| 上梁不正下梁歪是什么意思| 干咳吃什么药效果好| 十一月十九是什么星座| 狗狗肠胃炎吃什么药| 什么油适合炒菜| 腺样体肥大挂什么科| 江米是什么米| 这个人就是娘是什么歌| 大红袍属于什么档次| 月经突然提前一周是什么原因| 男朋友有什么用| 4月2号是什么星座| 哀大莫过于心死是什么意思| 冬瓜有什么功效和作用| 生完孩子可以吃什么水果| 芫荽是什么| 四川代表什么生肖| 口腔疱疹吃什么药| 为什么转氨酶会偏高| 肺炎吃什么药有效| 胎膜是什么| 尿酸低是什么原因| 社保跟医保有什么区别| 牙齿发黄是什么原因| 外阴瘙痒用什么药膏好| 卵泡排出来是什么样的| 獭读什么| 胡萝卜不能和什么一起吃| 乳腺癌长在什么位置| 上火耳鸣吃什么药最好| 酸奶用什么菌发酵| 枕头什么牌子好| 考编制需要什么条件| 无情无义什么意思| 田童念什么| 悲欢离合是什么意思| 叶酸片是治什么的| 肛瘘是什么| 什么植物最老实| 咳嗽绿痰是什么原因| 提手旁有什么字| 什么补血最快| 脸上长红色的痘痘是什么原因| 永垂不朽是什么意思| 柏字五行属什么| 吃什么食物最补血| 黄色搭配什么颜色| 钩针ch是什么意思| 独善其身是什么意思啊| 坐骨神经痛是什么症状| 为什么脸突然肿了| 脾胃虚弱能吃什么水果| 后腰出汗多是什么原因| 急性结膜炎用什么眼药水| 冰心的原名是什么| 年上年下是什么意思| 非洲有什么动物| 氯偏低是什么原因| hvp是什么| 全麻后需要注意什么| 黄山四绝是什么| 七月十一是什么星座| 什么是紫癜| 胃轻度肠化是什么意思| 出痧是什么意思| 什么是热量| 减肥晚餐吃什么好| 苦尽甘来是什么意思| 交通运输是干什么的| 为什么贫血| 闲暇的意思是什么| 爆单什么意思| 大闸蟹什么时候吃| 百度Jump to content

陈水扁不甩中监警告罗智强吃准蔡英文不敢对他怎样

Permanently protected module
From Wikipedia, the free encyclopedia

require("strict")

--Helper functions
local function startswith(text, subtext)
	return string.sub(text, 1, #subtext) == subtext
end
local function endswith(text, subtext)
	return string.sub(text, -#subtext, -1) == subtext
end
local function allcases(s)
	return s:gsub("%a", function(c) 
		return "["..c:upper()..c:lower().."]"
	end)
end
local trimcache = {}
local whitespace = {[" "]=1, ["\n"]=1, ["\t"]=1, ["\r"]=1}
local function cheaptrim(str) --mw.text.trim is surprisingly expensive, so here's an alternative approach
	local quick = trimcache[str]
	if quick then
		return quick
	else
		-- local out = string.gsub(str, "^%s*(.-)%s*$", "%1")
		local lowEnd
		local strlen = #str
		for i = 1,strlen do
			if not whitespace[string.sub(str, i, i)] then
				lowEnd = i
				break
			end
		end
		if not lowEnd then
			trimcache[str] = ""
			return ""
		end
		for i = strlen,1,-1 do
			if not whitespace[string.sub(str, i, i)] then
				local out = string.sub(str, lowEnd, i)
				trimcache[str] = out
				return out
			end
		end
	end
end

--[=[ Implementation notes
---- NORMAL HTML TAGS ----
Tags are very strict on how they want to start, but loose on how they end.
The start must strictly follow <[tAgNaMe](%s|>) with no room for whitespace in
the tag's name, but may then flow as they want afterwards, making
<div\nclass\n=\n"\nerror\n"\n> valid

There's no sense of escaping < or >
E.g.
 <div class="error\>"> will end at \> despite it being inside a quote
 <div class="<span class="error">error</span>"> will not process the larger div

If a tag has no end, it will consume all text instead of not processing

---- NOPROCESSING TAGS (nowiki, pre, syntaxhighlight, source, etc.) ----
(In most comments, <source> will not be mentioned. This is because it is the
deprecated version of <syntaxhighlight>)

No-Processing tags have some interesting differences to the above rules.
For example, their syntax is a lot stricter. While an opening tag appears to
follow the same set of rules, A closing tag can't have any sort of extra
formatting period. While </div a/a> is valid, </nowiki a/a> isn't - only
newlines and spaces/tabs are allowed in closing tags.
Note that, even though <pre> tags cause a visual change when the ending tag has
extra formatting, it won't cause the no-processing effects. For some reason, the
format must be strict for that to apply.

Both the content inside the tag pair and the content inside each side of the
pair is not processed. E.g. <nowiki |}}>|}}</nowiki> would have both of the |}}
escaped in practice.

When something in the code is referenced to as a "Nowiki Tag", it means a tag
which causes wiki text to not be processed, which includes <nowiki>, <pre>,
and <syntaxhighlight>

Since we only care about these tags, we can ignore the idea of an intercepting
tag preventing processing, and just go straight for the first ending we can find
If there is no ending to find, the tag will NOT consume the rest of the text in
terms of processing behaviour (though <pre> will appear to have an effect).
Even if there is no end of the tag, the content inside the opening half will
still be unprocessed, meaning {{X20|<nowiki }}>}} wouldn't end at the first }}
despite there being no ending to the tag.

Note that there are some tags, like <math>, which also function like <nowiki>
which are included in this aswell. Some other tags, like <ref>, have far too
unpredictable behaviour to be handled currently (they'd have to be split and
processed as something seperate - its complicated, but maybe not impossible.)
I suspect that every tag listed in [[Special:Version]] may behave somewhat like
this, but that's far too many cases worth checking for rarely used tags that may
not even have a good reason to contain {{ or }} anyways, so we leave them alone.

---- HTML COMMENTS AND INCLUDEONLY ----
HTML Comments are about as basic as it could get for this
Start at <!--, end at -->, no extra conditions. Simple enough
If a comment has no end, it will eat all text instead of not being processed

includeonly tags function mostly like a regular nowiki tag, with the exception
that the tag will actually consume all future text if not given an ending as
opposed to simply giving up and not changing anything. Due to complications and
the fact that this is far less likely to be present on a page, aswell as being
something that may not want to be escaped, includeonly tags are ignored during
our processing
--]=]
local validtags = {nowiki=1, pre=1, syntaxhighlight=1, source=1, math=1}
--This function expects the string to start with the tag
local function TestForNowikiTag(text, scanPosition)
	local tagName = (string.match(text, "^<([^\n />]+)", scanPosition) or ""):lower()
	if not validtags[tagName] then
		return nil
	end
	local nextOpener = string.find(text, "<", scanPosition+1) or -1
	local nextCloser = string.find(text, ">", scanPosition+1) or -1
	if nextCloser > -1 and (nextOpener == -1 or nextCloser < nextOpener) then
		local startingTag = string.sub(text, scanPosition, nextCloser)
		--We have our starting tag (E.g. '<pre style="color:red">')
		--Now find our ending...
		if endswith(startingTag, "/>") then --self-closing tag (we are our own ending)
			return {
				Tag = tagName,
				Start = startingTag,
				Content = "", End = "",
				Length = #startingTag
			}

		else
			local endingTagStart, endingTagEnd = string.find(text, "</"..allcases(tagName).."[ \t\n]*>", scanPosition)
			if endingTagStart then --Regular tag formation
				local endingTag = string.sub(text, endingTagStart, endingTagEnd)
				local tagContent = string.sub(text, nextCloser+1, endingTagStart-1)
				return {
					Tag = tagName,
					Start = startingTag,
					Content = tagContent,
					End = endingTag,
					Length = #startingTag + #tagContent + #endingTag
				}

			else --Content inside still needs escaping (also linter error!)
				return {
					Tag = tagName,
					Start = startingTag,
					Content = "", End = "",
					Length = #startingTag
				}
			end
		end
	end
	return nil
end
local function TestForComment(text, scanPosition) --Like TestForNowikiTag but for <!-- -->
	if string.match(text, "^<!%-%-", scanPosition) then
		local commentEnd = string.find(text, "-->", scanPosition+4, true)
		if commentEnd then
			return {
				Start = "<!--", End = "-->",
				Content = string.sub(text, scanPosition+4, commentEnd-1),
				Length = commentEnd-scanPosition+3
			}
		else --Consumes all text if not given an ending
			return {
				Start = "<!--", End = "",
				Content = string.sub(text, scanPosition+4),
				Length = #text-scanPosition+1
			}
		end
	end
	return nil
end

--[[ Implementation notes
The goal of this function is to escape all text that wouldn't be parsed if it
was preprocessed (see above implementation notes).

Using keepComments will keep all HTML comments instead of removing them. They
will still be escaped regardless to avoid processing errors
--]]
local function PrepareText(text, keepComments)
	local newtext = {}
	local scanPosition = 1
	while true do
		local NextCheck = string.find(text, "<[NnSsPpMm!]", scanPosition) --Advance to the next potential tag we care about
		if not NextCheck then --Done
			newtext[#newtext+1] =  string.sub(text,scanPosition)
			break
		end
		newtext[#newtext+1] = string.sub(text,scanPosition,NextCheck-1)
		scanPosition = NextCheck
		local Comment = TestForComment(text, scanPosition)
		if Comment then
			if keepComments then
				newtext[#newtext+1] = Comment.Start .. mw.text.nowiki(Comment.Content) .. Comment.End
			end
			scanPosition = scanPosition + Comment.Length
		else
			local Tag = TestForNowikiTag(text, scanPosition)
			if Tag then
				local newTagStart = "<" .. mw.text.nowiki(string.sub(Tag.Start,2,-2)) .. ">"
				local newTagEnd = 
					Tag.End == "" and "" or --Respect no tag ending
					"</" .. mw.text.nowiki(string.sub(Tag.End,3,-2)) .. ">"
				local newContent = mw.text.nowiki(Tag.Content)
				newtext[#newtext+1] = newTagStart .. newContent .. newTagEnd
				scanPosition = scanPosition + Tag.Length
			else --Nothing special, move on...
				newtext[#newtext+1] = string.sub(text, scanPosition, scanPosition)
				scanPosition = scanPosition + 1
			end
		end
	end
	return table.concat(newtext, "")
end

--[=[ Implementation notes
This function is an alternative to Transcluder's getParameters which considers
the potential for a singular { or } or other odd syntax that %b doesn't like to
be in a parameter's value.

When handling the difference between {{ and {{{, mediawiki will attempt to match
as many sequences of {{{ as possible before matching a {{
E.g.
 {{{{A}}}} -> { {{{A}}} }
 {{{{{{{{Text|A}}}}}}}} -> {{ {{{ {{{Text|A}}} }}} }}
If there aren't enough triple braces on both sides, the parser will compromise
for a template interpretation.
E.g.
 {{{{A}} }} -> {{ {{ A }} }}

While there are technically concerns about things such as wikilinks breaking
template processing (E.g. {{[[}}]]}} doesn't stop at the first }}), it shouldn't
be our job to process inputs perfectly when the input has garbage ({ / } isn't
legal in titles anyways, so if something's unmatched in a wikilink, it's
guaranteed GIGO)

Setting dontEscape will prevent running the input text through EET. Avoid
setting this to true if you don't have to set it.

Returned values:
A table of all templates. Template data goes as follows:
 Text: The raw text of the template
 Name: The name of the template
 Args: A list of arguments
 Children: A list of immediate template children
--]=]
--Helper functions
local function boundlen(pair)
	return pair.End-pair.Start+1
end

--Main function
local function ParseTemplates(InputText, dontEscape)
	--Setup
	if not dontEscape then
		InputText = PrepareText(InputText)
	end
	local function finalise(text)
		if not dontEscape then
			return mw.text.decode(text)
		else
			return text
		end
	end
	local function CreateContainerObj(Container)
		Container.Text = {}
		Container.Args = {}
		Container.ArgOrder = {}
		Container.Children = {}
		-- Container.Name = nil
		-- Container.Value = nil
		-- Container.Key = nil
		Container.BeyondStart = false
		Container.LastIndex = 1
		Container.finalise = finalise
		function Container:HandleArgInput(character, internalcall)
			if not internalcall then
				self.Text[#self.Text+1] = character
			end
			if character == "=" then
				if self.Key then
					self.Value[#self.Value+1] = character
				else
					self.Key = cheaptrim(self.Value and table.concat(self.Value, "") or "")
					self.Value = {}
				end
			else --"|" or "}"
				if not self.Name then
					self.Name = cheaptrim(self.Value and table.concat(self.Value, "") or "")
					self.Value = nil
				else
					self.Value = self.finalise(self.Value and table.concat(self.Value, "") or "")
					if self.Key then
						self.Key = self.finalise(self.Key)
						self.Args[self.Key] = cheaptrim(self.Value)
						self.ArgOrder[#self.ArgOrder+1] = self.Key
					else
						local Key = tostring(self.LastIndex)
						self.Args[Key] = self.Value
						self.ArgOrder[#self.ArgOrder+1] = Key
						self.LastIndex = self.LastIndex + 1
					end
					self.Key = nil
					self.Value = nil
				end
			end
		end
		function Container:AppendText(text, ftext)
			self.Text[#self.Text+1] = (ftext or text)
			if not self.Value then
				self.Value = {}
			end
			self.BeyondStart = self.BeyondStart or (#table.concat(self.Text, "") > 2)
			if self.BeyondStart then
				self.Value[#self.Value+1] = text
			end
		end
		function Container:Clean(IsTemplate)
			self.Text = table.concat(self.Text, "")
			if self.Value and IsTemplate then
				self.Value = {string.sub(table.concat(self.Value, ""), 1, -3)} --Trim ending }}
				self:HandleArgInput("|", true) --Simulate ending
			end
			self.Value = nil
			self.Key = nil
			self.BeyondStart = nil
			self.LastIndex = nil
			self.finalise = nil
			self.HandleArgInput = nil
			self.AppendText = nil
			self.Clean = nil
		end
		return Container
	end
	
	--Step 1: Find and escape the content of all wikilinks on the page, which are stronger than templates (see implementation notes)
	local scannerPosition = 1
	local wikilinks = {}
	local openWikilinks = {}
	while true do
		local Position, _, Character = string.find(InputText, "([%[%]])%1", scannerPosition)
		if not Position then --Done
			break
		end

		scannerPosition = Position+2 --+2 to pass the [[ / ]]
		if Character == "[" then --Add a [[ to the pending wikilink queue
			openWikilinks[#openWikilinks+1] = Position
		else --Pair up the ]] to any available [[
			if #openWikilinks >= 1 then
				local start = table.remove(openWikilinks) --Pop the latest [[
				wikilinks[start] = {Start=start, End=Position+1, Type="Wikilink"} --Note the pair
			end
		end
	end
	
	--Step 2: Find the bounds of every valid template and variable ({{ and {{{)
	local scannerPosition = 1
	local templates = {}
	local variables = {}
	local openBrackets = {}
	while true do
		local Start, _, Character = string.find(InputText, "([{}])%1", scannerPosition)
		if not Start then --Done (both 9e9)
			break
		end
		local _, End = string.find(InputText, "^"..Character.."+", Start)

		scannerPosition = Start --Get to the {{ / }} set
		if Character == "{" then --Add the {{+ set to the queue
			openBrackets[#openBrackets+1] = {Start=Start, End=End}

		else --Pair up the }} to any available {{, accounting for {{{ / }}}
			local BracketCount = End-Start+1
			while BracketCount >= 2 and #openBrackets >= 1 do
				local OpenSet = table.remove(openBrackets)
				if boundlen(OpenSet) >= 3 and BracketCount >= 3 then --We have a {{{variable}}} (both sides have 3 spare)
					variables[OpenSet.End-2] = {Start=OpenSet.End-2, End=scannerPosition+2, Type="Variable"} --Done like this to ensure chronological order
					BracketCount = BracketCount - 3
					OpenSet.End = OpenSet.End - 3
					scannerPosition = scannerPosition + 3

				else --We have a {{template}} (both sides have 2 spare, but at least one side doesn't have 3 spare)
					templates[OpenSet.End-1] = {Start=OpenSet.End-1, End=scannerPosition+1, Type="Template"} --Done like this to ensure chronological order
					BracketCount = BracketCount - 2
					OpenSet.End = OpenSet.End - 2
					scannerPosition = scannerPosition + 2
				end

				if boundlen(OpenSet) >= 2 then --Still has enough data left, leave it in
					openBrackets[#openBrackets+1] = OpenSet
				end
			end
		end
		scannerPosition = End --Now move past the bracket set
	end
	
	--Step 3: Re-trace every object using their known bounds, collecting our parameters with (slight) ease
	local scannerPosition = 1
	local activeObjects = {}
	local finalObjects = {}
	while true do
		local LatestObject = activeObjects[#activeObjects] --Commonly needed object
		local NNC, _, Character --NNC = NextNotableCharacter
		if LatestObject then
			NNC, _, Character = string.find(InputText, "([{}%[%]|=])", scannerPosition)
		else
			NNC, _, Character = string.find(InputText, "([{}])", scannerPosition) --We are only after templates right now
		end
		if not NNC then
			break
		end
		if NNC > scannerPosition and LatestObject then
			local scannedContent = string.sub(InputText, scannerPosition, NNC-1)
			LatestObject:AppendText(scannedContent, finalise(scannedContent))
		end

		scannerPosition = NNC+1
		if Character == "{" or Character == "[" then
			local Container = templates[NNC] or variables[NNC] or wikilinks[NNC]
			if Container then
				CreateContainerObj(Container)
				if Container.Type == "Template" then
					Container:AppendText("{{")
					scannerPosition = NNC+2
				elseif Container.Type == "Variable" then
					Container:AppendText("{{{")
					scannerPosition = NNC+3
				else --Wikilink
					Container:AppendText("[[")
					scannerPosition = NNC+2
				end
				if LatestObject and Container.Type == "Template" then --Only templates count as children
					LatestObject.Children[#LatestObject.Children+1] = Container
				end
				activeObjects[#activeObjects+1] = Container
			elseif LatestObject then
				LatestObject:AppendText(Character)
			end

		elseif Character == "}" or Character == "]" then
			if LatestObject then
				LatestObject:AppendText(Character)
				if LatestObject.End == NNC then
					if LatestObject.Type == "Template" then
						LatestObject:Clean(true)
						finalObjects[#finalObjects+1] = LatestObject
					else
						LatestObject:Clean(false)
					end
					activeObjects[#activeObjects] = nil
					local NewLatest = activeObjects[#activeObjects]
					if NewLatest then
						NewLatest:AppendText(LatestObject.Text) --Append to new latest
					end
				end
			end

		else --| or =
			if LatestObject then
				LatestObject:HandleArgInput(Character)
			end
		end
	end
	
	--Step 4: Fix the order
	local FixedOrder = {}
	local SortableReference = {}
	for _,Object in next,finalObjects do
		SortableReference[#SortableReference+1] = Object.Start
	end
	table.sort(SortableReference)
	for i = 1,#SortableReference do
		local start = SortableReference[i]
		for n,Object in next,finalObjects do
			if Object.Start == start then
				finalObjects[n] = nil
				Object.Start = nil --Final cleanup
				Object.End = nil
				Object.Type = nil
				FixedOrder[#FixedOrder+1] = Object
				break
			end
		end
	end
	
	--Finished, return
	return FixedOrder
end

local p = {}
--Main entry points
p.PrepareText = PrepareText
p.ParseTemplates = ParseTemplates
--Extra entry points, not really required
p.TestForNowikiTag = TestForNowikiTag
p.TestForComment = TestForComment

return p

--[==[ console tests

local s = [=[Hey!{{Text|<nowiki | ||>
Hey! }}
A</nowiki>|<!--AAAAA|AAA-->Should see|Shouldn't see}}]=]
local out = p.PrepareText(s)
mw.logObject(out)

local s = [=[B<!--
Hey!
-->A]=]
local out = p.TestForComment(s, 2)
mw.logObject(out); mw.log(string.sub(s, 2, out.Length))

local a = p.ParseTemplates([=[
{{User:Aidan9382/templates/dummy
|A|B|C {{{A|B}}} { } } {
|<nowiki>D</nowiki>
|<pre>E
|F</pre>
|G|=|a=|A  =  [[{{PAGENAME}}|A=B]]{{Text|1==<nowiki>}}</nowiki>}}|A B=Success}}
]=])
mw.logObject(a)

]==]
空明什么意思 稀字五行属什么 美育是什么意思 心悸吃什么药效果好 做梦梦见狗咬我什么意思啊
胃息肉吃什么好 人间正道是沧桑是什么意思 马镫什么时候发明的 梦见跟别人打架是什么意思 保花保果用什么药最好
夏的五行属什么 74年属什么生肖 半边脸疼是什么原因 胎停是什么原因引起的 两肺散在小结节是什么意思
马加大是什么字 肺气肿吃什么食物 芒果是什么季节的水果 接龙是什么意思 ivf是什么意思
左脸颊长痘是什么原因hcv9jop0ns5r.cn 早泄吃什么好hcv9jop0ns4r.cn 感冒吃什么药好hcv7jop6ns9r.cn 后脑勺出汗是什么原因wuhaiwuya.com 晨咳是什么原因引起的hcv8jop4ns8r.cn
什么样的牙齿需要矫正hcv9jop4ns4r.cn 菊花什么时候种植hcv9jop1ns5r.cn 一度房室传导阻滞是什么意思hcv9jop7ns3r.cn 太上皇是什么意思hcv8jop6ns5r.cn 阳痿是什么症状hcv8jop0ns7r.cn
被蜱虫咬了有什么症状hcv9jop4ns9r.cn 胸胀痛什么原因hcv8jop8ns0r.cn 八月17号是什么星座的hcv8jop9ns6r.cn 怀孕吃火龙果对胎儿有什么好hcv7jop4ns8r.cn 背债是什么意思hcv8jop5ns1r.cn
长脚气是什么原因引起的hcv9jop3ns2r.cn 化学性肝损伤是什么意思hcv9jop0ns7r.cn 舌吻什么感觉hcv8jop2ns9r.cn 神奇是什么意思hcv7jop4ns5r.cn 梦见好多水果是什么预兆hcv9jop6ns6r.cn
百度