markita 2.0.210906 → 3.2.210915

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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