tedi2tex.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*jslint browser: true*/
  2. "use strict";
  3. /*jshint esversion: 6 */
  4. class tedi2tex extends tedi2lang {
  5. constructor() {
  6. const td = {
  7. start_heading_first_level_tag:"\\section{",
  8. start_heading_second_level_tag:"\\subsection{",
  9. start_heading_third_level_tag:"\\subsubsection{",
  10. start_heading_fourth_level_tag:"\\subsubsection{",
  11. end_heading_first_level_tag:"}",
  12. end_heading_second_level_tag:"}",
  13. end_heading_third_level_tag:"}",
  14. end_heading_fourth_level_tag:"}",
  15. start_list_tag:"\\begin{itemize}",
  16. list_item_tag:"\\item ",
  17. end_list_tag:"\\end{itemize}",
  18. start_container_tag:"",
  19. middle_container_tag:"",
  20. end_container_tag:"",
  21. start_link_tag:"\\href{",
  22. middle_link_tag:"}{",
  23. end_link_tag:"}",
  24. start_image_tag:"\\begin{figure}[h!]\n\\centering\n\\includegraphics[width=1\\textwidth]{",
  25. middle_image_tag:"",
  26. end_image_tag:"",
  27. start_table_tag:"",
  28. end_table_tag:"\\hline\n\\end{longtable}",
  29. start_table_row_tag:"\\hline",
  30. end_table_row_tag:"\\tabularnewline",
  31. start_table_data_tag:" & ",
  32. end_table_data_tag:"",
  33. end_paragraph_tag:"\n"
  34. };
  35. super(td);
  36. }
  37. /*
  38. * Underscores are subscripts in LaTeX
  39. *
  40. */
  41. escape_underscores(line) {
  42. let underscore = line.find('_');
  43. while(this.found(underscore)) {
  44. let start_list_tag = line.find("__");
  45. if(!this.found(start_list_tag))
  46. line = line.insert(underscore, 1, '\\');
  47. underscore = line.find('_', underscore + 2);
  48. }
  49. return line;
  50. }
  51. /*
  52. * Main logic converting line.
  53. *
  54. */
  55. convert_line(line) {
  56. if(line[0] != '<') {
  57. line = this.escape_underscores(line);
  58. let end_table = this.convert_end_table(line);
  59. let hash = line.find('#');
  60. if(this.found(hash) && this.is_first_tag(line, hash))
  61. return end_table + this.convert_line_heading(line, hash);
  62. else {
  63. let ul = line.find("__");
  64. if(this.found(ul))
  65. return end_table + this.convert_line_list_start(line);
  66. else {
  67. this._line = line;
  68. let li = this._line.find("--");
  69. if(this.found(li) && this._is_unordered_list)
  70. this.convert_line_list_item(li);
  71. let ul_end = this._line.find(",,");
  72. if(this.found(ul_end) && this._is_unordered_list)
  73. return end_table + this.convert_line_list_end(line);
  74. else {
  75. if(this._line[0] == '"')
  76. this.convert_line_quote();
  77. else
  78. this.convert_unquoted_tags();
  79. let first_pipe = this._line.find("|");
  80. if(this.found(first_pipe))
  81. return this.convert_line_table(first_pipe);
  82. else
  83. return end_table + this.convert_line_ending(this._line);
  84. }
  85. }
  86. }
  87. } else
  88. return this.convert_end_table_control_tags(line) + this.convert_line_control_tags(line);
  89. }
  90. /*
  91. * Deletes image tag and insert image tag
  92. *
  93. */
  94. convert_line_image() {
  95. let start_tag = this.get_not_escaped_tag("([");
  96. if(this.found(start_tag) && !this.is_tag_escaped(start_tag)) {
  97. this._line = this._line.erase(start_tag, 2);
  98. let square_bracket = this.get_not_escaped_tag("] ");
  99. if(this.found(square_bracket) && !this.is_tag_escaped(square_bracket)) {
  100. let caption = this._line.substr(start_tag, square_bracket - start_tag);
  101. this._line = this._line.erase(start_tag, square_bracket + 2 - start_tag);
  102. this._line = this._line.insert(start_tag, this._start_image_tag);
  103. let last_parenthesis = this.correct_position(start_tag + this._middle_image_tag.size(), '(', ')');
  104. if(this.found(last_parenthesis)) {
  105. this._line = this._line.erase(last_parenthesis, 1);
  106. this._line = this._line.insert(last_parenthesis, "}\n\\caption{" + caption + "}\n\\end{figure}");
  107. } else
  108. throw "Missing ')' in images tag." + this._line;
  109. } else
  110. throw "Missing ']' in images tag." + this._line;
  111. } else
  112. throw "Missing images tag." + this._line;
  113. }
  114. /*
  115. * Deletes block tag and insert block tag
  116. *
  117. */
  118. convert_line_block() {
  119. let start_tag = this.get_not_escaped_tag("{(");
  120. if(this.found(start_tag) && !this.is_tag_escaped(start_tag)) {
  121. this._line = this._line.erase(start_tag, 2);
  122. this._line = this._line.insert(start_tag, this._start_container_tag);
  123. let parenthesis = this.get_not_escaped_tag(") ");
  124. if(this.found(parenthesis) && !this.is_tag_escaped(parenthesis)) {
  125. this._line = this._line.erase(start_tag, parenthesis - start_tag + 2);
  126. let end_tag = this.correct_position(start_tag + this._middle_container_tag.size(), '{', '}');
  127. if(this.found(end_tag)) {
  128. this._line = this._line.erase(end_tag, 1);
  129. } else
  130. ++this._open_brackets;
  131. } else
  132. throw "Missing ')' in block tag." + this._line;
  133. } else
  134. throw "Missing block tag." + this._line;
  135. this._has_block = true;
  136. }
  137. /*
  138. * Start or continue table conversion
  139. *
  140. */
  141. convert_line_table(first_pipe) {
  142. let return_text = "";
  143. if(!this._is_converting_table) {
  144. if(first_pipe != -1 && first_pipe != this._line.lastIndexOf("\|")) {
  145. return_text = this.get_table_start_tag();
  146. this._is_converting_table = true;
  147. return return_text + this.convert_line_table_row(this._line);
  148. } else
  149. return this.convert_line_ending(this._line);
  150. }else
  151. return this.convert_line_table_row(this._line);
  152. }
  153. /*
  154. * Convert every cell of one table row
  155. *
  156. */
  157. convert_line_table_row(line) {
  158. let pipe = line.find("|");
  159. if(this.found(pipe)) {
  160. ++pipe;
  161. let return_text = this._start_table_row_tag + "\n";
  162. line = line.substr(pipe, line.size() - 1);
  163. pipe = line.find("|");
  164. if(this.found(pipe)) {
  165. let size = line.size() - 1;
  166. if(line[size] == '|') {
  167. let start = true;
  168. while(this.found(pipe) && line[size] == '|') {
  169. if(!start) {
  170. return_text += this._start_table_data_tag;
  171. } else
  172. start = false;
  173. return_text += line.substr(0, pipe);
  174. ++pipe;
  175. line = line.substr(pipe, size);
  176. pipe = line.find("|");
  177. size = line.size() - 1;
  178. }
  179. return return_text + this._end_table_row_tag + "\n";
  180. } else
  181. throw "Table not correctly written\n" +
  182. "Maybe there's a whitespace at end of line" + line;
  183. } else
  184. throw "Expected '|' in table" + this._line;
  185. } else
  186. throw "Expected '|' in table" + this._line;
  187. }
  188. /*
  189. * Control tags:
  190. * <!, <>, <+. <
  191. */
  192. convert_line_control_tags(line) {
  193. if(line[1] != '!') {
  194. if(line[1] == '>') {
  195. line = line.erase(0,2);
  196. return line + "\n";
  197. } else if(line[1] == '+') {
  198. line = line.erase(0,2);
  199. return "\\begin{verbatim}\n" + line + "\n\\end{verbatim}\n\n";
  200. } else if(!this.found(line.find("!")) && !this.found(line.find("¡"))) {
  201. line = line.erase(0,1);
  202. return "\\verb!" + line + "!\n";
  203. } else if(!this.found(line.find("}")) && !this.found(line.find("{"))) {
  204. line = line.erase(0,1);
  205. return "\\verb{" + line + "}\n";
  206. } else {
  207. line = line.erase(0, 1);
  208. return "\\begin{verbatim}\n" + line + "\n\\end{verbatim}\n\n";
  209. }
  210. } else
  211. return "";
  212. }
  213. /*
  214. * Check line ending and convert depending ending whitespace
  215. *
  216. */
  217. convert_line_ending(line) {
  218. line = this.strip_escaping(line);
  219. if(line[line.size() - 1] == ' ' && !this._is_unordered_list)
  220. return line + this._end_paragraph_tag + "\n";
  221. else
  222. return line + "\n";
  223. }
  224. get_table_start_tag() {
  225. let columns = this.get_table_columns(this._line);
  226. let start_table_tag = "\\begin{longtable}{";
  227. let size_per_column = 0.9 / columns;
  228. for(let i = 0; i < columns; ++i)
  229. start_table_tag += "|p{" + size_per_column + "\\linewidth}";
  230. start_table_tag += "|}\n";
  231. return start_table_tag;
  232. }
  233. get_table_columns(line) {
  234. let data = 0;
  235. let pipe = line.find("|");
  236. let size = line.size() - 1;
  237. while(this.found(pipe) && (line[size] == '|' || line[size - 1] == '|')) {
  238. ++pipe;
  239. line = line.substr(pipe);
  240. pipe = line.find("|");
  241. size = line.size() - 1;
  242. ++data;
  243. }
  244. return data - 1;
  245. }
  246. }