memorack 0.1.2 → 0.2.0
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 +4 -4
- data/HISTORY.md +15 -0
- data/README.md +17 -15
- data/VERSION +1 -1
- data/lib/memorack/builder.rb +36 -2
- data/lib/memorack/cli.rb +8 -5
- data/lib/memorack/config/macro.yml +2 -0
- data/lib/memorack/core.rb +339 -47
- data/lib/memorack/locales/en.yml +1 -0
- data/lib/memorack/locales/ja.yml +1 -0
- data/lib/memorack/locals.rb +31 -1
- data/lib/memorack/locals/app.rb +16 -0
- data/lib/memorack/locals/base.rb +84 -0
- data/lib/memorack/mdmenu.rb +3 -2
- data/lib/memorack/memoapp.rb +7 -2
- data/lib/memorack/pageinfo.rb +151 -0
- data/lib/memorack/plugin.rb +54 -0
- data/lib/memorack/plugins/formats/formats.rb +12 -0
- data/lib/memorack/plugins/formats/markdown.rb +32 -0
- data/lib/memorack/plugins/formats/org.rb +54 -0
- data/lib/memorack/template/.gitignore +1 -0
- data/lib/memorack/template/plugins/.gitkeep +0 -0
- data/lib/memorack/template/themes/custom/locales/.gitkeep +0 -0
- data/lib/memorack/template/themes/custom/macro.yml +2 -0
- data/lib/memorack/template/themes/custom/pages/.gitkeep +0 -0
- data/spec/memorack_spec.rb +115 -15
- data/spec/patches/git/0001-add-HISTORY.patch +15 -0
- data/spec/patches/git/0002-change-HISTORY.patch +19 -0
- data/spec/patches/git/0003-index.html.patch +75 -0
- data/spec/patches/macro.patch +20 -0
- data/spec/patches/plugin.patch +87 -0
- metadata +24 -2
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'memorack/pageinfo'
|
4
|
+
|
5
|
+
|
6
|
+
module MemoRack
|
7
|
+
|
8
|
+
class PageInfoMarkdown < PageInfo
|
9
|
+
# ファイル拡張子
|
10
|
+
def self.extnames
|
11
|
+
['md', 'mkd', 'markdown']
|
12
|
+
end
|
13
|
+
|
14
|
+
def accept_title(line, prev = nil)
|
15
|
+
case line
|
16
|
+
when /^(\#{1,6}?)\s+(.+)$/
|
17
|
+
level = $1.length
|
18
|
+
headline = $2.gsub(/\#+\s*$/, '').strip
|
19
|
+
return headline
|
20
|
+
when /^\s*([=\-])+\s*$/
|
21
|
+
return nil unless prev
|
22
|
+
|
23
|
+
prev = prev.strip
|
24
|
+
unless prev.empty?
|
25
|
+
level = ($1 == '=') ? 1 : 2
|
26
|
+
return prev
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'memorack/pageinfo'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'org-ruby'
|
8
|
+
|
9
|
+
|
10
|
+
module MemoRack
|
11
|
+
|
12
|
+
class PageInfoOrg < PageInfo
|
13
|
+
# ファイル拡張子
|
14
|
+
def self.extnames
|
15
|
+
['org']
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.org_keys(*keys, &block)
|
19
|
+
define_keys *keys
|
20
|
+
|
21
|
+
keys.each { |name|
|
22
|
+
block = lambda { |line, prev = nil| org_info(name, line) }
|
23
|
+
define_method("accept_#{name}", &block)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# ファイル解析の終了か?
|
28
|
+
def parse_end?(line, n)
|
29
|
+
line !~ /^\#/
|
30
|
+
end
|
31
|
+
|
32
|
+
def org_info(name, line)
|
33
|
+
name = name.to_s.upcase
|
34
|
+
|
35
|
+
if line =~ /^\#\+#{name}:\s*(.+)$/
|
36
|
+
$1.strip
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def accept_date(line, prev = nil)
|
41
|
+
value = org_info(:date, line)
|
42
|
+
value = Time.parse(value) if value
|
43
|
+
value
|
44
|
+
end
|
45
|
+
|
46
|
+
# 作成日
|
47
|
+
define_key(:ctime) { |key|
|
48
|
+
values[key] ||= parse(:date) || File::Stat.new(@path).ctime
|
49
|
+
}
|
50
|
+
|
51
|
+
org_keys :title, :author, :email, :language, :description
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
data/spec/memorack_spec.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require File.expand_path('../spec_helper', __FILE__)
|
4
4
|
require 'memorack'
|
5
5
|
require 'memorack/cli'
|
6
|
+
require 'cgi'
|
6
7
|
|
7
8
|
|
8
9
|
describe MemoRack do
|
@@ -45,6 +46,38 @@ describe MemoRack do
|
|
45
46
|
}
|
46
47
|
end
|
47
48
|
|
49
|
+
# パッチをあてる
|
50
|
+
def patch(name)
|
51
|
+
path = File.expand_path("../patches/#{name}", __FILE__)
|
52
|
+
if File.directory?(path)
|
53
|
+
Dir[File.join(path, '*.patch')].each { |path|
|
54
|
+
`patch -p1 < "#{path}"`
|
55
|
+
}
|
56
|
+
else
|
57
|
+
path += '.patch'
|
58
|
+
`patch -p1 < "#{path}"`
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# git でパッチをあてる
|
63
|
+
def git_am(name)
|
64
|
+
unless File.exists?('.git')
|
65
|
+
`git init`
|
66
|
+
`git add .`
|
67
|
+
`git commit -m "first commit"`
|
68
|
+
end
|
69
|
+
|
70
|
+
path = File.expand_path("../patches/#{name}", __FILE__)
|
71
|
+
if File.directory?(path)
|
72
|
+
Dir[File.join(path, '*.patch')].each { |path|
|
73
|
+
`git am -3 "#{path}"`
|
74
|
+
}
|
75
|
+
else
|
76
|
+
path += '.patch'
|
77
|
+
`git am -3 "#{path}"`
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
48
81
|
before do
|
49
82
|
require 'tmpdir'
|
50
83
|
@tmpdir = Dir.mktmpdir
|
@@ -60,7 +93,7 @@ describe MemoRack do
|
|
60
93
|
proc { memorack '-h' }.must_output nil, <<-EOD.cut_indent
|
61
94
|
Usage: memorack create [options] PATH
|
62
95
|
memorack theme [options] [THEME]
|
63
|
-
memorack server [options] PATH
|
96
|
+
memorack server [options] [PATH]
|
64
97
|
memorack build [options] [PATH]
|
65
98
|
|
66
99
|
-h, --help Show this message
|
@@ -86,10 +119,10 @@ describe MemoRack do
|
|
86
119
|
|
87
120
|
it "server" do
|
88
121
|
proc { memorack 'server', '-h' }.must_output nil, <<-EOD.cut_indent
|
89
|
-
Usage: memorack server [options] PATH
|
122
|
+
Usage: memorack server [options] [PATH]
|
90
123
|
|
91
124
|
-p, --port PORT use PORT (default: 9292)
|
92
|
-
-t, --theme THEME use THEME (default:
|
125
|
+
-t, --theme THEME use THEME (default: custom)
|
93
126
|
-h, --help Show this message
|
94
127
|
EOD
|
95
128
|
end
|
@@ -103,6 +136,7 @@ describe MemoRack do
|
|
103
136
|
--url URL Site URL (default: )
|
104
137
|
--local Site URL is output directory
|
105
138
|
--prettify prettify URL
|
139
|
+
--index output index.html of sub directory
|
106
140
|
-h, --help Show this message
|
107
141
|
EOD
|
108
142
|
end
|
@@ -117,7 +151,7 @@ describe MemoRack do
|
|
117
151
|
proc { memorack '-h' }.must_output nil, <<-EOD.cut_indent
|
118
152
|
Usage: memorack create [options] PATH
|
119
153
|
memorack theme [options] [THEME]
|
120
|
-
memorack server [options] PATH
|
154
|
+
memorack server [options] [PATH]
|
121
155
|
memorack build [options] [PATH]
|
122
156
|
|
123
157
|
-h, --help このメッセージを表示
|
@@ -144,10 +178,10 @@ describe MemoRack do
|
|
144
178
|
|
145
179
|
it "server" do
|
146
180
|
proc { memorack 'server', '-h' }.must_output nil, <<-EOD.cut_indent
|
147
|
-
Usage: memorack server [options] PATH
|
181
|
+
Usage: memorack server [options] [PATH]
|
148
182
|
|
149
183
|
-p, --port PORT ポートを使う (省略値: 9292)
|
150
|
-
-t, --theme THEME テーマを使う (省略値:
|
184
|
+
-t, --theme THEME テーマを使う (省略値: custom)
|
151
185
|
-h, --help このメッセージを表示
|
152
186
|
EOD
|
153
187
|
end
|
@@ -161,6 +195,7 @@ describe MemoRack do
|
|
161
195
|
--url URL サイトURL (省略値: )
|
162
196
|
--local サイトURLをアウトプットディレクトリにする
|
163
197
|
--prettify 綺麗なURLになるように生成する
|
198
|
+
--index サブディレクトリの index.html を出力する
|
164
199
|
-h, --help このメッセージを表示
|
165
200
|
EOD
|
166
201
|
end
|
@@ -181,10 +216,17 @@ describe MemoRack do
|
|
181
216
|
./content
|
182
217
|
./content/README.md
|
183
218
|
./Gemfile
|
219
|
+
./plugins
|
220
|
+
./plugins/.gitkeep
|
184
221
|
./themes
|
185
222
|
./themes/custom
|
186
223
|
./themes/custom/config.json
|
187
224
|
./themes/custom/index.md
|
225
|
+
./themes/custom/locales
|
226
|
+
./themes/custom/locales/.gitkeep
|
227
|
+
./themes/custom/macro.yml
|
228
|
+
./themes/custom/pages
|
229
|
+
./themes/custom/pages/.gitkeep
|
188
230
|
EOD
|
189
231
|
}
|
190
232
|
end
|
@@ -226,6 +268,11 @@ describe MemoRack do
|
|
226
268
|
custom --> [oreilly] --> [basic]
|
227
269
|
config.json
|
228
270
|
index.md
|
271
|
+
locales/
|
272
|
+
locales/.gitkeep
|
273
|
+
macro.yml
|
274
|
+
pages/
|
275
|
+
pages/.gitkeep
|
229
276
|
EOD
|
230
277
|
}
|
231
278
|
end
|
@@ -266,6 +313,7 @@ describe MemoRack do
|
|
266
313
|
@hash = {}
|
267
314
|
@hash['basic'] = '9b6d4163c422ff9304ebfec6beacb89e23715fe5'
|
268
315
|
@hash['oreilly'] = 'ef118f287e80648235a314980da908f70e982478'
|
316
|
+
@theme = 'oreilly'
|
269
317
|
|
270
318
|
@file_lists = <<-EOD.cut_indent
|
271
319
|
.
|
@@ -279,7 +327,7 @@ describe MemoRack do
|
|
279
327
|
end
|
280
328
|
|
281
329
|
it "build" do
|
282
|
-
theme =
|
330
|
+
theme = @theme
|
283
331
|
output = '_site'
|
284
332
|
|
285
333
|
chmemo { |name|
|
@@ -293,7 +341,7 @@ describe MemoRack do
|
|
293
341
|
end
|
294
342
|
|
295
343
|
it "build PATH" do
|
296
|
-
theme =
|
344
|
+
theme = @theme
|
297
345
|
output = '_site'
|
298
346
|
|
299
347
|
chmemo { |name|
|
@@ -313,7 +361,7 @@ describe MemoRack do
|
|
313
361
|
end
|
314
362
|
|
315
363
|
it "build --output DIRECTORY" do
|
316
|
-
theme =
|
364
|
+
theme = @theme
|
317
365
|
output = 'output'
|
318
366
|
|
319
367
|
chmemo { |name|
|
@@ -341,7 +389,7 @@ describe MemoRack do
|
|
341
389
|
end
|
342
390
|
|
343
391
|
it "build --url URL" do
|
344
|
-
theme =
|
392
|
+
theme = @theme
|
345
393
|
output = '_site'
|
346
394
|
url = 'http://memo.pow'
|
347
395
|
|
@@ -351,13 +399,13 @@ describe MemoRack do
|
|
351
399
|
Dir.chdir(output) { |output|
|
352
400
|
`find . -print`.must_equal @file_lists
|
353
401
|
`git hash-object css/styles.css`.must_equal @hash[theme]+"\n"
|
354
|
-
File.read('index.html').must_match %r[<a href="#{url}/README.html">
|
402
|
+
File.read('index.html').must_match %r[<a href="#{url}/README.html">MemoRack について</a>]
|
355
403
|
}
|
356
404
|
}
|
357
405
|
end
|
358
406
|
|
359
407
|
it "build --local" do
|
360
|
-
theme =
|
408
|
+
theme = @theme
|
361
409
|
output = '_site'
|
362
410
|
|
363
411
|
chmemo { |name|
|
@@ -368,13 +416,13 @@ describe MemoRack do
|
|
368
416
|
Dir.chdir(output) { |output|
|
369
417
|
`find . -print`.must_equal @file_lists
|
370
418
|
`git hash-object css/styles.css`.must_equal @hash[theme]+"\n"
|
371
|
-
File.read('index.html').must_match %r[<a href="#{url}/README.html">
|
419
|
+
File.read('index.html').must_match %r[<a href="#{url}/README.html">MemoRack について</a>]
|
372
420
|
}
|
373
421
|
}
|
374
422
|
end
|
375
423
|
|
376
424
|
it "build --prettify" do
|
377
|
-
theme =
|
425
|
+
theme = @theme
|
378
426
|
output = '_site'
|
379
427
|
url = ''
|
380
428
|
|
@@ -394,7 +442,56 @@ describe MemoRack do
|
|
394
442
|
EOD
|
395
443
|
|
396
444
|
`git hash-object css/styles.css`.must_equal @hash[theme]+"\n"
|
397
|
-
File.read('index.html').must_match %r[<a href="#{url}/README">
|
445
|
+
File.read('index.html').must_match %r[<a href="#{url}/README">MemoRack について</a>]
|
446
|
+
}
|
447
|
+
}
|
448
|
+
end
|
449
|
+
|
450
|
+
it "plugin" do
|
451
|
+
theme = @theme
|
452
|
+
output = '_site'
|
453
|
+
|
454
|
+
chmemo { |name|
|
455
|
+
patch 'plugin'
|
456
|
+
proc { memorack 'build' }.must_output "Build 'content/' -> '#{output}'\n"
|
457
|
+
|
458
|
+
Dir.chdir(output) { |output|
|
459
|
+
theme_chain = 'Theme (custom --> oreilly --> basic)'
|
460
|
+
File.read('index.html').must_match /#{Regexp.escape CGI.escapeHTML theme_chain}/
|
461
|
+
}
|
462
|
+
}
|
463
|
+
end
|
464
|
+
|
465
|
+
it "macro" do
|
466
|
+
theme = @theme
|
467
|
+
output = '_site'
|
468
|
+
|
469
|
+
chmemo { |name|
|
470
|
+
patch 'macro'
|
471
|
+
proc { memorack 'build' }.must_output "Build 'content/' -> '#{output}'\n"
|
472
|
+
|
473
|
+
Dir.chdir(output) { |output|
|
474
|
+
File.read('index.html').must_match %r[<title>覚書き</title>]
|
475
|
+
File.read('README.html').must_match %r[<title>MemoRack について ≫ 覚書き</title>]
|
476
|
+
}
|
477
|
+
}
|
478
|
+
end
|
479
|
+
|
480
|
+
it "git" do
|
481
|
+
theme = @theme
|
482
|
+
output = '_site'
|
483
|
+
|
484
|
+
chmemo { |name|
|
485
|
+
git_am 'git'
|
486
|
+
proc { memorack 'build' }.must_output "Build 'content/' -> '#{output}'\n"
|
487
|
+
|
488
|
+
Dir.chdir(output) { |output|
|
489
|
+
ctime = '<div>作成時間:2013-05-11 18:47:31 +0900</div>'
|
490
|
+
mtime = '<div>更新時間:2013-05-11 18:49:46 +0900</div>'
|
491
|
+
|
492
|
+
history = File.read('HISTORY.html')
|
493
|
+
history.must_match /#{Regexp.escape ctime}/
|
494
|
+
history.must_match /#{Regexp.escape mtime}/
|
398
495
|
}
|
399
496
|
}
|
400
497
|
end
|
@@ -420,18 +517,21 @@ describe MemoRack do
|
|
420
517
|
get '/'
|
421
518
|
last_response.must_be :ok?
|
422
519
|
last_response.body.must_match /Powered by <a href="#{MemoRack::HOMEPAGE}"[^>]*>/
|
520
|
+
last_response.body.must_match %r[<title>覚書き</title>]
|
423
521
|
end
|
424
522
|
|
425
523
|
it "server /README" do
|
426
524
|
get '/README'
|
427
525
|
last_response.must_be :ok?
|
428
526
|
last_response.body.must_match /このディレクトリに markdown 等のメモファイルを作成してください/
|
527
|
+
last_response.body.must_match %r[<title>MemoRack について \| 覚書き</title>]
|
429
528
|
end
|
430
529
|
|
431
530
|
it "server /404" do
|
432
531
|
get '/404'
|
433
532
|
last_response.status.must_equal 404
|
434
533
|
last_response.body.must_match %r[<div id="content"><h3>Not Found</h3>\s+</div>]
|
534
|
+
last_response.body.must_match %r[<title>Error 404 \| 覚書き</title>]
|
435
535
|
end
|
436
536
|
|
437
537
|
after do
|
@@ -0,0 +1,15 @@
|
|
1
|
+
From f816996d9e38bff0a10839e4fa66b00d0a2a7569 Mon Sep 17 00:00:00 2001
|
2
|
+
From: gnue <gnue@so-kukan.com>
|
3
|
+
Date: Sat, 11 May 2013 18:47:31 +0900
|
4
|
+
Subject: [PATCH 1/3] add HISTORY
|
5
|
+
|
6
|
+
---
|
7
|
+
0 files changed
|
8
|
+
create mode 100644 content/HISTORY.md
|
9
|
+
|
10
|
+
diff --git a/content/HISTORY.md b/content/HISTORY.md
|
11
|
+
new file mode 100644
|
12
|
+
index 0000000..e69de29
|
13
|
+
--
|
14
|
+
1.7.12.4 (Apple Git-37)
|
15
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
From eacb034650f18239f9cd99f8833ebe730595b69b Mon Sep 17 00:00:00 2001
|
2
|
+
From: gnue <gnue@so-kukan.com>
|
3
|
+
Date: Sat, 11 May 2013 18:49:46 +0900
|
4
|
+
Subject: [PATCH 2/3] change HISTORY
|
5
|
+
|
6
|
+
---
|
7
|
+
content/HISTORY.md | 2 ++
|
8
|
+
1 file changed, 2 insertions(+)
|
9
|
+
|
10
|
+
diff --git a/content/HISTORY.md b/content/HISTORY.md
|
11
|
+
index e69de29..a01569d 100644
|
12
|
+
--- a/content/HISTORY.md
|
13
|
+
+++ b/content/HISTORY.md
|
14
|
+
@@ -0,0 +1,2 @@
|
15
|
+
+## HISTORY
|
16
|
+
+
|
17
|
+
--
|
18
|
+
1.7.12.4 (Apple Git-37)
|
19
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
From 3dbf53d1c486ff86cbbd229c9c42f9d8260c2349 Mon Sep 17 00:00:00 2001
|
2
|
+
From: gnue <gnue@so-kukan.com>
|
3
|
+
Date: Sat, 11 May 2013 18:58:35 +0900
|
4
|
+
Subject: [PATCH 3/3] =?UTF-8?q?index.html=20=E3=82=92=E8=BF=BD=E5=8A=A0?=
|
5
|
+
MIME-Version: 1.0
|
6
|
+
Content-Type: text/plain; charset=UTF-8
|
7
|
+
Content-Transfer-Encoding: 8bit
|
8
|
+
|
9
|
+
---
|
10
|
+
themes/custom/index.html | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
|
11
|
+
1 file changed, 53 insertions(+)
|
12
|
+
create mode 100644 themes/custom/index.html
|
13
|
+
|
14
|
+
diff --git a/themes/custom/index.html b/themes/custom/index.html
|
15
|
+
new file mode 100644
|
16
|
+
index 0000000..2fa51a5
|
17
|
+
--- /dev/null
|
18
|
+
+++ b/themes/custom/index.html
|
19
|
+
@@ -0,0 +1,53 @@
|
20
|
+
+<!DOCTYPE html>
|
21
|
+
+<html>
|
22
|
+
+<head>
|
23
|
+
+<meta charset="utf-8" />
|
24
|
+
+
|
25
|
+
+<style>
|
26
|
+
+ article, aside, dialog, figure, footer, header,
|
27
|
+
+ hgroup, menu, nav, section { display: block; }
|
28
|
+
+</style>
|
29
|
+
+
|
30
|
+
+<meta name="keywords" content="" />
|
31
|
+
+<meta name="description" content="" />
|
32
|
+
+<title>{{page.title}}</title>
|
33
|
+
+
|
34
|
+
+<link type="text/css" href="{{site.url}}/css/styles.css" rel="stylesheet" media="all" />
|
35
|
+
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
|
36
|
+
+<script type="text/javascript">
|
37
|
+
+ $(function(){
|
38
|
+
+ // 表示しているメニューを選択
|
39
|
+
+ $('#menu a[href="' + document.location.pathname + '"]').parent().addClass('selected');
|
40
|
+
+ $('#menu a[href="' + document.location + '"]').parent().addClass('selected');
|
41
|
+
+
|
42
|
+
+ // 外部サイトのリンクに target='_blank' を追加
|
43
|
+
+ $('a[href^=http]').not('[href*="://' + location.hostname + '"]').attr('target', '_blank');
|
44
|
+
+ });
|
45
|
+
+</script>
|
46
|
+
+
|
47
|
+
+</head>
|
48
|
+
+<body>
|
49
|
+
+ <div id="page">
|
50
|
+
+ <header>
|
51
|
+
+ <h1><a href="{{site.url}}/">{{title}}</a></h1>
|
52
|
+
+ </header>
|
53
|
+
+
|
54
|
+
+ <div id="content-container">
|
55
|
+
+ <div id="menu" class="importdoc">{{{__menu__}}}</div>
|
56
|
+
+ <div id="content">
|
57
|
+
+ {{#content?}}
|
58
|
+
+ <div>作成時間:{{page.ctime}}</div>
|
59
|
+
+ <div>更新時間:{{page.mtime}}</div>
|
60
|
+
+ {{/content?}}
|
61
|
+
+
|
62
|
+
+ {{{__content__}}}
|
63
|
+
+ </div>
|
64
|
+
+ <div class="clear"></div>
|
65
|
+
+ </div>
|
66
|
+
+
|
67
|
+
+ <footer>
|
68
|
+
+ <p>Powered by <a href="{{app.url}}" target="_blank"> {{app.name}} {{app.version}}</a></p>
|
69
|
+
+ </footer>
|
70
|
+
+ </div>
|
71
|
+
+</body>
|
72
|
+
+</html>
|
73
|
+
--
|
74
|
+
1.7.12.4 (Apple Git-37)
|
75
|
+
|