<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://en.teopedia.org/w-lib/index.php?action=history&amp;feed=atom&amp;title=Module%3ALucifer_authors</id>
	<title>Module:Lucifer authors - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://en.teopedia.org/w-lib/index.php?action=history&amp;feed=atom&amp;title=Module%3ALucifer_authors"/>
	<link rel="alternate" type="text/html" href="https://en.teopedia.org/w-lib/index.php?title=Module:Lucifer_authors&amp;action=history"/>
	<updated>2026-11-05T03:55:15Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.2</generator>
	<entry>
		<id>https://en.teopedia.org/w-lib/index.php?title=Module:Lucifer_authors&amp;diff=55364&amp;oldid=prev</id>
		<title>24pmBot2: Add an automatic Lucifer author index and navigation link</title>
		<link rel="alternate" type="text/html" href="https://en.teopedia.org/w-lib/index.php?title=Module:Lucifer_authors&amp;diff=55364&amp;oldid=prev"/>
		<updated>2026-11-01T07:32:43Z</updated>

		<summary type="html">&lt;p&gt;Add an automatic Lucifer author index and navigation link&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
local FS, RS, AS = mw.ustring.char(0x2063), mw.ustring.char(0x2064), mw.ustring.char(0x2062)&lt;br /&gt;
&lt;br /&gt;
local function split(s, sep)&lt;br /&gt;
    local out, start = {}, 1&lt;br /&gt;
    while true do&lt;br /&gt;
        local a, b = string.find(s, sep, start, true)&lt;br /&gt;
        if not a then table.insert(out, string.sub(s, start)); return out end&lt;br /&gt;
        table.insert(out, string.sub(s, start, a - 1)); start = b + 1&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function trim(s) return mw.text.trim(s or &amp;#039;&amp;#039;) end&lt;br /&gt;
&lt;br /&gt;
-- Legacy records sometimes separate linked coauthors with commas rather than&lt;br /&gt;
-- the property&amp;#039;s semicolon separator. Never split commas inside a page name.&lt;br /&gt;
local function authors(value)&lt;br /&gt;
    local out = {}&lt;br /&gt;
    for _, part in ipairs(split(value, AS)) do&lt;br /&gt;
        if part:find(&amp;#039;[[&amp;#039;, 1, true) then&lt;br /&gt;
            local start = 1&lt;br /&gt;
            while true do&lt;br /&gt;
                local a, b = part:find(&amp;#039;%[%[[^]]+%]%]&amp;#039;, start)&lt;br /&gt;
                local rest = part:sub(start, a and a - 1 or #part)&lt;br /&gt;
                rest = trim(rest:gsub(&amp;#039;^[%s,;]+&amp;#039;, &amp;#039;&amp;#039;):gsub(&amp;#039;[%s,;]+$&amp;#039;, &amp;#039;&amp;#039;))&lt;br /&gt;
                if rest ~= &amp;#039;&amp;#039; and rest ~= &amp;#039;and&amp;#039; then table.insert(out, rest) end&lt;br /&gt;
                if not a then break end&lt;br /&gt;
                table.insert(out, part:sub(a, b))&lt;br /&gt;
                start = b + 1&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            table.insert(out, part)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return out&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function fetch(frame)&lt;br /&gt;
    local rows, offset = {}, 0&lt;br /&gt;
    for batch = 1, 100 do&lt;br /&gt;
        local query = &amp;#039;{{#ask:[[Lucifer item author::+]]&amp;#039;&lt;br /&gt;
            .. &amp;#039;|?Lucifer item author=a|+sep=&amp;#039; .. AS&lt;br /&gt;
            .. &amp;#039;|?Lucifer item ID=id|?Lucifer item title=t&amp;#039;&lt;br /&gt;
            .. &amp;#039;|?Lucifer item volume=v|?Lucifer item number=n|?Lucifer item page=pg&amp;#039;&lt;br /&gt;
            .. &amp;#039;|?Lucifer item month=m|?Lucifer item year=y&amp;#039;&lt;br /&gt;
            .. &amp;#039;|?Lucifer item links to text=links|+sep=; &amp;#039;&lt;br /&gt;
            .. &amp;#039;|mainlabel=-|link=none|headers=hide|named args=yes&amp;#039;&lt;br /&gt;
            .. &amp;#039;|format=template|template=Lucifer authors raw row&amp;#039;&lt;br /&gt;
            .. &amp;#039;|sort=Lucifer item ID|order=asc|searchlabel=|limit=500|offset=&amp;#039; .. offset .. &amp;#039;}}&amp;#039;&lt;br /&gt;
        local text = frame:preprocess(query):gsub(&amp;#039;%[%[SMW::off%]%]&amp;#039;, &amp;#039;&amp;#039;):gsub(&amp;#039;%[%[SMW::on%]%]&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
        local count = 0&lt;br /&gt;
        for _, record in ipairs(split(text, RS)) do&lt;br /&gt;
            local f = split(record, FS)&lt;br /&gt;
            if #f == 9 and trim(f[2]) ~= &amp;#039;&amp;#039; then&lt;br /&gt;
                table.insert(rows, {a=trim(f[1]), id=f[2], t=f[3], v=f[4], n=f[5], pg=f[6], m=f[7], y=f[8], links=f[9]})&lt;br /&gt;
                count = count + 1&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if count == 0 then return rows end&lt;br /&gt;
        offset = offset + count&lt;br /&gt;
    end&lt;br /&gt;
    error(&amp;#039;Lucifer author index exceeds the pagination safety limit.&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function group(rows)&lt;br /&gt;
    local map, order = {}, {}&lt;br /&gt;
    for _, r in ipairs(rows) do&lt;br /&gt;
        local seen = {}&lt;br /&gt;
        for _, raw in ipairs(authors(r.a)) do&lt;br /&gt;
            raw = trim(raw)&lt;br /&gt;
            local target = raw:match(&amp;#039;^%[%[([^]|]+)|[^]]+%]%]$&amp;#039;) or raw:match(&amp;#039;^%[%[([^]]+)%]%]$&amp;#039;)&lt;br /&gt;
            local name = trim(target or raw)&lt;br /&gt;
            if name ~= &amp;#039;&amp;#039; and not seen[name] then&lt;br /&gt;
                seen[name] = true&lt;br /&gt;
                if not map[name] then&lt;br /&gt;
                    map[name] = {target=target, label=raw, items={}}&lt;br /&gt;
                    table.insert(order, name)&lt;br /&gt;
                end&lt;br /&gt;
                table.insert(map[name].items, r)&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    table.sort(order, function(a,b) return mw.ustring.lower(a) &amp;lt; mw.ustring.lower(b) end)&lt;br /&gt;
    return map, order&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.list(frame)&lt;br /&gt;
    local map, order = group(fetch(frame))&lt;br /&gt;
    local out = {}&lt;br /&gt;
    for _, name in ipairs(order) do&lt;br /&gt;
        local author = map[name]&lt;br /&gt;
        local label = author.label&lt;br /&gt;
        if author.target then&lt;br /&gt;
            label = frame:expandTemplate{title=&amp;#039;CTD show name&amp;#039;, args={[1]=author.target, mode=&amp;#039;full LF&amp;#039;}}&lt;br /&gt;
            label = &amp;#039;[[&amp;#039; .. author.target .. &amp;#039;|&amp;#039; .. label .. &amp;#039;]]&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(out, &amp;#039;&amp;lt;h3&amp;gt;&amp;#039; .. label .. &amp;#039;&amp;lt;/h3&amp;gt;\n&amp;lt;ol&amp;gt;&amp;#039;)&lt;br /&gt;
        table.sort(author.items, function(a,b)&lt;br /&gt;
            if a.t == b.t then return a.id &amp;lt; b.id end&lt;br /&gt;
            return mw.ustring.lower(a.t) &amp;lt; mw.ustring.lower(b.t)&lt;br /&gt;
        end)&lt;br /&gt;
        for _, r in ipairs(author.items) do&lt;br /&gt;
            local location = &amp;#039;Lucifer/Vol&amp;#039; .. r.v .. &amp;#039;#n&amp;#039; .. r.n&lt;br /&gt;
            local details = &amp;#039;vol. &amp;#039; .. r.v .. &amp;#039;, no. &amp;#039; .. r.n .. &amp;#039;, &amp;#039; .. r.m .. &amp;#039; &amp;#039; .. r.y .. &amp;#039;, pp. &amp;#039; .. r.pg&lt;br /&gt;
            if not r.pg:find(&amp;#039;-&amp;#039;, 1, true) then details = details:gsub(&amp;#039;, pp%. &amp;#039;, &amp;#039;, p. &amp;#039;) end&lt;br /&gt;
            local links = trim(r.links) ~= &amp;#039;&amp;#039; and (&amp;#039;; &amp;#039; .. r.links) or &amp;#039;&amp;#039;&lt;br /&gt;
            table.insert(out, &amp;#039;&amp;lt;li&amp;gt;&amp;lt;i&amp;gt;&amp;#039; .. r.t .. &amp;#039;&amp;lt;/i&amp;gt; &amp;lt;span style=&amp;quot;color:grey; font-size:85%;&amp;quot;&amp;gt;([[&amp;#039; .. location .. &amp;#039;|&amp;#039; .. details .. &amp;#039;]])&amp;#039; .. links .. &amp;#039;&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(out, &amp;#039;&amp;lt;/ol&amp;gt;&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    return table.concat(out, &amp;#039;\n&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.debug(frame)&lt;br /&gt;
    local rows = fetch(frame)&lt;br /&gt;
    local _, order = group(rows)&lt;br /&gt;
    return &amp;#039;Total rows fetched: &amp;#039; .. #rows .. &amp;#039;; unique authors: &amp;#039; .. #order&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>24pmBot2</name></author>
	</entry>
</feed>