tedi2html.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*jslint browser: true*/
  2. "use strict";
  3. /*jshint esversion: 6 */
  4. class tedi2html extends tedi2lang {
  5. constructor() {
  6. const td = {
  7. start_heading_first_level_tag:"<h1>",
  8. start_heading_second_level_tag:"<h2>",
  9. start_heading_third_level_tag:"<h3>",
  10. start_heading_fourth_level_tag:"<h4>",
  11. end_heading_first_level_tag:"</h1>",
  12. end_heading_second_level_tag:"</h2>",
  13. end_heading_third_level_tag:"</h3>",
  14. end_heading_fourth_level_tag:"</h4>",
  15. start_list_tag:"<ul>",
  16. list_item_tag:"<li>",
  17. end_list_tag:"</ul>",
  18. start_container_tag:"<div class=\"",
  19. middle_container_tag:"\">",
  20. end_container_tag:"</div>",
  21. start_link_tag:"<a href=\"",
  22. middle_link_tag:"\">",
  23. end_link_tag:"</a>",
  24. start_image_tag:"<img alt=\"",
  25. middle_image_tag:"\" src=\"",
  26. end_image_tag:"\">",
  27. start_table_tag:"<table>",
  28. end_table_tag:"</table>",
  29. start_table_row_tag:"<tr>",
  30. end_table_row_tag:"</tr>",
  31. start_table_data_tag:"<td>",
  32. end_table_data_tag:"</td>",
  33. end_paragraph_tag:""
  34. };
  35. super(td);
  36. this._start_paragraph_tag = "";
  37. }
  38. /*
  39. * Add header, iterate through text and finish with footer
  40. *
  41. */
  42. convert(text, header = "", footer = "") {
  43. let index = this.get_lines(text);
  44. let return_text = header;
  45. this._open_brackets = 0;
  46. this._is_converting_table = false;
  47. this._is_unordered_list = 0;
  48. this._is_paragraph = false;
  49. for(let i = 0; i < index.length; ++i) {
  50. this._has_image = false;
  51. this._has_block = false;
  52. let line = index[i];
  53. return_text += this.convert_line(line);
  54. }
  55. if(this._open_brackets > 0)
  56. throw "Missing '}' in document. End of file";
  57. if(this._is_converting_table) return_text += this._end_table_tag + "\n";
  58. if(this._is_paragraph) return_text += this._end_paragraph_tag + "\n";
  59. return_text += footer;
  60. return return_text;
  61. }
  62. /*
  63. * Deletes heading tag and insert new heading tag
  64. *
  65. */
  66. convert_line_heading(line, hash_position) {
  67. let level = 0;
  68. while(this.found(hash_position) && line[hash_position + level] == '#')
  69. ++level;
  70. if((hash_position + level) >= line.size())
  71. throw "Unexpected heading size" + line;
  72. else
  73. line = line.substring(hash_position + level, line.size());
  74. switch(level) {
  75. case 1: line = this._start_heading_first_level_tag + this.strip_escaping(line) + this._end_heading_first_level_tag; break;
  76. case 2: line = this._start_heading_second_level_tag + this.strip_escaping(line) + this._end_heading_second_level_tag; break;
  77. case 3: line = this._start_heading_third_level_tag + this.strip_escaping(line) + this._end_heading_third_level_tag; break;
  78. case 4: line = this._start_heading_fourth_level_tag + this.strip_escaping(line) + this._end_heading_fourth_level_tag; break;
  79. default: line = this._start_heading_fourth_level_tag + this.strip_escaping(line) + this._end_heading_fourth_level_tag; break;
  80. }
  81. return (this.close_paragraph(this._is_paragraph) + line + "\n");
  82. }
  83. // List tags
  84. convert_line_list_start() {
  85. ++this._is_unordered_list;
  86. return this.close_paragraph(this._is_paragraph) + this._start_list_tag + "\n";
  87. }
  88. convert_line_list_item(li) {
  89. this._line = this._line.erase(li, 2);
  90. this._line = this._line.insert(li, this.close_paragraph(this._is_paragraph) + this._list_item_tag);
  91. }
  92. convert_line_list_end() {
  93. --this._is_unordered_list;
  94. if(this._is_unordered_list)
  95. return this.close_paragraph(this._is_paragraph) + this._end_list_tag + "\n";
  96. else
  97. return this.close_paragraph(this._is_paragraph) + this._end_list_tag + "\n";
  98. }
  99. /*
  100. * Deletes block tag and insert block tag
  101. *
  102. */
  103. convert_line_block() {
  104. let start_tag = this.get_not_escaped_tag("{(");
  105. if(this.found(start_tag) && !this.is_tag_escaped(start_tag)) {
  106. this._line = this._line.erase(start_tag, 2);
  107. this._line = this._line.insert(start_tag, this._start_container_tag);
  108. start_tag = this.get_not_escaped_tag(") ");
  109. if(this.found(start_tag) && !this.is_tag_escaped(start_tag)) {
  110. this._line = this._line.erase(start_tag, 2);
  111. this._line = this._line.insert(start_tag, this._middle_container_tag);
  112. let end_tag = this.correct_position(start_tag + this._middle_container_tag.size(), '{', '}');
  113. if(this.found(end_tag)) {
  114. this._line = this._line.erase(end_tag, 1);
  115. this._line = this._line.insert(end_tag, this._end_container_tag);
  116. } else
  117. ++this._open_brackets;
  118. } else
  119. throw "Missing ')' in block tag." + this._line;
  120. } else
  121. throw "Missing block tag." + this._line;
  122. this._has_block = true;
  123. }
  124. /*
  125. * Start or continue table conversion
  126. *
  127. */
  128. convert_line_table(first_pipe) {
  129. let return_text = "";
  130. if(!this._is_converting_table) {
  131. if(first_pipe != -1 && first_pipe != this._line.lastIndexOf("\|")) {
  132. return_text = this.close_paragraph(this._is_paragraph) + this._start_table_tag;
  133. this._is_converting_table = true;
  134. return return_text + this.convert_line_table_row(this._line);
  135. } else
  136. return this.convert_line_ending(this._line);
  137. }else
  138. return this.convert_line_table_row(this._line);
  139. }
  140. /*
  141. * Convert every cell of one table row
  142. *
  143. */
  144. convert_line_table_row(line) {
  145. let pipe = line.find("|");
  146. if(this.found(pipe)) {
  147. ++pipe;
  148. let return_text = this._start_table_row_tag;
  149. line = line.substr(pipe, line.size() - 1);
  150. pipe = line.find("|");
  151. if(this.found(pipe)) {
  152. let size = line.size() - 1;
  153. if(line[size] == '|') {
  154. while(this.found(pipe) && line[size] == '|') {
  155. return_text += this._start_table_data_tag + this.strip_escaping(line.substr(0, pipe)) + this._end_table_data_tag;
  156. ++pipe;
  157. line = line.substr(pipe, size);
  158. pipe = line.find("|");
  159. size = line.size() - 1;
  160. }
  161. return return_text + this._end_table_row_tag;
  162. } else
  163. throw "Table not correctly written\n" +
  164. "Maybe there's a whitespace at end of line" + line;
  165. } else
  166. throw "Expected '|' in table" + this._line;
  167. } else
  168. throw "Expected '|' in table" + this._line;
  169. }
  170. /*
  171. * Check line ending and convert depending ending whitespace
  172. *
  173. */
  174. convert_line_ending(line) {
  175. line = this.strip_escaping(line);
  176. if(line.size() > 1) {
  177. if(line[line.size() - 1] == ' ' && (this._has_image || this._has_block)) {
  178. return line.substring(0, line.size() - 1) + "\n";
  179. } else if(line[line.size() - 1] == ' '){
  180. return line + "\n";
  181. } else if(!this._is_converting_table && !this._has_block && !this._is_unordered_list) {
  182. return line;
  183. } else {
  184. return line;
  185. }
  186. } else
  187. return line + "\n";
  188. }
  189. /*
  190. * Control tags:
  191. * <!, <>, <+. <
  192. */
  193. convert_line_control_tags(line) {
  194. if(line[1] != '!') {
  195. if(line[1] == '>') {
  196. line = line.erase(0,2);
  197. return "<div class=\"embed\">" + line + "</div>" + "\n";
  198. } else if(line[1] == '+') {
  199. line = line.erase(0,2);
  200. return "<pre>" + line + "</pre>" + "\n";
  201. } else {
  202. line = line.erase(0,1);
  203. if(line.slice(-1) == "\n")
  204. return line + "\n";
  205. else
  206. return "<code>" + line + "</code>";
  207. }
  208. } else
  209. return "";
  210. }
  211. /*
  212. * If there's an open paragraph, close it
  213. *
  214. */
  215. close_paragraph() {
  216. let p = "";
  217. if(this._is_paragraph) {
  218. p = this._end_paragraph_tag + "\n";
  219. this._is_paragraph = false;
  220. }
  221. return p;
  222. }
  223. }