kramdown-ansi 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7249444853b46b626b782ea417e62827627ba0d1da6f54cc8801f8459839f775
4
+ data.tar.gz: 75884f2bf3c0e3b06e71c28f9f4775315745b76ab9cf0d73ec57e49829cd7f6f
5
+ SHA512:
6
+ metadata.gz: 10c992685654c67686a24e4a323ab04619d8957faa61a119569e16dbdb82119278b2756b3cf8d3ba921f7343997d12ddb6632fc8fc3379b00be844862e730d4a
7
+ data.tar.gz: d3342cdf38698f5f59035b0a06dff0341a3fc66127d4de3fd7de46d25d55831175a087f6375fb2052f5e10ff1aabb026026361ab3e73f9a87329b19f3be2d05d
data/CHANGES.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changes
2
+
3
+ ## 2024-10-31 v0.0.0
4
+
5
+ * Start
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright Florian Frank
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the “Software”), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Kramdown ANSI - Output markdown with ANSI
2
+
3
+ ## Description
4
+
5
+ Kramdown::ANSI: A library for rendering Markdown(ish) documents with beautiful
6
+ ANSI escape sequences in the terminal.
7
+
8
+ ## Installation (gem & bundler)
9
+
10
+ To install Kramdown::ANSI, you can use the following methods:
11
+
12
+ 1. Type
13
+
14
+ ```shell
15
+ gem install kramdown-ansi
16
+ ```
17
+
18
+ in your terminal.
19
+
20
+ 1. Or add the line
21
+
22
+ ```ruby
23
+ gem 'kramdown-ansi'
24
+ ```
25
+
26
+ to your Gemfile and run `bundle install` in your terminal.
27
+
28
+ ## Usage
29
+
30
+ In your own software the library can be used as shown in this example:
31
+
32
+ ```ruby
33
+ require 'kramdown/ansi'
34
+
35
+ puts Kramdown::ANSI.parse(markdown)
36
+ ```
37
+
38
+ ## Executables
39
+
40
+ | Method | Description |
41
+ | :----- | :---------- |
42
+ | `md` executable | Outputs Markdown files with ANSI escape sequences in the terminal |
43
+ | `git-md` executable | A Git plugin that outputs Markdown formatted git commit messages into the terminal |
44
+
45
+ ### The md executable
46
+
47
+ The `md` executable can by used with file arguments:
48
+
49
+ ```shell
50
+ md Foo.md Bar.md …
51
+ ```
52
+
53
+ or as a unix filter:
54
+
55
+ ```shell
56
+ cat Foo.md Bar.md | md
57
+ ```
58
+
59
+ It outputs the markdown files with ANSI escape sequences in the terminal. If
60
+ the file has more lines than the current terminal window has, it attempts to
61
+ open a pager command like `less` or `more` and pipes its output into it.
62
+ By setting the `PAGER` environment variable accordingly one can define a custom
63
+ command for this purpose.
64
+
65
+ ### The git-md executable
66
+
67
+ The `git-md` executable is a git plugin that can be used to output markdown
68
+ formatted git commit messages (just like `git log`) into the terminal using
69
+
70
+ ```shell
71
+ git md
72
+ ```
73
+
74
+ You can pass arguments to it like you would of `git log`, e.g.
75
+
76
+ ```shell
77
+ git md -p
78
+ ```
79
+
80
+ to show the patches additionally to the log messages.
81
+
82
+ By setting the `GIT_PAGER` or `PAGER` environment variable accordingly one can
83
+ define a custom command for this purpose as well, unless a different
84
+ pager command was defined setting `git config set core.pager FOO`, in which
85
+ case the FOO command is used as a pager for all git commands including `git
86
+ md`.
87
+
88
+ ## Download
89
+
90
+ The homepage of this library is located at
91
+
92
+ * https://github.com/flori/kramdown-ansi
93
+
94
+ ## Author
95
+
96
+ <b>Kramdown ANSI</b> was written by Florian Frank [Florian Frank](mailto:flori@ping.de)
97
+
98
+ ## License
99
+
100
+ This software is licensed under the <i>MIT</i> license.
101
+
102
+ ## Mandatory Kitten Image
103
+
104
+ ![cat](spec/assets/kitten.jpg)
105
+
106
+ ---
107
+
108
+ This is the end.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ require 'gem_hadar'
4
+
5
+ GemHadar do
6
+ name 'kramdown-ansi'
7
+ path_name 'kramdown'
8
+ module_type :module
9
+ author 'Florian Frank'
10
+ email 'flori@ping.de'
11
+ homepage "https://github.com/flori/#{name}"
12
+ summary 'Output markdown in the terminal with ANSI escape sequences'
13
+ description <<~EOT
14
+ Kramdown::ANSI: A library for rendering Markdown(ish) documents with
15
+ beautiful ANSI escape sequences in the terminal.
16
+ EOT
17
+ test_dir 'spec'
18
+ ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.AppleDouble', '.bundle',
19
+ '.yardoc', 'doc', 'tags', 'errors.lst', 'cscope.out', 'coverage', 'tmp',
20
+ 'yard'
21
+ package_ignore '.all_images.yml', '.tool-versions', '.gitignore', 'VERSION',
22
+ '.rspec', *Dir.glob('.github/**/*', File::FNM_DOTMATCH)
23
+ readme 'README.md'
24
+
25
+ executables << 'md' << 'git-md'
26
+
27
+ required_ruby_version '~> 3.1'
28
+
29
+ dependency 'term-ansicolor', '~> 1.11'
30
+ dependency 'kramdown-parser-gfm', '~> 1.1'
31
+ dependency 'terminal-table', '~> 3.0'
32
+ development_dependency 'all_images', '~> 0.4'
33
+ development_dependency 'rspec', '~> 3.2'
34
+ development_dependency 'debug'
35
+ development_dependency 'simplecov'
36
+
37
+ licenses << 'MIT'
38
+
39
+ clobber 'coverage'
40
+ end
data/bin/git-md ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'kramdown/ansi'
4
+ include Term::ANSIColor
5
+ require 'shellwords'
6
+
7
+ cmd = %{git log --color=always --pretty=format:"commit %H%C(auto)%d%nDate: %Cgreen%cD (%cr)%Creset%nAuthor: %Cblue%an <%ae>%Creset%n%nMARKUP%n%s%n%n%b%nMARKDOWN%n"}
8
+
9
+ core_pager = `git config get core.pager`.chomp.full?
10
+ git_pager = ENV['GIT_PAGER'].full?
11
+ default_pager = ENV['PAGER'].full?
12
+ if fallback_pager = `which less`.chomp.full? || `which more`.chomp.full?
13
+ fallback_pager << ' -r'
14
+ end
15
+ my_pager = git_pager || core_pager || default_pager || fallback_pager
16
+
17
+ repo_url = case git_origin_url = `git remote get-url origin`.chomp
18
+ when %r(\Ahttps://)
19
+ u = git_origin_url.sub(%r(\.git\z), '')
20
+ u << '/commit/'
21
+ when %r(\Agit@github.com:([^.]+))
22
+ "https://github.com/#$1/commit/"
23
+ end
24
+
25
+ Kramdown::ANSI::Pager.pager(command: my_pager) do |output|
26
+ IO.popen("#{cmd} #{Shellwords.join(ARGV)}") do |log|
27
+ until log.eof?
28
+ message = nil
29
+ log.each do |line|
30
+ case line
31
+ when /^MARKUP$/
32
+ message = ''
33
+ when /^MARKDOWN$/
34
+ output.puts Kramdown::ANSI.parse(message + "\n---\n")
35
+ message = nil
36
+ else
37
+ if message
38
+ message << line
39
+ else
40
+ output.puts line.sub(/(?<=^commit )(\h{40})/) {
41
+ yellow { repo_url ? hyperlink(repo_url + $1) { $1 } : $1 }
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
data/bin/md ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'kramdown/ansi'
4
+
5
+ rendered = Kramdown::ANSI.parse(ARGF.read)
6
+ default_pager = ENV['PAGER'].full?
7
+ if fallback_pager = `which less`.chomp.full? || `which more`.chomp.full?
8
+ fallback_pager << ' -r'
9
+ end
10
+ my_pager = default_pager || fallback_pager
11
+
12
+ Kramdown::ANSI::Pager.pager(lines: rendered.count(?\n), command: my_pager) do |output|
13
+ output.puts rendered
14
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # stub: kramdown-ansi 0.0.0 ruby lib
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "kramdown-ansi".freeze
6
+ s.version = "0.0.0".freeze
7
+
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
+ s.require_paths = ["lib".freeze]
10
+ s.authors = ["Florian Frank".freeze]
11
+ s.date = "2024-10-31"
12
+ s.description = "Kramdown::ANSI: A library for rendering Markdown(ish) documents with\nbeautiful ANSI escape sequences in the terminal.\n".freeze
13
+ s.email = "flori@ping.de".freeze
14
+ s.executables = ["md".freeze, "git-md".freeze]
15
+ s.extra_rdoc_files = ["README.md".freeze, "lib/kramdown/ansi.rb".freeze, "lib/kramdown/ansi/pager.rb".freeze, "lib/kramdown/ansi/width.rb".freeze, "lib/kramdown/version.rb".freeze]
16
+ s.files = ["CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/git-md".freeze, "bin/md".freeze, "kramdown-ansi.gemspec".freeze, "lib/kramdown/ansi.rb".freeze, "lib/kramdown/ansi/pager.rb".freeze, "lib/kramdown/ansi/width.rb".freeze, "lib/kramdown/version.rb".freeze, "spec/assets/README.ansi".freeze, "spec/assets/kitten.jpg".freeze, "spec/kramdown/ansi/pager_spec.rb".freeze, "spec/kramdown/ansi/width_spec.rb".freeze, "spec/kramdown/ansi_spec.rb".freeze, "spec/spec_helper.rb".freeze]
17
+ s.homepage = "https://github.com/flori/kramdown-ansi".freeze
18
+ s.licenses = ["MIT".freeze]
19
+ s.rdoc_options = ["--title".freeze, "Kramdown-ansi - Output markdown in the terminal with ANSI escape sequences".freeze, "--main".freeze, "README.md".freeze]
20
+ s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
21
+ s.rubygems_version = "3.5.22".freeze
22
+ s.summary = "Output markdown in the terminal with ANSI escape sequences".freeze
23
+ s.test_files = ["spec/kramdown/ansi/pager_spec.rb".freeze, "spec/kramdown/ansi/width_spec.rb".freeze, "spec/kramdown/ansi_spec.rb".freeze, "spec/spec_helper.rb".freeze]
24
+
25
+ s.specification_version = 4
26
+
27
+ s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.19".freeze])
28
+ s.add_development_dependency(%q<all_images>.freeze, ["~> 0.4".freeze])
29
+ s.add_development_dependency(%q<rspec>.freeze, ["~> 3.2".freeze])
30
+ s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
31
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
32
+ s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
33
+ s.add_runtime_dependency(%q<kramdown-parser-gfm>.freeze, ["~> 1.1".freeze])
34
+ s.add_runtime_dependency(%q<terminal-table>.freeze, ["~> 3.0".freeze])
35
+ end
@@ -0,0 +1,37 @@
1
+ require 'tins/terminal'
2
+
3
+ module Kramdown::ANSI::Pager
4
+ module_function
5
+
6
+ # If called without a block returns either the provided command for paging if
7
+ # the given number of lines are exceeding the available number of terminal
8
+ # lines or nil. If a block was provided it yields to an IO handle for the
9
+ # pager command in the latter case or STDOUT in the former.
10
+ #
11
+ # @param command [String] the pager command (optional)
12
+ # @param lines [Integer] the number of lines in the output (optional)
13
+ # @yield [IO] yields the output IO handle for further processing
14
+ # @return [NilClass] returns nil if STDOUT is used or STDOUT is not a TTY.
15
+ def pager(command: nil, lines: nil, &block)
16
+ if block
17
+ if my_pager = pager(command:, lines:)
18
+ IO.popen(my_pager, 'w') do |output|
19
+ output.sync = true
20
+ yield output
21
+ output.close
22
+ end
23
+ else
24
+ yield STDOUT
25
+ end
26
+ else
27
+ return unless STDOUT.tty?
28
+ if lines
29
+ if lines >= Tins::Terminal.lines
30
+ pager(command:)
31
+ end
32
+ else
33
+ command
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,61 @@
1
+ require 'tins/terminal'
2
+ require 'term/ansicolor'
3
+
4
+ module Kramdown::ANSI::Width
5
+ include Term::ANSIColor
6
+ extend Term::ANSIColor
7
+
8
+ module_function
9
+
10
+ # Returns the width of the terminal in characters, given a percentage.
11
+ #
12
+ # @param percentage [Numeric] the percentage value (defaults to 100.0)
13
+ # @return [Integer] the calculated width
14
+ def width(percentage: 100.0)
15
+ ((Float(percentage) * Tins::Terminal.columns) / 100).floor
16
+ end
17
+
18
+ # Wraps text to a specified width.
19
+ #
20
+ # @param text [String] the text to wrap
21
+ # @option percentage [Numeric] the percentage value for the width (defaults to nil)
22
+ # @option length [Integer] the character length for the width (defaults to nil)
23
+ # @return [String] the wrapped text
24
+ # @raise [ArgumentError] if neither `percentage` nor `length` is provided
25
+ def wrap(text, percentage: nil, length: nil)
26
+ percentage.nil? ^ length.nil? or
27
+ raise ArgumentError, "either pass percentage or length argument"
28
+ percentage and length ||= width(percentage:)
29
+ text.gsub(/(?<!\n)\n(?!\n)/, ' ').lines.map do |line|
30
+ if length >= 1 && uncolor { line }.length > length
31
+ line.gsub(/(.{1,#{length}})(\s+|$)/, "\\1\n").strip
32
+ else
33
+ line.strip
34
+ end
35
+ end * ?\n
36
+ end
37
+
38
+ # Truncates a given string to a specified length or percentage. If the text
39
+ # is longer an ellipsis sequence is added at the end of the generated string,
40
+ # to indicate that a truncation has been performed.
41
+ #
42
+ # @param text [String] the input string to truncate
43
+ # @option percentage [Numeric] the percentage value for the width (defaults to nil)
44
+ # @option length [Integer] the character length for the width (defaults to nil)
45
+ # @option ellipsis [Character] the truncation indicator (defaults to ?…)
46
+ # @return [String] the truncated string
47
+ # @raise [ArgumentError] if neither `percentage` nor `length` is provided
48
+ def truncate(text, percentage: nil, length: nil, ellipsis: ?…)
49
+ percentage.nil? ^ length.nil? or
50
+ raise ArgumentError, "either pass percentage or length argument"
51
+ percentage and length ||= width(percentage:)
52
+ ellipsis_length = ellipsis.size
53
+ if length < ellipsis_length
54
+ +''
55
+ elsif text.size >= length + ellipsis_length
56
+ text[0, length - ellipsis_length] + ellipsis
57
+ else
58
+ text
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,224 @@
1
+ require 'kramdown'
2
+ require 'kramdown-parser-gfm'
3
+ require 'terminal-table'
4
+ require 'term/ansicolor'
5
+ module Kramdown
6
+ class Kramdown::ANSI < Kramdown::Converter::Base
7
+ end
8
+ end
9
+ require 'kramdown/ansi/width'
10
+ require 'kramdown/ansi/pager'
11
+
12
+ class Kramdown::ANSI < Kramdown::Converter::Base
13
+ include Term::ANSIColor
14
+ include Kramdown::ANSI::Width
15
+
16
+ class ::Kramdown::Parser::Mygfm < ::Kramdown::Parser::GFM
17
+ def initialize(source, options)
18
+ options[:gfm_quirks] << :no_auto_typographic
19
+ super
20
+ @block_parsers -= %i[
21
+ definition_list block_html block_math
22
+ footnote_definition abbrev_definition
23
+ ]
24
+ @span_parsers -= %i[ footnote_marker inline_math ]
25
+ end
26
+ end
27
+
28
+ def self.parse(source)
29
+ @doc = Kramdown::Document.new(
30
+ source, input: :mygfm, auto_ids: false, entity_output: :as_char
31
+ ).to_ansi
32
+ end
33
+
34
+ def initialize(root, options)
35
+ super
36
+ end
37
+
38
+ def convert(el, opts = {})
39
+ send("convert_#{el.type}", el, opts)
40
+ end
41
+
42
+ def inner(el, opts, &block)
43
+ result = +''
44
+ options = opts.dup.merge(parent: el)
45
+ el.children.each_with_index do |inner_el, index|
46
+ options[:index] = index
47
+ options[:result] = result
48
+ begin
49
+ content = send("convert_#{inner_el.type}", inner_el, options)
50
+ result << (block&.(inner_el, index, content) || content)
51
+ rescue NameError => e
52
+ warning "Caught #{e.class} for #{inner_el.type}"
53
+ end
54
+ end
55
+ result
56
+ end
57
+
58
+ def convert_root(el, opts)
59
+ inner(el, opts)
60
+ end
61
+
62
+ def convert_blank(_el, opts)
63
+ opts[:result] =~ /\n\n\Z|\A\Z/ ? "" : "\n"
64
+ end
65
+
66
+ def convert_text(el, _opts)
67
+ el.value
68
+ end
69
+
70
+ def convert_header(el, opts)
71
+ newline bold { underline { inner(el, opts) } }
72
+ end
73
+
74
+ def convert_p(el, opts)
75
+ length = width(percentage: 90) - opts[:list_indent].to_i
76
+ length < 0 and return ''
77
+ newline wrap(inner(el, opts), length:)
78
+ end
79
+
80
+ def convert_strong(el, opts)
81
+ bold { inner(el, opts) }
82
+ end
83
+
84
+ def convert_em(el, opts)
85
+ italic { inner(el, opts) }
86
+ end
87
+
88
+ def convert_a(el, opts)
89
+ url = el.attr['href']
90
+ hyperlink(url) { inner(el, opts) }
91
+ end
92
+
93
+ def convert_codespan(el, _opts)
94
+ blue { el.value }
95
+ end
96
+
97
+ def convert_codeblock(el, _opts)
98
+ blue { el.value }
99
+ end
100
+
101
+ def convert_blockquote(el, opts)
102
+ newline ?“ + inner(el, opts).sub(/\n+\z/, '') + ?”
103
+ end
104
+
105
+ def convert_hr(_el, _opts)
106
+ newline ?─ * width(percentage: 100)
107
+ end
108
+
109
+ def convert_img(el, _opts)
110
+ url = el.attr['src']
111
+ alt = el.attr['alt']
112
+ alt.strip.size == 0 and alt = url
113
+ alt = '🖼 ' + alt
114
+ hyperlink(url) { alt }
115
+ end
116
+
117
+ def convert_ul(el, opts)
118
+ list_indent = opts[:list_indent].to_i
119
+ inner(el, opts) { |_inner_el, index, content|
120
+ result = '· %s' % content
121
+ result = newline(result, count: index <= el.children.size - 1 ? 1 : 2)
122
+ result.gsub(/^/, ' ' * list_indent)
123
+ }
124
+ end
125
+
126
+ def convert_ol(el, opts)
127
+ list_indent = opts[:list_indent].to_i
128
+ inner(el, opts) { |_inner_el, index, content|
129
+ result = '%u. %s' % [ index + 1, content ]
130
+ result = newline(result, count: index <= el.children.size - 1 ? 1 : 2)
131
+ result.gsub(/^/, ' ' * list_indent)
132
+ }
133
+ end
134
+
135
+ def convert_li(el, opts)
136
+ opts = opts.dup
137
+ opts[:list_indent] = 2 + opts[:list_indent].to_i
138
+ newline inner(el, opts).sub(/\n+\Z/, '')
139
+ end
140
+
141
+ def convert_html_element(el, opts)
142
+ if el.value == 'i' || el.value == 'em'
143
+ italic { inner(el, opts) }
144
+ elsif el.value == 'b' || el.value == 'strong'
145
+ bold { inner(el, opts) }
146
+ else
147
+ ''
148
+ end
149
+ end
150
+
151
+ def convert_table(el, opts)
152
+ table = Terminal::Table.new
153
+ table.style = {
154
+ all_separators: true,
155
+ border: :unicode_round,
156
+ }
157
+ opts[:table] = table
158
+ inner(el, opts)
159
+ el.options[:alignment].each_with_index do |a, i|
160
+ a == :default and next
161
+ opts[:table].align_column(i, a)
162
+ end
163
+ newline table.to_s
164
+ end
165
+
166
+ def convert_thead(el, opts)
167
+ rows = inner(el, opts)
168
+ rows = rows.split(/\s*\|\s*/)[1..].map(&:strip)
169
+ opts[:table].headings = rows
170
+ ''
171
+ end
172
+
173
+ def convert_tbody(el, opts)
174
+ res = +''
175
+ res << inner(el, opts)
176
+ end
177
+
178
+ def convert_tfoot(el, opts)
179
+ ''
180
+ end
181
+
182
+ def convert_tr(el, opts)
183
+ return '' if el.children.empty?
184
+ full_width = width(percentage: 90)
185
+ cols = el.children.map { |c| convert(c, opts).strip }
186
+ row_size = cols.sum(&:size)
187
+ return '' if row_size.zero?
188
+ opts[:table] << cols.map { |c|
189
+ length = (full_width * (c.size / row_size.to_f)).floor
190
+ wrap(c, length:)
191
+ }
192
+ ''
193
+ end
194
+
195
+ def convert_td(el, opts)
196
+ inner(el, opts)
197
+ end
198
+
199
+ def convert_entity(el, _opts)
200
+ el.value.char
201
+ end
202
+
203
+ def convert_xml_comment(*)
204
+ ''
205
+ end
206
+
207
+ def convert_xml_pi(*)
208
+ ''
209
+ end
210
+
211
+ def convert_br(_el, opts)
212
+ ''
213
+ end
214
+
215
+ def convert_smart_quote(el, _opts)
216
+ el.value.to_s =~ /[rl]dquo/ ? "\"" : "'"
217
+ end
218
+
219
+ def newline(text, count: 1)
220
+ text.gsub(/\n*\z/, ?\n * count)
221
+ end
222
+ end
223
+
224
+ Kramdown::Converter.const_set(:Ansi, Kramdown::ANSI)
@@ -0,0 +1,8 @@
1
+ module Kramdown
2
+ # Kramdown version
3
+ VERSION = '0.0.0'
4
+ VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
8
+ end