feat(launcher): cache manifest.launcher.md per module on init
manifest_loader.load_for(id) reads <install>/modules/<id>/
manifest.launcher.md via engine.module.read_file, runs the JSON
frontmatter through frontmatter.parse, and pre-parses the body via
markdown.parse. Cached on the shared ctx so the detail-panel render
loop does not pay the parse cost per frame. Missing files degrade to
{_missing=true} and the list falls back to the module's name/id.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
12
init.lua
12
init.lua
@@ -5,7 +5,8 @@ local depf = require("lib-management.dep-fetcher")
|
|||||||
-- resolves declared lib-deps, so multi-file modules use dofile +
|
-- resolves declared lib-deps, so multi-file modules use dofile +
|
||||||
-- engine.module.dir_of.
|
-- engine.module.dir_of.
|
||||||
local MODULE_DIR = engine.module.dir_of("lib-management.launcher")
|
local MODULE_DIR = engine.module.dir_of("lib-management.launcher")
|
||||||
local fsm = dofile(MODULE_DIR .. "/fsm.lua")
|
local fsm = dofile(MODULE_DIR .. "/fsm.lua")
|
||||||
|
local manifest_loader = dofile(MODULE_DIR .. "/manifest_loader.lua")
|
||||||
|
|
||||||
local function require_panel(name)
|
local function require_panel(name)
|
||||||
return dofile(MODULE_DIR .. "/panels/" .. name .. ".lua")
|
return dofile(MODULE_DIR .. "/panels/" .. name .. ".lua")
|
||||||
@@ -199,6 +200,15 @@ function init(ctx)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- L.3: load + cache manifest.launcher.md for each module. Missing
|
||||||
|
-- files degrade gracefully (meta._missing=true) so the list-panel
|
||||||
|
-- falls back to name/id.
|
||||||
|
for _, entry in ipairs(ctx_panels.module_entries) do
|
||||||
|
local meta, blocks = manifest_loader.load_for(entry.id)
|
||||||
|
ctx_panels.manifest_cache[entry.id] = { meta = meta, blocks = blocks }
|
||||||
|
entry.summary = meta.summary
|
||||||
|
end
|
||||||
|
|
||||||
local wy, hy = engine.render.measure_text(YES_LABEL, FONT_BUTTON)
|
local wy, hy = engine.render.measure_text(YES_LABEL, FONT_BUTTON)
|
||||||
local wn, hn = engine.render.measure_text(NO_LABEL, FONT_BUTTON)
|
local wn, hn = engine.render.measure_text(NO_LABEL, FONT_BUTTON)
|
||||||
local qbtn_w = math.max(wy, wn) + 2 * PAD_X
|
local qbtn_w = math.max(wy, wn) + 2 * PAD_X
|
||||||
|
|||||||
31
manifest_loader.lua
Normal file
31
manifest_loader.lua
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
local fm
|
||||||
|
|
||||||
|
local function ensure_deps()
|
||||||
|
if not fm then
|
||||||
|
fm = dofile(engine.module.dir_of("lib-management.launcher") .. "/frontmatter.lua")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns:
|
||||||
|
-- meta = { summary, description_md, author, tags, teaser_images,
|
||||||
|
-- carousel_interval_seconds, ... }
|
||||||
|
-- body_blocks = output of markdown.parse(body) — pre-parsed for cache reuse
|
||||||
|
-- On any failure (file missing, parse error): meta = {}, body_blocks = {}.
|
||||||
|
function M.load_for(module_id)
|
||||||
|
ensure_deps()
|
||||||
|
local content, err = engine.module.read_file(module_id, "manifest.launcher.md")
|
||||||
|
if not content then
|
||||||
|
return { _missing = true, _err = err }, {}
|
||||||
|
end
|
||||||
|
local meta, body, perr = fm.parse(content)
|
||||||
|
if not meta then
|
||||||
|
return { _missing = false, _err = perr }, {}
|
||||||
|
end
|
||||||
|
local md = dofile(engine.module.dir_of("lib-management.launcher") .. "/markdown.lua")
|
||||||
|
local blocks = md.parse(body)
|
||||||
|
return meta, blocks
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
Reference in New Issue
Block a user