asciidoctor 1.5.8 → 2.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/CHANGELOG.adoc +628 -45
  4. data/LICENSE +2 -1
  5. data/README-de.adoc +28 -38
  6. data/README-fr.adoc +30 -43
  7. data/README-jp.adoc +255 -201
  8. data/README-zh_CN.adoc +40 -44
  9. data/README.adoc +170 -143
  10. data/asciidoctor.gemspec +22 -34
  11. data/bin/asciidoctor +5 -4
  12. data/data/locale/attributes-ar.adoc +4 -3
  13. data/data/locale/attributes-be.adoc +23 -0
  14. data/data/locale/attributes-bg.adoc +4 -3
  15. data/data/locale/attributes-ca.adoc +6 -5
  16. data/data/locale/attributes-cs.adoc +4 -3
  17. data/data/locale/attributes-da.adoc +6 -5
  18. data/data/locale/attributes-de.adoc +6 -5
  19. data/data/locale/attributes-en.adoc +4 -4
  20. data/data/locale/attributes-es.adoc +6 -5
  21. data/data/locale/attributes-fa.adoc +4 -3
  22. data/data/locale/attributes-fi.adoc +4 -3
  23. data/data/locale/attributes-fr.adoc +8 -7
  24. data/data/locale/attributes-hu.adoc +4 -3
  25. data/data/locale/attributes-id.adoc +4 -3
  26. data/data/locale/attributes-it.adoc +6 -5
  27. data/data/locale/attributes-ja.adoc +4 -3
  28. data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
  29. data/data/locale/attributes-nb.adoc +4 -3
  30. data/data/locale/attributes-nl.adoc +6 -5
  31. data/data/locale/attributes-nn.adoc +4 -3
  32. data/data/locale/attributes-pl.adoc +8 -7
  33. data/data/locale/attributes-pt.adoc +6 -5
  34. data/data/locale/attributes-pt_BR.adoc +6 -5
  35. data/data/locale/attributes-ro.adoc +4 -3
  36. data/data/locale/attributes-ru.adoc +6 -5
  37. data/data/locale/attributes-sr.adoc +4 -4
  38. data/data/locale/attributes-sr_Latn.adoc +4 -4
  39. data/data/locale/attributes-sv.adoc +4 -4
  40. data/data/locale/attributes-th.adoc +23 -0
  41. data/data/locale/attributes-tr.adoc +4 -3
  42. data/data/locale/attributes-uk.adoc +6 -5
  43. data/data/locale/attributes-vi.adoc +23 -0
  44. data/data/locale/attributes-zh_CN.adoc +4 -3
  45. data/data/locale/attributes-zh_TW.adoc +4 -3
  46. data/data/reference/syntax.adoc +296 -0
  47. data/data/stylesheets/asciidoctor-default.css +120 -114
  48. data/data/stylesheets/coderay-asciidoctor.css +15 -17
  49. data/lib/asciidoctor/abstract_block.rb +146 -140
  50. data/lib/asciidoctor/abstract_node.rb +152 -170
  51. data/lib/asciidoctor/attribute_list.rb +77 -89
  52. data/lib/asciidoctor/block.rb +29 -28
  53. data/lib/asciidoctor/callouts.rb +4 -2
  54. data/lib/asciidoctor/cli/invoker.rb +20 -24
  55. data/lib/asciidoctor/cli/options.rb +107 -96
  56. data/lib/asciidoctor/cli.rb +3 -2
  57. data/lib/asciidoctor/convert.rb +199 -0
  58. data/lib/asciidoctor/converter/composite.rb +40 -48
  59. data/lib/asciidoctor/converter/docbook5.rb +627 -644
  60. data/lib/asciidoctor/converter/html5.rb +1053 -951
  61. data/lib/asciidoctor/converter/manpage.rb +581 -532
  62. data/lib/asciidoctor/converter/template.rb +232 -271
  63. data/lib/asciidoctor/converter.rb +370 -185
  64. data/lib/asciidoctor/core_ext/float/truncate.rb +20 -0
  65. data/lib/asciidoctor/core_ext/hash/merge.rb +8 -0
  66. data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
  67. data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
  68. data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
  69. data/lib/asciidoctor/core_ext.rb +8 -17
  70. data/lib/asciidoctor/document.rb +503 -461
  71. data/lib/asciidoctor/extensions.rb +127 -174
  72. data/lib/asciidoctor/helpers.rb +184 -107
  73. data/lib/asciidoctor/inline.rb +9 -12
  74. data/lib/asciidoctor/list.rb +11 -29
  75. data/lib/asciidoctor/load.rb +119 -0
  76. data/lib/asciidoctor/logging.rb +22 -17
  77. data/lib/asciidoctor/parser.rb +673 -719
  78. data/lib/asciidoctor/path_resolver.rb +48 -33
  79. data/lib/asciidoctor/reader.rb +383 -338
  80. data/lib/asciidoctor/rouge_ext.rb +39 -0
  81. data/lib/asciidoctor/rx.rb +723 -0
  82. data/lib/asciidoctor/section.rb +17 -16
  83. data/lib/asciidoctor/stylesheets.rb +19 -37
  84. data/lib/asciidoctor/substitutors.rb +926 -1022
  85. data/lib/asciidoctor/syntax_highlighter/coderay.rb +88 -0
  86. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +34 -0
  87. data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
  88. data/lib/asciidoctor/syntax_highlighter/prettify.rb +30 -0
  89. data/lib/asciidoctor/syntax_highlighter/pygments.rb +157 -0
  90. data/lib/asciidoctor/syntax_highlighter/rouge.rb +143 -0
  91. data/lib/asciidoctor/syntax_highlighter.rb +253 -0
  92. data/lib/asciidoctor/table.rb +152 -114
  93. data/lib/asciidoctor/timings.rb +7 -5
  94. data/lib/asciidoctor/version.rb +2 -1
  95. data/lib/asciidoctor/writer.rb +30 -0
  96. data/lib/asciidoctor.rb +266 -1340
  97. data/man/asciidoctor.1 +49 -47
  98. data/man/asciidoctor.adoc +54 -45
  99. metadata +50 -245
  100. data/CONTRIBUTING.adoc +0 -185
  101. data/Gemfile +0 -60
  102. data/Rakefile +0 -129
  103. data/bin/asciidoctor-safe +0 -15
  104. data/features/open_block.feature +0 -92
  105. data/features/pass_block.feature +0 -66
  106. data/features/step_definitions.rb +0 -49
  107. data/features/text_formatting.feature +0 -57
  108. data/features/xref.feature +0 -1039
  109. data/lib/asciidoctor/converter/base.rb +0 -59
  110. data/lib/asciidoctor/converter/docbook45.rb +0 -93
  111. data/lib/asciidoctor/converter/factory.rb +0 -226
  112. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
  113. data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
  114. data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
  115. data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
  116. data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
  117. data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
  118. data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
  119. data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
  120. data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
  121. data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
  122. data/test/api_test.rb +0 -1240
  123. data/test/attribute_list_test.rb +0 -242
  124. data/test/attributes_test.rb +0 -1623
  125. data/test/blocks_test.rb +0 -3870
  126. data/test/converter_test.rb +0 -470
  127. data/test/document_test.rb +0 -1853
  128. data/test/extensions_test.rb +0 -1560
  129. data/test/fixtures/asciidoc_index.txt +0 -521
  130. data/test/fixtures/basic-docinfo-footer.html +0 -6
  131. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  132. data/test/fixtures/basic-docinfo.html +0 -1
  133. data/test/fixtures/basic-docinfo.xml +0 -4
  134. data/test/fixtures/basic.asciidoc +0 -5
  135. data/test/fixtures/chapter-a.adoc +0 -3
  136. data/test/fixtures/child-include.adoc +0 -5
  137. data/test/fixtures/circle.svg +0 -9
  138. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  139. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  140. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  141. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  142. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  143. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  144. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  145. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  146. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  147. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  148. data/test/fixtures/docinfo-footer.html +0 -1
  149. data/test/fixtures/docinfo-footer.xml +0 -9
  150. data/test/fixtures/docinfo.html +0 -1
  151. data/test/fixtures/docinfo.xml +0 -3
  152. data/test/fixtures/doctime-localtime.adoc +0 -2
  153. data/test/fixtures/dot.gif +0 -0
  154. data/test/fixtures/encoding.asciidoc +0 -13
  155. data/test/fixtures/file-with-missing-include.adoc +0 -1
  156. data/test/fixtures/grandchild-include.adoc +0 -3
  157. data/test/fixtures/hello-asciidoctor.pdf +0 -69
  158. data/test/fixtures/include-file.asciidoc +0 -24
  159. data/test/fixtures/include-file.jsx +0 -8
  160. data/test/fixtures/include-file.ml +0 -3
  161. data/test/fixtures/include-file.xml +0 -5
  162. data/test/fixtures/lists.adoc +0 -96
  163. data/test/fixtures/master.adoc +0 -5
  164. data/test/fixtures/mismatched-end-tag.adoc +0 -7
  165. data/test/fixtures/other-chapters.adoc +0 -11
  166. data/test/fixtures/outer-include.adoc +0 -5
  167. data/test/fixtures/parent-include-restricted.adoc +0 -5
  168. data/test/fixtures/parent-include.adoc +0 -5
  169. data/test/fixtures/sample.asciidoc +0 -30
  170. data/test/fixtures/section-a.adoc +0 -4
  171. data/test/fixtures/stylesheets/custom.css +0 -3
  172. data/test/fixtures/subdir/index.adoc +0 -3
  173. data/test/fixtures/subdir/inner-include.adoc +0 -3
  174. data/test/fixtures/subdir/middle-include.adoc +0 -5
  175. data/test/fixtures/subs-docinfo.html +0 -2
  176. data/test/fixtures/subs.adoc +0 -6
  177. data/test/fixtures/tagged-class-enclosed.rb +0 -25
  178. data/test/fixtures/tagged-class.rb +0 -23
  179. data/test/fixtures/tip.gif +0 -0
  180. data/test/fixtures/unclosed-tag.adoc +0 -3
  181. data/test/fixtures/unexpected-end-tag.adoc +0 -4
  182. data/test/invoker_test.rb +0 -745
  183. data/test/links_test.rb +0 -855
  184. data/test/lists_test.rb +0 -5151
  185. data/test/logger_test.rb +0 -211
  186. data/test/manpage_test.rb +0 -660
  187. data/test/options_test.rb +0 -262
  188. data/test/paragraphs_test.rb +0 -562
  189. data/test/parser_test.rb +0 -742
  190. data/test/paths_test.rb +0 -395
  191. data/test/preamble_test.rb +0 -173
  192. data/test/reader_test.rb +0 -2161
  193. data/test/sections_test.rb +0 -3575
  194. data/test/substitutions_test.rb +0 -2066
  195. data/test/tables_test.rb +0 -2036
  196. data/test/test_helper.rb +0 -447
  197. data/test/text_test.rb +0 -309
@@ -1,2066 +0,0 @@
1
- # encoding: UTF-8
2
- unless defined? ASCIIDOCTOR_PROJECT_DIR
3
- $: << File.dirname(__FILE__); $:.uniq!
4
- require 'test_helper'
5
- end
6
-
7
- # TODO
8
- # - test negatives
9
- # - test role on every quote type
10
- context 'Substitutions' do
11
- BACKSLASH = %(\x5c)
12
- context 'Dispatcher' do
13
- test 'apply normal substitutions' do
14
- para = block_from_string("[blue]_http://asciidoc.org[AsciiDoc]_ & [red]*Ruby*\n&#167; Making +++<u>documentation</u>+++ together +\nsince (C) {inception_year}.")
15
- para.document.attributes['inception_year'] = '2012'
16
- result = para.apply_subs(para.source)
17
- assert_equal %{<em class="blue"><a href="http://asciidoc.org">AsciiDoc</a></em> &amp; <strong class="red">Ruby</strong>\n&#167; Making <u>documentation</u> together<br>\nsince &#169; 2012.}, result
18
- end
19
-
20
- test 'apply_subs should not modify string directly' do
21
- input = '<html> -- the root of all web'
22
- para = block_from_string input
23
- para_source = para.source
24
- result = para.apply_subs para_source
25
- assert_equal '&lt;html&gt;&#8201;&#8212;&#8201;the root of all web', result
26
- assert_equal input, para_source
27
- end
28
-
29
- test 'should not drop trailing blank lines when performing substitutions' do
30
- para = block_from_string %([%hardbreaks]\nthis\nis\n-> {program})
31
- para.lines << ''
32
- para.lines << ''
33
- para.document.attributes['program'] = 'Asciidoctor'
34
- result = para.apply_subs(para.lines)
35
- assert_equal ['this<br>', 'is<br>', '&#8594; Asciidoctor<br>', '<br>', ''], result
36
- result = para.apply_subs(para.lines * "\n")
37
- assert_equal %(this<br>\nis<br>\n&#8594; Asciidoctor<br>\n<br>\n), result
38
- end
39
-
40
- test 'should expand subs passe to expand_subs' do
41
- para = block_from_string %({program}\n*bold*\n2 > 1)
42
- para.document.attributes['program'] = 'Asciidoctor'
43
- assert_equal [:specialcharacters], (para.expand_subs [:specialchars])
44
- refute para.expand_subs([:none])
45
- assert_equal [:specialcharacters, :quotes, :attributes, :replacements, :macros, :post_replacements], (para.expand_subs [:normal])
46
- end
47
-
48
- test 'apply_subs should allow the subs argument to be nil' do
49
- block = block_from_string %([pass]\n*raw*)
50
- result = block.apply_subs block.source, nil
51
- assert_equal '*raw*', result
52
- end
53
- end
54
-
55
- context 'Quotes' do
56
- test 'single-line double-quoted string' do
57
- para = block_from_string(%q{``a few quoted words''}, :attributes => {'compat-mode' => ''})
58
- assert_equal '&#8220;a few quoted words&#8221;', para.sub_quotes(para.source)
59
-
60
- para = block_from_string(%q{"`a few quoted words`"})
61
- assert_equal '&#8220;a few quoted words&#8221;', para.sub_quotes(para.source)
62
-
63
- para = block_from_string(%q{"`a few quoted words`"}, :backend => 'docbook')
64
- assert_equal '<quote>a few quoted words</quote>', para.sub_quotes(para.source)
65
- end
66
-
67
- test 'escaped single-line double-quoted string' do
68
- para = block_from_string %(#{BACKSLASH}``a few quoted words''), :attributes => {'compat-mode' => ''}
69
- assert_equal %q(&#8216;`a few quoted words&#8217;'), para.sub_quotes(para.source)
70
-
71
- para = block_from_string %(#{BACKSLASH * 2}``a few quoted words''), :attributes => {'compat-mode' => ''}
72
- assert_equal %q(``a few quoted words''), para.sub_quotes(para.source)
73
-
74
- para = block_from_string(%(#{BACKSLASH}"`a few quoted words`"))
75
- assert_equal %q("`a few quoted words`"), para.sub_quotes(para.source)
76
-
77
- para = block_from_string(%(#{BACKSLASH * 2}"`a few quoted words`"))
78
- assert_equal %(#{BACKSLASH}"`a few quoted words`"), para.sub_quotes(para.source)
79
- end
80
-
81
- test 'multi-line double-quoted string' do
82
- para = block_from_string(%Q{``a few\nquoted words''}, :attributes => {'compat-mode' => ''})
83
- assert_equal "&#8220;a few\nquoted words&#8221;", para.sub_quotes(para.source)
84
-
85
- para = block_from_string(%Q{"`a few\nquoted words`"})
86
- assert_equal "&#8220;a few\nquoted words&#8221;", para.sub_quotes(para.source)
87
- end
88
-
89
- test 'double-quoted string with inline single quote' do
90
- para = block_from_string(%q{``Here's Johnny!''}, :attributes => {'compat-mode' => ''})
91
- assert_equal %q{&#8220;Here's Johnny!&#8221;}, para.sub_quotes(para.source)
92
-
93
- para = block_from_string(%q{"`Here's Johnny!`"})
94
- assert_equal %q{&#8220;Here's Johnny!&#8221;}, para.sub_quotes(para.source)
95
- end
96
-
97
- test 'double-quoted string with inline backquote' do
98
- para = block_from_string(%q{``Here`s Johnny!''}, :attributes => {'compat-mode' => ''})
99
- assert_equal %q{&#8220;Here`s Johnny!&#8221;}, para.sub_quotes(para.source)
100
-
101
- para = block_from_string(%q{"`Here`s Johnny!`"})
102
- assert_equal %q{&#8220;Here`s Johnny!&#8221;}, para.sub_quotes(para.source)
103
- end
104
-
105
- test 'double-quoted string around monospaced text' do
106
- para = block_from_string(%q("``E=mc^2^` is the solution!`"))
107
- assert_equal %q(&#8220;`E=mc<sup>2</sup>` is the solution!&#8221;), para.apply_subs(para.source);
108
-
109
- para = block_from_string(%q("```E=mc^2^`` is the solution!`"))
110
- assert_equal %q(&#8220;<code>E=mc<sup>2</sup></code> is the solution!&#8221;), para.apply_subs(para.source);
111
- end
112
-
113
- test 'single-line single-quoted string' do
114
- para = block_from_string(%q{`a few quoted words'}, :attributes => {'compat-mode' => ''})
115
- assert_equal '&#8216;a few quoted words&#8217;', para.sub_quotes(para.source)
116
-
117
- para = block_from_string(%q{'`a few quoted words`'})
118
- assert_equal '&#8216;a few quoted words&#8217;', para.sub_quotes(para.source)
119
-
120
- para = block_from_string(%q{'`a few quoted words`'}, :backend => 'docbook')
121
- assert_equal '<quote>a few quoted words</quote>', para.sub_quotes(para.source)
122
- end
123
-
124
- test 'escaped single-line single-quoted string' do
125
- para = block_from_string(%(#{BACKSLASH}`a few quoted words'), :attributes => {'compat-mode' => ''})
126
- assert_equal %(`a few quoted words'), para.sub_quotes(para.source)
127
-
128
- para = block_from_string(%(#{BACKSLASH}'`a few quoted words`'))
129
- assert_equal %('`a few quoted words`'), para.sub_quotes(para.source)
130
- end
131
-
132
- test 'multi-line single-quoted string' do
133
- para = block_from_string(%Q{`a few\nquoted words'}, :attributes => {'compat-mode' => ''})
134
- assert_equal "&#8216;a few\nquoted words&#8217;", para.sub_quotes(para.source)
135
-
136
- para = block_from_string(%Q{'`a few\nquoted words`'})
137
- assert_equal "&#8216;a few\nquoted words&#8217;", para.sub_quotes(para.source)
138
- end
139
-
140
- test 'single-quoted string with inline single quote' do
141
- para = block_from_string(%q{`That isn't what I did.'}, :attributes => {'compat-mode' => ''})
142
- assert_equal %q{&#8216;That isn't what I did.&#8217;}, para.sub_quotes(para.source)
143
-
144
- para = block_from_string(%q{'`That isn't what I did.`'})
145
- assert_equal %q{&#8216;That isn't what I did.&#8217;}, para.sub_quotes(para.source)
146
- end
147
-
148
- test 'single-quoted string with inline backquote' do
149
- para = block_from_string(%q{`Here`s Johnny!'}, :attributes => {'compat-mode' => ''})
150
- assert_equal %q{&#8216;Here`s Johnny!&#8217;}, para.sub_quotes(para.source)
151
-
152
- para = block_from_string(%q{'`Here`s Johnny!`'})
153
- assert_equal %q{&#8216;Here`s Johnny!&#8217;}, para.sub_quotes(para.source)
154
- end
155
-
156
- test 'single-line constrained marked string' do
157
- #para = block_from_string(%q{#a few words#}, :attributes => {'compat-mode' => ''})
158
- #assert_equal 'a few words', para.sub_quotes(para.source)
159
-
160
- para = block_from_string(%q{#a few words#})
161
- assert_equal '<mark>a few words</mark>', para.sub_quotes(para.source)
162
- end
163
-
164
- test 'escaped single-line constrained marked string' do
165
- para = block_from_string(%(#{BACKSLASH}#a few words#))
166
- assert_equal '#a few words#', para.sub_quotes(para.source)
167
- end
168
-
169
- test 'multi-line constrained marked string' do
170
- #para = block_from_string(%Q{#a few\nwords#}, :attributes => {'compat-mode' => ''})
171
- #assert_equal "a few\nwords", para.sub_quotes(para.source)
172
-
173
- para = block_from_string(%Q{#a few\nwords#})
174
- assert_equal "<mark>a few\nwords</mark>", para.sub_quotes(para.source)
175
- end
176
-
177
- test 'constrained marked string should not match entity references' do
178
- para = block_from_string('111 #mark a# 222 "`quote a`" 333 #mark b# 444')
179
- assert_equal %(111 <mark>mark a</mark> 222 &#8220;quote a&#8221; 333 <mark>mark b</mark> 444), para.sub_quotes(para.source)
180
- end
181
-
182
- test 'single-line unconstrained marked string' do
183
- #para = block_from_string(%q{##--anything goes ##}, :attributes => {'compat-mode' => ''})
184
- #assert_equal '--anything goes ', para.sub_quotes(para.source)
185
-
186
- para = block_from_string(%q{##--anything goes ##})
187
- assert_equal '<mark>--anything goes </mark>', para.sub_quotes(para.source)
188
- end
189
-
190
- test 'escaped single-line unconstrained marked string' do
191
- para = block_from_string(%(#{BACKSLASH}#{BACKSLASH}##--anything goes ##))
192
- assert_equal '##--anything goes ##', para.sub_quotes(para.source)
193
- end
194
-
195
- test 'multi-line unconstrained marked string' do
196
- #para = block_from_string(%Q{##--anything\ngoes ##}, :attributes => {'compat-mode' => ''})
197
- #assert_equal "--anything\ngoes ", para.sub_quotes(para.source)
198
-
199
- para = block_from_string(%Q{##--anything\ngoes ##})
200
- assert_equal "<mark>--anything\ngoes </mark>", para.sub_quotes(para.source)
201
- end
202
-
203
- test 'single-line constrained marked string with role' do
204
- para = block_from_string(%q{[statement]#a few words#})
205
- assert_equal '<span class="statement">a few words</span>', para.sub_quotes(para.source)
206
- end
207
-
208
- test 'single-line constrained strong string' do
209
- para = block_from_string(%q{*a few strong words*})
210
- assert_equal '<strong>a few strong words</strong>', para.sub_quotes(para.source)
211
- end
212
-
213
- test 'escaped single-line constrained strong string' do
214
- para = block_from_string(%(#{BACKSLASH}*a few strong words*))
215
- assert_equal '*a few strong words*', para.sub_quotes(para.source)
216
- end
217
-
218
- test 'multi-line constrained strong string' do
219
- para = block_from_string(%Q{*a few\nstrong words*})
220
- assert_equal "<strong>a few\nstrong words</strong>", para.sub_quotes(para.source)
221
- end
222
-
223
- test 'constrained strong string containing an asterisk' do
224
- para = block_from_string(%q{*bl*ck*-eye})
225
- assert_equal '<strong>bl*ck</strong>-eye', para.sub_quotes(para.source)
226
- end
227
-
228
- test 'constrained strong string containing an asterisk and multibyte word chars' do
229
- para = block_from_string(%q{*黑*眼圈*})
230
- assert_equal '<strong>黑*眼圈</strong>', para.sub_quotes(para.source)
231
- end if ::RUBY_MIN_VERSION_1_9
232
-
233
- test 'single-line constrained quote variation emphasized string' do
234
- para = block_from_string(%q{_a few emphasized words_})
235
- assert_equal '<em>a few emphasized words</em>', para.sub_quotes(para.source)
236
- end
237
-
238
- test 'escaped single-line constrained quote variation emphasized string' do
239
- para = block_from_string(%(#{BACKSLASH}_a few emphasized words_))
240
- assert_equal %q(_a few emphasized words_), para.sub_quotes(para.source)
241
- end
242
-
243
- test 'escaped single quoted string' do
244
- para = block_from_string(%(#{BACKSLASH}'a few emphasized words'))
245
- # NOTE the \' is replaced with ' by the :replacements substitution, later in the substitution pipeline
246
- assert_equal %(#{BACKSLASH}'a few emphasized words'), para.sub_quotes(para.source)
247
- end
248
-
249
- test 'multi-line constrained emphasized quote variation string' do
250
- para = block_from_string(%Q{_a few\nemphasized words_})
251
- assert_equal "<em>a few\nemphasized words</em>", para.sub_quotes(para.source)
252
- end
253
-
254
- test 'single-quoted string containing an emphasized phrase' do
255
- para = block_from_string(%q{`I told him, 'Just go for it!''}, :attributes => {'compat-mode' => ''})
256
- assert_equal '&#8216;I told him, <em>Just go for it!</em>&#8217;', para.sub_quotes(para.source)
257
-
258
- para = block_from_string(%q{'`I told him, 'Just go for it!'`'})
259
- assert_equal %q(&#8216;I told him, 'Just go for it!'&#8217;), para.sub_quotes(para.source)
260
- end
261
-
262
- test 'escaped single-quotes inside emphasized words are restored' do
263
- para = block_from_string(%('Here#{BACKSLASH}'s Johnny!'), :attributes => {'compat-mode' => ''})
264
- assert_equal %q(<em>Here's Johnny!</em>), para.apply_subs(para.source)
265
-
266
- para = block_from_string(%('Here#{BACKSLASH}'s Johnny!'))
267
- assert_equal %q('Here's Johnny!'), para.apply_subs(para.source)
268
- end
269
-
270
- test 'single-line constrained emphasized underline variation string' do
271
- para = block_from_string(%q{_a few emphasized words_})
272
- assert_equal '<em>a few emphasized words</em>', para.sub_quotes(para.source)
273
- end
274
-
275
- test 'escaped single-line constrained emphasized underline variation string' do
276
- para = block_from_string(%(#{BACKSLASH}_a few emphasized words_))
277
- assert_equal '_a few emphasized words_', para.sub_quotes(para.source)
278
- end
279
-
280
- test 'multi-line constrained emphasized underline variation string' do
281
- para = block_from_string(%Q{_a few\nemphasized words_})
282
- assert_equal "<em>a few\nemphasized words</em>", para.sub_quotes(para.source)
283
- end
284
-
285
- # NOTE must use apply_subs because constrained monospaced is handled as a passthrough
286
- test 'single-line constrained monospaced string' do
287
- para = block_from_string(%(`a few <{monospaced}> words`), :attributes => {'monospaced' => 'monospaced', 'compat-mode' => ''})
288
- assert_equal '<code>a few &lt;{monospaced}&gt; words</code>', para.apply_subs(para.source)
289
-
290
- para = block_from_string(%(`a few <{monospaced}> words`), :attributes => {'monospaced' => 'monospaced'})
291
- assert_equal '<code>a few &lt;monospaced&gt; words</code>', para.apply_subs(para.source)
292
- end
293
-
294
- # NOTE must use apply_subs because constrained monospaced is handled as a passthrough
295
- test 'single-line constrained monospaced string with role' do
296
- para = block_from_string(%([input]`a few <{monospaced}> words`), :attributes => {'monospaced' => 'monospaced', 'compat-mode' => ''})
297
- assert_equal '<code class="input">a few &lt;{monospaced}&gt; words</code>', para.apply_subs(para.source)
298
-
299
- para = block_from_string(%([input]`a few <{monospaced}> words`), :attributes => {'monospaced' => 'monospaced'})
300
- assert_equal '<code class="input">a few &lt;monospaced&gt; words</code>', para.apply_subs(para.source)
301
- end
302
-
303
- # NOTE must use apply_subs because constrained monospaced is handled as a passthrough
304
- test 'escaped single-line constrained monospaced string' do
305
- para = block_from_string(%(#{BACKSLASH}`a few <monospaced> words`), :attributes => {'compat-mode' => ''})
306
- assert_equal '`a few &lt;monospaced&gt; words`', para.apply_subs(para.source)
307
-
308
- para = block_from_string(%(#{BACKSLASH}`a few <monospaced> words`))
309
- assert_equal '`a few &lt;monospaced&gt; words`', para.apply_subs(para.source)
310
- end
311
-
312
- # NOTE must use apply_subs because constrained monospaced is handled as a passthrough
313
- test 'escaped single-line constrained monospaced string with role' do
314
- para = block_from_string(%([input]#{BACKSLASH}`a few <monospaced> words`), :attributes => {'compat-mode' => ''})
315
- assert_equal '[input]`a few &lt;monospaced&gt; words`', para.apply_subs(para.source)
316
-
317
- para = block_from_string(%([input]#{BACKSLASH}`a few <monospaced> words`))
318
- assert_equal '[input]`a few &lt;monospaced&gt; words`', para.apply_subs(para.source)
319
- end
320
-
321
- # NOTE must use apply_subs because constrained monospaced is handled as a passthrough
322
- test 'escaped role on single-line constrained monospaced string' do
323
- para = block_from_string(%(#{BACKSLASH}[input]`a few <monospaced> words`), :attributes => {'compat-mode' => ''})
324
- assert_equal '[input]<code>a few &lt;monospaced&gt; words</code>', para.apply_subs(para.source)
325
-
326
- para = block_from_string(%(#{BACKSLASH}[input]`a few <monospaced> words`))
327
- assert_equal '[input]<code>a few &lt;monospaced&gt; words</code>', para.apply_subs(para.source)
328
- end
329
-
330
- # NOTE must use apply_subs because constrained monospaced is handled as a passthrough
331
- test 'escaped role on escaped single-line constrained monospaced string' do
332
- para = block_from_string(%(#{BACKSLASH}[input]#{BACKSLASH}`a few <monospaced> words`), :attributes => {'compat-mode' => ''})
333
- assert_equal %(#{BACKSLASH}[input]`a few &lt;monospaced&gt; words`), para.apply_subs(para.source)
334
-
335
- para = block_from_string(%(#{BACKSLASH}[input]#{BACKSLASH}`a few <monospaced> words`))
336
- assert_equal %(#{BACKSLASH}[input]`a few &lt;monospaced&gt; words`), para.apply_subs(para.source)
337
- end
338
-
339
- # NOTE must use apply_subs because constrained monospaced is handled as a passthrough
340
- test 'multi-line constrained monospaced string' do
341
- para = block_from_string(%(`a few\n<{monospaced}> words`), :attributes => {'monospaced' => 'monospaced', 'compat-mode' => ''})
342
- assert_equal "<code>a few\n&lt;{monospaced}&gt; words</code>", para.apply_subs(para.source)
343
-
344
- para = block_from_string(%(`a few\n<{monospaced}> words`), :attributes => {'monospaced' => 'monospaced'})
345
- assert_equal "<code>a few\n&lt;monospaced&gt; words</code>", para.apply_subs(para.source)
346
- end
347
-
348
- test 'single-line unconstrained strong chars' do
349
- para = block_from_string(%q{**Git**Hub})
350
- assert_equal '<strong>Git</strong>Hub', para.sub_quotes(para.source)
351
- end
352
-
353
- test 'escaped single-line unconstrained strong chars' do
354
- para = block_from_string(%(#{BACKSLASH}**Git**Hub))
355
- assert_equal '<strong>*Git</strong>*Hub', para.sub_quotes(para.source)
356
- end
357
-
358
- test 'multi-line unconstrained strong chars' do
359
- para = block_from_string(%Q{**G\ni\nt\n**Hub})
360
- assert_equal "<strong>G\ni\nt\n</strong>Hub", para.sub_quotes(para.source)
361
- end
362
-
363
- test 'unconstrained strong chars with inline asterisk' do
364
- para = block_from_string(%q{**bl*ck**-eye})
365
- assert_equal '<strong>bl*ck</strong>-eye', para.sub_quotes(para.source)
366
- end
367
-
368
- test 'unconstrained strong chars with role' do
369
- para = block_from_string(%q{Git[blue]**Hub**})
370
- assert_equal %q{Git<strong class="blue">Hub</strong>}, para.sub_quotes(para.source)
371
- end
372
-
373
- # TODO this is not the same result as AsciiDoc, though I don't understand why AsciiDoc gets what it gets
374
- test 'escaped unconstrained strong chars with role' do
375
- para = block_from_string(%(Git#{BACKSLASH}[blue]**Hub**))
376
- assert_equal %q{Git[blue]<strong>*Hub</strong>*}, para.sub_quotes(para.source)
377
- end
378
-
379
- test 'single-line unconstrained emphasized chars' do
380
- para = block_from_string(%q{__Git__Hub})
381
- assert_equal '<em>Git</em>Hub', para.sub_quotes(para.source)
382
- end
383
-
384
- test 'escaped single-line unconstrained emphasized chars' do
385
- para = block_from_string(%(#{BACKSLASH}__Git__Hub))
386
- assert_equal '__Git__Hub', para.sub_quotes(para.source)
387
- end
388
-
389
- test 'escaped single-line unconstrained emphasized chars around word' do
390
- para = block_from_string(%(#{BACKSLASH}#{BACKSLASH}__GitHub__))
391
- assert_equal '__GitHub__', para.sub_quotes(para.source)
392
- end
393
-
394
- test 'multi-line unconstrained emphasized chars' do
395
- para = block_from_string(%Q{__G\ni\nt\n__Hub})
396
- assert_equal "<em>G\ni\nt\n</em>Hub", para.sub_quotes(para.source)
397
- end
398
-
399
- test 'unconstrained emphasis chars with role' do
400
- para = block_from_string(%q{[gray]__Git__Hub})
401
- assert_equal %q{<em class="gray">Git</em>Hub}, para.sub_quotes(para.source)
402
- end
403
-
404
- test 'escaped unconstrained emphasis chars with role' do
405
- para = block_from_string(%(#{BACKSLASH}[gray]__Git__Hub))
406
- assert_equal %q{[gray]__Git__Hub}, para.sub_quotes(para.source)
407
- end
408
-
409
- test 'single-line constrained monospaced chars' do
410
- para = block_from_string(%q{call +save()+ to persist the changes}, :attributes => {'compat-mode' => ''})
411
- assert_equal 'call <code>save()</code> to persist the changes', para.sub_quotes(para.source)
412
-
413
- para = block_from_string(%q{call [x-]+save()+ to persist the changes})
414
- assert_equal 'call <code>save()</code> to persist the changes', para.apply_subs(para.source)
415
-
416
- para = block_from_string(%q{call `save()` to persist the changes})
417
- assert_equal 'call <code>save()</code> to persist the changes', para.sub_quotes(para.source)
418
- end
419
-
420
- test 'single-line constrained monospaced chars with role' do
421
- para = block_from_string(%q{call [method]+save()+ to persist the changes}, :attributes => {'compat-mode' => ''})
422
- assert_equal 'call <code class="method">save()</code> to persist the changes', para.sub_quotes(para.source)
423
-
424
- para = block_from_string(%q{call [method x-]+save()+ to persist the changes})
425
- assert_equal 'call <code class="method">save()</code> to persist the changes', para.apply_subs(para.source)
426
-
427
- para = block_from_string(%q{call [method]`save()` to persist the changes})
428
- assert_equal 'call <code class="method">save()</code> to persist the changes', para.sub_quotes(para.source)
429
- end
430
-
431
- test 'escaped single-line constrained monospaced chars' do
432
- para = block_from_string(%(call #{BACKSLASH}+save()+ to persist the changes), :attributes => {'compat-mode' => ''})
433
- assert_equal 'call +save()+ to persist the changes', para.sub_quotes(para.source)
434
-
435
- para = block_from_string(%(call #{BACKSLASH}`save()` to persist the changes))
436
- assert_equal 'call `save()` to persist the changes', para.sub_quotes(para.source)
437
- end
438
-
439
- test 'escaped single-line constrained monospaced chars with role' do
440
- para = block_from_string(%(call [method]#{BACKSLASH}+save()+ to persist the changes), :attributes => {'compat-mode' => ''})
441
- assert_equal 'call [method]+save()+ to persist the changes', para.sub_quotes(para.source)
442
-
443
- para = block_from_string(%(call [method]#{BACKSLASH}`save()` to persist the changes))
444
- assert_equal 'call [method]`save()` to persist the changes', para.sub_quotes(para.source)
445
- end
446
-
447
- test 'escaped role on single-line constrained monospaced chars' do
448
- para = block_from_string(%(call #{BACKSLASH}[method]+save()+ to persist the changes), :attributes => {'compat-mode' => ''})
449
- assert_equal 'call [method]<code>save()</code> to persist the changes', para.sub_quotes(para.source)
450
-
451
- para = block_from_string(%(call #{BACKSLASH}[method]`save()` to persist the changes))
452
- assert_equal 'call [method]<code>save()</code> to persist the changes', para.sub_quotes(para.source)
453
- end
454
-
455
- test 'escaped role on escaped single-line constrained monospaced chars' do
456
- para = block_from_string(%(call #{BACKSLASH}[method]#{BACKSLASH}+save()+ to persist the changes), :attributes => {'compat-mode' => ''})
457
- assert_equal %(call #{BACKSLASH}[method]+save()+ to persist the changes), para.sub_quotes(para.source)
458
-
459
- para = block_from_string(%(call #{BACKSLASH}[method]#{BACKSLASH}`save()` to persist the changes))
460
- assert_equal %(call #{BACKSLASH}[method]`save()` to persist the changes), para.sub_quotes(para.source)
461
- end
462
-
463
- test 'single-line unconstrained monospaced chars' do
464
- para = block_from_string(%q{Git++Hub++}, :attributes => {'compat-mode' => ''})
465
- assert_equal 'Git<code>Hub</code>', para.sub_quotes(para.source)
466
-
467
- para = block_from_string(%q{Git[x-]++Hub++})
468
- assert_equal 'Git<code>Hub</code>', para.apply_subs(para.source)
469
-
470
- para = block_from_string(%q{Git``Hub``})
471
- assert_equal 'Git<code>Hub</code>', para.sub_quotes(para.source)
472
- end
473
-
474
- test 'escaped single-line unconstrained monospaced chars' do
475
- para = block_from_string(%(Git#{BACKSLASH}++Hub++), :attributes => {'compat-mode' => ''})
476
- assert_equal 'Git+<code>Hub</code>+', para.sub_quotes(para.source)
477
-
478
- para = block_from_string(%(Git#{BACKSLASH * 2}++Hub++), :attributes => {'compat-mode' => ''})
479
- assert_equal 'Git++Hub++', para.sub_quotes(para.source)
480
-
481
- para = block_from_string(%(Git#{BACKSLASH}``Hub``))
482
- assert_equal 'Git``Hub``', para.sub_quotes(para.source)
483
- end
484
-
485
- test 'multi-line unconstrained monospaced chars' do
486
- para = block_from_string(%Q{Git++\nH\nu\nb++}, :attributes => {'compat-mode' => ''})
487
- assert_equal "Git<code>\nH\nu\nb</code>", para.sub_quotes(para.source)
488
-
489
- para = block_from_string(%Q{Git[x-]++\nH\nu\nb++})
490
- assert_equal %(Git<code>\nH\nu\nb</code>), para.apply_subs(para.source)
491
-
492
- para = block_from_string(%Q{Git``\nH\nu\nb``})
493
- assert_equal "Git<code>\nH\nu\nb</code>", para.sub_quotes(para.source)
494
- end
495
-
496
- test 'single-line superscript chars' do
497
- para = block_from_string(%(x^2^ = x * x, e = mc^2^, there's a 1^st^ time for everything))
498
- assert_equal %(x<sup>2</sup> = x * x, e = mc<sup>2</sup>, there\'s a 1<sup>st</sup> time for everything), para.sub_quotes(para.source)
499
- end
500
-
501
- test 'escaped single-line superscript chars' do
502
- para = block_from_string(%(x#{BACKSLASH}^2^ = x * x))
503
- assert_equal 'x^2^ = x * x', para.sub_quotes(para.source)
504
- end
505
-
506
- test 'does not match superscript across whitespace' do
507
- para = block_from_string(%Q{x^(n\n-\n1)^})
508
- assert_equal para.source, para.sub_quotes(para.source)
509
- end
510
-
511
- test 'does not match adjacent superscript chars' do
512
- para = block_from_string 'a ^^ b'
513
- assert_equal 'a ^^ b', para.sub_quotes(para.source)
514
- end
515
-
516
- test 'does not confuse superscript and links with blank window shorthand' do
517
- para = block_from_string(%Q{http://localhost[Text^] on the 21^st^ and 22^nd^})
518
- assert_equal '<a href="http://localhost" target="_blank" rel="noopener">Text</a> on the 21<sup>st</sup> and 22<sup>nd</sup>', para.content
519
- end
520
-
521
- test 'single-line subscript chars' do
522
- para = block_from_string(%q{H~2~O})
523
- assert_equal 'H<sub>2</sub>O', para.sub_quotes(para.source)
524
- end
525
-
526
- test 'escaped single-line subscript chars' do
527
- para = block_from_string(%(H#{BACKSLASH}~2~O))
528
- assert_equal 'H~2~O', para.sub_quotes(para.source)
529
- end
530
-
531
- test 'does not match subscript across whitespace' do
532
- para = block_from_string(%Q{project~ view\non\nGitHub~})
533
- assert_equal para.source, para.sub_quotes(para.source)
534
- end
535
-
536
- test 'does not match adjacent subscript chars' do
537
- para = block_from_string 'a ~~ b'
538
- assert_equal 'a ~~ b', para.sub_quotes(para.source)
539
- end
540
-
541
- test 'does not match subscript across distinct URLs' do
542
- para = block_from_string(%Q{http://www.abc.com/~def[DEF] and http://www.abc.com/~ghi[GHI]})
543
- assert_equal para.source, para.sub_quotes(para.source)
544
- end
545
-
546
- test 'quoted text with role shorthand' do
547
- para = block_from_string(%q{[.white.red-background]#alert#})
548
- assert_equal '<span class="white red-background">alert</span>', para.sub_quotes(para.source)
549
- end
550
-
551
- test 'quoted text with id shorthand' do
552
- para = block_from_string(%q{[#bond]#007#})
553
- assert_equal '<span id="bond">007</span>', para.sub_quotes(para.source)
554
- end
555
-
556
- test 'quoted text with id and role shorthand' do
557
- para = block_from_string(%q{[#bond.white.red-background]#007#})
558
- assert_equal '<span id="bond" class="white red-background">007</span>', para.sub_quotes(para.source)
559
- end
560
-
561
- test 'quoted text with id and role shorthand using docbook backend' do
562
- para = block_from_string(%q{[#bond.white.red-background]#007#}, :backend => 'docbook45')
563
- assert_equal '<anchor id="bond" xreflabel="007"/><phrase role="white red-background">007</phrase>', para.sub_quotes(para.source)
564
- end
565
-
566
- test 'should ignore attributes after comma' do
567
- para = block_from_string(%q{[red, foobar]#alert#})
568
- assert_equal '<span class="red">alert</span>', para.sub_quotes(para.source)
569
- end
570
-
571
- test 'inline passthrough with id and role set using shorthand' do
572
- para = block_from_string '[#id.role]+pass+'
573
- # FIXME id should be propogated
574
- assert_equal '<span class="role">pass</span>', para.content
575
- end
576
-
577
- test 'should assign role attribute when shorthand style contains a role' do
578
- para = block_from_string 'blah'
579
- result = para.parse_quoted_text_attributes '.red#idref'
580
- expect = {'id' => 'idref', 'role' => 'red'}
581
- assert_equal expect, result
582
- end
583
-
584
- test 'should not assign role attribute if shorthand style has no roles' do
585
- para = block_from_string 'blah'
586
- result = para.parse_quoted_text_attributes '#idref'
587
- expect = {'id' => 'idref'}
588
- assert_equal expect, result
589
- end
590
- end
591
-
592
- context 'Macros' do
593
- test 'a single-line link macro should be interpreted as a link' do
594
- para = block_from_string('link:/home.html[]')
595
- assert_equal %q{<a href="/home.html" class="bare">/home.html</a>}, para.sub_macros(para.source)
596
- end
597
-
598
- test 'a single-line link macro with text should be interpreted as a link' do
599
- para = block_from_string('link:/home.html[Home]')
600
- assert_equal %q{<a href="/home.html">Home</a>}, para.sub_macros(para.source)
601
- end
602
-
603
- test 'a mailto macro should be interpreted as a mailto link' do
604
- para = block_from_string('mailto:doc.writer@asciidoc.org[]')
605
- assert_equal %q{<a href="mailto:doc.writer@asciidoc.org">doc.writer@asciidoc.org</a>}, para.sub_macros(para.source)
606
- end
607
-
608
- test 'a mailto macro with text should be interpreted as a mailto link' do
609
- para = block_from_string('mailto:doc.writer@asciidoc.org[Doc Writer]')
610
- assert_equal %q{<a href="mailto:doc.writer@asciidoc.org">Doc Writer</a>}, para.sub_macros(para.source)
611
- end
612
-
613
- test 'a mailto macro with text and subject should be interpreted as a mailto link' do
614
- para = block_from_string('mailto:doc.writer@asciidoc.org[Doc Writer, Pull request]')
615
- assert_equal %q{<a href="mailto:doc.writer@asciidoc.org?subject=Pull%20request">Doc Writer</a>}, para.sub_macros(para.source)
616
- end
617
-
618
- test 'a mailto macro with text, subject and body should be interpreted as a mailto link' do
619
- para = block_from_string('mailto:doc.writer@asciidoc.org[Doc Writer, Pull request, Please accept my pull request]')
620
- assert_equal %q{<a href="mailto:doc.writer@asciidoc.org?subject=Pull%20request&amp;body=Please%20accept%20my%20pull%20request">Doc Writer</a>}, para.sub_macros(para.source)
621
- end
622
-
623
- test 'should recognize inline email addresses' do
624
- para = block_from_string('doc.writer@asciidoc.org')
625
- assert_equal %q{<a href="mailto:doc.writer@asciidoc.org">doc.writer@asciidoc.org</a>}, para.sub_macros(para.source)
626
- para = block_from_string('<doc.writer@asciidoc.org>')
627
- assert_equal %q{&lt;<a href="mailto:doc.writer@asciidoc.org">doc.writer@asciidoc.org</a>&gt;}, para.apply_subs(para.source)
628
- para = block_from_string('author+website@4fs.no')
629
- assert_equal %q{<a href="mailto:author+website@4fs.no">author+website@4fs.no</a>}, para.sub_macros(para.source)
630
- para = block_from_string('john@domain.uk.co')
631
- assert_equal %q{<a href="mailto:john@domain.uk.co">john@domain.uk.co</a>}, para.sub_macros(para.source)
632
- end
633
-
634
- test 'should ignore escaped inline email address' do
635
- para = block_from_string(%(#{BACKSLASH}doc.writer@asciidoc.org))
636
- assert_equal %q{doc.writer@asciidoc.org}, para.sub_macros(para.source)
637
- end
638
-
639
- test 'a single-line raw url should be interpreted as a link' do
640
- para = block_from_string('http://google.com')
641
- assert_equal %q{<a href="http://google.com" class="bare">http://google.com</a>}, para.sub_macros(para.source)
642
- end
643
-
644
- test 'a single-line raw url with text should be interpreted as a link' do
645
- para = block_from_string('http://google.com[Google]')
646
- assert_equal %q{<a href="http://google.com">Google</a>}, para.sub_macros(para.source)
647
- end
648
-
649
- test 'a multi-line raw url with text should be interpreted as a link' do
650
- para = block_from_string("http://google.com[Google\nHomepage]")
651
- assert_equal %{<a href="http://google.com">Google\nHomepage</a>}, para.sub_macros(para.source)
652
- end
653
-
654
- test 'a single-line raw url with attribute as text should be interpreted as a link with resolved attribute' do
655
- para = block_from_string("http://google.com[{google_homepage}]")
656
- para.document.attributes['google_homepage'] = 'Google Homepage'
657
- assert_equal %q{<a href="http://google.com">Google Homepage</a>}, para.sub_macros(para.sub_attributes(para.source))
658
- end
659
-
660
- test 'should not resolve an escaped attribute in link text' do
661
- {
662
- 'http://google.com' => "http://google.com[#{BACKSLASH}{google_homepage}]",
663
- 'http://google.com?q=,' => "link:http://google.com?q=,[#{BACKSLASH}{google_homepage}]"
664
- }.each do |uri, macro|
665
- para = block_from_string macro
666
- para.document.attributes['google_homepage'] = 'Google Homepage'
667
- assert_equal %(<a href="#{uri}">{google_homepage}</a>), para.sub_macros(para.sub_attributes(para.source))
668
- end
669
- end
670
-
671
- test 'a single-line escaped raw url should not be interpreted as a link' do
672
- para = block_from_string(%(#{BACKSLASH}http://google.com))
673
- assert_equal %q{http://google.com}, para.sub_macros(para.source)
674
- end
675
-
676
- test 'a comma separated list of links should not include commas in links' do
677
- para = block_from_string('http://foo.com, http://bar.com, http://example.org')
678
- assert_equal %q{<a href="http://foo.com" class="bare">http://foo.com</a>, <a href="http://bar.com" class="bare">http://bar.com</a>, <a href="http://example.org" class="bare">http://example.org</a>}, para.sub_macros(para.source)
679
- end
680
-
681
- test 'a single-line image macro should be interpreted as an image' do
682
- para = block_from_string('image:tiger.png[]')
683
- assert_equal %{<span class="image"><img src="tiger.png" alt="tiger"></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
684
- end
685
-
686
- test 'should replace underscore and hyphen with space in generated alt text for an inline image' do
687
- para = block_from_string('image:tiger-with-family_1.png[]')
688
- assert_equal %{<span class="image"><img src="tiger-with-family_1.png" alt="tiger with family 1"></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
689
- end
690
-
691
- test 'a single-line image macro with text should be interpreted as an image with alt text' do
692
- para = block_from_string('image:tiger.png[Tiger]')
693
- assert_equal %{<span class="image"><img src="tiger.png" alt="Tiger"></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
694
- end
695
-
696
- test 'should encode special characters in alt text of inline image' do
697
- input = 'A tiger\'s "roar" is < a bear\'s "growl"'
698
- expected = 'A tiger&#8217;s &quot;roar&quot; is &lt; a bear&#8217;s &quot;growl&quot;'
699
- output = (convert_inline_string %(image:tiger-roar.png[#{input}])).gsub(/>\s+</, '><')
700
- assert_equal %(<span class="image"><img src="tiger-roar.png" alt="#{expected}"></span>), output
701
- end
702
-
703
- test 'an image macro with SVG image and text should be interpreted as an image with alt text' do
704
- para = block_from_string('image:tiger.svg[Tiger]')
705
- assert_equal %{<span class="image"><img src="tiger.svg" alt="Tiger"></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
706
- end
707
-
708
- test 'an image macro with an interactive SVG image and alt text should be converted to an object element' do
709
- para = block_from_string('image:tiger.svg[Tiger,opts=interactive]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'imagesdir' => 'images' })
710
- assert_equal %{<span class="image"><object type="image/svg+xml" data="images/tiger.svg"><span class="alt">Tiger</span></object></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
711
- end
712
-
713
- test 'an image macro with an interactive SVG image, fallback and alt text should be converted to an object element' do
714
- para = block_from_string('image:tiger.svg[Tiger,fallback=tiger.png,opts=interactive]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'imagesdir' => 'images' })
715
- assert_equal %{<span class="image"><object type="image/svg+xml" data="images/tiger.svg"><img src="images/tiger.png" alt="Tiger"></object></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
716
- end
717
-
718
- test 'an image macro with an inline SVG image should be converted to an svg element' do
719
- para = block_from_string('image:circle.svg[Tiger,100,opts=inline]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'imagesdir' => 'fixtures', 'docdir' => testdir })
720
- result = para.sub_macros(para.source).gsub(/>\s+</, '><')
721
- assert_match(/<svg\s[^>]*width="100px"[^>]*>/, result)
722
- refute_match(/<svg\s[^>]*width="500px"[^>]*>/, result)
723
- refute_match(/<svg\s[^>]*height="500px"[^>]*>/, result)
724
- refute_match(/<svg\s[^>]*style="width:500px;height:500px"[^>]*>/, result)
725
- end
726
-
727
- test 'an image macro with an inline SVG image should be converted to an svg element even when data-uri is set' do
728
- para = block_from_string('image:circle.svg[Tiger,100,opts=inline]', :safe => Asciidoctor::SafeMode::SERVER, :attributes => { 'data-uri' => '', 'imagesdir' => 'fixtures', 'docdir' => testdir })
729
- assert_match(/<svg\s[^>]*width="100px">/, para.sub_macros(para.source).gsub(/>\s+</, '><'))
730
- end
731
-
732
- test 'an image macro with an SVG image should not use an object element when safe mode is secure' do
733
- para = block_from_string('image:tiger.svg[Tiger,opts=interactive]', :attributes => { 'imagesdir' => 'images' })
734
- assert_equal %{<span class="image"><img src="images/tiger.svg" alt="Tiger"></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
735
- end
736
-
737
- test 'a single-line image macro with text containing escaped square bracket should be interpreted as an image with alt text' do
738
- para = block_from_string(%(image:tiger.png[[Another#{BACKSLASH}] Tiger]))
739
- assert_equal %{<span class="image"><img src="tiger.png" alt="[Another] Tiger"></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
740
- end
741
-
742
- test 'a single-line image macro with text and dimensions should be interpreted as an image with alt text and dimensions' do
743
- para = block_from_string('image:tiger.png[Tiger, 200, 100]')
744
- assert_equal %{<span class="image"><img src="tiger.png" alt="Tiger" width="200" height="100"></span>},
745
- para.sub_macros(para.source).gsub(/>\s+</, '><')
746
- end
747
-
748
- test 'a single-line image macro with text and dimensions should be interpreted as an image with alt text and dimensions in docbook' do
749
- para = block_from_string 'image:tiger.png[Tiger, 200, 100]', :backend => 'docbook'
750
- assert_equal %{<inlinemediaobject><imageobject><imagedata fileref="tiger.png" contentwidth="200" contentdepth="100"/></imageobject><textobject><phrase>Tiger</phrase></textobject></inlinemediaobject>},
751
- para.sub_macros(para.source).gsub(/>\s+</, '><')
752
- end
753
-
754
- test 'a single-line image macro with text and link should be interpreted as a linked image with alt text' do
755
- para = block_from_string('image:tiger.png[Tiger, link="http://en.wikipedia.org/wiki/Tiger"]')
756
- assert_equal %{<span class="image"><a class="image" href="http://en.wikipedia.org/wiki/Tiger"><img src="tiger.png" alt="Tiger"></a></span>},
757
- para.sub_macros(para.source).gsub(/>\s+</, '><')
758
- end
759
-
760
- test 'rel=noopener should be added to an image with a link that targets the _blank window' do
761
- para = block_from_string 'image:tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,window=_blank]'
762
- assert_equal %{<span class="image"><a class="image" href="http://en.wikipedia.org/wiki/Tiger" target="_blank" rel="noopener"><img src="tiger.png" alt="Tiger"></a></span>},
763
- para.sub_macros(para.source).gsub(/>\s+</, '><')
764
- end
765
-
766
- test 'rel=noopener should be added to an image with a link that targets a named window when the noopener option is set' do
767
- para = block_from_string 'image:tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,window=name,opts=noopener]'
768
- assert_equal %{<span class="image"><a class="image" href="http://en.wikipedia.org/wiki/Tiger" target="name" rel="noopener"><img src="tiger.png" alt="Tiger"></a></span>},
769
- para.sub_macros(para.source).gsub(/>\s+</, '><')
770
- end
771
-
772
- test 'rel=nofollow should be added to an image with a link when the nofollow option is set' do
773
- para = block_from_string 'image:tiger.png[Tiger,link=http://en.wikipedia.org/wiki/Tiger,opts=nofollow]'
774
- assert_equal %{<span class="image"><a class="image" href="http://en.wikipedia.org/wiki/Tiger" rel="nofollow"><img src="tiger.png" alt="Tiger"></a></span>},
775
- para.sub_macros(para.source).gsub(/>\s+</, '><')
776
- end
777
-
778
- test 'a multi-line image macro with text and dimensions should be interpreted as an image with alt text and dimensions' do
779
- para = block_from_string(%(image:tiger.png[Another\nAwesome\nTiger, 200,\n100]))
780
- assert_equal %{<span class="image"><img src="tiger.png" alt="Another Awesome Tiger" width="200" height="100"></span>},
781
- para.sub_macros(para.source).gsub(/>\s+</, '><')
782
- end
783
-
784
- test 'an inline image macro with a url target should be interpreted as an image' do
785
- para = block_from_string %(Beware of the image:http://example.com/images/tiger.png[tiger].)
786
- assert_equal %{Beware of the <span class="image"><img src="http://example.com/images/tiger.png" alt="tiger"></span>.},
787
- para.sub_macros(para.source).gsub(/>\s+</, '><')
788
- end
789
-
790
- test 'an inline image macro with a float attribute should be interpreted as a floating image' do
791
- para = block_from_string %(image:http://example.com/images/tiger.png[tiger, float="right"] Beware of the tigers!)
792
- assert_equal %{<span class="image right"><img src="http://example.com/images/tiger.png" alt="tiger"></span> Beware of the tigers!},
793
- para.sub_macros(para.source).gsub(/>\s+</, '><')
794
- end
795
-
796
- test 'should prepend value of imagesdir attribute to inline image target if target is relative path' do
797
- para = block_from_string %(Beware of the image:tiger.png[tiger].), :attributes => {'imagesdir' => './images'}
798
- assert_equal %{Beware of the <span class="image"><img src="./images/tiger.png" alt="tiger"></span>.},
799
- para.sub_macros(para.source).gsub(/>\s+</, '><')
800
- end
801
-
802
- test 'should not prepend value of imagesdir attribute to inline image target if target is absolute path' do
803
- para = block_from_string %(Beware of the image:/tiger.png[tiger].), :attributes => {'imagesdir' => './images'}
804
- assert_equal %{Beware of the <span class="image"><img src="/tiger.png" alt="tiger"></span>.},
805
- para.sub_macros(para.source).gsub(/>\s+</, '><')
806
- end
807
-
808
- test 'should not prepend value of imagesdir attribute to inline image target if target is url' do
809
- para = block_from_string %(Beware of the image:http://example.com/images/tiger.png[tiger].), :attributes => {'imagesdir' => './images'}
810
- assert_equal %{Beware of the <span class="image"><img src="http://example.com/images/tiger.png" alt="tiger"></span>.},
811
- para.sub_macros(para.source).gsub(/>\s+</, '><')
812
- end
813
-
814
- test 'should match an inline image macro if target contains a space character' do
815
- para = block_from_string(%(Beware of the image:big cats.png[] around here.))
816
- assert_equal %(Beware of the <span class="image"><img src="big%20cats.png" alt="big cats"></span> around here.),
817
- para.sub_macros(para.source).gsub(/>\s+</, '><')
818
- end
819
-
820
- test 'should not match an inline image macro if target contains an endline character' do
821
- para = block_from_string(%(Fear not. There are no image:big\ncats.png[] around here.))
822
- result = para.sub_macros(para.source)
823
- refute_includes result, '<img '
824
- assert_includes result, %(image:big\ncats.png[])
825
- end
826
-
827
- test 'should not match an inline image macro if target begins or ends with space character' do
828
- ['image: big cats.png[]', 'image:big cats.png []'].each do |input|
829
- para = block_from_string %(Fear not. There are no #{input} around here.)
830
- result = para.sub_macros(para.source)
831
- refute_includes result, '<img '
832
- assert_includes result, input
833
- end
834
- end
835
-
836
- test 'should not detect a block image macro found inline' do
837
- para = block_from_string(%(Not an inline image macro image::tiger.png[].))
838
- result = para.sub_macros(para.source)
839
- refute_includes result, '<img '
840
- assert_includes result, 'image::tiger.png[]'
841
- end
842
-
843
- # NOTE this test verifies attributes get substituted eagerly in target of image in title
844
- test 'should substitute attributes in target of inline image in section title' do
845
- input = <<-EOS
846
- == image:{iconsdir}/dot.gif[dot] Title
847
- EOS
848
-
849
- using_memory_logger do |logger|
850
- sect = block_from_string input, :attributes => { 'data-uri' => '', 'iconsdir' => 'fixtures', 'docdir' => testdir }, :safe => :server, :catalog_assets => true
851
- assert 1, sect.document.catalog[:images].size
852
- assert_equal 'fixtures/dot.gif', sect.document.catalog[:images][0].to_s
853
- assert_nil sect.document.catalog[:images][0].imagesdir
854
- assert logger.empty?
855
- end
856
- end
857
-
858
- test 'an icon macro should be interpreted as an icon if icons are enabled' do
859
- para = block_from_string 'icon:github[]', :attributes => {'icons' => ''}
860
- assert_equal %{<span class="icon"><img src="./images/icons/github.png" alt="github"></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
861
- end
862
-
863
- test 'an icon macro should be interpreted as alt text if icons are disabled' do
864
- para = block_from_string 'icon:github[]'
865
- assert_equal %{<span class="icon">[github]</span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
866
- end
867
-
868
- test 'an icon macro should output alt text if icons are disabled and alt is given' do
869
- para = block_from_string 'icon:github[alt="GitHub"]'
870
- assert_equal %{<span class="icon">[GitHub]</span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
871
- end
872
-
873
- test 'an icon macro should be interpreted as a font-based icon when icons=font' do
874
- para = block_from_string 'icon:github[]', :attributes => {'icons' => 'font'}
875
- assert_equal %{<span class="icon"><i class="fa fa-github"></i></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
876
- end
877
-
878
- test 'an icon macro with a size should be interpreted as a font-based icon with a size when icons=font' do
879
- para = block_from_string 'icon:github[4x]', :attributes => {'icons' => 'font'}
880
- assert_equal %{<span class="icon"><i class="fa fa-github fa-4x"></i></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
881
- end
882
-
883
- test 'an icon macro with a role and title should be interpreted as a font-based icon with a class and title when icons=font' do
884
- para = block_from_string 'icon:heart[role="red", title="Heart me"]', :attributes => {'icons' => 'font'}
885
- assert_equal %{<span class="icon red"><i class="fa fa-heart" title="Heart me"></i></span>}, para.sub_macros(para.source).gsub(/>\s+</, '><')
886
- end
887
-
888
- test 'a single-line footnote macro should be registered and output as a footnote' do
889
- para = block_from_string('Sentence text footnote:[An example footnote.].')
890
- assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
891
- assert_equal 1, para.document.catalog[:footnotes].size
892
- footnote = para.document.catalog[:footnotes].first
893
- assert_equal 1, footnote.index
894
- assert_nil footnote.id
895
- assert_equal 'An example footnote.', footnote.text
896
- end
897
-
898
- test 'a multi-line footnote macro should be registered and output as a footnote without endline' do
899
- para = block_from_string("Sentence text footnote:[An example footnote\nwith wrapped text.].")
900
- assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
901
- assert_equal 1, para.document.catalog[:footnotes].size
902
- footnote = para.document.catalog[:footnotes].first
903
- assert_equal 1, footnote.index
904
- assert_nil footnote.id
905
- assert_equal "An example footnote with wrapped text.", footnote.text
906
- end
907
-
908
- test 'an escaped closing square bracket in a footnote should be unescaped when converted' do
909
- para = block_from_string(%(footnote:[a #{BACKSLASH}] b].))
910
- assert_equal %(<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
911
- assert_equal 1, para.document.catalog[:footnotes].size
912
- footnote = para.document.catalog[:footnotes].first
913
- assert_equal "a ] b", footnote.text
914
- end
915
-
916
- test 'a footnote macro can be directly adjacent to preceding word' do
917
- para = block_from_string('Sentence textfootnote:[An example footnote.].')
918
- assert_equal %(Sentence text<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
919
- end
920
-
921
- test 'a footnote macro may contain an escaped backslash' do
922
- para = block_from_string("footnote:[\\]]\nfootnote:[a \\] b]\nfootnote:[a \\]\\] b]")
923
- para.sub_macros(para.source)
924
- assert_equal 3, para.document.catalog[:footnotes].size
925
- footnote1 = para.document.catalog[:footnotes][0]
926
- assert_equal ']', footnote1.text
927
- footnote2 = para.document.catalog[:footnotes][1]
928
- assert_equal 'a ] b', footnote2.text
929
- footnote3 = para.document.catalog[:footnotes][2]
930
- assert_equal 'a ]] b', footnote3.text
931
- end
932
-
933
- test 'a footnote macro may contain a link macro' do
934
- para = block_from_string('Share your code. footnote:[https://github.com[GitHub]]')
935
- assert_equal %(Share your code. <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
936
- assert_equal 1, para.document.catalog[:footnotes].size
937
- footnote1 = para.document.catalog[:footnotes][0]
938
- assert_equal '<a href="https://github.com">GitHub</a>', footnote1.text
939
- end
940
-
941
- test 'a footnote macro may contain a plain URL' do
942
- para = block_from_string %(the JLine footnote:[https://github.com/jline/jline2]\nlibrary.)
943
- result = para.sub_macros para.source
944
- assert_equal %(the JLine <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>\nlibrary.), result
945
- assert_equal 1, para.document.catalog[:footnotes].size
946
- fn1 = para.document.catalog[:footnotes].first
947
- assert_equal '<a href="https://github.com/jline/jline2" class="bare">https://github.com/jline/jline2</a>', fn1.text
948
- end
949
-
950
- test 'a footnote macro followed by a semi-colon may contain a plain URL' do
951
- para = block_from_string %(the JLine footnote:[https://github.com/jline/jline2];\nlibrary.)
952
- result = para.sub_macros para.source
953
- assert_equal %(the JLine <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>;\nlibrary.), result
954
- assert_equal 1, para.document.catalog[:footnotes].size
955
- fn1 = para.document.catalog[:footnotes].first
956
- assert_equal '<a href="https://github.com/jline/jline2" class="bare">https://github.com/jline/jline2</a>', fn1.text
957
- end
958
-
959
- test 'a footnote macro may contain an xref macro' do
960
- # specialcharacters escaping is simulated
961
- para = block_from_string('text footnote:[&lt;&lt;_install,install&gt;&gt;]')
962
- doc = para.document
963
- doc.register :refs, ['_install', (Asciidoctor::Inline.new doc, :anchor, 'Install', :type => :ref, :target => '_install'), 'Install']
964
- catalog = doc.catalog
965
- assert_equal %(text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
966
- assert_equal 1, catalog[:footnotes].size
967
- footnote1 = catalog[:footnotes][0]
968
- assert_equal '<a href="#_install">install</a>', footnote1.text
969
- end
970
-
971
- test 'a footnote macro may contain an anchor macro' do
972
- para = block_from_string('text footnote:[a [[b\]\] \[[c\]\] d]')
973
- assert_equal %(text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>), para.sub_macros(para.source)
974
- assert_equal 1, para.document.catalog[:footnotes].size
975
- footnote1 = para.document.catalog[:footnotes][0]
976
- assert_equal 'a <a id="b"></a> [[c]] d', footnote1.text
977
- end
978
-
979
- test 'subsequent footnote macros with escaped URLs should be restored in DocBook' do
980
- input = <<-EOS
981
- foofootnote:[+http://example.com+]barfootnote:[+http://acme.com+]baz
982
- EOS
983
-
984
- result = convert_string_to_embedded input, :doctype => 'inline', :backend => 'docbook'
985
- assert_equal 'foo<footnote><simpara>http://example.com</simpara></footnote>bar<footnote><simpara>http://acme.com</simpara></footnote>baz', result
986
- end
987
-
988
- test 'should increment index of subsequent footnote macros' do
989
- para = block_from_string("Sentence text footnote:[An example footnote.]. Sentence text footnote:[Another footnote.].")
990
- assert_equal %(Sentence text <sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>. Sentence text <sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup>.), para.sub_macros(para.source)
991
- assert_equal 2, para.document.catalog[:footnotes].size
992
- footnote1 = para.document.catalog[:footnotes][0]
993
- assert_equal 1, footnote1.index
994
- assert_nil footnote1.id
995
- assert_equal "An example footnote.", footnote1.text
996
- footnote2 = para.document.catalog[:footnotes][1]
997
- assert_equal 2, footnote2.index
998
- assert_nil footnote2.id
999
- assert_equal "Another footnote.", footnote2.text
1000
- end
1001
-
1002
- test 'a footnoteref macro with id and single-line text should be registered and output as a footnote' do
1003
- para = block_from_string('Sentence text footnoteref:[ex1, An example footnote.].')
1004
- assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
1005
- assert_equal 1, para.document.catalog[:footnotes].size
1006
- footnote = para.document.catalog[:footnotes].first
1007
- assert_equal 1, footnote.index
1008
- assert_equal 'ex1', footnote.id
1009
- assert_equal 'An example footnote.', footnote.text
1010
- end
1011
-
1012
- test 'a footnoteref macro with id and multi-line text should be registered and output as a footnote without endlines' do
1013
- para = block_from_string("Sentence text footnoteref:[ex1, An example footnote\nwith wrapped text.].")
1014
- assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
1015
- assert_equal 1, para.document.catalog[:footnotes].size
1016
- footnote = para.document.catalog[:footnotes].first
1017
- assert_equal 1, footnote.index
1018
- assert_equal 'ex1', footnote.id
1019
- assert_equal "An example footnote with wrapped text.", footnote.text
1020
- end
1021
-
1022
- test 'a footnoteref macro with id should refer to footnoteref with same id' do
1023
- para = block_from_string('Sentence text footnoteref:[ex1, An example footnote.]. Sentence text footnoteref:[ex1].')
1024
- assert_equal %(Sentence text <sup class="footnote" id="_footnote_ex1">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>. Sentence text <sup class="footnoteref">[<a class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>.), para.sub_macros(para.source)
1025
- assert_equal 1, para.document.catalog[:footnotes].size
1026
- footnote = para.document.catalog[:footnotes].first
1027
- assert_equal 1, footnote.index
1028
- assert_equal 'ex1', footnote.id
1029
- assert_equal 'An example footnote.', footnote.text
1030
- end
1031
-
1032
- test 'an unresolved footnote reference should produce a warning message' do
1033
- input = 'Sentence text.footnote:ex1[]'
1034
- using_memory_logger do |logger|
1035
- para = block_from_string input
1036
- para.sub_macros para.source
1037
- assert_message logger, :WARN, 'invalid footnote reference: ex1'
1038
- end
1039
- end
1040
-
1041
- test 'inline footnote macro can be used to define and reference a footnote reference' do
1042
- input = <<-EOS
1043
- You can download the software from the product page.footnote:sub[Option only available if you have an active subscription.]
1044
-
1045
- You can also file a support request.footnote:sub[]
1046
-
1047
- If all else fails, you can give us a call.footnoteref:[sub]
1048
- EOS
1049
-
1050
- output = convert_string_to_embedded input
1051
- assert_css '#_footnotedef_1', output, 1
1052
- assert_css 'p a[href="#_footnotedef_1"]', output, 3
1053
- assert_css '#footnotes .footnote', output, 1
1054
- end
1055
-
1056
- test 'should parse multiple footnote references in a single line' do
1057
- input = <<-'EOS'
1058
- notable text.footnote:id[about this [text\]], footnote:id[], footnote:id[]
1059
- EOS
1060
-
1061
- output = convert_string_to_embedded input
1062
- assert_xpath '(//p)[1]/sup[starts-with(@class,"footnote")]', output, 3
1063
- assert_xpath '(//p)[1]/sup[@class="footnote"]', output, 1
1064
- assert_xpath '(//p)[1]/sup[@class="footnoteref"]', output, 2
1065
- assert_xpath '(//p)[1]/sup[starts-with(@class,"footnote")]/a[@class="footnote"][text()="1"]', output, 3
1066
- assert_css '#footnotes .footnote', output, 1
1067
- end
1068
-
1069
- test 'should not resolve an inline footnote macro missing both id and text' do
1070
- input = <<-EOS
1071
- The footnote:[] macro can be used for defining and referencing footnotes.
1072
-
1073
- The footnoteref:[] macro is now deprecated.
1074
- EOS
1075
-
1076
- output = convert_string_to_embedded input
1077
- assert_includes output, 'The footnote:[] macro'
1078
- assert_includes output, 'The footnoteref:[] macro'
1079
- end
1080
-
1081
- test 'inline footnote macro can define a numeric id without conflicting with auto-generated ID' do
1082
- input = <<-EOS
1083
- You can download the software from the product page.footnote:1[Option only available if you have an active subscription.]
1084
- EOS
1085
-
1086
- output = convert_string_to_embedded input
1087
- assert_css '#_footnote_1', output, 1
1088
- assert_css 'p sup#_footnote_1', output, 1
1089
- assert_css 'p a#_footnoteref_1', output, 1
1090
- assert_css 'p a[href="#_footnotedef_1"]', output, 1
1091
- assert_css '#footnotes #_footnotedef_1', output, 1
1092
- end
1093
-
1094
- test 'a single-line index term macro with a primary term should be registered as an index reference' do
1095
- sentence = "The tiger (Panthera tigris) is the largest cat species.\n"
1096
- macros = ['indexterm:[Tigers]', '(((Tigers)))']
1097
- macros.each do |macro|
1098
- para = block_from_string("#{sentence}#{macro}")
1099
- output = para.sub_macros(para.source)
1100
- assert_equal sentence, output
1101
- assert_equal 1, para.document.catalog[:indexterms].size
1102
- assert_equal ['Tigers'], para.document.catalog[:indexterms].first
1103
- end
1104
- end
1105
-
1106
- test 'a single-line index term macro with primary and secondary terms should be registered as an index reference' do
1107
- sentence = "The tiger (Panthera tigris) is the largest cat species.\n"
1108
- macros = ['indexterm:[Big cats, Tigers]', '(((Big cats, Tigers)))']
1109
- macros.each do |macro|
1110
- para = block_from_string("#{sentence}#{macro}")
1111
- output = para.sub_macros(para.source)
1112
- assert_equal sentence, output
1113
- assert_equal 1, para.document.catalog[:indexterms].size
1114
- assert_equal ['Big cats', 'Tigers'], para.document.catalog[:indexterms].first
1115
- end
1116
- end
1117
-
1118
- test 'a single-line index term macro with primary, secondary and tertiary terms should be registered as an index reference' do
1119
- sentence = "The tiger (Panthera tigris) is the largest cat species.\n"
1120
- macros = ['indexterm:[Big cats,Tigers , Panthera tigris]', '(((Big cats,Tigers , Panthera tigris)))']
1121
- macros.each do |macro|
1122
- para = block_from_string("#{sentence}#{macro}")
1123
- output = para.sub_macros(para.source)
1124
- assert_equal sentence, output
1125
- assert_equal 1, para.document.catalog[:indexterms].size
1126
- assert_equal ['Big cats', 'Tigers', 'Panthera tigris'], para.document.catalog[:indexterms].first
1127
- end
1128
- end
1129
-
1130
- test 'a multi-line index term macro should be compacted and registered as an index reference' do
1131
- sentence = "The tiger (Panthera tigris) is the largest cat species.\n"
1132
- macros = ["indexterm:[Panthera\ntigris]", "(((Panthera\ntigris)))"]
1133
- macros.each do |macro|
1134
- para = block_from_string("#{sentence}#{macro}")
1135
- output = para.sub_macros(para.source)
1136
- assert_equal sentence, output
1137
- assert_equal 1, para.document.catalog[:indexterms].size
1138
- assert_equal ['Panthera tigris'], para.document.catalog[:indexterms].first
1139
- end
1140
- end
1141
-
1142
- test 'should escape concealed index term if second bracket is preceded by a backslash' do
1143
- input = %[National Institute of Science and Technology (#{BACKSLASH}((NIST)))]
1144
- doc = document_from_string input, :header_footer => false
1145
- output = doc.convert
1146
- assert_xpath '//p[text()="National Institute of Science and Technology (((NIST)))"]', output, 1
1147
- assert doc.catalog[:indexterms].empty?
1148
- end
1149
-
1150
- test 'should only escape enclosing brackets if concealed index term is preceded by a backslash' do
1151
- input = %[National Institute of Science and Technology #{BACKSLASH}(((NIST)))]
1152
- doc = document_from_string input, :header_footer => false
1153
- output = doc.convert
1154
- assert_xpath '//p[text()="National Institute of Science and Technology (NIST)"]', output, 1
1155
- term = doc.catalog[:indexterms].first
1156
- assert_equal 1, term.size
1157
- assert_equal 'NIST', term.first
1158
- end
1159
-
1160
- test 'should not split index terms on commas inside of quoted terms' do
1161
- inputs = []
1162
- inputs.push <<-EOS
1163
- Tigers are big, scary cats.
1164
- indexterm:[Tigers, "[Big\\],
1165
- scary cats"]
1166
- EOS
1167
- inputs.push <<-EOS
1168
- Tigers are big, scary cats.
1169
- (((Tigers, "[Big],
1170
- scary cats")))
1171
- EOS
1172
-
1173
- inputs.each do |input|
1174
- para = block_from_string input
1175
- output = para.sub_macros(para.source)
1176
- assert_equal input.lines.first, output
1177
- assert_equal 1, para.document.catalog[:indexterms].size
1178
- terms = para.document.catalog[:indexterms].first
1179
- assert_equal 2, terms.size
1180
- assert_equal 'Tigers', terms.first
1181
- assert_equal '[Big], scary cats', terms.last
1182
- end
1183
- end
1184
-
1185
- test 'normal substitutions are performed on an index term macro' do
1186
- sentence = "The tiger (Panthera tigris) is the largest cat species.\n"
1187
- macros = ['indexterm:[*Tigers*]', '(((*Tigers*)))']
1188
- macros.each do |macro|
1189
- para = block_from_string("#{sentence}#{macro}")
1190
- output = para.apply_subs(para.source)
1191
- assert_equal sentence, output
1192
- assert_equal 1, para.document.catalog[:indexterms].size
1193
- assert_equal ['<strong>Tigers</strong>'], para.document.catalog[:indexterms].first
1194
- end
1195
- end
1196
-
1197
- test 'registers multiple index term macros' do
1198
- sentence = "The tiger (Panthera tigris) is the largest cat species."
1199
- macros = "(((Tigers)))\n(((Animals,Cats)))"
1200
- para = block_from_string("#{sentence}\n#{macros}")
1201
- output = para.sub_macros(para.source)
1202
- assert_equal sentence, output.rstrip
1203
- assert_equal 2, para.document.catalog[:indexterms].size
1204
- assert_equal ['Tigers'], para.document.catalog[:indexterms][0]
1205
- assert_equal ['Animals', 'Cats'], para.document.catalog[:indexterms][1]
1206
- end
1207
-
1208
- test 'an index term macro with round bracket syntax may contain round brackets in term' do
1209
- sentence = "The tiger (Panthera tigris) is the largest cat species.\n"
1210
- macro = '(((Tiger (Panthera tigris))))'
1211
- para = block_from_string("#{sentence}#{macro}")
1212
- output = para.sub_macros(para.source)
1213
- assert_equal sentence, output
1214
- assert_equal 1, para.document.catalog[:indexterms].size
1215
- assert_equal ['Tiger (Panthera tigris)'], para.document.catalog[:indexterms].first
1216
- end
1217
-
1218
- test 'visible shorthand index term macro should not consume trailing round bracket' do
1219
- input = '(text with ((index term)))'
1220
- expected = '(text with <indexterm><primary>index term</primary></indexterm>index term)'
1221
- expected_term = ['index term']
1222
- para = block_from_string input, :backend => :docbook
1223
- output = para.sub_macros para.source
1224
- indexterms_table = para.document.catalog[:indexterms]
1225
- assert_equal 1, indexterms_table.size
1226
- assert_equal expected_term, indexterms_table[0]
1227
- assert_equal expected, output
1228
- end
1229
-
1230
- test 'visible shorthand index term macro should not consume leading round bracket' do
1231
- input = '(((index term)) for text)'
1232
- expected = '(<indexterm><primary>index term</primary></indexterm>index term for text)'
1233
- expected_term = ['index term']
1234
- para = block_from_string input, :backend => :docbook
1235
- output = para.sub_macros para.source
1236
- indexterms_table = para.document.catalog[:indexterms]
1237
- assert_equal 1, indexterms_table.size
1238
- assert_equal expected_term, indexterms_table[0]
1239
- assert_equal expected, output
1240
- end
1241
-
1242
- test 'an index term macro with square bracket syntax may contain square brackets in term' do
1243
- sentence = "The tiger (Panthera tigris) is the largest cat species.\n"
1244
- macro = 'indexterm:[Tiger [Panthera tigris\\]]'
1245
- para = block_from_string("#{sentence}#{macro}")
1246
- output = para.sub_macros(para.source)
1247
- assert_equal sentence, output
1248
- assert_equal 1, para.document.catalog[:indexterms].size
1249
- assert_equal ['Tiger [Panthera tigris]'], para.document.catalog[:indexterms].first
1250
- end
1251
-
1252
- test 'a single-line index term 2 macro should be registered as an index reference and retain term inline' do
1253
- sentence = 'The tiger (Panthera tigris) is the largest cat species.'
1254
- macros = ['The indexterm2:[tiger] (Panthera tigris) is the largest cat species.', 'The ((tiger)) (Panthera tigris) is the largest cat species.']
1255
- macros.each do |macro|
1256
- para = block_from_string(macro)
1257
- output = para.sub_macros(para.source)
1258
- assert_equal sentence, output
1259
- assert_equal 1, para.document.catalog[:indexterms].size
1260
- assert_equal ['tiger'], para.document.catalog[:indexterms].first
1261
- end
1262
- end
1263
-
1264
- test 'a multi-line index term 2 macro should be compacted and registered as an index reference and retain term inline' do
1265
- sentence = 'The panthera tigris is the largest cat species.'
1266
- macros = ["The indexterm2:[ panthera\ntigris ] is the largest cat species.", "The (( panthera\ntigris )) is the largest cat species."]
1267
- macros.each do |macro|
1268
- para = block_from_string(macro)
1269
- output = para.sub_macros(para.source)
1270
- assert_equal sentence, output
1271
- assert_equal 1, para.document.catalog[:indexterms].size
1272
- assert_equal ['panthera tigris'], para.document.catalog[:indexterms].first
1273
- end
1274
- end
1275
-
1276
- test 'registers multiple index term 2 macros' do
1277
- sentence = "The ((tiger)) (Panthera tigris) is the largest ((cat)) species."
1278
- para = block_from_string(sentence)
1279
- output = para.sub_macros(para.source)
1280
- assert_equal 'The tiger (Panthera tigris) is the largest cat species.', output
1281
- assert_equal 2, para.document.catalog[:indexterms].size
1282
- assert_equal ['tiger'], para.document.catalog[:indexterms][0]
1283
- assert_equal ['cat'], para.document.catalog[:indexterms][1]
1284
- end
1285
-
1286
- test 'should escape visible index term if preceded by a backslash' do
1287
- sentence = "The #{BACKSLASH}((tiger)) (Panthera tigris) is the largest #{BACKSLASH}((cat)) species."
1288
- para = block_from_string(sentence)
1289
- output = para.sub_macros(para.source)
1290
- assert_equal 'The ((tiger)) (Panthera tigris) is the largest ((cat)) species.', output
1291
- assert para.document.catalog[:indexterms].empty?
1292
- end
1293
-
1294
- test 'normal substitutions are performed on an index term 2 macro' do
1295
- sentence = 'The ((*tiger*)) (Panthera tigris) is the largest cat species.'
1296
- para = block_from_string sentence
1297
- output = para.apply_subs(para.source)
1298
- assert_equal 'The <strong>tiger</strong> (Panthera tigris) is the largest cat species.', output
1299
- assert_equal 1, para.document.catalog[:indexterms].size
1300
- assert_equal ['<strong>tiger</strong>'], para.document.catalog[:indexterms].first
1301
- end
1302
-
1303
- test 'index term 2 macro with round bracket syntex should not interfer with index term macro with round bracket syntax' do
1304
- sentence = "The ((panthera tigris)) is the largest cat species.\n(((Big cats,Tigers)))"
1305
- para = block_from_string sentence
1306
- output = para.sub_macros(para.source)
1307
- assert_equal "The panthera tigris is the largest cat species.\n", output
1308
- terms = para.document.catalog[:indexterms]
1309
- assert_equal 2, terms.size
1310
- assert_equal ['panthera tigris'], terms[0]
1311
- assert_equal ['Big cats', 'Tigers'], terms[1]
1312
- end
1313
-
1314
- context 'Button macro' do
1315
- test 'btn macro' do
1316
- para = block_from_string('btn:[Save]', :attributes => {'experimental' => ''})
1317
- assert_equal %q{<b class="button">Save</b>}, para.sub_macros(para.source)
1318
- end
1319
-
1320
- test 'btn macro that spans multiple lines' do
1321
- para = block_from_string(%(btn:[Rebase and\nmerge]), :attributes => {'experimental' => ''})
1322
- assert_equal %q{<b class="button">Rebase and merge</b>}, para.sub_macros(para.source)
1323
- end
1324
-
1325
- test 'btn macro for docbook backend' do
1326
- para = block_from_string('btn:[Save]', :backend => 'docbook', :attributes => {'experimental' => ''})
1327
- assert_equal %q{<guibutton>Save</guibutton>}, para.sub_macros(para.source)
1328
- end
1329
- end
1330
-
1331
- context 'Keyboard macro' do
1332
- test 'kbd macro with single key' do
1333
- para = block_from_string('kbd:[F3]', :attributes => {'experimental' => ''})
1334
- assert_equal %q{<kbd>F3</kbd>}, para.sub_macros(para.source)
1335
- end
1336
-
1337
- test 'kbd macro with single backslash key' do
1338
- para = block_from_string("kbd:[#{BACKSLASH} ]", :attributes => {'experimental' => ''})
1339
- assert_equal %q(<kbd>\</kbd>), para.sub_macros(para.source)
1340
- end
1341
-
1342
- test 'kbd macro with single key, docbook backend' do
1343
- para = block_from_string('kbd:[F3]', :backend => 'docbook', :attributes => {'experimental' => ''})
1344
- assert_equal %q{<keycap>F3</keycap>}, para.sub_macros(para.source)
1345
- end
1346
-
1347
- test 'kbd macro with key combination' do
1348
- para = block_from_string('kbd:[Ctrl+Shift+T]', :attributes => {'experimental' => ''})
1349
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd></span>}, para.sub_macros(para.source)
1350
- end
1351
-
1352
- test 'kbd macro with key combination that spans multiple lines' do
1353
- para = block_from_string(%(kbd:[Ctrl +\nT]), :attributes => {'experimental' => ''})
1354
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>T</kbd></span>}, para.sub_macros(para.source)
1355
- end
1356
-
1357
- test 'kbd macro with key combination, docbook backend' do
1358
- para = block_from_string('kbd:[Ctrl+Shift+T]', :backend => 'docbook', :attributes => {'experimental' => ''})
1359
- assert_equal %q{<keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><keycap>T</keycap></keycombo>}, para.sub_macros(para.source)
1360
- end
1361
-
1362
- test 'kbd macro with key combination delimited by pluses with spaces' do
1363
- para = block_from_string('kbd:[Ctrl + Shift + T]', :attributes => {'experimental' => ''})
1364
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd></span>}, para.sub_macros(para.source)
1365
- end
1366
-
1367
- test 'kbd macro with key combination delimited by commas' do
1368
- para = block_from_string('kbd:[Ctrl,Shift,T]', :attributes => {'experimental' => ''})
1369
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd></span>}, para.sub_macros(para.source)
1370
- end
1371
-
1372
- test 'kbd macro with key combination delimited by commas with spaces' do
1373
- para = block_from_string('kbd:[Ctrl, Shift, T]', :attributes => {'experimental' => ''})
1374
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd></span>}, para.sub_macros(para.source)
1375
- end
1376
-
1377
- test 'kbd macro with key combination delimited by plus containing a comma key' do
1378
- para = block_from_string('kbd:[Ctrl+,]', :attributes => {'experimental' => ''})
1379
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>,</kbd></span>}, para.sub_macros(para.source)
1380
- end
1381
-
1382
- test 'kbd macro with key combination delimited by commas containing a plus key' do
1383
- para = block_from_string('kbd:[Ctrl, +, Shift]', :attributes => {'experimental' => ''})
1384
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>+</kbd>+<kbd>Shift</kbd></span>}, para.sub_macros(para.source)
1385
- end
1386
-
1387
- test 'kbd macro with key combination where last key matches plus delimiter' do
1388
- para = block_from_string('kbd:[Ctrl + +]', :attributes => {'experimental' => ''})
1389
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>+</kbd></span>}, para.sub_macros(para.source)
1390
- end
1391
-
1392
- test 'kbd macro with key combination where last key matches comma delimiter' do
1393
- para = block_from_string('kbd:[Ctrl, ,]', :attributes => {'experimental' => ''})
1394
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>,</kbd></span>}, para.sub_macros(para.source)
1395
- end
1396
-
1397
- test 'kbd macro with key combination containing escaped bracket' do
1398
- para = block_from_string('kbd:[Ctrl + \]]', :attributes => {'experimental' => ''})
1399
- assert_equal %q{<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>]</kbd></span>}, para.sub_macros(para.source)
1400
- end
1401
-
1402
- test 'kbd macro with key combination ending in backslash' do
1403
- para = block_from_string("kbd:[Ctrl + #{BACKSLASH} ]", :attributes => {'experimental' => ''})
1404
- assert_equal %q(<span class="keyseq"><kbd>Ctrl</kbd>+<kbd>\\</kbd></span>), para.sub_macros(para.source)
1405
- end
1406
-
1407
- test 'kbd macro looks for delimiter beyond first character' do
1408
- para = block_from_string('kbd:[,te]', :attributes => {'experimental' => ''})
1409
- assert_equal %q(<kbd>,te</kbd>), para.sub_macros(para.source)
1410
- end
1411
-
1412
- test 'kbd macro restores trailing delimiter as key value' do
1413
- para = block_from_string('kbd:[te,]', :attributes => {'experimental' => ''})
1414
- assert_equal %q(<kbd>te,</kbd>), para.sub_macros(para.source)
1415
- end
1416
- end
1417
-
1418
- context 'Menu macro' do
1419
- test 'should process menu using macro sytnax' do
1420
- para = block_from_string('menu:File[]', :attributes => {'experimental' => ''})
1421
- assert_equal %q{<b class="menuref">File</b>}, para.sub_macros(para.source)
1422
- end
1423
-
1424
- test 'should process menu for docbook backend' do
1425
- para = block_from_string('menu:File[]', :backend => 'docbook', :attributes => {'experimental' => ''})
1426
- assert_equal %q{<guimenu>File</guimenu>}, para.sub_macros(para.source)
1427
- end
1428
-
1429
- test 'should process menu with menu item using macro syntax' do
1430
- para = block_from_string('menu:File[Save As&#8230;]', :attributes => {'experimental' => ''})
1431
- assert_equal %q{<span class="menuseq"><b class="menu">File</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Save As&#8230;</b></span>}, para.sub_macros(para.source)
1432
- end
1433
-
1434
- test 'should process menu macro that spans multiple lines' do
1435
- input = %(menu:Preferences[Compile\non\nSave])
1436
- para = block_from_string input, :attributes => {'experimental' => ''}
1437
- assert_equal %(<span class="menuseq"><b class="menu">Preferences</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Compile\non\nSave</b></span>), para.sub_macros(para.source)
1438
- end
1439
-
1440
- test 'should unescape escaped closing bracket in menu macro' do
1441
- input = 'menu:Preferences[Compile [on\\] Save]'
1442
- para = block_from_string input, :attributes => {'experimental' => ''}
1443
- assert_equal %q(<span class="menuseq"><b class="menu">Preferences</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Compile [on] Save</b></span>), para.sub_macros(para.source)
1444
- end
1445
-
1446
- test 'should process menu with menu item using macro syntax when fonts icons are enabled' do
1447
- para = block_from_string('menu:Tools[More Tools &gt; Extensions]', :attributes => {'experimental' => '', 'icons' => 'font'})
1448
- assert_equal %q{<span class="menuseq"><b class="menu">Tools</b>&#160;<i class="fa fa-angle-right caret"></i> <b class="submenu">More Tools</b>&#160;<i class="fa fa-angle-right caret"></i> <b class="menuitem">Extensions</b></span>}, para.sub_macros(para.source)
1449
- end
1450
-
1451
- test 'should process menu with menu item for docbook backend' do
1452
- para = block_from_string('menu:File[Save As&#8230;]', :backend => 'docbook', :attributes => {'experimental' => ''})
1453
- assert_equal %q{<menuchoice><guimenu>File</guimenu> <guimenuitem>Save As&#8230;</guimenuitem></menuchoice>}, para.sub_macros(para.source)
1454
- end
1455
-
1456
- test 'should process menu with menu item in submenu using macro syntax' do
1457
- para = block_from_string('menu:Tools[Project &gt; Build]', :attributes => {'experimental' => ''})
1458
- assert_equal %q{<span class="menuseq"><b class="menu">Tools</b>&#160;<b class="caret">&#8250;</b> <b class="submenu">Project</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Build</b></span>}, para.sub_macros(para.source)
1459
- end
1460
-
1461
- test 'should process menu with menu item in submenu for docbook backend' do
1462
- para = block_from_string('menu:Tools[Project &gt; Build]', :backend => 'docbook', :attributes => {'experimental' => ''})
1463
- assert_equal %q{<menuchoice><guimenu>Tools</guimenu> <guisubmenu>Project</guisubmenu> <guimenuitem>Build</guimenuitem></menuchoice>}, para.sub_macros(para.source)
1464
- end
1465
-
1466
- test 'should process menu with menu item in submenu using macro syntax and comma delimiter' do
1467
- para = block_from_string('menu:Tools[Project, Build]', :attributes => {'experimental' => ''})
1468
- assert_equal %q{<span class="menuseq"><b class="menu">Tools</b>&#160;<b class="caret">&#8250;</b> <b class="submenu">Project</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Build</b></span>}, para.sub_macros(para.source)
1469
- end
1470
-
1471
- test 'should process menu with menu item using inline syntax' do
1472
- para = block_from_string('"File &gt; Save As&#8230;"', :attributes => {'experimental' => ''})
1473
- assert_equal %q{<span class="menuseq"><b class="menu">File</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Save As&#8230;</b></span>}, para.sub_macros(para.source)
1474
- end
1475
-
1476
- test 'should process menu with menu item in submenu using inline syntax' do
1477
- para = block_from_string('"Tools &gt; Project &gt; Build"', :attributes => {'experimental' => ''})
1478
- assert_equal %q{<span class="menuseq"><b class="menu">Tools</b>&#160;<b class="caret">&#8250;</b> <b class="submenu">Project</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Build</b></span>}, para.sub_macros(para.source)
1479
- end
1480
-
1481
- test 'inline menu syntax should not match closing quote of XML attribute' do
1482
- para = block_from_string('<span class="xmltag">&lt;node&gt;</span><span class="classname">r</span>', :attributes => {'experimental' => ''})
1483
- assert_equal %q{<span class="xmltag">&lt;node&gt;</span><span class="classname">r</span>}, para.sub_macros(para.source)
1484
- end
1485
-
1486
- test 'should process menu macro with items containing multibyte characters' do
1487
- para = block_from_string('menu:视图[放大, 重置]', :attributes => {'experimental' => ''})
1488
- assert_equal %q{<span class="menuseq"><b class="menu">视图</b>&#160;<b class="caret">&#8250;</b> <b class="submenu">放大</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">重置</b></span>}, para.sub_macros(para.source)
1489
- end if ::RUBY_MIN_VERSION_1_9
1490
-
1491
- test 'should process inline menu with items containing multibyte characters' do
1492
- para = block_from_string('"视图 &gt; 放大 &gt; 重置"', :attributes => {'experimental' => ''})
1493
- assert_equal %q{<span class="menuseq"><b class="menu">视图</b>&#160;<b class="caret">&#8250;</b> <b class="submenu">放大</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">重置</b></span>}, para.sub_macros(para.source)
1494
- end if ::RUBY_MIN_VERSION_1_9
1495
-
1496
- test 'should process a menu macro with a target that begins with a character reference' do
1497
- para = block_from_string('menu:&#8942;[More Tools, Extensions]', :attributes => {'experimental' => ''})
1498
- assert_equal %q{<span class="menuseq"><b class="menu">&#8942;</b>&#160;<b class="caret">&#8250;</b> <b class="submenu">More Tools</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Extensions</b></span>}, para.sub_macros(para.source)
1499
- end
1500
-
1501
- test 'should not process a menu macro with a target that ends with a space' do
1502
- input = 'menu:foo [bar] menu:File[Save]'
1503
- para = block_from_string input, :attributes => {'experimental' => ''}
1504
- result = para.sub_macros para.source
1505
- assert_xpath '/span[@class="menuseq"]', result, 1
1506
- assert_xpath '//b[@class="menu"][text()="File"]', result, 1
1507
- end
1508
-
1509
- test 'should process an inline menu that begins with a character reference' do
1510
- para = block_from_string('"&#8942; &gt; More Tools &gt; Extensions"', :attributes => {'experimental' => ''})
1511
- assert_equal %q{<span class="menuseq"><b class="menu">&#8942;</b>&#160;<b class="caret">&#8250;</b> <b class="submenu">More Tools</b>&#160;<b class="caret">&#8250;</b> <b class="menuitem">Extensions</b></span>}, para.sub_macros(para.source)
1512
- end
1513
- end
1514
- end
1515
-
1516
- context 'Passthroughs' do
1517
- test 'collect inline triple plus passthroughs' do
1518
- para = block_from_string('+++<code>inline code</code>+++')
1519
- result = para.extract_passthroughs(para.source)
1520
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1521
- assert_equal 1, para.passthroughs.size
1522
- assert_equal '<code>inline code</code>', para.passthroughs[0][:text]
1523
- assert_empty para.passthroughs[0][:subs]
1524
- end
1525
-
1526
- test 'collect multi-line inline triple plus passthroughs' do
1527
- para = block_from_string("+++<code>inline\ncode</code>+++")
1528
- result = para.extract_passthroughs(para.source)
1529
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1530
- assert_equal 1, para.passthroughs.size
1531
- assert_equal "<code>inline\ncode</code>", para.passthroughs[0][:text]
1532
- assert_empty para.passthroughs[0][:subs]
1533
- end
1534
-
1535
- test 'collect inline double dollar passthroughs' do
1536
- para = block_from_string('$$<code>{code}</code>$$')
1537
- result = para.extract_passthroughs(para.source)
1538
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1539
- assert_equal 1, para.passthroughs.size
1540
- assert_equal '<code>{code}</code>', para.passthroughs[0][:text]
1541
- assert_equal [:specialcharacters], para.passthroughs[0][:subs]
1542
- end
1543
-
1544
- test 'collect inline double plus passthroughs' do
1545
- para = block_from_string('++<code>{code}</code>++')
1546
- result = para.extract_passthroughs(para.source)
1547
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1548
- assert_equal 1, para.passthroughs.size
1549
- assert_equal '<code>{code}</code>', para.passthroughs[0][:text]
1550
- assert_equal [:specialcharacters], para.passthroughs[0][:subs]
1551
- end
1552
-
1553
- test 'should not crash if role on passthrough is enclosed in quotes' do
1554
- %W(
1555
- ['role']#{BACKSLASH}++This++++++++++++
1556
- ['role']#{BACKSLASH}+++++++++This++++++++++++
1557
- ).each do |input|
1558
- para = block_from_string input
1559
- assert_includes para.content, %(<span class="'role'">)
1560
- end
1561
- end
1562
-
1563
- test 'should allow inline double plus passthrough to be escaped using backslash' do
1564
- para = block_from_string("you need to replace `int a = n#{BACKSLASH}++;` with `int a = ++n;`!")
1565
- result = para.apply_subs para.source
1566
- assert_equal 'you need to replace <code>int a = n++;</code> with <code>int a = ++n;</code>!', result
1567
- end
1568
-
1569
- test 'should allow inline double plus passthrough with attributes to be escaped using backslash' do
1570
- para = block_from_string("=[attrs]#{BACKSLASH}#{BACKSLASH}++text++")
1571
- result = para.apply_subs para.source
1572
- assert_equal '=[attrs]++text++', result
1573
- end
1574
-
1575
- test 'collect multi-line inline double dollar passthroughs' do
1576
- para = block_from_string("$$<code>\n{code}\n</code>$$")
1577
- result = para.extract_passthroughs(para.source)
1578
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1579
- assert_equal 1, para.passthroughs.size
1580
- assert_equal "<code>\n{code}\n</code>", para.passthroughs[0][:text]
1581
- assert_equal [:specialcharacters], para.passthroughs[0][:subs]
1582
- end
1583
-
1584
- test 'collect multi-line inline double plus passthroughs' do
1585
- para = block_from_string("++<code>\n{code}\n</code>++")
1586
- result = para.extract_passthroughs(para.source)
1587
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1588
- assert_equal 1, para.passthroughs.size
1589
- assert_equal "<code>\n{code}\n</code>", para.passthroughs[0][:text]
1590
- assert_equal [:specialcharacters], para.passthroughs[0][:subs]
1591
- end
1592
-
1593
- test 'collect passthroughs from inline pass macro' do
1594
- para = block_from_string(%Q{pass:specialcharacters,quotes[<code>['code'\\]</code>]})
1595
- result = para.extract_passthroughs(para.source)
1596
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1597
- assert_equal 1, para.passthroughs.size
1598
- assert_equal %q{<code>['code']</code>}, para.passthroughs[0][:text]
1599
- assert_equal [:specialcharacters, :quotes], para.passthroughs[0][:subs]
1600
- end
1601
-
1602
- test 'collect multi-line passthroughs from inline pass macro' do
1603
- para = block_from_string(%Q{pass:specialcharacters,quotes[<code>['more\ncode'\\]</code>]})
1604
- result = para.extract_passthroughs(para.source)
1605
- assert_equal Asciidoctor::Substitutors::PASS_START + '0' + Asciidoctor::Substitutors::PASS_END, result
1606
- assert_equal 1, para.passthroughs.size
1607
- assert_equal %Q{<code>['more\ncode']</code>}, para.passthroughs[0][:text]
1608
- assert_equal [:specialcharacters, :quotes], para.passthroughs[0][:subs]
1609
- end
1610
-
1611
- test 'should find and replace placeholder duplicated by substitution' do
1612
- input = %q(+first passthrough+ followed by link:$$http://example.com/__u_no_format_me__$$[] with passthrough)
1613
- result = convert_inline_string input
1614
- assert_equal 'first passthrough followed by <a href="http://example.com/__u_no_format_me__" class="bare">http://example.com/__u_no_format_me__</a> with passthrough', result
1615
- end
1616
-
1617
- test 'resolves sub shorthands on inline pass macro' do
1618
- para = block_from_string 'pass:q,a[*<{backend}>*]'
1619
- result = para.extract_passthroughs para.source
1620
- assert_equal 1, para.passthroughs.size
1621
- assert_equal [:quotes, :attributes], para.passthroughs[0][:subs]
1622
- result = para.restore_passthroughs result
1623
- assert_equal '<strong><html5></strong>', result
1624
- end
1625
-
1626
- test 'should not recognize pass macro with invalid subsitution list' do
1627
- [',', '42', 'a,'].each do |subs|
1628
- para = block_from_string %(pass:#{subs}[foobar])
1629
- result = para.extract_passthroughs para.source
1630
- assert_equal %(pass:#{subs}[foobar]), result
1631
- end
1632
- end
1633
-
1634
- test 'should allow content of inline pass macro to be empty' do
1635
- para = block_from_string 'pass:[]'
1636
- result = para.extract_passthroughs para.source
1637
- assert_equal 1, para.passthroughs.size
1638
- assert_equal '', para.restore_passthroughs(result)
1639
- end
1640
-
1641
- # NOTE placeholder is surrounded by text to prevent reader from stripping trailing boundary char (unique to test scenario)
1642
- test 'restore inline passthroughs without subs' do
1643
- para = block_from_string("some #{Asciidoctor::Substitutors::PASS_START}" + '0' + "#{Asciidoctor::Substitutors::PASS_END} to study")
1644
- para.passthroughs[0] = {:text => '<code>inline code</code>', :subs => []}
1645
- result = para.restore_passthroughs(para.source)
1646
- assert_equal "some <code>inline code</code> to study", result
1647
- end
1648
-
1649
- # NOTE placeholder is surrounded by text to prevent reader from stripping trailing boundary char (unique to test scenario)
1650
- test 'restore inline passthroughs with subs' do
1651
- para = block_from_string("some #{Asciidoctor::Substitutors::PASS_START}" + '0' + "#{Asciidoctor::Substitutors::PASS_END} to study in the #{Asciidoctor::Substitutors::PASS_START}" + '1' + "#{Asciidoctor::Substitutors::PASS_END} programming language")
1652
- para.passthroughs[0] = {:text => '<code>{code}</code>', :subs => [:specialcharacters]}
1653
- para.passthroughs[1] = {:text => '{language}', :subs => [:specialcharacters]}
1654
- result = para.restore_passthroughs(para.source)
1655
- assert_equal 'some &lt;code&gt;{code}&lt;/code&gt; to study in the {language} programming language', result
1656
- end
1657
-
1658
- test 'should restore nested passthroughs' do
1659
- result = convert_inline_string %q(+Sometimes you feel pass:q[`mono`].+ Sometimes you +$$don't$$+.)
1660
- assert_equal %q(Sometimes you feel <code>mono</code>. Sometimes you don't.), result
1661
- end
1662
-
1663
- test 'should honor role on double plus passthrough' do
1664
- result = convert_inline_string 'Print the version using [var]++{asciidoctor-version}++.'
1665
- assert_equal 'Print the version using <span class="var">{asciidoctor-version}</span>.', result
1666
- end
1667
-
1668
- test 'complex inline passthrough macro' do
1669
- text_to_escape = %q{[(] <'basic form'> <'logical operator'> <'basic form'> [)]}
1670
- para = block_from_string %($$#{text_to_escape}$$)
1671
- para.extract_passthroughs(para.source)
1672
- assert_equal 1, para.passthroughs.size
1673
- assert_equal text_to_escape, para.passthroughs[0][:text]
1674
-
1675
- text_to_escape_escaped = %q{[(\] <'basic form'> <'logical operator'> <'basic form'> [)\]}
1676
- para = block_from_string %(pass:specialcharacters[#{text_to_escape_escaped}])
1677
- para.extract_passthroughs(para.source)
1678
- assert_equal 1, para.passthroughs.size
1679
- assert_equal text_to_escape, para.passthroughs[0][:text]
1680
- end
1681
-
1682
- test 'inline pass macro with a composite sub' do
1683
- para = block_from_string %(pass:verbatim[<{backend}>])
1684
- assert_equal '&lt;{backend}&gt;', para.content
1685
- end
1686
-
1687
- context 'Math macros' do
1688
- test 'should passthrough text in asciimath macro and surround with AsciiMath delimiters' do
1689
- input = 'asciimath:[x/x={(1,if x!=0),(text{undefined},if x=0):}]'
1690
- para = block_from_string input
1691
- assert_equal '\$x/x={(1,if x!=0),(text{undefined},if x=0):}\$', para.content
1692
- end
1693
-
1694
- test 'should not recognize asciimath macro with no content' do
1695
- input = 'asciimath:[]'
1696
- para = block_from_string input
1697
- assert_equal 'asciimath:[]', para.content
1698
- end
1699
-
1700
- test 'should perform specialcharacters subs on asciimath macro content in html backend by default' do
1701
- input = 'asciimath:[a < b]'
1702
- para = block_from_string input
1703
- assert_equal '\$a &lt; b\$', para.content
1704
- end
1705
-
1706
- test 'should convert contents of asciimath macro to MathML in DocBook output if asciimath gem is available' do
1707
- asciimath_available = !(Asciidoctor::Helpers.require_library 'asciimath', true, :ignore).nil?
1708
- input = 'asciimath:[a < b]'
1709
- expected = '<inlineequation><mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>a</mml:mi><mml:mo>&#x003C;</mml:mo><mml:mi>b</mml:mi></mml:math></inlineequation>'
1710
- using_memory_logger do |logger|
1711
- para = block_from_string input, :backend => :docbook
1712
- actual = para.content
1713
- if asciimath_available
1714
- assert_equal expected, actual
1715
- assert_equal :loaded, para.document.converter.instance_variable_get(:@asciimath)
1716
- else
1717
- assert_message logger, :WARN, 'optional gem \'asciimath\' is not installed. Functionality disabled.'
1718
- assert_equal :unavailable, para.document.converter.instance_variable_get(:@asciimath)
1719
- end
1720
- end
1721
- end
1722
-
1723
- test 'should not perform specialcharacters subs on asciimath macro content in Docbook output if asciimath gem not available' do
1724
- asciimath_available = !(Asciidoctor::Helpers.require_library 'asciimath', true, :ignore).nil?
1725
- input = 'asciimath:[a < b]'
1726
- para = block_from_string input, :backend => :docbook
1727
- para.document.converter.instance_variable_set :@asciimath, :unavailable
1728
- if asciimath_available
1729
- old_asciimath = ::AsciiMath
1730
- Object.send :remove_const, 'AsciiMath'
1731
- end
1732
- assert_equal '<inlineequation><mathphrase><![CDATA[a < b]]></mathphrase></inlineequation>', para.content
1733
- ::AsciiMath = old_asciimath if asciimath_available
1734
- end
1735
-
1736
- test 'should honor explicit subslist on asciimath macro' do
1737
- input = 'asciimath:attributes[{expr}]'
1738
- para = block_from_string input, :attributes => {'expr' => 'x != 0'}
1739
- assert_equal '\$x != 0\$', para.content
1740
- end
1741
-
1742
- test 'should passthrough text in latexmath macro and surround with LaTeX math delimiters' do
1743
- input = 'latexmath:[C = \alpha + \beta Y^{\gamma} + \epsilon]'
1744
- para = block_from_string input
1745
- assert_equal '\(C = \alpha + \beta Y^{\gamma} + \epsilon\)', para.content
1746
- end
1747
-
1748
- test 'should not recognize latexmath macro with no content' do
1749
- input = 'latexmath:[]'
1750
- para = block_from_string input
1751
- assert_equal 'latexmath:[]', para.content
1752
- end
1753
-
1754
- test 'should perform specialcharacters subs on latexmath macro in html backend by default' do
1755
- input = 'latexmath:[a < b]'
1756
- para = block_from_string input
1757
- assert_equal '\(a &lt; b\)', para.content
1758
- end
1759
-
1760
- test 'should not perform specialcharacters subs on latexmath macro content in docbook backend by default' do
1761
- input = 'latexmath:[a < b]'
1762
- para = block_from_string input, :backend => :docbook
1763
- assert_equal '<inlineequation><alt><![CDATA[a < b]]></alt><mathphrase><![CDATA[a < b]]></mathphrase></inlineequation>', para.content
1764
- end
1765
-
1766
- test 'should honor explicit subslist on latexmath macro' do
1767
- input = 'latexmath:attributes[{expr}]'
1768
- para = block_from_string input, :attributes => {'expr' => '\sqrt{4} = 2'}
1769
- assert_equal '\(\sqrt{4} = 2\)', para.content
1770
- end
1771
-
1772
- test 'should passthrough math macro inside another passthrough' do
1773
- input = 'the text `asciimath:[x = y]` should be passed through as +literal+ text'
1774
- para = block_from_string input, :attributes => {'compat-mode' => ''}
1775
- assert_equal 'the text <code>asciimath:[x = y]</code> should be passed through as <code>literal</code> text', para.content
1776
-
1777
- input = 'the text [x-]`asciimath:[x = y]` should be passed through as `literal` text'
1778
- para = block_from_string input
1779
- assert_equal 'the text <code>asciimath:[x = y]</code> should be passed through as <code>literal</code> text', para.content
1780
-
1781
- input = 'the text `+asciimath:[x = y]+` should be passed through as `literal` text'
1782
- para = block_from_string input
1783
- assert_equal 'the text <code>asciimath:[x = y]</code> should be passed through as <code>literal</code> text', para.content
1784
- end
1785
-
1786
- test 'should not process an escaped passthrough macro inside a monospaced phrase' do
1787
- input = 'use the `\pass:c[]` macro'
1788
- para = block_from_string input
1789
- assert_equal 'use the <code>pass:c[]</code> macro', para.content
1790
- end
1791
-
1792
- test 'should not process an escaped passthrough macro inside a monospaced phrase with attributes' do
1793
- input = 'use the [syntax]`\pass:c[]` macro'
1794
- para = block_from_string input
1795
- assert_equal 'use the <code class="syntax">pass:c[]</code> macro', para.content
1796
- end
1797
-
1798
- test 'should honor an escaped single plus passthrough inside a monospaced phrase' do
1799
- input = 'use `\+{author}+` to show an attribute reference'
1800
- para = block_from_string input
1801
- assert_equal 'use <code>+{author}+</code> to show an attribute reference', para.content
1802
- end
1803
-
1804
- test 'should not recognize stem macro with no content' do
1805
- input = 'stem:[]'
1806
- para = block_from_string input
1807
- assert_equal input, para.content
1808
- end
1809
-
1810
- test 'should passthrough text in stem macro and surround with AsciiMath delimiters if stem attribute is asciimath, empty, or not set' do
1811
- [
1812
- {},
1813
- {'stem' => ''},
1814
- {'stem' => 'asciimath'},
1815
- {'stem' => 'bogus'}
1816
- ].each do |attributes|
1817
- input = 'stem:[x/x={(1,if x!=0),(text{undefined},if x=0):}]'
1818
- para = block_from_string input, :attributes => attributes
1819
- assert_equal '\$x/x={(1,if x!=0),(text{undefined},if x=0):}\$', para.content
1820
- end
1821
- end
1822
-
1823
- test 'should passthrough text in stem macro and surround with LaTeX math delimiters if stem attribute is latexmath, latex, or tex' do
1824
- [
1825
- {'stem' => 'latexmath'},
1826
- {'stem' => 'latex'},
1827
- {'stem' => 'tex'}
1828
- ].each do |attributes|
1829
- input = 'stem:[C = \alpha + \beta Y^{\gamma} + \epsilon]'
1830
- para = block_from_string input, :attributes => attributes
1831
- assert_equal '\(C = \alpha + \beta Y^{\gamma} + \epsilon\)', para.content
1832
- end
1833
- end
1834
-
1835
- test 'should apply substitutions specified on stem macro' do
1836
- input = 'stem:c,a[sqrt(x) <=> {solve-for-x}]'
1837
- para = block_from_string input, :attributes => {'stem' => 'asciimath', 'solve-for-x' => '13'}
1838
- assert_equal '\$sqrt(x) &lt;=&gt; 13\$', para.content
1839
- end
1840
-
1841
- test 'should not recognize stem macro with invalid substitution list' do
1842
- [',', '42', 'a,'].each do |subs|
1843
- input = %(stem:#{subs}[x^2])
1844
- para = block_from_string input, :attributes => {'stem' => 'asciimath'}
1845
- assert_equal %(stem:#{subs}[x^2]), para.content
1846
- end
1847
- end
1848
- end
1849
- end
1850
-
1851
- context 'Replacements' do
1852
- test 'unescapes XML entities' do
1853
- para = block_from_string '< &quot; &there4; &#34; &#x22; >'
1854
- assert_equal '&lt; &quot; &there4; &#34; &#x22; &gt;', para.apply_subs(para.source)
1855
- end
1856
-
1857
- test 'replaces arrows' do
1858
- para = block_from_string '<- -> <= => \<- \-> \<= \=>'
1859
- assert_equal '&#8592; &#8594; &#8656; &#8658; &lt;- -&gt; &lt;= =&gt;', para.apply_subs(para.source)
1860
- end
1861
-
1862
- test 'replaces dashes' do
1863
- para = block_from_string %(-- foo foo--bar foo\\--bar foo -- bar foo \\-- bar
1864
- stuff in between
1865
- -- foo
1866
- stuff in between
1867
- foo --
1868
- stuff in between
1869
- foo --)
1870
- expected = '&#8201;&#8212;&#8201;foo foo&#8212;&#8203;bar foo--bar foo&#8201;&#8212;&#8201;bar foo -- bar
1871
- stuff in between&#8201;&#8212;&#8201;foo
1872
- stuff in between
1873
- foo&#8201;&#8212;&#8201;stuff in between
1874
- foo&#8201;&#8212;&#8201;'
1875
- assert_equal expected, para.sub_replacements(para.source)
1876
- end
1877
-
1878
- test 'replaces dashes between multibyte word characters' do
1879
- para = block_from_string %(富--巴)
1880
- expected = '富&#8212;&#8203;巴'
1881
- assert_equal expected, para.sub_replacements(para.source)
1882
- end if ::RUBY_MIN_VERSION_1_9
1883
-
1884
- test 'replaces marks' do
1885
- para = block_from_string '(C) (R) (TM) \(C) \(R) \(TM)'
1886
- assert_equal '&#169; &#174; &#8482; (C) (R) (TM)', para.sub_replacements(para.source)
1887
- end
1888
-
1889
- test 'preserves entity references' do
1890
- input = '&amp; &#169; &#10004; &#128512; &#x2022; &#x1f600;'
1891
- result = convert_inline_string input
1892
- assert_equal input, result
1893
- end
1894
-
1895
- test 'only preserves named entities with two or more letters' do
1896
- input = '&amp; &a; &gt;'
1897
- result = convert_inline_string input
1898
- assert_equal '&amp; &amp;a; &gt;', result
1899
- end
1900
-
1901
- test 'replaces punctuation' do
1902
- para = block_from_string %(John's Hideout is the Whites`' place... foo\\'bar)
1903
- assert_equal "John&#8217;s Hideout is the Whites&#8217; place&#8230;&#8203; foo'bar", para.sub_replacements(para.source)
1904
- end
1905
-
1906
- test 'should replace right single quote marks' do
1907
- given = [
1908
- %(`'Twas the night),
1909
- %(a `'57 Chevy!),
1910
- %(the whites`' place),
1911
- %(the whites`'.),
1912
- %(the whites`'--where the wild things are),
1913
- %(the whites`'\nhave),
1914
- %(It's Mary`'s little lamb.),
1915
- %(consecutive single quotes '' are not modified),
1916
- %(he is 6' tall),
1917
- %(\\`')
1918
- ]
1919
- expected = [
1920
- %(&#8217;Twas the night),
1921
- %(a &#8217;57 Chevy!),
1922
- %(the whites&#8217; place),
1923
- %(the whites&#8217;.),
1924
- %(the whites&#8217;--where the wild things are),
1925
- %(the whites&#8217;\nhave),
1926
- %(It&#8217;s Mary&#8217;s little lamb.),
1927
- %(consecutive single quotes '' are not modified),
1928
- %(he is 6' tall),
1929
- %(`')
1930
- ]
1931
- given.size.times {|i|
1932
- para = block_from_string given[i]
1933
- assert_equal expected[i], para.sub_replacements(para.source)
1934
- }
1935
- end
1936
- end
1937
-
1938
- context 'Post replacements' do
1939
- test 'line break inserted after line with line break character' do
1940
- para = block_from_string("First line +\nSecond line")
1941
- result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1942
- assert_equal 'First line<br>', result.first
1943
- end
1944
-
1945
- test 'line break inserted after line wrap with hardbreaks enabled' do
1946
- para = block_from_string("First line\nSecond line", :attributes => {'hardbreaks' => ''})
1947
- result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1948
- assert_equal 'First line<br>', result.first
1949
- end
1950
-
1951
- test 'line break character stripped from end of line with hardbreaks enabled' do
1952
- para = block_from_string("First line +\nSecond line", :attributes => {'hardbreaks' => ''})
1953
- result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1954
- assert_equal 'First line<br>', result.first
1955
- end
1956
-
1957
- test 'line break not inserted for single line with hardbreaks enabled' do
1958
- para = block_from_string('First line', :attributes => {'hardbreaks' => ''})
1959
- result = para.apply_subs para.lines, (para.expand_subs :post_replacements)
1960
- assert_equal 'First line', result.first
1961
- end
1962
- end
1963
-
1964
- context 'Resolve subs' do
1965
- test 'should resolve subs for block' do
1966
- block = Asciidoctor::Block.new(empty_document, :paragraph)
1967
- block.attributes['subs'] = 'quotes,normal'
1968
- block.lock_in_subs
1969
- assert_equal [:quotes, :specialcharacters, :attributes, :replacements, :macros, :post_replacements], block.subs
1970
- end
1971
-
1972
- test 'should resolve specialcharacters sub as highlight for source block when source highlighter is coderay' do
1973
- doc = empty_document :attributes => {'source-highlighter' => 'coderay'}
1974
- block = Asciidoctor::Block.new(doc, :listing, :content_model => :verbatim)
1975
- block.style = 'source'
1976
- block.attributes['subs'] = 'specialcharacters'
1977
- block.attributes['language'] = 'ruby'
1978
- block.lock_in_subs
1979
- assert_equal [:highlight], block.subs
1980
- end
1981
-
1982
- test 'should resolve specialcharacters sub as highlight for source block when source highlighter is pygments' do
1983
- doc = empty_document :attributes => {'source-highlighter' => 'pygments'}
1984
- block = Asciidoctor::Block.new(doc, :listing, :content_model => :verbatim)
1985
- block.style = 'source'
1986
- block.attributes['subs'] = 'specialcharacters'
1987
- block.attributes['language'] = 'ruby'
1988
- block.lock_in_subs
1989
- assert_equal [:highlight], block.subs
1990
- end
1991
-
1992
- test 'should not resolve specialcharacters sub as highlight for source block when source highlighter is not set' do
1993
- doc = empty_document
1994
- block = Asciidoctor::Block.new(doc, :listing, :content_model => :verbatim)
1995
- block.style = 'source'
1996
- block.attributes['subs'] = 'specialcharacters'
1997
- block.attributes['language'] = 'ruby'
1998
- block.lock_in_subs
1999
- assert_equal [:specialcharacters], block.subs
2000
- end
2001
-
2002
- test 'should not use subs if subs option passed to block constructor is nil' do
2003
- doc = empty_document
2004
- block = Asciidoctor::Block.new doc, :paragraph, :source => '*bold* _italic_', :subs => nil, :attributes => {'subs' => 'quotes'}
2005
- assert_empty block.subs
2006
- block.lock_in_subs
2007
- assert_empty block.subs
2008
- end
2009
-
2010
- test 'should not use subs if subs option passed to block constructor is empty array' do
2011
- doc = empty_document
2012
- block = Asciidoctor::Block.new doc, :paragraph, :source => '*bold* _italic_', :subs => [], :attributes => {'subs' => 'quotes'}
2013
- assert_empty block.subs
2014
- block.lock_in_subs
2015
- assert_empty block.subs
2016
- end
2017
-
2018
- test 'should use subs from subs option passed to block constructor' do
2019
- doc = empty_document
2020
- block = Asciidoctor::Block.new doc, :paragraph, :source => '*bold* _italic_', :subs => [:specialcharacters], :attributes => {'subs' => 'quotes'}
2021
- assert_equal [:specialcharacters], block.subs
2022
- block.lock_in_subs
2023
- assert_equal [:specialcharacters], block.subs
2024
- end
2025
-
2026
- test 'should use subs from subs attribute if subs option is not passed to block constructor' do
2027
- doc = empty_document
2028
- block = Asciidoctor::Block.new doc, :paragraph, :source => '*bold* _italic_', :attributes => {'subs' => 'quotes'}
2029
- assert_empty block.subs
2030
- # in this case, we have to call lock_in_subs to resolve the subs
2031
- block.lock_in_subs
2032
- assert_equal [:quotes], block.subs
2033
- end
2034
-
2035
- test 'should use subs from subs attribute if subs option passed to block constructor is :default' do
2036
- doc = empty_document
2037
- block = Asciidoctor::Block.new doc, :paragraph, :source => '*bold* _italic_', :subs => :default, :attributes => {'subs' => 'quotes'}
2038
- assert_equal [:quotes], block.subs
2039
- block.lock_in_subs
2040
- assert_equal [:quotes], block.subs
2041
- end
2042
-
2043
- test 'should use built-in subs if subs option passed to block constructor is :default and subs attribute is absent' do
2044
- doc = empty_document
2045
- block = Asciidoctor::Block.new doc, :paragraph, :source => '*bold* _italic_', :subs => :default
2046
- assert_equal [:specialcharacters, :quotes, :attributes, :replacements, :macros, :post_replacements], block.subs
2047
- block.lock_in_subs
2048
- assert_equal [:specialcharacters, :quotes, :attributes, :replacements, :macros, :post_replacements], block.subs
2049
- end
2050
- end
2051
-
2052
- # TODO move to helpers_test.rb
2053
- context 'Helpers' do
2054
- test 'should URI encode non-word characters generally' do
2055
- given = ' /%&?\\'
2056
- expect = '%20%2F%25%26%3F%5C'
2057
- assert_equal expect, (Asciidoctor::Helpers.uri_encode given)
2058
- end
2059
-
2060
- test 'should not URI select non-word characters' do
2061
- given = '-.!~*\';:@=+$,()[]'
2062
- expect = given
2063
- assert_equal expect, (Asciidoctor::Helpers.uri_encode given)
2064
- end
2065
- end
2066
- end