<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://kingwarzcharts.com/index.php?action=history&amp;feed=atom&amp;title=Module%3AKWCChart</id>
	<title>Module:KWCChart - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://kingwarzcharts.com/index.php?action=history&amp;feed=atom&amp;title=Module%3AKWCChart"/>
	<link rel="alternate" type="text/html" href="https://kingwarzcharts.com/index.php?title=Module:KWCChart&amp;action=history"/>
	<updated>2026-07-21T16:40:50Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://kingwarzcharts.com/index.php?title=Module:KWCChart&amp;diff=3145&amp;oldid=prev</id>
		<title>KWCBot: Accept |years= for tooltip year display (kwcYears, rendered by Common.js)</title>
		<link rel="alternate" type="text/html" href="https://kingwarzcharts.com/index.php?title=Module:KWCChart&amp;diff=3145&amp;oldid=prev"/>
		<updated>2026-07-12T23:44:25Z</updated>

		<summary type="html">&lt;p&gt;Accept |years= for tooltip year display (kwcYears, rendered by Common.js)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Module:KWCChart — interactive ECharts builder for King Warz Charts.&lt;br /&gt;
-- Rendered client-side by the loader in [[MediaWiki:Common.js]] (ECharts via&lt;br /&gt;
-- cdnjs, which Miraheze&amp;#039;s CSP allows). Parameter interface mirrors the&lt;br /&gt;
-- familiar Fandom chart template: weeks, positions N, name N, color N,&lt;br /&gt;
-- places, height, width — plus type=line|bar and inverse=0|1.&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- keep only characters that can legally appear in a JSON number/null/string&lt;br /&gt;
-- fragment list; blocks wikitext/HTML injection into the config JSON.&lt;br /&gt;
local function cleanFragment(s)&lt;br /&gt;
    if not s then return nil end&lt;br /&gt;
    s = mw.text.trim(s)&lt;br /&gt;
    if s == &amp;#039;&amp;#039; then return nil end&lt;br /&gt;
    -- allow: digits, quotes, letters (labels), spaces, commas, dots, dashes,&lt;br /&gt;
    -- slashes, colons, apostrophes, parentheses, null&lt;br /&gt;
    if s:find(&amp;#039;[{}&amp;lt;&amp;gt;%[%]\\]&amp;#039;) then return nil end&lt;br /&gt;
    return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function cleanText(s)&lt;br /&gt;
    if not s then return nil end&lt;br /&gt;
    s = mw.text.trim(s)&lt;br /&gt;
    if s == &amp;#039;&amp;#039; then return nil end&lt;br /&gt;
    return (s:gsub(&amp;#039;[{}&amp;lt;&amp;gt;%[%]\\&amp;quot;]&amp;#039;, &amp;#039;&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.chart(frame)&lt;br /&gt;
    local pargs = frame:getParent().args&lt;br /&gt;
    local fargs = frame.args&lt;br /&gt;
&lt;br /&gt;
    local charttype = cleanText(fargs.type or pargs.type) or &amp;#039;line&amp;#039;&lt;br /&gt;
    if charttype ~= &amp;#039;line&amp;#039; and charttype ~= &amp;#039;bar&amp;#039; then charttype = &amp;#039;line&amp;#039; end&lt;br /&gt;
    local inverse = (fargs.inverse or pargs.inverse or &amp;#039;&amp;#039;) ~= &amp;#039;&amp;#039;&lt;br /&gt;
    local places = tonumber(pargs.places) or 60&lt;br /&gt;
    local height = cleanText(pargs.height) or &amp;#039;400px&amp;#039;&lt;br /&gt;
    local width = cleanText(pargs.width) or &amp;#039;100%&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    local labels = cleanFragment(pargs.weeks or pargs.labels or pargs[1])&lt;br /&gt;
    if not labels then&lt;br /&gt;
        return &amp;#039;&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;KWCChart: missing weeks/labels&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    -- optional per-label years, shown in the hover tooltip as &amp;quot;143 (2026)&amp;quot;&lt;br /&gt;
    local years = cleanFragment(pargs.years)&lt;br /&gt;
&lt;br /&gt;
    -- optional peak marker: peak week / peak pos / peak series (1-based)&lt;br /&gt;
    local peakWeek = cleanText(pargs[&amp;#039;peak week&amp;#039;])&lt;br /&gt;
    local peakPos = tonumber(pargs[&amp;#039;peak pos&amp;#039;])&lt;br /&gt;
    local peakSeries = tonumber(pargs[&amp;#039;peak series&amp;#039;]) or 1&lt;br /&gt;
    -- optional shaded band for the longest consecutive chart run&lt;br /&gt;
    local runStart = cleanText(pargs[&amp;#039;run start&amp;#039;])&lt;br /&gt;
    local runEnd = cleanText(pargs[&amp;#039;run end&amp;#039;])&lt;br /&gt;
&lt;br /&gt;
    -- series 1..20 (positions/positions N, values/values N aliases)&lt;br /&gt;
    local series = {}&lt;br /&gt;
    for i = 1, 20 do&lt;br /&gt;
        local key = (i == 1)&lt;br /&gt;
            and (pargs[&amp;#039;positions&amp;#039;] or pargs[&amp;#039;positions 1&amp;#039;]&lt;br /&gt;
                 or pargs[&amp;#039;values&amp;#039;] or pargs[&amp;#039;values 1&amp;#039;] or pargs[2])&lt;br /&gt;
            or (pargs[&amp;#039;positions &amp;#039; .. i] or pargs[&amp;#039;values &amp;#039; .. i])&lt;br /&gt;
        local data = cleanFragment(key)&lt;br /&gt;
        if data then&lt;br /&gt;
            local name = cleanText(pargs[&amp;#039;name &amp;#039; .. i]&lt;br /&gt;
                                   or (i == 1 and pargs[&amp;#039;name&amp;#039;] or nil))&lt;br /&gt;
            local color = cleanText(pargs[&amp;#039;color &amp;#039; .. i]&lt;br /&gt;
                                    or (i == 1 and pargs[&amp;#039;color&amp;#039;] or nil))&lt;br /&gt;
            local s = &amp;#039;{&amp;quot;type&amp;quot;:&amp;quot;&amp;#039; .. charttype .. &amp;#039;&amp;quot;,&amp;quot;smooth&amp;quot;:true,&amp;#039; ..&lt;br /&gt;
                      &amp;#039;&amp;quot;connectNulls&amp;quot;:false,&amp;quot;symbolSize&amp;quot;:5,&amp;#039;&lt;br /&gt;
            if name then s = s .. &amp;#039;&amp;quot;name&amp;quot;:&amp;quot;&amp;#039; .. name .. &amp;#039;&amp;quot;,&amp;#039; end&lt;br /&gt;
            if color then&lt;br /&gt;
                s = s .. &amp;#039;&amp;quot;lineStyle&amp;quot;:{&amp;quot;color&amp;quot;:&amp;quot;&amp;#039; .. color .. &amp;#039;&amp;quot;},&amp;#039; ..&lt;br /&gt;
                         &amp;#039;&amp;quot;itemStyle&amp;quot;:{&amp;quot;color&amp;quot;:&amp;quot;&amp;#039; .. color .. &amp;#039;&amp;quot;},&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
            if peakWeek and peakPos and (#series + 1) == peakSeries then&lt;br /&gt;
                s = s .. &amp;#039;&amp;quot;markPoint&amp;quot;:{&amp;quot;symbol&amp;quot;:&amp;quot;pin&amp;quot;,&amp;quot;symbolSize&amp;quot;:34,&amp;#039; ..&lt;br /&gt;
                    &amp;#039;&amp;quot;itemStyle&amp;quot;:{&amp;quot;color&amp;quot;:&amp;quot;#d4a72c&amp;quot;},&amp;#039; ..&lt;br /&gt;
                    &amp;#039;&amp;quot;label&amp;quot;:{&amp;quot;fontSize&amp;quot;:9,&amp;quot;color&amp;quot;:&amp;quot;#fff&amp;quot;},&amp;#039; ..&lt;br /&gt;
                    &amp;#039;&amp;quot;data&amp;quot;:[{&amp;quot;coord&amp;quot;:[&amp;quot;&amp;#039; .. peakWeek .. &amp;#039;&amp;quot;,&amp;#039; .. peakPos ..&lt;br /&gt;
                    &amp;#039;],&amp;quot;value&amp;quot;:&amp;quot;#&amp;#039; .. peakPos .. &amp;#039;&amp;quot;}]},&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
            if runStart and runEnd and #series == 0 then&lt;br /&gt;
                s = s .. &amp;#039;&amp;quot;markArea&amp;quot;:{&amp;quot;silent&amp;quot;:true,&amp;#039; ..&lt;br /&gt;
                    &amp;#039;&amp;quot;itemStyle&amp;quot;:{&amp;quot;color&amp;quot;:&amp;quot;rgba(47,111,235,0.07)&amp;quot;},&amp;#039; ..&lt;br /&gt;
                    &amp;#039;&amp;quot;data&amp;quot;:[[{&amp;quot;xAxis&amp;quot;:&amp;quot;&amp;#039; .. runStart .. &amp;#039;&amp;quot;},&amp;#039; ..&lt;br /&gt;
                    &amp;#039;{&amp;quot;xAxis&amp;quot;:&amp;quot;&amp;#039; .. runEnd .. &amp;#039;&amp;quot;}]]},&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
            s = s .. &amp;#039;&amp;quot;data&amp;quot;:[&amp;#039; .. data .. &amp;#039;]}&amp;#039;&lt;br /&gt;
            series[#series + 1] = s&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if #series == 0 then&lt;br /&gt;
        return &amp;#039;&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;KWCChart: no positions/values given&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local yaxis&lt;br /&gt;
    if inverse then&lt;br /&gt;
        yaxis = &amp;#039;{&amp;quot;type&amp;quot;:&amp;quot;value&amp;quot;,&amp;quot;min&amp;quot;:1,&amp;quot;max&amp;quot;:&amp;#039; .. places ..&lt;br /&gt;
                &amp;#039;,&amp;quot;inverse&amp;quot;:true}&amp;#039;&lt;br /&gt;
    else&lt;br /&gt;
        yaxis = &amp;#039;{&amp;quot;type&amp;quot;:&amp;quot;value&amp;quot;}&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local legend = (#series &amp;gt; 1)&lt;br /&gt;
        and &amp;#039;&amp;quot;legend&amp;quot;:{&amp;quot;top&amp;quot;:0,&amp;quot;type&amp;quot;:&amp;quot;scroll&amp;quot;},&amp;#039; or &amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    local yearsPart = &amp;#039;&amp;#039;&lt;br /&gt;
    if years then&lt;br /&gt;
        yearsPart = &amp;#039;&amp;quot;kwcYears&amp;quot;:[&amp;#039; .. years .. &amp;#039;],&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local json = &amp;#039;{&amp;#039; ..&lt;br /&gt;
        yearsPart ..&lt;br /&gt;
        &amp;#039;&amp;quot;textStyle&amp;quot;:{&amp;quot;fontSize&amp;quot;:12},&amp;#039; ..&lt;br /&gt;
        &amp;#039;&amp;quot;tooltip&amp;quot;:{&amp;quot;trigger&amp;quot;:&amp;quot;axis&amp;quot;},&amp;#039; ..&lt;br /&gt;
        legend ..&lt;br /&gt;
        &amp;#039;&amp;quot;grid&amp;quot;:{&amp;quot;top&amp;quot;:&amp;#039; .. (#series &amp;gt; 1 and 48 or 40) ..&lt;br /&gt;
            &amp;#039;,&amp;quot;left&amp;quot;:40,&amp;quot;right&amp;quot;:16,&amp;quot;bottom&amp;quot;:54},&amp;#039; ..&lt;br /&gt;
        &amp;#039;&amp;quot;dataZoom&amp;quot;:[{&amp;quot;type&amp;quot;:&amp;quot;inside&amp;quot;},{&amp;quot;type&amp;quot;:&amp;quot;slider&amp;quot;,&amp;quot;height&amp;quot;:18,&amp;quot;bottom&amp;quot;:6}],&amp;#039; ..&lt;br /&gt;
        &amp;#039;&amp;quot;xAxis&amp;quot;:{&amp;quot;type&amp;quot;:&amp;quot;category&amp;quot;,&amp;quot;axisLabel&amp;quot;:{&amp;quot;interval&amp;quot;:&amp;quot;auto&amp;quot;,&amp;quot;rotate&amp;quot;:45},&amp;#039; ..&lt;br /&gt;
            &amp;#039;&amp;quot;data&amp;quot;:[&amp;#039; .. labels .. &amp;#039;]},&amp;#039; ..&lt;br /&gt;
        &amp;#039;&amp;quot;yAxis&amp;quot;:&amp;#039; .. yaxis .. &amp;#039;,&amp;#039; ..&lt;br /&gt;
        &amp;#039;&amp;quot;series&amp;quot;:[&amp;#039; .. table.concat(series, &amp;#039;,&amp;#039;) .. &amp;#039;]&amp;#039; ..&lt;br /&gt;
        &amp;#039;}&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    return &amp;#039;&amp;lt;div class=&amp;quot;kwc-echart&amp;quot; style=&amp;quot;width:&amp;#039; .. width ..&lt;br /&gt;
           &amp;#039;;height:&amp;#039; .. height .. &amp;#039;&amp;quot;&amp;gt;&amp;#039; ..&lt;br /&gt;
           &amp;#039;&amp;lt;pre class=&amp;quot;kwc-echart-config&amp;quot; style=&amp;quot;display:none&amp;quot;&amp;gt;&amp;#039; ..&lt;br /&gt;
           mw.text.nowiki(json) .. &amp;#039;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>KWCBot</name></author>
	</entry>
</feed>