kramdown-man 0.1.7

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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 880a3d1dd1e58aa950685bf312a66797f2d39d33c436eb9d67525289ce8abf45
4
+ data.tar.gz: e2f259869cb035f4868dab9ac584da53eafacbccc76b3323c3c32deb3133163c
5
+ SHA512:
6
+ metadata.gz: 7d2b3f3a3fa1d58fc40e980fe8a6193746c2d6b4b38ddbbe4682b7c209128df67cc30090d08deaad0c2e59d62bec6fa3226ab7670d8d13c499c431a21a2feec9
7
+ data.tar.gz: 14630b3b4ba02083266fc248b7179d409c79937f20fb81bb2feb0bf61c657b88999a8ec95e6912e1bd0bd7d0c012927d3cc58386f5cb95e4246745b698ccf0bc
@@ -0,0 +1,4 @@
1
+ -
2
+ ChangeLog.md
3
+ LICENSE.txt
4
+ man/kramdown-man.1.md
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ doc/
3
+ pkg/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
@@ -0,0 +1,11 @@
1
+ ---
2
+ before_install:
3
+ - gem update --system
4
+ - gem install bundler -v "~> 2.0"
5
+ language: ruby
6
+ rvm:
7
+ - 2.5
8
+ - 2.6
9
+ - 2.7
10
+ - jruby
11
+ script: bundle exec rake spec
@@ -0,0 +1 @@
1
+ --markup markdown --markup-provider kramdown --title "kramdown-man Documentation" --protected
@@ -0,0 +1,45 @@
1
+ ### 0.1.7 / 2020-07-22
2
+
3
+ * Fixed a bug where kramdown's version of `kramdown/converter/man` was being
4
+ loaded instead of kramdown-man's version.
5
+
6
+ ### 0.1.6 / 2015-12-25
7
+
8
+ * Commented out duplicate Hash entries that were causing warnings.
9
+
10
+ ### 0.1.5 / 2013-05-19
11
+
12
+ * Translate unicode symbols into roff glyphs.
13
+ * Convert typographic symbols and smart quotes into glyphs.
14
+ * Simplify `\fB\fC` as `\fC` (Colin Watson).
15
+ * Use `\fB` for codespans (Colin Watson).
16
+ * Escape `--` as `\-\-` (Colin Watson).
17
+ * Escape `\` as `\e` (Colin Watson).
18
+ * Emit `.TP` or `.HP` if the paragraph begins with a strong element.
19
+
20
+ ### 0.1.4 / 2013-05-05
21
+
22
+ * Improve detection of tagged paragraphs.
23
+ * Support emitted a hanging paragraph (`.HP`) for command synopsis lines.
24
+ * Strip leading whitespace from each line of emitted text.
25
+
26
+ ### 0.1.3 / 2013-05-05
27
+
28
+ * Initial release:
29
+ * Converts markdown to [roff]:
30
+ * Supports codespans, emphasis and strong fonts.
31
+ * Supports normal and tagged paragraphs.
32
+ * Supports bullet lists.
33
+ * Supports multi-paragraph list items and blockquotes.
34
+ * Supports horizontal rules.
35
+ * Supports converting `[bash](man:bash(1))` links into man page references.
36
+ * Provides Rake task for converting `man/*.md` into man pages.
37
+ * Uses the pure-Ruby [Kramdown][kramdown] markdown parser.
38
+ * Supports [Ruby] 1.8.x, 1.9.x, 2.0.x, [JRuby], [Rubinius].
39
+
40
+ [kramdown]: http://kramdown.rubyforge.org/
41
+ [roff]: http://en.wikipedia.org/wiki/Roff
42
+
43
+ [Ruby]: http://www.ruby-lang.org/
44
+ [JRuby]: http://jruby.org/
45
+ [Rubinius]: http://rubini.us/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org/'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'rubygems-tasks', '~> 0.2'
8
+ gem 'rspec', '~> 3.0'
9
+ gem 'yard', '~> 0.9'
10
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013-2020 Hal Brodigan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,181 @@
1
+ # kramdown-man
2
+
3
+ * [Homepage](https://github.com/postmodern/kramdown-man#readme)
4
+ * [Issues](https://github.com/postmodern/kramdown-man/issues)
5
+ * [Documentation](http://rubydoc.info/gems/kramdown-man/frames)
6
+ * [Email](mailto:postmodern.mod3 at gmail.com)
7
+
8
+ [![Build Status](https://secure.travis-ci.org/postmodern/kramdown-man.png?branch=master)](https://travis-ci.org/postmodern/kramdown-man)
9
+
10
+ ## Description
11
+
12
+ A [Kramdown][kramdown] convert for converting Markdown files into man pages.
13
+
14
+ ## Features
15
+
16
+ * Converts markdown to [roff]:
17
+ * Supports codespans, emphasis and strong fonts.
18
+ * Supports normal, hanging and tagged paragraphs.
19
+ * Supports bullet lists.
20
+ * Supports multi-paragraph list items and blockquotes.
21
+ * Supports horizontal rules.
22
+ * Supports converting `[bash](man:bash(1))` links into man page references.
23
+ * Provides Rake task for converting `man/*.md` into man pages.
24
+ * Uses the pure-Ruby [Kramdown][kramdown] markdown parser.
25
+ * Supports [Ruby] 2.0 and [JRuby].
26
+
27
+ ## Synopsis
28
+
29
+ Render a man page from markdown:
30
+
31
+ $ kramdown-man <man/myprog.1.md >man/myprog.1
32
+
33
+ ## Examples
34
+
35
+ Render a man page from a markdown file:
36
+
37
+ require 'kramdown/man'
38
+
39
+ doc = Kramdown::Document.new(File.read('man/kramdown-man.1.md'))
40
+ File.write('man/kramdown-man.1',doc.to_man)
41
+
42
+ system 'man', 'man/kramdown-man.1'
43
+
44
+ Define a `man` and file tasks which render all `*.md` files within the
45
+ `man/` directory:
46
+
47
+ require 'kramdown/man/task'
48
+ Kramdown::Man::Task.new
49
+
50
+ ## Syntax
51
+
52
+ ### Formatting
53
+
54
+ `code`
55
+
56
+ `code`
57
+
58
+ *emphasis*
59
+
60
+ *emphasis*
61
+
62
+ **strong**
63
+
64
+ **strong**
65
+
66
+ ### Paragraphs
67
+
68
+ Normal paragraph.
69
+
70
+ Normal paragraph.
71
+
72
+ `command` [`--foo`] *FILE*
73
+
74
+ `command` [`--foo`] *FILE*
75
+
76
+ `--tagged`
77
+ Text here.
78
+
79
+ `--tagged`
80
+ Text here.
81
+
82
+ ### Links
83
+
84
+ [website](http://example.com/)
85
+
86
+ [website](http://example.com/)
87
+
88
+ [bash](man:bash(1))
89
+
90
+ [bash](man:bash(1))
91
+
92
+ Email <bob@example.com>
93
+
94
+ Email <bob@example.com>
95
+
96
+ ### Lists
97
+
98
+ * one
99
+ * two
100
+ * three
101
+
102
+ extra paragraph
103
+
104
+
105
+ * one
106
+ * two
107
+ * three
108
+
109
+ extra paragraph
110
+
111
+ 1. one
112
+ 2. two
113
+ 3. three
114
+
115
+ extra paragraph
116
+
117
+ 1. one
118
+ 2. two
119
+ 3. three
120
+
121
+ extra paragraph
122
+
123
+ ### Horizontal Rule
124
+
125
+ -------------------------------------------------------------------------------
126
+
127
+ -------------------------------------------------------------------------------
128
+
129
+ ### Blockquotes
130
+
131
+ > Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
132
+ >
133
+ > --Antoine de Saint-Exupéry
134
+
135
+ > Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
136
+ >
137
+ > --Antoine de Saint-Exupéry
138
+
139
+ ### Code Blocks
140
+
141
+ #include <stdio.h>
142
+
143
+ int main()
144
+ {
145
+ printf("hello world\n");
146
+ return 0;
147
+ }
148
+
149
+ #include <stdio.h>
150
+
151
+ int main()
152
+ {
153
+ printf("hello world\n");
154
+ return 0;
155
+ }
156
+
157
+ ## Requirements
158
+
159
+ * [kramdown] ~> 1.0
160
+
161
+ ## Install
162
+
163
+ $ gem install kramdown-man
164
+
165
+ ## Alternatives
166
+
167
+ * [Redcarpet::Render::ManPage](http://rubydoc.info/gems/redcarpet/Redcarpet/Render/ManPage)
168
+ * [ronn](https://github.com/rtomayko/ronn#readme)
169
+ * [md2man](https://github.com/sunaku/md2man#readme)
170
+
171
+ ## Copyright
172
+
173
+ Copyright (c) 2013-2020 Hal Brodigan
174
+
175
+ See {file:LICENSE.txt} for details.
176
+
177
+ [kramdown]: http://kramdown.gettalong.org/
178
+ [roff]: http://en.wikipedia.org/wiki/Roff
179
+
180
+ [Ruby]: http://www.ruby-lang.org/
181
+ [JRuby]: http://jruby.org/
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError => error
6
+ abort error.message
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rubygems/tasks'
11
+ Gem::Tasks.new
12
+
13
+ require 'rspec/core/rake_task'
14
+ RSpec::Core::RakeTask.new
15
+ task :test => :spec
16
+ task :default => :spec
17
+
18
+ require 'yard'
19
+ YARD::Rake::YardocTask.new
20
+ task :doc => :yard
21
+
22
+ require 'kramdown/man/task'
23
+ Kramdown::Man::Task.new
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib_dir = File.expand_path('../lib',File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
5
+
6
+ require 'kramdown'
7
+ require 'kramdown/man'
8
+
9
+ case ARGV[0]
10
+ when '-h', '--help'
11
+ warn "usage: #{File.dirname($0)} <INPUT.md >OUTPUT"
12
+ exit
13
+ end
14
+
15
+ doc = Kramdown::Document.new(ARGF.read)
16
+ puts doc.to_man
@@ -0,0 +1,13 @@
1
+ name: kramdown-man
2
+ summary: Converts markdown to man pages
3
+ description: A Kramdown converter for converting Markdown files into man pages.
4
+ license: MIT
5
+ authors: Postmodern
6
+ email: postmodern.mod3@gmail.com
7
+ homepage: https://github.com/postmodern/kramdown-man#readme
8
+
9
+ dependencies:
10
+ kramdown: ~> 1.0
11
+
12
+ development_dependencies:
13
+ bundler: ~> 2.0
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gemspec = YAML.load_file('gemspec.yml')
7
+
8
+ gem.name = gemspec.fetch('name')
9
+ gem.version = gemspec.fetch('version') do
10
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
11
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
12
+
13
+ require 'kramdown/man/version'
14
+ Kramdown::Man::VERSION
15
+ end
16
+
17
+ gem.summary = gemspec['summary']
18
+ gem.description = gemspec['description']
19
+ gem.licenses = Array(gemspec['license'])
20
+ gem.authors = Array(gemspec['authors'])
21
+ gem.email = gemspec['email']
22
+ gem.homepage = gemspec['homepage']
23
+
24
+ glob = lambda { |patterns| gem.files & Dir[*patterns] }
25
+
26
+ gem.files = `git ls-files`.split($/)
27
+ gem.files = glob[gemspec['files']] if gemspec['files']
28
+
29
+ gem.executables = gemspec.fetch('executables') do
30
+ glob['bin/*'].map { |path| File.basename(path) }
31
+ end
32
+ gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
33
+
34
+ gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
35
+ gem.test_files = glob[gemspec['test_files'] || '{test/{**/}*_test.rb']
36
+ gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
37
+
38
+ gem.require_paths = Array(gemspec.fetch('require_paths') {
39
+ %w[ext lib].select { |dir| File.directory?(dir) }
40
+ })
41
+
42
+ gem.requirements = gemspec['requirements']
43
+ gem.required_ruby_version = gemspec['required_ruby_version']
44
+ gem.required_rubygems_version = gemspec['required_rubygems_version']
45
+ gem.post_install_message = gemspec['post_install_message']
46
+
47
+ split = lambda { |string| string.split(/,\s*/) }
48
+
49
+ if gemspec['dependencies']
50
+ gemspec['dependencies'].each do |name,versions|
51
+ gem.add_dependency(name,split[versions])
52
+ end
53
+ end
54
+
55
+ if gemspec['development_dependencies']
56
+ gemspec['development_dependencies'].each do |name,versions|
57
+ gem.add_development_dependency(name,split[versions])
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,811 @@
1
+ # encoding: utf-8
2
+ require_relative '../man/version'
3
+
4
+ require 'kramdown/converter/base'
5
+
6
+ module Kramdown
7
+ module Converter
8
+ #
9
+ # Converts markdown into a roff man-page.
10
+ #
11
+ class Man < ::Kramdown::Converter::Base
12
+
13
+ # Comment header
14
+ HEADER = [
15
+ ".\\\" Generated by kramdown-man #{::Kramdown::Man::VERSION}",
16
+ ".\\\" https://github.com/postmodern/kramdown-man#readme"
17
+ ].join("\n")
18
+
19
+ # Typographic Symbols and their UTF8 chars
20
+ TYPOGRAPHIC_SYMS = {
21
+ :ndash => '\-\-',
22
+ :mdash => '\[em]',
23
+ :hellip => '\.\.\.',
24
+ :laquo => '\[Fo]',
25
+ :raquo => '\[Fc]',
26
+ :laquo_space => '\[Fo]',
27
+ :raquo_space => '\[Fc]'
28
+ }
29
+
30
+ # Smart Quotes and their UTF8 chars
31
+ SMART_QUOTES = {
32
+ :lsquo => '\[oq]',
33
+ :rsquo => '\[cq]',
34
+ :ldquo => '\[lq]',
35
+ :rdquo => '\[rq]'
36
+ }
37
+
38
+ GLYPHS = {
39
+ 'Ð' => '\[-D]',
40
+ 'ð' => '\[Sd]',
41
+ 'Þ' => '\[TP]',
42
+ 'þ' => '\[Tp]',
43
+ 'ß' => '\[ss]',
44
+ # Ligatures and Other Latin Glyphs
45
+ 'ff' => '\[ff]',
46
+ 'fi' => '\[fi]',
47
+ 'fl' => '\[fl]',
48
+ 'ffi' => '\[Fi]',
49
+ 'ffl' => '\[Fl]',
50
+ 'Ł' => '\[/L]',
51
+ 'ł' => '\[/l]',
52
+ 'Ø' => '\[/O]',
53
+ 'ø' => '\[/o]',
54
+ 'Æ' => '\[AE]',
55
+ 'æ' => '\[ae]',
56
+ 'Œ' => '\[OE]',
57
+ 'œ' => '\[oe]',
58
+ 'IJ' => '\[IJ]',
59
+ 'ij' => '\[ij]',
60
+ 'ı' => '\[.i]',
61
+ 'ȷ' => '\[.j]',
62
+ # Accented Characters
63
+ 'Á' => '\[\'A]',
64
+ 'Ć' => '\[\'C]',
65
+ 'É' => '\[\'E]',
66
+ 'Í' => '\[\'I]',
67
+ 'Ó' => '\[\'O]',
68
+ 'Ú' => '\[\'U]',
69
+ 'Ý' => '\[\'Y]',
70
+ 'á' => '\[\'a]',
71
+ 'ć' => '\[\'c]',
72
+ 'é' => '\[\'e]',
73
+ 'í' => '\[\'i]',
74
+ 'ó' => '\[\'o]',
75
+ 'ú' => '\[\'u]',
76
+ 'ý' => '\[\'y]',
77
+ 'Ä' => '\[:A]',
78
+ 'Ë' => '\[:E]',
79
+ 'Ï' => '\[:I]',
80
+ 'Ö' => '\[:O]',
81
+ 'Ü' => '\[:U]',
82
+ 'Ÿ' => '\[:Y]',
83
+ 'ä' => '\[:a]',
84
+ 'ë' => '\[:e]',
85
+ 'ï' => '\[:i]',
86
+ 'ö' => '\[:o]',
87
+ 'ü' => '\[:u]',
88
+ 'ÿ' => '\[:y]',
89
+ 'Â' => '\[^A]',
90
+ 'Ê' => '\[^E]',
91
+ 'Î' => '\[^I]',
92
+ 'Ô' => '\[^O]',
93
+ 'Û' => '\[^U]',
94
+ 'â' => '\[^a]',
95
+ 'ê' => '\[^e]',
96
+ 'î' => '\[^i]',
97
+ 'ô' => '\[^o]',
98
+ 'û' => '\[^u]',
99
+ 'À' => '\[`A]',
100
+ 'È' => '\[`E]',
101
+ 'Ì' => '\[`I]',
102
+ 'Ò' => '\[`O]',
103
+ 'Ù' => '\[`U]',
104
+ 'à' => '\[`a]',
105
+ 'è' => '\[`e]',
106
+ 'ì' => '\[`i]',
107
+ 'ò' => '\[`o]',
108
+ 'ù' => '\[`u]',
109
+ 'Ã' => '\[~A]',
110
+ 'Ñ' => '\[~N]',
111
+ 'Õ' => '\[~O]',
112
+ 'ã' => '\[~a]',
113
+ 'ñ' => '\[~n]',
114
+ 'õ' => '\[~o]',
115
+ 'Š' => '\[vS]',
116
+ 'š' => '\[vs]',
117
+ 'Ž' => '\[vZ]',
118
+ 'ž' => '\[vz]',
119
+ 'Ç' => '\[,C]',
120
+ 'ç' => '\[,c]',
121
+ 'Å' => '\[oA]',
122
+ 'å' => '\[oa]',
123
+ # Accents
124
+ '˝' => '\[a"]',
125
+ '¯' => '\[a-]',
126
+ '˙' => '\[a.]',
127
+ # '^' => '\[a^]',
128
+ '´' => "\\´",
129
+ '`' => '\`',
130
+ '˘' => '\[ab]',
131
+ '¸' => '\[ac]',
132
+ '¨' => '\[ad]',
133
+ 'ˇ' => '\[ah]',
134
+ '˚' => '\[ao]',
135
+ # '~' => '\(ti',
136
+ '˛' => '\[ho]',
137
+ '^' => '\(ha',
138
+ '~' => '\[ti]',
139
+ # Quotes
140
+ '„' => '\[Bq]',
141
+ '‚' => '\[bq]',
142
+ '“' => '\[lq]',
143
+ '”' => '\[rq]',
144
+ '‘' => '\[oq]',
145
+ '’' => '\[cq]',
146
+ "'" => '\(aq',
147
+ '"' => '\[dq]',
148
+ '«' => '\[Fo]',
149
+ '»' => '\[Fc]',
150
+ '‹' => '\[fo]',
151
+ '›' => '\[fc]',
152
+ # Punctuation
153
+ '.' => '\.',
154
+ '¡' => '\[r!]',
155
+ '¿' => '\[r?]',
156
+ '—' => '\[em]',
157
+ '–' => '\[en]',
158
+ '‐' => '\[hy]',
159
+ # Brackets
160
+ '[' => '\[lB]',
161
+ ']' => '\[rB]',
162
+ '{' => '\[lC]',
163
+ '}' => '\[rC]',
164
+ '⟨' => '\[la]',
165
+ '⟩' => '\[ra]',
166
+ # '⎪' => '\[bv]',
167
+ # '⎪' => '\[braceex]',
168
+ '⎡' => '\[bracketlefttp]',
169
+ '⎣' => '\[bracketleftbt]',
170
+ '⎢' => '\[bracketleftex]',
171
+ '⎤' => '\[bracketrighttp]',
172
+ '⎦' => '\[bracketrightbt]',
173
+ '⎥' => '\[bracketrightex]',
174
+ '╭' => '\[lt]',
175
+ '⎧' => '\[bracelefttp]',
176
+ '┥' => '\[lk]',
177
+ '⎨' => '\[braceleftmid]',
178
+ '╰' => '\[lb]',
179
+ '⎩' => '\[braceleftbt]',
180
+ # '⎪' => '\[braceleftex]',
181
+ '╮' => '\[rt]',
182
+ '⎫' => '\[bracerighttp]',
183
+ '┝' => '\[rk]',
184
+ '⎬' => '\[bracerightmid]',
185
+ '╯' => '\[rb]',
186
+ '⎭' => '\[bracerightbt]',
187
+ '⎪' => '\[bracerightex]',
188
+ '⎛' => '\[parenlefttp]',
189
+ '⎝' => '\[parenleftbt]',
190
+ '⎜' => '\[parenleftex]',
191
+ '⎞' => '\[parenrighttp]',
192
+ '⎠' => '\[parenrightbt]',
193
+ '⎟' => '\[parenrightex]',
194
+ # Arrows
195
+ '←' => '\[<-]',
196
+ '→' => '\[->]',
197
+ '↔' => '\[<>]',
198
+ '↓' => '\[da]',
199
+ '↑' => '\[ua]',
200
+ '↕' => '\[va]',
201
+ '⇐' => '\[lA]',
202
+ '⇒' => '\[rA]',
203
+ '⇔' => '\[hA]',
204
+ '⇓' => '\[dA]',
205
+ '⇑' => '\[uA]',
206
+ '⇕' => '\[vA]',
207
+ '⎯' => '\[an]',
208
+ # Lines
209
+ # '|' => '\[ba]',
210
+ '│' => '\[br]',
211
+ # '_' => '\[ul]',
212
+ '‾' => '\[rn]',
213
+ '_' => '\[ru]',
214
+ '¦' => '\[bb]',
215
+ '/' => '\[sl]',
216
+ '\\' => '\e',
217
+ # Text markers
218
+ '○' => '\[ci]',
219
+ # '·' => '\[bu]',
220
+ '‡' => '\[dd]',
221
+ '†' => '\[dg]',
222
+ '◊' => '\[lz]',
223
+ '□' => '\[sq]',
224
+ '¶' => '\[ps]',
225
+ '§' => '\[sc]',
226
+ '☜' => '\[lh]',
227
+ '☞' => '\[rh]',
228
+ '@' => '\[at]',
229
+ '#' => '\[sh]',
230
+ '↵' => '\[CR]',
231
+ '✓' => '\[OK]',
232
+ # Legal Symbols
233
+ '©' => '\[co]',
234
+ '®' => '\[rg]',
235
+ '™' => '\[tm]',
236
+ # Currency symbols
237
+ '$' => '\[Do]',
238
+ '¢' => '\[ct]',
239
+ # '€' => '\[eu]',
240
+ '€' => '\[Eu]',
241
+ '¥' => '\[Ye]',
242
+ '£' => '\[Po]',
243
+ '¤' => '\[Cs]',
244
+ 'ƒ' => '\[Fn]',
245
+ # Units
246
+ '°' => '\[de]',
247
+ '‰' => '\[%0]',
248
+ '′' => '\[fm]',
249
+ '″' => '\[sd]',
250
+ 'µ' => '\[mc]',
251
+ 'ª' => '\[Of]',
252
+ 'º' => '\[Om]',
253
+ # Logical Symbols
254
+ '∧' => '\[AN]',
255
+ '∨' => '\[OR]',
256
+ # '¬' => '\[no]',
257
+ '¬' => '\[tno]',
258
+ '∃' => '\[te]',
259
+ '∀' => '\[fa]',
260
+ '∋' => '\[st]',
261
+ # '∴' => '\[3d]',
262
+ '∴' => '\[tf]',
263
+ '|' => '\[or]',
264
+ # Mathematical Symbols
265
+ '½' => '\[12]',
266
+ '¼' => '\[14]',
267
+ '¾' => '\[34]',
268
+ '⅛' => '\[18]',
269
+ '⅜' => '\[38]',
270
+ '⅝' => '\[58]',
271
+ '⅞' => '\[78]',
272
+ '¹' => '\[S1]',
273
+ '²' => '\[S2]',
274
+ '³' => '\[S3]',
275
+ '+' => '\[pl]',
276
+ '-' => '\-',
277
+ '−' => '\[mi]',
278
+ '∓' => '\[-+]',
279
+ # '±' => '\[+-]',
280
+ '±' => '\[t+-]',
281
+ '·' => '\[pc]',
282
+ '⋅' => '\[md]',
283
+ # '×' => '\[mu]',
284
+ '×' => '\[tmu]',
285
+ '⊗' => '\[c*]',
286
+ '⊕' => '\[c+]',
287
+ # '÷' => '\[di]',
288
+ '÷' => '\[tdi]',
289
+ '⁄' => '\[f/]',
290
+ '∗' => '\[**]',
291
+ '≤' => '\[<=]',
292
+ '≥' => '\[>=]',
293
+ '≪' => '\[<<]',
294
+ '≫' => '\[>>]',
295
+ '=' => '\[eq]',
296
+ '≠' => '\[!=]',
297
+ '≡' => '\[==]',
298
+ '≢' => '\[ne]',
299
+ '≅' => '\[=~]',
300
+ '≃' => '\[|=]',
301
+ '∼' => '\[ap]',
302
+ # '≈' => '\[~~]',
303
+ '≈' => '\[~=]',
304
+ '∝' => '\[pt]',
305
+ '∅' => '\[es]',
306
+ '∈' => '\[mo]',
307
+ '∉' => '\[nm]',
308
+ '⊂' => '\[sb]',
309
+ '⊄' => '\[nb]',
310
+ '⊃' => '\[sp]',
311
+ '⊅' => '\[nc]',
312
+ '⊆' => '\[ib]',
313
+ '⊇' => '\[ip]',
314
+ '∩' => '\[ca]',
315
+ '∪' => '\[cu]',
316
+ '∠' => '\[/_]',
317
+ '⊥' => '\[pp]',
318
+ # '∫' => '\[is]',
319
+ '∫' => '\[integral]',
320
+ '∑' => '\[sum]',
321
+ '∏' => '\[product]',
322
+ '∐' => '\[coproduct]',
323
+ '∇' => '\[gr]',
324
+ # '√' => '\[sr]',
325
+ '√' => '\[sqrt]',
326
+ '⌈' => '\[lc]',
327
+ '⌉' => '\[rc]',
328
+ '⌊' => '\[lf]',
329
+ '⌋' => '\[rf]',
330
+ '∞' => '\[if]',
331
+ 'ℵ' => '\[Ah]',
332
+ 'ℑ' => '\[Im]',
333
+ 'ℜ' => '\[Re]',
334
+ '℘' => '\[wp]',
335
+ '∂' => '\[pd]',
336
+ # 'ℏ' => '\[-h]',
337
+ 'ℏ' => '\[hbar]',
338
+ # Greek glyphs
339
+ 'Α' => '\[*A]',
340
+ 'Β' => '\[*B]',
341
+ 'Γ' => '\[*G]',
342
+ 'Δ' => '\[*D]',
343
+ 'Ε' => '\[*E]',
344
+ 'Ζ' => '\[*Z]',
345
+ 'Η' => '\[*Y]',
346
+ 'Θ' => '\[*H]',
347
+ 'Ι' => '\[*I]',
348
+ 'Κ' => '\[*K]',
349
+ 'Λ' => '\[*L]',
350
+ 'Μ' => '\[*M]',
351
+ 'Ν' => '\[*N]',
352
+ 'Ξ' => '\[*C]',
353
+ 'Ο' => '\[*O]',
354
+ 'Π' => '\[*P]',
355
+ 'Ρ' => '\[*R]',
356
+ 'Σ' => '\[*S]',
357
+ 'Τ' => '\[*T]',
358
+ 'Υ' => '\[*U]',
359
+ 'Φ' => '\[*F]',
360
+ 'Χ' => '\[*X]',
361
+ 'Ψ' => '\[*Q]',
362
+ 'Ω' => '\[*W]',
363
+ 'α' => '\[*a]',
364
+ 'β' => '\[*b]',
365
+ 'γ' => '\[*g]',
366
+ 'δ' => '\[*d]',
367
+ 'ε' => '\[*e]',
368
+ 'ζ' => '\[*z]',
369
+ 'η' => '\[*y]',
370
+ 'θ' => '\[*h]',
371
+ 'ι' => '\[*i]',
372
+ 'κ' => '\[*k]',
373
+ 'λ' => '\[*l]',
374
+ 'μ' => '\[*m]',
375
+ 'ν' => '\[*n]',
376
+ 'ξ' => '\[*c]',
377
+ 'ο' => '\[*o]',
378
+ 'π' => '\[*p]',
379
+ 'ρ' => '\[*r]',
380
+ 'ς' => '\[ts]',
381
+ 'σ' => '\[*s]',
382
+ 'τ' => '\[*t]',
383
+ 'υ' => '\[*u]',
384
+ 'ϕ' => '\[*f]',
385
+ 'χ' => '\[*x]',
386
+ 'ψ' => '\[*q]',
387
+ 'ω' => '\[*w]',
388
+ 'ϑ' => '\[+h]',
389
+ 'φ' => '\[+f]',
390
+ 'ϖ' => '\[+p]',
391
+ 'ϵ' => '\[+e]',
392
+ # Card symbols
393
+ '♣' => '\[CL]',
394
+ '♠' => '\[SP]',
395
+ '♥' => '\[HE]',
396
+ '♡' => '\[u2661]',
397
+ '♦' => '\[DI]',
398
+ '♢' => '\[u2662]'
399
+ }
400
+
401
+ # Regular expression to convert unicode characters into glyphs
402
+ GLYPH_REGEXP = Regexp.union(GLYPHS.keys)
403
+
404
+ #
405
+ # Initializes the converter.
406
+ #
407
+ # @param [Kramdown::Element] root
408
+ # The root of the markdown document.
409
+ #
410
+ # @param [Hash] options
411
+ # Markdown options.
412
+ #
413
+ def initialize(root,options)
414
+ super(root,options)
415
+
416
+ @ol_index = 0
417
+ end
418
+
419
+ #
420
+ # Converts the markdown document into a man-page.
421
+ #
422
+ # @param [Kramdown::Element] root
423
+ # The root of a markdown document.
424
+ #
425
+ # @return [String]
426
+ # The roff output.
427
+ #
428
+ def convert(root)
429
+ "#{HEADER}\n#{convert_root(root)}"
430
+ end
431
+
432
+ #
433
+ # Converts the root of a markdown document.
434
+ #
435
+ # @param [Kramdown::Element] root
436
+ # The root of the markdown document.
437
+ #
438
+ # @return [String]
439
+ # The roff output.
440
+ #
441
+ def convert_root(root)
442
+ root.children.map { |child|
443
+ convert_element(child)
444
+ }.compact.join("\n")
445
+ end
446
+
447
+ #
448
+ # Converts an element.
449
+ #
450
+ # @param [Kramdown::Element] element
451
+ # An arbitrary element within the markdown document.
452
+ #
453
+ # @return [String]
454
+ # The roff output.
455
+ #
456
+ def convert_element(element)
457
+ method = "convert_#{element.type}"
458
+ send(method,element) if respond_to?(method)
459
+ end
460
+
461
+ #
462
+ # Converts a `kd:blank` element.
463
+ #
464
+ # @param [Kramdown::Element] blank
465
+ # A `kd:blank` element.
466
+ #
467
+ # @return [String]
468
+ # The roff output.
469
+ #
470
+ def convert_blank(blank)
471
+ '.LP'
472
+ end
473
+
474
+ #
475
+ # Converts a `kd:text` element.
476
+ #
477
+ # @param [Kramdown::Element] text
478
+ # A `kd:text` element.
479
+ #
480
+ # @return [String]
481
+ # The roff output.
482
+ #
483
+ def convert_text(text)
484
+ escape(text.value.gsub(/^( +|\t)/,''))
485
+ end
486
+
487
+ #
488
+ # Converts a `kd:typographic_sym` element.
489
+ #
490
+ # @param [Kramdown::Element] sym
491
+ # A `kd:typographic_sym` element.
492
+ #
493
+ # @return [String]
494
+ # The roff output.
495
+ #
496
+ def convert_typographic_sym(sym)
497
+ TYPOGRAPHIC_SYMS[sym.value]
498
+ end
499
+
500
+ #
501
+ # Converts a `kd:smart_quote` element.
502
+ #
503
+ # @param [Kramdown::Element] quote
504
+ # A `kd:smart_quote` element.
505
+ #
506
+ # @return [String]
507
+ # The roff output.
508
+ #
509
+ def convert_smart_quote(quote)
510
+ SMART_QUOTES[quote.value]
511
+ end
512
+
513
+ #
514
+ # Converts a `kd:header` element.
515
+ #
516
+ # @param [Kramdown::Element] header
517
+ # A `kd:header` element.
518
+ #
519
+ # @return [String]
520
+ # The roff output.
521
+ #
522
+ def convert_header(header)
523
+ text = header.options[:raw_text]
524
+
525
+ case header.options[:level]
526
+ when 1 then ".TH #{text}"
527
+ when 2 then ".SH #{text}"
528
+ else ".SS #{text}"
529
+ end
530
+ end
531
+
532
+ #
533
+ # Converts a `kd:hr` element.
534
+ #
535
+ # @param [Kramdown::Element] hr
536
+ # A `kd:hr` element.
537
+ #
538
+ # @return [String]
539
+ # The roff output.
540
+ #
541
+ def convert_hr(hr)
542
+ ".ti 0\n\\l'\\n(.lu'"
543
+ end
544
+
545
+ #
546
+ # Converts a `kd:ul` element.
547
+ #
548
+ # @param [Kramdown::Element] ul
549
+ # A `kd:ul` element.
550
+ #
551
+ # @return [String]
552
+ # The roff output.
553
+ #
554
+ def convert_ul(ul)
555
+ content = ul.children.map { |li| convert_ul_li(li) }.join("\n")
556
+
557
+ return ".RS\n#{content}\n.RE"
558
+ end
559
+
560
+ #
561
+ # Converts a `kd:li` element within a `kd:ul` list.
562
+ #
563
+ # @param [Kramdown::Element] li
564
+ # A `kd:li` element.
565
+ #
566
+ # @return [String]
567
+ # The roff output.
568
+ #
569
+ def convert_ul_li(li)
570
+ li.children.each_with_index.map { |child,index|
571
+ if child.type == :p
572
+ content = convert_children(child.children)
573
+
574
+ if index == 0 then ".IP \\(bu 2\n#{content}"
575
+ else ".IP \\( 2\n#{content}"
576
+ end
577
+ end
578
+ }.compact.join("\n")
579
+ end
580
+
581
+ #
582
+ # Converts a `kd:ol` element.
583
+ #
584
+ # @param [Kramdown::Element] ol
585
+ # A `kd:ol` element.
586
+ #
587
+ # @return [String]
588
+ # The roff output.
589
+ #
590
+ def convert_ol(ol)
591
+ @ol_index += 1
592
+
593
+ header = ".nr step#{@ol_index} 0 1"
594
+ content = ol.children.map { |li| convert_ol_li(li) }.join("\n")
595
+
596
+ return "#{header}\n.RS\n#{content}\n.RE"
597
+ end
598
+
599
+ #
600
+ # Converts a `kd:li` element within a `kd:ol` list.
601
+ #
602
+ # @param [Kramdown::Element] li
603
+ # A `kd:li` element.
604
+ #
605
+ # @return [String]
606
+ # The roff output.
607
+ #
608
+ def convert_ol_li(li)
609
+ li.children.each_with_index.map { |child,index|
610
+ if child.type == :p
611
+ content = convert_children(child.children)
612
+
613
+ if index == 0 then ".IP \\n+[step#{@ol_index}]\n#{content}"
614
+ else ".IP \\n\n#{content}"
615
+ end
616
+ end
617
+ }.compact.join("\n")
618
+ end
619
+
620
+ #
621
+ # Converts a `kd:abbreviation` element.
622
+ #
623
+ # @param [Kramdown::Element] abbr
624
+ # A `kd:abbreviation` element.
625
+ #
626
+ # @return [String]
627
+ # The roff output.
628
+ #
629
+ def convert_abbreviation(abbr)
630
+ escape(abbr.value)
631
+ end
632
+
633
+ #
634
+ # Converts a `kd:blockquote` element.
635
+ #
636
+ # @param [Kramdown::Element] blockquote
637
+ # A `kd:blockquote` element.
638
+ #
639
+ # @return [String]
640
+ # The roff output.
641
+ #
642
+ def convert_blockquote(blockquote)
643
+ content = blockquote.children.map { |child|
644
+ case child.type
645
+ when :p then convert_children(child.children)
646
+ else convert_element(child)
647
+ end
648
+ }.join("\n")
649
+
650
+ return ".PP\n.RS\n#{content}\n.RE"
651
+ end
652
+
653
+ #
654
+ # Converts a `kd:codeblock` element.
655
+ #
656
+ # @param [Kramdown::Element] codeblock
657
+ # A `kd:codeblock` element.
658
+ #
659
+ # @return [String]
660
+ # The roff output.
661
+ #
662
+ def convert_codeblock(codeblock)
663
+ ".nf\n#{escape(codeblock.value).rstrip}\n.fi"
664
+ end
665
+
666
+ #
667
+ # Converts a `kd:comment` element.
668
+ #
669
+ # @param [Kramdown::Element] comment
670
+ # A `kd:comment` element.
671
+ #
672
+ # @return [String]
673
+ # The roff output.
674
+ #
675
+ def convert_comment(comment)
676
+ comment.value.lines.map { |line|
677
+ ".\\\" #{line}"
678
+ }.join("\n")
679
+ end
680
+
681
+ #
682
+ # Converts a `kd:p` element.
683
+ #
684
+ # @param [Kramdown::Element] p
685
+ # A `kd:p` element.
686
+ #
687
+ # @return [String]
688
+ # The roff output.
689
+ #
690
+ def convert_p(p)
691
+ children = p.children
692
+
693
+ if ((children.length >= 2) && (children.first.type == :codespan ||
694
+ children.first.type == :em ||
695
+ children.first.type == :strong))
696
+ newline = children.find_index { |el|
697
+ el.type == :text && el.value.start_with?("\n")
698
+ }
699
+
700
+ if newline
701
+ first_line = convert_children(children[0...newline])
702
+ rest = convert_children(children[newline..-1]).strip
703
+
704
+ ".TP\n#{first_line}\n#{rest}"
705
+ else
706
+ ".HP\n#{convert_children(children)}"
707
+ end
708
+ else
709
+ ".PP\n#{convert_children(children)}"
710
+ end
711
+ end
712
+
713
+ #
714
+ # Converts a `kd:em` element.
715
+ #
716
+ # @param [Kramdown::Element] em
717
+ # A `kd:em` element.
718
+ #
719
+ # @return [String]
720
+ # The roff output.
721
+ #
722
+ def convert_em(em)
723
+ "\\fI#{convert_children(em.children)}\\fP"
724
+ end
725
+
726
+ #
727
+ # Converts a `kd:strong` element.
728
+ #
729
+ # @param [Kramdown::Element] strong
730
+ # A `kd:strong` element.
731
+ #
732
+ # @return [String]
733
+ # The roff output.
734
+ #
735
+ def convert_strong(strong)
736
+ "\\fB#{convert_children(strong.children)}\\fP"
737
+ end
738
+
739
+ #
740
+ # Converts a `kd:codespan` element.
741
+ #
742
+ # @param [Kramdown::Element] codespan
743
+ # A `kd:codespan` element.
744
+ #
745
+ # @return [String]
746
+ # The roff output.
747
+ #
748
+ def convert_codespan(codespan)
749
+ "\\fB#{codespan.value}\\fR"
750
+ end
751
+
752
+ #
753
+ # Converts a `kd:a` element.
754
+ #
755
+ # @param [Kramdown::Element] a
756
+ # A `kd:a` element.
757
+ #
758
+ # @return [String]
759
+ # The roff output.
760
+ #
761
+ def convert_a(a)
762
+ href = escape(a.attr['href'])
763
+ text = convert_children(a.children)
764
+
765
+ case href
766
+ when /^mailto:/
767
+ email = href[7..-1]
768
+
769
+ unless text == email then "#{text}\n.MT #{email}\n.ME"
770
+ else "\n.MT #{email}\n.ME"
771
+ end
772
+ when /^man:/
773
+ match = href.match(/man:([A-Za-z0-9_-]+)(?:\((\d[a-z]?)\))?/)
774
+
775
+ if match[2] then "\n.BR #{match[1]} (#{match[2]})"
776
+ else "\n.BR #{match[1]}"
777
+ end
778
+ else
779
+ "#{text}\n.UR #{href}\n.UE"
780
+ end
781
+ end
782
+
783
+ #
784
+ # Converts the children of an element.
785
+ #
786
+ # @param [Array<Kramdown::Element>] children
787
+ # The children of an element.
788
+ #
789
+ # @return [String]
790
+ # The roff output.
791
+ #
792
+ def convert_children(children)
793
+ children.map { |child| convert_element(child) }.join.strip
794
+ end
795
+
796
+ #
797
+ # Escapes text for roff.
798
+ #
799
+ # @param [String] text
800
+ # The unescaped text.
801
+ #
802
+ # @return [String]
803
+ # The escaped text.
804
+ #
805
+ def escape(text)
806
+ text.gsub(GLYPH_REGEXP) { |char| GLYPHS[char] }
807
+ end
808
+
809
+ end
810
+ end
811
+ end