summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2019-10-29 19:50:18 +0300
committerAleksey Veresov <aleksey@veresov.pro>2019-10-29 19:50:18 +0300
commit3b13f7ac20875df55e02d5e407c4c3cbab3f159c (patch)
treee4c1010278ada9b64b9f785b37aa7a9b3859110e
parent1de3a9aae84ec71c4fd83604ea9c45204efb9baf (diff)
downloadtexo-3b13f7ac20875df55e02d5e407c4c3cbab3f159c.tar
texo-3b13f7ac20875df55e02d5e407c4c3cbab3f159c.tar.xz
texo-3b13f7ac20875df55e02d5e407c4c3cbab3f159c.zip
.
-rw-r--r--examples/markdown.cpp61
-rw-r--r--examples/markdown.md28
-rw-r--r--src/html.hpp21
-rw-r--r--src/lines.cpp10
-rw-r--r--src/lines.hpp1
-rw-r--r--src/markdown.cpp232
-rw-r--r--src/markdown.hpp53
7 files changed, 381 insertions, 25 deletions
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 <stdio.h>
+#include <html.hpp>
+#include <plain.hpp>
+#include <lines.hpp>
+#include <markdown.hpp>
+#include <file.hpp>
+
+
+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 ("&gt;" -> ">")
- 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();
};