From fb3e87a9e3059111d355bd21f955c55575f3b881 Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 26 Apr 2024 17:31:42 +0200 Subject: [PATCH] Added the ability to script the rendering of the MarkdownRenderer. Also added a new render() method equivalent to render_to_html(). --- modules/web/config.py | 1 + modules/web/html/markdown_renderer.cpp | 1095 +++++++++++++++++++++++- modules/web/html/markdown_renderer.h | 201 +++++ modules/web/register_types.cpp | 1 + 4 files changed, 1297 insertions(+), 1 deletion(-) diff --git a/modules/web/config.py b/modules/web/config.py index afe39e8a1..5fbf650c1 100644 --- a/modules/web/config.py +++ b/modules/web/config.py @@ -63,6 +63,7 @@ def get_doc_classes(): "BBCodeParser", "MarkdownRenderer", + "MarkdownRendererCustomRendererCallback", "StaticWebPage", "StaticWebPageFile", diff --git a/modules/web/html/markdown_renderer.cpp b/modules/web/html/markdown_renderer.cpp index cc0d4358a..dc78a77f5 100644 --- a/modules/web/html/markdown_renderer.cpp +++ b/modules/web/html/markdown_renderer.cpp @@ -38,6 +38,259 @@ #include "./libs/hoedown/html.h" #include "core/object/object.h" +///// ======== MarkdownRendererCustomRendererCallback ======== + +MarkdownRendererCustomRendererCallback::CallbackType MarkdownRendererCustomRendererCallback::get_callback_type() const { + return _callback_type; +} +void MarkdownRendererCustomRendererCallback::set_callback_type(const CallbackType val) { + _callback_type = val; +} + +String MarkdownRendererCustomRendererCallback::get_text() const { + return _text; +} +void MarkdownRendererCustomRendererCallback::set_text(const String &val) { + _text = val; +} + +String MarkdownRendererCustomRendererCallback::get_lang() const { + return _lang; +} +void MarkdownRendererCustomRendererCallback::set_lang(const String &val) { + _lang = val; +} + +String MarkdownRendererCustomRendererCallback::get_content() const { + return _content; +} +void MarkdownRendererCustomRendererCallback::set_content(const String &val) { + _content = val; +} + +int MarkdownRendererCustomRendererCallback::get_level() const { + return _level; +} +void MarkdownRendererCustomRendererCallback::set_level(const int val) { + _level = val; +} + +int MarkdownRendererCustomRendererCallback::get_list_flags() const { + return _list_flags; +} +void MarkdownRendererCustomRendererCallback::set_list_flags(const int val) { + _list_flags = val; +} + +int MarkdownRendererCustomRendererCallback::get_table_flags() const { + return _table_flags; +} +void MarkdownRendererCustomRendererCallback::set_table_flags(const int val) { + _table_flags = val; +} + +String MarkdownRendererCustomRendererCallback::get_link() const { + return _link; +} +void MarkdownRendererCustomRendererCallback::set_link(const String &val) { + _link = val; +} + +MarkdownRendererCustomRendererCallback::AutolinkType MarkdownRendererCustomRendererCallback::get_auto_link_type() const { + return _auto_link_type; +} +void MarkdownRendererCustomRendererCallback::set_auto_link_type(const AutolinkType val) { + _auto_link_type = val; +} + +String MarkdownRendererCustomRendererCallback::get_title() const { + return _title; +} +void MarkdownRendererCustomRendererCallback::set_title(const String &val) { + _title = val; +} + +String MarkdownRendererCustomRendererCallback::get_alt() const { + return _alt; +} +void MarkdownRendererCustomRendererCallback::set_alt(const String &val) { + _alt = val; +} + +uint32_t MarkdownRendererCustomRendererCallback::get_num() const { + return _num; +} +void MarkdownRendererCustomRendererCallback::set_num(const uint32_t val) { + _num = val; +} + +int MarkdownRendererCustomRendererCallback::get_display_mode() const { + return _display_mode; +} +void MarkdownRendererCustomRendererCallback::set_display_mode(const int val) { + _display_mode = val; +} + +int MarkdownRendererCustomRendererCallback::get_inline_render() const { + return _inline_render; +} +void MarkdownRendererCustomRendererCallback::set_inline_render(const int val) { + _inline_render = val; +} + +String MarkdownRendererCustomRendererCallback::get_result() const { + return _result; +} +void MarkdownRendererCustomRendererCallback::set_result(const String &val) { + _result = val; +} + +int MarkdownRendererCustomRendererCallback::get_result_code() const { + return _result_code; +} +void MarkdownRendererCustomRendererCallback::set_result_code(const int val) { + _result_code = val; +} + +MarkdownRendererCustomRendererCallback::MarkdownRendererCustomRendererCallback() { + _callback_type = CALLBACK_BLOCKCODE; + + _level = 0; + _list_flags = 0; + _table_flags = 0; + + _auto_link_type = AUTOLINK_TYPE_NONE; + + _num = 0; + _display_mode = 0; + _inline_render = 0; + + _result_code = 1; +} +MarkdownRendererCustomRendererCallback::~MarkdownRendererCustomRendererCallback() { +} + +void MarkdownRendererCustomRendererCallback::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_callback_type"), &MarkdownRendererCustomRendererCallback::get_callback_type); + ClassDB::bind_method(D_METHOD("set_callback_type", "val"), &MarkdownRendererCustomRendererCallback::set_callback_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "callback_type"), "set_callback_type", "get_callback_type"); + + ClassDB::bind_method(D_METHOD("get_text"), &MarkdownRendererCustomRendererCallback::get_text); + ClassDB::bind_method(D_METHOD("set_text", "val"), &MarkdownRendererCustomRendererCallback::set_text); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); + + ClassDB::bind_method(D_METHOD("get_lang"), &MarkdownRendererCustomRendererCallback::get_lang); + ClassDB::bind_method(D_METHOD("set_lang", "val"), &MarkdownRendererCustomRendererCallback::set_lang); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "lang"), "set_lang", "get_lang"); + + ClassDB::bind_method(D_METHOD("get_content"), &MarkdownRendererCustomRendererCallback::get_content); + ClassDB::bind_method(D_METHOD("set_content", "val"), &MarkdownRendererCustomRendererCallback::set_content); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "content"), "set_content", "get_content"); + + ClassDB::bind_method(D_METHOD("get_level"), &MarkdownRendererCustomRendererCallback::get_level); + ClassDB::bind_method(D_METHOD("set_level", "val"), &MarkdownRendererCustomRendererCallback::set_level); + ADD_PROPERTY(PropertyInfo(Variant::INT, "level"), "set_level", "get_level"); + + ClassDB::bind_method(D_METHOD("get_list_flags"), &MarkdownRendererCustomRendererCallback::get_list_flags); + ClassDB::bind_method(D_METHOD("set_list_flags", "val"), &MarkdownRendererCustomRendererCallback::set_list_flags); + ADD_PROPERTY(PropertyInfo(Variant::INT, "list_flags", PROPERTY_HINT_FLAGS, "Ordered,LI Block"), "set_list_flags", "get_list_flags"); + + ClassDB::bind_method(D_METHOD("get_table_flags"), &MarkdownRendererCustomRendererCallback::get_table_flags); + ClassDB::bind_method(D_METHOD("set_table_flags", "val"), &MarkdownRendererCustomRendererCallback::set_table_flags); + ADD_PROPERTY(PropertyInfo(Variant::INT, "table_flags", PROPERTY_HINT_FLAGS, "Align Left,Align Right,Align Center"), "set_table_flags", "get_table_flags"); + + ClassDB::bind_method(D_METHOD("get_link"), &MarkdownRendererCustomRendererCallback::get_link); + ClassDB::bind_method(D_METHOD("set_link", "val"), &MarkdownRendererCustomRendererCallback::set_link); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "link"), "set_link", "get_link"); + + ClassDB::bind_method(D_METHOD("get_auto_link_type"), &MarkdownRendererCustomRendererCallback::get_auto_link_type); + ClassDB::bind_method(D_METHOD("set_auto_link_type", "val"), &MarkdownRendererCustomRendererCallback::set_auto_link_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "auto_link_type", PROPERTY_HINT_ENUM, "None,Normal,EMail"), "set_auto_link_type", "get_auto_link_type"); + + ClassDB::bind_method(D_METHOD("get_title"), &MarkdownRendererCustomRendererCallback::get_title); + ClassDB::bind_method(D_METHOD("set_title", "val"), &MarkdownRendererCustomRendererCallback::set_title); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title"); + + ClassDB::bind_method(D_METHOD("get_alt"), &MarkdownRendererCustomRendererCallback::get_alt); + ClassDB::bind_method(D_METHOD("set_alt", "val"), &MarkdownRendererCustomRendererCallback::set_alt); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "alt"), "set_alt", "get_alt"); + + ClassDB::bind_method(D_METHOD("get_num"), &MarkdownRendererCustomRendererCallback::get_num); + ClassDB::bind_method(D_METHOD("set_num", "val"), &MarkdownRendererCustomRendererCallback::set_num); + ADD_PROPERTY(PropertyInfo(Variant::INT, "num"), "set_num", "get_num"); + + ClassDB::bind_method(D_METHOD("get_display_mode"), &MarkdownRendererCustomRendererCallback::get_display_mode); + ClassDB::bind_method(D_METHOD("set_display_mode", "val"), &MarkdownRendererCustomRendererCallback::set_display_mode); + ADD_PROPERTY(PropertyInfo(Variant::INT, "display_mode"), "set_display_mode", "get_display_mode"); + + ClassDB::bind_method(D_METHOD("get_inline_render"), &MarkdownRendererCustomRendererCallback::get_inline_render); + ClassDB::bind_method(D_METHOD("set_inline_render", "val"), &MarkdownRendererCustomRendererCallback::set_inline_render); + ADD_PROPERTY(PropertyInfo(Variant::INT, "inline_render"), "set_inline_render", "get_inline_render"); + + ClassDB::bind_method(D_METHOD("get_result"), &MarkdownRendererCustomRendererCallback::get_result); + ClassDB::bind_method(D_METHOD("set_result", "val"), &MarkdownRendererCustomRendererCallback::set_result); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "result"), "set_result", "get_result"); + + ClassDB::bind_method(D_METHOD("get_result_code"), &MarkdownRendererCustomRendererCallback::get_result_code); + ClassDB::bind_method(D_METHOD("set_result_code", "val"), &MarkdownRendererCustomRendererCallback::set_result_code); + ADD_PROPERTY(PropertyInfo(Variant::INT, "result_code"), "set_result_code", "get_result_code"); + + BIND_ENUM_CONSTANT(CALLBACK_BLOCKCODE); + BIND_ENUM_CONSTANT(CALLBACK_BLOCKQUOTE); + BIND_ENUM_CONSTANT(CALLBACK_HEADER); + BIND_ENUM_CONSTANT(CALLBACK_HRULE); + BIND_ENUM_CONSTANT(CALLBACK_LIST); + BIND_ENUM_CONSTANT(CALLBACK_LISTITEM); + BIND_ENUM_CONSTANT(CALLBACK_PARAGRAPH); + BIND_ENUM_CONSTANT(CALLBACK_TABLE); + BIND_ENUM_CONSTANT(CALLBACK_TABLE_HEADER); + BIND_ENUM_CONSTANT(CALLBACK_TABLE_BODY); + BIND_ENUM_CONSTANT(CALLBACK_TABLE_ROW); + BIND_ENUM_CONSTANT(CALLBACK_TABLE_CELL); + BIND_ENUM_CONSTANT(CALLBACK_FOOTNOTES); + BIND_ENUM_CONSTANT(CALLBACK_FOOTNOTE_DEF); + BIND_ENUM_CONSTANT(CALLBACK_BLOCKHTML); + + BIND_ENUM_CONSTANT(CALLBACK_AUTOLINK); + BIND_ENUM_CONSTANT(CALLBACK_CODESPAN); + BIND_ENUM_CONSTANT(CALLBACK_DOUBLE_EMPHASIS); + BIND_ENUM_CONSTANT(CALLBACK_EMPHASIS); + BIND_ENUM_CONSTANT(CALLBACK_UNDERLINE); + BIND_ENUM_CONSTANT(CALLBACK_HIGHLIGHT); + BIND_ENUM_CONSTANT(CALLBACK_QUOTE); + BIND_ENUM_CONSTANT(CALLBACK_IMAGE); + BIND_ENUM_CONSTANT(CALLBACK_LINEBREAK); + BIND_ENUM_CONSTANT(CALLBACK_LINK); + + BIND_ENUM_CONSTANT(CALLBACK_TRIPLE_EMPHASIS); + BIND_ENUM_CONSTANT(CALLBACK_STRIKETHROUGH); + BIND_ENUM_CONSTANT(CALLBACK_SUPERSCRIPT); + BIND_ENUM_CONSTANT(CALLBACK_FOOTNOTE_REF); + BIND_ENUM_CONSTANT(CALLBACK_MATH); + BIND_ENUM_CONSTANT(CALLBACK_RAW_HTML); + + BIND_ENUM_CONSTANT(CALLBACK_ENTITY); + BIND_ENUM_CONSTANT(CALLBACK_NORMAL_TEXT); + + BIND_ENUM_CONSTANT(CALLBACK_DOC_HEADER); + BIND_ENUM_CONSTANT(CALLBACK_DOC_FOOTER); + + BIND_ENUM_CONSTANT(LIST_FLAG_ORDERED); + BIND_ENUM_CONSTANT(LIST_FLAG_LI_BLOCK); + + BIND_ENUM_CONSTANT(TABLE_FLAG_ALIGN_LEFT); + BIND_ENUM_CONSTANT(TABLE_FLAG_ALIGN_RIGHT); + BIND_ENUM_CONSTANT(TABLE_FLAG_ALIGN_CENTER); + BIND_ENUM_CONSTANT(TABLE_FLAG_ALIGNMASK); + BIND_ENUM_CONSTANT(TABLE_FLAG_HEADER); + + BIND_ENUM_CONSTANT(AUTOLINK_TYPE_NONE); + BIND_ENUM_CONSTANT(AUTOLINK_TYPE_NORMAL); + BIND_ENUM_CONSTANT(AUTOLINK_TYPE_EMAIL); +} + +///// ======== MarkdownRenderer ======== + MarkdownRenderer::RenderType MarkdownRenderer::get_render_type() { return _render_type; } @@ -81,6 +334,10 @@ void MarkdownRenderer::set_toc_level(const int val) { } String MarkdownRenderer::render_to_html(const String &markdown) { + return render(markdown); +} + +String MarkdownRenderer::render(const String &markdown) { hoedown_renderer *renderer; switch (_render_type) { @@ -90,6 +347,9 @@ String MarkdownRenderer::render_to_html(const String &markdown) { case RENDER_TYPE_HTML_TOC: { renderer = hoedown_html_toc_renderer_new(_toc_level); } break; + case RENDERER_TYPE_CUSTOM: { + renderer = create_custom_hoedown_renderer(); + } break; default: { renderer = hoedown_html_renderer_new(static_cast(_html_flags), _toc_level); } break; @@ -160,7 +420,18 @@ String MarkdownRenderer::render_to_html(const String &markdown) { hoedown_buffer_free(html); hoedown_document_free(document); - hoedown_html_renderer_free(renderer); + + switch (_render_type) { + case RENDER_TYPE_HTML: + case RENDER_TYPE_HTML_TOC: { + hoedown_html_renderer_free(renderer); + } break; + case RENDERER_TYPE_CUSTOM: { + memfree(renderer); + } break; + default: { + } break; + } return html_str; } @@ -178,6 +449,76 @@ MarkdownRenderer::MarkdownRenderer() { MarkdownRenderer::~MarkdownRenderer() { } +hoedown_renderer *MarkdownRenderer::create_custom_hoedown_renderer() { + static const hoedown_renderer cb_custom = { + NULL, + + /* block level callbacks - NULL skips the block */ + MarkdownRenderer::hoedown_cb_blockcode, + MarkdownRenderer::hoedown_cb_blockquote, + MarkdownRenderer::hoedown_cb_header, + MarkdownRenderer::hoedown_cb_hrule, + MarkdownRenderer::hoedown_cb_list, + MarkdownRenderer::hoedown_cb_listitem, + MarkdownRenderer::hoedown_cb_paragraph, + MarkdownRenderer::hoedown_cb_table, + MarkdownRenderer::hoedown_cb_table_header, + MarkdownRenderer::hoedown_cb_table_body, + MarkdownRenderer::hoedown_cb_table_row, + MarkdownRenderer::hoedown_cb_table_cell, + MarkdownRenderer::hoedown_cb_footnotes, + MarkdownRenderer::hoedown_cb_footnote_def, + MarkdownRenderer::hoedown_cb_blockhtml, + + /* span level callbacks - NULL or return 0 prints the span verbatim */ + MarkdownRenderer::hoedown_cb_autolink, + MarkdownRenderer::hoedown_cb_codespan, + MarkdownRenderer::hoedown_cb_double_emphasis, + MarkdownRenderer::hoedown_cb_emphasis, + MarkdownRenderer::hoedown_cb_underline, + MarkdownRenderer::hoedown_cb_highlight, + MarkdownRenderer::hoedown_cb_quote, + MarkdownRenderer::hoedown_cb_image, + MarkdownRenderer::hoedown_cb_linebreak, + MarkdownRenderer::hoedown_cb_link, + MarkdownRenderer::hoedown_cb_triple_emphasis, + MarkdownRenderer::hoedown_cb_strikethrough, + MarkdownRenderer::hoedown_cb_superscript, + MarkdownRenderer::hoedown_cb_footnote_ref, + MarkdownRenderer::hoedown_cb_math, + MarkdownRenderer::hoedown_cb_raw_html, + + MarkdownRenderer::hoedown_cb_entity, + MarkdownRenderer::hoedown_cb_normal_text, + + MarkdownRenderer::hoedown_cb_doc_header, + MarkdownRenderer::hoedown_cb_doc_footer, + }; + + hoedown_custom_renderer_state *state; + hoedown_renderer *renderer; + + /* Prepare the state pointer */ + state = memnew(hoedown_custom_renderer_state); + memset(state, 0x0, sizeof(hoedown_custom_renderer_state)); + + state->self = this; + + /* Prepare the renderer */ + renderer = memnew(hoedown_renderer); + memcpy(renderer, &cb_custom, sizeof(hoedown_renderer)); + + renderer->opaque = state; + + return renderer; +} + +void MarkdownRenderer::renderer_callback(Ref data) { + call("_renderer_callback", data); +} +void MarkdownRenderer::_renderer_callback(Ref data) { +} + void MarkdownRenderer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_render_type"), &MarkdownRenderer::get_render_type); ClassDB::bind_method(D_METHOD("set_render_type", "val"), &MarkdownRenderer::set_render_type); @@ -204,9 +545,16 @@ void MarkdownRenderer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toc_level"), "set_toc_level", "get_toc_level"); ClassDB::bind_method(D_METHOD("render_to_html", "markdown"), &MarkdownRenderer::render_to_html); + ClassDB::bind_method(D_METHOD("render", "markdown"), &MarkdownRenderer::render); + + BIND_VMETHOD(MethodInfo("_renderer_callback", PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "MarkdownRendererCustomRendererCallback"))); + + ClassDB::bind_method(D_METHOD("renderer_callback", "data"), &MarkdownRenderer::renderer_callback); + ClassDB::bind_method(D_METHOD("_renderer_callback", "data"), &MarkdownRenderer::_renderer_callback); BIND_ENUM_CONSTANT(RENDER_TYPE_HTML); BIND_ENUM_CONSTANT(RENDER_TYPE_HTML_TOC); + BIND_ENUM_CONSTANT(RENDERER_TYPE_CUSTOM); BIND_ENUM_CONSTANT(HTML_FLAG_SKIP_HTML); BIND_ENUM_CONSTANT(HTML_FLAG_ESCAPE); @@ -231,3 +579,748 @@ void MarkdownRenderer::_bind_methods() { BIND_ENUM_CONSTANT(EXTENSION_DISABLE_INDENTED_CODE); }; + +/* block level callbacks - NULL skips the block */ +void MarkdownRenderer::hoedown_cb_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_BLOCKCODE); + if (text) { + cb->set_text(String::utf8((const char *)text->data, text->size)); + } + if (lang) { + cb->set_lang(String::utf8((const char *)lang->data, lang->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_BLOCKQUOTE); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_HEADER); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + cb->set_level(level); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_HRULE); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_LIST); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + cb->set_list_flags(flags); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_LISTITEM); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + cb->set_list_flags(flags); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_PARAGRAPH); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_table(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_TABLE); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_table_header(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_TABLE_HEADER); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_TABLE_BODY); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_table_row(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_TABLE_ROW); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_table_cell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_TABLE_CELL); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + cb->set_table_flags(flags); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_FOOTNOTES); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_FOOTNOTE_DEF); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + cb->set_num(num); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_blockhtml(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_BLOCKHTML); + if (text) { + cb->set_text(String::utf8((const char *)text->data, text->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} + +/* span level callbacks - NULL or return 0 prints the span verbatim */ +int MarkdownRenderer::hoedown_cb_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_AUTOLINK); + if (link) { + cb->set_link(String::utf8((const char *)link->data, link->size)); + } + cb->set_auto_link_type((MarkdownRendererCustomRendererCallback::AutolinkType)(int)type); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_CODESPAN); + if (text) { + cb->set_text(String::utf8((const char *)text->data, text->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_DOUBLE_EMPHASIS); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_EMPHASIS); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_UNDERLINE); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_HIGHLIGHT); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_QUOTE); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_IMAGE); + if (link) { + cb->set_link(String::utf8((const char *)link->data, link->size)); + } + if (title) { + cb->set_title(String::utf8((const char *)title->data, title->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_LINEBREAK); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_LINK); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + if (link) { + cb->set_link(String::utf8((const char *)link->data, link->size)); + } + if (title) { + cb->set_title(String::utf8((const char *)title->data, title->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_TRIPLE_EMPHASIS); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_STRIKETHROUGH); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_SUPERSCRIPT); + if (content) { + cb->set_content(String::utf8((const char *)content->data, content->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_footnote_ref(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_FOOTNOTE_REF); + cb->set_num(num); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_MATH); + if (text) { + cb->set_text(String::utf8((const char *)text->data, text->size)); + } + cb->set_display_mode(displaymode); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} +int MarkdownRenderer::hoedown_cb_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_RAW_HTML); + if (text) { + cb->set_text(String::utf8((const char *)text->data, text->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } + + return cb->get_result_code(); +} + +void MarkdownRenderer::hoedown_cb_entity(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_ENTITY); + if (text) { + cb->set_text(String::utf8((const char *)text->data, text->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_normal_text(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_NORMAL_TEXT); + if (text) { + cb->set_text(String::utf8((const char *)text->data, text->size)); + } + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} + +void MarkdownRenderer::hoedown_cb_doc_header(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_DOC_HEADER); + cb->set_inline_render(inline_render); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} +void MarkdownRenderer::hoedown_cb_doc_footer(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data) { + hoedown_custom_renderer_state *state = (hoedown_custom_renderer_state *)data->opaque; + MarkdownRenderer *self = (MarkdownRenderer *)state->self; + + Ref cb; + cb.instance(); + + cb->set_callback_type(MarkdownRendererCustomRendererCallback::CALLBACK_DOC_FOOTER); + cb->set_inline_render(inline_render); + + self->renderer_callback(cb); + + CharString cs = cb->get_result().utf8(); + + if (cs.length() > 0) { + hoedown_buffer_put(ob, (const uint8_t *)cs.get_data(), cs.length()); + } +} diff --git a/modules/web/html/markdown_renderer.h b/modules/web/html/markdown_renderer.h index 0234a4095..8def04ca0 100644 --- a/modules/web/html/markdown_renderer.h +++ b/modules/web/html/markdown_renderer.h @@ -36,6 +36,149 @@ #include "core/object/reference.h" +#include "libs/hoedown/document.h" + +// So there is no need to add ~20 virtual methods +class MarkdownRendererCustomRendererCallback : public Reference { + GDCLASS(MarkdownRendererCustomRendererCallback, Reference); + +public: + enum CallbackType { + CALLBACK_BLOCKCODE = 0, + CALLBACK_BLOCKQUOTE, + CALLBACK_HEADER, + CALLBACK_HRULE, + CALLBACK_LIST, + CALLBACK_LISTITEM, + CALLBACK_PARAGRAPH, + CALLBACK_TABLE, + CALLBACK_TABLE_HEADER, + CALLBACK_TABLE_BODY, + CALLBACK_TABLE_ROW, + CALLBACK_TABLE_CELL, + CALLBACK_FOOTNOTES, + CALLBACK_FOOTNOTE_DEF, + CALLBACK_BLOCKHTML, + + CALLBACK_AUTOLINK, + CALLBACK_CODESPAN, + CALLBACK_DOUBLE_EMPHASIS, + CALLBACK_EMPHASIS, + CALLBACK_UNDERLINE, + CALLBACK_HIGHLIGHT, + CALLBACK_QUOTE, + CALLBACK_IMAGE, + CALLBACK_LINEBREAK, + CALLBACK_LINK, + + CALLBACK_TRIPLE_EMPHASIS, + CALLBACK_STRIKETHROUGH, + CALLBACK_SUPERSCRIPT, + CALLBACK_FOOTNOTE_REF, + CALLBACK_MATH, + CALLBACK_RAW_HTML, + + CALLBACK_ENTITY, + CALLBACK_NORMAL_TEXT, + + CALLBACK_DOC_HEADER, + CALLBACK_DOC_FOOTER, + }; + + enum ListFlags { + LIST_FLAG_ORDERED = (1 << 0), + LIST_FLAG_LI_BLOCK = (1 << 1) + }; + + enum TableFlags { + TABLE_FLAG_ALIGN_LEFT = 1, + TABLE_FLAG_ALIGN_RIGHT = 2, + TABLE_FLAG_ALIGN_CENTER = 3, + TABLE_FLAG_ALIGNMASK = 3, + TABLE_FLAG_HEADER = 4 + }; + + enum AutolinkType { + AUTOLINK_TYPE_NONE = 0, /* used internally when it is not an autolink*/ + AUTOLINK_TYPE_NORMAL, /* normal http/http/ftp/mailto/etc link */ + AUTOLINK_TYPE_EMAIL /* e-mail link without explit mailto: */ + }; + + CallbackType get_callback_type() const; + void set_callback_type(const CallbackType val); + + String get_text() const; + void set_text(const String &val); + + String get_lang() const; + void set_lang(const String &val); + + String get_content() const; + void set_content(const String &val); + + int get_level() const; + void set_level(const int val); + + int get_list_flags() const; + void set_list_flags(const int val); + + int get_table_flags() const; + void set_table_flags(const int val); + + String get_link() const; + void set_link(const String &val); + + AutolinkType get_auto_link_type() const; + void set_auto_link_type(const AutolinkType val); + + String get_title() const; + void set_title(const String &val); + + String get_alt() const; + void set_alt(const String &val); + + uint32_t get_num() const; + void set_num(const uint32_t val); + + int get_display_mode() const; + void set_display_mode(const int val); + + int get_inline_render() const; + void set_inline_render(const int val); + + String get_result() const; + void set_result(const String &val); + + int get_result_code() const; + void set_result_code(const int val); + + MarkdownRendererCustomRendererCallback(); + virtual ~MarkdownRendererCustomRendererCallback(); + +protected: + static void _bind_methods(); + +protected: + CallbackType _callback_type; + + String _text; + String _lang; + String _content; + int _level; + int _list_flags; + int _table_flags; + String _link; + AutolinkType _auto_link_type; + String _title; + String _alt; + uint32_t _num; + int _display_mode; + int _inline_render; + + String _result; + int _result_code; +}; + class MarkdownRenderer : public Reference { GDCLASS(MarkdownRenderer, Reference); @@ -43,6 +186,7 @@ public: enum RenderType { RENDER_TYPE_HTML = 0, RENDER_TYPE_HTML_TOC = 1, + RENDERER_TYPE_CUSTOM = 2, }; enum HTMLFlags { @@ -92,11 +236,15 @@ public: void set_toc_level(const int val); String render_to_html(const String &markdown); + String render(const String &markdown); MarkdownRenderer(); virtual ~MarkdownRenderer(); protected: + void renderer_callback(Ref data); + virtual void _renderer_callback(Ref data); + static void _bind_methods(); RenderType _render_type; @@ -105,10 +253,63 @@ protected: int _max_nesting; int _toc_level; bool _use_smartypants; + +protected: + struct hoedown_custom_renderer_state { + void *self; + }; + + /* block level callbacks - NULL skips the block */ + static void hoedown_cb_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data); + static void hoedown_cb_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static void hoedown_cb_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data); + static void hoedown_cb_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data); + static void hoedown_cb_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data); + static void hoedown_cb_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data); + static void hoedown_cb_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static void hoedown_cb_table(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static void hoedown_cb_table_header(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static void hoedown_cb_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static void hoedown_cb_table_row(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static void hoedown_cb_table_cell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data); + static void hoedown_cb_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static void hoedown_cb_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data); + static void hoedown_cb_blockhtml(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + + /* span level callbacks - NULL or return 0 prints the span verbatim */ + static int hoedown_cb_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data); + static int hoedown_cb_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + static int hoedown_cb_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data); + static int hoedown_cb_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data); + static int hoedown_cb_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data); + static int hoedown_cb_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); + static int hoedown_cb_footnote_ref(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data); + static int hoedown_cb_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data); + static int hoedown_cb_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + + static void hoedown_cb_entity(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + static void hoedown_cb_normal_text(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + + static void hoedown_cb_doc_header(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data); + static void hoedown_cb_doc_footer(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data); + + hoedown_renderer *create_custom_hoedown_renderer(); }; VARIANT_ENUM_CAST(MarkdownRenderer::RenderType); VARIANT_ENUM_CAST(MarkdownRenderer::HTMLFlags); VARIANT_ENUM_CAST(MarkdownRenderer::MarkdownExtensions); +VARIANT_ENUM_CAST(MarkdownRendererCustomRendererCallback::CallbackType); +VARIANT_ENUM_CAST(MarkdownRendererCustomRendererCallback::ListFlags); +VARIANT_ENUM_CAST(MarkdownRendererCustomRendererCallback::TableFlags); +VARIANT_ENUM_CAST(MarkdownRendererCustomRendererCallback::AutolinkType); + #endif diff --git a/modules/web/register_types.cpp b/modules/web/register_types.cpp index b7d9b0767..3c3c26512 100644 --- a/modules/web/register_types.cpp +++ b/modules/web/register_types.cpp @@ -122,6 +122,7 @@ void register_web_types(ModuleRegistrationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class();