Jump to content

Module:CodeToText: Difference between revisions

// via Wikitext Extension for VSCode
// via Wikitext Extension for VSCode
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
-- Module:TranscludeModuleCode
--[[
-- Extracts a snippet of content from a specified page using either:
* Name: CodeToText
-- 1. A defined line range (from/to parameters)
* Author: Mark W. Datysgeld
-- 2. Hook markers like emojis (hook parameter)
* Description: Utility for extracting content snippets from wiki pages using emoji hook markers placed at the beginning and end of desired content sections
-- The module finds content between matching instances of the same hook,
* Notes: Example usage: {{#invoke:CodeToText|showSnippet|page=Module:Example|hook=⭐}}; Supports emoji hooks like 🪝, 📌, 🔖, ⭐ for both inline and block content extraction
-- either on different lines or within the same line.
]]


local p = {}
local p = {}
Line 13: Line 13:
         return "Error: 'page' parameter is required"
         return "Error: 'page' parameter is required"
     end
     end
   
 
     local hook = frame.args.hook
     local hook = frame.args.hook
     local includeHook = frame.args.includeHook == 'true'
     if not hook then
    local debug = frame.args.debug == 'true'
        return "Error: 'hook' parameter is required"
   
     end
    -- 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)
     local titleObj = mw.title.new(pageName)
Line 32: Line 29:
     end
     end


     local lines = {}
    -- Try inline hooks first
     for line in content:gmatch("[^\r\n]+") do
     local inlineSnippet = content:match(hook .. "(.-)" .. hook)
         table.insert(lines, line)
    if inlineSnippet then
        return inlineSnippet
     end
 
    -- Find block hooks
    local s, e = content:find(hook, 1, true)
    if not s then
         return "Error: Need at least 2 instances of hook '" .. hook .. "' in '" .. pageName .. "'"
    end
 
    local s2, e2 = content:find(hook, e + 1, true)
    if not s2 then
        return "Error: Need at least 2 instances of hook '" .. hook .. "' in '" .. pageName .. "'"
     end
     end


    local snippet = {}
     -- Extract text between the two hooks, excluding the hook lines
    local debugInfo = {}
    local snippet = content:sub(e + 1, s2 - 1)
   
 
     -- If hook is provided, use it to extract the snippet
    -- Trim leading and trailing newlines
    if hook then
    if snippet:sub(1,1) == "\n" then
        -- First, check if any line contains multiple instances of the hook
        snippet = snippet:sub(2)
        local inlineHookFound = false
    end
       
    if snippet:sub(-1) == "\n" then
        for i, line in ipairs(lines) do
        snippet = snippet:sub(1, -2)
            -- 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
                   
                    if debug then
                        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)
                   
                    if includeHook then
                        extractedContent = hook .. extractedContent .. hook
                    end
                   
                    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
                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)
                    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
           
            if #hookPositions < 2 then
                local errorMsg = "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
           
            -- Extract content between first two hook instances
            local startLine = hookPositions[1]
            local endLine = hookPositions[2]
           
            local startIndex = includeHook and startLine or startLine + 1
            local endIndex = includeHook and endLine or endLine - 1
           
            for i = startIndex, endIndex do
                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
    else
        -- Fallback to line number-based extraction
        for i = fromLine, math.min(toLine, #lines) do
            table.insert(snippet, lines[i])
        end
     end
     end


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


return p
return p

Latest revision as of 02:56, 25 August 2025

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

--[[
* Name: CodeToText
* Author: Mark W. Datysgeld
* Description: Utility for extracting content snippets from wiki pages using emoji hook markers placed at the beginning and end of desired content sections
* Notes: Example usage: {{#invoke:CodeToText|showSnippet|page=Module:Example|hook=⭐}}; Supports emoji hooks like 🪝, 📌, 🔖, ⭐ for both inline and block content extraction
]]

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
    if not hook then
        return "Error: 'hook' parameter is required"
    end

    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

    -- Try inline hooks first
    local inlineSnippet = content:match(hook .. "(.-)" .. hook)
    if inlineSnippet then
        return inlineSnippet
    end

    -- Find block hooks
    local s, e = content:find(hook, 1, true)
    if not s then
        return "Error: Need at least 2 instances of hook '" .. hook .. "' in '" .. pageName .. "'"
    end

    local s2, e2 = content:find(hook, e + 1, true)
    if not s2 then
        return "Error: Need at least 2 instances of hook '" .. hook .. "' in '" .. pageName .. "'"
    end

    -- Extract text between the two hooks, excluding the hook lines
    local snippet = content:sub(e + 1, s2 - 1)

    -- Trim leading and trailing newlines
    if snippet:sub(1,1) == "\n" then
        snippet = snippet:sub(2)
    end
    if snippet:sub(-1) == "\n" then
        snippet = snippet:sub(1, -2)
    end

    return snippet
end

return p