Add my own highlight extension
parent
8adba1214c
commit
749fdbb8fb
|
@ -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})
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
24
src/draw.cc
24
src/draw.cc
|
@ -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
|
||||
*****************************************************/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue