Jump to content

Module:CodeToText: Difference between revisions

// via Wikitext Extension for VSCode
// via Wikitext Extension for VSCode
Line 3: Line 3:
-- 1. A defined line range (from/to parameters)
-- 1. A defined line range (from/to parameters)
-- 2. Hook markers like emojis (hook parameter)
-- 2. Hook markers like emojis (hook parameter)
--
-- The module finds content between matching instances of the same hook,
-- The module finds content between matching instances of the same hook,
-- either on different lines or within the same line.
-- either on different lines or within the same line. Any emoji can be used
-- as a hook (🪝, 📌, 🔖, 🏷️, 🚩, ⭐, etc.) - just place the same emoji at
-- the beginning and end of the content you want to extract.
--
-- Example:
--  {{#invoke:TranscludeModuleCode|showSnippet|page=Module:Example|hook=⭐}}


local p = {}
local p = {}
Line 15: Line 21:
      
      
     local hook = frame.args.hook
     local hook = frame.args.hook
    local includeHook = frame.args.includeHook == 'true'
    local debug = frame.args.debug == 'true'
      
      
     -- Fallback to line numbers if hook isn't provided
     -- Fallback to line numbers if hook isn't provided
Line 38: Line 42:


     local snippet = {}
     local snippet = {}
    local debugInfo = {}
      
      
     -- If hook is provided, use it to extract the snippet
     -- If hook is provided, use it to extract the snippet
Line 56: Line 59:
                     inlineHookFound = true
                     inlineHookFound = true
                      
                      
                    if debug then
                     -- Extract the content between the hooks (excluding the hooks themselves)
                        table.insert(debugInfo, "Found inline hooks at line " .. i .. ": " .. line)
                        table.insert(debugInfo, "Start position: " .. startPos .. ", End position: " .. endPos)
                    end
                   
                     -- Extract the content between the hooks
                     local extractedContent = line:sub(startPos + #hook, endPos - 1)
                     local extractedContent = line:sub(startPos + #hook, endPos - 1)
                   
                    if includeHook then
                        extractedContent = hook .. extractedContent .. hook
                    end
                   
                     table.insert(snippet, extractedContent)
                     table.insert(snippet, extractedContent)
                   
                    if debug then
                        table.insert(snippet, "\n-- Debug info:")
                        table.insert(snippet, "-- Found inline hooks on line " .. i)
                        table.insert(snippet, "-- Extracted content between positions " .. (startPos + #hook) .. " and " .. (endPos - 1))
                    end
                      
                      
                     break
                     break
Line 89: Line 76:
                 if line:find(hook, 1, true) then
                 if line:find(hook, 1, true) then
                     table.insert(hookPositions, i)
                     table.insert(hookPositions, i)
                    if debug then
                        table.insert(debugInfo, "Found hook at line " .. i .. ": " .. line)
                    end
                elseif debug then
                    table.insert(debugInfo, "Line " .. i .. " (no hook): " .. line:sub(1, 30) .. (line:len() > 30 and "..." or ""))
                 end
                 end
             end
             end
              
              
             if #hookPositions < 2 then
             if #hookPositions < 2 then
                 local errorMsg = "Error: Need at least 2 instances of hook '" .. hook .. "' in '" .. pageName .. "'"
                 return "Error: Need at least 2 instances of hook '" .. hook .. "' in '" .. pageName .. "'"
                if debug then
                    errorMsg = errorMsg .. "\n\nDebug info:\n" .. table.concat(debugInfo, "\n")
                end
                return errorMsg
             end
             end
              
              
             -- Extract content between first two hook instances
             -- Extract content between first two hook instances (excluding the hook lines)
             local startLine = hookPositions[1]
             local startLine = hookPositions[1]
             local endLine = hookPositions[2]
             local endLine = hookPositions[2]
              
              
             local startIndex = includeHook and startLine or startLine + 1
            -- Always exclude the hook lines
             local endIndex = includeHook and endLine or endLine - 1
             local startIndex = startLine + 1
             local endIndex = endLine - 1
              
              
             for i = startIndex, endIndex do
             for i = startIndex, endIndex do
                 table.insert(snippet, lines[i])
                 table.insert(snippet, lines[i])
            end
           
            if debug then
                table.insert(snippet, "\n-- Debug info:")
                table.insert(snippet, "-- Found " .. #hookPositions .. " hook instances on separate lines")
                table.insert(snippet, "-- Extracting content between lines " .. startIndex .. " and " .. endIndex)
             end
             end
         end
         end

Revision as of 00:00, 4 April 2025

Documentation for this module may be created at Module:CodeToText/doc

-- Module:TranscludeModuleCode
-- Extracts a snippet of content from a specified page using either:
-- 1. A defined line range (from/to parameters)
-- 2. Hook markers like emojis (hook parameter)
-- 
-- The module finds content between matching instances of the same hook,
-- either on different lines or within the same line. Any emoji can be used
-- as a hook (🪝, 📌, 🔖, 🏷️, 🚩, ⭐, etc.) - just place the same emoji at
-- the beginning and end of the content you want to extract.
-- 
-- Example:
--   {{#invoke:TranscludeModuleCode|showSnippet|page=Module:Example|hook=⭐}}

local p = {}

function p.showSnippet(frame)
    local pageName = frame.args.page
    if not pageName then
        return "Error: 'page' parameter is required"
    end
    
    local hook = frame.args.hook
    
    -- Fallback to line numbers if hook isn't provided
    local fromLine = tonumber(frame.args.from) or 1
    local toLine   = tonumber(frame.args.to)   or fromLine

    local titleObj = mw.title.new(pageName)
    if not titleObj then
        return "Failed to create mw.title object for '" .. pageName .. "'"
    end

    local content = titleObj:getContent()
    if not content then
        return "No content for '" .. pageName .. "'"
    end

    local lines = {}
    for line in content:gmatch("[^\r\n]+") do
        table.insert(lines, line)
    end

    local snippet = {}
    
    -- If hook is provided, use it to extract the snippet
    if hook then
        -- First, check if any line contains multiple instances of the hook
        local inlineHookFound = false
        
        for i, line in ipairs(lines) do
            -- Find first occurrence of hook in the line
            local startPos = line:find(hook, 1, true)
            if startPos then
                -- Find second occurrence of hook in the same line
                local endPos = line:find(hook, startPos + #hook, true)
                
                if endPos then
                    -- We found a line with multiple hooks - extract content between them
                    inlineHookFound = true
                    
                    -- Extract the content between the hooks (excluding the hooks themselves)
                    local extractedContent = line:sub(startPos + #hook, endPos - 1)
                    table.insert(snippet, extractedContent)
                    
                    break
                end
            end
        end
        
        -- If we didn't find inline hooks, look for hooks on different lines
        if not inlineHookFound then
            local hookPositions = {}
            
            -- Find all instances of the hook
            for i, line in ipairs(lines) do
                if line:find(hook, 1, true) then
                    table.insert(hookPositions, i)
                end
            end
            
            if #hookPositions < 2 then
                return "Error: Need at least 2 instances of hook '" .. hook .. "' in '" .. pageName .. "'"
            end
            
            -- Extract content between first two hook instances (excluding the hook lines)
            local startLine = hookPositions[1]
            local endLine = hookPositions[2]
            
            -- Always exclude the hook lines
            local startIndex = startLine + 1
            local endIndex = endLine - 1
            
            for i = startIndex, endIndex do
                table.insert(snippet, lines[i])
            end
        end
    else
        -- Fallback to line number-based extraction
        for i = fromLine, math.min(toLine, #lines) do
            table.insert(snippet, lines[i])
        end
    end

    return table.concat(snippet, "\n")
end

return p