markita 2.0.210906 → 3.2.210915

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4bf395f9651feb6f5a7a4ede56db6a75fa0ea50383a0bc06a0cc1c8b39d27c8
4
- data.tar.gz: 5b76214448e81a4c24b01f287d3a8e11fcaead0a6c1b0e188e547d1dbb8617a0
3
+ metadata.gz: 2d00ccf97d0939c6b5ebd695e248046eabda96bc285b528f42ccec7e0ecddfaf
4
+ data.tar.gz: c3ad41a468998efd4511e72bae1cba352aca5f6ad7309f8ecb969fd3f83fe670
5
5
  SHA512:
6
- metadata.gz: 23339420ce626aa7f436ca31641deed88144684df32c4b947adf109f687341a1819e48780305683ab82fbfe63bf5170abf2afd1068aeb86d88b014d370e5e18f
7
- data.tar.gz: a7e8d715ff4d818f92afeec4bf64f074b10b8ac496495225ba0d1beb9e014098713c28690ea36ce46454d9a5a21e4f6780745eb34a7ae4b2f5f379f76abd80ee
6
+ metadata.gz: d24749f9a8550b67efe84f3ed16c42461f7a9cdfd5ab2608bc16af580af761c0761f86c4b7906feef3114f8c5f62ff67222e865cee85061799f6983ad509948b
7
+ data.tar.gz: 051d4e295dcff13a3b6bdf3679196741c18853cc8c9167ef6ac9a6bf20381c2fed38525e44c4def393e409d4d0bfa565e8e3a60388db4c117a3c320f976f5184
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Markita
2
2
 
3
- * [VERSION 2.0.210906](https://github.com/carlosjhr64/markita/releases)
3
+ * [VERSION 3.2.210915](https://github.com/carlosjhr64/markita/releases)
4
4
  * [github](https://www.github.com/carlosjhr64/markita)
5
5
  * [rubygems](https://rubygems.org/gems/markita)
6
6
 
@@ -27,6 +27,7 @@ Options:
27
27
  --no_about
28
28
  --no_favicon
29
29
  --no_highlight
30
+ --no_navigation
30
31
  --no_login
31
32
  --no_plugs
32
33
  Types:
@@ -62,11 +63,23 @@ Markdown:
62
63
  ![Left Floating ](/img/image.png)
63
64
  ![ Right Floating](/img/image.png)
64
65
  Image centered above.
65
- Image to the left.
66
+ Image to the left with width and height set.
66
67
  Image to the right.
67
68
  And set a HR bar below.
68
69
  ---
69
70
 
71
+ ### Image size
72
+
73
+ Markdown:
74
+
75
+ ![In alt text say 100x100](/img/image.png)
76
+
77
+ ### Image link
78
+
79
+ Markdown:
80
+
81
+ ![Alt text](/img/image.png /href_to/page)
82
+
70
83
  ### Forms
71
84
 
72
85
  Markdown:
@@ -83,6 +96,9 @@ Markdown:
83
96
  ! Address:[address]
84
97
  ! Code:[code="1234"]
85
98
 
99
+ A selection list:
100
+ ! Color:[color="Red","White","Blue"]
101
+
86
102
  ### Template substitutions
87
103
 
88
104
  Markdown:
data/bin/markita CHANGED
@@ -13,13 +13,13 @@ Options:
13
13
  --no_about
14
14
  --no_favicon
15
15
  --no_highlight
16
+ --no_navigation
16
17
  --no_login
17
18
  --no_plugs
18
19
  Types:
19
20
  DIRECTORY /^~?[\\/\\w\\.]+$/
20
21
  BIND /^[\\w\\.]+$/
21
22
  PORT /^\\d+$/
22
- THEME /^[\\w\\.]+$/
23
23
  IPS /^[\\d\\.\\,]+$/
24
24
  # NOTE:
25
25
  # Assuming site is in ~/vimwiki,
data/lib/markita/base.rb CHANGED
@@ -1,33 +1,4 @@
1
1
  module Markita
2
- class Preprocess
3
- def initialize(file)
4
- @file = (file.is_a? String)? StringIO.new(file) : file
5
- @regx = @template = nil
6
- end
7
-
8
- def gets
9
- if line = @file.gets
10
- case line
11
- when @regx
12
- line = @template if @template
13
- $~.named_captures.each do |name, value|
14
- line = line.gsub("&#{name.downcase};", value)
15
- line = line.gsub("&#{name.upcase};", CGI.escape(value))
16
- end
17
- when %r(^! regx = /(.*)/$)
18
- @regx = Regexp.new $1
19
- line = gets
20
- when %r(^! template = "(.*)"$)
21
- @template = $1+"\n"
22
- line = gets
23
- else
24
- @regx &&= (@template=nil)
25
- end
26
- end
27
- line
28
- end
29
- end
30
-
31
2
  class Base < Sinatra::Base
32
3
  set bind: OPTIONS&.bind || '0.0.0.0'
33
4
  set port: OPTIONS&.port || '8080'
@@ -47,44 +18,10 @@ class Base < Sinatra::Base
47
18
  end
48
19
  end
49
20
 
50
- def Base.header(key)
51
- <<~HEADER
52
- <!DOCTYPE html>
53
- <html>
54
- <head>
55
- <title>#{key}</title>
56
- #{HEADER_LINKS}</head>
57
- <body>
58
- HEADER
59
- end
60
-
61
- def Base.footer
62
- <<~FOOTER
63
- </body>
64
- </html>
65
- FOOTER
66
- end
67
-
68
- DEFAULT = lambda do |line, html, file, _, _|
69
- html << line
70
- file.gets
71
- end
72
-
73
- def Base.page(key, f)
74
- html,opt,file,line = '',{},Preprocess.new(f),Base.header(key)
75
- fct,md = nil,nil
76
- while line = (fct||DEFAULT)[line, html, file, opt, md]
77
- fct = nil
78
- Markdown::PARSER.each{|r,f| break if md=r.match(line) and fct=f}
79
- end
80
- html << Base.footer
81
- html
82
- end
83
-
84
21
  get PAGE_KEY do |key|
85
22
  filepath = File.join ROOT, key+'.md'
86
23
  raise Sinatra::NotFound unless File.exist? filepath
87
- File.open(filepath, 'r'){|f| Base.page key, f}
24
+ Markdown.new(key).filepath filepath
88
25
  end
89
26
 
90
27
  get IMAGE_PATH do |path, *_|
@@ -2,6 +2,7 @@ module Markita
2
2
  OPTIONS ||= nil
3
3
 
4
4
  HEADER_LINKS = ''
5
+ NAVIGATION = ''
5
6
 
6
7
  ROOT = File.expand_path OPTIONS&.root || '~/vimwiki'
7
8
  raise "Missing site root directory: "+ROOT unless File.directory? ROOT
@@ -0,0 +1,25 @@
1
+ module Markita
2
+ module HTML
3
+ def HTML.header(key)
4
+ <<~HEADER
5
+ <!DOCTYPE html>
6
+ <html>
7
+ <head>
8
+ <title>#{key}</title>
9
+ #{HEADER_LINKS}</head>
10
+ <body>
11
+ HEADER
12
+ end
13
+
14
+ def HTML.navigation
15
+ NAVIGATION
16
+ end
17
+
18
+ def HTML.footer
19
+ <<~FOOTER
20
+ </body>
21
+ </html>
22
+ FOOTER
23
+ end
24
+ end
25
+ end
@@ -1,269 +1,344 @@
1
1
  module Markita
2
- module Markdown
2
+ class Markdown
3
+ ROUGE = Rouge::Formatters::HTML.new
4
+ PARSERS = []
5
+
6
+ def initialize(title)
7
+ @title = title
8
+ @line=@html=@file=@opt=nil
9
+ end
10
+
11
+ def start
12
+ @html << HTML.header(@title)
13
+ @line = HTML.navigation
14
+ end
15
+
16
+ def finish
17
+ @html << HTML.footer
18
+ @line = nil
19
+ end
20
+
21
+ def default
22
+ @html << @line
23
+ @line = @file.gets
24
+ end
25
+
26
+ def init(fh)
27
+ @file,@html,@opt = Preprocess.new(fh),'',{}
28
+ end
29
+
30
+ def parse(fh)
31
+ init(fh)
32
+ start
33
+ while @line
34
+ PARSERS.detect{method(_1).call} or default
35
+ end
36
+ finish
37
+ end
38
+
39
+ def markdown(string)
40
+ parse StringIO.new string
41
+ @html
42
+ end
43
+
44
+ def filepath(filepath)
45
+ File.open(filepath, 'r'){|fh| parse fh}
46
+ @html
47
+ end
48
+
3
49
  Ux = /_([^_]+)_/
4
- U = lambda {|md| "<u>#{md[1]}</u>"}
50
+ U = lambda {|m| "<u>#{m[1]}</u>"}
5
51
 
6
52
  Sx = /~([^~]+)~/
7
- S = lambda {|md| "<s>#{md[1]}</s>"}
53
+ S = lambda {|m| "<s>#{m[1]}</s>"}
8
54
 
9
55
  Ix = /"([^"]+)"/
10
- I = lambda {|md| "<i>#{md[1]}</i>"}
56
+ I = lambda {|m| "<i>#{m[1]}</i>"}
11
57
 
12
58
  Bx = /\*([^\*]+)\*/
13
- B = lambda {|md| "<b>#{md[1]}</b>"}
59
+ B = lambda {|m| "<b>#{m[1]}</b>"}
14
60
 
15
61
  CODEx = /`([^`]+)`/
16
- CODE = lambda {|md| "<code>#{md[1]}</code>"}
62
+ CODE = lambda {|m| "<code>#{m[1]}</code>"}
17
63
 
18
64
  Ax = /\[([^\[\]]+)\]\(([^()]+)\)/
19
- A = lambda {|md| %Q(<a href="#{md[2]}">#{md[1]}</a>)}
65
+ A = lambda {|m| %Q(<a href="#{m[2]}">#{m[1]}</a>)}
20
66
 
21
67
  URLx = %r(\[(https?://[\w\.\-\/\&\+\?\%]+)\])
22
- URL = lambda {|md| %Q(<a href="#{md[1]}">#{md[1]}</a>)}
68
+ URL = lambda {|m| %Q(<a href="#{m[1]}">#{m[1]}</a>)}
23
69
 
24
70
  EMOJIx = /:(\w+):/
25
- EMOJI = lambda {|md| (_=EMOJIS[md[1]])? "&\#x#{_};" : md[0]}
71
+ EMOJI = lambda {|m| (_=EMOJIS[m[1]])? "&\#x#{_};" : m[0]}
26
72
 
27
73
  FOOTNOTEx = /\[\^(\d+)\](:)?/
28
- FOOTNOTE = lambda do |md|
29
- if md[2]
30
- %Q(<a id="fn:#{md[1]}" href="\#fnref:#{md[1]}">#{md[1]}:</a>)
74
+ FOOTNOTE = lambda do |m|
75
+ if m[2]
76
+ %Q(<a id="fn:#{m[1]}" href="\#fnref:#{m[1]}">#{m[1]}:</a>)
31
77
  else
32
- %Q(<a id="fnref:#{md[1]}" href="\#fn:#{md[1]}"><sup>#{md[1]}</sup></a>)
78
+ %Q(<a id="fnref:#{m[1]}" href="\#fn:#{m[1]}"><sup>#{m[1]}</sup></a>)
33
79
  end
34
80
  end
35
81
 
36
- def Markdown.tag(line, regx, md2string, &block)
37
- if md = regx.match(line)
38
- pre_match = (block ? block.call(md.pre_match) : md.pre_match)
39
- string = pre_match + md2string[md]
40
- post_match = md.post_match
41
- while md = regx.match(post_match)
42
- pre_match = (block ? block.call(md.pre_match) : md.pre_match)
43
- string << pre_match + md2string[md]
44
- post_match = md.post_match
82
+ def Markdown.tag(entry, regx, m2string, &block)
83
+ if m = regx.match(entry)
84
+ pre_match = (block ? block.call(m.pre_match) : m.pre_match)
85
+ string = pre_match + m2string[m]
86
+ post_match = m.post_match
87
+ while m = regx.match(post_match)
88
+ pre_match = (block ? block.call(m.pre_match) : m.pre_match)
89
+ string << pre_match + m2string[m]
90
+ post_match = m.post_match
45
91
  end
46
92
  string << (block ? block.call(post_match) : post_match)
47
93
  return string
48
94
  end
49
- return (block ? block.call(line) : line)
95
+ return (block ? block.call(entry) : entry)
50
96
  end
51
97
 
52
- INLINE = lambda do |line|
53
- string = Markdown.tag(line, CODEx, CODE) do |line|
54
- Markdown.tag(line, Ax, A) do |line|
55
- Markdown.tag(line, URLx, URL) do |line|
56
- string = Markdown.tag(line, Bx, B)
57
- string = Markdown.tag(string, Ix, I)
58
- string = Markdown.tag(string, Sx, S)
59
- string = Markdown.tag(string, Ux, U)
60
- string = Markdown.tag(string, FOOTNOTEx, FOOTNOTE)
61
- Markdown.tag(string, EMOJIx, EMOJI)
98
+ INLINE = lambda do |entry|
99
+ string = Markdown.tag(entry, CODEx, CODE) do |entry|
100
+ Markdown.tag(entry, Ax, A) do |entry|
101
+ Markdown.tag(entry, URLx, URL) do |entry|
102
+ entry = Markdown.tag(entry, EMOJIx, EMOJI)
103
+ entry = Markdown.tag(entry, Bx, B)
104
+ entry = Markdown.tag(entry, Ix, I)
105
+ entry = Markdown.tag(entry, Sx, S)
106
+ entry = Markdown.tag(entry, Ux, U)
107
+ entry = Markdown.tag(entry, FOOTNOTEx, FOOTNOTE)
62
108
  end
63
109
  end
64
110
  end
65
111
  string.sub(/ $/,'<br>')
66
112
  end
67
113
 
68
- PARSER = Hash.new
69
-
70
114
  # Empty
71
- PARSER[/^$/] = lambda do |_, _, file, _, _|
72
- file.gets
115
+ EMPTY = /^$/
116
+ PARSERS << :empty
117
+ def empty
118
+ EMPTY.match?(@line) or return false
119
+ @line = @file.gets
120
+ true
73
121
  end
74
122
 
75
123
  # Ordered list
76
124
  ORDERED = /^\d+. (.*)$/
77
- PARSER[ORDERED] = lambda do |line, html, file, opt, md|
78
- html << "<ol#{opt[:attributes]}>\n"
79
- opt.delete(:attributes)
125
+ PARSERS << :ordered
126
+ def ordered
127
+ md = ORDERED.match(@line) or return false
128
+ @html << "<ol#{@opt[:attributes]}>\n"
129
+ @opt.delete(:attributes)
80
130
  while md
81
- html << " <li>#{INLINE[md[1]]}</li>\n"
82
- md = (line=file.gets)&.match ORDERED
131
+ @html << " <li>#{INLINE[md[1]]}</li>\n"
132
+ md = (@line=@file.gets)&.match ORDERED
83
133
  end
84
- html << "</ol>\n"
85
- line
134
+ @html << "</ol>\n"
135
+ true
86
136
  end
87
137
 
88
138
  # Paragraph
89
139
  PARAGRAPHS = /^[\[`*"~_]?\w/
90
- PARSER[PARAGRAPHS] = lambda do |line, html, file, opt, md|
91
- html << "<p#{opt[:attributes]}>\n"
92
- opt.delete(:attributes)
140
+ PARSERS << :paragraphs
141
+ def paragraphs
142
+ md = PARAGRAPHS.match(@line) or return false
143
+ @html << "<p#{@opt[:attributes]}>\n"
144
+ @opt.delete(:attributes)
93
145
  while md
94
- html << INLINE[line]
95
- md = (line=file.gets)&.match PARAGRAPHS
146
+ @html << INLINE[@line]
147
+ md = (@line=@file.gets)&.match PARAGRAPHS
96
148
  end
97
- html << "</p>\n"
98
- line
149
+ @html << "</p>\n"
150
+ true
99
151
  end
100
152
 
101
153
  # Unordered list
102
154
  UNORDERED = /^[*] (.*)$/
103
- PARSER[UNORDERED] = lambda do |line, html, file, opt, md|
104
- html << "<ul#{opt[:attributes]}>\n"
105
- opt.delete(:attributes)
155
+ PARSERS << :unordered
156
+ def unordered
157
+ md = UNORDERED.match(@line) or return false
158
+ @html << "<ul#{@opt[:attributes]}>\n"
159
+ @opt.delete(:attributes)
106
160
  while md
107
- html << " <li>#{INLINE[md[1]]}</li>\n"
108
- md = (line=file.gets)&.match UNORDERED
161
+ @html << " <li>#{INLINE[md[1]]}</li>\n"
162
+ md = (@line=@file.gets)&.match UNORDERED
109
163
  end
110
- html << "</ul>\n"
111
- line
164
+ @html << "</ul>\n"
165
+ true
112
166
  end
113
167
 
114
168
  # Ballot box
115
169
  BALLOTS = /^- \[(x| )\] (.*)$/
116
- PARSER[BALLOTS] = lambda do |line, html, file, opt, md|
117
- html << "<ul#{opt[:attributes]}>\n"
118
- opt.delete(:attributes)
170
+ PARSERS << :ballots
171
+ def ballots
172
+ md = BALLOTS.match(@line) or return false
173
+ @html << "<ul#{@opt[:attributes]}>\n"
174
+ @opt.delete(:attributes)
119
175
  while md
120
176
  x,t = md[1],md[2]
121
177
  li = (x=='x')?
122
178
  %q{<li style="list-style-type: '&#9745; '">} :
123
179
  %q{<li style="list-style-type: '&#9744; '">}
124
- html << " #{li}#{INLINE[t]}</li>\n"
125
- md = (line=file.gets)&.match BALLOTS
180
+ @html << " #{li}#{INLINE[t]}</li>\n"
181
+ md = (@line=@file.gets)&.match BALLOTS
126
182
  end
127
- html << "</ul>\n"
128
- line
183
+ @html << "</ul>\n"
184
+ true
129
185
  end
130
186
 
131
187
  # Definition list
132
188
  DEFINITIONS = /^: (.*)$/
133
- PARSER[DEFINITIONS] = lambda do |line, html, file, opt, md|
134
- html << "<dl#{opt[:attributes]}>\n"
135
- opt.delete(:attributes)
189
+ PARSERS << :definitions
190
+ def definitions
191
+ md = DEFINITIONS.match(@line) or return false
192
+ @html << "<dl#{@opt[:attributes]}>\n"
193
+ @opt.delete(:attributes)
136
194
  while md
137
195
  item = md[1]
138
- line = ((item[-1]==':')? "<dt>#{INLINE[item[0..-2]]}</dt>\n" :
196
+ @html << ((item[-1]==':')? "<dt>#{INLINE[item[0..-2]]}</dt>\n" :
139
197
  "<dd>#{INLINE[item]}</dd>\n")
140
- html << line
141
- md = (line=file.gets)&.match DEFINITIONS
198
+ md = (@line=@file.gets)&.match DEFINITIONS
142
199
  end
143
- html << "</dl>\n"
144
- line
200
+ @html << "</dl>\n"
201
+ true
145
202
  end
146
203
 
147
204
  # Headers
148
205
  HEADERS = /^([#]{1,6}) (.*)$/
149
- PARSER[HEADERS] = lambda do |line, html, file, opt, md|
206
+ PARSERS << :headers
207
+ def headers
208
+ md = HEADERS.match(@line) or return false
150
209
  i,header = md[1].length,md[2]
151
210
  id = header.strip.gsub(/\s+/,'+')
152
- html << %Q(<a id="#{id}">\n)
153
- html << " <h#{i}#{opt[:attributes]}>#{INLINE[header]}</h#{i}>\n"
154
- html << "</a>\n"
155
- opt.delete(:attributes)
156
- file.gets
211
+ @html << %Q(<a id="#{id}">\n)
212
+ @html << " <h#{i}#{@opt[:attributes]}>#{INLINE[header]}</h#{i}>\n"
213
+ @html << "</a>\n"
214
+ @opt.delete(:attributes)
215
+ @line = @file.gets
216
+ true
157
217
  end
158
218
 
159
219
  # Block-quote
160
220
  BLOCKQS = /^> (.*)$/
161
- PARSER[BLOCKQS] = lambda do |line, html, file, opt, md|
162
- html << "<blockquote#{opt[:attributes]}>\n"
163
- opt.delete(:attributes)
221
+ PARSERS << :blockqs
222
+ def blockqs
223
+ md = BLOCKQS.match(@line) or return false
224
+ @html << "<blockquote#{@opt[:attributes]}>\n"
225
+ @opt.delete(:attributes)
164
226
  while md
165
- html << INLINE[md[1]]
166
- html << "\n"
167
- md = (line=file.gets)&.match BLOCKQS
227
+ @html << INLINE[md[1]]
228
+ @html << "\n"
229
+ md = (@line=@file.gets)&.match BLOCKQS
168
230
  end
169
- html << "</blockquote>\n"
170
- line
231
+ @html << "</blockquote>\n"
232
+ true
171
233
  end
172
234
 
173
- HTML = Rouge::Formatters::HTML.new
174
235
 
175
236
  # Code
176
237
  CODES = /^[`~]{3}\s*(\w+)?$/
177
- PARSER[CODES] = lambda do |line, html, file, opt, md|
238
+ PARSERS << :codes
239
+ def codes
240
+ md = CODES.match(@line) or return false
178
241
  lang = Rouge::Lexer.find md[1]
179
242
  klass = lang ? ' class="highlight"' : nil
180
- html << "<pre#{klass}#{opt[:attributes]}><code>\n"
181
- opt.delete(:attributes)
243
+ @html << "<pre#{klass}#{@opt[:attributes]}><code>\n"
244
+ @opt.delete(:attributes)
182
245
  code = ''
183
- while line=file.gets and not CODES.match(line)
184
- code << line
246
+ while @line=@file.gets and not CODES.match(@line)
247
+ code << @line
185
248
  end
186
- html << (lang ? HTML.format(lang.new.lex(code)) : code)
187
- html << "</code></pre>\n"
188
- # line is either nil or the code close
189
- line and file.gets
249
+ @html << (lang ? ROUGE.format(lang.new.lex(code)) : code)
250
+ @html << "</code></pre>\n"
251
+ @line = @file.gets if @line # then it's code close and thus need next @line.
252
+ true
190
253
  end
191
254
 
192
255
  # Preform
193
256
  PREFORMS = /^ {4}(.*)$/
194
- PARSER[PREFORMS] = lambda do |line, html, file, opt, md|
195
- html << "<pre#{opt[:attributes]}>\n"
196
- opt.delete(:attributes)
257
+ PARSERS << :preforms
258
+ def preforms
259
+ md = PREFORMS.match(@line) or return false
260
+ @html << "<pre#{@opt[:attributes]}>\n"
261
+ @opt.delete(:attributes)
197
262
  while md
198
- html << md[1]
199
- html << "\n"
200
- md = (line=file.gets)&.match PREFORMS
263
+ @html << md[1]
264
+ @html << "\n"
265
+ md = (@line=@file.gets)&.match PREFORMS
201
266
  end
202
- html << "</pre>\n"
203
- line
267
+ @html << "</pre>\n"
268
+ true
204
269
  end
205
270
 
206
271
  # Horizontal rule
207
272
  HRS = /^---+$/
208
- PARSER[HRS] = lambda do |_, html, file, opt, _|
209
- html << "<hr#{opt[:attributes]}>\n"
210
- opt.delete(:attributes)
211
- file.gets
273
+ PARSERS << :hrs
274
+ def hrs
275
+ HRS.match? @line or return false
276
+ @html << "<hr#{@opt[:attributes]}>\n"
277
+ @opt.delete(:attributes)
278
+ @line = @file.gets
279
+ true
212
280
  end
213
281
 
214
282
  # Table
215
283
  TABLES = /^\|.+\|$/
216
- PARSER[TABLES] = lambda do |line, html, file, opt, _|
217
- html << "<table#{opt[:attributes]}>\n"
218
- opt.delete(:attributes)
219
- html << '<thead><tr><th>'
220
- html << line[1...-1].split('|').map{INLINE[_1.strip]}.join('</th><th>')
221
- html << "</th></tr></thead>\n"
284
+ PARSERS << :tables
285
+ def tables
286
+ TABLES.match? @line or return false
287
+ @html << "<table#{@opt[:attributes]}>\n"
288
+ @opt.delete(:attributes)
289
+ @html << '<thead><tr><th>'
290
+ @html << @line[1...-1].split('|').map{INLINE[_1.strip]}.join('</th><th>')
291
+ @html << "</th></tr></thead>\n"
222
292
  align = []
223
- while (line=file.gets)&.match TABLES
224
- html << '<tr>'
225
- line[1...-1].split('|').each_with_index do |cell, i|
293
+ while (@line=@file.gets)&.match TABLES
294
+ @html << '<tr>'
295
+ @line[1...-1].split('|').each_with_index do |cell, i|
226
296
  case cell
227
297
  when /^\s*:-+:\s*$/
228
298
  align[i] = ' align="center"'
229
- html << '<td><hr></td>'
299
+ @html << '<td><hr></td>'
230
300
  when /^\s*-+:\s*$/
231
301
  align[i] = ' align="right"'
232
- html << '<td><hr></td>'
302
+ @html << '<td><hr></td>'
233
303
  when /^\s*:-+\s*$/
234
304
  align[i] = ' align="left"'
235
- html << '<td><hr></td>'
305
+ @html << '<td><hr></td>'
236
306
  else
237
- html << "<td#{align[i]}>#{INLINE[cell.strip]}</td>"
307
+ @html << "<td#{align[i]}>#{INLINE[cell.strip]}</td>"
238
308
  end
239
309
  end
240
- html << "</tr>\n"
310
+ @html << "</tr>\n"
241
311
  end
242
- html << "</table>\n"
243
- line
312
+ @html << "</table>\n"
313
+ true
244
314
  end
245
315
 
246
316
  # Splits
247
317
  SPLITS = /^:?\|:?$/
248
- PARSER[SPLITS] = lambda do |line, html, file, opt, _|
249
- case line.chomp
318
+ PARSERS << :splits
319
+ def splits
320
+ SPLITS.match? @line or return false
321
+ case @line.chomp
250
322
  when '|:'
251
- html << %Q(<table><tr><td#{opt[:attributes]}>\n)
323
+ @html << %Q(<table><tr><td#{@opt[:attributes]}>\n)
252
324
  when '|'
253
- html << %Q(</td><td#{opt[:attributes]}>\n)
325
+ @html << %Q(</td><td#{@opt[:attributes]}>\n)
254
326
  when ':|:'
255
- html << %Q(</td></tr><tr><td#{opt[:attributes]}>\n)
327
+ @html << %Q(</td></tr><tr><td#{@opt[:attributes]}>\n)
256
328
  when ':|'
257
- html << %Q(</td></tr></table>\n)
329
+ @html << %Q(</td></tr></table>\n)
258
330
  end
259
- opt.delete(:attributes)
260
- file.gets
331
+ @opt.delete(:attributes)
332
+ @line = @file.gets
333
+ true
261
334
  end
262
335
 
263
336
  # Image
264
337
  IMAGES = /^!\[([^\[\]]+)\]\(([^\(\)]+)\)$/
265
- PARSER[IMAGES] = lambda do |line, html, file, opt, md|
266
- alt,src=md[1],md[2]
338
+ PARSERS << :images
339
+ def images
340
+ md = IMAGES.match(@line) or return false
341
+ alt,src,href=md[1],*md[2].strip.split(/\s+/,2)
267
342
  style = ' '
268
343
  case alt
269
344
  when /^ .* $/
@@ -273,30 +348,50 @@ module Markdown
273
348
  when /^ /
274
349
  style = %Q( style="float:right;" )
275
350
  end
276
- html << %Q(<img src="#{src}"#{style}alt="#{alt.strip}"#{opt[:attributes]}>\n)
277
- opt.delete(:attributes)
278
- file.gets
351
+ if /(\d+)x(\d+)/.match alt
352
+ style << %Q(width="#{$1}" height="#{$2}" )
353
+ end
354
+ @html << %Q(<a href="#{href}">\n) if href
355
+ @html << %Q(<img src="#{src}"#{style}alt="#{alt.strip}"#{@opt[:attributes]}>\n)
356
+ @html << %Q(</a>\n) if href
357
+ @opt.delete(:attributes)
358
+ @line = @file.gets
359
+ true
279
360
  end
280
361
 
281
362
  # Forms
282
- FORMS = /^!( (\w+:)?\[\*?\w+(="[^"]*")?\])+/
283
- PARSER[FORMS] = lambda do |line, html, file, opt, md|
363
+ FIELD = '(\w+:)?\[(\*)?(\w+)(=("[^"]+")(,"[^"]+")*)?\]'
364
+ FIELDS = Regexp.new FIELD
365
+ FORMS = Regexp.new "^!( #{FIELD})+"
366
+ PARSERS << :forms
367
+ def forms
368
+ md = FORMS.match(@line) or return false
284
369
  form = []
285
- lines,fields,submit,method = 0,0,nil,nil
286
- action = (_=/\(([^\(\)]*)\)$/.match(line))? _[1] : nil
370
+ n,fields,submit,method = 0,0,nil,nil
371
+ action = (_=/\(([^\(\)]*)\)$/.match(@line))? _[1] : nil
287
372
  while md
288
- lines += 1
289
- form << ' <br>' if lines > 1
290
- line.scan(/(\w+:)?\[(\*)?(\w+)(="[^"]*")?\]/).each do |field, pwd, name, value|
373
+ n += 1
374
+ form << ' <br>' if n > 1
375
+ @line.scan(FIELDS).each do |field, pwd, name, value|
291
376
  method ||= ' method="post"' if pwd
292
377
  field &&= field[0...-1]
293
378
  value &&= value[2...-1]
294
379
  if field
295
- fields += 1
296
380
  type = (pwd)? 'password' : 'text'
297
381
  if value
298
- form << %Q{ #{field}:<input type="#{type}" name="#{name}" value="#{value}">}
382
+ if (values = value.split('","')).length > 1
383
+ form << %Q(#{field}:<select name="#{name}">)
384
+ values.each do |value|
385
+ fields += 1
386
+ form << %Q( <option value="#{value}">#{value}</option>)
387
+ end
388
+ form << "</select>"
389
+ else
390
+ fields += 1
391
+ form << %Q{ #{field}:<input type="#{type}" name="#{name}" value="#{value}">}
392
+ end
299
393
  else
394
+ fields += 1
300
395
  form << %Q{ #{field}:<input type="#{type}" name="#{name}">}
301
396
  end
302
397
  elsif name=='submit'
@@ -305,51 +400,59 @@ module Markdown
305
400
  form << %Q{ <input type="hidden" name="#{name}" value="#{value}">}
306
401
  end
307
402
  end
308
- md = (line=file.gets)&.match FORMS
403
+ md = (@line=@file.gets)&.match FORMS
309
404
  end
310
405
  if submit or not fields==1
311
406
  submit ||= 'Submit'
312
- form << ' <br>' if lines > 1
407
+ form << ' <br>' if n > 1
313
408
  form << %Q( <input type="submit" value="#{submit}">)
314
409
  end
315
- form.unshift %Q(<form action="#{action}"#{method}#{opt[:attributes]}>)
410
+ form.unshift %Q(<form action="#{action}"#{method}#{@opt[:attributes]}>)
316
411
  form << %Q(</form>)
317
- html << form.join("\n")
318
- html << "\n"
319
- opt.delete(:attributes)
320
- line
412
+ @html << form.join("\n")
413
+ @html << "\n"
414
+ @opt.delete(:attributes)
415
+ true
321
416
  end
322
417
 
323
418
  # Embed text
324
419
  EMBED_TEXTS = /^!> (#{PAGE_KEY}\.txt)$/
325
- PARSER[EMBED_TEXTS] = lambda do |line, html, file, opt, md|
420
+ PARSERS << :embed_texts
421
+ def embed_texts
422
+ md = EMBED_TEXTS.match(@line) or return false
326
423
  if File.exist?(filename=File.join(ROOT, md[1]))
327
- html << "<pre>\n"
328
- html << File.read(filename)
329
- html << "</pre>\n"
424
+ @html << "<pre>\n"
425
+ @html << File.read(filename)
426
+ @html << "</pre>\n"
330
427
  else
331
- html << line
428
+ @html << @line
332
429
  end
333
- file.gets
430
+ @line = @file.gets
431
+ true
334
432
  end
335
433
 
336
434
  # Footnotes
337
435
  FOOTNOTES = /^\[\^\d+\]:/
338
- PARSER[FOOTNOTES] = lambda do |line, html, file, opt, md|
339
- html << "<small>\n"
436
+ PARSERS << :footnotes
437
+ def footnotes
438
+ md = FOOTNOTES.match(@line) or return false
439
+ @html << "<small>\n"
340
440
  while md
341
- html << INLINE[line.chomp]+"<br>\n"
342
- md = (line=file.gets)&.match FOOTNOTES
441
+ @html << INLINE[@line.chomp]+"<br>\n"
442
+ md = (@line=@file.gets)&.match FOOTNOTES
343
443
  end
344
- html << "</small>\n"
345
- line
444
+ @html << "</small>\n"
445
+ true
346
446
  end
347
447
 
348
448
  # Attributes
349
449
  ATTRIBUTES = /^\{:( .*)\}/
350
- PARSER[ATTRIBUTES] = lambda do |line, html, file, opt, md|
351
- opt[:attributes] = md[1]
352
- md.post_match
450
+ PARSERS << :attributes
451
+ def attributes
452
+ md = ATTRIBUTES.match(@line) or return false
453
+ @opt[:attributes] = md[1]
454
+ @line = md.post_match
455
+ true
353
456
  end
354
457
  end
355
458
  end
@@ -27,7 +27,7 @@ class Base
27
27
  end
28
28
 
29
29
  get '/about.html' do
30
- Base.page 'about', About.page
30
+ Markdown.new('About').markdown About.page
31
31
  end
32
32
  end
33
33
  end
@@ -1,5 +1,5 @@
1
1
  module Markita
2
- class Base < Sinatra::Base
2
+ class Base
3
3
  HEADER_LINKS << %Q( <link rel="icon" type="image/x-icon" href="/favicon.ico">\n)
4
4
  module Favicon
5
5
  ICO = File.read PATH['favicon.ico']
@@ -1,5 +1,5 @@
1
1
  module Markita
2
- class Base < Sinatra::Base
2
+ class Base
3
3
  HEADER_LINKS << %Q( <link rel="stylesheet" href="/highlight.css" type="text/css">\n)
4
4
  module Highlight
5
5
  CSS = File.read PATH['highlight.css']
@@ -0,0 +1,3 @@
1
+ module Markita
2
+ NAVIGATION << %Q(![ Navigation](/favicon.ico /index)\n)
3
+ end
@@ -0,0 +1,30 @@
1
+ module Markita
2
+ class Preprocess
3
+ def initialize(file)
4
+ @file = (file.is_a? String)? StringIO.new(file) : file
5
+ @regx = @template = nil
6
+ end
7
+
8
+ def gets
9
+ if line = @file.gets
10
+ case line
11
+ when @regx
12
+ line = @template if @template
13
+ $~.named_captures.each do |name, value|
14
+ line = line.gsub("&#{name.downcase};", value)
15
+ line = line.gsub("&#{name.upcase};", CGI.escape(value))
16
+ end
17
+ when %r(^! regx = /(.*)/$)
18
+ @regx = Regexp.new $1
19
+ line = gets
20
+ when %r(^! template = "(.*)"$)
21
+ @template = $1+"\n"
22
+ line = gets
23
+ else
24
+ @regx &&= (@template=nil)
25
+ end
26
+ end
27
+ line
28
+ end
29
+ end
30
+ end
data/lib/markita.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Markita
2
- VERSION = '2.0.210906'
2
+ VERSION = '3.2.210915'
3
3
 
4
4
  def self.run!
5
5
  # Standard libraries
@@ -11,11 +11,14 @@ module Markita
11
11
  require 'thin'
12
12
  # Local
13
13
  require_relative 'markita/config.rb'
14
+ require_relative 'markita/html.rb'
15
+ require_relative 'markita/preprocess.rb'
14
16
  require_relative 'markita/markdown.rb'
15
17
  require_relative 'markita/base.rb'
16
18
  # Plugs
17
19
  require_relative 'markita/plug/favicon.rb' unless OPTIONS&.no_favicon
18
20
  require_relative 'markita/plug/highlight.rb' unless OPTIONS&.no_highlight
21
+ require_relative 'markita/plug/navigation.rb' unless OPTIONS&.no_navigation
19
22
  require_relative 'markita/plug/login.rb' unless OPTIONS&.no_login
20
23
  require_relative 'markita/plug/about.rb' unless OPTIONS&.no_about
21
24
  require_relative 'markita/plug/plugs.rb' unless OPTIONS&.no_plugs
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markita
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.210906
4
+ version: 3.2.210915
5
5
  platform: ruby
6
6
  authors:
7
7
  - CarlosJHR64
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-06 00:00:00.000000000 Z
11
+ date: 2021-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: help_parser
@@ -111,12 +111,15 @@ files:
111
111
  - lib/markita.rb
112
112
  - lib/markita/base.rb
113
113
  - lib/markita/config.rb
114
+ - lib/markita/html.rb
114
115
  - lib/markita/markdown.rb
115
116
  - lib/markita/plug/about.rb
116
117
  - lib/markita/plug/favicon.rb
117
118
  - lib/markita/plug/highlight.rb
118
119
  - lib/markita/plug/login.rb
120
+ - lib/markita/plug/navigation.rb
119
121
  - lib/markita/plug/plugs.rb
122
+ - lib/markita/preprocess.rb
120
123
  homepage: https://github.com/carlosjhr64/markita
121
124
  licenses:
122
125
  - MIT