kramdown-asciidoc 1.0.0.alpha.10 → 1.0.0.alpha.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +19 -0
  3. data/README.adoc +4 -1
  4. data/lib/kramdown-asciidoc/api.rb +27 -0
  5. data/lib/kramdown-asciidoc/cli.rb +14 -22
  6. data/lib/kramdown-asciidoc/converter.rb +62 -33
  7. data/lib/kramdown-asciidoc/kramdown_ext/parser/html.rb +9 -0
  8. data/lib/kramdown-asciidoc/version.rb +1 -1
  9. data/lib/kramdown-asciidoc/writer.rb +3 -3
  10. data/lib/kramdown-asciidoc.rb +3 -9
  11. data/spec/api_spec.rb +63 -0
  12. data/spec/cli_spec.rb +1 -2
  13. data/spec/converter_spec.rb +5 -5
  14. data/spec/scenario_spec.rb +1 -1
  15. data/spec/scenarios/blockquote/attribution-separated.md +1 -0
  16. data/spec/scenarios/blockquote/{with-attribution.adoc → attribution.adoc} +0 -0
  17. data/spec/scenarios/blockquote/{with-attribution.md → attribution.md} +0 -0
  18. data/spec/scenarios/codeblock/{fenced/with-command-prompt.adoc → command-prompt.adoc} +0 -0
  19. data/spec/scenarios/codeblock/{with-command-prompt.md → command-prompt.md} +0 -0
  20. data/spec/scenarios/codeblock/{with-command-prompt.adoc → fenced/command-prompt.adoc} +0 -0
  21. data/spec/scenarios/codeblock/fenced/{with-command-prompt.md → command-prompt.md} +0 -0
  22. data/spec/scenarios/codeblock/fenced/{with-language.adoc → language.adoc} +0 -0
  23. data/spec/scenarios/codeblock/fenced/{with-language.md → language.md} +0 -0
  24. data/spec/scenarios/codeblock/fenced/{with-non-contiguous-command-prompts.adoc → non-contiguous-command-prompts.adoc} +0 -0
  25. data/spec/scenarios/codeblock/fenced/{with-non-contiguous-command-prompts.md → non-contiguous-command-prompts.md} +0 -0
  26. data/spec/scenarios/codeblock/{with-non-contiguous-command-prompts.adoc → non-contiguous-command-prompts.adoc} +0 -0
  27. data/spec/scenarios/codeblock/{with-non-contiguous-command-prompts.md → non-contiguous-command-prompts.md} +0 -0
  28. data/spec/scenarios/codespan/caret.adoc +1 -0
  29. data/spec/scenarios/codespan/caret.md +1 -0
  30. data/spec/scenarios/codespan/possessive.adoc +3 -0
  31. data/spec/scenarios/codespan/possessive.md +3 -0
  32. data/spec/scenarios/codespan/quoted.adoc +1 -0
  33. data/spec/scenarios/codespan/quoted.md +1 -0
  34. data/spec/scenarios/codespan/smart-quotes.adoc +1 -0
  35. data/spec/scenarios/codespan/smart-quotes.md +1 -0
  36. data/spec/scenarios/codespan/unconstrained.adoc +1 -0
  37. data/spec/scenarios/codespan/unconstrained.md +1 -0
  38. data/spec/scenarios/heading/auto-id-prefix.adoc +11 -0
  39. data/spec/scenarios/heading/auto-id-prefix.md +7 -0
  40. data/spec/scenarios/heading/auto-id-prefix.opts +2 -0
  41. data/spec/scenarios/heading/auto-ids.adoc +1 -1
  42. data/spec/scenarios/heading/auto-ids.md +1 -1
  43. data/spec/scenarios/heading/{with-formatting.adoc → formatting.adoc} +0 -0
  44. data/spec/scenarios/heading/{with-formatting.md → formatting.md} +0 -0
  45. data/spec/scenarios/heading/{with-anchor.adoc → leading-anchor.adoc} +0 -0
  46. data/spec/scenarios/heading/leading-anchor.md +1 -0
  47. data/spec/scenarios/heading/surrounding-anchor.adoc +2 -0
  48. data/spec/scenarios/heading/{with-anchor.md → surrounding-anchor.md} +0 -0
  49. data/spec/scenarios/html_element/div-mixed.adoc +1 -0
  50. data/spec/scenarios/html_element/div-mixed.md +4 -0
  51. data/spec/scenarios/html_element/div-text-only.adoc +1 -0
  52. data/spec/scenarios/html_element/div-text-only.md +1 -0
  53. data/spec/scenarios/html_element/mark.adoc +1 -0
  54. data/spec/scenarios/html_element/mark.md +1 -0
  55. data/spec/scenarios/html_element/span.adoc +3 -0
  56. data/spec/scenarios/html_element/span.md +3 -0
  57. data/spec/scenarios/html_element/unrecognized-admonition.adoc +5 -0
  58. data/spec/scenarios/html_element/unrecognized-admonition.md +5 -0
  59. data/spec/scenarios/p/admonition/label-only.adoc +1 -0
  60. data/spec/scenarios/p/admonition/label-only.md +1 -0
  61. data/spec/scenarios/table/{with-header.adoc → header.adoc} +0 -0
  62. data/spec/scenarios/table/{with-header.md → header.md} +0 -0
  63. data/spec/scenarios/table/{without-header.adoc → no-header.adoc} +0 -0
  64. data/spec/scenarios/table/{without-header.md → no-header.md} +0 -0
  65. data/spec/scenarios/wrap/ventilate-with-comments.adoc +5 -0
  66. data/spec/scenarios/wrap/ventilate-with-comments.md +5 -0
  67. data/spec/scenarios/wrap/ventilate-with-comments.opts +1 -0
  68. data/spec/scenarios/xml_comment/above-block.adoc +7 -0
  69. data/spec/scenarios/xml_comment/above-block.md +5 -0
  70. data/spec/scenarios/xml_comment/line-empty.adoc +7 -0
  71. data/spec/scenarios/xml_comment/line-empty.md +9 -0
  72. data/spec/scenarios/xml_comment/multiline-span.adoc +4 -0
  73. data/spec/scenarios/xml_comment/multiline-span.md +4 -0
  74. data/spec/scenarios/xml_comment/p-separator.adoc +5 -0
  75. data/spec/scenarios/xml_comment/p-separator.md +5 -0
  76. data/spec/scenarios/xml_comment/surrounded-by-spaces.adoc +3 -0
  77. data/spec/scenarios/xml_comment/surrounded-by-spaces.md +1 -0
  78. data/spec/spec_helper.rb +1 -0
  79. metadata +118 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c9eaf28d5d26d6a4fe664121fa5d19507c9144644711cca82e348330428a1b2
4
- data.tar.gz: d4a0b308bb683012ccc1ed75a54aeeb8f6ceefcf6fbabd54ce4728b34f728895
3
+ metadata.gz: a8a8579b7930fcfba55c49f569adfffcf2f0d4f98d324e5a928493dca246e78e
4
+ data.tar.gz: dca656316d4e76d2ea0169b9568ab5f54cab4a8add284f6ca24c0ff141e4918f
5
5
  SHA512:
6
- metadata.gz: c2b4579e6829ae8b230ac72d9fb5f8e9880c4c40ad037784f695e916cfbd4b83353e44a8b507bd4c92baa1b3805d389420dc12944be0f283c3a30969e5444b50
7
- data.tar.gz: 8a73cc65511611f3f5aa541818314bd938e5b0be9aa0f8585e3f2883065fafee1c1d96018c5a552ca6936f73ffa6ec36d67b68e7a9316a305d1ac7f6bba62ab5
6
+ metadata.gz: c77f10db21bbace2285b3ad00b04cdf4a45306d681739d36395a35d89b78fb5b512eb678afc9a07c965d219cddf7895a314b76e9a97d45971102b25bc976556b
7
+ data.tar.gz: c4938413fa37f131723e5d08ff44a0cc42c61c0586227a2f984a1c82818d34de62de8d08cf755aef6acf5719728e6de12d6162b5965e7eea2d939de0e78b7c97
data/CHANGELOG.adoc CHANGED
@@ -5,6 +5,25 @@
5
5
  This document provides a high-level view of the changes to {project-name} by release.
6
6
  For a detailed view of what has changed, refer to the {uri-repo}/commits/master[commit history] on GitHub.
7
7
 
8
+ == 1.0.0.alpha.11 (2018-08-02) - @mojavelinux
9
+
10
+ === Added
11
+
12
+ * add a public API (Kramdoc.convert and Kramdoc.convert_file) for converting input strings and paths, respectively (#31)
13
+ * update CLI to use public API (#31)
14
+ * run test suite on Windows using AppVeyor (#32)
15
+ * don't crash when empty comment occurs under primary text of list item
16
+ * convert phrase enclosed in <span> (#36)
17
+ * convert phrase enclosed in <mark>
18
+ * convert a bare <div> to a paragraph
19
+ * remove leading space from text if at beginning of line
20
+
21
+ === Changed
22
+
23
+ * add code role to codespan if enclosed in quotes (required for AsciiDoc to parse properly) (#29)
24
+ * use unconstrained codespan if bounded on either side by a smart quote
25
+ * ignore auto-generated ID if heading has an explicit inline anchor
26
+
8
27
  == 1.0.0.alpha.10 (2018-07-16) - @mojavelinux
9
28
 
10
29
  === Added
data/README.adoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = {project-name} (Markdown to AsciiDoc)
2
2
  Dan Allen <https://github.com/mojavelinux>
3
- v1.0.0.alpha.10, 2018-07-16
3
+ v1.0.0.alpha.11, 2018-08-02
4
4
  // Aliases:
5
5
  :project-name: Kramdown AsciiDoc
6
6
  :project-handle: kramdown-asciidoc
@@ -25,6 +25,8 @@ endif::[]
25
25
  :uri-kramdown: https://kramdown.gettalong.org
26
26
  :uri-rvm: https://rvm.io
27
27
  :uri-rvm-install: https://rvm.io/rvm/install
28
+ :uri-ci-appveyor: https://ci.appveyor.com/project/asciidoctor/kramdown-asciidoc
29
+ :img-ci-appveyor: https://ci.appveyor.com/api/projects/status/2pwvdbcoeux1ifb5/branch/master?svg=true
28
30
  :uri-ci-travis: https://travis-ci.org/asciidoctor/kramdown-asciidoc
29
31
  :uri-ci-travis-img: https://img.shields.io/travis/asciidoctor/kramdown-asciidoc/master.svg
30
32
  :uri-gem: https://rubygems.org/gems/kramdown-asciidoc
@@ -33,6 +35,7 @@ endif::[]
33
35
  ifdef::status[]
34
36
  image:{uri-gem-img}[Gem Version,link={uri-gem}]
35
37
  image:{uri-ci-travis-img}[Build Status (Travis CI),link={uri-ci-travis}]
38
+ image:{img-ci-appveyor}[Build Status (AppVeyor),link={uri-ci-appveyor}]
36
39
  endif::[]
37
40
 
38
41
  {uri-repo}[{project-name}] (gem: *{project-handle}*) is a {uri-kramdown}[kramdown] extension for converting Markdown documents to {uri-asciidoc}[AsciiDoc].
@@ -0,0 +1,27 @@
1
+ module Kramdown; module AsciiDoc
2
+ LF = ?\n
3
+
4
+ def self.convert markdown, opts = {}
5
+ markdown = markdown.rstrip
6
+ markdown = markdown.slice 1, markdown.length while markdown.start_with? LF
7
+ attributes = (opts[:attributes] ||= {})
8
+ markdown = ::Kramdown::AsciiDoc.extract_front_matter markdown, attributes
9
+ markdown = ::Kramdown::AsciiDoc.replace_toc markdown, attributes
10
+ asciidoc = (::Kramdown::Document.new markdown, (::Kramdown::AsciiDoc::DEFAULT_PARSER_OPTS.merge opts)).to_asciidoc
11
+ asciidoc += LF unless asciidoc.empty?
12
+ if (to = opts[:to])
13
+ (to.respond_to? :write) ? (to.write asciidoc) : (::IO.write to, asciidoc)
14
+ nil
15
+ else
16
+ asciidoc
17
+ end
18
+ end
19
+
20
+ def self.convert_file markdown_file, opts = {}
21
+ markdown = ::IO.read markdown_file, mode: 'r:UTF-8', newline: :universal
22
+ (output_file = (::Pathname.new markdown_file).sub_ext '.adoc').dirname.mkpath
23
+ convert markdown, (opts.merge to: output_file)
24
+ end
25
+ end; end
26
+
27
+ Kramdoc = Kramdown::AsciiDoc
@@ -62,12 +62,12 @@ module Kramdown; module AsciiDoc
62
62
  end
63
63
 
64
64
  opts.on '-h', '--help', 'Display this help text and exit' do
65
- $stdout.puts opts.help
65
+ $stdout.write opts.help
66
66
  return 0
67
67
  end
68
68
 
69
69
  opts.on '-v', '--version', %(Display version information and exit) do
70
- $stdout.puts %(#{opts.program_name} #{VERSION})
70
+ $stdout.write %(#{opts.program_name} #{VERSION}\n)
71
71
  return 0
72
72
  end
73
73
  end
@@ -76,7 +76,7 @@ module Kramdown; module AsciiDoc
76
76
 
77
77
  if args.empty?
78
78
  opt_parser.warn 'Please specify a Markdown file to convert.'
79
- $stdout.puts opt_parser.help
79
+ $stdout.write opt_parser.help
80
80
  return 1
81
81
  end
82
82
 
@@ -85,12 +85,12 @@ module Kramdown; module AsciiDoc
85
85
  [0, options]
86
86
  else
87
87
  opt_parser.warn %(extra arguments detected (unparsed arguments: #{(args.drop 1).join ' '}))
88
- $stdout.puts opt_parser.help
88
+ $stdout.write opt_parser.help
89
89
  [1, options]
90
90
  end
91
91
  rescue ::OptionParser::InvalidOption
92
- $stderr.puts %(#{opt_parser.program_name}: #{$!.message})
93
- $stdout.puts opt_parser.help
92
+ $stderr.write %(#{opt_parser.program_name}: #{$!.message}\n)
93
+ $stdout.write opt_parser.help
94
94
  return 1
95
95
  end
96
96
 
@@ -99,33 +99,25 @@ module Kramdown; module AsciiDoc
99
99
  return code unless code == 0 && options
100
100
  if (input_file = options.delete :input_file) == '-'
101
101
  pipe_in = true
102
- markdown = $stdin.read.rstrip
102
+ markdown = $stdin.read
103
103
  else
104
- markdown = (::IO.read input_file, mode: 'r:UTF-8', newline: :universal).rstrip
104
+ markdown = ::IO.read input_file, mode: 'r:UTF-8', newline: :universal
105
105
  end
106
106
  if (output_file = options.delete :output_file)
107
107
  if output_file == '-'
108
108
  pipe_out = true
109
109
  else
110
- (::Pathname.new output_file).dirname.mkpath
110
+ (output_file = ::Pathname.new output_file).dirname.mkpath
111
111
  end
112
112
  else
113
- output_file = ((::Pathname.new input_file).sub_ext '.adoc').to_s
113
+ output_file = (::Pathname.new input_file).sub_ext '.adoc'
114
114
  end
115
- if !(pipe_in || pipe_out) && (::File.absolute_path input_file) == (::File.absolute_path output_file)
116
- $stderr.puts %(kramdoc: input and output file cannot be the same: #{input_file})
115
+ if !pipe_in && !pipe_out && (::File.expand_path input_file) == output_file.expand_path.to_s
116
+ $stderr.write %(kramdoc: input and output file cannot be the same: #{input_file}\n)
117
117
  return 1
118
118
  end
119
- markdown = markdown.slice 1, markdown.length while markdown.start_with? ?\n
120
- attributes = options[:attributes]
121
- markdown = ::Kramdown::AsciiDoc.extract_front_matter markdown, attributes
122
- markdown = ::Kramdown::AsciiDoc.replace_toc markdown, attributes
123
- doc = ::Kramdown::Document.new markdown, (::Kramdown::AsciiDoc::DEFAULT_PARSER_OPTS.merge options)
124
- if pipe_out
125
- $stdout.puts doc.to_asciidoc
126
- else
127
- ::IO.write output_file, doc.to_asciidoc
128
- end
119
+ # QUESTION should we set :from option?
120
+ ::Kramdoc.convert markdown, (options.merge to: (pipe_out ? $stdout : output_file))
129
121
  0
130
122
  end
131
123
  end
@@ -142,12 +142,13 @@ module Kramdown; module AsciiDoc
142
142
  end
143
143
  style << 'discrete'
144
144
  end
145
- if (id = el.attr['id'])
146
- style << %(##{id})
147
- elsif (child_i = el.children[0] || VoidElement).type == :html_element && child_i.value == 'a' && (id = child_i.attr['id'])
145
+ if (child_i = to_element el.children[0]).type == :html_element && child_i.value == 'a' && (id = child_i.attr['id'])
148
146
  el = clone el, children: child_i.children + (el.children.drop 1)
149
147
  style << %(##{id})
150
- elsif (role = el.attr['class'])
148
+ elsif (id = el.attr['id'])
149
+ style << %(##{id})
150
+ end
151
+ if (role = el.attr['class'])
151
152
  style << %(.#{role.tr ' ', '.'})
152
153
  end
153
154
  lines = []
@@ -184,7 +185,7 @@ module Kramdown; module AsciiDoc
184
185
  # NOTE detect formatted admonition marker (e.g., *Note:* ...)
185
186
  elsif (child_i.type == :strong || child_i.type == :em) &&
186
187
  (marker_el = child_i.children[0]) && ((marker = ADMON_FORMATTED_MARKERS[marker_el.value]) ||
187
- ((marker = ADMON_LABELS[marker_el.value]) && (child_ii = children[1] || VoidElement).type == :text &&
188
+ ((marker = ADMON_LABELS[marker_el.value]) && (child_ii = to_element children[1]).type == :text &&
188
189
  ((child_ii_text = child_ii.value).start_with? ': ')))
189
190
  children = children.drop 1
190
191
  children[0] = clone child_ii, value: (child_ii_text.slice 1, child_ii_text.length) if child_ii
@@ -209,7 +210,8 @@ module Kramdown; module AsciiDoc
209
210
  if contents.size > 1 && (contents[-1].start_with? '-- ')
210
211
  attribution = (attribution_line = contents.pop).slice 3, attribution_line.length
211
212
  writer.add_line %([,#{attribution}])
212
- contents.pop while contents.size > 0 && contents[-1].empty?
213
+ # NOTE there will be at least one non-blank line, but coerce .to_s just to be safe
214
+ contents.pop while contents[-1].to_s.empty?
213
215
  end
214
216
  # Q: should writer handle delimited block nesting?
215
217
  delimiter = depth > 0 ? ('____' + '__' * depth) : '_'
@@ -250,7 +252,7 @@ module Kramdown; module AsciiDoc
250
252
  end
251
253
 
252
254
  def convert_img el, opts
253
- if !(parent = opts[:parent]) || parent.type == :p && parent.children.size == 1
255
+ if (parent = opts[:parent]).type == :p && parent.children.size == 1
254
256
  style = []
255
257
  if (id = el.attr['id'])
256
258
  style << %(##{id})
@@ -318,8 +320,9 @@ module Kramdown; module AsciiDoc
318
320
  primary_lines.unshift %(#{indent > 0 ? ' ' * indent : ''}#{marker * level} #{primary_lines.shift})
319
321
  writer.add_lines primary_lines
320
322
  unless remaining.empty?
321
- next_node = remaining.find {|n| n.type != :blank }
322
- el.options[:compound] = true if next_node && (BLOCK_TYPES.include? next_node.type)
323
+ if remaining.find {|n| (type = n.type) == :blank ? nil : ((BLOCK_TYPES.include? type) ? true : break) }
324
+ el.options[:compound] = true
325
+ end
323
326
  traverse remaining, (opts.merge parent: el)
324
327
  end
325
328
  end
@@ -348,8 +351,9 @@ module Kramdown; module AsciiDoc
348
351
  end
349
352
  end
350
353
  unless remaining.empty?
351
- next_node = remaining.find {|n| n.type != :blank }
352
- el.options[:compound] = true if next_node && (BLOCK_TYPES.include? next_node.type)
354
+ if remaining.find {|n| (type = n.type) == :blank ? nil : ((BLOCK_TYPES.include? type) ? true : break) }
355
+ el.options[:compound] = true
356
+ end
353
357
  traverse remaining, (opts.merge parent: el)
354
358
  end
355
359
  end
@@ -425,7 +429,21 @@ module Kramdown; module AsciiDoc
425
429
  end
426
430
 
427
431
  def convert_codespan el, opts
428
- mark = (unconstrained? opts[:prev], opts[:next], :codespan) ? '``' : '`'
432
+ attrlist, mark = '', '`'
433
+ if unconstrained? (prev_el = opts[:prev]), (next_el = opts[:next])
434
+ mark = '``'
435
+ elsif next_el
436
+ case next_el.type
437
+ when :smart_quote
438
+ if prev_el && prev_el.type == :smart_quote
439
+ attrlist, mark = '[.code]', '``'
440
+ else
441
+ mark = '``'
442
+ end
443
+ when :text
444
+ mark = '``' if (next_el.value.chr == ?') || (prev_el && prev_el.type == :smart_quote)
445
+ end
446
+ end
429
447
  text = el.value
430
448
  pass = (replaceable? text) ? :shorthand : nil
431
449
  pass = :macro if text.include? '++'
@@ -434,13 +452,13 @@ module Kramdown; module AsciiDoc
434
452
  elsif pass == :macro
435
453
  opts[:writer].append %(#{mark}pass:c[#{text}]#{mark})
436
454
  else
437
- opts[:writer].append %(#{mark}#{text}#{mark})
455
+ opts[:writer].append %(#{attrlist}#{mark}#{text}#{mark})
438
456
  end
439
457
  end
440
458
 
441
459
  def convert_em el, opts
442
460
  composed_text = compose_text el
443
- mark = (unconstrained? opts[:prev], opts[:next], :em) ? '__' : '_'
461
+ mark = (unconstrained? opts[:prev], opts[:next]) ? '__' : '_'
444
462
  opts[:writer].append %(#{mark}#{composed_text}#{mark})
445
463
  end
446
464
 
@@ -449,25 +467,21 @@ module Kramdown; module AsciiDoc
449
467
  @attributes['experimental'] = ''
450
468
  opts[:writer].append %(menu:#{$1}[#{$2}])
451
469
  else
452
- mark = (unconstrained? opts[:prev], opts[:next], :strong) ? '**' : '*'
470
+ mark = (unconstrained? opts[:prev], opts[:next]) ? '**' : '*'
453
471
  opts[:writer].append %(#{mark}#{composed_text}#{mark})
454
472
  end
455
473
  end
456
474
 
457
- def unconstrained? prev_el, next_el, enclosure
458
- (next_char_word? next_el, enclosure) || (prev_char_wordish? prev_el)
475
+ def unconstrained? prev_el, next_el
476
+ (next_char_word? next_el) || (prev_char_wordish? prev_el)
459
477
  end
460
478
 
461
479
  def prev_char_wordish? prev_el
462
480
  prev_el && (prev_el.type == :entity || (prev_el.type == :text && (WordishRx.match? prev_el.value[-1])))
463
481
  end
464
482
 
465
- def next_char_word? next_el, enclosure
466
- if next_el.type == :text
467
- (WordRx.match? (next_ch = next_el.value.chr)) || (enclosure == :codespan && next_ch == ?')
468
- elsif enclosure == :codespan && next_el.type == :smart_quote
469
- true
470
- end if next_el
483
+ def next_char_word? next_el
484
+ next_el && next_el.type == :text && (WordRx.match? next_el.value.chr)
471
485
  end
472
486
 
473
487
  def convert_text el, opts
@@ -476,7 +490,11 @@ module Kramdown; module AsciiDoc
476
490
  @attributes['pp'] = '{plus}{plus}'
477
491
  text = text.gsub '++', '{pp}'
478
492
  end
479
- opts[:writer].append text
493
+ if (current_line = (writer = opts[:writer]).current_line).to_s.empty?
494
+ writer.append text.lstrip
495
+ else
496
+ writer.append text
497
+ end
480
498
  end
481
499
 
482
500
  def replaceable? text
@@ -503,7 +521,7 @@ module Kramdown; module AsciiDoc
503
521
  writer.append %(#{(writer.current_line.end_with? ' ') ? '' : ' '}+)
504
522
  end
505
523
  if el.options[:html_tag]
506
- writer.add_blank_line unless (next_el = opts[:next] || VoidElement).type == :text && (next_el.value.start_with? LF)
524
+ writer.add_blank_line unless (next_el = to_element opts[:next]).type == :text && (next_el.value.start_with? LF)
507
525
  end
508
526
  end
509
527
 
@@ -522,29 +540,36 @@ module Kramdown; module AsciiDoc
522
540
 
523
541
  def convert_html_element el, opts
524
542
  if (tag = el.value) == 'div' && (child_i = el.children[0]) && child_i.options[:transparent] && (child_i_i = child_i.children[0])
525
- if child_i_i.type == :img
526
- convert_img child_i_i, (opts.merge parent: child_i, index: 0) if child_i.children.size == 1
527
- return
528
- elsif child_i_i.value == 'span' && ((role = el.attr['class'] || '').start_with? 'note') && child_i_i.attr['class'] == 'notetitle'
529
- marker = ADMON_FORMATTED_MARKERS[(child_i_i.children[0] || VoidElement).value] || 'Note'
543
+ if child_i_i.value == 'span' && ((role = el.attr['class'].to_s).start_with? 'note') && child_i_i.attr['class'] == 'notetitle'
544
+ marker = ADMON_FORMATTED_MARKERS[(to_element child_i_i.children[0]).value] || 'Note'
530
545
  lines = compose_text (child_i.children.drop 1), parent: child_i, strip: true, split: true, wrap: @wrap
531
546
  lines.unshift %(#{ADMON_TYPE_MAP[marker]}: #{lines.shift})
532
547
  opts[:writer].start_block
533
548
  opts[:writer].add_lines lines
534
549
  return
550
+ else
551
+ return convert_p child_i, (opts.merge parent: el, index: 0)
535
552
  end
536
553
  end
537
554
 
538
555
  contents = compose_text el, (opts.merge strip: el.options[:category] == :block)
539
- attrs = (attrs = el.attr).empty? ? '' : attrs.map {|k, v| %( #{k}="#{v}") }.join
540
556
  case tag
541
557
  when 'del'
542
558
  opts[:writer].append %([.line-through]##{contents}#)
559
+ when 'mark'
560
+ opts[:writer].append %(##{contents}#)
561
+ when 'span'
562
+ if (role = el.attr['class'])
563
+ opts[:writer].append %([.#{role.tr ' ', '.'}]##{contents}#)
564
+ else
565
+ opts[:writer].append contents
566
+ end
543
567
  when 'sup'
544
568
  opts[:writer].append %(^#{contents}^)
545
569
  when 'sub'
546
570
  opts[:writer].append %(~#{contents}~)
547
571
  else
572
+ attrs = (attrs = el.attr).empty? ? '' : attrs.map {|k, v| %( #{k}="#{v}") }.join
548
573
  opts[:writer].append %(+++<#{tag}#{attrs}>+++#{contents}+++</#{tag}>+++)
549
574
  end
550
575
  end
@@ -566,7 +591,7 @@ module Kramdown; module AsciiDoc
566
591
  else
567
592
  writer.add_line %(// #{lines[0]})
568
593
  end
569
- else
594
+ elsif !lines.empty?
570
595
  if (current_line = writer.current_line) && !(current_line.end_with? LF)
571
596
  start_new_line = true
572
597
  writer.replace_line current_line.rstrip if current_line.end_with? ' '
@@ -583,7 +608,7 @@ module Kramdown; module AsciiDoc
583
608
  end
584
609
 
585
610
  def extract_prologue el, opts
586
- if (child_i = (children = el.children)[0] || VoidElement).type == :xml_comment
611
+ if (child_i = to_element (children = el.children)[0]).type == :xml_comment
587
612
  (prologue_el = el.dup).children = children.take_while {|child| child.type == :xml_comment || child.type == :blank }
588
613
  (el = el.dup).children = children.drop prologue_el.children.size
589
614
  traverse prologue_el, (opts.merge writer: (prologue_writer = Writer.new))
@@ -600,6 +625,10 @@ module Kramdown; module AsciiDoc
600
625
  el
601
626
  end
602
627
 
628
+ def to_element el
629
+ el || VoidElement
630
+ end
631
+
603
632
  def traverse el, opts
604
633
  if ::Array === el
605
634
  nodes = el
@@ -0,0 +1,9 @@
1
+ class Kramdown::Parser::Html::ElementConverter
2
+ # Overload convert_br to add the :html_tag option to indicate this br element originates from an HTML tag
3
+ def convert_br el
4
+ el.options.replace location: el.options[:location], html_tag: true
5
+ el.type = el.value.to_sym
6
+ el.value = nil
7
+ nil
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Kramdown; module AsciiDoc
2
- VERSION = '1.0.0.alpha.10'
2
+ VERSION = '1.0.0.alpha.11'
3
3
  end; end
@@ -60,7 +60,7 @@ module Kramdown; module AsciiDoc
60
60
  end
61
61
 
62
62
  # Q: perhaps do_in_list that takes a block?
63
- def start_list compound, kin = :list
63
+ def start_list compound, kin
64
64
  # Q: can this be further optimized?
65
65
  @body << '' if in_list? ? compound : !empty?
66
66
  @block_separator << '+'
@@ -68,7 +68,7 @@ module Kramdown; module AsciiDoc
68
68
  nil
69
69
  end
70
70
 
71
- def end_list kin = :list
71
+ def end_list kin
72
72
  @block_separator.pop
73
73
  @list_level[kin] -= 1
74
74
  nil
@@ -125,7 +125,7 @@ module Kramdown; module AsciiDoc
125
125
  end
126
126
 
127
127
  def to_s
128
- ((@header.empty? ? @body : (@header + (@body.empty? ? [] : ['']) + @body)).join LF) + LF
128
+ (@header.empty? ? @body : (@header + (@body.empty? ? [] : [''] + @body))).join LF
129
129
  end
130
130
  end
131
131
  end; end
@@ -1,14 +1,8 @@
1
1
  require 'kramdown'
2
+ require_relative 'kramdown-asciidoc/kramdown_ext/parser/html'
2
3
  require_relative 'kramdown-asciidoc/core_ext/regexp/is_match'
4
+ require_relative 'kramdown-asciidoc/api'
3
5
  require_relative 'kramdown-asciidoc/converter'
4
6
  require_relative 'kramdown-asciidoc/writer'
7
+ autoload :Pathname, 'pathname'
5
8
  autoload :YAML, 'yaml'
6
-
7
- class Kramdown::Parser::Html::ElementConverter
8
- def convert_br el
9
- el.options.replace location: el.options[:location], html_tag: true
10
- el.type = el.value.to_sym
11
- el.value = nil
12
- nil
13
- end
14
- end
data/spec/api_spec.rb ADDED
@@ -0,0 +1,63 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Kramdown::AsciiDoc do
4
+ context '#convert' do
5
+ it 'converts Markdown to AsciiDoc' do
6
+ input = <<~EOS
7
+ ---
8
+ title: Document Title
9
+ ---
10
+
11
+ Body content.
12
+ EOS
13
+
14
+ expected = <<~EOS
15
+ = Document Title
16
+
17
+ Body content.
18
+ EOS
19
+
20
+ (expect subject.convert input).to eql expected
21
+ end
22
+
23
+ it 'writes AsciiDoc to filename specified in :to option' do
24
+ the_output_file = output_file 'convert-api.adoc'
25
+ (expect subject.convert 'Converted using the API', to: the_output_file).to be_nil
26
+ (expect (IO.read the_output_file)).to eql %(Converted using the API\n)
27
+ end
28
+
29
+ it 'writes AsciiDoc to IO object specified in :to option' do
30
+ old_stdout, $stdout = $stdout, StringIO.new
31
+ begin
32
+ (expect subject.convert 'text', to: $stdout).to be_nil
33
+ (expect $stdout.string).to eql %(text\n)
34
+ ensure
35
+ $stdout = old_stdout
36
+ end
37
+ end
38
+
39
+ it 'adds line feed (EOL) to end of output document if non-empty' do
40
+ (expect subject.convert 'paragraph').to end_with ?\n
41
+ end
42
+
43
+ it 'does not add line feed (EOL) to end of output document if empty' do
44
+ (expect subject.convert '').to be_empty
45
+ end
46
+ end
47
+
48
+ context '#convert_file' do
49
+ it 'converts Markdown file to AsciiDoc file' do
50
+ the_source_file = output_file 'convert-file-api.md'
51
+ the_output_file = output_file 'convert-file-api.adoc'
52
+ IO.write the_source_file, 'Converted using the API'
53
+ (expect subject.convert_file the_source_file).to be_nil
54
+ (expect (IO.read the_output_file)).to eql %(Converted using the API\n)
55
+ end
56
+ end
57
+ end
58
+
59
+ describe Kramdoc do
60
+ it 'supports Kramdoc as an alias for Kramdown::AsciiDoc' do
61
+ (expect Kramdoc).to eql Kramdown::AsciiDoc
62
+ end
63
+ end
data/spec/cli_spec.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require_relative 'spec_helper'
2
2
  require 'kramdown-asciidoc/cli'
3
- require 'stringio'
4
3
 
5
4
  describe Kramdown::AsciiDoc::Cli do
6
5
  subject { Kramdown::AsciiDoc::Cli }
@@ -211,7 +210,7 @@ describe Kramdown::AsciiDoc::Cli do
211
210
  [#_heading-2]
212
211
  == Heading 2
213
212
 
214
- [#_heading-3]
213
+ [#explicit-id]
215
214
  === Heading 3
216
215
 
217
216
  [#_back-to-heading-2]
@@ -9,9 +9,9 @@ describe Kramdown::AsciiDoc::Converter do
9
9
  context '#convert' do
10
10
  let (:input) { %(# Document Title\n\nBody text.) }
11
11
 
12
- it 'adds line feed (EOL) to end of output document' do
13
- (expect converter.convert root).to end_with %(\n)
14
- (expect doc.to_asciidoc).to end_with %(\n)
12
+ it 'does not add line feed (EOL) to end of output document' do
13
+ (expect converter.convert root).not_to end_with ?\n
14
+ (expect doc.to_asciidoc).not_to end_with ?\n
15
15
  end
16
16
 
17
17
  # Q: can we find a scenario that covers this?
@@ -154,7 +154,7 @@ describe Kramdown::AsciiDoc::Converter do
154
154
  When using this technology, anything is possible.
155
155
  EOS
156
156
 
157
- expected = <<~EOS
157
+ expected = <<~EOS.chomp
158
158
  = Introduction
159
159
  :description: An introduction to this amazing technology.
160
160
 
@@ -177,7 +177,7 @@ describe Kramdown::AsciiDoc::Converter do
177
177
  When using this technology, anything is possible.
178
178
  EOS
179
179
 
180
- expected = <<~EOS
180
+ expected = <<~EOS.chomp
181
181
  = Introduction
182
182
  :description: An introduction to this amazing technology.
183
183
 
@@ -15,7 +15,7 @@ describe 'scenario' do
15
15
  context %(for #{scenario_name}) do
16
16
  let(:input) { IO.read input_filename, mode: 'r:UTF-8', newline: :universal }
17
17
  let(:extra_options) { options }
18
- let(:expected) { IO.read output_filename, mode: 'r:UTF-8', newline: :universal }
18
+ let(:expected) { (IO.read output_filename, mode: 'r:UTF-8', newline: :universal).chomp }
19
19
  it 'converts Markdown to AsciiDoc' do
20
20
  (expect doc.to_asciidoc).to eql expected
21
21
  end
@@ -1,4 +1,5 @@
1
1
  > Not everything that is faced can be changed.
2
2
  > But nothing can be changed until it is faced.
3
3
  >
4
+ >
4
5
  > -- James Baldwin
@@ -0,0 +1 @@
1
+ `^` is often used for superscript
@@ -0,0 +1 @@
1
+ `^` is often used for superscript
@@ -0,0 +1,3 @@
1
+ ``lerna``'s link command
2
+
3
+ ``yarn``'s workspace command
@@ -0,0 +1,3 @@
1
+ `lerna`'s link command
2
+
3
+ `yarn`\'s workspace command
@@ -0,0 +1 @@
1
+ use "[.code]``short``" as the attribute value
@@ -0,0 +1 @@
1
+ use "`short`" as the attribute value
@@ -0,0 +1 @@
1
+ assign the value "[.code]``short``" to the attribute
@@ -0,0 +1 @@
1
+ assign the value "`short`" to the attribute