markita 3.1.210913 → 3.4.211004

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: d48cd0cacac70dc9974733968e16d5958676172aae7ac7138995855ef82839b7
4
- data.tar.gz: 1355e68fa3255f16331a4afc36f2d47ecfbd1583fbf2f16a9742c53e50390414
3
+ metadata.gz: 2a83f3ae0cb87314ee1ea28a3f5c39cd84813d9564e666f4ed474627988b12cf
4
+ data.tar.gz: c180906afdac8f5343f99cc86c28d9c6db3ae38fdb8828d65f50f338d7b15757
5
5
  SHA512:
6
- metadata.gz: 54630f6cef7d9632699c16b8e9e447799c85806adc75202cc774272066de82927260ba5fbb4da5f974860dc48d5a26ef9e96d463c4825676a801207c28f850bd
7
- data.tar.gz: 34a7e703827b69fb3e0c4e406d477c3ab35d605fc9f1d87c9cae1a2724b8e01099de74b7c6b1ee5f6c220f35bc277e717637925464dfab5938303fcfb37f601b
6
+ metadata.gz: 98e97748ae3187b627841670a4744e55ec3a630a49839a069268ef99fdf12cecfe78589b64e7f8ab01fa2c8a4ec7f7fed07535ff5908c423190c19f807c663de
7
+ data.tar.gz: 0ca77e473071ef3716812dac6d727ec21229acf42ea73d367913cbfa5ec4bb32449798a3649c74c01aaa9d5640d8d30b31aaf2140f996299a6b6efab64f1694f
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Markita
2
2
 
3
- * [VERSION 3.1.210913](https://github.com/carlosjhr64/markita/releases)
3
+ * [VERSION 3.4.211004](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
 
@@ -23,6 +23,7 @@ Options:
23
23
  --root=DIRECTORY ~/vimwiki
24
24
  --bind=BIND 0.0.0.0
25
25
  --port=PORT 8080
26
+ --theme=THEME base16.light
26
27
  --allowed=IPS
27
28
  --no_about
28
29
  --no_favicon
@@ -34,8 +35,8 @@ Types:
34
35
  DIRECTORY /^~?[\/\w\.]+$/
35
36
  BIND /^[\w\.]+$/
36
37
  PORT /^\d+$/
37
- THEME /^[\w\.]+$/
38
38
  IPS /^[\d\.\,]+$/
39
+ THEME /^[\w\.]+$/
39
40
  # NOTE:
40
41
  # Assuming site is in ~/vimwiki,
41
42
  # when ~/vimwiki/.valid-id is set with a sha256sum of a password,
@@ -96,6 +97,9 @@ Markdown:
96
97
  ! Address:[address]
97
98
  ! Code:[code="1234"]
98
99
 
100
+ A selection list:
101
+ ! Color:[color="Red","White","Blue"]
102
+
99
103
  ### Template substitutions
100
104
 
101
105
  Markdown:
@@ -265,8 +269,9 @@ Markdown:
265
269
 
266
270
  !> /path-to/ascii_art.txt
267
271
 
268
- Must be a `*.txt` file.
269
272
  Useful for ASCII art.
273
+ Unless an `*.html` file, the text is embedded in `pre` tags.
274
+ Further more unless a `*.txt` file, the text is embedded in `code` tags.
270
275
 
271
276
  ### Emojis
272
277
 
@@ -290,6 +295,16 @@ Markdown:
290
295
  [^2]: Cash is money in currency.
291
296
  [^3]: Read as "Nan took it."
292
297
 
298
+ ### Meta-data
299
+
300
+ Markdown:
301
+
302
+ ---
303
+ Title: The Title You Want For Your Page
304
+ 1: https://way.to/create/ref/links
305
+ ---
306
+ You can now [link](1) with a reference number.
307
+
293
308
  ## HOW-TOs
294
309
 
295
310
  ### Set site password:
@@ -297,12 +312,11 @@ Markdown:
297
312
  $ # Assuming ~/vimwiki is your site's root...
298
313
  $ echo -n '<SitePasswordHere>' | sha256sum | grep -o '^\w*' > ~/vimwiki/.valid-id
299
314
  ```
300
- ### Set site custom favicon, css, not found page, and login form and fail page:
315
+ ### Set site custom favicon, not found page, and login form and fail page:
301
316
  ```console
302
317
  $ # Assuming ~/vimwiki is your site's root...
303
318
  $ # Note that you'll have to restart the server on any change to these:
304
319
  $ cp /path-to/custom/favicon.ico ~/vimwiki/favicon.ico
305
- $ cp /path-to/custom/highlight.css ~/vimwiki/highlight.css
306
320
  $ cp /path-to/custom/not_found.html ~/vimwiki/not_found.html
307
321
  $ cp /path-to/custom/login_form.html ~/vimwiki/login_form.html
308
322
  $ cp /path-to/custom/login_fail.html ~/vimwiki/login_fail.html
data/bin/markita CHANGED
@@ -9,6 +9,7 @@ Options:
9
9
  --root=DIRECTORY \t ~/vimwiki
10
10
  --bind=BIND \t 0.0.0.0
11
11
  --port=PORT \t 8080
12
+ --theme=THEME \t base16.light
12
13
  --allowed=IPS
13
14
  --no_about
14
15
  --no_favicon
@@ -20,8 +21,8 @@ Types:
20
21
  DIRECTORY /^~?[\\/\\w\\.]+$/
21
22
  BIND /^[\\w\\.]+$/
22
23
  PORT /^\\d+$/
23
- THEME /^[\\w\\.]+$/
24
24
  IPS /^[\\d\\.\\,]+$/
25
+ THEME /^[\\w\\.]+$/
25
26
  # NOTE:
26
27
  # Assuming site is in ~/vimwiki,
27
28
  # when ~/vimwiki/.valid-id is set with a sha256sum of a password,
@@ -6,6 +6,7 @@ class Markdown
6
6
  def initialize(title)
7
7
  @title = title
8
8
  @line=@html=@file=@opt=nil
9
+ @metadata = {}
9
10
  end
10
11
 
11
12
  def start
@@ -14,6 +15,9 @@ class Markdown
14
15
  end
15
16
 
16
17
  def finish
18
+ if title = @metadata['Title']
19
+ @html << %Q(<script> document.title = "#{title}" </script>\n)
20
+ end
17
21
  @html << HTML.footer
18
22
  @line = nil
19
23
  end
@@ -62,7 +66,10 @@ class Markdown
62
66
  CODE = lambda {|m| "<code>#{m[1]}</code>"}
63
67
 
64
68
  Ax = /\[([^\[\]]+)\]\(([^()]+)\)/
65
- A = lambda {|m| %Q(<a href="#{m[2]}">#{m[1]}</a>)}
69
+ def anchor(m)
70
+ href = ((_=m[2]).match?(/^\d+$/) and @metadata[_] or _)
71
+ %Q(<a href="#{href}">#{m[1]}</a>)
72
+ end
66
73
 
67
74
  URLx = %r(\[(https?://[\w\.\-\/\&\+\?\%]+)\])
68
75
  URL = lambda {|m| %Q(<a href="#{m[1]}">#{m[1]}</a>)}
@@ -95,9 +102,9 @@ class Markdown
95
102
  return (block ? block.call(entry) : entry)
96
103
  end
97
104
 
98
- INLINE = lambda do |entry|
105
+ def inline(entry)
99
106
  string = Markdown.tag(entry, CODEx, CODE) do |entry|
100
- Markdown.tag(entry, Ax, A) do |entry|
107
+ Markdown.tag(entry, Ax, method(:anchor)) do |entry|
101
108
  Markdown.tag(entry, URLx, URL) do |entry|
102
109
  entry = Markdown.tag(entry, EMOJIx, EMOJI)
103
110
  entry = Markdown.tag(entry, Bx, B)
@@ -121,29 +128,34 @@ class Markdown
121
128
  end
122
129
 
123
130
  # Ordered list
124
- ORDERED = /^\d+. (.*)$/
131
+ ORDERED = /^( {0,3})\d+\. (\S.*)$/
125
132
  PARSERS << :ordered
126
- def ordered
127
- md = ORDERED.match(@line) or return false
133
+ def ordered(md=ORDERED.match(@line), level=0)
134
+ return false unless md
128
135
  @html << "<ol#{@opt[:attributes]}>\n"
129
136
  @opt.delete(:attributes)
130
- while md
131
- @html << " <li>#{INLINE[md[1]]}</li>\n"
132
- md = (@line=@file.gets)&.match ORDERED
137
+ while md and level==md[1].length
138
+ @html << " <li>#{inline(md[2])}</li>\n"
139
+ if md = (@line=@file.gets)&.match(ORDERED)
140
+ if level < md[1].length
141
+ ordered(md, md[1].length)
142
+ md = @line&.match(ORDERED)
143
+ end
144
+ end
133
145
  end
134
146
  @html << "</ol>\n"
135
147
  true
136
148
  end
137
149
 
138
150
  # Paragraph
139
- PARAGRAPHS = /^[\[`*"~_]?\w/
151
+ PARAGRAPHS = /^[\[\(`*"~_]?\w/
140
152
  PARSERS << :paragraphs
141
153
  def paragraphs
142
154
  md = PARAGRAPHS.match(@line) or return false
143
155
  @html << "<p#{@opt[:attributes]}>\n"
144
156
  @opt.delete(:attributes)
145
157
  while md
146
- @html << INLINE[@line]
158
+ @html << inline(@line)
147
159
  md = (@line=@file.gets)&.match PARAGRAPHS
148
160
  end
149
161
  @html << "</p>\n"
@@ -151,15 +163,20 @@ class Markdown
151
163
  end
152
164
 
153
165
  # Unordered list
154
- UNORDERED = /^[*] (.*)$/
166
+ UNORDERED = /^( {0,3})[*] (\S.*)$/
155
167
  PARSERS << :unordered
156
- def unordered
157
- md = UNORDERED.match(@line) or return false
168
+ def unordered(md=UNORDERED.match(@line), level=0)
169
+ return false unless md
158
170
  @html << "<ul#{@opt[:attributes]}>\n"
159
171
  @opt.delete(:attributes)
160
- while md
161
- @html << " <li>#{INLINE[md[1]]}</li>\n"
162
- md = (@line=@file.gets)&.match UNORDERED
172
+ while md and level==md[1].length
173
+ @html << " <li>#{inline(md[2])}</li>\n"
174
+ if md = (@line=@file.gets)&.match(UNORDERED)
175
+ if level < md[1].length
176
+ unordered(md, md[1].length)
177
+ md = @line&.match(UNORDERED)
178
+ end
179
+ end
163
180
  end
164
181
  @html << "</ul>\n"
165
182
  true
@@ -177,7 +194,7 @@ class Markdown
177
194
  li = (x=='x')?
178
195
  %q{<li style="list-style-type: '&#9745; '">} :
179
196
  %q{<li style="list-style-type: '&#9744; '">}
180
- @html << " #{li}#{INLINE[t]}</li>\n"
197
+ @html << " #{li}#{inline(t)}</li>\n"
181
198
  md = (@line=@file.gets)&.match BALLOTS
182
199
  end
183
200
  @html << "</ul>\n"
@@ -193,8 +210,8 @@ class Markdown
193
210
  @opt.delete(:attributes)
194
211
  while md
195
212
  item = md[1]
196
- @html << ((item[-1]==':')? "<dt>#{INLINE[item[0..-2]]}</dt>\n" :
197
- "<dd>#{INLINE[item]}</dd>\n")
213
+ @html << ((item[-1]==':')? "<dt>#{inline(item[0..-2])}</dt>\n" :
214
+ "<dd>#{inline(item)}</dd>\n")
198
215
  md = (@line=@file.gets)&.match DEFINITIONS
199
216
  end
200
217
  @html << "</dl>\n"
@@ -207,9 +224,9 @@ class Markdown
207
224
  def headers
208
225
  md = HEADERS.match(@line) or return false
209
226
  i,header = md[1].length,md[2]
210
- id = header.strip.gsub(/\s+/,'+')
227
+ id = header.gsub(/\([^\(\)]*\)/,'').scan(/\w+/).join('+')
211
228
  @html << %Q(<a id="#{id}">\n)
212
- @html << " <h#{i}#{@opt[:attributes]}>#{INLINE[header]}</h#{i}>\n"
229
+ @html << " <h#{i}#{@opt[:attributes]}>#{inline(header)}</h#{i}>\n"
213
230
  @html << "</a>\n"
214
231
  @opt.delete(:attributes)
215
232
  @line = @file.gets
@@ -224,7 +241,7 @@ class Markdown
224
241
  @html << "<blockquote#{@opt[:attributes]}>\n"
225
242
  @opt.delete(:attributes)
226
243
  while md
227
- @html << INLINE[md[1]]
244
+ @html << inline(md[1])
228
245
  @html << "\n"
229
246
  md = (@line=@file.gets)&.match BLOCKQS
230
247
  end
@@ -268,14 +285,31 @@ class Markdown
268
285
  true
269
286
  end
270
287
 
271
- # Horizontal rule
288
+ # Meta-data
289
+ METADATAS = /^(\w+): (.*)$/
290
+ def metadata
291
+ md = METADATAS.match(@line) or return false
292
+ while md
293
+ @metadata[md[1]] = md[2]
294
+ md = (@line=@file.gets)&.match METADATAS
295
+ end
296
+ true
297
+ end
298
+
299
+ # Horizontal rule or Meta-data
272
300
  HRS = /^---+$/
273
301
  PARSERS << :hrs
274
302
  def hrs
275
303
  HRS.match? @line or return false
276
- @html << "<hr#{@opt[:attributes]}>\n"
277
- @opt.delete(:attributes)
278
304
  @line = @file.gets
305
+ if metadata
306
+ # Optional closing HRS
307
+ @line = @file.gets if @line&.match? HRS
308
+ else
309
+ # Display HR
310
+ @html << "<hr#{@opt[:attributes]}>\n"
311
+ @opt.delete(:attributes)
312
+ end
279
313
  true
280
314
  end
281
315
 
@@ -287,7 +321,7 @@ class Markdown
287
321
  @html << "<table#{@opt[:attributes]}>\n"
288
322
  @opt.delete(:attributes)
289
323
  @html << '<thead><tr><th>'
290
- @html << @line[1...-1].split('|').map{INLINE[_1.strip]}.join('</th><th>')
324
+ @html << @line[1...-1].split('|').map{inline(_1.strip)}.join('</th><th>')
291
325
  @html << "</th></tr></thead>\n"
292
326
  align = []
293
327
  while (@line=@file.gets)&.match TABLES
@@ -304,7 +338,7 @@ class Markdown
304
338
  align[i] = ' align="left"'
305
339
  @html << '<td><hr></td>'
306
340
  else
307
- @html << "<td#{align[i]}>#{INLINE[cell.strip]}</td>"
341
+ @html << "<td#{align[i]}>#{inline(cell.strip)}</td>"
308
342
  end
309
343
  end
310
344
  @html << "</tr>\n"
@@ -360,7 +394,9 @@ class Markdown
360
394
  end
361
395
 
362
396
  # Forms
363
- FORMS = /^!( (\w+:)?\[\*?\w+(="[^"]*")?\])+/
397
+ FIELD = '(\w+:)?\[(\*)?(\w+)(=("[^"]+")(,"[^"]+")*)?\]'
398
+ FIELDS = Regexp.new FIELD
399
+ FORMS = Regexp.new "^!( #{FIELD})+"
364
400
  PARSERS << :forms
365
401
  def forms
366
402
  md = FORMS.match(@line) or return false
@@ -370,16 +406,26 @@ class Markdown
370
406
  while md
371
407
  n += 1
372
408
  form << ' <br>' if n > 1
373
- @line.scan(/(\w+:)?\[(\*)?(\w+)(="[^"]*")?\]/).each do |field, pwd, name, value|
409
+ @line.scan(FIELDS).each do |field, pwd, name, value|
374
410
  method ||= ' method="post"' if pwd
375
411
  field &&= field[0...-1]
376
412
  value &&= value[2...-1]
377
413
  if field
378
- fields += 1
379
414
  type = (pwd)? 'password' : 'text'
380
415
  if value
381
- form << %Q{ #{field}:<input type="#{type}" name="#{name}" value="#{value}">}
416
+ if (values = value.split('","')).length > 1
417
+ form << %Q(#{field}:<select name="#{name}">)
418
+ values.each do |value|
419
+ fields += 1
420
+ form << %Q( <option value="#{value}">#{value}</option>)
421
+ end
422
+ form << "</select>"
423
+ else
424
+ fields += 1
425
+ form << %Q{ #{field}:<input type="#{type}" name="#{name}" value="#{value}">}
426
+ end
382
427
  else
428
+ fields += 1
383
429
  form << %Q{ #{field}:<input type="#{type}" name="#{name}">}
384
430
  end
385
431
  elsif name=='submit'
@@ -404,14 +450,27 @@ class Markdown
404
450
  end
405
451
 
406
452
  # Embed text
407
- EMBED_TEXTS = /^!> (#{PAGE_KEY}\.txt)$/
453
+ EMBED_TEXTS = /^!> (#{PAGE_KEY}\.\w+)$/
408
454
  PARSERS << :embed_texts
409
455
  def embed_texts
410
456
  md = EMBED_TEXTS.match(@line) or return false
411
457
  if File.exist?(filename=File.join(ROOT, md[1]))
412
- @html << "<pre>\n"
413
- @html << File.read(filename)
414
- @html << "</pre>\n"
458
+ extension,lang = filename.split('.').last,nil
459
+ unless extension=='html'
460
+ lang = Rouge::Lexer.find extension
461
+ klass = lang ? ' class="highlight"' : nil
462
+ @html << "<pre#{klass}#{@opt[:attributes]}>"
463
+ @opt.delete(:attributes)
464
+ @html << '<code>' unless extension=='txt'
465
+ @html << "\n"
466
+ end
467
+ code = File.read(filename)
468
+ @html << (lang ? ROUGE.format(lang.new.lex(code)) : code)
469
+ unless extension=='html'
470
+ @html << '</code>' unless extension=='txt'
471
+ @html << '</pre>'
472
+ @html << "\n"
473
+ end
415
474
  else
416
475
  @html << @line
417
476
  end
@@ -426,7 +485,7 @@ class Markdown
426
485
  md = FOOTNOTES.match(@line) or return false
427
486
  @html << "<small>\n"
428
487
  while md
429
- @html << INLINE[@line.chomp]+"<br>\n"
488
+ @html << inline(@line.chomp)+"<br>\n"
430
489
  md = (@line=@file.gets)&.match FOOTNOTES
431
490
  end
432
491
  @html << "</small>\n"
@@ -2,7 +2,9 @@ module Markita
2
2
  class Base
3
3
  HEADER_LINKS << %Q( <link rel="stylesheet" href="/highlight.css" type="text/css">\n)
4
4
  module Highlight
5
- CSS = File.read PATH['highlight.css']
5
+ theme = OPTIONS&.theme || 'base16.light'
6
+ CSS = Rouge::Theme.find(theme)&.render(scope: '.highlight')
7
+ raise "Can't find Rouge Theme "+theme unless CSS
6
8
  end
7
9
 
8
10
  get '/highlight.css' do
data/lib/markita.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Markita
2
- VERSION = '3.1.210913'
2
+ VERSION = '3.4.211004'
3
3
 
4
4
  def self.run!
5
5
  # Standard libraries
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: 3.1.210913
4
+ version: 3.4.211004
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-13 00:00:00.000000000 Z
11
+ date: 2021-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: help_parser
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '7.0'
19
+ version: '8.0'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 7.0.200907
22
+ version: 8.0.210917
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '7.0'
29
+ version: '8.0'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 7.0.200907
32
+ version: 8.0.210917
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rouge
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: '3.26'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 3.26.0
42
+ version: 3.26.1
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: '3.26'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 3.26.0
52
+ version: 3.26.1
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: sinatra
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -104,7 +104,6 @@ files:
104
104
  - bin/markita
105
105
  - data/emojis.tsv
106
106
  - data/favicon.ico
107
- - data/highlight.css
108
107
  - data/login_failed.html
109
108
  - data/login_form.html
110
109
  - data/not_found.html
data/data/highlight.css DELETED
@@ -1,81 +0,0 @@
1
- /* Ruby Gem Rouge's base16.light */
2
- .highlight table td { padding: 5px; }
3
- .highlight table pre { margin: 0; }
4
- .highlight, .highlight .w {
5
- color: #303030;
6
- }
7
- .highlight .err {
8
- color: #151515;
9
- background-color: #ac4142;
10
- }
11
- .highlight .c, .highlight .ch, .highlight .cd, .highlight .cm, .highlight .cpf, .highlight .c1, .highlight .cs {
12
- color: #505050;
13
- }
14
- .highlight .cp {
15
- color: #f4bf75;
16
- }
17
- .highlight .nt {
18
- color: #f4bf75;
19
- }
20
- .highlight .o, .highlight .ow {
21
- color: #d0d0d0;
22
- }
23
- .highlight .p, .highlight .pi {
24
- color: #d0d0d0;
25
- }
26
- .highlight .gi {
27
- color: #90a959;
28
- }
29
- .highlight .gd {
30
- color: #ac4142;
31
- }
32
- .highlight .gh {
33
- color: #6a9fb5;
34
- background-color: #151515;
35
- font-weight: bold;
36
- }
37
- .highlight .k, .highlight .kn, .highlight .kp, .highlight .kr, .highlight .kv {
38
- color: #aa759f;
39
- }
40
- .highlight .kc {
41
- color: #d28445;
42
- }
43
- .highlight .kt {
44
- color: #d28445;
45
- }
46
- .highlight .kd {
47
- color: #d28445;
48
- }
49
- .highlight .s, .highlight .sb, .highlight .sc, .highlight .dl, .highlight .sd, .highlight .s2, .highlight .sh, .highlight .sx, .highlight .s1 {
50
- color: #90a959;
51
- }
52
- .highlight .sa {
53
- color: #aa759f;
54
- }
55
- .highlight .sr {
56
- color: #75b5aa;
57
- }
58
- .highlight .si {
59
- color: #8f5536;
60
- }
61
- .highlight .se {
62
- color: #8f5536;
63
- }
64
- .highlight .nn {
65
- color: #f4bf75;
66
- }
67
- .highlight .nc {
68
- color: #f4bf75;
69
- }
70
- .highlight .no {
71
- color: #f4bf75;
72
- }
73
- .highlight .na {
74
- color: #6a9fb5;
75
- }
76
- .highlight .m, .highlight .mb, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .il, .highlight .mo, .highlight .mx {
77
- color: #90a959;
78
- }
79
- .highlight .ss {
80
- color: #90a959;
81
- }