Для документации этого модуля может быть создана страница Модуль:Get page content/doc

local p = {}

local monthNames = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'}

if not getArgs then
	getArgs = require('Модуль:Arguments').getArgs
end

local pageTitle, pageTitleText, sectionHeading, _frame

--[=[
Helper function that escapes all pattern characters so that they will be treated
as plain text. Copied from [[:en:Module:String]].
]=]
local function escapePattern(pattern_str)
	return mw.ustring.gsub(pattern_str, '([%(%)%.%%%+%-%*%?%[%^%$%]])', '%%%1')
end

-- Native function can return "Ошибка Lua: PCRE backtrack limit reached while matching pattern '^[	� ]*(.-)[	� ]*$'."
-- in case of very long sections.
local function trim(str)
	str = mw.ustring.gsub(str, '^[	� ]*', '')
	str = mw.ustring.gsub(str, '[	� ]*$', '')
	return str
end

local function cleanSectionHeading(heading)
	-- The following patterns reproduce [[Участник:Jack who built the house/transferHeadingToSummary.js]]
	heading = mw.ustring.gsub(heading, '%[%[:?[^|%]]*|([^%]]*)%]%]', '%1')
	heading = mw.ustring.gsub(heading, '%[%[:?([^%]]*)%]%]', '%1')
	heading = mw.ustring.gsub(heading, "'''(.-)'''", '%1')
	heading = mw.ustring.gsub(heading, "''(.-)''", '%1')
	heading = mw.ustring.gsub(heading, '</?%w+ ?/?>', '')
	heading = mw.ustring.gsub(heading, '<%w+ [%w ]-=[^<>]->', '')
	heading = mw.ustring.gsub(heading, '  +', ' ')
	heading = mw.text.trim(heading)
	return heading
end

local function sectionHeadingToLink(sectionHeading)
	local sectionHeadingLink = sectionHeading
	-- The following reproduces processURI function of [[Участник:Jack who built the house/copyWikilinks.js]]
	--[[sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, '<', '%%3C')
	sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, '>', '%%3E')
	sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, '%[', '%%5B')
	sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, '%]', '%%5D')
	sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, '{', '%%7B')
	sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, '|', '%%7C')
	sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, '}', '%%7D')
	sectionHeadingLink = mw.ustring.gsub(sectionHeadingLink, ' ', '.C2.A0')]]
	return '#' .. sectionHeadingLink
end

local function expandTemplate(tname, targs)
	local success, result = pcall(
		_frame.expandTemplate,
		_frame,
		{title = tname, args = targs}
	)
	return success and result or ''
end

local function getLastMatchWith2Captures(s, pattern)
	local iterator = mw.ustring.gmatch(s, pattern)
	local lastCapture1, lastCapture2
	for capture1, capture2 in iterator do
		lastCapture1 = capture1
		lastCapture2 = capture2
	end
	return lastCapture1, lastCapture2
end

local function isEmptyClosure(closureContent)
	if closureContent then
		closureContent = closureContent
			:gsub('<includeonly>.-</includeonly>', '')
			:gsub('<!%-%-.-%-%->', '')
		closureContent = mw.text.trim(closureContent)
		if #closureContent < 10 then
			return true
		else
			return false
		end
	else
		return true
	end
end

local function killHeadingMarkers(content)
	content = mw.ustring.gsub(
		content,
		string.char(127) .. '\'"`UNIQ%-%-h%-%d+%-%-QINU`"\'' .. string.char(127),
		''
	)
	return content
end

local function parsePage(args, talkpageMode)
	if not _frame then
		_frame = mw.getCurrentFrame()
	end
	
	local yesno = require('Module:Yesno')
	
	local afdMode = yesno(args['режим КУ'], false)
	local pageListMode = yesno(args['режим списков страниц'], false)
	local standardMode
	if not talkpageMode and not afdMode and not pageListMode then
		standardMode = true
	end
	
	local returnAsData = not standardMode or yesno(args['как данные'], false)
	
	local returnAsData_onlyStats
	if returnAsData and args['только статистика'] then
		returnAsData_onlyStats = yesno(args['только статистика'], false)
	else
		returnAsData_onlyStats = false
	end
	
	local subsectionHeading, resultMode
	if standardMode then
		resultMode = yesno(args['итог'], false)
		subsectionHeading = args['подраздел']
	end
	
	local standardHeading = not standardMode or yesno(args['стандартный заголовок'], false)
	local shortHeadings = talkpageMode and yesno(args['короткие заголовки'], false)
	
	local collapsed = not returnAsData and yesno(args['свернуть'], false)
	local showFrame = collapsed or (not returnAsData and (yesno(args['обрамление']) or (yesno(args['из шаблона'], false) and (args['обрамление'] == nil))))
	
	local sectionHeadingLink
	if showFrame or (standardHeading or returnAsData_onlyStats) and not talkpageMode then
		sectionHeadingLink = sectionHeadingToLink(sectionHeading)
	end
	
	local renameHeading = args['переименовать раздел']
	
	local withoutHeading, standardSectionHeading
	if standardHeading then
		withoutHeading = true
		
		if afdMode then
			standardSectionHeading = sectionHeading .. ' <span style="font-size:80%;">← [[' .. pageTitleText .. sectionHeadingLink .. '|' .. pageTitleText .. ']]</span>'
		elseif not talkpageMode then
			standardSectionHeading = '[[' .. pageTitleText .. sectionHeadingLink .. '|' .. (
					subsectionHeading
					and subsectionHeading .. ' (' .. (renameHeading or sectionHeading) .. ')'
					or (sectionHeading == 'top' and '<i>Преамбула</i>' or renameHeading or sectionHeading)
				) .. ']] <span style="font-size:80%;">← ' .. pageTitleText .. '</span>'
		end
	elseif not talkpageMode and args['заголовок'] then
		withoutHeading = not yesno(args['заголовок'], false)
	else
		withoutHeading = false
	end
	
	local level = tonumber(args['уровень']) or 2  -- базовый уровень при вставке разделов
	local additionalEqualSigns = ''
	if level > 2 then
		for i = 3, level do
			additionalEqualSigns = additionalEqualSigns .. '='
		end
	end
	
	local showInTOC
	if args['показывать в содержании'] then
		showInTOC = yesno(args['показывать в содержании'], true)
	elseif collapsed then
		showInTOC = false
	else
		showInTOC = true
	end
	
	local showEditLink
	if args['править'] then
		showEditLink = yesno(args['править'], true)
	else
		showEditLink = true
	end
	
	local showStatsLine
	if standardHeading and args['строка статистики'] then
		showStatsLine = yesno(args['строка статистики'], false)
	else
		showStatsLine = false
	end
	
	--local additionalLabels = afdMode or args['дополнительные ярлыки']
	
	local sectionContent
	local data = {}
	local allData = talkpageMode and {}
	if pageTitle.exists then
		local fullContent = (talkpageMode and '' or '\n== top ==') .. '\n' .. pageTitle:getContent() .. '\n= technical heading =\n'
		fullContent = mw.ustring.gsub('\n' .. fullContent, '(\n(=+)[^\n]-%2[ \t\f\v]*)<!%-%-.-%-%->', '%1')
		
		local iterator
		local rootSectionID
		if talkpageMode then -- соответствие заголовков второго уровня заголовкам вообще для talkpageMode
			rootSectionID = {}
			iterator = mw.ustring.gmatch(fullContent, '\n(=+)[^\n]-%1')
			local i, j = 0, 0
			for equalSigns in iterator do
				i = i + 1
				if equalSigns == '==' then
					j = j + 1
					rootSectionID[j] = i
				end
			end
			
			iterator = mw.ustring.gmatch(fullContent, '\n((==)([^=][^\n]-)==)')
		else
			iterator = mw.ustring.gmatch(fullContent, '\n((=+)([^\n]-)%2)')
		end
		
		local headingNum = 0
		for fullMatch, equalSigns, match in iterator do
			headingNum = headingNum + 1
			data = {}
			match = mw.text.trim(match)
			
			local thisHeading = mw.text.encode(cleanSectionHeading(match), '<>%[%]{|}')
			if thisHeading == sectionHeading or talkpageMode then
				-- получаем содержимое раздела
				local equalSignsPattern = '='
				for i = 2, #equalSigns do
					equalSignsPattern = equalSignsPattern .. '=?'
				end
				
				sectionContent =
					mw.ustring.match(fullContent,
						   (withoutHeading and '' or '(')
						.. escapePattern(fullMatch) .. '[ \t\f\v]*\n+'
						.. (withoutHeading and '(' or '')
						.. '.-)\n' .. equalSignsPattern .. '[^=][^\n]-=+[ \t\f\v]*\n') or '' --will fail at "===" or the like
				sectionContent = sectionContent:gsub('<onlyinclude>.-</onlyinclude>', '')
				sectionContent = sectionContent:gsub('<includeonly>(.-)</includeonly>', '%1')
				
				local subsectionHeadingNum
				if subsectionHeading then -- withoutHeading тут неактуально — standardHeading всегда true
					local beforeContent
					beforeContent, sectionContent = mw.ustring.match(sectionContent .. '\n= technical heading =\n', '(.-)\n' .. equalSigns .. '=[ \t\f\v]*' .. escapePattern(subsectionHeading) .. '[ \t\f\v]*=+[ \t\f\v]*\n+(.-)\n' .. equalSignsPattern .. '[^=][^\n]-=+[ \t\f\v]*\n')
					subsectionHeadingNum = 0
					for match2 in mw.ustring.gmatch('\n' .. beforeContent, '\n=+[^\n]-=+') do
						subsectionHeadingNum = subsectionHeadingNum + 1
					end
					if not sectionContent then
						sectionContent = ''
					end
				end
				
				local closureHeading, resultMode_closureHeadingNum
				if resultMode then
					local beforeContent, newSectionContent, closureContent
					local closureTitles = {'Итог', 'Окончательный итог', 'Автоитог'}
					if withoutHeading and not standardHeading then
						for i = 1, #closureTitles do -- через or несколько match'ей тут нельзя, так как возвращаются несколько значений
							if i == 1 or not newSectionContent then
								beforeContent, closureHeading, newSectionContent = mw.ustring.match(sectionContent .. '\n= technical heading =\n', '(.*)\n' .. equalSigns .. '=[ \t\f\v]*(' .. closureTitles[i] .. '[^\n]-)[ \t\f\v]*=+[ \t\f\v]*\n+(.-)\n' .. equalSignsPattern .. '[^=][^\n]-=+[ \t\f\v]*\n')
							end
						end
					else
						for i = 1, #closureTitles do -- через or несколько match'ей тут нельзя, так как возвращаются несколько значений
							if i == 1 or not newSectionContent then
								beforeContent, newSectionContent, closureHeading, closureContent = mw.ustring.match(sectionContent .. '\n= technical heading =\n', '(.*)\n(' .. equalSigns .. '=[ \t\f\v]*(' .. closureTitles[i] .. '[^\n]-)[ \t\f\v]*=+[ \t\f\v]*\n(.-))\n' .. equalSignsPattern .. '[^=][^\n]-=+[ \t\f\v]*\n')
							end
						end
					end
					if newSectionContent then
						sectionContent = newSectionContent
						newSectionContent = nil
						resultMode_closureHeadingNum = 0
						for match2 in mw.ustring.gmatch('\n' .. beforeContent, '\n=+[^\n]-=+') do
							resultMode_closureHeadingNum = resultMode_closureHeadingNum + 1
						end
						
						-- проверяем, не пустая ли секция итога
						emptyClosure = isEmptyClosure(closureContent or sectionContent)
						if emptyClosure then
							closureHeading = nil
							
							if not returnAsData_onlyStats then
								sectionContent = "''Похоже, что итога пока нет.''"
							end
						end
					else
						if not returnAsData_onlyStats then
							sectionContent = "''Похоже, что итога пока нет.''"
						else
							sectionContent = ''
						end
					end
				end
				
				-- извлекаем данные:
				-- о сообщениях
				if showStatsLine or returnAsData then
					local iterator2 = mw.ustring.gmatch('\n' .. sectionContent, '\n([^\n]+)((%d%d):(%d%d), (%d%d?) (%w+) (%d%d%d%d)) %(UTC%)') --(%d%d? %w+ %d%d%d%d)
					local msgCount, authors = 0, {}
					local lastMsgDate, lastMsgDateString, lastMsgAuthor
					for precedingText, fullDateString, h, i, d, mesyats, y in iterator2 do
						msgCount = msgCount + 1
						h = tonumber(h)
						i = tonumber(i)
						d = tonumber(d)
						y = tonumber(y)
						local m = 1
						for k, v in pairs(monthNames) do
							if v == mesyats then
								m = k
							end
						end
						
						local patterns = {
							'()%[%[[УуUu]:([^|%]#]+)',
							'()%[%[[Уу]частни[кц]а?:([^|%]#]+)',
							'()%[%[[Uu]ser:([^|%]#]+)',
							'()%[%[[Оо][Уу]:([^|%]#]+)',                    
							'()%[%[[Оо]бсуждение[ _]участника:([^|%]#]+)',  
							'()%[%[[Uu]ser[ _]talk:([^|%]#]+)',
							'()%[%[Special:Contributions/([^|%]#]+)', -- анонимы
							'()%[%[[^|]+|([^%]]+)%]%]'                -- случаи типа [[w:en:Wikipedia:TWL/Coordinators|The Wikipedia Library Team]]
						}
						local lastPos = 0
						local author
						for k, v in pairs(patterns) do
							pos, mention = getLastMatchWith2Captures(precedingText, v)
							if pos and pos > lastPos then
								lastPos = pos
								author = mention
							end
							
							-- чтобы «обс» / «вкл» и т. п. из последнего паттерна
							-- не вытесняли ники
							if k == #patterns - 1 and author then break end
						end
						if author then
							author = mw.text.encode(author)
						end
						
						if
							   not lastMsgDate
							or (y > lastMsgDate.y)
							or (y == lastMsgDate.y and m > lastMsgDate.m)
							or (y == lastMsgDate.y and m == lastMsgDate.m and d > lastMsgDate.d)
							or (y == lastMsgDate.y and m == lastMsgDate.m and d == lastMsgDate.d and h > lastMsgDate.h)
							or (y == lastMsgDate.y and m == lastMsgDate.m and d == lastMsgDate.d and h == lastMsgDate.h and i > lastMsgDate.i)
						then
							lastMsgDate = {y = y, m = m, d = d, h = h, i = i}
							lastMsgDateString = fullDateString
							lastMsgAuthor = author or '?'
						end
						
						local found = false
						for k, v in pairs(authors) do
							if v == author then
								found = true
								break
							end
						end
						if not found then
							table.insert(authors, author)
						end
					end
					--local authorsList = table.concat(authors, ', ')
					if msgCount > 0 then
						if returnAsData then
							data.msgCount = msgCount
							--data.lastMsgDate = lastMsgDate
							data.lastMsgDateString = lastMsgDateString
							data.lastMsgDateTimestamp = os.time({year = lastMsgDate.y, month = lastMsgDate.m, day = lastMsgDate.d, hour = lastMsgDate.h, min = lastMsgDate.i})
							data.lastMsgAuthor = lastMsgAuthor
							data.lastMsgAnchor = string.format('%.4d%.2d%.2d%.2d%.2d_%s', lastMsgDate.y, lastMsgDate.m, lastMsgDate.d, lastMsgDate.h, lastMsgDate.i, lastMsgAuthor)
							data.authors = authors
						end
						if showStatsLine then
							sectionContent = '\'\'Последнее сообщение: ' .. lastMsgDateString .. ' от ' .. lastMsgAuthor .. '. Всего ' .. msgCount .. ' {{plural: ' .. msgCount .. '|сообщение|сообщения|сообщений}} от ' .. #authors .. ' {{plural: ' .. #authors .. '|автора|авторов}}.\'\'\n' .. sectionContent
						end
					end
				end
				
				-- ...для ярлыков
				local preclosureHeading, challengedClosureHeading, partialClosureHeading, warningHeading
				if afdMode then
					closureHeading = mw.ustring.match(match, '^<s>.*')
				elseif pageListMode then
					warningHeading =
						   mw.ustring.match(match, '^Предупреждение.*')
						or mw.ustring.match(match, '^Блокировка.*')
						or mw.ustring.match(match, '^Нарушение авторских прав.*')
						or mw.ustring.match(match, '^Нарушение АП.*')
				end
				
				-- экономим ресурсы и совершаем максимум два действия за один обход регуляркой:
				-- извлечение данных для ярлыков и формирование заголовков с корректной ссылкой на правку
				local i = 0
				local emptyClosure
				sectionContent = mw.ustring.gsub('\n' .. sectionContent, '\n((=+)([^\n]-)%2)', function (fullMatch2, equalSigns2, match2)
					i = i + 1
					match2 = mw.text.trim(match2)
					
					if returnAsData and not resultMode and not emptyClosure then
						if not closureHeading and #equalSigns2 == #equalSigns + 1 then
							closureHeading =
								   mw.ustring.match(match2, '^Итог.*')
								or mw.ustring.match(match2, '^Окончательный итог.*')
								or mw.ustring.match(match2, '^Автоитог.*')
								--or mw.ustring.match(match2, '^Автоматический итог.*')
							
							if closureHeading then
								-- проверяем, не пустая ли секция итога
								local closureContent = mw.ustring.match(sectionContent .. '\n= technical heading =\n', '\n===+[ \t\f\v]*Итог[^\n]-[ \t\f\v]*=+[ \t\f\v]*\n+(.-)\n=+[^\n]-=+[ \t\f\v]*\n')
								emptyClosure = isEmptyClosure(closureContent);
								if emptyClosure then
									closureHeading = nil
									challengedClosureHeading = nil
									preclosureHeading = nil
									partialClosureHeading = nil
								end
							end
						end
						if not closureHeading then  -- not closureHeading and additionalLabels
							if afdMode and not partialClosureHeading and #equalSigns2 == #equalSigns + 2 then
								partialClosureHeading =
									   mw.ustring.match(match2, '^Итог.*')
								 	or mw.ustring.match(match2, '^Окончательный итог.*')
								 	or mw.ustring.match(match2, '^Автоитог.*')
									or mw.ustring.match(match2, '^Автоматический итог.*')
							end
							if not challengedClosureHeading and #equalSigns2 == #equalSigns + 1 then
								challengedClosureHeading =
									   mw.ustring.match(match2, '^Оспоренный [иИ]тог.*')
									or mw.ustring.match(match2, '^Опротестованный [иИ]тог.*')
								 --or mw.ustring.match(match2, '^Не [иИ]тог.*')
								if challengedClosureHeading then
									preclosureHeading = nil
									partialClosureHeading = nil
								end
							end
							if not challengedClosureHeading and #equalSigns2 == #equalSigns + 1 then
								preclosureHeading =
									   mw.ustring.match(match2, '^Предварительный итог.*')
									or mw.ustring.match(match2, '^Пред[иы]тог.*')
							end
						end
						if closureHeading and #equalSigns2 == #equalSigns + 1 then
							challengedClosureHeading =
								mw.ustring.match(match2, '^Оспаривание [иИтога]*')
							if challengedClosureHeading then
								closureHeading = nil
							end
						end
					end
					
					local editLink2
					if showEditLink then
						editLink2 = pageTitle:fullUrl('action=edit&section=' ..
							(talkpageMode and rootSectionID[headingNum] + i or headingNum - 1 + i)
						  + (not withoutHeading and -1 or 0)
						  + (resultMode_closureHeadingNum and resultMode_closureHeadingNum or 0)
						  + (subsectionHeadingNum and subsectionHeadingNum or 0)
						) -- «- 1», так как, за исключением talkpageMode, мы вставляем искусственную первую секцию
					end
					return '\n' .. expandTemplate('fake heading', {
						['sub'] = #equalSigns2 + level - 2,
						renameHeading or match2,
						['real heading'] = showInTOC and additionalEqualSigns .. '== ' .. (renameHeading or match2) .. ' ==' .. additionalEqualSigns or '',
						['edit link'] = showEditLink and editLink2 or '',
						['in frame'] = (showFrame and (not withoutHeading or standardHeading) and i == 1 and '1' or '')
					})
				end)
				
				if returnAsData then
					data.closureHeading = closureHeading
					data.preclosureHeading = preclosureHeading
					data.challengedClosureHeading = challengedClosureHeading
					data.partialClosureHeading = partialClosureHeading
					data.warningHeading = warningHeading
				end
				
				local thisHeadingLink = sectionHeadingLink and sectionHeadingLink or sectionHeadingToLink(thisHeading)
				if returnAsData then
					data.sectionHeadingLink = thisHeadingLink
				end
				
				local editLink
				editLink = pageTitle:fullUrl('action=edit&section=' .. (talkpageMode and rootSectionID[headingNum] or headingNum - 1))
				if returnAsData then
					data.sectionEditLink = editLink
				end
				
				-- формируем заголовок
				if not returnAsData_onlyStats and standardHeading then
					if talkpageMode then
						if shortHeadings then
							standardSectionHeading = '[[' .. pageTitleText .. thisHeadingLink .. '|' .. thisHeading .. ']]'
						else
							standardSectionHeading = '[[' .. pageTitleText .. thisHeadingLink .. '|' .. thisHeading .. ']] <span style="font-size:80%;">← ' .. pageTitleText .. '</span>'
						end
					elseif afdMode then
						standardSectionHeading = match .. ' <span style="font-size:80%;">← [[' .. pageTitleText .. thisHeadingLink .. '|' .. pageTitleText .. ']]</span>'
					end
					
					sectionContent = expandTemplate('fake heading', {
						['sub'] = 2 + level - 2,
						renameHeading or standardSectionHeading,
						['real heading'] = showInTOC and additionalEqualSigns .. '== ' .. (renameHeading or standardSectionHeading) .. ' ==' .. additionalEqualSigns or '',
						['edit link'] = showEditLink and editLink or ''
					}) .. '\n' .. sectionContent
				end
				
				sectionContent = trim(sectionContent)
				
				if talkpageMode then
					data.sectionHeading = thisHeading
					if not returnAsData_onlyStats then
						data.sectionContent = sectionContent
					end
				else
					break
				end
			end
			if talkpageMode and data.sectionHeading then
				table.insert(allData, data)
			end
		end
		if not talkpageMode and (returnAsData or not returnAsData_onlyStats) then
			if sectionContent == '' then
				if subsectionHeading then
					local sectionNotExistMessage = 'На странице [[' .. pageTitleText .. ']] в разделе «' .. sectionHeading .. '» не найден подраздел «' .. subsectionHeading .. '». Возможно, тема была заархивирована.'
					if returnAsData then
						data.sectionNotExistMessage = sectionNotExistMessage
					end
					if not returnAsData_onlyStats then
						sectionContent = '== ' .. (renameHeading or standardSectionHeading) .. " ==\n''" .. sectionNotExistMessage .. "''"
					end
				elseif not returnAsData_onlyStats then
					sectionContent = '== ' .. (renameHeading or standardSectionHeading) .. " ==\n''<span class=\"error\">Не удалось получить содержимое раздела «' .. sectionHeading .. '» на странице [[' .. pageTitleText .. ']] (хотя он был найден).</span>''"
				end
			end
			if not sectionContent then
				local sectionNotExistMessage = 'На странице [[' .. pageTitleText .. ']] не найден раздел «' .. sectionHeading .. '».'
				if not (
					   mw.ustring.find(pageTitleText, '^Википедия:К удалению/')
					or mw.ustring.find(pageTitleText, '^Википедия:К восстановлению/')
					or mw.ustring.find(pageTitleText, '^Википедия:К переименованию/')
					or mw.ustring.find(pageTitleText, '^Википедия:К объединению/')
					or mw.ustring.find(pageTitleText, '^Википедия:К разделению/')
					or mw.ustring.find(pageTitleText, '^Википедия:К улучшению/')
				) then
					sectionNotExistMessage = sectionNotExistMessage .. ' Возможно, он был заархивирован.'
				end
				
				if returnAsData then
					data.sectionNotExistMessage = sectionNotExistMessage
				end
				if not returnAsData_onlyStats then
					sectionContent = (standardHeading and '== ' .. (renameHeading or standardSectionHeading) .. ' ==\n' or '') .. "''" .. sectionNotExistMessage .. "''"
				end
			end
		end
	else
		local pageNotExistMessage = 'Страницы [[' .. pageTitleText .. ']] не существует.'
		if not talkpageMode and not returnAsData_onlyStats then
			sectionContent = (standardHeading and '== ' .. (renameHeading or standardSectionHeading) .. ' ==\n' or '') .. "''" .. pageNotExistMessage .. "''"
		end
		if returnAsData then
			if talkpageMode then
				allData.pageNotExistMessage = pageNotExistMessage
			else
				data.pageNotExistMessage = pageNotExistMessage
			end
		end
	end
	
	if returnAsData then
		if talkpageMode then
			return allData
		else
			if not returnAsData_onlyStats then
				data.sectionContent = sectionContent
			end
			return data
		end
	else
		if collapsed then
			sectionContent =
			   	   '<blockquote style="margin:0; padding:0; background:transparent; overflow:visible; font-weight:bold; text-align:center; margin:0 5em;">Содержимое раздела «[[' .. pageTitleText .. sectionHeadingLink .. '|' .. sectionHeading .. ']]» на странице «' .. pageTitleText .. '»</div>'
			   	.. '<table class="collapsible collapsed" style="width:100%; margin-top:-22.4px; border-collapse:collapse;">'
			   	.. '<tr>'
				.. '<th style="padding:0;"></th>'
				.. '</tr>'
				.. '<tr>'
				.. '<td style="padding:0; padding-top:1em;">'
				.. '<div style="border-left:2px solid #a2a9b1; padding-left:0.75em;">' .. sectionContent .. '</div>'
				.. '</td>'
				.. '</tr>'
				.. '</table>'
		elseif showFrame then
			sectionContent =
			      '\'\'Ниже приведено содержимое раздела «[[' .. pageTitleText .. sectionHeadingLink .. '|' .. sectionHeading .. ']]» на странице «' .. pageTitleText .. '»:\'\''
			   .. '<blockquote style="margin:0; padding:0; background:transparent; overflow:visible; border-left:2px solid #a2a9b1; padding-left:0.75em;">' .. sectionContent .. '</div>'
		end
		return sectionContent
	end
end

function p._parse_section_content(args)
	if not args[1] then return '' end
	if type(args[1]) ~= 'table' and args[1]:find('#') then
		pageTitle, sectionHeading = args[1]:match('(.-)#(.+)')
		if pageTitle then
			pageTitle = mw.title.new(pageTitle)
		end
	else
		pageTitle = type(args[1]) == 'table' and args[1] or mw.title.new(args[1])
		sectionHeading = args[2]
	end
	if pageTitle then
		pageTitle.fragment = ''
		pageTitleText = pageTitle.prefixedText
	end
	
	if not pageTitle or not sectionHeading then return '' end
	
	return parsePage(args, false)
end

function p._parse_talkpage_content(args)
	pageTitle = type(args[1]) == 'table' and args[1] or mw.title.new(args[1])
	if pageTitle then
		pageTitle.fragment = ''
		pageTitleText = pageTitle.prefixedText
	end
	
	if not pageTitle then return '' end
	
	return parsePage(args, true)
end

function p.parse_section_content(frame)
	_frame = frame
	local args = getArgs(frame)
	return killHeadingMarkers(frame:preprocess(p._parse_section_content(args)))
end

--[[function p.parse_talkpage_content(frame)
	_frame = frame
	local args = getArgs(frame)
	return killHeadingMarkers(frame:preprocess(p._parse_talkpage_content(args)))
end]]

return p