blob: 1a08ccf633eb3d4e15c2e5c0bb9ca336fd9d5772 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
\ 2022 - winduptoy.sensorstation.co
\ PUBLIC DOMAIN
\ USAGE
\ $ cat in.gmi | gforth gmi2html.fs > out.html
\
\ This only outputs major blocks, allowing full customization of the HTML document.
\ Best used in composition, like so:
\
\ $ cat _header.html > out.html
\ $ cat in.gmi | gforth gmi2html.fs >> out.html
\ $ cat _footer.html >> out.html
\ === HTML Output === \
\ : html-line-break ." <br>" ;
: html-line-break ." " ;
: html-blockquote-open ." <blockquote>" ;
: html-blockquote-close ." </blockquote>" ;
: html-preformatted-open ( c-content u -- )
.\" <pre aria-label=\"" type .\" \">" cr ;
: html-preformatted-close ." </pre>" cr ;
: html-list-open ." <ul>" ;
: html-list-close ." </ul>" ;
: html-paragraph-open ." <p>" ;
: html-paragraph-close ." </p>" ;
: html-list-item ( c-content u -- )
." <li>" type ." </li>" ;
: html-link ( c-content u c-url u -- )
.\" <p><a rel=\"noreferrer\" href=\"" type .\" \">"
type
." </a></p>"
;
: html-heading ( level c-content u -- )
." <h" 2 pick 48 + emit ." >"
type
." </h" 48 + emit ." >"
;
\ === Parsing === \
: starts-preformatted? ( c-addr u -- f )
s" ```" string-prefix? ;
: starts-blockquote? ( c-addr u -- f )
s" >" string-prefix? ;
: starts-list-item? ( c-addr u -- f )
s" *" string-prefix? ;
: starts-link? ( c-addr u -- f )
s" =>" string-prefix? ;
: starts-heading? ( c-addr u -- n ) \ returns header level
0 rot rot
3 min 0 ?do
dup i + c@ '# = if swap 1 + swap endif
loop drop ;
4096 constant line-buffer-size
create line-buffer line-buffer-size chars allot
variable line-number
variable line-len
0 constant capture-none
1 constant capture-preformatted
2 constant capture-blockquote
3 constant capture-list
variable capture-state
: process-line ( -- )
capture-state @ case
capture-preformatted of
line-buffer line-len @ starts-preformatted? if
html-preformatted-close
capture-none capture-state !
exit
else
line-buffer line-len @ type cr
exit
endif
endof
capture-blockquote of
line-buffer line-len @ starts-blockquote? invert if
html-blockquote-close
capture-none capture-state !
endif
endof
capture-list of
line-buffer line-len @ starts-list-item? invert if
html-list-close
capture-none capture-state !
endif
endof
endcase
line-buffer line-len @ starts-preformatted? if
capture-preformatted capture-state !
line-buffer line-len @ '` skip
html-preformatted-open
exit
endif
line-buffer line-len @ starts-blockquote? if
capture-state @ capture-blockquote = invert if
html-blockquote-open
capture-blockquote capture-state !
endif
line-buffer 1 + line-len @ 1 - type
html-line-break cr
exit
endif
line-buffer line-len @ starts-list-item? if
capture-state @ capture-list = invert if
html-list-open
capture-list capture-state !
endif
line-buffer 1 + line-len @ 1 - html-list-item cr
exit
endif
line-buffer line-len @ starts-heading? dup if
line-buffer line-len @ '# skip 32 skip 9 skip html-heading cr
exit
endif drop
line-buffer line-len @ starts-link? if
line-buffer line-len @ '= skip '> skip 32 skip 9 skip ( c-addr len )
\ find end of URL
over over 32 scan ( c-addr len label-addr label-len )
>r dup >r 2 pick - swap drop ( c-addr url-len )
r> r> 32 skip 9 skip ( c-addr url-len label-addr label-len )
dup 0 = if \ use the URL for the label if no label is provided
drop drop over over
endif
2swap
html-link
exit
endif
line-len @ 0 = if
html-line-break cr
else
html-paragraph-open
line-buffer line-len @ type
html-paragraph-close cr
endif
;
: gmi-to-html
begin
1 line-number +!
line-buffer line-buffer-size stdin read-line ( len flag err )
throw
invert if drop exit endif \ false flag == eof
line-len !
process-line
again ;
gmi-to-html
depth throw \ ensure stack is clean
bye
|