#include
#include
#include
#include
struct membuffer {
char* data;
size_t asize;
size_t size;
};
static int membuf_init(struct membuffer* buf, MD_SIZE new_asize) {
buf->size = 0;
buf->asize = new_asize;
buf->data = malloc(buf->asize);
if (buf->data == NULL) {
return -1;
}
return 0;
}
static void membuf_exit(struct membuffer* buf) {
if (buf->data) {
free(buf->data);
}
}
static int membuf_grow(struct membuffer* buf, size_t new_asize) {
buf->data = realloc(buf->data, new_asize);
if (buf->data == NULL) {
return -1;
}
buf->asize = new_asize;
return 0;
}
static void membuf_append(struct membuffer* buf, const char* data, MD_SIZE size) {
if (buf->asize < buf->size + size) {
membuf_grow(buf, buf->size + buf->size / 2 + size);
}
memcpy(buf->data + buf->size, data, size);
buf->size += size;
}
static void process_output(const MD_CHAR* text, MD_SIZE size, void* userdata) {
membuf_append((struct membuffer*)userdata, text, size);
}
static int md2html(lua_State* lua) {
size_t mdlen = 0;
const char* mdstr = luaL_checklstring(lua, 1, &mdlen);
struct membuffer buf_out = {0};
if (membuf_init(&buf_out, (MD_SIZE)(mdlen + mdlen / 8 + 64)) < 0) {
lua_pushnil(lua);
lua_pushliteral(lua, "could not allocate output buffer!");
return 2;
}
int p_flags = MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS | MD_FLAG_UNDERLINE | MD_FLAG_NOHTMLBLOCKS | MD_DIALECT_COMMONMARK | MD_DIALECT_GITHUB;
int r_flags = 0;
int ret = md_html(mdstr, (MD_SIZE)mdlen, process_output, (void*)&buf_out, p_flags, r_flags);
if (ret != 0) {
lua_pushnil(lua);
lua_pushliteral(lua, "could not convert markdown to html!");
membuf_exit(&buf_out);
return 2;
}
lua_pushlstring(lua, buf_out.data, buf_out.size);
membuf_exit(&buf_out);
return 1;
}
int luaopen(md4c, lua_State* lua) {
static const luaL_Reg funcs[] = {
{"md2html", md2html},
{NULL, NULL}
};
lua_newtable(lua);
luaL_setfuncs(lua, funcs, 0);
return 1;
}