kramdown-man 0.1.8 → 1.0.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/.github/workflows/ruby.yml +4 -9
- data/.gitignore +4 -3
- data/.yardopts +1 -1
- data/ChangeLog.md +61 -0
- data/Gemfile +6 -3
- data/LICENSE.txt +1 -1
- data/README.md +156 -57
- data/Rakefile +1 -1
- data/bin/kramdown-man +3 -12
- data/gemspec.yml +7 -0
- data/kramdown-man.gemspec +2 -1
- data/lib/kramdown/man/cli.rb +202 -0
- data/lib/kramdown/{converter/man.rb → man/converter.rb} +328 -89
- data/lib/kramdown/man/task.rb +3 -1
- data/lib/kramdown/man/version.rb +3 -1
- data/lib/kramdown/man.rb +28 -3
- data/man/kramdown-man.1 +203 -101
- data/man/kramdown-man.1.md +102 -27
- data/spec/cli_spec.rb +218 -0
- data/spec/converter_spec.rb +969 -0
- data/spec/{kramdown/document_spec.rb → integration_spec.rb} +3 -3
- data/spec/{kramdown/man_spec.rb → man_spec.rb} +1 -1
- data/spec/spec_helper.rb +2 -0
- metadata +18 -11
- data/spec/kramdown/converter/man_spec.rb +0 -562
@@ -0,0 +1,969 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'kramdown/man/converter'
|
3
|
+
|
4
|
+
describe Kramdown::Man::Converter do
|
5
|
+
let(:markdown) { File.read('man/kramdown-man.1.md') }
|
6
|
+
let(:doc) { Kramdown::Document.new(markdown) }
|
7
|
+
let(:root) { doc.root }
|
8
|
+
|
9
|
+
subject { described_class.send(:new,root,{}) }
|
10
|
+
|
11
|
+
describe "#convert" do
|
12
|
+
let(:markdown) do
|
13
|
+
<<~MARKDOWN
|
14
|
+
# Header
|
15
|
+
|
16
|
+
Hello world.
|
17
|
+
MARKDOWN
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:root) { doc.root }
|
21
|
+
|
22
|
+
it "should add the header" do
|
23
|
+
expect(subject.convert(root)).to eq(
|
24
|
+
<<~ROFF
|
25
|
+
#{described_class::HEADER.chomp}
|
26
|
+
.TH Header
|
27
|
+
.PP
|
28
|
+
Hello world\\.
|
29
|
+
ROFF
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#convert_root" do
|
35
|
+
let(:markdown) do
|
36
|
+
<<~MARKDOWN
|
37
|
+
# Header
|
38
|
+
|
39
|
+
Hello world.
|
40
|
+
MARKDOWN
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:root) { doc.root }
|
44
|
+
|
45
|
+
it "should convert every element" do
|
46
|
+
expect(subject.convert_root(root)).to eq(
|
47
|
+
<<~ROFF
|
48
|
+
.TH Header
|
49
|
+
.PP
|
50
|
+
Hello world\\.
|
51
|
+
ROFF
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#convert_element" do
|
57
|
+
let(:markdown) { " puts 'hello'" }
|
58
|
+
let(:el) { doc.root.children[0] }
|
59
|
+
|
60
|
+
it "should convert the element based on it's type" do
|
61
|
+
expect(subject.convert_element(el)).to eq(subject.convert_codeblock(el))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#convert_blank" do
|
66
|
+
let(:markdown) do
|
67
|
+
<<~MARKDOWN
|
68
|
+
foo
|
69
|
+
|
70
|
+
bar
|
71
|
+
MARKDOWN
|
72
|
+
end
|
73
|
+
|
74
|
+
let(:blank) { doc.root.children[0].children[1] }
|
75
|
+
|
76
|
+
it "must return nil" do
|
77
|
+
expect(subject.convert_blank(blank)).to be(nil)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#convert_text" do
|
82
|
+
let(:content) { 'Foo bar' }
|
83
|
+
let(:markdown) { content }
|
84
|
+
let(:text) { doc.root.children[0].children[0] }
|
85
|
+
|
86
|
+
it "should convert text elements" do
|
87
|
+
expect(subject.convert_text(text)).to eq(content)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#convert_typographic_sym" do
|
92
|
+
context "ndash" do
|
93
|
+
let(:markdown) { "-- foo" }
|
94
|
+
let(:sym) { doc.root.children[0].children[0] }
|
95
|
+
|
96
|
+
it "should convert ndash symbols back into '\-\-'" do
|
97
|
+
expect(subject.convert_typographic_sym(sym)).to eq("\\-\\-")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "mdash" do
|
102
|
+
let(:markdown) { "--- foo" }
|
103
|
+
let(:sym) { doc.root.children[0].children[0] }
|
104
|
+
|
105
|
+
it "should convert mdash symbols into '\[em]'" do
|
106
|
+
expect(subject.convert_typographic_sym(sym)).to eq('\[em]')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "hellip" do
|
111
|
+
let(:markdown) { "... foo" }
|
112
|
+
let(:sym) { doc.root.children[0].children[0] }
|
113
|
+
|
114
|
+
it "should convert mdash symbols into '\\.\\.\\.'" do
|
115
|
+
expect(subject.convert_typographic_sym(sym)).to eq('\.\.\.')
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "laquo" do
|
120
|
+
let(:markdown) { "<< foo" }
|
121
|
+
let(:sym) { doc.root.children[0].children[0] }
|
122
|
+
|
123
|
+
it "should convert mdash symbols into '\[Fo]'" do
|
124
|
+
expect(subject.convert_typographic_sym(sym)).to eq('\[Fo]')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "raquo" do
|
129
|
+
let(:markdown) { "foo >> bar" }
|
130
|
+
let(:sym) { doc.root.children[0].children[1] }
|
131
|
+
|
132
|
+
it "should convert mdash symbols into '\[Fc]'" do
|
133
|
+
expect(subject.convert_typographic_sym(sym)).to eq('\[Fc]')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "laquo_space" do
|
138
|
+
let(:markdown) { " << foo" }
|
139
|
+
let(:sym) { doc.root.children[0].children[0] }
|
140
|
+
|
141
|
+
it "should convert mdash symbols into '\[Fo]'" do
|
142
|
+
expect(subject.convert_typographic_sym(sym)).to eq('\[Fo]')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context "raquo_space" do
|
147
|
+
let(:markdown) { "foo >> bar" }
|
148
|
+
let(:sym) { doc.root.children[0].children[1] }
|
149
|
+
|
150
|
+
it "should convert mdash symbols into '\[Fc]'" do
|
151
|
+
expect(subject.convert_typographic_sym(sym)).to eq('\[Fc]')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "#convert_smart_quote" do
|
157
|
+
context "lsquo" do
|
158
|
+
let(:markdown) { "'hello world'" }
|
159
|
+
let(:quote) { doc.root.children[0].children.first }
|
160
|
+
|
161
|
+
it "should convert lsquo quotes into '\[oq]'" do
|
162
|
+
expect(subject.convert_smart_quote(quote)).to eq('\[oq]')
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "rsquo" do
|
167
|
+
let(:markdown) { "'hello world'" }
|
168
|
+
let(:quote) { doc.root.children[0].children.last }
|
169
|
+
|
170
|
+
it "should convert rsquo quotes into '\[cq]'" do
|
171
|
+
expect(subject.convert_smart_quote(quote)).to eq('\[cq]')
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "ldquo" do
|
176
|
+
let(:markdown) { '"hello world"' }
|
177
|
+
let(:quote) { doc.root.children[0].children.first }
|
178
|
+
|
179
|
+
it "should convert lsquo quotes into '\[lq]'" do
|
180
|
+
expect(subject.convert_smart_quote(quote)).to eq('\[lq]')
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "rdquo" do
|
185
|
+
let(:markdown) { '"hello world"' }
|
186
|
+
let(:quote) { doc.root.children[0].children.last }
|
187
|
+
|
188
|
+
it "should convert lsquo quotes into '\[rq]'" do
|
189
|
+
expect(subject.convert_smart_quote(quote)).to eq('\[rq]')
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "#convert_header" do
|
195
|
+
let(:title) { 'Header' }
|
196
|
+
|
197
|
+
context "when level is 1" do
|
198
|
+
let(:markdown) { "# #{title}" }
|
199
|
+
let(:header) { doc.root.children[0] }
|
200
|
+
|
201
|
+
it "should convert level 1 headers into '.TH text'" do
|
202
|
+
expect(subject.convert_header(header)).to eq(
|
203
|
+
<<~ROFF
|
204
|
+
.TH #{title}
|
205
|
+
ROFF
|
206
|
+
)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context "when level is 2" do
|
211
|
+
let(:markdown) { "## #{title}" }
|
212
|
+
let(:header) { doc.root.children[0] }
|
213
|
+
|
214
|
+
it "should convert level 2 headers into '.SH text'" do
|
215
|
+
expect(subject.convert_header(header)).to eq(
|
216
|
+
<<~ROFF
|
217
|
+
.SH #{title}
|
218
|
+
ROFF
|
219
|
+
)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context "when level is 3" do
|
224
|
+
let(:markdown) { "### #{title}" }
|
225
|
+
let(:header) { doc.root.children[0] }
|
226
|
+
|
227
|
+
it "should convert level 2 headers into '.SS text'" do
|
228
|
+
expect(subject.convert_header(header)).to eq(
|
229
|
+
<<~ROFF
|
230
|
+
.SS #{title}
|
231
|
+
ROFF
|
232
|
+
)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context "when level is 4 or greater" do
|
237
|
+
let(:markdown) { "#### #{title}" }
|
238
|
+
let(:header) { doc.root.children[0] }
|
239
|
+
|
240
|
+
it "should convert level 2 headers into '.SS text'" do
|
241
|
+
expect(subject.convert_header(header)).to eq(
|
242
|
+
<<~ROFF
|
243
|
+
.SS #{title}
|
244
|
+
ROFF
|
245
|
+
)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe "#convert_hr" do
|
251
|
+
let(:markdown) { '------------------------------------' }
|
252
|
+
let(:hr) { doc.root.children[0] }
|
253
|
+
|
254
|
+
it "must return nil" do
|
255
|
+
expect(subject.convert_hr(hr)).to be(nil)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe "#convert_ul" do
|
260
|
+
let(:text1) { 'foo' }
|
261
|
+
let(:text2) { 'bar' }
|
262
|
+
let(:markdown) do
|
263
|
+
<<~MARKDOWN
|
264
|
+
* #{text1}
|
265
|
+
* #{text2}
|
266
|
+
MARKDOWN
|
267
|
+
end
|
268
|
+
|
269
|
+
let(:ul) { doc.root.children[0] }
|
270
|
+
|
271
|
+
it "should convert ul elements into '.RS\\n...\\n.RE\\n'" do
|
272
|
+
expect(subject.convert_ul(ul)).to eq(
|
273
|
+
<<~ROFF
|
274
|
+
.RS
|
275
|
+
.IP \\(bu 2
|
276
|
+
#{text1}
|
277
|
+
.IP \\(bu 2
|
278
|
+
#{text2}
|
279
|
+
.RE
|
280
|
+
ROFF
|
281
|
+
)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
describe "#convert_ul_li" do
|
286
|
+
let(:text) { 'hello world' }
|
287
|
+
let(:markdown) { "* #{text}" }
|
288
|
+
|
289
|
+
let(:li) { doc.root.children[0].children[0] }
|
290
|
+
|
291
|
+
it "should convert the first p element to '.IP \\\\(bu 2\\n...'" do
|
292
|
+
expect(subject.convert_ul_li(li)).to eq(
|
293
|
+
<<~ROFF
|
294
|
+
.IP \\(bu 2
|
295
|
+
#{text}
|
296
|
+
ROFF
|
297
|
+
)
|
298
|
+
end
|
299
|
+
|
300
|
+
context "with multiple multiple paragraphs" do
|
301
|
+
let(:text1) { 'hello' }
|
302
|
+
let(:text2) { 'world' }
|
303
|
+
let(:markdown) do
|
304
|
+
<<~MARKDOWN
|
305
|
+
* #{text1}
|
306
|
+
|
307
|
+
#{text2}
|
308
|
+
MARKDOWN
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should convert the other p elements to '.IP \\\\( 2\\n...'" do
|
312
|
+
expect(subject.convert_ul_li(li)).to eq(
|
313
|
+
<<~ROFF
|
314
|
+
.IP \\(bu 2
|
315
|
+
#{text1}
|
316
|
+
.IP \\( 2
|
317
|
+
#{text2}
|
318
|
+
ROFF
|
319
|
+
)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "#convert_ol" do
|
325
|
+
let(:text1) { 'foo' }
|
326
|
+
let(:text2) { 'bar' }
|
327
|
+
let(:markdown) do
|
328
|
+
<<~MARKDOWN
|
329
|
+
1. #{text1}
|
330
|
+
2. #{text2}
|
331
|
+
MARKDOWN
|
332
|
+
end
|
333
|
+
|
334
|
+
let(:ol) { doc.root.children[0] }
|
335
|
+
|
336
|
+
it "should convert ol elements into '.RS\\n...\\n.RE'" do
|
337
|
+
expect(subject.convert_ol(ol)).to eq(
|
338
|
+
<<~ROFF
|
339
|
+
.nr step1 0 1
|
340
|
+
.RS
|
341
|
+
.IP \\n+[step1]
|
342
|
+
#{text1}
|
343
|
+
.IP \\n+[step1]
|
344
|
+
#{text2}
|
345
|
+
.RE
|
346
|
+
ROFF
|
347
|
+
)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe "#convert_ol_li" do
|
352
|
+
let(:text) { 'hello world' }
|
353
|
+
let(:markdown) { "1. #{text}" }
|
354
|
+
|
355
|
+
let(:li) { doc.root.children[0].children[0] }
|
356
|
+
|
357
|
+
it "should convert the first p element to '.IP \\\\n+[step0]\\n...'" do
|
358
|
+
expect(subject.convert_ol_li(li)).to eq(
|
359
|
+
<<~ROFF
|
360
|
+
.IP \\n+[step0]
|
361
|
+
#{text}
|
362
|
+
ROFF
|
363
|
+
)
|
364
|
+
end
|
365
|
+
|
366
|
+
context "with multiple multiple paragraphs" do
|
367
|
+
let(:text1) { 'hello' }
|
368
|
+
let(:text2) { 'world' }
|
369
|
+
let(:markdown) do
|
370
|
+
<<~MARKDOWN
|
371
|
+
1. #{text1}
|
372
|
+
|
373
|
+
#{text2}
|
374
|
+
MARKDOWN
|
375
|
+
end
|
376
|
+
|
377
|
+
it "should convert the other p elements to '.IP \\\\n\\n...'" do
|
378
|
+
expect(subject.convert_ol_li(li)).to eq(
|
379
|
+
<<~ROFF
|
380
|
+
.IP \\n+[step0]
|
381
|
+
#{text1}
|
382
|
+
.IP \\n
|
383
|
+
#{text2}
|
384
|
+
ROFF
|
385
|
+
)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
describe "#convert_dl" do
|
391
|
+
let(:term) { "foo bar" }
|
392
|
+
let(:definition) { "baz qux" }
|
393
|
+
let(:markdown) do
|
394
|
+
<<~MARKDOWN
|
395
|
+
#{term}
|
396
|
+
: #{definition}
|
397
|
+
MARKDOWN
|
398
|
+
end
|
399
|
+
|
400
|
+
let(:dl) { doc.root.children[0] }
|
401
|
+
|
402
|
+
it "must convert dl elements into '.TP\n...\n...'" do
|
403
|
+
expect(subject.convert_dl(dl)).to eq(
|
404
|
+
<<~ROFF
|
405
|
+
.TP
|
406
|
+
#{term}
|
407
|
+
#{definition}
|
408
|
+
ROFF
|
409
|
+
)
|
410
|
+
end
|
411
|
+
|
412
|
+
context "when there are multiple term lines" do
|
413
|
+
let(:term1) { "foo" }
|
414
|
+
let(:term2) { "bar" }
|
415
|
+
let(:markdown) do
|
416
|
+
<<~MARKDOWN
|
417
|
+
#{term1}
|
418
|
+
#{term2}
|
419
|
+
: #{definition}
|
420
|
+
MARKDOWN
|
421
|
+
end
|
422
|
+
|
423
|
+
it "must convert the multi-term dl element into '.TP\\nterm1\\n.TQ\\nterm2\\n...'" do
|
424
|
+
expect(subject.convert_dl(dl)).to eq(
|
425
|
+
<<~ROFF
|
426
|
+
.TP
|
427
|
+
#{term1}
|
428
|
+
.TQ
|
429
|
+
#{term2}
|
430
|
+
#{definition}
|
431
|
+
ROFF
|
432
|
+
)
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
context "when there are multiple definitions for a term" do
|
437
|
+
let(:term) { "foo" }
|
438
|
+
let(:definition1) { "Foo bar." }
|
439
|
+
let(:definition2) { "Baz qux." }
|
440
|
+
let(:markdown) do
|
441
|
+
<<~MARKDOWN
|
442
|
+
#{term}
|
443
|
+
: #{definition1}
|
444
|
+
|
445
|
+
: #{definition2}
|
446
|
+
MARKDOWN
|
447
|
+
end
|
448
|
+
|
449
|
+
let(:dl) { doc.root.children[0] }
|
450
|
+
|
451
|
+
let(:escaped_definition1) { definition1.gsub('.',"\\.") }
|
452
|
+
let(:escaped_definition2) { definition2.gsub('.',"\\.") }
|
453
|
+
|
454
|
+
it "must convert the following p children into '.RS\\n.PP\\n...\\n.RE'" do
|
455
|
+
expect(subject.convert_dl(dl)).to eq(
|
456
|
+
<<~ROFF
|
457
|
+
.TP
|
458
|
+
#{term}
|
459
|
+
#{escaped_definition1}
|
460
|
+
.RS
|
461
|
+
.PP
|
462
|
+
#{escaped_definition2}
|
463
|
+
.RE
|
464
|
+
ROFF
|
465
|
+
)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
describe "#convert_dt" do
|
471
|
+
let(:word1) { "foo" }
|
472
|
+
let(:word2) { "bar" }
|
473
|
+
let(:word3) { "baz" }
|
474
|
+
let(:term) { "#{word1} `#{word2}` *#{word3}*" }
|
475
|
+
let(:definition) { "abc xyz" }
|
476
|
+
let(:markdown) do
|
477
|
+
<<~MARKDOWN
|
478
|
+
#{term}
|
479
|
+
: #{definition}
|
480
|
+
MARKDOWN
|
481
|
+
end
|
482
|
+
|
483
|
+
let(:dt) { doc.root.children[0].children[0] }
|
484
|
+
|
485
|
+
it "must convert the dt element into '.TP\n...'" do
|
486
|
+
expect(subject.convert_dt(dt)).to eq(
|
487
|
+
<<~ROFF
|
488
|
+
.TP
|
489
|
+
#{word1} \\fB#{word2}\\fR \\fI#{word3}\\fP
|
490
|
+
ROFF
|
491
|
+
)
|
492
|
+
end
|
493
|
+
|
494
|
+
context "when given the index: keyword" do
|
495
|
+
context "and it's greater than 1" do
|
496
|
+
it "must convert the dt element into '.TQ\n...'" do
|
497
|
+
expect(subject.convert_dt(dt, index: 1)).to eq(
|
498
|
+
<<~ROFF
|
499
|
+
.TQ
|
500
|
+
#{word1} \\fB#{word2}\\fR \\fI#{word3}\\fP
|
501
|
+
ROFF
|
502
|
+
)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
describe "#convert_dd" do
|
509
|
+
let(:term) { "abc xyz" }
|
510
|
+
let(:word1) { "foo" }
|
511
|
+
let(:word2) { "bar" }
|
512
|
+
let(:word3) { "baz" }
|
513
|
+
let(:definition) { "#{word1} `#{word2}` *#{word3}*" }
|
514
|
+
let(:markdown) do
|
515
|
+
<<~MARKDOWN
|
516
|
+
#{term}
|
517
|
+
: #{definition}
|
518
|
+
MARKDOWN
|
519
|
+
end
|
520
|
+
|
521
|
+
let(:dd) { doc.root.children[0].children[1] }
|
522
|
+
|
523
|
+
it "must convert the children p element within the dd element" do
|
524
|
+
expect(subject.convert_dd(dd)).to eq(
|
525
|
+
<<~ROFF
|
526
|
+
#{word1} \\fB#{word2}\\fR \\fI#{word3}\\fP
|
527
|
+
ROFF
|
528
|
+
)
|
529
|
+
end
|
530
|
+
|
531
|
+
context "when the given index: is 0" do
|
532
|
+
context "and when the dd element contains multiple p children" do
|
533
|
+
let(:word4) { "qux" }
|
534
|
+
let(:definition1) { "#{word1} #{word2}" }
|
535
|
+
let(:definition2) { "`#{word3}` *#{word4}*" }
|
536
|
+
let(:markdown) do
|
537
|
+
<<~MARKDOWN
|
538
|
+
#{term}
|
539
|
+
: #{definition1}
|
540
|
+
|
541
|
+
#{definition2}
|
542
|
+
MARKDOWN
|
543
|
+
end
|
544
|
+
|
545
|
+
it "must convert the following p children into '.RS\\n.PP\\n...\\n.RE'" do
|
546
|
+
expect(subject.convert_dd(dd)).to eq(
|
547
|
+
<<~ROFF
|
548
|
+
#{word1} #{word2}
|
549
|
+
.RS
|
550
|
+
.PP
|
551
|
+
\\fB#{word3}\\fR \\fI#{word4}\\fP
|
552
|
+
.RE
|
553
|
+
ROFF
|
554
|
+
)
|
555
|
+
end
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
context "when the given index: is greater than 0" do
|
560
|
+
let(:word4) { "qux" }
|
561
|
+
let(:definition1) { "#{word1} #{word2}" }
|
562
|
+
let(:definition2) { "`#{word3}` *#{word4}*" }
|
563
|
+
let(:markdown) do
|
564
|
+
<<~MARKDOWN
|
565
|
+
#{term}
|
566
|
+
: #{definition1}
|
567
|
+
|
568
|
+
: #{definition2}
|
569
|
+
MARKDOWN
|
570
|
+
end
|
571
|
+
|
572
|
+
let(:dd) { doc.root.children[0].children[2] }
|
573
|
+
|
574
|
+
it "must convert the child elements into '.RS\\n...\\n.RE'" do
|
575
|
+
expect(subject.convert_dd(dd, index: 1)).to eq(
|
576
|
+
<<~ROFF
|
577
|
+
.RS
|
578
|
+
.PP
|
579
|
+
\\fB#{word3}\\fR \\fI#{word4}\\fP
|
580
|
+
.RE
|
581
|
+
ROFF
|
582
|
+
)
|
583
|
+
end
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
describe "#convert_abbreviation" do
|
588
|
+
let(:acronym) { 'HTML' }
|
589
|
+
let(:definition) { 'Hyper Text Markup Language' }
|
590
|
+
let(:markdown) do
|
591
|
+
<<~MARKDOWN
|
592
|
+
This is an #{acronym} example.
|
593
|
+
|
594
|
+
*[#{acronym}]: #{definition}
|
595
|
+
MARKDOWN
|
596
|
+
end
|
597
|
+
|
598
|
+
let(:abbreviation) { doc.root.children[0].children[1] }
|
599
|
+
|
600
|
+
it "should convert abbreviation elements into their text" do
|
601
|
+
expect(subject.convert_abbreviation(abbreviation)).to eq(acronym)
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
describe "#convert_blockquote" do
|
606
|
+
let(:text) { "Some quote." }
|
607
|
+
let(:markdown) do
|
608
|
+
<<~MARKDOWN
|
609
|
+
> #{text}
|
610
|
+
MARKDOWN
|
611
|
+
end
|
612
|
+
let(:escaped_text) { 'Some quote\.' }
|
613
|
+
let(:blockquote) { doc.root.children[0] }
|
614
|
+
|
615
|
+
it "should convert blockquote elements into '.RS\\n.PP\\ntext...\\n.RE'" do
|
616
|
+
expect(subject.convert_blockquote(blockquote)).to eq(
|
617
|
+
<<~ROFF
|
618
|
+
.RS
|
619
|
+
.PP
|
620
|
+
#{escaped_text}
|
621
|
+
.RE
|
622
|
+
ROFF
|
623
|
+
)
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
describe "#convert_codeblock" do
|
628
|
+
let(:code) { "puts 'hello world'" }
|
629
|
+
let(:escaped_code) { 'puts \(aqhello world\(aq' }
|
630
|
+
let(:markdown) do
|
631
|
+
" #{code}"
|
632
|
+
end
|
633
|
+
|
634
|
+
let(:codeblock) { doc.root.children[0] }
|
635
|
+
|
636
|
+
it "should convert codeblock elements into '.PP\\n.EX\\ntext...\\n.EE'" do
|
637
|
+
expect(subject.convert_codeblock(codeblock)).to eq(
|
638
|
+
<<~ROFF
|
639
|
+
.PP
|
640
|
+
.RS 4
|
641
|
+
.EX
|
642
|
+
#{escaped_code}
|
643
|
+
.EE
|
644
|
+
.RE
|
645
|
+
ROFF
|
646
|
+
)
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
describe "#convert_comment" do
|
651
|
+
let(:text) { "Copyright (c) 2013" }
|
652
|
+
let(:markdown) do
|
653
|
+
<<~MARKDOWN
|
654
|
+
{::comment}
|
655
|
+
#{text}
|
656
|
+
{:/comment}
|
657
|
+
MARKDOWN
|
658
|
+
end
|
659
|
+
|
660
|
+
let(:comment) { doc.root.children[0] }
|
661
|
+
|
662
|
+
it "should convert comment elements into '.\\\" text...'" do
|
663
|
+
expect(subject.convert_comment(comment)).to eq(
|
664
|
+
<<~ROFF
|
665
|
+
.\\\" #{text}
|
666
|
+
ROFF
|
667
|
+
)
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
describe "#convert_p" do
|
672
|
+
let(:text) { "Hello world." }
|
673
|
+
let(:markdown) { text }
|
674
|
+
let(:escaped_text) { 'Hello world\.' }
|
675
|
+
|
676
|
+
let(:p) { doc.root.children[0] }
|
677
|
+
|
678
|
+
it "should convert p elements into '.PP\\ntext'" do
|
679
|
+
expect(subject.convert_p(p)).to eq(
|
680
|
+
<<~ROFF
|
681
|
+
.PP
|
682
|
+
#{escaped_text}
|
683
|
+
ROFF
|
684
|
+
)
|
685
|
+
end
|
686
|
+
end
|
687
|
+
|
688
|
+
describe "#convert_em" do
|
689
|
+
let(:text) { "hello world" }
|
690
|
+
let(:markdown) { "*#{text}*" }
|
691
|
+
|
692
|
+
let(:em) { doc.root.children[0].children[0] }
|
693
|
+
|
694
|
+
it "should convert em elements into '\\fItext\\fP'" do
|
695
|
+
expect(subject.convert_em(em)).to eq("\\fI#{text}\\fP")
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
describe "#convert_strong" do
|
700
|
+
let(:text) { "hello world" }
|
701
|
+
let(:markdown) { "**#{text}**" }
|
702
|
+
|
703
|
+
let(:strong) { doc.root.children[0].children[0] }
|
704
|
+
|
705
|
+
it "should convert strong elements into '\\fBtext\\fP'" do
|
706
|
+
expect(subject.convert_strong(strong)).to eq("\\fB#{text}\\fP")
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
describe "#convert_codespan" do
|
711
|
+
let(:code) { "puts 'hello world'" }
|
712
|
+
let(:markdown) { "`#{code}`" }
|
713
|
+
|
714
|
+
let(:codespan) { doc.root.children[0].children[0] }
|
715
|
+
|
716
|
+
it "should convert codespan elements into '\\fBcode\\fR'" do
|
717
|
+
expect(subject.convert_codespan(codespan)).to eq("\\fB#{code}\\fR")
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
describe "#convert_a" do
|
722
|
+
let(:text) { 'example' }
|
723
|
+
let(:href) { 'http://example.com/' }
|
724
|
+
let(:markdown) { "[#{text}](#{href})" }
|
725
|
+
let(:escaped_href) { 'http:\[sl]\[sl]example\.com\[sl]' }
|
726
|
+
|
727
|
+
let(:link) { doc.root.children[0].children[0] }
|
728
|
+
|
729
|
+
it "should convert a link elements into 'text\\n.UR href\\n.UE'" do
|
730
|
+
expect(subject.convert_a(link)).to eq(
|
731
|
+
<<~ROFF
|
732
|
+
#{text}
|
733
|
+
.UR #{escaped_href}
|
734
|
+
.UE
|
735
|
+
ROFF
|
736
|
+
)
|
737
|
+
end
|
738
|
+
|
739
|
+
context "when the href is to another .1.md file" do
|
740
|
+
let(:man) { 'foo-bar' }
|
741
|
+
let(:section) { '1' }
|
742
|
+
let(:markdown) { "[#{man}](#{man}.#{section}.md)" }
|
743
|
+
|
744
|
+
let(:escaped_man) { man.gsub('-','\\-') }
|
745
|
+
|
746
|
+
it "should convert the link elements into '.BR page (section)'" do
|
747
|
+
expect(subject.convert_a(link)).to eq(
|
748
|
+
<<~ROFF
|
749
|
+
.BR #{escaped_man} (#{section})
|
750
|
+
ROFF
|
751
|
+
)
|
752
|
+
end
|
753
|
+
end
|
754
|
+
|
755
|
+
context "when the href begins with mailto:" do
|
756
|
+
let(:text) { 'Bob' }
|
757
|
+
let(:email) { 'bob@example.com' }
|
758
|
+
let(:markdown) { "[#{text}](mailto:#{email})" }
|
759
|
+
|
760
|
+
let(:escaped_email) { 'bob\[at]example\.com' }
|
761
|
+
|
762
|
+
it "should convert the link elements into '.MT email\\n.ME'" do
|
763
|
+
expect(subject.convert_a(link)).to eq(
|
764
|
+
<<~ROFF
|
765
|
+
#{text}
|
766
|
+
.MT #{escaped_email}
|
767
|
+
.ME
|
768
|
+
ROFF
|
769
|
+
)
|
770
|
+
end
|
771
|
+
|
772
|
+
context "when link is <email>" do
|
773
|
+
let(:markdown) { "<#{email}>" }
|
774
|
+
|
775
|
+
it "should convert the link elements into '.MT email\\n.ME'" do
|
776
|
+
expect(subject.convert_a(link)).to eq(
|
777
|
+
<<~ROFF
|
778
|
+
.MT #{escaped_email}
|
779
|
+
.ME
|
780
|
+
ROFF
|
781
|
+
)
|
782
|
+
end
|
783
|
+
end
|
784
|
+
end
|
785
|
+
|
786
|
+
context "when the href begins with man:" do
|
787
|
+
let(:man) { 'bash' }
|
788
|
+
let(:markdown) { "[#{man}](man:#{man})" }
|
789
|
+
|
790
|
+
it "should convert the link elements into '.BR man'" do
|
791
|
+
expect(subject.convert_a(link)).to eq(
|
792
|
+
<<~ROFF
|
793
|
+
.BR #{man}
|
794
|
+
ROFF
|
795
|
+
)
|
796
|
+
end
|
797
|
+
|
798
|
+
context "and when the path is of the form 'page(section)'" do
|
799
|
+
let(:section) { '1' }
|
800
|
+
let(:markdown) { "[#{man}](man:#{man}(#{section}))" }
|
801
|
+
|
802
|
+
it "should convert the link elements into '.BR page (section)'" do
|
803
|
+
expect(subject.convert_a(link)).to eq(
|
804
|
+
<<~ROFF
|
805
|
+
.BR #{man} (#{section})
|
806
|
+
ROFF
|
807
|
+
)
|
808
|
+
end
|
809
|
+
end
|
810
|
+
|
811
|
+
context "and when the path is of the form 'page.section'" do
|
812
|
+
let(:section) { '1' }
|
813
|
+
let(:markdown) { "[#{man}](man:#{man}.#{section})" }
|
814
|
+
|
815
|
+
it "should convert the link elements into '.BR page (section)'" do
|
816
|
+
expect(subject.convert_a(link)).to eq(
|
817
|
+
<<~ROFF
|
818
|
+
.BR #{man} (#{section})
|
819
|
+
ROFF
|
820
|
+
)
|
821
|
+
end
|
822
|
+
end
|
823
|
+
|
824
|
+
context "when the path ends with a file extension" do
|
825
|
+
let(:file) { 'shard.yml' }
|
826
|
+
let(:escaped_file) { file.gsub('.','\\.') }
|
827
|
+
let(:markdown) { "[#{man}](man:#{file})" }
|
828
|
+
|
829
|
+
it "should convert the link elements into '.BR file'" do
|
830
|
+
expect(subject.convert_a(link)).to eq(
|
831
|
+
<<~ROFF
|
832
|
+
.BR #{escaped_file}
|
833
|
+
ROFF
|
834
|
+
)
|
835
|
+
end
|
836
|
+
end
|
837
|
+
end
|
838
|
+
end
|
839
|
+
|
840
|
+
describe "#man_page_link" do
|
841
|
+
let(:man) { 'foo-bar' }
|
842
|
+
|
843
|
+
let(:escaped_man) { man.gsub('-','\\-') }
|
844
|
+
|
845
|
+
it "should convert the link elements into '.BR man'" do
|
846
|
+
expect(subject.man_page_link(man)).to eq(
|
847
|
+
<<~ROFF
|
848
|
+
.BR #{escaped_man}
|
849
|
+
ROFF
|
850
|
+
)
|
851
|
+
end
|
852
|
+
|
853
|
+
context "when a section argument is given" do
|
854
|
+
let(:section) { '1' }
|
855
|
+
|
856
|
+
it "should convert the link elements into '.BR page (section)'" do
|
857
|
+
expect(subject.man_page_link(man,section)).to eq(
|
858
|
+
<<~ROFF
|
859
|
+
.BR #{escaped_man} (#{section})
|
860
|
+
ROFF
|
861
|
+
)
|
862
|
+
end
|
863
|
+
end
|
864
|
+
end
|
865
|
+
|
866
|
+
describe "#convert_children_of" do
|
867
|
+
let(:markdown) do
|
868
|
+
<<~MARKDOWN
|
869
|
+
A paragraph
|
870
|
+
|
871
|
+
* a list
|
872
|
+
MARKDOWN
|
873
|
+
end
|
874
|
+
|
875
|
+
let(:element) { doc.root }
|
876
|
+
|
877
|
+
it "must convert each element and join them into a String" do
|
878
|
+
expect(subject.convert_children_of(element)).to eq(
|
879
|
+
[
|
880
|
+
subject.convert_element(element.children[0]),
|
881
|
+
subject.convert_element(element.children[2])
|
882
|
+
].join
|
883
|
+
)
|
884
|
+
end
|
885
|
+
|
886
|
+
context "when the given elements contains an element that cannot be converted" do
|
887
|
+
let(:markdown) do
|
888
|
+
<<~MARKDOWN
|
889
|
+
A paragraph
|
890
|
+
|
891
|
+
----------------------------------------------------------------------
|
892
|
+
|
893
|
+
* a list
|
894
|
+
MARKDOWN
|
895
|
+
end
|
896
|
+
|
897
|
+
it "must omit the non-convertable elements" do
|
898
|
+
expect(subject.convert_children_of(element)).to eq(
|
899
|
+
[
|
900
|
+
subject.convert_element(element.children[0]),
|
901
|
+
subject.convert_element(element.children[4])
|
902
|
+
].join
|
903
|
+
)
|
904
|
+
end
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
describe "#convert_text_elements" do
|
909
|
+
let(:markdown) do
|
910
|
+
<<~MARKDOWN
|
911
|
+
Word *emphasis* **strong** `code`
|
912
|
+
MARKDOWN
|
913
|
+
end
|
914
|
+
let(:elements) { doc.root.children[0].children }
|
915
|
+
|
916
|
+
it "must convert each text element and join the results together" do
|
917
|
+
expect(subject.convert_text_elements(elements)).to eq(
|
918
|
+
[
|
919
|
+
subject.convert_element(elements[0]),
|
920
|
+
subject.convert_element(elements[1]),
|
921
|
+
subject.convert_element(elements[2]),
|
922
|
+
subject.convert_element(elements[3]),
|
923
|
+
subject.convert_element(elements[4]),
|
924
|
+
subject.convert_element(elements[5])
|
925
|
+
].join
|
926
|
+
)
|
927
|
+
end
|
928
|
+
|
929
|
+
context "when the text elements contain a 'a' type element" do
|
930
|
+
let(:markdown) do
|
931
|
+
<<~MARKDOWN
|
932
|
+
Word1 [link](https://example.com) word2.
|
933
|
+
MARKDOWN
|
934
|
+
end
|
935
|
+
|
936
|
+
it "must remove leading spaces from each line" do
|
937
|
+
expect(subject.convert_text_elements(elements)).to_not match(/^ /)
|
938
|
+
end
|
939
|
+
end
|
940
|
+
|
941
|
+
context "when the text elements contain consecutive 'a' elements" do
|
942
|
+
let(:markdown) do
|
943
|
+
<<~MARKDOWN
|
944
|
+
[link1](link1.html) [link2](link2.html) [link3](link3.html)
|
945
|
+
MARKDOWN
|
946
|
+
end
|
947
|
+
|
948
|
+
it "must avoid adding duplicate newlines" do
|
949
|
+
expect(subject.convert_text_elements(elements)).to eq(
|
950
|
+
[
|
951
|
+
subject.convert_element(elements[0]),
|
952
|
+
subject.convert_element(elements[2]),
|
953
|
+
subject.convert_element(elements[4]),
|
954
|
+
].join
|
955
|
+
)
|
956
|
+
end
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
describe "#escape" do
|
961
|
+
let(:text) { "hello\nworld" }
|
962
|
+
|
963
|
+
described_class::GLYPHS.each do |char,glyph|
|
964
|
+
it "should convert #{char.dump} into #{glyph.dump}" do
|
965
|
+
expect(subject.escape("#{text} #{char}")).to eq("#{text} #{glyph}")
|
966
|
+
end
|
967
|
+
end
|
968
|
+
end
|
969
|
+
end
|