diff options
Diffstat (limited to 'scripts/lua/mason-scripts/markdown.lua')
| -rw-r--r-- | scripts/lua/mason-scripts/markdown.lua | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/scripts/lua/mason-scripts/markdown.lua b/scripts/lua/mason-scripts/markdown.lua new file mode 100644 index 00000000..bc20fe3f --- /dev/null +++ b/scripts/lua/mason-scripts/markdown.lua @@ -0,0 +1,93 @@ +local path = require "mason-core.path" +local _ = require "mason-core.functional" +local script_utils = require "mason-scripts.utils" +local fs = require "mason-core.fs" + +local M = {} + +---Direct context access syntax (e.g. "{{ value }}" or "{{ nested.value }}") +---@param context table<string, any> +---@param str string +local prop_interpolate = _.curryN(function(context, str) + return _.gsub("{{%s?([%w_%.0-9]+)%s?}}", function(key) + return vim.tbl_get(context, unpack(_.split("%.", key))) + end, str) +end, 2) + +local TEMPLATE_GLOBALS = { + _ = _, + url = function(url) + return ("[%s](%s)"):format(url, url) + end, + link = function(heading) + -- TODO turn heading into valid string, not needed for now + return ("[%s](#%s)"):format(heading, heading) + end, + list = _.compose(_.join "\n", _.map(_.format "- %s")), + join = _.curryN(function(items, delim) + return _.join(delim, items) + end, 2), + each = _.curryN(function(items, format) + local formatter = _.cond { + { _.is "function", _.identity }, + { + _.is "string", + function(template) + return function(item) + return prop_interpolate({ it = item }, template) + end + end, + }, + }(format) + return _.map(formatter, items) + end, 2), + render_each = _.curryN(function(items, template_file) + return _.map(M.render(template_file), items) + end, 2), +} + +---Expression syntax (e.g. "{% "hello world" %}" or "{% join({"One", "Two"}), "\n" %}") +---@param context table<string, any> +---@param str string +local expr_interpolate = _.curryN(function(context, str) + return _.gsub( + [[{%%%s?([%w%-_%.0-9%(%)%[%]%s%+%*,"/\|=%{%}]+)%s?%%}]], -- giggity + function(expr) + local eval_result = + setfenv(loadstring(("return %s"):format(expr)), setmetatable(TEMPLATE_GLOBALS, { __index = context }))() + + if type(eval_result) == "table" then + -- expressions may return tables for convenience reasons + return _.join("", eval_result) + else + return eval_result + end + end, + str + ) +end, 2) + +local header_interpolate = _.curryN(function(context, str) + return _.gsub([[{#%s?([%w%s_%-%.0-9/"]+)%s?#}]], function(header) + setfenv(loadstring(header), { + include = function(file) + local mod = require(("mason-scripts.templates.%s"):format(file)) + for k, v in pairs(mod) do + context[k] = v + end + end, + })() + return "" + end, str) +end, 2) + +---@param template_file string +---@param context table<string, string> +M.render = _.curryN(function(template_file, context) + local template = fs.sync.read_file(script_utils.rel_path(path.concat { "templates", template_file })) + local interpolate = _.compose(prop_interpolate(context), expr_interpolate(context), header_interpolate(context)) + local formatted_template = interpolate(template) + return formatted_template +end, 2) + +return M |
