Skip to content

Commit 6c75f54

Browse files
author
Charlotte
authored
Merge pull request #2 from coco33920/math
[Feature] Add supports for inline math and some env
2 parents da64210 + 1915362 commit 6c75f54

File tree

8 files changed

+333
-217
lines changed

8 files changed

+333
-217
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ translates TeX Books (simple one like stories kind of book) to HTML. I use this
77

88
## What this project *is not*
99
The purpose of this project **is not** and never will be a kind of "TeX To HTML" compiler, I do *not* intend to implement the full TeX
10-
and LaTeX specification. As such the support of mathematics is likely **never to be** included here. This is a tool mainly done *for me* for my usage, that is publishing my book on ScribbleHub and the web. I'm sure you can find real compilers if you want to support
10+
and LaTeX specification. This is a tool mainly done *for me* for my usage, that is publishing my book on ScribbleHub and the web. I'm sure you can find real compilers if you want to support
1111
the full specification of TeX and LaTeX
1212

1313
## Support
@@ -23,6 +23,13 @@ The project currently translate *LaTeX* to human-readable HTML files (the line b
2323
- `textbf` is replaced by `<b>`
2424
- `newline`, `\\`, and `par` puts a `<br>`
2525
- `bigskip` closes the paragraph and open another one.
26+
- Some math
27+
- Inline math with `$`
28+
- Math env
29+
- Align*
30+
- Align
31+
- Equation
32+
- Equation*
2633

2734
## Near Future TODO List
2835
* parsing glossary entries from a glossary file and printing the `gls` with a link to the glossary

bin/main.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ let spec = [
1414
]
1515

1616
let execute_command file outname start_chapter =
17-
Htmlfromtexbooks.Parser.print_file_in_html ~min_chap:start_chapter file outname;;
17+
Htmlfromtexbooks.Htmlgen.print_file_in_html ~min_chap:start_chapter file outname;;
1818

1919
let parse_filename file outname start_chapter =
2020
if not (Sys.file_exists file) then (Printf.printf "The %s file do not exists" file; exit 2)

lib/dune

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
(include_subdirs unqualified)
2+
13
(library
24
(name htmlfromtexbooks)
35
(libraries str))

lib/htmlgen.ml

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
open Parser
2+
open Glossary
3+
open Utils
4+
5+
let url_encoded_str s = s;;
6+
7+
let print_table_of_content ast min_chap =
8+
let count = [|1;1;1;1|] in
9+
let rec aux acc ast =
10+
match ast with
11+
| [] -> acc
12+
| Chapter (s,l)::q ->
13+
let chapnum = count.(0) in
14+
begin
15+
count.(0) <- count.(0) + 1;
16+
count.(1) <- 1;
17+
count.(2) <- 1;
18+
count.(3) <- 1;
19+
end;
20+
let str = aux "" l in
21+
let new_line = if chapnum>=min_chap then Printf.sprintf "<li><a href=\"#c%i\">Chapter %i : %s</a></li>\n"
22+
chapnum (chapnum-min_chap+1) s else "" in
23+
aux (acc^new_line^str) q
24+
25+
| Section (s,l)::q ->
26+
let chapnum,secnum = count.(0),count.(1) in
27+
begin
28+
count.(1) <- count.(1) + 1;
29+
count.(2) <- 1;
30+
count.(3) <- 1;
31+
end;
32+
let str = aux "" l in
33+
let new_line = Printf.sprintf "<li><a href=\"#s%f\">Section %i.%i : %s</a></li>\n"
34+
(2.**(float chapnum)*.3.**(float secnum)) (chapnum-min_chap+1) secnum s in
35+
aux (acc^new_line^str) q
36+
37+
| Subsection (s,l)::q ->
38+
let chapnum,secnum,ssecnum = count.(0),count.(1),count.(2) in
39+
begin
40+
count.(2) <- count.(2) + 1;
41+
count.(3) <- 1;
42+
end;
43+
let str = aux "" l in
44+
let new_line = Printf.sprintf "<li><a href=\"#ss%f\">Subsection %i.%i.%i : %s</a></li>\n"
45+
(2.**(float chapnum)*.3.**(float secnum)*.5.**(float ssecnum)) (chapnum-min_chap+1) secnum ssecnum s in
46+
aux (acc^new_line^str) q
47+
48+
| Subsubsection (s,l)::q ->
49+
let chapnum,secnum,ssecnum,sssecnum = count.(0),count.(1),count.(2),count.(3) in
50+
begin
51+
count.(3) <- count.(3) + 1;
52+
end;
53+
let str = aux "" l in
54+
let new_line = Printf.sprintf "<li><a href=\"#sss%f\">Subsubsection %i.%i.%i.%i : %s</a></li>\n"
55+
(2.**(float chapnum)*.3.**(float secnum)*.5.**(float ssecnum)*.7.**(float sssecnum)) (chapnum-min_chap+1) secnum ssecnum sssecnum s in
56+
aux (acc^new_line^str) q
57+
| Env (_,l)::q -> let a = aux acc l in aux (acc^a) q
58+
| _::q -> aux acc q
59+
in (aux "" ast);;
60+
61+
let parse_to_html ?(min_chap=1) write_before ast=
62+
let count = [|1;1;1;1|] in
63+
let rec aux ?(write=write_before) acc ast =
64+
match ast with
65+
| [] -> acc
66+
| Nul::q -> aux acc q
67+
| Line s::q ->
68+
let line= if write then Printf.sprintf "%s\n" s else ""
69+
in aux ~write:write (acc^line) q
70+
| Math s::q ->
71+
let url = Printf.sprintf "https://latex.codecogs.com/svg.image?%s"s in
72+
let url = url_encoded_str url in
73+
let line = if write then Printf.sprintf "<img src=\"%s\"/>\n" url else ""
74+
in aux ~write:write (acc^line) q
75+
| AtomicCmd (s,_)::q ->
76+
let new_line = (match s with
77+
| "par" -> "<br/>\n"
78+
| "bigskip" -> "</p>\n\n<p>\n"
79+
| "\\" -> "<br/>\n"
80+
| "printglossaries" -> ""
81+
| "sep" -> "<div class=\"center\"><b>***</b></div>"
82+
| "item" -> "·"
83+
| "newline" -> "<br/>\n"
84+
| "ast" -> "*"
85+
| e ->
86+
(try
87+
let structure = Hashtbl.find commands e in
88+
let str = aux ~write:write acc structure
89+
in str
90+
with _ -> ""))
91+
in let new_acc = if write then acc^new_line^"\n" else ""
92+
in aux ~write:write new_acc q
93+
94+
| OneArgCmd (s,_,l)::q ->
95+
let str = aux "" l in
96+
let new_line = (match s with
97+
| "par" -> "<br/>\n"
98+
| "bigskip" -> "</p>\n\n<p>\n"
99+
| "\\" -> "<br/>\n"
100+
| "printglossaries" -> ""
101+
| "item" -> "·"
102+
| "sep" -> "<div class=\"center\"><b>***</b></div>"
103+
| "newline" -> "<br/>\n"
104+
| "ast" -> "*"
105+
| "gls" ->
106+
(match l with
107+
| [] -> ""
108+
| Line s::_ ->
109+
let name,_ = recognize_gls s in Printf.sprintf "<a href=\"#%s\">%s</a> " s name
110+
| _::_ -> "")
111+
| "textit" -> (Printf.sprintf "<i>%s</i>" str)
112+
| "textbf" -> (Printf.sprintf "<b>%s</b>" str)
113+
| "url" -> (Printf.sprintf "<a href=\"%s\">%s</a>" (Str.global_replace (Str.regexp "\n") "" str) str)
114+
| e ->
115+
(try
116+
let structure = Hashtbl.find commands e in
117+
let str = aux ~write:write acc structure
118+
in str
119+
with _ -> ""))
120+
in let new_acc = if write then acc^(new_line) else ""
121+
in aux ~write:write new_acc q
122+
123+
| Chapter (s,l)::q ->
124+
let chapnum = count.(0) in
125+
begin
126+
count.(0) <- count.(0) + 1;
127+
count.(1) <- 1;
128+
count.(2) <- 1;
129+
count.(3) <- 1;
130+
end;
131+
let str = aux ~write:(chapnum>=min_chap) "" l in
132+
let new_line = if chapnum>=min_chap then Printf.sprintf "<h1 id=\"c%i\">Chapter %i : %s</h1><br/>\n"
133+
chapnum (chapnum-min_chap+1) s else "" in
134+
aux ~write:write (acc^new_line^str) q
135+
136+
| Section (s,l)::q ->
137+
let chapnum,secnum = count.(0),count.(1) in
138+
begin
139+
count.(1) <- count.(1) + 1;
140+
count.(2) <- 1;
141+
count.(3) <- 1;
142+
end;
143+
let str = aux ~write:write "" l in
144+
let new_line = Printf.sprintf "<h2 id=\"s%f\">Section %i.%i : %s</h2><br/>\n"
145+
(2.**(float chapnum)*.3.**(float secnum)) (chapnum-min_chap+1) secnum s in
146+
aux ~write:write (acc^new_line^str) q
147+
148+
| Subsection (s,l)::q ->
149+
let chapnum,secnum,ssecnum = count.(0),count.(1),count.(2) in
150+
begin
151+
count.(2) <- count.(2) + 1;
152+
count.(3) <- 1;
153+
end;
154+
let str = aux ~write:write "" l in
155+
let new_line = Printf.sprintf "<h3 id=\"ss%f\">Subsection %i.%i.%i : %s</h3><br/>\n"
156+
(2.**(float chapnum)*.3.**(float secnum)*.5.**(float ssecnum)) (chapnum-min_chap+1) secnum ssecnum s in
157+
aux ~write:write (acc^new_line^str) q
158+
159+
| Subsubsection (s,l)::q ->
160+
let chapnum,secnum,ssecnum,sssecnum = count.(0),count.(1),count.(2),count.(3) in
161+
begin
162+
count.(3) <- count.(3) + 1;
163+
end;
164+
let str = aux ~write:write "" l in
165+
let new_line = Printf.sprintf "<h4 id=\"sss%f\">Subsubsection %i.%i.%i.%i : %s</h4><br/>\n"
166+
(2.**(float chapnum)*.3.**(float secnum)*.5.**(float ssecnum)*.7.**(float sssecnum)) (chapnum-min_chap+1) secnum ssecnum sssecnum s in
167+
aux ~write:write (acc^new_line^str) q
168+
169+
| Env (s,l)::q ->
170+
let str = aux ~write:write "" l in
171+
let new_line = (match s with
172+
| "document" -> str
173+
| "center" -> Printf.sprintf "<div style=\"margin: auto; text-align: center;\">\n%s\n</div>" str
174+
| _ -> str)
175+
in aux ~write:write (acc^new_line^"\n") q
176+
| _::q -> aux acc q
177+
in aux "" ast;;
178+
179+
180+
let prepare_body name str toc =
181+
let line = "<title>" ^ name ^ "</title>\n"
182+
in let line = line ^ "<body>\n"
183+
in let line = line ^ "<style>\n.center {\nmargin:auto;\ntext-align:center;\n}\n </style>"
184+
in let line = line ^ "<div class=\"center\">\n"
185+
in let line = line ^ (Printf.sprintf "<h1>%s</h1>\n" name)
186+
in let line = line ^ "<h2>Table of Content</h2>\n"
187+
in let line = line ^ "<ul>\n"
188+
in let line = line ^ toc ^ "\n"
189+
in let line = line ^ "</ul>\n"
190+
in let line = line ^ "</div>\n"
191+
in let line = line ^ str ^ "\n"
192+
in let line = line ^ (prints_glossary ()) ^ "\n"
193+
in let line = line ^ "</body>"
194+
in line;;
195+
196+
197+
let pre_parse_file file =
198+
let str = read_file file in
199+
let str = String.concat "\n" str in
200+
let a = parse_string str
201+
in let p,doc = separate_preamble a
202+
in read_preamble p;
203+
let doc = separate_sections doc
204+
in let doc = calculate_environments doc
205+
in let doc = Mathgen.re_calculate_env doc in
206+
(match (Hashtbl.find_opt preamble "glossary") with
207+
| Some s -> init_glossary s
208+
| None -> (););
209+
doc;;
210+
211+
212+
let print_file_in_html ?(min_chap=1) ?(write_before=false) file outname =
213+
let a = pre_parse_file file in
214+
let html = parse_to_html ~min_chap:min_chap write_before a in
215+
let toc = print_table_of_content a min_chap in
216+
let name = try Hashtbl.find preamble "title" with _ -> "Generic" in
217+
prepare_body name html toc
218+
|> write_to_file outname;;

lib/mathgen.ml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
open Parser
2+
3+
let generate_latex_command s l =
4+
let line = "\\"^s in
5+
let args = String.concat "," l in
6+
let line = if args="" then line else Printf.sprintf "%s[%s]" line args in
7+
line;;
8+
9+
10+
11+
let generate_latex l =
12+
let rec unparse acc l =
13+
match l with
14+
| [] -> String.concat " " acc
15+
| Line s::q -> unparse (s::acc) q
16+
| AtomicCmd (s,l)::q ->
17+
let line = generate_latex_command s l in
18+
unparse (line::acc) q
19+
| OneArgCmd (s,l,l2)::q ->
20+
let line = generate_latex_command s l in
21+
let line = Printf.sprintf "%s{%s}" line (unparse [] l2) in
22+
unparse (line::acc) q
23+
| MultipleArgCmd (s,l,l2)::q ->
24+
let line = generate_latex_command s l in
25+
let l = List.map (unparse []) l2 in
26+
let line = Printf.sprintf "%s{%s}" line (String.concat "\n" l) in
27+
unparse (line::acc) q
28+
| _::q -> unparse acc q
29+
in unparse [] l;;
30+
31+
let env_de_latexer env =
32+
match env with
33+
| e -> e;;
34+
35+
let re_calculate_env ast =
36+
let rec aux acc ast =
37+
match ast with
38+
| [] -> acc
39+
| Env (s,n)::q when s="align"
40+
-> aux (Math(Printf.sprintf "\\begin{align}%s\\end{align}" (generate_latex n))::acc) q
41+
| Env (s,n)::q when s="align*"
42+
-> aux (Math(Printf.sprintf "\\begin{align*}%s\\end{align*}" (generate_latex n))::acc) q
43+
| Env (s,n)::q when s="equation"
44+
-> aux (Math(Printf.sprintf "\\begin{equation}%s\\end{equation}" (generate_latex n))::acc) q
45+
| Env (s,n)::q when s="equation*"
46+
-> aux (Math(Printf.sprintf "\\begin{equation*}%s\\end{equation*}" (generate_latex n))::acc) q
47+
| Env(s,n)::q
48+
-> let ast = aux [] n in
49+
let ast = List.rev ast
50+
in let env = Env(s,ast)
51+
in aux (env::acc) q
52+
| e::q -> aux (e::acc) q
53+
in List.rev (aux [] ast);;

0 commit comments

Comments
 (0)