mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-27 14:17:37 +01:00
234 lines
9.5 KiB
C++
234 lines
9.5 KiB
C++
/*************************************************************************/
|
|
/* markdown_renderer.cpp */
|
|
/*************************************************************************/
|
|
/* This file is part of: */
|
|
/* PANDEMONIUM ENGINE */
|
|
/* https://github.com/Relintai/pandemonium_engine */
|
|
/*************************************************************************/
|
|
/* Copyright (c) 2022-present Péter Magyar. */
|
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
|
/* */
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
/* a copy of this software and associated documentation files (the */
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
/* the following conditions: */
|
|
/* */
|
|
/* The above copyright notice and this permission notice shall be */
|
|
/* included in all copies or substantial portions of the Software. */
|
|
/* */
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
/*************************************************************************/
|
|
|
|
#include "markdown_renderer.h"
|
|
|
|
#include "core/error/error_macros.h"
|
|
#include "core/log/logger.h"
|
|
#include "core/object/class_db.h"
|
|
|
|
#include "./libs/hoedown/html.h"
|
|
#include "core/object/object.h"
|
|
|
|
MarkdownRenderer::RenderType MarkdownRenderer::get_render_type() {
|
|
return _render_type;
|
|
}
|
|
void MarkdownRenderer::set_render_type(const MarkdownRenderer::RenderType val) {
|
|
_render_type = val;
|
|
}
|
|
|
|
int MarkdownRenderer::get_html_flags() {
|
|
return _html_flags;
|
|
}
|
|
void MarkdownRenderer::set_html_flags(const int val) {
|
|
_html_flags = val;
|
|
}
|
|
|
|
int MarkdownRenderer::get_markdown_extensions() {
|
|
return _markdown_extensions;
|
|
}
|
|
void MarkdownRenderer::set_markdown_extensions(const int val) {
|
|
_markdown_extensions = val;
|
|
}
|
|
|
|
int MarkdownRenderer::get_max_nesting() {
|
|
return _max_nesting;
|
|
}
|
|
void MarkdownRenderer::set_max_nesting(const int val) {
|
|
_max_nesting = val;
|
|
}
|
|
|
|
bool MarkdownRenderer::get_use_smartypants() {
|
|
return _use_smartypants;
|
|
}
|
|
void MarkdownRenderer::set_use_smartypants(const bool val) {
|
|
_use_smartypants = val;
|
|
}
|
|
|
|
int MarkdownRenderer::get_toc_level() {
|
|
return _toc_level;
|
|
}
|
|
void MarkdownRenderer::set_toc_level(const int val) {
|
|
_toc_level = val;
|
|
}
|
|
|
|
String MarkdownRenderer::render_to_html(const String &markdown) {
|
|
hoedown_renderer *renderer;
|
|
|
|
switch (_render_type) {
|
|
case RENDER_TYPE_HTML: {
|
|
renderer = hoedown_html_renderer_new(static_cast<hoedown_html_flags>(_html_flags), _toc_level);
|
|
} break;
|
|
case RENDER_TYPE_HTML_TOC: {
|
|
renderer = hoedown_html_toc_renderer_new(_toc_level);
|
|
} break;
|
|
default: {
|
|
renderer = hoedown_html_renderer_new(static_cast<hoedown_html_flags>(_html_flags), _toc_level);
|
|
} break;
|
|
}
|
|
|
|
int hoedown_ext_flags = 0;
|
|
|
|
if ((_markdown_extensions & EXTENSION_TABLES) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_TABLES;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_FENCED_CODE) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_FENCED_CODE;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_FOOTNOTES) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_FOOTNOTES;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_AUTOLINK) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_AUTOLINK;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_STRKIETHROUGH) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_STRIKETHROUGH;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_UNDERLINE) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_UNDERLINE;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_HIGHLIGHT) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_HIGHLIGHT;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_QUOTE) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_QUOTE;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_SUPERSCRIPT) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_SUPERSCRIPT;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_MATH) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_MATH;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_NO_INTRA_EMPHASIS) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_NO_INTRA_EMPHASIS;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_SPACE_HEADERS) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_SPACE_HEADERS;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_MATH_EXPLICIT) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_MATH_EXPLICIT;
|
|
}
|
|
if ((_markdown_extensions & EXTENSION_DISABLE_INDENTED_CODE) != 0) {
|
|
hoedown_ext_flags |= HOEDOWN_EXT_DISABLE_INDENTED_CODE;
|
|
}
|
|
|
|
hoedown_document *document = hoedown_document_new(renderer, static_cast<hoedown_extensions>(hoedown_ext_flags), _max_nesting);
|
|
|
|
hoedown_buffer *html = hoedown_buffer_new(16);
|
|
|
|
CharString csmd = markdown.utf8();
|
|
|
|
hoedown_document_render(document, html, reinterpret_cast<const uint8_t *>(csmd.get_data()), csmd.length());
|
|
|
|
String html_str = String::utf8(reinterpret_cast<const char *>(html->data), html->size);
|
|
|
|
if (_use_smartypants) {
|
|
CharString cshtml = html_str.utf8();
|
|
|
|
hoedown_html_smartypants(html, reinterpret_cast<const uint8_t *>(cshtml.get_data()), cshtml.length());
|
|
|
|
html_str = String::utf8(reinterpret_cast<const char *>(html->data), html->size);
|
|
}
|
|
|
|
hoedown_buffer_free(html);
|
|
hoedown_document_free(document);
|
|
hoedown_html_renderer_free(renderer);
|
|
|
|
return html_str;
|
|
}
|
|
|
|
MarkdownRenderer::MarkdownRenderer() {
|
|
_render_type = RENDER_TYPE_HTML;
|
|
_html_flags = 0;
|
|
//https://github.com/hoedown/hoedown/wiki/Popular-presets
|
|
_markdown_extensions = EXTENSION_TABLES | EXTENSION_FENCED_CODE | EXTENSION_AUTOLINK | EXTENSION_STRKIETHROUGH | EXTENSION_NO_INTRA_EMPHASIS;
|
|
_max_nesting = 16;
|
|
_toc_level = 0;
|
|
_use_smartypants = false;
|
|
}
|
|
|
|
MarkdownRenderer::~MarkdownRenderer() {
|
|
}
|
|
|
|
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);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_type", PROPERTY_HINT_ENUM, "HTML,HTML TOC"), "set_render_type", "get_render_type");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_html_flags"), &MarkdownRenderer::get_html_flags);
|
|
ClassDB::bind_method(D_METHOD("set_html_flags", "val"), &MarkdownRenderer::set_html_flags);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "html_flags", PROPERTY_HINT_FLAGS, "Skip HTML,Escape,Hard Wrap,Use XHTML"), "set_html_flags", "get_html_flags");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_markdown_extensions"), &MarkdownRenderer::get_markdown_extensions);
|
|
ClassDB::bind_method(D_METHOD("set_markdown_extensions", "val"), &MarkdownRenderer::set_markdown_extensions);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "markdown_extensions", PROPERTY_HINT_FLAGS, "Tables,Fenced Code,Footnotes,Autolink,Strikethrough,Underline,Highlight,Quote,Superscript,Math,No Intra Emphasis,Space Headers,Math Explicit,Disable Indented Code"), "set_markdown_extensions", "get_markdown_extensions");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_max_nesting"), &MarkdownRenderer::get_max_nesting);
|
|
ClassDB::bind_method(D_METHOD("set_max_nesting", "val"), &MarkdownRenderer::set_max_nesting);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_nesting"), "set_max_nesting", "get_max_nesting");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_use_smartypants"), &MarkdownRenderer::get_use_smartypants);
|
|
ClassDB::bind_method(D_METHOD("set_use_smartypants", "val"), &MarkdownRenderer::set_use_smartypants);
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "use_smartypants"), "set_use_smartypants", "get_use_smartypants");
|
|
|
|
ClassDB::bind_method(D_METHOD("get_toc_level"), &MarkdownRenderer::get_toc_level);
|
|
ClassDB::bind_method(D_METHOD("set_toc_level", "val"), &MarkdownRenderer::set_toc_level);
|
|
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);
|
|
|
|
BIND_ENUM_CONSTANT(RENDER_TYPE_HTML);
|
|
BIND_ENUM_CONSTANT(RENDER_TYPE_HTML_TOC);
|
|
|
|
BIND_ENUM_CONSTANT(HTML_FLAG_SKIP_HTML);
|
|
BIND_ENUM_CONSTANT(HTML_FLAG_ESCAPE);
|
|
BIND_ENUM_CONSTANT(HTML_FLAG_HARD_WRAP);
|
|
BIND_ENUM_CONSTANT(HTML_FLAG_USE_XHTML);
|
|
|
|
BIND_ENUM_CONSTANT(EXTENSION_TABLES);
|
|
BIND_ENUM_CONSTANT(EXTENSION_FENCED_CODE);
|
|
BIND_ENUM_CONSTANT(EXTENSION_FOOTNOTES);
|
|
|
|
BIND_ENUM_CONSTANT(EXTENSION_AUTOLINK);
|
|
BIND_ENUM_CONSTANT(EXTENSION_STRKIETHROUGH);
|
|
BIND_ENUM_CONSTANT(EXTENSION_UNDERLINE);
|
|
BIND_ENUM_CONSTANT(EXTENSION_HIGHLIGHT);
|
|
BIND_ENUM_CONSTANT(EXTENSION_QUOTE);
|
|
BIND_ENUM_CONSTANT(EXTENSION_SUPERSCRIPT);
|
|
BIND_ENUM_CONSTANT(EXTENSION_MATH);
|
|
|
|
BIND_ENUM_CONSTANT(EXTENSION_NO_INTRA_EMPHASIS);
|
|
BIND_ENUM_CONSTANT(EXTENSION_SPACE_HEADERS);
|
|
BIND_ENUM_CONSTANT(EXTENSION_MATH_EXPLICIT);
|
|
|
|
BIND_ENUM_CONSTANT(EXTENSION_DISABLE_INDENTED_CODE);
|
|
};
|