<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://en.stargatewiki.noip.me/index.php?action=history&amp;feed=atom&amp;title=Module%3AEpisode%2Findex</id>
	<title>Module:Episode/index - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://en.stargatewiki.noip.me/index.php?action=history&amp;feed=atom&amp;title=Module%3AEpisode%2Findex"/>
	<link rel="alternate" type="text/html" href="https://en.stargatewiki.noip.me/index.php?title=Module:Episode/index&amp;action=history"/>
	<updated>2026-05-30T12:23:57Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://en.stargatewiki.noip.me/index.php?title=Module:Episode/index&amp;diff=17492&amp;oldid=prev</id>
		<title>LIMAFOX76: Created page with &quot;local p = {}  -- List of source modules local sources = {     -- Stargate SG-1     &quot;Module:Episode/SG1Season1&quot;,     &quot;Module:Episode/SG1Season2&quot;,     &quot;Module:Episode/SG1Season3&quot;,     &quot;Module:Episode/SG1Season4&quot;,     &quot;Module:Episode/SG1Season5&quot;,     &quot;Module:Episode/SG1Season6&quot;,     &quot;Module:Episode/SG1Season7&quot;,     &quot;Module:Episode/SG1Season8&quot;,     &quot;Module:Episode/SG1Season9&quot;,     &quot;Module:Episode/SG1Season10&quot;,      -- Stargate Atlantis     &quot;Module:Episode/SGASeason1&quot;,     &quot;M...&quot;</title>
		<link rel="alternate" type="text/html" href="https://en.stargatewiki.noip.me/index.php?title=Module:Episode/index&amp;diff=17492&amp;oldid=prev"/>
		<updated>2026-05-28T21:20:42Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;local p = {}  -- List of source modules local sources = {     -- Stargate SG-1     &amp;quot;Module:Episode/SG1Season1&amp;quot;,     &amp;quot;Module:Episode/SG1Season2&amp;quot;,     &amp;quot;Module:Episode/SG1Season3&amp;quot;,     &amp;quot;Module:Episode/SG1Season4&amp;quot;,     &amp;quot;Module:Episode/SG1Season5&amp;quot;,     &amp;quot;Module:Episode/SG1Season6&amp;quot;,     &amp;quot;Module:Episode/SG1Season7&amp;quot;,     &amp;quot;Module:Episode/SG1Season8&amp;quot;,     &amp;quot;Module:Episode/SG1Season9&amp;quot;,     &amp;quot;Module:Episode/SG1Season10&amp;quot;,      -- Stargate Atlantis     &amp;quot;Module:Episode/SGASeason1&amp;quot;,     &amp;quot;M...&amp;quot;&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;
&lt;br /&gt;
-- List of source modules&lt;br /&gt;
local sources = {&lt;br /&gt;
    -- Stargate SG-1&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season1&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season2&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season3&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season4&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season5&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season6&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season7&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season8&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season9&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SG1Season10&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
    -- Stargate Atlantis&lt;br /&gt;
    &amp;quot;Module:Episode/SGASeason1&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SGASeason2&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SGASeason3&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SGASeason4&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SGASeason5&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
    -- Stargate Universe&lt;br /&gt;
    &amp;quot;Module:Episode/SGUSeason1&amp;quot;,&lt;br /&gt;
    &amp;quot;Module:Episode/SGUSeason2&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
    -- Stargate Infinity&lt;br /&gt;
    &amp;quot;Module:Episode/SGISeason1&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
    -- Stargate Origins&lt;br /&gt;
    &amp;quot;Module:Episode/SGOSeason1&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
    -- Films and TV movies&lt;br /&gt;
    &amp;quot;Module:Episode/SGUMovies&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p.index = {}&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
-- Normalization&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function normalize(s)&lt;br /&gt;
    s = s or &amp;quot;&amp;quot;&lt;br /&gt;
    s = mw.text.trim(s)&lt;br /&gt;
&lt;br /&gt;
    -- Unicode NFD decomposition (allows accent stripping)&lt;br /&gt;
    s = mw.ustring.toNFD(s)&lt;br /&gt;
&lt;br /&gt;
    -- Remove combining diacritics (U+0300–U+036F)&lt;br /&gt;
    local combining_start = mw.ustring.char(0x0300)&lt;br /&gt;
    local combining_end   = mw.ustring.char(0x036F)&lt;br /&gt;
    s = mw.ustring.gsub(s, &amp;quot;[&amp;quot; .. combining_start .. &amp;quot;-&amp;quot; .. combining_end .. &amp;quot;]&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    -- Normalize apostrophes&lt;br /&gt;
    s = mw.ustring.gsub(s, &amp;quot;[’‘´`]&amp;quot;, &amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    -- Normalize curly quotes&lt;br /&gt;
    s = mw.ustring.gsub(s, &amp;quot;[“”]&amp;quot;, &amp;quot;\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    -- Normalize all dash types to a simple hyphen&lt;br /&gt;
    s = mw.ustring.gsub(s, &amp;quot;[–—−]&amp;quot;, &amp;quot;-&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    -- Collapse multiple spaces&lt;br /&gt;
    s = mw.ustring.gsub(s, &amp;quot;%s+&amp;quot;, &amp;quot; &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    -- Lowercase&lt;br /&gt;
    s = mw.ustring.lower(s)&lt;br /&gt;
&lt;br /&gt;
    return mw.text.trim(s)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
-- Alias variant generators&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function alias_no_dash(a)&lt;br /&gt;
    return mw.ustring.gsub(a, &amp;quot;[-–—]&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function alias_dash_to_space(a)&lt;br /&gt;
    return mw.ustring.gsub(a, &amp;quot;[-–—]&amp;quot;, &amp;quot; &amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
-- Build the multi-key index&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
for _, modname in ipairs(sources) do&lt;br /&gt;
    local ok, mod = pcall(require, modname)&lt;br /&gt;
    if ok and mod.episodes then&lt;br /&gt;
&lt;br /&gt;
        -- Detect movie module&lt;br /&gt;
        local isMovieModule = modname:match(&amp;quot;SGUMovies&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for _, ep in ipairs(mod.episodes) do&lt;br /&gt;
&lt;br /&gt;
            -- Clone to avoid mutating source data&lt;br /&gt;
            ep = mw.clone(ep)&lt;br /&gt;
&lt;br /&gt;
            -- Movie-specific adjustments&lt;br /&gt;
            if isMovieModule then&lt;br /&gt;
                ep.namespace = ep.namespace or &amp;quot;&amp;quot;  -- Movies use main namespace&lt;br /&gt;
                ep.season    = ep.season    or &amp;quot;&amp;quot;  -- No season number&lt;br /&gt;
                ep.episode   = ep.episode   or &amp;quot;&amp;quot;  -- No episode number&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            -- Generate alias variants&lt;br /&gt;
            for _, key in ipairs(ep.alias or {}) do&lt;br /&gt;
&lt;br /&gt;
                local variants = { key }&lt;br /&gt;
&lt;br /&gt;
                -- Remove dashes&lt;br /&gt;
                local nd = alias_no_dash(key)&lt;br /&gt;
                if nd ~= key then table.insert(variants, nd) end&lt;br /&gt;
&lt;br /&gt;
                -- Replace dashes with spaces&lt;br /&gt;
                local sp = alias_dash_to_space(key)&lt;br /&gt;
                if sp ~= key then table.insert(variants, sp) end&lt;br /&gt;
&lt;br /&gt;
                -- Index all variants&lt;br /&gt;
                for _, raw in ipairs(variants) do&lt;br /&gt;
                    local nkey = normalize(raw)&lt;br /&gt;
&lt;br /&gt;
                    if p.index[nkey] then&lt;br /&gt;
                        mw.log(string.format(&lt;br /&gt;
                            &amp;quot;[EpisodeIndex] Alias collision detected: &amp;#039;%s&amp;#039; → %s and %s&amp;quot;,&lt;br /&gt;
                            nkey,&lt;br /&gt;
                            p.index[nkey].id or &amp;quot;(no id)&amp;quot;,&lt;br /&gt;
                            ep.id or &amp;quot;(no id)&amp;quot;&lt;br /&gt;
                        ))&lt;br /&gt;
                    else&lt;br /&gt;
                        p.index[nkey] = ep&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
-- Access function&lt;br /&gt;
------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.get(key)&lt;br /&gt;
    local ep = p.index[normalize(key)]&lt;br /&gt;
    if not ep then return nil end&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        id          = ep.id,&lt;br /&gt;
        namespace   = ep.namespace,&lt;br /&gt;
        page_title  = ep.page_title,&lt;br /&gt;
        title_en    = ep.title_en or ep.title_vo,  -- English wiki: keep only English/VO&lt;br /&gt;
        property    = ep.property,&lt;br /&gt;
        season      = ep.season,&lt;br /&gt;
        episode     = ep.episode,&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>LIMAFOX76</name></author>
	</entry>
</feed>