Add my own highlight extension

master
Melroy van den Berg 2021-02-26 23:13:24 +01:00
parent 8adba1214c
commit 749fdbb8fb
7 changed files with 168 additions and 5 deletions

View File

@ -10,6 +10,7 @@ set (LIBRARY_SOURCES
ext_scanners.re
ext_scanners.h
tasklist.c
highlight.c
)
set_property(GLOBAL PROPERTY COMMONMARKER_EXTENSIONS_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})

View File

@ -4,6 +4,7 @@
#include "table.h"
#include "tagfilter.h"
#include "tasklist.h"
#include "highlight.h"
#include "registry.h"
#include "plugin.h"
@ -14,6 +15,7 @@ static int core_extensions_registration(cmark_plugin *plugin) {
cmark_plugin_register_syntax_extension(plugin, create_autolink_extension());
cmark_plugin_register_syntax_extension(plugin, create_tagfilter_extension());
cmark_plugin_register_syntax_extension(plugin, create_tasklist_extension());
cmark_plugin_register_syntax_extension(plugin, create_highlight_extension());
return 1;
}

View File

@ -0,0 +1,128 @@
#include "highlight.h"
#include <parser.h>
#include <render.h>
cmark_node_type CMARK_NODE_HIGHLIGHT;
static cmark_node *match(cmark_syntax_extension *self, cmark_parser *parser,
cmark_node *parent, unsigned char character,
cmark_inline_parser *inline_parser) {
cmark_node *res = NULL;
int left_flanking, right_flanking, punct_before, punct_after, delims;
char buffer[101] = {0};
if (character != '=')
return NULL;
delims = cmark_inline_parser_scan_delimiters(
inline_parser, sizeof(buffer) - 1, '=',
&left_flanking,
&right_flanking, &punct_before, &punct_after);
memset(buffer, '=', delims);
buffer[delims] = 0;
res = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem);
cmark_node_set_literal(res, buffer);
res->start_line = res->end_line = cmark_inline_parser_get_line(inline_parser);
res->start_column = cmark_inline_parser_get_column(inline_parser) - delims;
// '=' char needs to be matched 2x
if ((left_flanking || right_flanking) && (delims == 2)) {
cmark_inline_parser_push_delimiter(inline_parser, character, left_flanking,
right_flanking, res);
}
return res;
}
static delimiter *insert(cmark_syntax_extension *self, cmark_parser *parser,
cmark_inline_parser *inline_parser, delimiter *opener,
delimiter *closer) {
cmark_node *highlight;
cmark_node *tmp, *next;
delimiter *delim, *tmp_delim;
delimiter *res = closer->next;
highlight = opener->inl_text;
if (opener->inl_text->as.literal.len != closer->inl_text->as.literal.len)
goto done;
if (!cmark_node_set_type(highlight, CMARK_NODE_HIGHLIGHT))
goto done;
cmark_node_set_syntax_extension(highlight, self);
tmp = cmark_node_next(opener->inl_text);
while (tmp) {
if (tmp == closer->inl_text)
break;
next = cmark_node_next(tmp);
cmark_node_append_child(highlight, tmp);
tmp = next;
}
highlight->end_column = closer->inl_text->start_column + closer->inl_text->as.literal.len - 1;
cmark_node_free(closer->inl_text);
delim = closer;
while (delim != NULL && delim != opener) {
tmp_delim = delim->previous;
cmark_inline_parser_remove_delimiter(inline_parser, delim);
delim = tmp_delim;
}
cmark_inline_parser_remove_delimiter(inline_parser, opener);
done:
return res;
}
static const char *get_type_string(cmark_syntax_extension *extension,
cmark_node *node) {
return node->type == CMARK_NODE_HIGHLIGHT ? "highlight" : "<unknown>";
}
static int can_contain(cmark_syntax_extension *extension, cmark_node *node,
cmark_node_type child_type) {
if (node->type != CMARK_NODE_HIGHLIGHT)
return false;
return CMARK_NODE_TYPE_INLINE_P(child_type);
}
static void commonmark_render(cmark_syntax_extension *extension,
cmark_renderer *renderer, cmark_node *node,
cmark_event_type ev_type, int options) {
renderer->out(renderer, node, "==", false, LITERAL);
}
static void plaintext_render(cmark_syntax_extension *extension,
cmark_renderer *renderer, cmark_node *node,
cmark_event_type ev_type, int options) {
renderer->out(renderer, node, "=", false, LITERAL);
}
cmark_syntax_extension *create_highlight_extension(void) {
cmark_syntax_extension *ext = cmark_syntax_extension_new("highlight");
cmark_llist *special_chars = NULL;
cmark_syntax_extension_set_get_type_string_func(ext, get_type_string);
cmark_syntax_extension_set_can_contain_func(ext, can_contain);
cmark_syntax_extension_set_commonmark_render_func(ext, commonmark_render);
cmark_syntax_extension_set_plaintext_render_func(ext, plaintext_render);
CMARK_NODE_HIGHLIGHT = cmark_syntax_extension_add_node(1);
cmark_syntax_extension_set_match_inline_func(ext, match);
cmark_syntax_extension_set_inline_from_delim_func(ext, insert);
cmark_mem *mem = cmark_get_default_mem_allocator();
special_chars = cmark_llist_append(mem, special_chars, (void *)'=');
cmark_syntax_extension_set_special_inline_chars(ext, special_chars);
cmark_syntax_extension_set_emphasis(ext, 1);
return ext;
}

View File

@ -0,0 +1,13 @@
/**
* Markdown Highlight extension by Melroy van den Berg
* Usage: ==Highlight text==
*/
#ifndef CMARK_GFM_HIGHLIGHT_H
#define CMARK_GFM_HIGHLIGHT_H
#include "cmark-gfm-core-extensions.h"
extern cmark_node_type CMARK_NODE_HIGHLIGHT;
cmark_syntax_extension *create_highlight_extension(void);
#endif

View File

@ -29,6 +29,7 @@ Draw::Draw(MainWindow &mainWindow)
isBold(false),
isItalic(false),
isStrikethrough(false),
isHighlight(false),
bulletListLevel(0),
orderedListLevel(0),
isOrderedList(false),
@ -52,13 +53,13 @@ Draw::Draw(MainWindow &mainWindow)
set_app_paintable(true);
defaultFont.set_size(fontSize);
boldItalic.set_size(fontSize);
boldItalic.set_weight(Pango::WEIGHT_BOLD);
boldItalic.set_style(Pango::Style::STYLE_ITALIC);
bold.set_size(fontSize);
bold.set_weight(Pango::WEIGHT_BOLD);
italic.set_size(fontSize);
italic.set_style(Pango::Style::STYLE_ITALIC);
boldItalic.set_size(fontSize);
boldItalic.set_weight(Pango::WEIGHT_BOLD);
boldItalic.set_style(Pango::Style::STYLE_ITALIC);
heading1.set_size(fontSize * PANGO_SCALE_XXX_LARGE);
heading1.set_weight(Pango::WEIGHT_BOLD);
@ -617,8 +618,13 @@ void Draw::processNode(cmark_node *node, cmark_event_type ev_type)
if (strcmp(node->extension->name, "strikethrough") == 0)
{
isStrikethrough = entering;
return;
}
else if (strcmp(node->extension->name, "highlight") == 0)
{
isHighlight = entering;
return;
}
return;
}
switch (node->type)
@ -635,6 +641,7 @@ void Draw::processNode(cmark_node *node, cmark_event_type ev_type)
isBold = false;
isItalic = false;
isStrikethrough = false;
isHighlight = false;
}
break;
@ -821,6 +828,10 @@ void Draw::processNode(cmark_node *node, cmark_event_type ev_type)
{
insertStrikethrough(text);
}
else if (isHighlight)
{
insertHighlight(text);
}
// URL
else if (isLink)
{
@ -969,6 +980,11 @@ void Draw::insertStrikethrough(const std::string &text)
insertMarkupTextOnThread("<span font_desc=\"" + defaultFont.to_string() + "\" strikethrough=\"true\">" + text + "</span>");
}
void Draw::insertHighlight(const std::string &text)
{
insertMarkupTextOnThread("<span font_desc=\"" + defaultFont.to_string() + "\" foreground=\"black\" background=\"#FFFF00\">" + text + "</span>");
}
/******************************************************
* Helper functions below
*****************************************************/

View File

@ -76,6 +76,7 @@ private:
void insertItalic(const std::string &text);
void insertBold(const std::string &text);
void insertStrikethrough(const std::string &text);
void insertHighlight(const std::string &text);
void insertMarkupTextOnThread(const std::string &text);
void clearOnThread();
@ -94,6 +95,7 @@ private:
bool isBold;
bool isItalic;
bool isStrikethrough;
bool isHighlight;
int bulletListLevel;
int orderedListLevel;
bool isOrderedList;
@ -102,9 +104,9 @@ private:
std::map<int,int> orderedListCounters;
Pango::FontDescription defaultFont;
Pango::FontDescription boldItalic;
Pango::FontDescription bold;
Pango::FontDescription italic;
Pango::FontDescription boldItalic;
Pango::FontDescription heading1;
Pango::FontDescription heading2;
Pango::FontDescription heading3;

View File

@ -40,6 +40,7 @@ cmark_node *Parser::parseContent(const std::string &content)
cmark_node *document;
// Add extensions
addMarkdownExtension(parser, "strikethrough");
addMarkdownExtension(parser, "highlight");
addMarkdownExtension(parser, "table");
cmark_parser_feed(parser, data, strlen(data));