kramdown-asciidoc 1.0.0.alpha.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.
Files changed (221) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.adoc +10 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE.adoc +22 -0
  5. data/README.adoc +147 -0
  6. data/Rakefile +3 -0
  7. data/bin/kramdoc +24 -0
  8. data/kramdown-asciidoc.gemspec +41 -0
  9. data/lib/kramdown-asciidoc.rb +2 -0
  10. data/lib/kramdown-asciidoc/converter.rb +413 -0
  11. data/lib/kramdown-asciidoc/version.rb +3 -0
  12. data/spec/converter_spec.rb +114 -0
  13. data/spec/fixtures/a/bare-url.adoc +1 -0
  14. data/spec/fixtures/a/bare-url.md +1 -0
  15. data/spec/fixtures/a/interdoc-xref.adoc +1 -0
  16. data/spec/fixtures/a/interdoc-xref.md +1 -0
  17. data/spec/fixtures/a/internal.adoc +5 -0
  18. data/spec/fixtures/a/internal.md +5 -0
  19. data/spec/fixtures/a/local.adoc +1 -0
  20. data/spec/fixtures/a/local.md +1 -0
  21. data/spec/fixtures/a/url-matches-text.adoc +1 -0
  22. data/spec/fixtures/a/url-matches-text.md +1 -0
  23. data/spec/fixtures/a/url-with-text.adoc +1 -0
  24. data/spec/fixtures/a/url-with-text.md +1 -0
  25. data/spec/fixtures/blockquote/basic.adoc +3 -0
  26. data/spec/fixtures/blockquote/basic.md +1 -0
  27. data/spec/fixtures/blockquote/list.adoc +5 -0
  28. data/spec/fixtures/blockquote/list.md +3 -0
  29. data/spec/fixtures/blockquote/multiple-lines.adoc +5 -0
  30. data/spec/fixtures/blockquote/multiple-lines.md +3 -0
  31. data/spec/fixtures/blockquote/nested.adoc +7 -0
  32. data/spec/fixtures/blockquote/nested.md +3 -0
  33. data/spec/fixtures/blockquote/with-attribution.adoc +5 -0
  34. data/spec/fixtures/blockquote/with-attribution.md +3 -0
  35. data/spec/fixtures/br/tag-followed-by-newline.adoc +3 -0
  36. data/spec/fixtures/br/tag-followed-by-newline.md +3 -0
  37. data/spec/fixtures/br/tag-preceded-by-space.adoc +3 -0
  38. data/spec/fixtures/br/tag-preceded-by-space.md +1 -0
  39. data/spec/fixtures/br/tag.adoc +3 -0
  40. data/spec/fixtures/br/tag.md +1 -0
  41. data/spec/fixtures/br/trailing-double-space.adoc +3 -0
  42. data/spec/fixtures/br/trailing-double-space.md +3 -0
  43. data/spec/fixtures/codeblock/contiguous-lines.adoc +5 -0
  44. data/spec/fixtures/codeblock/contiguous-lines.md +3 -0
  45. data/spec/fixtures/codeblock/fenced/bash-to-console.adoc +4 -0
  46. data/spec/fixtures/codeblock/fenced/bash-to-console.md +3 -0
  47. data/spec/fixtures/codeblock/fenced/with-command-prompt.adoc +1 -0
  48. data/spec/fixtures/codeblock/fenced/with-command-prompt.md +3 -0
  49. data/spec/fixtures/codeblock/fenced/with-language.adoc +8 -0
  50. data/spec/fixtures/codeblock/fenced/with-language.md +7 -0
  51. data/spec/fixtures/codeblock/fenced/with-non-contiguous-command-prompts.adoc +5 -0
  52. data/spec/fixtures/codeblock/fenced/with-non-contiguous-command-prompts.md +5 -0
  53. data/spec/fixtures/codeblock/fenced/without-language.adoc +5 -0
  54. data/spec/fixtures/codeblock/fenced/without-language.md +5 -0
  55. data/spec/fixtures/codeblock/non-contiguous-lines.adoc +7 -0
  56. data/spec/fixtures/codeblock/non-contiguous-lines.md +5 -0
  57. data/spec/fixtures/codeblock/with-command-prompt.adoc +1 -0
  58. data/spec/fixtures/codeblock/with-command-prompt.md +1 -0
  59. data/spec/fixtures/codeblock/with-non-contiguous-command-prompts.adoc +5 -0
  60. data/spec/fixtures/codeblock/with-non-contiguous-command-prompts.md +3 -0
  61. data/spec/fixtures/codespan/constrained.adoc +1 -0
  62. data/spec/fixtures/codespan/constrained.md +1 -0
  63. data/spec/fixtures/codespan/literal.adoc +3 -0
  64. data/spec/fixtures/codespan/literal.md +3 -0
  65. data/spec/fixtures/em/asterisks.adoc +1 -0
  66. data/spec/fixtures/em/asterisks.md +1 -0
  67. data/spec/fixtures/em/constrained.adoc +1 -0
  68. data/spec/fixtures/em/constrained.md +1 -0
  69. data/spec/fixtures/entity/numeric.adoc +1 -0
  70. data/spec/fixtures/entity/numeric.md +1 -0
  71. data/spec/fixtures/entity/reverse.adoc +1 -0
  72. data/spec/fixtures/entity/reverse.md +1 -0
  73. data/spec/fixtures/heading/out-of-sequence.adoc +23 -0
  74. data/spec/fixtures/heading/out-of-sequence.md +21 -0
  75. data/spec/fixtures/heading/outline.adoc +13 -0
  76. data/spec/fixtures/heading/outline.md +13 -0
  77. data/spec/fixtures/heading/with-anchor.adoc +2 -0
  78. data/spec/fixtures/heading/with-anchor.md +1 -0
  79. data/spec/fixtures/heading/with-formatting.adoc +1 -0
  80. data/spec/fixtures/heading/with-formatting.md +1 -0
  81. data/spec/fixtures/hr/between-blocks.adoc +5 -0
  82. data/spec/fixtures/hr/between-blocks.md +5 -0
  83. data/spec/fixtures/hr/dashes.adoc +1 -0
  84. data/spec/fixtures/hr/dashes.md +1 -0
  85. data/spec/fixtures/html_element/abbr.adoc +1 -0
  86. data/spec/fixtures/html_element/abbr.md +1 -0
  87. data/spec/fixtures/html_element/heading-with-class.adoc +7 -0
  88. data/spec/fixtures/html_element/heading-with-class.md +5 -0
  89. data/spec/fixtures/html_element/heading-with-id.adoc +2 -0
  90. data/spec/fixtures/html_element/heading-with-id.md +1 -0
  91. data/spec/fixtures/html_element/native.adoc +1 -0
  92. data/spec/fixtures/html_element/native.md +1 -0
  93. data/spec/fixtures/html_element/sub.adoc +1 -0
  94. data/spec/fixtures/html_element/sub.md +1 -0
  95. data/spec/fixtures/html_element/sup.adoc +1 -0
  96. data/spec/fixtures/html_element/sup.md +1 -0
  97. data/spec/fixtures/img/block-with-alt.adoc +1 -0
  98. data/spec/fixtures/img/block-with-alt.md +1 -0
  99. data/spec/fixtures/img/block-with-link-and-alt.adoc +1 -0
  100. data/spec/fixtures/img/block-with-link-and-alt.md +1 -0
  101. data/spec/fixtures/img/block-with-link.adoc +1 -0
  102. data/spec/fixtures/img/block-with-link.md +1 -0
  103. data/spec/fixtures/img/block.adoc +1 -0
  104. data/spec/fixtures/img/block.md +1 -0
  105. data/spec/fixtures/img/imagesdir.adoc +4 -0
  106. data/spec/fixtures/img/imagesdir.md +3 -0
  107. data/spec/fixtures/img/imagesdir.opts +2 -0
  108. data/spec/fixtures/img/implicit-imagesdir.adoc +3 -0
  109. data/spec/fixtures/img/implicit-imagesdir.md +3 -0
  110. data/spec/fixtures/img/implicit-imagesdir.opts +2 -0
  111. data/spec/fixtures/img/inline-with-alt.adoc +1 -0
  112. data/spec/fixtures/img/inline-with-alt.md +1 -0
  113. data/spec/fixtures/img/inline-with-link-and-alt.adoc +1 -0
  114. data/spec/fixtures/img/inline-with-link-and-alt.md +1 -0
  115. data/spec/fixtures/img/inline-with-link.adoc +1 -0
  116. data/spec/fixtures/img/inline-with-link.md +1 -0
  117. data/spec/fixtures/img/inline.adoc +1 -0
  118. data/spec/fixtures/img/inline.md +1 -0
  119. data/spec/fixtures/ol/compound-separated.adoc +25 -0
  120. data/spec/fixtures/ol/compound-separated.md +23 -0
  121. data/spec/fixtures/ol/compound.adoc +25 -0
  122. data/spec/fixtures/ol/compound.md +18 -0
  123. data/spec/fixtures/ol/mixed-separated.adoc +6 -0
  124. data/spec/fixtures/ol/mixed-separated.md +11 -0
  125. data/spec/fixtures/ol/mixed.adoc +6 -0
  126. data/spec/fixtures/ol/mixed.md +6 -0
  127. data/spec/fixtures/ol/nested-separated.adoc +7 -0
  128. data/spec/fixtures/ol/nested-separated.md +13 -0
  129. data/spec/fixtures/ol/nested.adoc +7 -0
  130. data/spec/fixtures/ol/nested.md +7 -0
  131. data/spec/fixtures/ol/simple-separated.adoc +4 -0
  132. data/spec/fixtures/ol/simple-separated.md +7 -0
  133. data/spec/fixtures/ol/simple.adoc +4 -0
  134. data/spec/fixtures/ol/simple.md +4 -0
  135. data/spec/fixtures/p/admonition/emphasis.adoc +11 -0
  136. data/spec/fixtures/p/admonition/emphasis.md +11 -0
  137. data/spec/fixtures/p/admonition/in-list-item.adoc +6 -0
  138. data/spec/fixtures/p/admonition/in-list-item.md +6 -0
  139. data/spec/fixtures/p/admonition/plain.adoc +11 -0
  140. data/spec/fixtures/p/admonition/plain.md +11 -0
  141. data/spec/fixtures/p/admonition/strong-emphasis.adoc +11 -0
  142. data/spec/fixtures/p/admonition/strong-emphasis.md +11 -0
  143. data/spec/fixtures/p/multiple-lines.adoc +2 -0
  144. data/spec/fixtures/p/multiple-lines.md +2 -0
  145. data/spec/fixtures/p/multiple.adoc +3 -0
  146. data/spec/fixtures/p/multiple.md +3 -0
  147. data/spec/fixtures/p/single-line.adoc +1 -0
  148. data/spec/fixtures/p/single-line.md +1 -0
  149. data/spec/fixtures/root/body-only.adoc +1 -0
  150. data/spec/fixtures/root/body-only.md +1 -0
  151. data/spec/fixtures/root/book-doctype.adoc +10 -0
  152. data/spec/fixtures/root/book-doctype.md +9 -0
  153. data/spec/fixtures/root/header-and-body.adoc +3 -0
  154. data/spec/fixtures/root/header-and-body.md +3 -0
  155. data/spec/fixtures/root/header-only.adoc +1 -0
  156. data/spec/fixtures/root/header-only.md +1 -0
  157. data/spec/fixtures/smart_quote/apostrophe.adoc +1 -0
  158. data/spec/fixtures/smart_quote/apostrophe.md +1 -0
  159. data/spec/fixtures/smart_quote/double-quotes.adoc +1 -0
  160. data/spec/fixtures/smart_quote/double-quotes.md +1 -0
  161. data/spec/fixtures/smart_quote/single-quotes.adoc +1 -0
  162. data/spec/fixtures/smart_quote/single-quotes.md +1 -0
  163. data/spec/fixtures/strong/constrained.adoc +1 -0
  164. data/spec/fixtures/strong/constrained.md +1 -0
  165. data/spec/fixtures/strong/nested-emphasis.adoc +1 -0
  166. data/spec/fixtures/strong/nested-emphasis.md +1 -0
  167. data/spec/fixtures/table/with-header.adoc +9 -0
  168. data/spec/fixtures/table/with-header.md +4 -0
  169. data/spec/fixtures/table/without-header.adoc +8 -0
  170. data/spec/fixtures/table/without-header.md +2 -0
  171. data/spec/fixtures/text/lte.adoc +1 -0
  172. data/spec/fixtures/text/lte.md +1 -0
  173. data/spec/fixtures/text/plus-plus.adoc +6 -0
  174. data/spec/fixtures/text/plus-plus.md +5 -0
  175. data/spec/fixtures/text/typographic_sym/apostrophe.adoc +1 -0
  176. data/spec/fixtures/text/typographic_sym/apostrophe.md +1 -0
  177. data/spec/fixtures/text/typographic_sym/double-quotes.adoc +1 -0
  178. data/spec/fixtures/text/typographic_sym/double-quotes.md +1 -0
  179. data/spec/fixtures/text/typographic_sym/ellipsis.adoc +1 -0
  180. data/spec/fixtures/text/typographic_sym/ellipsis.md +1 -0
  181. data/spec/fixtures/text/typographic_sym/mdash.adoc +1 -0
  182. data/spec/fixtures/text/typographic_sym/mdash.md +1 -0
  183. data/spec/fixtures/text/typographic_sym/ndash.adoc +1 -0
  184. data/spec/fixtures/text/typographic_sym/ndash.md +1 -0
  185. data/spec/fixtures/text/typographic_sym/single-quotes.adoc +1 -0
  186. data/spec/fixtures/text/typographic_sym/single-quotes.md +1 -0
  187. data/spec/fixtures/typographic_sym/ellipsis.adoc +1 -0
  188. data/spec/fixtures/typographic_sym/ellipsis.md +1 -0
  189. data/spec/fixtures/typographic_sym/mdash.adoc +1 -0
  190. data/spec/fixtures/typographic_sym/mdash.md +1 -0
  191. data/spec/fixtures/typographic_sym/ndash.adoc +1 -0
  192. data/spec/fixtures/typographic_sym/ndash.md +1 -0
  193. data/spec/fixtures/ul/compound-separated.adoc +25 -0
  194. data/spec/fixtures/ul/compound-separated.md +23 -0
  195. data/spec/fixtures/ul/compound.adoc +25 -0
  196. data/spec/fixtures/ul/compound.md +18 -0
  197. data/spec/fixtures/ul/nested-separated.adoc +11 -0
  198. data/spec/fixtures/ul/nested-separated.md +21 -0
  199. data/spec/fixtures/ul/nested.adoc +11 -0
  200. data/spec/fixtures/ul/nested.md +11 -0
  201. data/spec/fixtures/ul/simple-separated.adoc +3 -0
  202. data/spec/fixtures/ul/simple-separated.md +5 -0
  203. data/spec/fixtures/ul/simple.adoc +3 -0
  204. data/spec/fixtures/ul/simple.md +3 -0
  205. data/spec/fixtures/xml_comment/block.adoc +7 -0
  206. data/spec/fixtures/xml_comment/block.md +6 -0
  207. data/spec/fixtures/xml_comment/line-offset-by-space.adoc +1 -0
  208. data/spec/fixtures/xml_comment/line-offset-by-space.md +1 -0
  209. data/spec/fixtures/xml_comment/line.adoc +1 -0
  210. data/spec/fixtures/xml_comment/line.md +1 -0
  211. data/spec/fixtures/xml_comment/list-separator.adoc +7 -0
  212. data/spec/fixtures/xml_comment/list-separator.md +7 -0
  213. data/spec/fixtures/xml_comment/mixed.adoc +7 -0
  214. data/spec/fixtures/xml_comment/mixed.md +6 -0
  215. data/spec/fixtures/xml_comment/multiline-span.adoc +4 -0
  216. data/spec/fixtures/xml_comment/multiline-span.md +3 -0
  217. data/spec/fixtures/xml_comment/styled.adoc +6 -0
  218. data/spec/fixtures/xml_comment/styled.md +6 -0
  219. data/spec/integration_spec.rb +27 -0
  220. data/spec/spec_helper.rb +9 -0
  221. metadata +533 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 70b7c1c3b371ac7e88456a531413b89ccb7186f706f44ad33abedd96ce6ef52d
4
+ data.tar.gz: b8ee1cb2365ff90ad26abb4528dad929cb75034297bd2e590c48453c2a3f61bc
5
+ SHA512:
6
+ metadata.gz: b2cf8e0cf5ef344ee31621f1b05e86e9504c5392adbc79b443db9594764bf51d39371cb2db57a36d7bb59ed4b0079a0eec0519c95d78cfb615c4cf00d8680830
7
+ data.tar.gz: 1bc00c04fd46be08e697a562eeea7f583a0e6afc3949a9c1bc937f1509d0605c07b367dec9fc2c578a8ff31f4d438349c5832b72799612f18b53eb9306549ce6
@@ -0,0 +1,10 @@
1
+ = {project-name} Changelog
2
+ :project-name: Kramdown AsciiDoc
3
+ :uri-repo: https://github.com/asciidoctor/kramdown-asciidoc
4
+
5
+ This document provides a high-level view of the changes to {project-name} by release.
6
+ For a detailed view of what has changed, refer to the {uri-repo}/commits/master[commit history] on GitHub.
7
+
8
+ == 1.0.0.alpha.1 (2018-05-22) - @mojavelinux
9
+
10
+ Initial release.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ .The MIT License
2
+ ....
3
+ Copyright (C) 2016 OpenDevise Inc. (on behalf of the Asciidoctor Project)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+ ....
@@ -0,0 +1,147 @@
1
+ = {project-name} (Markdown to AsciiDoc)
2
+ Dan Allen <https://github.com/mojavelinux>
3
+ v1.0.0.alpha.1, 2018-05-22
4
+ // Aliases:
5
+ :project-name: Kramdown AsciiDoc
6
+ :project-handle: kramdown-asciidoc
7
+ // Settings:
8
+ :idprefix:
9
+ :idseparator: -
10
+ ifndef::env-github[:icons: font]
11
+ ifdef::env-github,env-browser[]
12
+ :toc: preamble
13
+ :toclevels: 1
14
+ endif::[]
15
+ ifdef::env-github[]
16
+ :status:
17
+ :!toc-title:
18
+ :note-caption: :paperclip:
19
+ :tip-caption: :bulb:
20
+ endif::[]
21
+ // URIs:
22
+ :uri-repo: https://github.com/asciidoctor/kramdown-asciidoc
23
+ :uri-asciidoc: https://asciidoctor.org/docs/what-is-asciidoc/#what-is-asciidoc
24
+ :uri-asciidoctor: https://asciidoctor.org
25
+ :uri-rvm: https://rvm.io
26
+ :uri-install-rvm: https://rvm.io/rvm/install
27
+ //:img-gem: https://img.shields.io/gem/v/kramdown-asciidoc.svg?label=gem
28
+ :uri-ci-travis: https://travis-ci.org/asciidoctor/kramdown-asciidoc
29
+ :img-ci-travis: https://img.shields.io/travis/asciidoctor/kramdown-asciidoc/master.svg
30
+
31
+ ifdef::status[]
32
+ //image:{img-gem}[Gem Version,link={uri-gem}]
33
+ image:{img-ci-travis}[Build Status (Travis CI),link={uri-ci-travis}]
34
+ endif::[]
35
+
36
+ {uri-repo}[{project-name}] (gem: *{project-handle}*) is a Kramdown extension for converting Markdown documents to {uri-asciidoc}[AsciiDoc].
37
+ Notably, the converter generates modern AsciiDoc syntax suitable for use with {uri-asciidoctor}[Asciidoctor].
38
+
39
+ == Prerequisites
40
+
41
+ To install and run {project-name}, you need Ruby 2.4 or better installed and a few RubyGems (aka gems).
42
+ We'll explain how to install the gems in the next section.
43
+
44
+ To check whether you have Ruby installed, and which version you have, run the following command:
45
+
46
+ $ ruby -v
47
+
48
+ If Ruby is not installed, you can install it using {uri-rvm}[RVM] (or, if you prefer, the package manager for your system).
49
+ We generally recommend using RVM because it allows you to install gems without requiring elevated privileges or messing with system libraries.
50
+
51
+ == Installation
52
+
53
+ {project-name} is published as a pre-release gem named {project-handle} to RubyGems.org.
54
+
55
+ You can install the pre-release version using the following command:
56
+
57
+ $ gem install kramdown-asciidoc --pre
58
+
59
+ Installing this gem makes the `kramdoc` command available on your $PATH.
60
+
61
+ TIP: To test a feature that's not yet released, you can <<Development,run the application from source>>.
62
+
63
+ == Usage
64
+
65
+ To convert a Markdown file to AsciiDoc using {project-name}, run the `kramdoc` command as follows:
66
+
67
+ $ kramdoc sample.md
68
+
69
+ The `kramdoc` command automatically creates the output file [.path]_sample.adoc_ in the same folder as the input file.
70
+ This path is calculated by removing the Markdown file extension, `.md`, and adding the AsciiDoc file extension, `.adoc`.
71
+
72
+ NOTE: The converter assumes the input uses the GitHub-flavor Markdown (GFM) syntax.
73
+
74
+ The `kramdoc` command does not currently support any options other than the input file.
75
+ Support for additional options is planned.
76
+
77
+ == Development
78
+
79
+ To help develop {project-name}, or to simply test-drive the development version, you need to retrieve the source from GitHub.
80
+ Follow the instructions below to learn how to clone the source and run the application from source (i.e., your clone).
81
+
82
+ === Retrieve the source code
83
+
84
+ Simply copy the {uri-repo}[GitHub repository URL] and pass it to the `git clone` command:
85
+
86
+ [subs=attributes+]
87
+ $ git clone {uri-repo}
88
+
89
+ Next, switch to the project directory:
90
+
91
+ [subs=attributes+]
92
+ $ cd {project-handle}
93
+
94
+ === Prepare RVM (optional)
95
+
96
+ We recommend using {uri-rvm}[RVM] when developing applications with Ruby.
97
+ We like RVM because it keeps the dependencies required by the project isolated from the rest of your system.
98
+ Follow the {uri-install-rvm}[installation instructions] on the RVM site to setup RVM and install Ruby.
99
+
100
+ Once you have RVM setup, switch to the RVM-managed version of Ruby recommended by the project using this command:
101
+
102
+ $ rvm use
103
+
104
+ The recommended version of Ruby is defined in the [.path]_.ruby-version_ file at the root of the project.
105
+
106
+ === Install the dependencies
107
+
108
+ The dependencies needed to use {project-name} are defined in the [.path]_Gemfile_ at the root of the project.
109
+ You'll use Bundler to install these dependencies.
110
+
111
+ To check if you have Bundler available, use the `bundle` command to query the version installed:
112
+
113
+ $ bundle --version
114
+
115
+ If Bundler is not installed, use the `gem` command to install it.
116
+
117
+ $ gem install bundler
118
+
119
+ Then, use the `bundle` command to install the project dependencies under the project directory:
120
+
121
+ $ bundle --path=.bundle/gems
122
+
123
+ NOTE: You must invoke `bundle` from the project's root directory so it can locate the [.path]_Gemfile_.
124
+
125
+ === Usage
126
+
127
+ When running the `kramdoc` command from source, you must prefix the command with `bundle exec`:
128
+
129
+ $ bundle exec kramdoc sample.md
130
+
131
+ To avoid having to do this, or make the `kramdoc` command available from anywhere, you need to build the development gem and install it.
132
+
133
+ == Alternatives
134
+
135
+ * https://github.com/bodiam/markdown-to-asciidoc[markdown-to-asciidoc] (Java library)
136
+ * http://pandoc.org[pandoc] (Haskell-based CLI tool)
137
+
138
+ == Authors
139
+
140
+ *{project-name}* was written by {email}[{author}].
141
+
142
+ == Copyright
143
+
144
+ Copyright (C) 2016-2018 OpenDevise Inc. (on behalf of the Asciidoctor Project).
145
+ Free use of this software is granted under the terms of the MIT License.
146
+
147
+ See the link:LICENSE.adoc[LICENSE] file for details.
@@ -0,0 +1,3 @@
1
+ Dir.glob('tasks/*.rake').each {|file| load file }
2
+
3
+ task default: %w(spec)
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if File.exist? (kramdown_asciidoc = File.absolute_path '../lib/kramdown-asciidoc', __dir__)
4
+ require kramdown_asciidoc
5
+ else
6
+ require 'kramdown-asciidoc'
7
+ end
8
+
9
+ infile = ARGV.first
10
+ unless infile
11
+ warn 'Please specify a Markdown file to convert.'
12
+ exit 1
13
+ end
14
+ outfile = %(#{infile.slice 0, infile.length - (File.extname infile).length}.adoc)
15
+ input = (IO.read infile, open_args: ['rb:UTF-8']).rstrip
16
+ input = input.slice 1, input.length while input.start_with? ?\n
17
+ attributes = {}
18
+ input = Kramdown::AsciiDoc.extract_front_matter input, attributes
19
+ input = Kramdown::AsciiDoc.replace_toc input, attributes
20
+ # FIXME allow input type to be specified (Kramdown, GFM, etc)
21
+ doc = Kramdown::Document.new input, (Kramdown::AsciiDoc::DEFAULT_PARSER_OPTS.merge attributes: attributes)
22
+ # FIXME provide option to write to different file or stdout
23
+ IO.write outfile, doc.to_asciidoc
24
+ exit 0
@@ -0,0 +1,41 @@
1
+ require File.absolute_path 'lib/kramdown-asciidoc/version', __dir__
2
+ require 'open3' unless defined? Open3
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'kramdown-asciidoc'
6
+ s.version = Kramdown::AsciiDoc::VERSION
7
+ s.summary = 'A Markdown to AsciiDoc converter based on Kramdown'
8
+ s.description = 'A Kramdown extension for converting Markdown documents to AsciiDoc.'
9
+
10
+ s.authors = ['Dan Allen']
11
+ s.email = ['dan.j.allen@gmail.com']
12
+ s.homepage = 'https://github.com/asciidoctor/kramdown-asciidoc'
13
+ s.license = 'MIT'
14
+ s.metadata = {
15
+ 'bug_tracker_uri' => 'https://github.com/asciidoctor/kramdown-asciidoc/issues',
16
+ 'changelog_uri' => 'https://github.com/asciidoctor/kramdown-asciidoc/blob/master/CHANGELOG.adoc',
17
+ 'mailing_list_uri' => 'http://discuss.asciidoctor.org',
18
+ 'source_code_uri' => 'https://github.com/asciidoctor/kramdown-asciidoc'
19
+ }
20
+ #s.required_ruby_version = '>= 2.4.0'
21
+
22
+ files = begin
23
+ (result = Open3.popen3('git ls-files -z') {|_, out| out.read }.split ?\0).empty? ? Dir['**/*'] : result
24
+ rescue
25
+ Dir['**/*']
26
+ end
27
+ s.files = files.grep %r/^(?:lib\/.+|Gemfile|Rakefile|(?:CHANGELOG|CONTRIBUTING|LICENSE|README)\.adoc|#{s.name}\.gemspec)$/
28
+ s.test_files = files.grep %r/^(?:spec\/.+)$/
29
+ s.executables = ['kramdoc']
30
+
31
+ s.require_paths = ['lib']
32
+
33
+ #s.has_rdoc = true
34
+ #s.rdoc_options = ['--charset=UTF-8']
35
+ #s.extra_rdoc_files = ['CHANGELOG.adoc', 'LICENSE.adoc']
36
+
37
+ s.add_runtime_dependency 'kramdown', '~> 1.16.2'
38
+ s.add_development_dependency 'rake', '~> 12.3.1'
39
+ s.add_development_dependency 'rspec', '~> 3.7.0'
40
+ s.add_development_dependency 'simplecov', '~> 0.16.1'
41
+ end
@@ -0,0 +1,2 @@
1
+ require 'kramdown'
2
+ require_relative 'kramdown-asciidoc/converter'
@@ -0,0 +1,413 @@
1
+ # encoding: UTF-8
2
+ module Kramdown; module AsciiDoc
3
+ DEFAULT_PARSER_OPTS = {
4
+ auto_ids: false,
5
+ hard_wrap: false,
6
+ html_to_native: true,
7
+ input: 'GFM',
8
+ }
9
+
10
+ TocDirectiveTip = '<!-- TOC '
11
+ TocDirectiveRx = /^<!-- TOC .*<!-- \/TOC -->/m
12
+
13
+ def self.replace_toc source, attributes
14
+ if source.include? TocDirectiveTip
15
+ attributes['toc'] = 'macro'
16
+ source.gsub TocDirectiveRx, 'toc::[]'
17
+ else
18
+ source
19
+ end
20
+ end
21
+
22
+ def self.extract_front_matter source, attributes
23
+ if (line_i = (lines = source.each_line).next) && line_i.chomp == '---'
24
+ require 'yaml' unless defined? ::YAML
25
+ lines = lines.drop 1
26
+ front_matter = []
27
+ while (line = lines.shift) && line.chomp != '---'
28
+ front_matter << line
29
+ end
30
+ lines.shift while (line = lines[0]) && line.chomp.empty?
31
+ (::YAML.load front_matter.join).each do |key, val|
32
+ case key
33
+ when 'title'
34
+ # skip
35
+ when 'layout'
36
+ attributes['page-layout'] = val unless val == 'default'
37
+ else
38
+ attributes[key] = val.to_s
39
+ end
40
+ end
41
+ lines.join
42
+ else
43
+ source
44
+ end
45
+ end
46
+
47
+ class Converter < ::Kramdown::Converter::Base
48
+ RESOLVE_ENTITY_TABLE = %w(lt gt).map {|name| Utils::Entities.entity name }.map {|obj| [obj, obj.char] }.to_h
49
+ ADMON_LABELS = %w(Note Tip Caution Warning Important Attention).map {|l| [l, l] }.to_h
50
+ ADMON_MARKERS = ADMON_LABELS.map {|l, _| %(#{l}: ) }
51
+ ADMON_FORMATTED_MARKERS = ADMON_LABELS.map {|l, _| [%(#{l}:), l] }.to_h
52
+ ADMON_TYPE_MAP = ADMON_LABELS.map {|l, _| [l, l.upcase] }.to_h.merge 'Attention' => 'IMPORTANT'
53
+ # FIXME here we reverse the smart quotes; add option to allow them (needs to be handled carefully)
54
+ SMART_QUOTE_ENTITY_TO_MARKUP = { ldquo: ?", rdquo: ?", lsquo: ?', rsquo: ?' }
55
+ TYPOGRAPHIC_SYMBOL_TO_MARKUP = {
56
+ '“' => '"`',
57
+ '”' => '`"',
58
+ '‘' => '\'`',
59
+ '’' => '`\'',
60
+ # FIXME in the future, mdash will be three dashes in AsciiDoc; for now, down-convert
61
+ '—' => '--',
62
+ '–' => '&#8211;',
63
+ '…' => '...',
64
+ }
65
+ TYPOGRAPHIC_ENTITY_TO_MARKUP = {
66
+ # FIXME in the future, mdash will be three dashes in AsciiDoc; for now, down-convert
67
+ mdash: '--',
68
+ ndash: '--',
69
+ hellip: '...',
70
+ laquo: '<<',
71
+ raquo: '>>',
72
+ laquo_scape: '<< ',
73
+ raquo_space: ' >>',
74
+ }
75
+
76
+ ApostropheRx = /\b’\b/
77
+ CommentPrefixRx = /^ *! ?/m
78
+ ReplaceableTextRx = /[-=]>|<[-=]|\.\.\./
79
+ StartOfLinesRx = /^/m
80
+ TypographicSymbolRx = /[“”‘’—–…]/
81
+ XmlCommentRx = /\A<!--(.*)-->\Z/m
82
+
83
+ VoidElement = Element.new nil
84
+
85
+ LF = ?\n
86
+ LFx2 = LF * 2
87
+
88
+ def initialize root, opts
89
+ super
90
+ @header = []
91
+ @attributes = opts[:attributes] || {}
92
+ @imagesdir = (@attributes.delete 'implicit-imagesdir') || @attributes['imagesdir']
93
+ @last_heading_level = nil
94
+ end
95
+
96
+ def convert el, opts = {}
97
+ send %(convert_#{el.type}), el, opts
98
+ end
99
+
100
+ def convert_root el, opts
101
+ body = %(#{inner el, (opts.merge rstrip: true)}#{LF})
102
+ @attributes.each {|k, v| @header << %(:#{k}: #{v}) } unless @attributes.empty?
103
+ @header.empty? ? body : %(#{@header.join LF}#{body == LF ? '' : LFx2}#{body})
104
+ end
105
+
106
+ def convert_blank el, opts
107
+ nil
108
+ end
109
+
110
+ def convert_heading el, opts
111
+ result = []
112
+ style = []
113
+ level = el.options[:level]
114
+ style << 'discrete' if (discrete = @last_heading_level && level > @last_heading_level + 1)
115
+ if (id = el.attr['id'])
116
+ style << %(##{id})
117
+ elsif (child_i = el.children[0] || VoidElement).type == :html_element && child_i.value == 'a' && (id = child_i.attr['id'])
118
+ el.children.shift
119
+ el.children.unshift(*child_i.children) unless child_i.children.empty?
120
+ style << %(##{id})
121
+ elsif (role = el.attr['class'])
122
+ style << %(.#{role.tr ' ', '.'})
123
+ end
124
+ result << %([#{style.join}]) unless style.empty?
125
+ result << %(#{'=' * level} #{inner el, opts})
126
+ @last_heading_level = level unless discrete
127
+ if level == 1 && opts[:result].empty?
128
+ @header = result
129
+ nil
130
+ else
131
+ @attributes['doctype'] = 'book' if level == 1
132
+ %(#{result.join LF}#{LFx2})
133
+ end
134
+ end
135
+
136
+ # Kramdown incorrectly uses the term header for headings
137
+ alias convert_header convert_heading
138
+
139
+ def convert_p el, opts
140
+ if (parent = opts[:parent]) && parent.type == :li
141
+ # NOTE :prev option not set indicates primary text; convert_li appends LF
142
+ return inner el, opts unless opts[:prev]
143
+ parent.options[:compound] = true
144
+ opts[:result].pop unless opts[:result][-1]
145
+ prefix, suffix = %(#{LF}+#{LF}), ''
146
+ else
147
+ prefix, suffix = '', LFx2
148
+ end
149
+ # NOTE detect plain admonition marker (e.g, Note: ...)
150
+ if (child_i = el.children[0] || VoidElement).type == :text && (child_i_text = child_i.value).start_with?(*ADMON_MARKERS)
151
+ marker, child_i_text = child_i_text.split ': ', 2
152
+ child_i.value = %(#{ADMON_TYPE_MAP[marker]}: #{child_i_text})
153
+ contents = inner el, opts
154
+ # NOTE detect formatted admonition marker (e.g., *Note:* ...)
155
+ elsif (child_i.type == :strong || child_i.type == :em) &&
156
+ (marker_el = child_i.children[0]) && ((marker = ADMON_FORMATTED_MARKERS[marker_el.value]) ||
157
+ ((marker = ADMON_LABELS[marker_el.value]) && (child_ii = el.children[1] || VoidElement).type == :text &&
158
+ ((child_ii_text = child_ii.value).start_with? ': ')))
159
+ el.children.shift
160
+ child_ii.value = child_ii_text.slice 1, child_ii_text.length if child_ii
161
+ contents = %(#{ADMON_TYPE_MAP[marker]}:#{inner el, opts})
162
+ else
163
+ contents = inner el, opts
164
+ end
165
+ %(#{prefix}#{contents}#{suffix})
166
+ end
167
+
168
+ # TODO detect admonition masquerading as blockquote
169
+ def convert_blockquote el, opts
170
+ result = []
171
+ # TODO support more than one level of nesting
172
+ boundary = (parent = opts[:parent]) && parent.type == :blockquote ? '______' : '____'
173
+ contents = inner el, (opts.merge rstrip: true)
174
+ if (contents.include? LF) && ((attribution_line = (lines = contents.split LF).pop).start_with? '-- ')
175
+ attribution = attribution_line.slice 3, attribution_line.length
176
+ result << %([,#{attribution}])
177
+ lines.pop while lines.size > 0 && lines[-1].empty?
178
+ contents = lines.join LF
179
+ end
180
+ result << boundary
181
+ result << contents
182
+ result << boundary
183
+ %(#{result.join LF}#{LFx2})
184
+ end
185
+
186
+ def convert_codeblock el, opts
187
+ result = []
188
+ if (parent = opts[:parent]) && parent.type == :li
189
+ parent.options[:compound] = true
190
+ if (current_line = opts[:result].pop)
191
+ opts[:result] << current_line.chomp
192
+ end unless opts[:result].empty?
193
+ list_continuation = %(#{LF}+)
194
+ suffix = ''
195
+ else
196
+ suffix = LFx2
197
+ end
198
+ contents = el.value.rstrip
199
+ if (lang = el.attr['class'])
200
+ lang = lang.slice 9, lang.length if lang.start_with? 'language-'
201
+ #lang = 'console' if lang == 'bash' && (contents.start_with? '$ ')
202
+ lang = 'console' if lang == 'bash'
203
+ result << %([source,#{lang}])
204
+ end
205
+ if !lang && (contents.start_with? '$ ')
206
+ if contents.include? LFx2
207
+ result << '....'
208
+ result << contents
209
+ result << '....'
210
+ else
211
+ list_continuation = LF if list_continuation
212
+ result << (contents.gsub StartOfLinesRx, ' ')
213
+ end
214
+ else
215
+ result << '----'
216
+ result << contents
217
+ result << '----'
218
+ end
219
+ result.unshift list_continuation if list_continuation
220
+ %(#{result.join LF}#{suffix})
221
+ end
222
+
223
+ def convert_ul el, opts
224
+ # TODO create do_in_level block
225
+ level = opts[:level] ? (opts[:level] += 1) : (opts[:level] = 1)
226
+ # REVIEW this is whack
227
+ prefix = (parent = opts[:parent]) && parent.type == :li && !opts[:result][-1] ? LF : ''
228
+ contents = inner el, (opts.merge rstrip: true)
229
+ if level == 1
230
+ suffix = LFx2
231
+ opts.delete :level
232
+ else
233
+ suffix = LF
234
+ opts[:level] -= 1
235
+ end
236
+ %(#{prefix}#{contents}#{suffix})
237
+ end
238
+
239
+ alias convert_ol convert_ul
240
+
241
+ def convert_li el, opts
242
+ prefix = (prev = opts[:prev]) && prev.options[:compound] ? LF : ''
243
+ marker = opts[:parent].type == :ol ? '.' : '*'
244
+ indent = (level = opts[:level]) - 1
245
+ %(#{prefix}#{indent > 0 ? (' ' * indent) : ''}#{marker * level} #{(inner el, (opts.merge rstrip: true))}#{LF})
246
+ end
247
+
248
+ def convert_table el, opts
249
+ head = cols = nil
250
+ table_buf = ['|===']
251
+ el.children.each do |container|
252
+ container.children.each do |row|
253
+ row_buf = []
254
+ row.children.each do |cell|
255
+ row_buf << %(| #{inner cell, opts})
256
+ end
257
+ cols = row_buf.size unless cols
258
+ if container.type == :thead
259
+ head = true
260
+ row_buf = [row_buf * ' ']
261
+ end
262
+ row_buf << ''
263
+ table_buf.concat row_buf
264
+ end
265
+ end
266
+ table_buf.unshift %([cols=#{cols}*]) unless head
267
+ table_buf.pop if table_buf[-1] == ''
268
+ table_buf << '|==='
269
+ %(#{table_buf * LF}#{LFx2})
270
+ end
271
+
272
+ def convert_hr el, opts
273
+ %('''#{LFx2})
274
+ end
275
+
276
+ def convert_text el, opts
277
+ if (result = el.value).include? '++'
278
+ @attributes['pp'] = '{plus}{plus}'
279
+ result = result.gsub '++', '{pp}'
280
+ end
281
+ result = result.gsub '<=', '\\<=' if result.include? '<='
282
+ if result.ascii_only?
283
+ result
284
+ else
285
+ (result.gsub ApostropheRx, ?').gsub TypographicSymbolRx, TYPOGRAPHIC_SYMBOL_TO_MARKUP
286
+ end
287
+ end
288
+
289
+ def convert_codespan el, opts
290
+ (val = el.value) =~ ReplaceableTextRx ? %(`+#{val}+`) : %(`#{val}`)
291
+ end
292
+
293
+ def convert_em el, opts
294
+ %(_#{inner el, opts}_)
295
+ end
296
+
297
+ def convert_strong el, opts
298
+ %(*#{inner el, opts}*)
299
+ end
300
+
301
+ # NOTE this logic assumes the :hard_wrap option is disabled in the parser
302
+ def convert_br el, opts
303
+ prefix = ((opts[:result][-1] || '').end_with? ' ') ? '' : ' '
304
+ # if @attr is set, this is a <br> HTML tag
305
+ if el.instance_variable_get :@attr
306
+ siblings = opts[:parent].children
307
+ suffix = (next_el = siblings[(siblings.index el) + 1] || VoidElement).type == :text && (next_el.value.start_with? LF) ? '' : LF
308
+ else
309
+ suffix = ''
310
+ end
311
+ %(#{prefix}+#{suffix})
312
+ end
313
+
314
+ def convert_smart_quote el, opts
315
+ SMART_QUOTE_ENTITY_TO_MARKUP[el.value]
316
+ end
317
+
318
+ def convert_entity el, opts
319
+ RESOLVE_ENTITY_TABLE[el.value] || el.options[:original]
320
+ end
321
+
322
+ def convert_a el, opts
323
+ if (url = el.attr['href']).start_with? '#'
324
+ %(<<#{url.slice 1, url.length},#{inner el, opts}>>)
325
+ elsif url.start_with? 'https://', 'http://'
326
+ if (child_i = el.children[0] || VoidElement).type == :img
327
+ convert_img child_i, parent: opts[:parent], index: 0, url: url
328
+ else
329
+ ((contents = inner el, opts).chomp '/') == (url.chomp '/') ? url : %(#{url}[#{contents}])
330
+ end
331
+ elsif url.end_with? '.md'
332
+ %(xref:#{url.slice 0, url.length - 3}.adoc[#{inner el, opts}])
333
+ else
334
+ %(link:#{url}[#{inner el, opts}])
335
+ end
336
+ end
337
+
338
+ def convert_img el, opts
339
+ prefix = !(parent = opts[:parent]) || parent.type == :p && parent.children.size == 1 ? 'image::' : 'image:'
340
+ alt_text = el.attr['alt']
341
+ link_attr = (url = opts[:url]) ? %(#{alt_text.empty? ? '' : ','}link=#{url}) : ''
342
+ src = el.attr['src']
343
+ if (imagesdir = @imagesdir) && (src.start_with? %(#{imagesdir}/))
344
+ src = src.slice imagesdir.length + 1, src.length
345
+ end
346
+ %(#{prefix}#{src}[#{alt_text}#{link_attr}])
347
+ end
348
+
349
+ # NOTE leave enabled so we can down-convert mdash to --
350
+ def convert_typographic_sym el, opts
351
+ TYPOGRAPHIC_ENTITY_TO_MARKUP[el.value]
352
+ end
353
+
354
+ def convert_html_element el, opts
355
+ contents = inner el, (opts.merge rstrip: el.options[:category] == :block)
356
+ attrs = (attrs = el.attr).empty? ? '' : attrs.map {|k, v| %( #{k}="#{v}") }.join
357
+ case (tagname = el.value)
358
+ when 'sup'
359
+ %(^#{contents}^)
360
+ when 'sub'
361
+ %(~#{contents}~)
362
+ else
363
+ %(+++<#{tagname}#{attrs}>+++#{contents}+++</#{tagname}>+++)
364
+ end
365
+ end
366
+
367
+ def convert_xml_comment el, opts
368
+ XmlCommentRx =~ el.value
369
+ comment_text = ($1.include? ' !') ? ($1.gsub CommentPrefixRx, '').strip : $1.strip
370
+ #siblings = (parent = opts[:parent]) ? parent.children : []
371
+ if (el.options[:category] == :block)# || (!opts[:result][-1] && siblings[-1] == el)
372
+ if comment_text.empty?
373
+ %(//-#{LFx2})
374
+ elsif comment_text.include? LF
375
+ %(////#{LF}#{comment_text}#{LF}////#{LFx2})
376
+ else
377
+ %(// #{comment_text}#{LFx2})
378
+ end
379
+ else
380
+ if (current_line = opts[:result][-1])
381
+ if current_line.end_with? LF
382
+ prefix = ''
383
+ else
384
+ prefix = LF
385
+ opts[:result][-1] = (current_line = current_line.rstrip) if current_line.end_with? ' '
386
+ end
387
+ else
388
+ prefix = ''
389
+ end
390
+ siblings = (parent = opts[:parent]) && parent.children
391
+ suffix = siblings && siblings[(siblings.index el) + 1] ? LF : ''
392
+ if comment_text.include? LF
393
+ %(#{prefix}#{comment_text.gsub StartOfLinesRx, '// '}#{suffix})
394
+ else
395
+ %(#{prefix}// #{comment_text}#{suffix})
396
+ end
397
+ end
398
+ end
399
+
400
+ def inner el, opts
401
+ rstrip = opts.delete :rstrip
402
+ result = []
403
+ prev = nil
404
+ el.children.each_with_index do |child, idx|
405
+ result << (send %(convert_#{child.type}), child, (opts.merge parent: el, index: idx, result: result, prev: prev))
406
+ prev = child
407
+ end
408
+ rstrip ? result.join.rstrip : result.join
409
+ end
410
+ end
411
+ end; end
412
+
413
+ Kramdown::Converter::Asciidoc = Kramdown::AsciiDoc::Converter