md2man 1.0.1

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.
@@ -0,0 +1,3 @@
1
+ module Md2Man
2
+ VERSION = "1.0.1"
3
+ end
data/lib/md2man.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'md2man/version'
2
+ require 'md2man/engine'
data/man/man1/md2man.1 ADDED
@@ -0,0 +1,79 @@
1
+ .TH MD2MAN 1 "2011\-12\-06" "1.0.1"
2
+ .SH NAME
3
+ .PP
4
+ md2man \- convert
5
+ .BR markdown (7)
6
+ into
7
+ .BR roff (7)
8
+ .SH SYNOPSIS
9
+ .PP
10
+ \fB\fCmd2man\fR [\fIOPTION\fP]... [\fIFILE\fP]
11
+ .SH DESCRIPTION
12
+ .PP
13
+ md2man
14
+ .UR https://github.com/sunaku/md2man
15
+ .UE
16
+ converts
17
+ .BR markdown (7)
18
+ input from the given \fIFILE\fP into
19
+ .BR roff (7)
20
+ using
21
+ Redcarpet2
22
+ .UR https://github.com/tanoku/redcarpet
23
+ .UE
24
+ and then prints the result to the standard output stream. If
25
+ \fIFILE\fP is not given, then the standard input stream is read in its place.
26
+ .SS Document Format
27
+ .PP
28
+ The following additional semantics are attached to
29
+ .BR markdown (7):
30
+ .RS
31
+ .IP \(bu 2
32
+ There can be at most one top\-level heading (H1). It is emitted as \fB\fC.TH\fR
33
+ in the
34
+ .BR roff (7)
35
+ output, specifying the UNIX man page's header and footer.
36
+ .IP \(bu 2
37
+ Paragraphs whose lines are all uniformly indented by two spaces are
38
+ considered to be "indented paragraphs". They are unindented accordingly
39
+ before emission as \fB\fC.IP\fR in the
40
+ .BR roff (7)
41
+ output.
42
+ .IP \(bu 2
43
+ Paragraphs whose subsequent lines (all except the first) are uniformly
44
+ indented by two spaces are considered to be a "tagged paragraphs". They
45
+ are unindented accordingly before emission as \fB\fC.TP\fR in the
46
+ .BR roff (7)
47
+ output.
48
+ .RE
49
+ .SS Markdown Extensions
50
+ .PP
51
+ The following Redcarpet2
52
+ .UR https://github.com/tanoku/redcarpet
53
+ .UE
54
+ extensions for
55
+ .BR markdown (7)
56
+ are enabled:
57
+ .RS
58
+ .IP \(bu 2
59
+ tables
60
+ .IP \(bu 2
61
+ autolink
62
+ .IP \(bu 2
63
+ superscript
64
+ .IP \(bu 2
65
+ strikethrough
66
+ .IP \(bu 2
67
+ no_intra_emphasis
68
+ .IP \(bu 2
69
+ fenced_code_blocks
70
+ .RE
71
+ .SH OPTIONS
72
+ .TP
73
+ \fB\fC-h\fR, \fB\fC--help\fR
74
+ Display this help manual using
75
+ .BR man (1).
76
+ .SH SEE ALSO
77
+ .PP
78
+ .BR markdown (7),
79
+ .BR roff (7)
data/md2man.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "md2man/version"
4
+ require "binman/gemspec"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "md2man"
8
+ s.version = Md2Man::VERSION
9
+ s.authors,
10
+ s.email = File.read('LICENSE').scan(/Copyright \d+ (.+) <(.+?)>/).transpose
11
+ s.homepage = "http://github.com/sunaku/md2man"
12
+ s.summary = "UNIX man pages using Redcarpet2"
13
+ s.description = nil
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ # specify any dependencies here; for example:
21
+ # s.add_development_dependency "rspec"
22
+ # s.add_runtime_dependency "rest-client"
23
+ s.add_runtime_dependency "redcarpet", ">= 2.0.0b5", "< 3"
24
+ s.add_development_dependency "minitest", ">= 2.7.0", "< 3"
25
+ end
@@ -0,0 +1,584 @@
1
+ # http://www.linuxjournal.com/article/1158
2
+ # http://www.premvet.co.uk/premvet/faq/roff.html
3
+ # http://www.linuxhowtos.org/System/creatingman.htm
4
+ # http://www.fnal.gov/docs/products/ups/ReferenceManual/html/manpages.html
5
+ # http://serverfault.com/questions/109490/how-do-i-write-man-pages
6
+ # man groff_man
7
+ # man 7 groff
8
+
9
+ require 'test_helper'
10
+ require 'md2man/engine'
11
+
12
+ describe Md2Man::Roff do
13
+ before do
14
+ @markdown = Redcarpet::Markdown.new(
15
+ Md2Man::Engine,
16
+ :tables => true,
17
+ :autolink => true,
18
+ )
19
+ end
20
+
21
+ SPACE = 0x20.chr
22
+
23
+ def heredoc document
24
+ document.gsub(/^\s*\|/, '').chomp
25
+ end
26
+
27
+ it 'renders nothing as nothing' do
28
+ @markdown.render('').must_be_empty
29
+ end
30
+
31
+ it 'renders paragraphs' do
32
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
33
+ |just some paragraph
34
+ |spanning
35
+ |multiple
36
+ |lines
37
+ |but within 4-space indent
38
+ INPUT
39
+ |.PP
40
+ |just some paragraph
41
+ |spanning
42
+ |multiple
43
+ |lines
44
+ |but within 4\\-space indent
45
+ OUTPUT
46
+ end
47
+
48
+ it 'renders paragraphs with unevenly indented bodies' do
49
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
50
+ |just some paragraph
51
+ | spanning
52
+ | multiple
53
+ | lines
54
+ |but within 4-space indent
55
+ INPUT
56
+ |.PP
57
+ |just some paragraph
58
+ | spanning
59
+ | multiple
60
+ | lines
61
+ |but within 4\\-space indent
62
+ OUTPUT
63
+ end
64
+
65
+ it 'renders tagged paragraphs with uniformly two-space indented bodies' do
66
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
67
+ |just some paragraph
68
+ | spanning
69
+ | multiple
70
+ | lines
71
+ | but within 4-space indent
72
+ INPUT
73
+ |.TP
74
+ |just some paragraph
75
+ |spanning
76
+ |multiple
77
+ |lines
78
+ |but within 4\\-space indent
79
+ OUTPUT
80
+ end
81
+
82
+ it 'renders indented paragraphs that are uniformly two-space indented' do
83
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
84
+ | just some paragraph
85
+ | spanning
86
+ | multiple
87
+ | lines
88
+ | but within 4-space indent
89
+ INPUT
90
+ |.IP
91
+ |just some paragraph
92
+ |spanning
93
+ |multiple
94
+ |lines
95
+ |but within 4\\-space indent
96
+ OUTPUT
97
+ end
98
+
99
+ it 'renders tagged, indented, and normal paragraphs' do
100
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
101
+ |This is a
102
+ |normal paragraph.
103
+ |
104
+ |This is a
105
+ | tagged paragraph.
106
+ |
107
+ | This is another
108
+ |tagged paragraph.
109
+ |
110
+ | This is an
111
+ | indented
112
+ | paragraph.
113
+ |
114
+ |This
115
+ | is another
116
+ | normal
117
+ | paragraph.
118
+ INPUT
119
+ |.PP
120
+ |This is a
121
+ |normal paragraph.
122
+ |.TP
123
+ |This is a
124
+ |tagged paragraph.
125
+ |.TP
126
+ |This is another
127
+ |tagged paragraph.
128
+ |.IP
129
+ |This is an
130
+ |indented
131
+ |paragraph.
132
+ |.PP
133
+ |This
134
+ | is another
135
+ | normal
136
+ | paragraph.
137
+ OUTPUT
138
+ end
139
+ it 'escapes hyphens in normal text' do
140
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
141
+ |pre-process
142
+ INPUT
143
+ |.PP
144
+ |pre\\-process
145
+ OUTPUT
146
+
147
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
148
+ |1-5
149
+ INPUT
150
+ |.PP
151
+ |1\\-5
152
+ OUTPUT
153
+ end
154
+
155
+ it 'renders emphasis' do
156
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
157
+ |just *some paragraph*
158
+ | spanning
159
+ | multiple
160
+ | *lines*
161
+ |but within 4-*space* indent
162
+ INPUT
163
+ |.PP
164
+ |just \\fIsome paragraph\\fP
165
+ | spanning
166
+ | multiple
167
+ | \\fIlines\\fP
168
+ |but within 4\\-\\fIspace\\fP indent
169
+ OUTPUT
170
+ end
171
+
172
+ it 'renders double emphasis' do
173
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
174
+ |just **some paragraph**
175
+ | spanning
176
+ | multiple
177
+ | **lines**
178
+ |but within 4-**space** indent
179
+ INPUT
180
+ |.PP
181
+ |just \\fBsome paragraph\\fP
182
+ | spanning
183
+ | multiple
184
+ | \\fBlines\\fP
185
+ |but within 4\\-\\fBspace\\fP indent
186
+ OUTPUT
187
+ end
188
+
189
+ it 'renders triple emphasis' do
190
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
191
+ |just ***some paragraph***
192
+ | spanning
193
+ | multiple
194
+ | ***lines***
195
+ |but within 4-***space*** indent
196
+ INPUT
197
+ |.PP
198
+ |just \\s+2\\fBsome paragraph\\fP\\s-2
199
+ | spanning
200
+ | multiple
201
+ | \\s+2\\fBlines\\fP\\s-2
202
+ |but within 4\\-\\s+2\\fBspace\\fP\\s-2 indent
203
+ OUTPUT
204
+ end
205
+
206
+ it 'renders top-level headings' do
207
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
208
+ |just some h1 heading
209
+ |====================
210
+ INPUT
211
+ |.TH just some h1 heading
212
+ OUTPUT
213
+
214
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
215
+ |BINMAN 1 "2011-11-05" "1.1.0" "Ruby User Manuals"
216
+ |=================================================
217
+ INPUT
218
+ |.TH BINMAN 1 "2011\\-11\\-05" "1.1.0" "Ruby User Manuals"
219
+ OUTPUT
220
+ end
221
+
222
+ it 'renders 2nd-level headings' do
223
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
224
+ |just some h2 heading
225
+ |--------------------
226
+ INPUT
227
+ |.SH just some h2 heading
228
+ OUTPUT
229
+ end
230
+
231
+ it 'renders level 3..6 headings' do
232
+ (3..6).each do |level|
233
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
234
+ |#{'#' * level} just some subheading
235
+ INPUT
236
+ |.SS just some subheading
237
+ OUTPUT
238
+ end
239
+ end
240
+
241
+ it 'renders linebreaks (2 spaces at EOL)' do
242
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
243
+ |line#{SPACE}#{SPACE}
244
+ |break
245
+ INPUT
246
+ |.PP
247
+ |line
248
+ |.br
249
+ |break
250
+ OUTPUT
251
+ end
252
+
253
+ it 'renders blockquotes' do
254
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
255
+ |>just some paragraph
256
+ |> spanning
257
+ |> multiple
258
+ |> lines
259
+ |>but within 4-space indent
260
+ INPUT
261
+ |.RS
262
+ |just some paragraph
263
+ |spanning
264
+ | multiple
265
+ | lines
266
+ |but within 4\\-space indent
267
+ |.RE
268
+ OUTPUT
269
+ end
270
+
271
+ it 'renders code blocks' do
272
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
273
+ | single preformatted line
274
+ INPUT
275
+ |.nf
276
+ |single preformatted line
277
+ |.fi
278
+ OUTPUT
279
+
280
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
281
+ | just some *paragraph*
282
+ | spanning
283
+ | **multiple**
284
+ | > lines
285
+ | with 4-space indent
286
+ INPUT
287
+ |.nf
288
+ |just some *paragraph*
289
+ | spanning
290
+ | **multiple**
291
+ |> lines
292
+ |with 4-space indent
293
+ |.fi
294
+ OUTPUT
295
+ end
296
+
297
+ it 'renders code spans' do
298
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
299
+ |here is `some code` for you
300
+ INPUT
301
+ |.PP
302
+ |here is \\fB\\fCsome code\\fR for you
303
+ OUTPUT
304
+ end
305
+
306
+ it 'renders hyperlinks' do
307
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
308
+ |Send [me](mailto:foo@bar.baz), e-mail.
309
+ INPUT
310
+ |.PP
311
+ |Send me
312
+ |.MT foo@bar.baz
313
+ |.ME , e\\-mail.
314
+ OUTPUT
315
+
316
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
317
+ |Take [me](http://myself), somewhere.
318
+ INPUT
319
+ |.PP
320
+ |Take me
321
+ |.UR http://myself
322
+ |.UE , somewhere.
323
+ OUTPUT
324
+
325
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
326
+ |Mail me foo@bar.baz now.
327
+ INPUT
328
+ |.PP
329
+ |Mail me#{SPACE}
330
+ |.MT foo@bar.baz
331
+ |.ME
332
+ |now.
333
+ OUTPUT
334
+
335
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
336
+ |Take me http://www.somewhere now.
337
+ INPUT
338
+ |.PP
339
+ |Take me#{SPACE}
340
+ |.UR http://www.somewhere
341
+ |.UE
342
+ |now.
343
+ OUTPUT
344
+ end
345
+
346
+ it 'renders unordered lists' do
347
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
348
+ |Here is an unordered list:
349
+ |
350
+ |* foo
351
+ | * bar
352
+ | * baz
353
+ |* qux
354
+ INPUT
355
+ |.PP
356
+ |Here is an unordered list:
357
+ |.RS
358
+ |.IP \\(bu 2
359
+ |foo
360
+ |.RS
361
+ |.IP \\(bu 2
362
+ |bar
363
+ |.RS
364
+ |.IP \\(bu 2
365
+ |baz
366
+ |.RE
367
+ |.RE
368
+ |.IP \\(bu 2
369
+ |qux
370
+ |.RE
371
+ OUTPUT
372
+ end
373
+
374
+ it 'renders unordered lists while squashing first paragraphs' do
375
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
376
+ |Here is an unordered list:
377
+ |
378
+ | * here is a
379
+ | paragraph
380
+ |
381
+ | here is a
382
+ | subparagraph
383
+ INPUT
384
+ |.PP
385
+ |Here is an unordered list:
386
+ |.RS
387
+ |.IP \\(bu 2
388
+ |here is a
389
+ |paragraph
390
+ |.PP
391
+ |here is a
392
+ |subparagraph
393
+ |.RE
394
+ OUTPUT
395
+ end
396
+
397
+ it 'renders ordered lists' do
398
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
399
+ |Here is an ordered list:
400
+ |
401
+ |1. foo
402
+ | 1. bar
403
+ | 1. baz
404
+ |2. qux
405
+ INPUT
406
+ |.PP
407
+ |Here is an ordered list:
408
+ |.nr step2 0 1
409
+ |.RS
410
+ |.IP \\n+[step2]
411
+ |foo
412
+ |.nr step1 0 1
413
+ |.RS
414
+ |.IP \\n+[step1]
415
+ |bar
416
+ |.nr step0 0 1
417
+ |.RS
418
+ |.IP \\n+[step0]
419
+ |baz
420
+ |.RE
421
+ |.RE
422
+ |.IP \\n+[step2]
423
+ |qux
424
+ |.RE
425
+ OUTPUT
426
+ end
427
+
428
+ it 'renders ordered lists while squashing first paragraphs' do
429
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
430
+ |Here is an ordered list:
431
+ |
432
+ |1. here is a
433
+ | paragraph
434
+ |
435
+ | here is a
436
+ | subparagraph
437
+ INPUT
438
+ |.PP
439
+ |Here is an ordered list:
440
+ |.nr step0 0 1
441
+ |.RS
442
+ |.IP \\n+[step0]
443
+ |here is a
444
+ |paragraph
445
+ |.PP
446
+ |here is a
447
+ |subparagraph
448
+ |.RE
449
+ OUTPUT
450
+ end
451
+
452
+ it 'renders horizontal rules' do
453
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
454
+ |foo
455
+ |
456
+ |* * *
457
+ |
458
+ |bar
459
+ INPUT
460
+ |.PP
461
+ |foo
462
+ |.ti 0
463
+ |\\l'\\n(.lu'
464
+ |.PP
465
+ |bar
466
+ OUTPUT
467
+ end
468
+
469
+ it 'renders horizontal rules inside blockquotes' do
470
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
471
+ |>foo
472
+ |>
473
+ |>* * *
474
+ |>
475
+ |>bar
476
+ INPUT
477
+ |.RS
478
+ |foo
479
+ |.ti 0
480
+ |\\l'\\n(.lu'
481
+ |.PP
482
+ |bar
483
+ |.RE
484
+ OUTPUT
485
+ end
486
+
487
+ it 'renders some named entities' do
488
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
489
+ |&middot; &#183;
490
+ |&copy; &#169;
491
+ |&cent; &#162;
492
+ |&Dagger; &#8225;
493
+ |&deg; &#176;
494
+ |&dagger; &#8224;
495
+ |&quot; &#34;
496
+ |&mdash; &#8212;
497
+ |&ndash; &#8211;
498
+ |&reg; &#174;
499
+ |&sect; &#167;
500
+ |&oline; &#8254;
501
+ |&equiv; &#8801;
502
+ |&ge; &#8805;
503
+ |&le; &#8804;
504
+ |&ne; &#8800;
505
+ |&rarr; &#8594;
506
+ |&larr; &#8592;
507
+ |&plusmn; &#177;
508
+ INPUT
509
+ |.PP
510
+ |\\[pc] \\[pc]
511
+ |\\[co] \\[co]
512
+ |\\[ct] \\[ct]
513
+ |\\[dd] \\[dd]
514
+ |\\[de] \\[de]
515
+ |\\[dg] \\[dg]
516
+ |\\[dq] \\[dq]
517
+ |\\[em] \\[em]
518
+ |\\[en] \\[en]
519
+ |\\[rg] \\[rg]
520
+ |\\[sc] \\[sc]
521
+ |\\[rn] \\[rn]
522
+ |\\[==] \\[==]
523
+ |\\[>=] \\[>=]
524
+ |\\[<=] \\[<=]
525
+ |\\[!=] \\[!=]
526
+ |\\[->] \\[->]
527
+ |\\[<-] \\[<-]
528
+ |\\[+-] \\[+-]
529
+ OUTPUT
530
+ end
531
+
532
+ it 'renders tables' do
533
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
534
+ |First Header | Second Header
535
+ |------------- | -------------
536
+ |First Content | Second Content
537
+ INPUT
538
+ |.TS
539
+ |allbox;
540
+ |cb cb
541
+ |l l
542
+ |.
543
+ |First Header\tSecond Header
544
+ |First Content\tSecond Content
545
+ |.TE
546
+ OUTPUT
547
+ end
548
+
549
+ it 'renders tables with alignment' do
550
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
551
+ || Item | Value |
552
+ || --------- | -----:|
553
+ || Computer | $1600 |
554
+ || Phone | $12 |
555
+ || Pipe | $1 |
556
+ INPUT
557
+ |.TS
558
+ |allbox;
559
+ |cb cb
560
+ |l r
561
+ |l r
562
+ |l r
563
+ |.
564
+ |Item\tValue
565
+ |Computer\t$1600
566
+ |Phone\t$12
567
+ |Pipe\t$1
568
+ |.TE
569
+ OUTPUT
570
+ end
571
+
572
+ it 'renders references to other man pages as hyperlinks' do
573
+ @markdown.render(heredoc(<<-INPUT)).must_equal(heredoc(<<-OUTPUT))
574
+ |convert them from markdown(7) into roff(7), using
575
+ INPUT
576
+ |.PP
577
+ |convert them from#{SPACE}
578
+ |.BR markdown (7)#{SPACE}
579
+ |into#{SPACE}
580
+ |.BR roff (7),#{SPACE}
581
+ |using
582
+ OUTPUT
583
+ end
584
+ end
@@ -0,0 +1,2 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'