Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Word count

From Wikipedia, the free encyclopedia

--- This module implements {{tl|Word count}}.
--
-- @module Word_count
-- @alias p
-- @release alpha
-- @require Module:Arguments


local p = {}
local yn = require("Module:Yesno")
local pv = require("Module:If preview")
local pvWarning = pv._warning

--- Strips wikitext
-- @param {string} text Text to strip
-- @return Stripped text
local function stripWikitext(text)
	text = mw.ustring.gsub(text, "<!%-%-.-%-%->", "")
	text = mw.ustring.gsub(text, "<ref[^>/]->.-</ref>", "")
	text = mw.ustring.gsub(text, "<ref[^/>]*/>", "")
	text = mw.ustring.gsub(text, "{{.-}}", "")
	text = mw.ustring.gsub(text, "{|.-|}", "")
	return text
end

--- Gets the page content
-- @param {string} pagename Name of page
-- @return Page content
local function getPageText(pagename)
	if not pagename or pagename == "" then
		return nil
	end

	local title = mw.title.new(pagename)
	if not title or not title.exists then
		return nil
	end

	return title:getContent()
end

--- Main entry point for modules
-- @param {string} str Input string
-- @param {number} limit Word count limit
-- @return table with necessary outputs

function p._main(str, limit)
	local strout = ""
	limit = limit or math.huge
	local count = 0
	local phrases = mw.text.split(str, "%s")
	local separators = {}
	for match in mw.ustring.gmatch(str, "%s") do
		table.insert(separators, match)
	end
	for k,v in pairs(phrases) do
		if (count < limit) then
			strout = strout .. v .. (separators[k] ~= nil and separators[k] or "")
		end
		if v ~= "" then
			count = count + 1
		end
	end
	return {str = str, trimmedstr = strout, count = count}
end

--- Entrypoint for template
-- @param {table} frame processing frame
-- @param {table} frame.args Template arguments
-- @param {string} frame.args.page Page mode
-- @param {string} frame.args.limit Word count limit
-- @param {boolean} frame.args.showcount whether to show the word count
-- @param {boolean} frame.args.trim Whether to trim at the word count limit
-- @param {boolean} frame.args.unsubst Whether to convert substitutions into transclusions
-- @param {string} frame.args.prepend What to prepend prior to word limited section
-- @param {string} frame.args.append What to append after word limited section
-- @return {string} Output wikitext
function p.main(frame)
	local args = require("Module:Arguments").getArgs(frame)
	local str = args[1] or ''
	local pageMode = args.page ~= nil
	if args.page then
		local pageText = getPageText(args.page)
		if not pageText then
			return '<span class="error">Invalid or non-existent page</span>'
		end
		str = stripWikitext(pageText)
	end
	local limit = tonumber(args['limit']) or tonumber(args[2]) or math.huge
	local result = p._main(str, limit)
	mw.logObject(result)
	local out = ''
	if (yn(args['showcount'] or false) and not mw.isSubsting()) or frame:preprocess('{{REVISIONID}}') == "" then -- always show in preview
		if limit == math.huge then
			out = out .. 'Word count: ' .. result['count'] .. '<br/>'
		elseif 0 <= result['count'] and result['count'] < limit / 2 then
			out = out .. 'Word count: <span class="wordcount-good">' .. result['count'] .. '</span>/' .. limit ..  '<br>'
		elseif limit / 2 <= result['count'] and result['count'] < limit then
			out = out .. 'Word count: <span class="wordcount-okay">' .. result['count'] .. '</span>/' .. limit ..  '<br>'
		else
			out = out .. 'Word count: <span class="wordcount-bad">' .. result['count'] .. '</span>/' .. limit .. '<br>'
		end
	end
	if yn(args['trim']) and result['count'] > limit then
		out = out .. pvWarning({"Word count limit of " .. limit .. " exceeded by " .. (result['count'] - limit) .. " words. Additional text will be ignored."})
	end
	local res = (yn(args['trim']) and result['trimmedstr'] or str)
	if not pageMode then
		out = out .. (args['prepend'] or '') .. res .. (args['append'] or '')
	end
	if mw.isSubsting() then
		if args['unsubst'] then
			local f = frame:getParent()
			local title = f:getTitle().text or "#invoke:Word count|main"
			local preout = '{{' .. title .. "\n"
			for k,v in pairs(args) do
				if k == args['unsubst'] or tonumber(k) == tonumber(args['unsubst'] or '0') then
					preout = preout .. '|' .. k .. '=' .. res .. "\n"
				else
					preout = preout .. '|' .. k .. '=' .. v
				end
			end
			return preout .. '}}'
		end
		return out
	end
	return frame:extensionTag("templatestyles", "", {src = "Module:Word_count/styles.css"}) .. out
end

return p