mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:27:44 +00:00
LibMarkdown: Add strike-through text support to markdown
Using ~~text~~ syntax will strike out the text between the two tildes. Only missing portion is the terminal rendering of strike through text. The ansi escape codes for strike through text are \e[9m and \e[29m but it appears the terminal does not support these. Please correct me if I am wrong. I tested that the render_to_terminal function was being called by giving it bold ANSI escape codes, and that did work so the function is being called correctly.
This commit is contained in:
parent
45f3fffbad
commit
25970f2763
3 changed files with 88 additions and 3 deletions
|
@ -223,6 +223,34 @@ RecursionDecision Text::MultiNode::walk(Visitor& visitor) const
|
|||
return RecursionDecision::Continue;
|
||||
}
|
||||
|
||||
void Text::StrikeThroughNode::render_to_html(StringBuilder& builder) const
|
||||
{
|
||||
builder.append("<del>");
|
||||
striked_text->render_to_html(builder);
|
||||
builder.append("</del>");
|
||||
}
|
||||
|
||||
void Text::StrikeThroughNode::render_for_terminal(StringBuilder& builder) const
|
||||
{
|
||||
builder.append("\e[9m");
|
||||
striked_text->render_for_terminal(builder);
|
||||
builder.append("\e[29m");
|
||||
}
|
||||
|
||||
size_t Text::StrikeThroughNode::terminal_length() const
|
||||
{
|
||||
return striked_text->terminal_length();
|
||||
}
|
||||
|
||||
RecursionDecision Text::StrikeThroughNode::walk(Visitor& visitor) const
|
||||
{
|
||||
RecursionDecision rd = visitor.visit(*this);
|
||||
if (rd != RecursionDecision::Recurse)
|
||||
return rd;
|
||||
|
||||
return striked_text->walk(visitor);
|
||||
}
|
||||
|
||||
size_t Text::terminal_length() const
|
||||
{
|
||||
return m_node->terminal_length();
|
||||
|
@ -330,7 +358,7 @@ Vector<Text::Token> Text::tokenize(StringView str)
|
|||
if (ch == '\\' && offset + 1 < str.length() && ispunct(str[offset + 1])) {
|
||||
current_token.append(str[offset + 1]);
|
||||
++offset;
|
||||
} else if (ch == '*' || ch == '_' || ch == '`') {
|
||||
} else if (ch == '*' || ch == '_' || ch == '`' || ch == '~') {
|
||||
flush_token();
|
||||
|
||||
char delim = ch;
|
||||
|
@ -388,6 +416,9 @@ NonnullOwnPtr<Text::MultiNode> Text::parse_sequence(Vector<Token>::ConstIterator
|
|||
case '`':
|
||||
node->children.append(parse_code(tokens));
|
||||
break;
|
||||
case '~':
|
||||
node->children.append(parse_strike_through(tokens));
|
||||
break;
|
||||
}
|
||||
} else if (*tokens == "[" || *tokens == " {
|
||||
return token.is_run && token.run_char() == '~' && token.run_length() == opening.run_length();
|
||||
};
|
||||
|
||||
bool is_all_whitespace = true;
|
||||
auto striked_text = make<MultiNode>();
|
||||
for (auto iterator = tokens + 1; !iterator.is_end(); ++iterator) {
|
||||
if (is_closing(*iterator)) {
|
||||
tokens = iterator;
|
||||
|
||||
if (!is_all_whitespace) {
|
||||
auto& first = dynamic_cast<TextNode&>(striked_text->children.first());
|
||||
auto& last = dynamic_cast<TextNode&>(striked_text->children.last());
|
||||
if (first.text.starts_with(" ") && last.text.ends_with(" ")) {
|
||||
first.text = first.text.substring(1);
|
||||
last.text = last.text.substring(0, last.text.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return make<StrikeThroughNode>(move(striked_text));
|
||||
}
|
||||
|
||||
is_all_whitespace = is_all_whitespace && iterator->data.is_whitespace();
|
||||
striked_text->children.append(make<TextNode>((*iterator == "\n") ? " " : iterator->data, false));
|
||||
}
|
||||
|
||||
return make<TextNode>(opening.data);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue