greenmat 3.2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +14 -0
  3. data/Gemfile +9 -0
  4. data/README.md +36 -0
  5. data/Rakefile +62 -0
  6. data/bin/greenmat +7 -0
  7. data/ext/greenmat/autolink.c +296 -0
  8. data/ext/greenmat/autolink.h +49 -0
  9. data/ext/greenmat/buffer.c +196 -0
  10. data/ext/greenmat/buffer.h +83 -0
  11. data/ext/greenmat/extconf.rb +6 -0
  12. data/ext/greenmat/gm_markdown.c +161 -0
  13. data/ext/greenmat/gm_render.c +534 -0
  14. data/ext/greenmat/greenmat.h +30 -0
  15. data/ext/greenmat/houdini.h +29 -0
  16. data/ext/greenmat/houdini_href_e.c +108 -0
  17. data/ext/greenmat/houdini_html_e.c +83 -0
  18. data/ext/greenmat/html.c +826 -0
  19. data/ext/greenmat/html.h +84 -0
  20. data/ext/greenmat/html_blocks.h +229 -0
  21. data/ext/greenmat/html_smartypants.c +445 -0
  22. data/ext/greenmat/markdown.c +2912 -0
  23. data/ext/greenmat/markdown.h +138 -0
  24. data/ext/greenmat/stack.c +62 -0
  25. data/ext/greenmat/stack.h +26 -0
  26. data/greenmat.gemspec +72 -0
  27. data/lib/greenmat.rb +92 -0
  28. data/lib/greenmat/compat.rb +73 -0
  29. data/lib/greenmat/render_man.rb +65 -0
  30. data/lib/greenmat/render_strip.rb +48 -0
  31. data/test/benchmark.rb +24 -0
  32. data/test/custom_render_test.rb +28 -0
  33. data/test/greenmat_compat_test.rb +38 -0
  34. data/test/html5_test.rb +69 -0
  35. data/test/html_render_test.rb +241 -0
  36. data/test/html_toc_render_test.rb +76 -0
  37. data/test/markdown_test.rb +337 -0
  38. data/test/pathological_inputs_test.rb +34 -0
  39. data/test/safe_render_test.rb +36 -0
  40. data/test/smarty_html_test.rb +45 -0
  41. data/test/smarty_pants_test.rb +48 -0
  42. data/test/stripdown_render_test.rb +40 -0
  43. data/test/test_helper.rb +33 -0
  44. metadata +158 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fda7624ffadcd3576cd31d5785a9aa9eaf14cfe7
4
+ data.tar.gz: 5ebc173f5a5dd42dcb73e3454303533484d31c47
5
+ SHA512:
6
+ metadata.gz: 9401853a7711a8969caabd10a54b3da514cbfc391cbdfc4796732876200f03d0c7d87f9266803069d2bd27cc4dc5806a711d8409efba540543d9d05afb6408d5
7
+ data.tar.gz: c7c3611dd92f07addaad1c3781eaabc5aa04e696c66ac52d5d5ca59985d6e621a47464f6453aabe9e6c2df925ab7ea167903273bd59ec6211638b9c62d2feb7f
data/COPYING ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2009, Natacha Porté
2
+ Copyright (c) 2011, Vicent Marti
3
+
4
+ Permission to use, copy, modify, and distribute this software for any
5
+ purpose with or without fee is hereby granted, provided that the above
6
+ copyright notice and this permission notice appear in all copies.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org/"
2
+
3
+ gemspec
4
+
5
+ group :benchmark do
6
+ gem "benchmark-ips", "~> 1.2.0"
7
+ gem "bluecloth", "~> 2.2.0"
8
+ gem "kramdown", "~> 1.0.2"
9
+ end
@@ -0,0 +1,36 @@
1
+ [![Gem Version](http://img.shields.io/gem/v/greenmat.svg?style=flat)](http://badge.fury.io/rb/greenmat)
2
+ [![Build Status](https://travis-ci.org/increments/greenmat.svg?branch=master&style=flat)](https://travis-ci.org/increments/greenmat)
3
+
4
+ # Greenmat
5
+
6
+ **Greenmat** is a Ruby library for Markdown processing, based on [Redcarpet](https://github.com/vmg/redcarpet).
7
+
8
+ It's a core module of [qiita-markdown](https://github.com/increments/qiita-markdown) gem and not intended for direct use. If you are looking for Qiita-specified markdown processor, use qiita-markdown gem.
9
+
10
+ ## Versioning Policy
11
+
12
+ Greenmat follows Redcarpet's updates by merging the upstream changes.
13
+ The version format is `MAJOR.MINOR.PATCH.FORK`.
14
+ `MAJOR.MINOR.PATCH` is the same as the version of Redcarpet that Greenmat is based on. `FORK` is incremented on each release of Greenmat itself and reset to zero when any of `MAJOR.MINOR.PATCH` is bumped.
15
+
16
+ ## Acknowledgment
17
+
18
+ We appreciate Redcarpet project and the contributors for the great efforts!
19
+
20
+ ## Legal
21
+
22
+ ### Redcarpet
23
+
24
+ Copyright (c) 2011-2014, Vicent Martí
25
+
26
+ Permission to use, copy, modify, and/or distribute this software for any
27
+ purpose with or without fee is hereby granted, provided that the above
28
+ copyright notice and this permission notice appear in all copies.
29
+
30
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,62 @@
1
+ require 'date'
2
+ require 'rake/clean'
3
+ require 'rake/extensiontask'
4
+ require 'digest/md5'
5
+
6
+ task :default => [:test, :spec]
7
+
8
+ # Gem Spec
9
+ gem_spec = Gem::Specification.load('greenmat.gemspec')
10
+
11
+ # Ruby Extension
12
+ Rake::ExtensionTask.new('greenmat', gem_spec)
13
+
14
+ # Packaging
15
+ require 'bundler/gem_tasks'
16
+
17
+ # Testing
18
+ require 'rake/testtask'
19
+
20
+ Rake::TestTask.new('test:unit') do |t|
21
+ t.libs << 'lib'
22
+ t.libs << 'test'
23
+ t.pattern = 'test/*_test.rb'
24
+ t.verbose = true
25
+ t.warning = false
26
+ end
27
+
28
+ task 'test:unit' => :compile
29
+
30
+ desc 'Run conformance tests (MARKDOWN_TEST_VER=1.0.3)'
31
+ task 'test:conformance' => :compile do |t|
32
+ script = "#{pwd}/bin/greenmat"
33
+ version = ENV['MARKDOWN_TEST_VER'] || '1.0.3'
34
+ lib_dir = "#{pwd}/lib"
35
+
36
+ chdir("test/MarkdownTest_#{version}") do
37
+ sh "RUBYLIB=#{lib_dir} ./MarkdownTest.pl --script='#{script}' --tidy"
38
+ end
39
+ end
40
+
41
+ desc 'Run version 1.0 conformance suite'
42
+ task 'test:conformance:1.0' => :compile do |t|
43
+ ENV['MARKDOWN_TEST_VER'] = '1.0'
44
+ Rake::Task['test:conformance'].invoke
45
+ end
46
+
47
+ desc 'Run 1.0.3 conformance suite'
48
+ task 'test:conformance:1.0.3' => :compile do |t|
49
+ ENV['MARKDOWN_TEST_VER'] = '1.0.3'
50
+ Rake::Task['test:conformance'].invoke
51
+ end
52
+
53
+ desc 'Run unit and conformance tests'
54
+ task :test => %w[test:unit test:conformance]
55
+
56
+ desc 'Run benchmarks'
57
+ task :benchmark => :compile do |t|
58
+ $:.unshift 'lib'
59
+ load 'test/benchmark.rb'
60
+ end
61
+
62
+ Dir['tasks/*.rake'].each { |file| load file }
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ lib_path = File.expand_path('../../lib', __FILE__)
3
+ $:.unshift(lib_path)
4
+
5
+ require 'greenmat/cli'
6
+
7
+ Greenmat::CLI.process(ARGV)
@@ -0,0 +1,296 @@
1
+ /*
2
+ * Copyright (c) 2011, Vicent Marti
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+ #include "buffer.h"
18
+ #include "autolink.h"
19
+
20
+ #include <string.h>
21
+ #include <stdlib.h>
22
+ #include <stdio.h>
23
+ #include <ctype.h>
24
+
25
+ #if defined(_WIN32)
26
+ #define strncasecmp _strnicmp
27
+ #endif
28
+
29
+ int
30
+ sd_autolink_issafe(const uint8_t *link, size_t link_len)
31
+ {
32
+ static const size_t valid_uris_count = 6;
33
+ static const char *valid_uris[] = {
34
+ "#", "/", "http://", "https://", "ftp://", "mailto:"
35
+ };
36
+
37
+ size_t i;
38
+
39
+ for (i = 0; i < valid_uris_count; ++i) {
40
+ size_t len = strlen(valid_uris[i]);
41
+
42
+ if (link_len > len &&
43
+ strncasecmp((char *)link, valid_uris[i], len) == 0 &&
44
+ isalnum(link[len]))
45
+ return 1;
46
+ }
47
+
48
+ return 0;
49
+ }
50
+
51
+ static size_t
52
+ autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
53
+ {
54
+ uint8_t cclose, copen = 0;
55
+ size_t i;
56
+
57
+ for (i = 0; i < link_end; ++i)
58
+ if (data[i] == '<') {
59
+ link_end = i;
60
+ break;
61
+ }
62
+
63
+ while (link_end > 0) {
64
+ if (strchr("?!.,", data[link_end - 1]) != NULL)
65
+ link_end--;
66
+
67
+ else if (data[link_end - 1] == ';') {
68
+ size_t new_end = link_end - 2;
69
+
70
+ while (new_end > 0 && isalpha(data[new_end]))
71
+ new_end--;
72
+
73
+ if (new_end < link_end - 2 && data[new_end] == '&')
74
+ link_end = new_end;
75
+ else
76
+ link_end--;
77
+ }
78
+ else break;
79
+ }
80
+
81
+ if (link_end == 0)
82
+ return 0;
83
+
84
+ cclose = data[link_end - 1];
85
+
86
+ switch (cclose) {
87
+ case '"': copen = '"'; break;
88
+ case '\'': copen = '\''; break;
89
+ case ')': copen = '('; break;
90
+ case ']': copen = '['; break;
91
+ case '}': copen = '{'; break;
92
+ }
93
+
94
+ if (copen != 0) {
95
+ size_t closing = 0;
96
+ size_t opening = 0;
97
+ size_t i = 0;
98
+
99
+ /* Try to close the final punctuation sign in this same line;
100
+ * if we managed to close it outside of the URL, that means that it's
101
+ * not part of the URL. If it closes inside the URL, that means it
102
+ * is part of the URL.
103
+ *
104
+ * Examples:
105
+ *
106
+ * foo http://www.pokemon.com/Pikachu_(Electric) bar
107
+ * => http://www.pokemon.com/Pikachu_(Electric)
108
+ *
109
+ * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
110
+ * => http://www.pokemon.com/Pikachu_(Electric)
111
+ *
112
+ * foo http://www.pokemon.com/Pikachu_(Electric)) bar
113
+ * => http://www.pokemon.com/Pikachu_(Electric))
114
+ *
115
+ * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
116
+ * => foo http://www.pokemon.com/Pikachu_(Electric)
117
+ */
118
+
119
+ while (i < link_end) {
120
+ if (data[i] == copen)
121
+ opening++;
122
+ else if (data[i] == cclose)
123
+ closing++;
124
+
125
+ i++;
126
+ }
127
+
128
+ if (closing != opening)
129
+ link_end--;
130
+ }
131
+
132
+ return link_end;
133
+ }
134
+
135
+ static size_t
136
+ check_domain(uint8_t *data, size_t size, int allow_short)
137
+ {
138
+ size_t i, np = 0;
139
+
140
+ if (!isalnum(data[0]))
141
+ return 0;
142
+
143
+ for (i = 1; i < size - 1; ++i) {
144
+ if (strchr(".:", data[i]) != NULL) np++;
145
+ else if (!isalnum(data[i]) && data[i] != '-') break;
146
+ }
147
+
148
+ if (allow_short) {
149
+ /* We don't need a valid domain in the strict sense (with
150
+ * least one dot; so just make sure it's composed of valid
151
+ * domain characters and return the length of the the valid
152
+ * sequence. */
153
+ return i;
154
+ } else {
155
+ /* a valid domain needs to have at least a dot.
156
+ * that's as far as we get */
157
+ return np ? i : 0;
158
+ }
159
+ }
160
+
161
+ size_t
162
+ sd_autolink__www(
163
+ size_t *rewind_p,
164
+ struct buf *link,
165
+ uint8_t *data,
166
+ size_t max_rewind,
167
+ size_t size,
168
+ unsigned int flags)
169
+ {
170
+ size_t link_end;
171
+
172
+ if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
173
+ return 0;
174
+
175
+ if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
176
+ return 0;
177
+
178
+ link_end = check_domain(data, size, 0);
179
+
180
+ if (link_end == 0)
181
+ return 0;
182
+
183
+ while (link_end < size && !isspace(data[link_end]))
184
+ link_end++;
185
+
186
+ link_end = autolink_delim(data, link_end, max_rewind, size);
187
+
188
+ if (link_end == 0)
189
+ return 0;
190
+
191
+ bufput(link, data, link_end);
192
+ *rewind_p = 0;
193
+
194
+ return (int)link_end;
195
+ }
196
+
197
+ size_t
198
+ sd_autolink__email(
199
+ size_t *rewind_p,
200
+ struct buf *link,
201
+ uint8_t *data,
202
+ size_t max_rewind,
203
+ size_t size,
204
+ unsigned int flags)
205
+ {
206
+ size_t link_end, rewind;
207
+ int nb = 0, np = 0;
208
+
209
+ for (rewind = 0; rewind < max_rewind; ++rewind) {
210
+ uint8_t c = data[-rewind - 1];
211
+
212
+ if (isalnum(c))
213
+ continue;
214
+
215
+ if (strchr(".+-_", c) != NULL)
216
+ continue;
217
+
218
+ break;
219
+ }
220
+
221
+ if (rewind == 0)
222
+ return 0;
223
+
224
+ for (link_end = 0; link_end < size; ++link_end) {
225
+ uint8_t c = data[link_end];
226
+
227
+ if (isalnum(c))
228
+ continue;
229
+
230
+ if (c == '@')
231
+ nb++;
232
+ else if (c == '.' && link_end < size - 1)
233
+ np++;
234
+ else if (c != '-' && c != '_')
235
+ break;
236
+ }
237
+
238
+ if (link_end < 2 || nb != 1 || np == 0)
239
+ return 0;
240
+
241
+ link_end = autolink_delim(data, link_end, max_rewind, size);
242
+
243
+ if (link_end == 0)
244
+ return 0;
245
+
246
+ bufput(link, data - rewind, link_end + rewind);
247
+ *rewind_p = rewind;
248
+
249
+ return link_end;
250
+ }
251
+
252
+ size_t
253
+ sd_autolink__url(
254
+ size_t *rewind_p,
255
+ struct buf *link,
256
+ uint8_t *data,
257
+ size_t max_rewind,
258
+ size_t size,
259
+ unsigned int flags)
260
+ {
261
+ size_t link_end, rewind = 0, domain_len;
262
+
263
+ if (size < 4 || data[1] != '/' || data[2] != '/')
264
+ return 0;
265
+
266
+ while (rewind < max_rewind && isalpha(data[-rewind - 1]))
267
+ rewind++;
268
+
269
+ if (!sd_autolink_issafe(data - rewind, size + rewind))
270
+ return 0;
271
+
272
+ link_end = strlen("://");
273
+
274
+ domain_len = check_domain(
275
+ data + link_end,
276
+ size - link_end,
277
+ flags & SD_AUTOLINK_SHORT_DOMAINS);
278
+
279
+ if (domain_len == 0)
280
+ return 0;
281
+
282
+ link_end += domain_len;
283
+ while (link_end < size && !isspace(data[link_end]))
284
+ link_end++;
285
+
286
+ link_end = autolink_delim(data, link_end, max_rewind, size);
287
+
288
+ if (link_end == 0)
289
+ return 0;
290
+
291
+ bufput(link, data - rewind, link_end + rewind);
292
+ *rewind_p = rewind;
293
+
294
+ return link_end;
295
+ }
296
+
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright (c) 2011, Vicent Marti
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+ #ifndef AUTOLINK_H__
18
+ #define AUTOLINK_H__
19
+
20
+ #include "buffer.h"
21
+
22
+ #ifdef __cplusplus
23
+ extern "C" {
24
+ #endif
25
+
26
+ enum {
27
+ SD_AUTOLINK_SHORT_DOMAINS = (1 << 0),
28
+ };
29
+
30
+ int
31
+ sd_autolink_issafe(const uint8_t *link, size_t link_len);
32
+
33
+ size_t
34
+ sd_autolink__www(size_t *rewind_p, struct buf *link,
35
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
36
+
37
+ size_t
38
+ sd_autolink__email(size_t *rewind_p, struct buf *link,
39
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
40
+
41
+ size_t
42
+ sd_autolink__url(size_t *rewind_p, struct buf *link,
43
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
44
+
45
+ #ifdef __cplusplus
46
+ }
47
+ #endif
48
+
49
+ #endif