tedi2html.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * This file is the main code of Texdi
  3. * Copyright (C) <2017> <alkeon> [alkeon@autistici.org]
  4. *
  5. * Texdi is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Texdi is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Texdi. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #include <iostream>
  20. #include <string>
  21. #include <fstream>
  22. #include <sstream>
  23. #include "tedi2html.h"
  24. #include "exception.h"
  25. using namespace std;
  26. /*
  27. * This function converts a string with Tedi format and return
  28. * a string with HTML format.
  29. * Header and footer are by default void.
  30. */
  31. string tedi2html(string text, string header, string footer){
  32. stringstream index(text);
  33. string line;
  34. string return_text;
  35. int control=0;
  36. int open_brackets=0;
  37. while(getline(index,line)){
  38. if(line[0]!='<'){
  39. size_t start=line.find("!head");
  40. size_t end=line.find("!end");
  41. if(start!=string::npos){
  42. return_text+=header + "\n";
  43. }else if(end!=string::npos){
  44. return_text+=footer + "\n";
  45. }else{
  46. size_t hash=line.find('#');
  47. if(hash!=string::npos){
  48. line=titles_ht(line);
  49. return_text+=line+"\n";
  50. }else{
  51. size_t ul=line.find("__");
  52. if(ul!=string::npos){
  53. return_text+="<ul>\n";
  54. }
  55. size_t li=line.find("--");
  56. if(li!=string::npos){
  57. line=line.erase(li,2);
  58. line=line.insert(li,"<li>");
  59. }
  60. size_t ulf=line.find(",,");
  61. if(ulf!=string::npos){
  62. return_text+="</ul>\n";
  63. }
  64. size_t comi=line.find("\"");
  65. if(comi!=string::npos){
  66. if(line[line.size()-1]=='"')
  67. line=line.substr(1,line.size()-2);
  68. else
  69. throw Invalid("Missing end quotes.",line);
  70. }else{
  71. int etiq=main_tag(line);
  72. while(etiq!=-1){
  73. //cout << line << etiq << endl;
  74. if(etiq==2){
  75. size_t lla2=line.find("}");
  76. if(lla2==string::npos){
  77. ++open_brackets;
  78. line=incomplete_blocks_ht(line);
  79. }else{
  80. line=blocks_ht(line);
  81. }
  82. }else{
  83. if(etiq==0){
  84. line=images_ht(line);
  85. }else{
  86. line=links_ht(line);
  87. }
  88. }
  89. etiq=main_tag(line);
  90. }
  91. size_t lla2=line.find("}");
  92. if(lla2!=string::npos){
  93. if(open_brackets==0)
  94. throw Invalid("Missing '{' in block tag.",line);
  95. --open_brackets;
  96. line=line.erase(lla2,1);
  97. line=line.insert(lla2,"</div>");
  98. }
  99. }
  100. size_t hor=line.find("|");
  101. if(control==0){
  102. size_t hor1=line.rfind("|");
  103. if(hor!=string::npos && hor!=hor1){
  104. return_text+="<table>\n<tr>\n";
  105. table_ht(line,return_text);
  106. control=1;
  107. }
  108. }else{
  109. if(hor==string::npos){
  110. return_text+="</table>\n";
  111. control=0;
  112. }else{
  113. return_text+="<tr>\n";
  114. table_ht(line,return_text);
  115. }
  116. }
  117. size_t minor=line.rfind(" ");
  118. if(minor==line.size()-1 && line.size()>1){
  119. return_text+=line+ "<p>\n";
  120. }else{
  121. if(ulf==string::npos && ul==string::npos && hash==string::npos){
  122. return_text+=line+ "\n";
  123. }
  124. }
  125. }
  126. }
  127. }else{
  128. if(line[1]!='!'){
  129. if(line[1]=='>'){
  130. line=line.erase(0,2);
  131. return_text+=line+ "\n";
  132. }else{
  133. line=line.erase(0,1);
  134. return_text+=line+ "<p>\n";
  135. }
  136. }
  137. }
  138. }
  139. if(open_brackets>0)
  140. throw Invalid("Missing '}' in document.","End of file");
  141. return return_text;
  142. }
  143. /*
  144. * Detects next tag
  145. * Returns
  146. * 0: images
  147. * 1: links
  148. * 2: blocks
  149. * -1: No tag
  150. */
  151. int main_tag(string line){
  152. int etiq=-1;
  153. size_t cont=line.size();
  154. size_t lla=line.find("{");
  155. size_t paren=line.find("(");
  156. size_t corch=line.find("[");
  157. if(lla!= string::npos && lla<cont){
  158. etiq=2;
  159. cont=lla;
  160. }
  161. if(corch != string::npos && corch<cont){
  162. cont=corch;
  163. etiq=1;
  164. }
  165. if(paren != string::npos && paren<cont){
  166. etiq=0;
  167. }
  168. return etiq;
  169. }
  170. /*
  171. * Convert Tedi table to a HTML link (line by line)
  172. *
  173. */
  174. void table_ht(string& line,string& return_text){
  175. return_text+="<tr>\n";
  176. size_t hor=line.find("|");
  177. if(hor!=string::npos){
  178. ++hor;
  179. line=line.substr(hor,line.size()-1);
  180. hor=line.find("|");
  181. if(hor!=string::npos){
  182. int tam=line.size()-1;
  183. while(hor!=string::npos && line[tam]=='|'){
  184. string elemento;
  185. elemento=line.substr(0,hor);
  186. return_text+="<td>"+elemento+"</td>\n";
  187. ++hor;
  188. line=line.substr(hor,line.size()-1);
  189. hor=line.find("|");
  190. tam=line.size()-1;
  191. }
  192. return_text+="</tr>\n";
  193. }else{
  194. throw Invalid("Expected '|' in table", line);
  195. }
  196. }else{
  197. throw Invalid("Expected '|' in table", line);
  198. }
  199. }
  200. /*
  201. * Convert Tedi link to a HTML link
  202. *
  203. */
  204. string links_ht(string line){
  205. size_t start_tag=line.find("[(");
  206. string aux="<a href=\"";
  207. if(start_tag!= string::npos){
  208. line=line.erase(start_tag,2);
  209. line=line.insert(start_tag,aux);
  210. size_t par1=line.find(")");
  211. if(par1!=string::npos){
  212. line=line.erase(par1,1);
  213. aux="\">";
  214. line=line.insert(par1,aux);
  215. size_t brack=line.rfind("]");
  216. if(brack!=string::npos){
  217. line=line.erase(brack,1);
  218. aux="</a>";
  219. line=line.insert(brack,aux);
  220. }else
  221. throw Invalid("Missing ']' in link tag.",line);
  222. }else
  223. throw Invalid("Missing ')' in link tag.",line);
  224. }else
  225. throw Invalid("Missing link tag.",line);
  226. return line;
  227. }
  228. /*
  229. * Deletes parentheses and adds HTML text of a image.
  230. *
  231. */
  232. string images_ht(string line){
  233. size_t par1=line.find("(");
  234. size_t par2=line.find(")");
  235. string aux="<img src=\"";
  236. if(par2!= string::npos){
  237. size_t pos=par2-par1;
  238. size_t point=line.find(".");
  239. if(point!=string::npos && point<par2 && point>par1)
  240. pos=point-par1;
  241. string alt=line.substr(par1+1,pos-1);
  242. line=line.erase(par1,1);
  243. line=line.insert(par1,aux);
  244. par2=line.find(")");
  245. if(par2!=string::npos){
  246. aux="\" alt=\""+alt+"\">";
  247. line=line.erase(par2,1);
  248. line=line.insert(par2,aux);
  249. }else
  250. throw Invalid("Missing ')' in image tag.",line);
  251. }else{
  252. throw Invalid("Missing image tag.",line);
  253. }
  254. return line;
  255. }
  256. /*
  257. * Deletes hashes and adds HTML text of a title.
  258. *
  259. */
  260. string titles_ht(string line){
  261. size_t exa1=line.find("#");
  262. int ti=0;
  263. while(exa1!=string::npos && line[exa1]=='#'){
  264. ++exa1;
  265. line=line.substr(exa1,line.size()-1);
  266. exa1=line.find("#");
  267. ++ti;
  268. }
  269. string ti2=to_string(ti);
  270. line="<h"+ti2+">"+line+"</h"+ti2+">";
  271. return line;
  272. }
  273. /*
  274. * Deletes brackes and parentheses. Adds HTML text
  275. * of a <div> container.
  276. *
  277. */
  278. string blocks_ht(string line){
  279. size_t lla1=line.find("{(");
  280. if(lla1!=string::npos){
  281. line=line.erase(lla1,2);
  282. string nop="<div class=\"";
  283. line=line.insert(lla1,nop);
  284. lla1=line.find(")");
  285. if(lla1!=string::npos){
  286. nop="\">";
  287. line=line.erase(lla1,1);
  288. line=line.insert(lla1,nop);
  289. lla1=line.rfind("}");
  290. if(lla1!=string::npos){
  291. nop="</div>";
  292. line=line.erase(lla1,1);
  293. line=line.insert(lla1,nop);
  294. }else
  295. throw Invalid("Missing '}' in block tag.",line);
  296. }else
  297. throw Invalid("Missing ')' in block tag.",line);
  298. }else
  299. throw Invalid("Missing block tag.",line);
  300. return line;
  301. }
  302. /*
  303. * Deletes brackes and parentheses. Adds HTML text
  304. * of a <div> container.
  305. *
  306. */
  307. string incomplete_blocks_ht(string line){
  308. size_t key1=line.find("{(");
  309. if(key1!= string::npos){
  310. line.erase(key1,2);
  311. line.insert(key1,"<div class=\"");
  312. size_t par=line.find(")");
  313. if(par!=string::npos){
  314. line.erase(par,1);
  315. line.insert(par,"\">");
  316. size_t key2=line.find("}");
  317. if(key2!=string::npos)
  318. throw Invalid("Unexpected '}' in incomplete block tag.",line);
  319. }else
  320. throw Invalid("Missing ')' in block tag.",line);
  321. }else
  322. throw Invalid("Missing block tag.",line);
  323. return line;
  324. }