handlers/render.lua

Sun, 06 Sep 2020 22:12:52 +0300

author
Tuomo Valkonen <tuomov@iki.fi>
date
Sun, 06 Sep 2020 22:12:52 +0300
changeset 35
2f927eae429b
parent 30
3ac53da03439
child 42
260f867d46c0
permissions
-rwxr-xr-x

Don't auto-create directories that will be empty


--@module handlers.render

local handlers_render={}

local ltp=require('ltp.template')
local markdown=require('markdown')
local config=require('config')
local path=require('mypath')
local filecache=require('filecache')
local log=require('log')
local dependency=require('dependency')
local pandoc=require('pandoc')
local markdown_it=require('markdown_it')
local err=require('err')

--
-- Phase 1: load & markup
--

function handlers_render.phase1(file, env)
    local f = io.open(path.join(env.paths.src, file), 'r')
    local data = nil
    local in_meta = false
    local linenum=1
    local meta = {}
    
    for l in f:lines() do
        if (linenum==1 or in_meta) and string.match(l, config.meta_marker) then
            in_meta = not in_meta
        elseif in_meta then
            local key, val = string.match(l, "%s*([^:]*)%s*:%s*(.*)%s*")
            if key and val then
                -- very primitive quoting, primarily as a hack to
                -- not need converting my files that much from Webgen.
                local val_unq=string.match(val, '^"(.*)"$')
                meta[key] = val_unq or val
            else
                err.file_pos(file, linenum, "meta data syntax error: " .. l)
            end
        else
            if data then
                data = data.."\n"..l
            else
                data=l
            end
        end
        linenum = linenum+1
    end
    
    log.log("Load "..file.."\n")
    
    f:close()

    local destination
    if meta.destination then
        destination=path.join(path.dirname(file), meta.destination)
    else
        -- If the file has two extensions, then only remove last extension.
        -- Otherwise replace extension with .html.
        destination=path.rmext(file)
        base=path.rmext(destination)
        if base==destination then
            destination = destination .. ".html"
        end
    end

    local page={
        data=data,
        meta=meta,
        destination=destination,
        file=file,
    }
    
    env.pages[file]=page
end

function handlers_render.process_lua(template, env)
    env=table.join(env, {env=env}) -- TODO: should use __index
    --return ltp.render(nil, 1, template, env, {}, "<%", "%>", {})
    return ltp.render_template(template, "<%", "%>", 
                               ltp.merge_index(env, _G))
end

function handlers_render.env_for(file, env, path_prefix)
    local newenv=table.copy(env)
    
    newenv.base_url=path.to_root(file)
    newenv.path_prefix=(path_prefix or "")
    newenv.page=env.pages[file]
    
    return newenv
end

function handlers_render.render(file, env, path_prefix, renderer)
    local data=env.pages[file].data
    if data then
        local newenv=handlers_render.env_for(file, env, path_prefix)
        local data2=handlers_render.process_lua(data, newenv)
        meta = env.pages[file].meta
        if renderer == "markdown-it" then
            return markdown_it.markdown(data2, env)
        elseif renderer == "pandoc" then
            return pandoc.pandoc(data2)
        elseif renderer == "lua-markdown" then
            return markdown(data2)
        elseif renderer == "none" then
            return data2
        else
            error('Unknown renderer')
        end
    end
end

function handlers_render.phase2(file, env)
    local page=env.pages[file]
    local src = path.join(env.paths.src, file)
    local dst = path.join(env.paths.dst, page.destination)
    local tmpl = path.join(env.paths.tmpl,
                           page.meta.template or "page.template")
    renderer = page.meta.renderer or "markdown-it"

    local deps = {src}
    
    local build=page.meta.always_build
    if not build then
        if page.meta.dependencies then
            for p, _ in pairs(env.pages) do
                if string.match(p, page.meta.dependencies) then
                    table.insert(deps, path.join(env.paths.src, p))
                end
            end
        end
        table.insert(deps, tmpl)
        if renderer=="markdown-it" then
            markdown_it.add_deps(deps, env)
        end
        build=dependency.simple_update_check(dst, deps)
    end
    
    if build then
        log.log("Render "..file.."\n")
        local content=handlers_render.render(file, env, page.meta, renderer)
        local page_template=filecache.get(tmpl)

        local newenv=table.join({content=content}, handlers_render.env_for(file, env))
        local data2=handlers_render.process_lua(page_template, newenv)
        
        log.log("Write "..page.destination.."\n")
        local f=io.openX(dst, "w")
        f:write(data2)
    end
end

return handlers_render

mercurial