qiita_marker 0.23.2.0 → 0.23.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ #include "cmark-gfm.h"
2
+ #include "cmark_ctype.h"
3
+ #include "config.h"
4
+
5
+ static bool is_wordchar(char c) {
6
+ return cmark_isalnum(c) || c == '_' || c == '-';
7
+ }
8
+
9
+ bool is_part_of_mention(unsigned char *data, bufsize_t offset) {
10
+ int i;
11
+ int lookbehind_limit = (int)-offset;
12
+ char character;
13
+
14
+ for (i = 0; i >= lookbehind_limit; i--) {
15
+ character = data[i];
16
+
17
+ if (is_wordchar(character)) {
18
+ // Continue lookbehind.
19
+ } else if (character == '@') {
20
+ if (i == offset) {
21
+ // The "@" is at beginning of the text. (e.g. "@foo")
22
+ return true;
23
+ } else {
24
+ // Check if the previous character of the "@" is alphanumeric or not.
25
+ // " @foo" and "あ@foo" are mentions.
26
+ // "a@foo" is not a mention.
27
+ char prev_character = data[i - 1];
28
+ return !cmark_isalnum(prev_character);
29
+ }
30
+ } else {
31
+ // Found non-mention character, so this is not a mention.
32
+ return false;
33
+ }
34
+ }
35
+
36
+ return false;
37
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef QFM_MENTION_NO_EMPHASIS
2
+ #define QFM_MENTION_NO_EMPHASIS
3
+
4
+ #include "cmark-gfm.h"
5
+
6
+ bool is_part_of_mention(unsigned char *data, bufsize_t offset);
7
+
8
+ #endif
@@ -0,0 +1,291 @@
1
+ /* Generated by re2c 1.3 */
2
+
3
+ #include "qfm_scanners.h"
4
+ #include <stdlib.h>
5
+
6
+ bufsize_t _qfm_scan_at(bufsize_t (*scanner)(const unsigned char *),
7
+ unsigned char *ptr, int len, bufsize_t offset) {
8
+ bufsize_t res;
9
+
10
+ if (ptr == NULL || offset >= len) {
11
+ return 0;
12
+ } else {
13
+ unsigned char lim = ptr[len];
14
+
15
+ ptr[len] = '\0';
16
+ res = scanner(ptr + offset);
17
+ ptr[len] = lim;
18
+ }
19
+
20
+ return res;
21
+ }
22
+
23
+ // Scan an opening qfm_custom_block fence.
24
+ bufsize_t _scan_open_qfm_custom_block_fence(const unsigned char *p) {
25
+ const unsigned char *marker = NULL;
26
+ const unsigned char *start = p;
27
+
28
+ {
29
+ unsigned char yych;
30
+ static const unsigned char yybm[] = {
31
+ 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 0,
32
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
33
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
34
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
35
+ 128, 128, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
36
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
37
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
38
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
39
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
40
+ 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49
+ 0, 0, 0, 0,
50
+ };
51
+ yych = *p;
52
+ if (yych == ':')
53
+ goto yy4;
54
+ ++p;
55
+ yy3 : { return 0; }
56
+ yy4:
57
+ yych = *(marker = ++p);
58
+ if (yych != ':')
59
+ goto yy3;
60
+ yych = *++p;
61
+ if (yybm[0 + yych] & 64) {
62
+ goto yy7;
63
+ }
64
+ yy6:
65
+ p = marker;
66
+ goto yy3;
67
+ yy7:
68
+ yych = *++p;
69
+ if (yybm[0 + yych] & 64) {
70
+ goto yy7;
71
+ }
72
+ if (yych <= 0xDF) {
73
+ if (yych <= '\f') {
74
+ if (yych <= 0x00)
75
+ goto yy6;
76
+ if (yych == '\n') {
77
+ marker = p;
78
+ goto yy11;
79
+ }
80
+ marker = p;
81
+ } else {
82
+ if (yych <= '\r') {
83
+ marker = p;
84
+ goto yy11;
85
+ }
86
+ if (yych <= 0x7F) {
87
+ marker = p;
88
+ goto yy9;
89
+ }
90
+ if (yych <= 0xC1)
91
+ goto yy6;
92
+ marker = p;
93
+ goto yy13;
94
+ }
95
+ } else {
96
+ if (yych <= 0xEF) {
97
+ if (yych <= 0xE0) {
98
+ marker = p;
99
+ goto yy14;
100
+ }
101
+ if (yych == 0xED) {
102
+ marker = p;
103
+ goto yy16;
104
+ }
105
+ marker = p;
106
+ goto yy15;
107
+ } else {
108
+ if (yych <= 0xF0) {
109
+ marker = p;
110
+ goto yy17;
111
+ }
112
+ if (yych <= 0xF3) {
113
+ marker = p;
114
+ goto yy18;
115
+ }
116
+ if (yych <= 0xF4) {
117
+ marker = p;
118
+ goto yy19;
119
+ }
120
+ goto yy6;
121
+ }
122
+ }
123
+ yy9:
124
+ yych = *++p;
125
+ if (yybm[0 + yych] & 128) {
126
+ goto yy9;
127
+ }
128
+ if (yych <= 0xEC) {
129
+ if (yych <= 0xC1) {
130
+ if (yych <= 0x00)
131
+ goto yy6;
132
+ if (yych >= 0x0E)
133
+ goto yy6;
134
+ } else {
135
+ if (yych <= 0xDF)
136
+ goto yy13;
137
+ if (yych <= 0xE0)
138
+ goto yy14;
139
+ goto yy15;
140
+ }
141
+ } else {
142
+ if (yych <= 0xF0) {
143
+ if (yych <= 0xED)
144
+ goto yy16;
145
+ if (yych <= 0xEF)
146
+ goto yy15;
147
+ goto yy17;
148
+ } else {
149
+ if (yych <= 0xF3)
150
+ goto yy18;
151
+ if (yych <= 0xF4)
152
+ goto yy19;
153
+ goto yy6;
154
+ }
155
+ }
156
+ yy11:
157
+ ++p;
158
+ p = marker;
159
+ { return (bufsize_t)(p - start); }
160
+ yy13:
161
+ yych = *++p;
162
+ if (yych <= 0x7F)
163
+ goto yy6;
164
+ if (yych <= 0xBF)
165
+ goto yy9;
166
+ goto yy6;
167
+ yy14:
168
+ yych = *++p;
169
+ if (yych <= 0x9F)
170
+ goto yy6;
171
+ if (yych <= 0xBF)
172
+ goto yy13;
173
+ goto yy6;
174
+ yy15:
175
+ yych = *++p;
176
+ if (yych <= 0x7F)
177
+ goto yy6;
178
+ if (yych <= 0xBF)
179
+ goto yy13;
180
+ goto yy6;
181
+ yy16:
182
+ yych = *++p;
183
+ if (yych <= 0x7F)
184
+ goto yy6;
185
+ if (yych <= 0x9F)
186
+ goto yy13;
187
+ goto yy6;
188
+ yy17:
189
+ yych = *++p;
190
+ if (yych <= 0x8F)
191
+ goto yy6;
192
+ if (yych <= 0xBF)
193
+ goto yy15;
194
+ goto yy6;
195
+ yy18:
196
+ yych = *++p;
197
+ if (yych <= 0x7F)
198
+ goto yy6;
199
+ if (yych <= 0xBF)
200
+ goto yy15;
201
+ goto yy6;
202
+ yy19:
203
+ yych = *++p;
204
+ if (yych <= 0x7F)
205
+ goto yy6;
206
+ if (yych <= 0x8F)
207
+ goto yy15;
208
+ goto yy6;
209
+ }
210
+ }
211
+
212
+ // Scan a closing qfm_custom_block fence with length at least len.
213
+ bufsize_t _scan_close_qfm_custom_block_fence(const unsigned char *p) {
214
+ const unsigned char *marker = NULL;
215
+ const unsigned char *start = p;
216
+
217
+ {
218
+ unsigned char yych;
219
+ static const unsigned char yybm[] = {
220
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
221
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
222
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0,
223
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
226
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
227
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
230
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
231
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
232
+ };
233
+ yych = *p;
234
+ if (yych == ':')
235
+ goto yy24;
236
+ ++p;
237
+ yy23 : { return 0; }
238
+ yy24:
239
+ yych = *(marker = ++p);
240
+ if (yych != ':')
241
+ goto yy23;
242
+ yych = *++p;
243
+ if (yybm[0 + yych] & 64) {
244
+ goto yy27;
245
+ }
246
+ yy26:
247
+ p = marker;
248
+ goto yy23;
249
+ yy27:
250
+ yych = *++p;
251
+ if (yybm[0 + yych] & 64) {
252
+ goto yy27;
253
+ }
254
+ if (yych <= '\f') {
255
+ if (yych <= 0x08)
256
+ goto yy26;
257
+ if (yych <= '\t') {
258
+ marker = p;
259
+ goto yy29;
260
+ }
261
+ if (yych <= '\n') {
262
+ marker = p;
263
+ goto yy31;
264
+ }
265
+ goto yy26;
266
+ } else {
267
+ if (yych <= '\r') {
268
+ marker = p;
269
+ goto yy31;
270
+ }
271
+ if (yych != ' ')
272
+ goto yy26;
273
+ marker = p;
274
+ }
275
+ yy29:
276
+ yych = *++p;
277
+ if (yybm[0 + yych] & 128) {
278
+ goto yy29;
279
+ }
280
+ if (yych <= 0x08)
281
+ goto yy26;
282
+ if (yych <= '\n')
283
+ goto yy31;
284
+ if (yych != '\r')
285
+ goto yy26;
286
+ yy31:
287
+ ++p;
288
+ p = marker;
289
+ { return (bufsize_t)(p - start); }
290
+ }
291
+ }
@@ -0,0 +1,20 @@
1
+ #include "chunk.h"
2
+ #include "cmark-gfm.h"
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ bufsize_t _qfm_scan_at(bufsize_t (*scanner)(const unsigned char *),
9
+ unsigned char *ptr, int len, bufsize_t offset);
10
+ bufsize_t _scan_open_qfm_custom_block_fence(const unsigned char *p);
11
+ bufsize_t _scan_close_qfm_custom_block_fence(const unsigned char *p);
12
+
13
+ #define scan_open_qfm_custom_block_fence(c, l, n) \
14
+ _qfm_scan_at(&_scan_open_qfm_custom_block_fence, c, l, n)
15
+ #define scan_close_qfm_custom_block_fence(c, l, n) \
16
+ _qfm_scan_at(&_scan_close_qfm_custom_block_fence, c, l, n)
17
+
18
+ #ifdef __cplusplus
19
+ }
20
+ #endif
@@ -0,0 +1,50 @@
1
+ /*!re2c re2c:flags:no-debug-info = 1; */
2
+ /*!re2c re2c:indent:string = ' '; */
3
+
4
+ #include "qfm_scanners.h"
5
+ #include <stdlib.h>
6
+
7
+ bufsize_t _qfm_scan_at(bufsize_t (*scanner)(const unsigned char *),
8
+ unsigned char *ptr, int len, bufsize_t offset) {
9
+ bufsize_t res;
10
+
11
+ if (ptr == NULL || offset >= len) {
12
+ return 0;
13
+ } else {
14
+ unsigned char lim = ptr[len];
15
+
16
+ ptr[len] = '\0';
17
+ res = scanner(ptr + offset);
18
+ ptr[len] = lim;
19
+ }
20
+
21
+ return res;
22
+ }
23
+
24
+ /*!re2c
25
+ re2c:define:YYCTYPE = "unsigned char";
26
+ re2c:define:YYCURSOR = p;
27
+ re2c:define:YYMARKER = marker;
28
+ re2c:define:YYCTXMARKER = marker;
29
+ re2c:yyfill:enable = 0;
30
+ */
31
+
32
+ // Scan an opening qfm_custom_block fence.
33
+ bufsize_t _scan_open_qfm_custom_block_fence(const unsigned char *p) {
34
+ const unsigned char *marker = NULL;
35
+ const unsigned char *start = p;
36
+ /*!re2c
37
+ [:]{3,} / [^:\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); }
38
+ * { return 0; }
39
+ */
40
+ }
41
+
42
+ // Scan a closing qfm_custom_block fence with length at least len.
43
+ bufsize_t _scan_close_qfm_custom_block_fence(const unsigned char *p) {
44
+ const unsigned char *marker = NULL;
45
+ const unsigned char *start = p;
46
+ /*!re2c
47
+ [:]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); }
48
+ * { return 0; }
49
+ */
50
+ }
@@ -13,7 +13,9 @@ module QiitaMarker
13
13
  SMART: (1 << 10),
14
14
  LIBERAL_HTML_TAG: (1 << 12),
15
15
  FOOTNOTES: (1 << 13),
16
- STRIKETHROUGH_DOUBLE_TILDE: (1 << 14)
16
+ STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
17
+ MENTION_NO_EMPHASIS: (1 << 26),
18
+ AUTOLINK_CLASS_NAME: (1 << 27)
17
19
  }.freeze,
18
20
  render: {
19
21
  DEFAULT: 0,
@@ -28,7 +30,10 @@ module QiitaMarker
28
30
  FOOTNOTES: (1 << 13),
29
31
  STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
30
32
  TABLE_PREFER_STYLE_ATTRIBUTES: (1 << 15),
31
- FULL_INFO_STRING: (1 << 16)
33
+ FULL_INFO_STRING: (1 << 16),
34
+ CODE_DATA_METADATA: (1 << 25),
35
+ MENTION_NO_EMPHASIS: (1 << 26),
36
+ AUTOLINK_CLASS_NAME: (1 << 27)
32
37
  }.freeze,
33
38
  format: %i[html xml commonmark plaintext].freeze
34
39
  }.freeze
@@ -94,6 +94,10 @@ module QiitaMarker
94
94
  out("<pre#{sourcepos(node)}")
95
95
  out(' lang="', node.fence_info.split(/\s+/)[0], '"') if node.fence_info && !node.fence_info.empty?
96
96
  out('><code>')
97
+ elsif option_enabled?(:CODE_DATA_METADATA)
98
+ out("<pre#{sourcepos(node)}><code")
99
+ out(' data-metadata="', node.fence_info, '"') if node.fence_info && !node.fence_info.empty?
100
+ out('>')
97
101
  else
98
102
  out("<pre#{sourcepos(node)}><code")
99
103
  if node.fence_info && !node.fence_info.empty?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QiitaMarker
4
- VERSION = '0.23.2.0'
4
+ VERSION = '0.23.2.3'
5
5
  end
data/qiita_marker.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.version = QiitaMarker::VERSION
10
10
  s.summary = 'Qiita Marker is a Ruby library for Markdown processing, based on CommonMarker.'
11
11
  s.description = 'A Ruby library that is the core module of the Qiita-specified markdown processor.'
12
- s.authors = ['Increments Inc.']
12
+ s.authors = ['Qiita Inc.']
13
13
  s.homepage = 'https://github.com/increments/qiita_marker'
14
14
  s.license = 'MIT'
15
15
 
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('test_helper')
4
+
5
+ describe 'TestQfmAutolinkClassName' do
6
+ let(:options) { %i[AUTOLINK_CLASS_NAME] }
7
+ let(:extensions) { %i[autolink] }
8
+ let(:text) do
9
+ <<~MD
10
+ https://example.com
11
+ <https://example.com>
12
+ [Example](https://example.com)
13
+ test@example.com
14
+ MD
15
+ end
16
+ let(:doc) { QiitaMarker.render_doc(text, options, extensions) }
17
+ let(:expected) do
18
+ <<~HTML
19
+ <p><a href="https://example.com" class="autolink">https://example.com</a>
20
+ <a href="https://example.com">https://example.com</a>
21
+ <a href="https://example.com">Example</a>
22
+ <a href="mailto:test@example.com" class="autolink">test@example.com</a></p>
23
+ HTML
24
+ end
25
+ let(:rendered_html) { doc.to_html(options, extensions) }
26
+
27
+ it "appends class name to extension's autolinks" do
28
+ assert_equal(expected, rendered_html)
29
+ end
30
+
31
+ describe 'without AUTOLINK_CLASS_NAME option' do
32
+ let(:options) { %i[DEFAULT] }
33
+ let(:expected) do
34
+ <<~HTML
35
+ <p><a href="https://example.com">https://example.com</a>
36
+ <a href="https://example.com">https://example.com</a>
37
+ <a href="https://example.com">Example</a>
38
+ <a href="mailto:test@example.com">test@example.com</a></p>
39
+ HTML
40
+ end
41
+
42
+ it "does not append class name to extension's autolink" do
43
+ assert_equal(expected, rendered_html)
44
+ end
45
+ end
46
+
47
+ describe 'without autolink extension' do
48
+ let(:extensions) { %i[] }
49
+ let(:expected) do
50
+ <<~HTML
51
+ <p>https://example.com
52
+ <a href="https://example.com">https://example.com</a>
53
+ <a href="https://example.com">Example</a>
54
+ test@example.com</p>
55
+ HTML
56
+ end
57
+
58
+ it 'does not append class name' do
59
+ assert_equal(expected, rendered_html)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('test_helper')
4
+
5
+ class TestQfmCodeDataMetadata < Minitest::Test
6
+ def test_to_html
7
+ text = <<~MD
8
+ ```ruby:example main.rb
9
+ puts :foo
10
+ ```
11
+ MD
12
+ doc = render_doc(text)
13
+ expected = <<~HTML
14
+ <pre><code data-metadata="ruby:example main.rb">puts :foo
15
+ </code></pre>
16
+ HTML
17
+
18
+ assert_equal(expected, doc.to_html(:CODE_DATA_METADATA))
19
+ assert_equal(expected, QiitaMarker::HtmlRenderer.new(options: :CODE_DATA_METADATA).render(doc))
20
+ end
21
+
22
+ def test_with_character_reference
23
+ text = <<~MD
24
+ ```ruby:example&#x20;main.rb
25
+ puts :foo
26
+ ```
27
+ MD
28
+ doc = render_doc(text)
29
+ expected = <<~HTML
30
+ <pre><code data-metadata="ruby:example main.rb">puts :foo
31
+ </code></pre>
32
+ HTML
33
+
34
+ assert_equal(expected, doc.to_html(:CODE_DATA_METADATA))
35
+ assert_equal(expected, QiitaMarker::HtmlRenderer.new(options: :CODE_DATA_METADATA).render(doc))
36
+ end
37
+
38
+ def render_doc(markdown)
39
+ QiitaMarker.render_doc(markdown, :DEFAULT, [])
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('test_helper')
4
+
5
+ class TestQfmCustomBlock < Minitest::Test
6
+ def setup
7
+ text = <<~MD
8
+ :::foo bar
9
+ message
10
+
11
+ - list1
12
+ - list2
13
+
14
+ ```ruby
15
+ puts 'hello'
16
+ ```
17
+
18
+ <div>html block</div>
19
+ :::
20
+ MD
21
+ @doc = QiitaMarker.render_doc(text, %i[UNSAFE], %i[custom_block])
22
+ @expected = <<~HTML
23
+ <div data-type="customblock" data-metadata="foo bar">
24
+ <p>message</p>
25
+ <ul>
26
+ <li>list1</li>
27
+ <li>list2</li>
28
+ </ul>
29
+ <pre><code class="language-ruby">puts 'hello'
30
+ </code></pre>
31
+ <div>html block</div>
32
+ </div>
33
+ HTML
34
+ end
35
+
36
+ def test_to_html
37
+ assert_equal(@expected, @doc.to_html(%i[UNSAFE], %i[custom_block]))
38
+ end
39
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TestQfmMentionNoEmphasis < Minitest::Test
6
+ describe 'with mention_no_emphasis option' do
7
+ [
8
+ ['@_username_', false],
9
+ ['@__username__', false],
10
+ ['@___username___', false],
11
+ ['@user__name__', false],
12
+ ['@some__user__name__', false],
13
+ [' @_username_', false],
14
+ ['あ@_username_', false],
15
+ ['A@_username_', true],
16
+ ['@*username*', true],
17
+ ['_foo_', true],
18
+ ['_', false],
19
+ ['_foo @username_', false],
20
+ ['__foo @username__', false],
21
+ ['___foo @username___', false]
22
+ ].each do |text, emphasize|
23
+ describe "with text #{text.inspect}" do
24
+ if emphasize
25
+ it 'emphasizes the text' do
26
+ QiitaMarker.render_html(text, :MENTION_NO_EMPHASIS).tap do |out|
27
+ assert_match(/(<em>|<strong>)/, out.chomp)
28
+ end
29
+ end
30
+ else
31
+ it 'does not emphasize the text' do
32
+ QiitaMarker.render_html(text, :MENTION_NO_EMPHASIS).tap do |out|
33
+ assert_match "<p>#{text.strip}</p>", out.chomp
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe 'without mention_no_emphasis option' do
42
+ describe 'with text "@_username_"' do
43
+ text = '@_username_'
44
+ it 'emphasizes the text' do
45
+ QiitaMarker.render_html(text, :DEFAULT, %i[]).tap do |out|
46
+ assert_match(/<em>/, out.chomp)
47
+ end
48
+ end
49
+ end
50
+
51
+ describe 'with text "_foo @username_"' do
52
+ text = '_foo @username_'
53
+ it 'emphasizes the text' do
54
+ QiitaMarker.render_html(text, :DEFAULT, %i[]).tap do |out|
55
+ assert_match(/<em>/, out.chomp)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end