From 3b13f7ac20875df55e02d5e407c4c3cbab3f159c Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Tue, 29 Oct 2019 19:50:18 +0300 Subject: . --- examples/markdown.cpp | 61 +++++++++++++ examples/markdown.md | 28 ++++++ src/html.hpp | 21 ----- src/lines.cpp | 10 ++- src/lines.hpp | 1 - src/markdown.cpp | 232 +++++++++++++++++++++++++++++++++++++++++++++++++- src/markdown.hpp | 53 ++++++++++++ 7 files changed, 381 insertions(+), 25 deletions(-) create mode 100644 examples/markdown.cpp create mode 100644 examples/markdown.md diff --git a/examples/markdown.cpp b/examples/markdown.cpp new file mode 100644 index 0000000..2fbe37f --- /dev/null +++ b/examples/markdown.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include + + +void plain() +{ + fputs(" ---- Markdown to Plain ----\n\n", stdout); + TexoExporterFile exporter(stdout); + TexoProducerPlain producer(exporter); + TexoImporterMarkdown importer(producer); + FILE *file = fopen("markdown.md", "r"); + importer.Put(file); + fclose(file); +} + +void html() +{ + fputs("\n\n ---- Markdown to HTML ----\n\n", stdout); + TexoExporterFile exporter(stdout); + TexoProducerHTML producer(exporter); + TexoImporterMarkdown importer(producer); + FILE *file = fopen("markdown.md", "r"); + importer.Put(file); + fclose(file); +} + +void markdown() +{ + fputs("\n\n ---- Markdown to Markdown ----\n\n", stdout); + TexoExporterFile exporter(stdout); + TexoProducerMarkdown producer(exporter); + TexoImporterMarkdown importer(producer); + FILE *file = fopen("markdown.md", "r"); + importer.Put(file); + fclose(file); +} + +void lines() +{ + fputs("\n\n ---- Markdown to Lines ----\n\n", stdout); + TexoExporterFile exporter(stdout); + TexoProducerLines producer(exporter); + TexoImporterMarkdown importer(producer); + FILE *file = fopen("markdown.md", "r"); + importer.Put(file); + fclose(file); +} + +int main() +{ + plain(); + html(); + markdown(); + lines(); + + return 0; +} diff --git a/examples/markdown.md b/examples/markdown.md new file mode 100644 index 0000000..d1413fd --- /dev/null +++ b/examples/markdown.md @@ -0,0 +1,28 @@ +# Huge header +###### Tiny header + +Some text: +blah-blah-blah... + +New paragraph. *Italic*. **Bold**. _alternative_ __style__. +++Underlined++. ~~Striked~~. `Mono`. + +---- + +This was horizontal rule. + +> This is +> *quote*. + +``` +bool Block::is_code() +{ + return this->should_be(); +} +``` + +![Awesome alt](../awseome.jpg "Awesome Title") + +[Awesome link](example.com "Awesome title of link") + +[![Magic alt](../magic.png "Ignored")](example.com "Magic title of linked pic") diff --git a/src/html.hpp b/src/html.hpp index fcf64e6..c9d2e97 100644 --- a/src/html.hpp +++ b/src/html.hpp @@ -37,27 +37,6 @@ public: void Put(char c); void Put(const ScriptVariable &str); void Put(FILE *file); - -private: - enum State { - text, // TODO: decoding (">" -> ">") - open, - tag_name, - tag_skip, - attr_pre, - attr_name, - attr_name_post, - attr_value_pre, - attr_value - } state; - bool closing; - ScriptVariable tag; - ScriptVariable attr; - ScriptVariable attr_src; - ScriptVariable attr_href; - ScriptVariable attr_title; - ScriptVariable attr_alt; - ScriptVariable link_text; }; diff --git a/src/lines.cpp b/src/lines.cpp index 05a75e4..f77ae40 100644 --- a/src/lines.cpp +++ b/src/lines.cpp @@ -2,15 +2,18 @@ TexoProducerLines::TexoProducerLines(TexoExporter &exporter): - TexoProducer(exporter) + TexoProducer(exporter), newline(false) {} void TexoProducerLines::Put(const Texo &piece) { if (piece.c == '\n') { - exporter.Put(' '); + if (!newline) { + exporter.Put(' '); + } } else { exporter.Put(piece.c); + newline = false; } } @@ -18,6 +21,7 @@ void TexoProducerLines::Put(const TexoParagraph &piece) { if (piece.closing) { exporter.Put('\n'); + newline = true; } } @@ -25,6 +29,7 @@ void TexoProducerLines::Put(const TexoQuote &piece) { if (piece.closing) { exporter.Put('\n'); + newline = true; } else { exporter.Put('>'); } @@ -33,6 +38,7 @@ void TexoProducerLines::Put(const TexoQuote &piece) void TexoProducerLines::Put(const TexoLineBreak &piece) { exporter.Put('\n'); + newline = true; } diff --git a/src/lines.hpp b/src/lines.hpp index 4f68cb9..7ddee07 100644 --- a/src/lines.hpp +++ b/src/lines.hpp @@ -18,7 +18,6 @@ public: void Put(const TexoLineBreak &piece); private: - bool quoted; bool newline; }; diff --git a/src/markdown.cpp b/src/markdown.cpp index c542a1f..0593eb9 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -2,7 +2,8 @@ TexoProducerMarkdown::TexoProducerMarkdown(TexoExporter &exporter): - TexoProducer(exporter), quoted(false), newline(false), code(false) + TexoProducer(exporter), + quoted(false), newline(false), header(false), code(false) {} void TexoProducerMarkdown::Put(const Texo &piece) @@ -165,3 +166,232 @@ void TexoProducerMarkdown::Put(const TexoHorizontalRule &piece) exporter.Put("---\n"); newline = false; } + + +TexoImporterMarkdown::TexoImporterMarkdown(TexoProducer &producer): + TexoImporter(producer), state(text) +{} + +TexoImporterMarkdown::~TexoImporterMarkdown() +{} + +void TexoImporterMarkdown::Put(char c) +{ + switch (state) { + case text: Text(c); break; + case header_text: HeaderText(c); break; + case quote_text: QuoteText(c); break; + case quote_newline: QuoteNewline(c); break; + case code_text: CodeText(c); break; + case code_newline: CodeNewline(c); break; + case code_end: CodeEnd(c); break; + case backslash: Backslash(c); break; + case asterisk: Asterisk(c); break; + case underline: Underline(c); break; + case plus: Plus(c); break; + case tilde: Tilde(c); break; + case newline: Newline(c); break; + case paragraph: Paragraph(c); break; + case header: Header(c); break; + case code: Code(c); break; + case quote: Quote(c); break; + } +} + +void TexoImporterMarkdown::Put(const ScriptVariable &str) +{ + TexoImporter::Put(str); +} + +void TexoImporterMarkdown::Put(FILE *file) +{ + TexoImporter::Put(file); +} + +void TexoImporterMarkdown::Text(char c) +{ + wrapping_state = text; + switch (c) { + case '\\': state = backslash; break; + case '\n': state = newline; break; + case '*': state = asterisk; break; + case '_': state = underline; break; + case '~': state = tilde; break; + case '`': Backquote(); break; + default: producer.Put(c); + } +} + +void TexoImporterMarkdown::HeaderText(char c) +{ + wrapping_state = header_text; + switch (c) { + case '\\': state = backslash; break; + case '\n': EndHeader(); break; + case '*': state = asterisk; break; + case '_': state = underline; break; + case '~': state = tilde; break; + case '`': Backquote(); break; + default: producer.Put(c); + } +} + +void TexoImporterMarkdown::QuoteText(char c) +{ + wrapping_state = header_text; + switch (c) { + case '\\': state = backslash; break; + case '\n': state = quote_newline; break; + case '*': state = asterisk; break; + case '_': state = underline; break; + case '~': state = tilde; break; + case '`': Backquote(); break; + default: producer.Put(c); + } +} + +void TexoImporterMarkdown::QuoteNewline(char c); +void TexoImporterMarkdown::CodeText(char c); +void TexoImporterMarkdown::CodeNewline(char c); +void TexoImporterMarkdown::CodeEnd(char c); + +void TexoImporterMarkdown::Backslash(char c) +{ + producer.Put(c); + state = wrapping_state; +} + +void TexoImporterMarkdown::Asterisk(char c) +{ + state = wrapping_state; + if (c == '*') { + producer.Put(TexoBold(is_bold)); + is_bold = !is_bold; + } else { + producer.Put(TexoItalic(is_italic)); + is_italic = !is_italic; + Put(c); + } +} + +void TexoImporterMarkdown::Underline(char c) +{ + state = wrapping_state; + if (c == '_') { + producer.Put(TexoBold(is_bold)); + is_bold = !is_bold; + } else { + producer.Put(TexoItalic(is_italic)); + is_italic = !is_italic; + Put(c); + } +} + +void TexoImporterMarkdown::Plus(char c) +{ + state = wrapping_state; + if (c == '+') { + producer.Put(TexoUnderline(is_underline)); + is_underline = !is_underline; + } else { + producer.Put('+'); + Put(c); + } +} + +void TexoImporterMarkdown::Tilde(char c) +{ + state = wrapping_state; + if (c == '~') { + producer.Put(TexoStrike(is_strike)); + is_strike = !is_strike; + } else { + producer.Put('~'); + Put(c); + } +} + +void TexoImporterMarkdown::Backquote() +{ + producer.Put(TexoMono(is_mono)); + is_mono = !is_mono; +} + +void TexoImporterMarkdown::Newline(char c) +{ + if (c == '\n') { + state = paragraph; + } else if (c == '#') { + state = header; + header_level = 6; + } else if (c == '>') { + state = quote; + } else if (c == '-') { + state = rule; + rule_dash_count = 1; + } else if (c == '`') { + state = code; + code_quote_count = 1; + } else { + producer.Put(' '); + state = text; + Put(c); + } +} + +void TexoImporterMarkdown::Rule(char c) +{ + if (c == '-') { + ++rule_dash_count; + } else { + if (rule_dash_count >= 3) { + producer.Put(TexoHorizontalRule()); + } else { + if (wrapping_state == paragraph) { + producer.Put(TexoParagraph()); + } + for (int i = 0; i < rule_dash_count; ++i) { + producer.Put('-'); + } + } + } +} + +void TexoImporterMarkdown::Paragraph(char c) +{ + wrapping_state = paragraph; + if (c == '#') { + state = header; + header_level = 6; + } else if (c == '>') { + state = quote; + } else if (c == '-') { + state = rule; + rule_dash_count = 1; + } else if (c == '`') { + state = code; + code_quote_count = 1; + } else { + producer.Put(TexoParagraph()); + state = text; + Put(c); + } +} + +void TexoImporterMarkdown::Header(char c) +{ + if (c == '#') { + if (header_level > 1) { + --header_level; + } + } else { + producer.Put(TexoHeader(header_level)); + state = header_text; + } +} + +void TexoImporterMarkdown::EndHeader() +{ + producer.Put(TexoHeader(header_level, true)); + state = paragraph; +} diff --git a/src/markdown.hpp b/src/markdown.hpp index 7a23fed..7b5ff58 100644 --- a/src/markdown.hpp +++ b/src/markdown.hpp @@ -43,6 +43,59 @@ public: void Put(char c); void Put(const ScriptVariable &str); void Put(FILE *file); + +private: + enum State { + text, + header_text, + quote_text, + quote_newline, + code_text, + code_newline, + code_end, + backslash, + asterisk, + underline, + plus, + tilde, + newline, + rule, + paragraph, + header, + code, + quote + } state; + State wrapping_state; + bool is_italic; + bool is_bold; + bool is_underline; + bool is_strike; + bool is_mono; + int header_level; + int rule_dash_count; + int code_quote_count; + + void Text(char c); + void HeaderText(char c); + void QuoteText(char c); + void QuoteNewline(char c); + void CodeText(char c); + void CodeNewline(char c); + void CodeEnd(char c); + void Backslash(char c); + void Asterisk(char c); + void Underline(char c); + void Plus(char c); + void Tilde(char c); + void Newline(char c); + void Rule(char c); + void Paragraph(char c); + void Header(char c); + void Code(char c); + void Quote(char c); + + void Backquote(); + void EndHeader(); }; -- cgit v1.2.3