123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /*
- * tedi2html main code
- * Copyright (C) <2022> <alkeon> [alkeon@autistici.org]
-
- * Texdi is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Texdi is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with tedi2html. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <iostream>
- #include <string>
- #include <fstream>
- #include <sstream>
- #include "../tedi2lang/tedi2lang.h"
- #include "tedi2html.h"
- #include "../tedi2lang/exception.h"
- using namespace std;
- #define BLOCK 2
- #define IMAGE 1
- #define LINK 0
- #define NO_TAG -1
- tedi2html::tedi2html(tags_definition td): tedi2lang(td), _start_paragraph_tag("<p>"){}
- tedi2html::tedi2html(): tedi2lang(default_tags_value()), _start_paragraph_tag("<p>"){}
- tags_definition tedi2html::default_tags_value(){
-
- tags_definition td;
- td.start_heading_first_level_tag = "<h1>";
- td.start_heading_second_level_tag = "<h2>";
- td.start_heading_third_level_tag = "<h3>";
- td.start_heading_fourth_level_tag = "<h4>";
- td.end_heading_first_level_tag = "</h1>";
- td.end_heading_second_level_tag = "</h2>";
- td.end_heading_third_level_tag = "</h3>";
- td.end_heading_fourth_level_tag = "</h4>";
- td.start_list_tag = "<ul>";
- td.list_item_tag = "<li>";
- td.end_list_tag = "</ul>";
- td.start_container_tag = "<div class=\"";
- td.middle_container_tag = "\">";
- td.end_container_tag = "</div>";
- td.start_link_tag = "<a href=\"";
- td.middle_link_tag = "\">";
- td.end_link_tag = "</a>";
- td.start_image_tag = "<img alt=\"";
- td.middle_image_tag = "\" src=\"";
- td.end_image_tag = "\">";
- td.start_table_tag = "<table>";
- td.end_table_tag = "</table>";
- td.start_table_row_tag = "<tr>";
- td.end_table_row_tag = "</tr>";
- td.start_table_data_tag = "<td>";
- td.end_table_data_tag = "</td>";
- td.end_paragraph_tag = "</p>";
- return td;
- }
- /*
- * Add header, iterate through text and finish with footer
- *
- */
- string tedi2html::convert(string text, string header, string footer) {
- stringstream index(text);
- string line, return_text = header;
- _open_brackets = 0;
- _is_paragraph = false;
- _is_converting_table = false;
- _is_unordered_list = 0;
- while(getline(index, line)){
- _has_block = false;
- return_text += convert_line(line);
- }
-
- if(_open_brackets > 0)
- throw Invalid("Missing '}' in document.", "End of file");
- if(_is_converting_table) return_text += _end_table_tag + "\n";
- if(_is_paragraph) return_text += _end_paragraph_tag + "\n";
- return_text += footer;
- return return_text;
- }
- /*
- * Deletes heading tag and insert HTML heading tag
- *
- */
- string tedi2html::convert_line_heading(string& line, size_t hash_position) {
- int level = 0;
- while(found(hash_position) && line[hash_position + level] == '#')
- ++level;
-
- if(hash_position + level >= line.size())
- throw Invalid("Unexpected heading size", line);
- else
- line = line.substr(hash_position + level, line.size() - 1);
-
- line = strip_escaping(line);
- switch(level){
- case 1: line = _start_heading_first_level_tag + line + _end_heading_first_level_tag; break;
- case 2: line = _start_heading_second_level_tag + line + _end_heading_second_level_tag; break;
- case 3: line = _start_heading_third_level_tag + line + _end_heading_third_level_tag; break;
- case 4: line = _start_heading_fourth_level_tag + line + _end_heading_fourth_level_tag; break;
- default: line = _start_heading_fourth_level_tag + line + _end_heading_fourth_level_tag; break;
- }
-
- return (close_paragraph(_is_paragraph) + line + "\n");
- }
- // List tags
- string tedi2html::convert_line_list_start(string& line) {
- ++_is_unordered_list;
- return close_paragraph(_is_paragraph) + _start_list_tag + "\n";
-
- }
- void tedi2html::convert_line_list_item(string& line, size_t li){
- line = line.erase(li, 2);
- line = line.insert(li, close_paragraph(_is_paragraph) + _list_item_tag);
-
- }
- string tedi2html::convert_line_list_end(string& line) {
- --_is_unordered_list;
- return close_paragraph(_is_paragraph) + _end_list_tag + "\n";
-
- }
- /*
- * Deletes block tag and insert block tag
- *
- */
- void tedi2html::convert_line_block(string& line) {
- if(_is_paragraph){
- line = "</p>\n" + line;
- _is_paragraph = false;
- }
- size_t start_tag = get_not_escaped_tag(line, "{(");
- if(found(start_tag) && !is_tag_escaped(line, start_tag)) {
- line = line.erase(start_tag, 2);
- line = line.insert(start_tag, _start_container_tag);
- start_tag = get_not_escaped_tag(line, ") ");
- if(found(start_tag) && !is_tag_escaped(line, start_tag)) {
- line = line.erase(start_tag, 2);
- line = line.insert(start_tag, _middle_container_tag);
- size_t end_tag = correct_position(line, start_tag + _middle_container_tag.size(), '{', '}');
- if(found(end_tag)) {
- line = line.erase(end_tag, 1);
- line = line.insert(end_tag, _end_container_tag);
- } else
- ++_open_brackets;
-
- } else
- throw Invalid("Missing ')' in block tag.",line);
- } else
- throw Invalid("Missing block tag.",line);
- _has_block = true;
- }
- /*
- * Start or continue table conversion
- *
- */
- string tedi2html::convert_line_table(string& line, size_t first_pipe) {
- string return_text;
- if(!_is_converting_table) {
- if(first_pipe != line.rfind("|")) {
- return_text += close_paragraph(_is_paragraph) + _start_table_tag + "\n";
- _is_converting_table = true;
- return return_text + convert_line_table_row(line);
- } else
- return convert_line_ending(line);
- }else
- return return_text + convert_line_table_row(line);
- }
- /*
- * Check line ending and convert depending ending whitespace
- *
- */
- string tedi2html::convert_line_ending(string& line){
- if(line.size() > 1){
- if(line[line.size() - 1] == ' '){
- if(_is_paragraph) {
- _is_paragraph = false;
- return strip_escaping(line) + _end_paragraph_tag + "\n";
- } else {
- if(!_is_converting_table && !_has_block && !_is_unordered_list)
- return _start_paragraph_tag + strip_escaping(line) + _end_paragraph_tag + "\n";
- else
- return strip_escaping(line) + "\n";
- }
- } else if(!_is_converting_table && !_has_block && !_is_unordered_list) {
- if(_is_paragraph)
- return strip_escaping(line) + "\n";
- else {
- _is_paragraph = true;
- return _start_paragraph_tag + strip_escaping(line) + "\n";
-
- }
- } else {
-
- if(_is_paragraph) {
- _is_paragraph = false;
- return _end_paragraph_tag + "\n" + strip_escaping(line) + "\n";
- } else
- return strip_escaping(line) + "\n";
- }
- } else
- return line + "\n";
-
- }
- /*
- * Control tags:
- * <!, <>, <+. <
- */
- string tedi2html::convert_line_control_tags(string& line){
- if(line[1] != '!') {
- if(line[1] == '>') {
- line = line.erase(0,2);
- return line + "\n";
- } else if(line[1] == '+') {
- line = line.erase(0,2);
- if(_is_paragraph) {
- _is_paragraph = false;
- return line + _end_paragraph_tag + "\n";
- } else
- return _start_paragraph_tag + line + _end_paragraph_tag + "\n";
-
- } else {
- line = line.erase(0,1);
- return line + "\n";
- }
- } else
- return "";
-
- }
- /*
- * If there's an open paragraph, close it
- *
- */
- string tedi2html::close_paragraph(bool& is_paragraph){
- string p;
- if(is_paragraph){
- p = _end_paragraph_tag + "\n";
- is_paragraph = false;
- }
- return p;
- }
|