#! lua-5.0.exe -- Create an HTML table of content (TOC) from an HTML file. Made mostly for the Lua manual... -- -- Take two parameters: the file to process as input, the resulting file as output. -- -- The program extracts the hierarchical titles ( tags) and store them with their level. -- It will then output the list of titles in a hierarchical HTML list. -- -- Actually, it will also take the latest named link before each title, so the above list -- can be used to jump to the chosen level. -- -- Note that the input HTML file must follow this structure for the output to be accurate. -- I had to make minor, invisible edits to the original Lua manuals, -- to create anchors or to move them before the title. -- -- The result must be inserted by hand in the HTML file. If used in a separated page, -- you must add the destination page name to the links. -- -- by Philippe Lhoste http://Phi.Lho.free.fr -- v. 1.2 -- 2004/04/22 -- Conversion to Lua 5.0 -- v. 1.1 -- 2003/05/20 -- Output of TOC -- v. 1.0 -- 2002/07/26 -- Initial code, extraction of data filenameIn = (arg and arg[1]) or "-" -- If absent, use standard input filenameOut = (arg and arg[2]) or "-" -- If absent, use standard output tocList = {} --lineNumber = 0 refNumber = 0 prevRef = "" prevLevel = 0 -- Extract useful information from the given line. function ProcessLine(line) if line == nil then return nil end -- lineNumber = lineNumber + 1 -- Remove tags other than those we are looking for. -- Replace the interesting tags by control chars, remove all other tags, -- and restore the control chars to the corresponding tags. line = string.gsub(line, "<[Hh]", "\1") line = string.gsub(line, "", "\4") line = string.gsub(line, "<[^>]->", "") line = string.gsub(line, "\1", "") local startRef, endRef, level, ref, title local tocData = {} -- Capture latest referenced string (by a tag) of the line endRef = 0 repeat startRef, endRef, ref = string.find(line, [[.*]], endRef + 1) if ref ~= nil then prevRef = ref end until startRef == nil -- Remove the anchors line = string.gsub(line, "]+>", "") line = string.gsub(line, "", "") -- Search if the line has a title ( tag, up to level 4) _, _, level, title = string.find(line, [[<[Hh]([1234])>([^<]*)]], 1) if level ~= nil then -- No need to loop to search another title in the line, -- unless the HTML is very sloppy... refNumber = refNumber + 1 tocData = { level = level, ref = prevRef, title = title } tocList[refNumber] = tocData end return true end -- Output an element of table of content. function OutputTOC(el) local level, nLevel level = el.level nLevel = tonumber(level) while nLevel > prevLevel do io.write"
    \n" nLevel = nLevel - 1 end while nLevel < prevLevel do io.write"
\n" nLevel = nLevel + 1 end prevLevel = tonumber(level) io.write([[
  • ]] .. el.title .. [[]] .. "\n") end -- Process the input file function ProcessFile() local fI, fO if filenameIn ~= '-' then fI = io.open(filenameIn, "r") if fI == nil then return false, "open r " .. filenameIn end else fI = io.stdin end if filenameOut ~= '-' then fO = io.open(filenameOut, "w") if fO == nil then return false, "open w " .. filenameOut end io.output(fO) end -- Loop on the lines and add any tag to the tocList table -- Note that these titles must be on the same line, no on one line and the title on the next... for line in fI:lines() do ProcessLine(line) end -- Build the table of content io.write([[

    0 - Contents

    ]]) for i, elements in ipairs(tocList) do OutputTOC(elements) end while prevLevel > 0 do io.write"\n" prevLevel = prevLevel - 1 end io.write"\n
    \n" if filenameIn ~= '-' then fI:close() end if filenameOut ~= '-' then io.output() fO:close() end return true, nil end result, op = ProcessFile() if not result then io.stderr:write("Error on operation : " .. (op or 'nil') .. '\n') else io.stderr:write("Done !\n") end