greenmat 3.5.1.0 → 3.5.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +47 -0
- data/CHANGELOG.md +18 -0
- data/Rakefile +2 -1
- data/ext/greenmat/gm_markdown.c +3 -0
- data/ext/greenmat/gm_render.c +8 -0
- data/ext/greenmat/html.c +48 -0
- data/ext/greenmat/html_blocks.h +70 -68
- data/ext/greenmat/markdown.c +139 -0
- data/ext/greenmat/markdown.h +3 -1
- data/greenmat.gemspec +2 -2
- data/lib/greenmat/version.rb +1 -1
- data/spec/greenmat/markdown_spec.rb +43 -0
- data/test/html5_test.rb +15 -6
- metadata +7 -7
- data/.travis.yml +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb401dc6f336d00057b17f5e59b2c9b99a1d55e3c7949d662aa06e781a8b8284
|
4
|
+
data.tar.gz: 0e3acbf68f1ec78bc8b2832a2ed163d350b6576d6f1b7de40b5aafe0b4e00a32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a64e6ecef30e67ff86c96a1d9a17a7f86ab6282264729952a6b1cb72a3fe7b530a01a5a5b285cd8369998196c9eb3903825d9b5f2c332bcfd2a835750ec5e50
|
7
|
+
data.tar.gz: 5cf349212cf416ee2a0bc0dda663297b3166954c4552d5160ce1f9ebeace107cb238e90c3630cdd85f3bd144b7750c2dba1f57b83b8314eedce1d9796072f0f0
|
@@ -0,0 +1,47 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
push:
|
6
|
+
branches:
|
7
|
+
- master
|
8
|
+
workflow_dispatch:
|
9
|
+
|
10
|
+
permissions:
|
11
|
+
contents: read
|
12
|
+
|
13
|
+
jobs:
|
14
|
+
test:
|
15
|
+
strategy:
|
16
|
+
fail-fast: false
|
17
|
+
matrix:
|
18
|
+
os: ['ubuntu-18.04', 'macos-latest']
|
19
|
+
ruby: ['2.5', '2.6', '2.7', '3.0', '3.1']
|
20
|
+
experimental: [false]
|
21
|
+
include:
|
22
|
+
- os: 'ubuntu-18.04'
|
23
|
+
ruby: 'head'
|
24
|
+
experimental: true
|
25
|
+
runs-on: ${{ matrix.os }}
|
26
|
+
continue-on-error: ${{ matrix.experimental }}
|
27
|
+
env:
|
28
|
+
BUNDLE_WITHOUT: benchmark
|
29
|
+
steps:
|
30
|
+
- uses: actions/checkout@v2
|
31
|
+
- name: Install prerequirements
|
32
|
+
if: runner.os == 'Linux'
|
33
|
+
run: |
|
34
|
+
sudo apt-get update
|
35
|
+
sudo apt-get install tidy
|
36
|
+
- uses: ruby/setup-ruby@v1
|
37
|
+
with:
|
38
|
+
ruby-version: ${{ matrix.ruby }}
|
39
|
+
bundler-cache: true
|
40
|
+
- name: Build
|
41
|
+
run: bundle exec rake compile
|
42
|
+
- name: Check prerequirements
|
43
|
+
run: |
|
44
|
+
tidy --version
|
45
|
+
bin/greenmat --version
|
46
|
+
- name: Run test
|
47
|
+
run: bundle exec rake
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,24 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## v3.5.1.3
|
6
|
+
|
7
|
+
* Remove support for ruby 2.5 and below
|
8
|
+
* Bump nokogiri from 1.6.0 to 1.11.7
|
9
|
+
* Support cpu archtecture for arm64/aarch64 systems (like Apple's M1)
|
10
|
+
* Change ci platform to Github Actions
|
11
|
+
|
12
|
+
## v3.5.1.2
|
13
|
+
|
14
|
+
* Support custom block notation.
|
15
|
+
* It starts with `:::` and ends with `:::`.
|
16
|
+
* Output a `<div data-type="customblock" data-metadata="">` element.
|
17
|
+
* Passes the string following `:::` to the `data-metadata` attribute.
|
18
|
+
|
19
|
+
## v3.5.1.1
|
20
|
+
|
21
|
+
* Unsupport details and summary tags.
|
22
|
+
|
5
23
|
## v3.5.1.0
|
6
24
|
|
7
25
|
* Update base Redcarpet version to 3.5.1.
|
data/Rakefile
CHANGED
@@ -4,6 +4,7 @@ require 'rake/extensiontask'
|
|
4
4
|
require 'digest/md5'
|
5
5
|
|
6
6
|
task :default => [:test, :spec]
|
7
|
+
task :spec => [:compile]
|
7
8
|
|
8
9
|
# Gem Spec
|
9
10
|
gem_spec = Gem::Specification.load('greenmat.gemspec')
|
@@ -34,7 +35,7 @@ task 'test:conformance' => :compile do |t|
|
|
34
35
|
lib_dir = "#{pwd}/lib"
|
35
36
|
|
36
37
|
chdir("test/MarkdownTest_#{version}") do
|
37
|
-
sh "RUBYLIB
|
38
|
+
sh "RUBYLIB=\"$RUBYLIB:#{lib_dir}\" ./MarkdownTest.pl --script='#{script}' --tidy"
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
data/ext/greenmat/gm_markdown.c
CHANGED
@@ -48,6 +48,9 @@ static void rb_greenmat_md_flags(VALUE hash, unsigned int *enabled_extensions_p)
|
|
48
48
|
if (rb_hash_lookup(hash, CSTR2SYM("fenced_code_blocks")) == Qtrue)
|
49
49
|
extensions |= MKDEXT_FENCED_CODE;
|
50
50
|
|
51
|
+
if (rb_hash_lookup(hash, CSTR2SYM("fenced_custom_blocks")) == Qtrue)
|
52
|
+
extensions |= MKDEXT_FENCED_CUSTOM;
|
53
|
+
|
51
54
|
if (rb_hash_lookup(hash, CSTR2SYM("disable_indented_code_blocks")) == Qtrue)
|
52
55
|
extensions |= MKDEXT_DISABLE_INDENTED_CODE;
|
53
56
|
|
data/ext/greenmat/gm_render.c
CHANGED
@@ -54,6 +54,12 @@ rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, v
|
|
54
54
|
BLOCK_CALLBACK("block_code", 2, buf2str(text), buf2str(lang));
|
55
55
|
}
|
56
56
|
|
57
|
+
static void
|
58
|
+
rndr_blockcustom(struct buf *ob, const struct buf *text, const struct buf *type, void *opaque)
|
59
|
+
{
|
60
|
+
BLOCK_CALLBACK("block_custom", 2, buf2str(text), buf2str(type));
|
61
|
+
}
|
62
|
+
|
57
63
|
static void
|
58
64
|
rndr_blockquote(struct buf *ob, const struct buf *text, void *opaque)
|
59
65
|
{
|
@@ -293,6 +299,7 @@ rndr_link_attributes(struct buf *ob, const struct buf *url, void *opaque)
|
|
293
299
|
|
294
300
|
static struct sd_callbacks rb_greenmat_callbacks = {
|
295
301
|
rndr_blockcode,
|
302
|
+
rndr_blockcustom,
|
296
303
|
rndr_blockquote,
|
297
304
|
rndr_raw_block,
|
298
305
|
rndr_header,
|
@@ -331,6 +338,7 @@ static struct sd_callbacks rb_greenmat_callbacks = {
|
|
331
338
|
|
332
339
|
static const char *rb_greenmat_method_names[] = {
|
333
340
|
"block_code",
|
341
|
+
"block_custom",
|
334
342
|
"block_quote",
|
335
343
|
"block_html",
|
336
344
|
"header",
|
data/ext/greenmat/html.c
CHANGED
@@ -120,6 +120,52 @@ rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, vo
|
|
120
120
|
return 1;
|
121
121
|
}
|
122
122
|
|
123
|
+
static void
|
124
|
+
rndr_blockcustom(struct buf *ob, const struct buf *text, const struct buf *type, void *opaque)
|
125
|
+
{
|
126
|
+
struct html_renderopt *options = opaque;
|
127
|
+
|
128
|
+
if (ob->size) bufputc(ob, '\n');
|
129
|
+
|
130
|
+
if (type && type->size) {
|
131
|
+
size_t i, cls;
|
132
|
+
if (options->flags & HTML_PRETTIFY) {
|
133
|
+
BUFPUTSL(ob, "<div data-type=\"customblock prettyprint\" data-metadata=\"");
|
134
|
+
cls++;
|
135
|
+
} else {
|
136
|
+
BUFPUTSL(ob, "<div data-type=\"customblock\" data-metadata=\"");
|
137
|
+
}
|
138
|
+
|
139
|
+
for (i = 0, cls = 0; i < type->size; ++i, ++cls) {
|
140
|
+
while (i < type->size && isspace(type->data[i]))
|
141
|
+
i++;
|
142
|
+
|
143
|
+
if (i < type->size) {
|
144
|
+
size_t org = i;
|
145
|
+
while (i < type->size && is_non_space(type->data[i]))
|
146
|
+
i++;
|
147
|
+
|
148
|
+
if (type->data[org] == '.')
|
149
|
+
org++;
|
150
|
+
|
151
|
+
if (cls) bufputc(ob, ' ');
|
152
|
+
escape_html(ob, type->data + org, i - org);
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
BUFPUTSL(ob, "\">");
|
157
|
+
} else if (options->flags & HTML_PRETTIFY) {
|
158
|
+
BUFPUTSL(ob, "<div data-type=\"customblock prettyprint\">");
|
159
|
+
} else {
|
160
|
+
BUFPUTSL(ob, "<div data-type=\"customblock\">");
|
161
|
+
}
|
162
|
+
|
163
|
+
if (text)
|
164
|
+
escape_html(ob, text->data, text->size);
|
165
|
+
|
166
|
+
BUFPUTSL(ob, "</div>\n");
|
167
|
+
}
|
168
|
+
|
123
169
|
static void
|
124
170
|
rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque)
|
125
171
|
{
|
@@ -749,6 +795,7 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio
|
|
749
795
|
NULL,
|
750
796
|
NULL,
|
751
797
|
NULL,
|
798
|
+
NULL,
|
752
799
|
toc_header,
|
753
800
|
NULL,
|
754
801
|
NULL,
|
@@ -794,6 +841,7 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options,
|
|
794
841
|
{
|
795
842
|
static const struct sd_callbacks cb_default = {
|
796
843
|
rndr_blockcode,
|
844
|
+
rndr_blockcustom,
|
797
845
|
rndr_blockquote,
|
798
846
|
rndr_raw_block,
|
799
847
|
rndr_header,
|
data/ext/greenmat/html_blocks.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
/* C code produced by gperf version 3.0.
|
1
|
+
/* C code produced by gperf version 3.0.4 */
|
2
2
|
/* Command-line: gperf -N find_block_tag -H hash_block_tag -C -c -E --ignore-case html_block_names.txt */
|
3
|
-
/* See
|
3
|
+
/* See http://git.io/RN0ncw for the list of recognized elements */
|
4
4
|
/* Computed positions: -k'1-2' */
|
5
5
|
|
6
6
|
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
@@ -30,7 +30,7 @@
|
|
30
30
|
error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
|
31
31
|
#endif
|
32
32
|
|
33
|
-
/* maximum key range =
|
33
|
+
/* maximum key range = 67, duplicates = 0 */
|
34
34
|
|
35
35
|
#ifndef GPERF_DOWNCASE
|
36
36
|
#define GPERF_DOWNCASE 1
|
@@ -94,34 +94,34 @@ hash_block_tag (str, len)
|
|
94
94
|
{
|
95
95
|
static const unsigned char asso_values[] =
|
96
96
|
{
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
0,
|
105
|
-
0,
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
97
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
98
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
99
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
100
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
101
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
102
|
+
55, 50, 45, 40, 35, 30, 68, 68, 68, 68,
|
103
|
+
68, 68, 68, 68, 68, 15, 10, 15, 15, 15,
|
104
|
+
0, 20, 10, 10, 5, 68, 68, 0, 20, 25,
|
105
|
+
0, 68, 68, 0, 25, 0, 15, 68, 68, 68,
|
106
|
+
68, 68, 68, 68, 68, 68, 68, 15, 10, 15,
|
107
|
+
15, 15, 0, 20, 10, 10, 5, 68, 68, 0,
|
108
|
+
20, 25, 0, 68, 68, 0, 25, 0, 15, 68,
|
109
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
110
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
111
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
112
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
113
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
114
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
115
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
116
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
117
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
118
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
119
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
120
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
121
|
+
68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
|
122
|
+
68, 68, 68, 68, 68, 68, 68
|
123
123
|
};
|
124
|
-
register
|
124
|
+
register int hval = len;
|
125
125
|
|
126
126
|
switch (hval)
|
127
127
|
{
|
@@ -135,6 +135,12 @@ hash_block_tag (str, len)
|
|
135
135
|
return hval;
|
136
136
|
}
|
137
137
|
|
138
|
+
#ifdef __GNUC__
|
139
|
+
__inline
|
140
|
+
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
|
141
|
+
__attribute__ ((__gnu_inline__))
|
142
|
+
#endif
|
143
|
+
#endif
|
138
144
|
const char *
|
139
145
|
find_block_tag (str, len)
|
140
146
|
register const char *str;
|
@@ -142,80 +148,76 @@ find_block_tag (str, len)
|
|
142
148
|
{
|
143
149
|
enum
|
144
150
|
{
|
145
|
-
TOTAL_KEYWORDS =
|
151
|
+
TOTAL_KEYWORDS = 41,
|
146
152
|
MIN_WORD_LENGTH = 1,
|
147
153
|
MAX_WORD_LENGTH = 10,
|
148
154
|
MIN_HASH_VALUE = 1,
|
149
|
-
MAX_HASH_VALUE =
|
155
|
+
MAX_HASH_VALUE = 67
|
150
156
|
};
|
151
157
|
|
152
158
|
static const char * const wordlist[] =
|
153
159
|
{
|
154
160
|
"",
|
155
161
|
"p",
|
156
|
-
"
|
157
|
-
"
|
162
|
+
"ul",
|
163
|
+
"pre",
|
158
164
|
"form",
|
159
|
-
"",
|
165
|
+
"style",
|
160
166
|
"footer",
|
161
|
-
"
|
162
|
-
"
|
163
|
-
"", "",
|
167
|
+
"section",
|
168
|
+
"", "", "",
|
164
169
|
"figure",
|
165
|
-
"
|
170
|
+
"hr",
|
166
171
|
"fieldset",
|
167
|
-
"",
|
172
|
+
"math",
|
168
173
|
"figcaption",
|
169
174
|
"header",
|
170
|
-
"
|
171
|
-
"
|
172
|
-
"math",
|
173
|
-
"video",
|
174
|
-
"script",
|
175
|
-
"section",
|
176
|
-
"noscript",
|
175
|
+
"dl",
|
176
|
+
"del",
|
177
177
|
"",
|
178
178
|
"blockquote",
|
179
|
-
"
|
180
|
-
"
|
181
|
-
"
|
182
|
-
"",
|
183
|
-
"style",
|
184
|
-
"output",
|
185
|
-
"summary",
|
186
|
-
"nav",
|
179
|
+
"script",
|
180
|
+
"article",
|
181
|
+
"div",
|
187
182
|
"",
|
188
|
-
"
|
183
|
+
"video",
|
184
|
+
"hgroup",
|
185
|
+
"ol",
|
186
|
+
"noscript",
|
187
|
+
"", "",
|
189
188
|
"canvas",
|
190
189
|
"dd",
|
191
|
-
"
|
190
|
+
"nav",
|
192
191
|
"abbr",
|
193
|
-
"
|
192
|
+
"audio",
|
194
193
|
"iframe",
|
195
|
-
"
|
196
|
-
"",
|
197
|
-
"
|
194
|
+
"address",
|
195
|
+
"ins",
|
196
|
+
"",
|
197
|
+
"table",
|
198
198
|
"",
|
199
199
|
"h6",
|
200
200
|
"", "",
|
201
|
+
"aside",
|
202
|
+
"output",
|
203
|
+
"h5",
|
204
|
+
"", "",
|
201
205
|
"tfoot",
|
202
206
|
"",
|
203
|
-
"h5",
|
204
|
-
"", "", "", "",
|
205
207
|
"h4",
|
206
208
|
"", "", "", "",
|
207
|
-
"address",
|
208
|
-
"", "", "", "",
|
209
209
|
"h3",
|
210
210
|
"", "", "", "",
|
211
|
-
"h2"
|
211
|
+
"h2",
|
212
|
+
"", "", "", "",
|
213
|
+
"h1"
|
212
214
|
};
|
213
215
|
|
214
216
|
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
215
217
|
{
|
216
|
-
|
218
|
+
register int key = hash_block_tag (str, len);
|
217
219
|
|
218
|
-
if (key <= MAX_HASH_VALUE)
|
220
|
+
if (key <= MAX_HASH_VALUE && key >= 0)
|
219
221
|
{
|
220
222
|
register const char *s = wordlist[key];
|
221
223
|
|
data/ext/greenmat/markdown.c
CHANGED
@@ -1442,6 +1442,37 @@ prefix_codefence(uint8_t *data, size_t size)
|
|
1442
1442
|
return i;
|
1443
1443
|
}
|
1444
1444
|
|
1445
|
+
/* check if a line begins with a custom fence; return the
|
1446
|
+
* width of the custom fence */
|
1447
|
+
static size_t
|
1448
|
+
prefix_customfence(uint8_t *data, size_t size)
|
1449
|
+
{
|
1450
|
+
size_t i = 0, n = 0;
|
1451
|
+
uint8_t c;
|
1452
|
+
|
1453
|
+
/* skipping initial spaces */
|
1454
|
+
if (size < 3) return 0;
|
1455
|
+
if (data[0] == ' ') { i++;
|
1456
|
+
if (data[1] == ' ') { i++;
|
1457
|
+
if (data[2] == ' ') { i++; } } }
|
1458
|
+
|
1459
|
+
/* looking at the hrule uint8_t */
|
1460
|
+
if (i + 2 >= size || !(data[i] == ':'))
|
1461
|
+
return 0;
|
1462
|
+
|
1463
|
+
c = data[i];
|
1464
|
+
|
1465
|
+
/* the whole line must be the uint8_t or whitespace */
|
1466
|
+
while (i < size && data[i] == c) {
|
1467
|
+
n++; i++;
|
1468
|
+
}
|
1469
|
+
|
1470
|
+
if (n < 3)
|
1471
|
+
return 0;
|
1472
|
+
|
1473
|
+
return i;
|
1474
|
+
}
|
1475
|
+
|
1445
1476
|
/* check if a line is a code fence; return its size if it is */
|
1446
1477
|
static size_t
|
1447
1478
|
is_codefence(uint8_t *data, size_t size, struct buf *syntax)
|
@@ -1499,6 +1530,63 @@ is_codefence(uint8_t *data, size_t size, struct buf *syntax)
|
|
1499
1530
|
return i + 1;
|
1500
1531
|
}
|
1501
1532
|
|
1533
|
+
/* check if a line is a custom fence; return its size if it is */
|
1534
|
+
static size_t
|
1535
|
+
is_customfence(uint8_t *data, size_t size, struct buf *syntax)
|
1536
|
+
{
|
1537
|
+
size_t i = 0, syn_len = 0;
|
1538
|
+
uint8_t *syn_start;
|
1539
|
+
|
1540
|
+
i = prefix_customfence(data, size);
|
1541
|
+
if (i == 0)
|
1542
|
+
return 0;
|
1543
|
+
|
1544
|
+
while (i < size && data[i] == ' ')
|
1545
|
+
i++;
|
1546
|
+
|
1547
|
+
syn_start = data + i;
|
1548
|
+
|
1549
|
+
if (i < size && data[i] == '{') {
|
1550
|
+
i++; syn_start++;
|
1551
|
+
|
1552
|
+
while (i < size && data[i] != '}' && data[i] != '\n') {
|
1553
|
+
syn_len++; i++;
|
1554
|
+
}
|
1555
|
+
|
1556
|
+
if (i == size || data[i] != '}')
|
1557
|
+
return 0;
|
1558
|
+
|
1559
|
+
/* strip all whitespace at the beginning and the end
|
1560
|
+
* of the {} block */
|
1561
|
+
while (syn_len > 0 && _isspace(syn_start[0])) {
|
1562
|
+
syn_start++; syn_len--;
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
while (syn_len > 0 && _isspace(syn_start[syn_len - 1]))
|
1566
|
+
syn_len--;
|
1567
|
+
|
1568
|
+
i++;
|
1569
|
+
} else {
|
1570
|
+
while (i < size && data[i] != '\n') {
|
1571
|
+
syn_len++; i++;
|
1572
|
+
}
|
1573
|
+
}
|
1574
|
+
|
1575
|
+
if (syntax) {
|
1576
|
+
syntax->data = syn_start;
|
1577
|
+
syntax->size = syn_len;
|
1578
|
+
}
|
1579
|
+
|
1580
|
+
while (i < size && data[i] != '\n') {
|
1581
|
+
if (!_isspace(data[i]))
|
1582
|
+
return 0;
|
1583
|
+
|
1584
|
+
i++;
|
1585
|
+
}
|
1586
|
+
|
1587
|
+
return i + 1;
|
1588
|
+
}
|
1589
|
+
|
1502
1590
|
/* is_atxheader • returns whether the line is a hash-prefixed header */
|
1503
1591
|
static int
|
1504
1592
|
is_atxheader(struct sd_markdown *rndr, uint8_t *data, size_t size)
|
@@ -1877,6 +1965,53 @@ parse_blockcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
|
|
1877
1965
|
return beg;
|
1878
1966
|
}
|
1879
1967
|
|
1968
|
+
|
1969
|
+
|
1970
|
+
/* parse_fencedcustom • handles parsing of a block-level custom fragment */
|
1971
|
+
static size_t
|
1972
|
+
parse_fencedcustom(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
|
1973
|
+
{
|
1974
|
+
size_t beg, end;
|
1975
|
+
struct buf *work = 0;
|
1976
|
+
struct buf type = { 0, 0, 0, 0 };
|
1977
|
+
|
1978
|
+
beg = is_customfence(data, size, &type);
|
1979
|
+
if (beg == 0) return 0;
|
1980
|
+
|
1981
|
+
work = rndr_newbuf(rndr, BUFFER_BLOCK);
|
1982
|
+
|
1983
|
+
while (beg < size) {
|
1984
|
+
size_t fence_end;
|
1985
|
+
struct buf fence_trail = { 0, 0, 0, 0 };
|
1986
|
+
|
1987
|
+
fence_end = is_customfence(data + beg, size - beg, &fence_trail);
|
1988
|
+
if (fence_end != 0 && fence_trail.size == 0) {
|
1989
|
+
beg += fence_end;
|
1990
|
+
break;
|
1991
|
+
}
|
1992
|
+
|
1993
|
+
for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
|
1994
|
+
|
1995
|
+
if (beg < end) {
|
1996
|
+
/* verbatim copy to the working buffer,
|
1997
|
+
escaping entities */
|
1998
|
+
if (is_empty(data + beg, end - beg))
|
1999
|
+
bufputc(work, '\n');
|
2000
|
+
else bufput(work, data + beg, end - beg);
|
2001
|
+
}
|
2002
|
+
beg = end;
|
2003
|
+
}
|
2004
|
+
|
2005
|
+
if (work->size && work->data[work->size - 1] != '\n')
|
2006
|
+
bufputc(work, '\n');
|
2007
|
+
|
2008
|
+
if (rndr->cb.blockcustom)
|
2009
|
+
rndr->cb.blockcustom(ob, work, type.size ? &type : NULL, rndr->opaque);
|
2010
|
+
|
2011
|
+
rndr_popbuf(rndr, BUFFER_BLOCK);
|
2012
|
+
return beg;
|
2013
|
+
}
|
2014
|
+
|
1880
2015
|
/* parse_listitem • parsing of a single list item */
|
1881
2016
|
/* assuming initial prefix is already removed */
|
1882
2017
|
static size_t
|
@@ -2513,6 +2648,10 @@ parse_block(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size
|
|
2513
2648
|
(i = parse_fencedcode(ob, rndr, txt_data, end)) != 0)
|
2514
2649
|
beg += i;
|
2515
2650
|
|
2651
|
+
else if ((rndr->ext_flags & MKDEXT_FENCED_CUSTOM) != 0 &&
|
2652
|
+
(i = parse_fencedcustom(ob, rndr, txt_data, end)) != 0)
|
2653
|
+
beg += i;
|
2654
|
+
|
2516
2655
|
else if ((rndr->ext_flags & MKDEXT_TABLES) != 0 &&
|
2517
2656
|
(i = parse_table(ob, rndr, txt_data, end)) != 0)
|
2518
2657
|
beg += i;
|
data/ext/greenmat/markdown.h
CHANGED
@@ -64,13 +64,15 @@ enum mkd_extensions {
|
|
64
64
|
MKDEXT_HIGHLIGHT = (1 << 10),
|
65
65
|
MKDEXT_FOOTNOTES = (1 << 11),
|
66
66
|
MKDEXT_QUOTE = (1 << 12),
|
67
|
-
MKDEXT_NO_MENTION_EMPHASIS = (1 << 13)
|
67
|
+
MKDEXT_NO_MENTION_EMPHASIS = (1 << 13),
|
68
|
+
MKDEXT_FENCED_CUSTOM = (1 << 14)
|
68
69
|
};
|
69
70
|
|
70
71
|
/* sd_callbacks - functions for rendering parsed data */
|
71
72
|
struct sd_callbacks {
|
72
73
|
/* block level callbacks - NULL skips the block */
|
73
74
|
void (*blockcode)(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque);
|
75
|
+
void (*blockcustom)(struct buf *ob, const struct buf *text, const struct buf *type, void *opaque);
|
74
76
|
void (*blockquote)(struct buf *ob, const struct buf *text, void *opaque);
|
75
77
|
void (*blockhtml)(struct buf *ob,const struct buf *text, void *opaque);
|
76
78
|
void (*header)(struct buf *ob, const struct buf *text, int level, void *opaque);
|
data/greenmat.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.homepage = 'https://github.com/increments/greenmat'
|
13
13
|
s.authors = ["Natacha Porté", "Vicent Martí"]
|
14
14
|
s.license = 'MIT'
|
15
|
-
s.required_ruby_version = '>= 2.
|
15
|
+
s.required_ruby_version = '>= 2.5.0'
|
16
16
|
|
17
17
|
s.files = `git ls-files -z`.split("\x0")
|
18
18
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.require_paths = ["lib"]
|
23
23
|
|
24
24
|
s.add_development_dependency "activesupport"
|
25
|
-
s.add_development_dependency "nokogiri", "~> 1.
|
25
|
+
s.add_development_dependency "nokogiri", "~> 1.11.7"
|
26
26
|
s.add_development_dependency "rake", "~> 12.2.1"
|
27
27
|
s.add_development_dependency "rake-compiler", "~> 1.0.3"
|
28
28
|
s.add_development_dependency "rspec", "~> 3.2"
|
data/lib/greenmat/version.rb
CHANGED
@@ -184,5 +184,48 @@ module Greenmat
|
|
184
184
|
EOS
|
185
185
|
end
|
186
186
|
end
|
187
|
+
|
188
|
+
context 'with fenced_custom_blocks option' do
|
189
|
+
let(:options) { { fenced_custom_blocks: true } }
|
190
|
+
|
191
|
+
context 'with custom block with any metadata' do
|
192
|
+
let(:text) do
|
193
|
+
<<-EOS.strip_heredoc
|
194
|
+
:::foo bar
|
195
|
+
message
|
196
|
+
:::
|
197
|
+
EOS
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'renders text with <div> tag that have customblock class & metadata in a data-metadata attribute' do
|
201
|
+
expect(rendered_html).to eq <<-EOS.strip_heredoc
|
202
|
+
<div data-type="customblock" data-metadata="foo bar">message
|
203
|
+
</div>
|
204
|
+
EOS
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context 'without fenced_custom_blocks option' do
|
210
|
+
let(:options) { {} }
|
211
|
+
|
212
|
+
context 'with custom block with any metadata' do
|
213
|
+
let(:text) do
|
214
|
+
<<-EOS.strip_heredoc
|
215
|
+
:::foo bar
|
216
|
+
message
|
217
|
+
:::
|
218
|
+
EOS
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'renders text with p tag' do
|
222
|
+
expect(rendered_html).to eq <<-EOS.strip_heredoc
|
223
|
+
<p>:::foo bar
|
224
|
+
message
|
225
|
+
:::</p>
|
226
|
+
EOS
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
187
230
|
end
|
188
231
|
end
|
data/test/html5_test.rb
CHANGED
@@ -68,15 +68,24 @@ class HTML5Test < Greenmat::TestCase
|
|
68
68
|
assert_renders html, html
|
69
69
|
end
|
70
70
|
|
71
|
-
def
|
71
|
+
def test_details_tags_ignoring
|
72
72
|
details = <<-HTML.chomp.strip_heredoc
|
73
|
-
<details>
|
74
|
-
log:
|
73
|
+
<details><summary>Folding sample</summary><div>
|
75
74
|
|
76
|
-
|
75
|
+
```rb
|
76
|
+
puts 'Hello, World'
|
77
|
+
```
|
78
|
+
</div></details>
|
77
79
|
HTML
|
80
|
+
html = <<-HTML.chomp.strip_heredoc
|
81
|
+
<p><details><summary>Folding sample</summary><div></p>
|
78
82
|
|
79
|
-
|
80
|
-
|
83
|
+
<p><code>rb
|
84
|
+
puts 'Hello, World'
|
85
|
+
</code>
|
86
|
+
</div></details></p>
|
87
|
+
HTML
|
81
88
|
|
89
|
+
assert_renders html, details
|
90
|
+
end
|
82
91
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: greenmat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.5.1.
|
4
|
+
version: 3.5.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Natacha Porté
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-03-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 1.
|
34
|
+
version: 1.11.7
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 1.
|
41
|
+
version: 1.11.7
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: rake
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,9 +104,9 @@ extensions:
|
|
104
104
|
extra_rdoc_files:
|
105
105
|
- COPYING
|
106
106
|
files:
|
107
|
+
- ".github/workflows/test.yml"
|
107
108
|
- ".gitignore"
|
108
109
|
- ".rspec"
|
109
|
-
- ".travis.yml"
|
110
110
|
- CHANGELOG.md
|
111
111
|
- COPYING
|
112
112
|
- Gemfile
|
@@ -254,14 +254,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
254
254
|
requirements:
|
255
255
|
- - ">="
|
256
256
|
- !ruby/object:Gem::Version
|
257
|
-
version: 2.
|
257
|
+
version: 2.5.0
|
258
258
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
259
259
|
requirements:
|
260
260
|
- - ">="
|
261
261
|
- !ruby/object:Gem::Version
|
262
262
|
version: '0'
|
263
263
|
requirements: []
|
264
|
-
rubygems_version: 3.
|
264
|
+
rubygems_version: 3.1.4
|
265
265
|
signing_key:
|
266
266
|
specification_version: 4
|
267
267
|
summary: A Markdown parser for Qiita, based on Redcarpet.
|
data/.travis.yml
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
dist: trusty
|
3
|
-
|
4
|
-
addons:
|
5
|
-
apt:
|
6
|
-
packages:
|
7
|
-
- tidy
|
8
|
-
- tcl
|
9
|
-
- tk
|
10
|
-
|
11
|
-
install: bundle install --without=benchmark
|
12
|
-
|
13
|
-
rvm:
|
14
|
-
- 2.0.0
|
15
|
-
- 2.1
|
16
|
-
- 2.2
|
17
|
-
- 2.3
|
18
|
-
- 2.4
|
19
|
-
- 2.5
|
20
|
-
- ruby-head
|
21
|
-
|
22
|
-
matrix:
|
23
|
-
allow_failures:
|
24
|
-
- rvm: ruby-head
|
25
|
-
|
26
|
-
notifications:
|
27
|
-
email: false
|