greenmat 3.5.1.1 → 3.5.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ebea41bf33e060dc7d4a5c28fbac9e49759062ac85dcbea55b14b1485cd18f1
4
- data.tar.gz: 18cf03b8c7b166736b13326d3e601384b3776d6a65384f46dbf7d7d9545a5528
3
+ metadata.gz: 4858c067ea172c8a8ee9733786f07cc4a9bd7f92159f11f653780ff25fdde1d1
4
+ data.tar.gz: 7559722e0e3a4a563e935fbc5495c336462e783919622e2c44cabf5dcf751cc4
5
5
  SHA512:
6
- metadata.gz: 7e2eb93fbef73b7bb5853db8e107910bf3e7b8e89a649496040cdf665a9b97f54fd0031e0f042c1f6622764e51a85d87bada46d60b0ccbcb352e7743134daab3
7
- data.tar.gz: 6da0421b78cf1b71fd92c080b62aeec8dc74726b999d5d4afb9dc10e465e15b0db28fef67d1d0343940bea56717ec94e944d47a6dfabbe8269dfd0d100fbd746
6
+ metadata.gz: f40e2e7494119ac4549486ed8b38e917fe640e0cc9344119059f2c6b5603c8f82cecb7d513658e0ff527cb413c551d430b1b256b704a32bce8968d39bde7bb17
7
+ data.tar.gz: c61ce570239683037a4736717bd59178b85a2a311b50d214153cb3b1b5ae101661bebe982e52c8b44a6743aebcc916b3a4c462f5c792b84d5ea3060cc7ae2312
@@ -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.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,25 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v3.5.1.4
6
+
7
+ * Dropped Ruby 2.5 support
8
+ * Support ruby version for 3.0, 3.1
9
+
10
+ ## v3.5.1.3
11
+
12
+ * Remove support for ruby 2.5 and below
13
+ * Bump nokogiri from 1.6.0 to 1.11.7
14
+ * Support cpu archtecture for arm64/aarch64 systems (like Apple's M1)
15
+ * Change ci platform to Github Actions
16
+
17
+ ## v3.5.1.2
18
+
19
+ * Support custom block notation.
20
+ * It starts with `:::` and ends with `:::`.
21
+ * Output a `<div data-type="customblock" data-metadata="">` element.
22
+ * Passes the string following `:::` to the `data-metadata` attribute.
23
+
5
24
  ## v3.5.1.1
6
25
 
7
26
  * Unsupport details and summary tags.
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=#{lib_dir} ./MarkdownTest.pl --script='#{script}' --tidy"
38
+ sh "RUBYLIB=\"$RUBYLIB:#{lib_dir}\" ./MarkdownTest.pl --script='#{script}' --tidy"
38
39
  end
39
40
  end
40
41
 
@@ -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
 
@@ -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,
@@ -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;
@@ -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.0.0'
15
+ s.required_ruby_version = '>= 2.6.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,9 +22,9 @@ 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.6.0"
26
- s.add_development_dependency "rake", "~> 12.2.1"
25
+ s.add_development_dependency "nokogiri", "~> 1.13.0"
26
+ s.add_development_dependency "rake", "~> 13"
27
27
  s.add_development_dependency "rake-compiler", "~> 1.0.3"
28
28
  s.add_development_dependency "rspec", "~> 3.2"
29
- s.add_development_dependency "test-unit", "~> 3.2.3"
29
+ s.add_development_dependency "test-unit", "~> 3.5.3"
30
30
  end
@@ -1,3 +1,3 @@
1
1
  module Greenmat
2
- VERSION = '3.5.1.1'
2
+ VERSION = '3.5.1.4'
3
3
  end
@@ -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
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.1
4
+ version: 3.5.1.4
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: 2021-03-03 00:00:00.000000000 Z
12
+ date: 2022-04-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -31,28 +31,28 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: 1.6.0
34
+ version: 1.13.0
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.6.0
41
+ version: 1.13.0
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rake
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: 12.2.1
48
+ version: '13'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: 12.2.1
55
+ version: '13'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rake-compiler
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -87,14 +87,14 @@ dependencies:
87
87
  requirements:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: 3.2.3
90
+ version: 3.5.3
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
- version: 3.2.3
97
+ version: 3.5.3
98
98
  description: A Markdown parser for Qiita, based on Redcarpet.
99
99
  email: nkymyj@gmail.com
100
100
  executables:
@@ -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.0.0
257
+ version: 2.6.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.0.3
264
+ rubygems_version: 3.2.32
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