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,138 @@
1
+ /* markdown.h - generic markdown parser */
2
+
3
+ /*
4
+ * Copyright (c) 2009, Natacha Porté
5
+ *
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+
19
+ #ifndef MARKDOWN_H__
20
+ #define MARKDOWN_H__
21
+
22
+ #include "buffer.h"
23
+ #include "autolink.h"
24
+
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
29
+ /********************
30
+ * TYPE DEFINITIONS *
31
+ ********************/
32
+
33
+ /* mkd_autolink - type of autolink */
34
+ enum mkd_autolink {
35
+ MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
36
+ MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */
37
+ MKDA_EMAIL, /* e-mail link without explit mailto: */
38
+ };
39
+
40
+ enum mkd_tableflags {
41
+ MKD_TABLE_ALIGN_L = 1,
42
+ MKD_TABLE_ALIGN_R = 2,
43
+ MKD_TABLE_ALIGN_CENTER = 3,
44
+ MKD_TABLE_ALIGNMASK = 3,
45
+ MKD_TABLE_HEADER = 4
46
+ };
47
+
48
+ enum mkd_extensions {
49
+ MKDEXT_NO_INTRA_EMPHASIS = (1 << 0),
50
+ MKDEXT_TABLES = (1 << 1),
51
+ MKDEXT_FENCED_CODE = (1 << 2),
52
+ MKDEXT_AUTOLINK = (1 << 3),
53
+ MKDEXT_STRIKETHROUGH = (1 << 4),
54
+ MKDEXT_UNDERLINE = (1 << 5),
55
+ MKDEXT_SPACE_HEADERS = (1 << 6),
56
+ MKDEXT_SUPERSCRIPT = (1 << 7),
57
+ MKDEXT_LAX_SPACING = (1 << 8),
58
+ MKDEXT_DISABLE_INDENTED_CODE = (1 << 9),
59
+ MKDEXT_HIGHLIGHT = (1 << 10),
60
+ MKDEXT_FOOTNOTES = (1 << 11),
61
+ MKDEXT_QUOTE = (1 << 12)
62
+ };
63
+
64
+ /* sd_callbacks - functions for rendering parsed data */
65
+ struct sd_callbacks {
66
+ /* block level callbacks - NULL skips the block */
67
+ void (*blockcode)(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque);
68
+ void (*blockquote)(struct buf *ob, const struct buf *text, void *opaque);
69
+ void (*blockhtml)(struct buf *ob,const struct buf *text, void *opaque);
70
+ void (*header)(struct buf *ob, const struct buf *text, int level, void *opaque);
71
+ void (*hrule)(struct buf *ob, void *opaque);
72
+ void (*list)(struct buf *ob, const struct buf *text, int flags, void *opaque);
73
+ void (*listitem)(struct buf *ob, const struct buf *text, int flags, void *opaque);
74
+ void (*paragraph)(struct buf *ob, const struct buf *text, void *opaque);
75
+ void (*table)(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque);
76
+ void (*table_row)(struct buf *ob, const struct buf *text, void *opaque);
77
+ void (*table_cell)(struct buf *ob, const struct buf *text, int flags, void *opaque);
78
+ void (*footnotes)(struct buf *ob, const struct buf *text, void *opaque);
79
+ void (*footnote_def)(struct buf *ob, const struct buf *text, unsigned int num, void *opaque);
80
+
81
+ /* span level callbacks - NULL or return 0 prints the span verbatim */
82
+ int (*autolink)(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque);
83
+ int (*codespan)(struct buf *ob, const struct buf *text, void *opaque);
84
+ int (*double_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
85
+ int (*emphasis)(struct buf *ob, const struct buf *text, void *opaque);
86
+ int (*underline)(struct buf *ob, const struct buf *text, void *opaque);
87
+ int (*highlight)(struct buf *ob, const struct buf *text, void *opaque);
88
+ int (*quote)(struct buf *ob, const struct buf *text, void *opaque);
89
+ int (*image)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque);
90
+ int (*linebreak)(struct buf *ob, void *opaque);
91
+ int (*link)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque);
92
+ int (*raw_html_tag)(struct buf *ob, const struct buf *tag, void *opaque);
93
+ int (*triple_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
94
+ int (*strikethrough)(struct buf *ob, const struct buf *text, void *opaque);
95
+ int (*superscript)(struct buf *ob, const struct buf *text, void *opaque);
96
+ int (*footnote_ref)(struct buf *ob, unsigned int num, void *opaque);
97
+
98
+ /* low level callbacks - NULL copies input directly into the output */
99
+ void (*entity)(struct buf *ob, const struct buf *entity, void *opaque);
100
+ void (*normal_text)(struct buf *ob, const struct buf *text, void *opaque);
101
+
102
+ /* header and footer */
103
+ void (*doc_header)(struct buf *ob, void *opaque);
104
+ void (*doc_footer)(struct buf *ob, void *opaque);
105
+ };
106
+
107
+ struct sd_markdown;
108
+
109
+ /*********
110
+ * FLAGS *
111
+ *********/
112
+
113
+ /* list/listitem flags */
114
+ #define MKD_LIST_ORDERED 1
115
+ #define MKD_LI_BLOCK 2 /* <li> containing block data */
116
+
117
+ /**********************
118
+ * EXPORTED FUNCTIONS *
119
+ **********************/
120
+
121
+ extern struct sd_markdown *
122
+ sd_markdown_new(
123
+ unsigned int extensions,
124
+ size_t max_nesting,
125
+ const struct sd_callbacks *callbacks,
126
+ void *opaque);
127
+
128
+ extern void
129
+ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md);
130
+
131
+ extern void
132
+ sd_markdown_free(struct sd_markdown *md);
133
+
134
+ #ifdef __cplusplus
135
+ }
136
+ #endif
137
+
138
+ #endif
@@ -0,0 +1,62 @@
1
+ #include "stack.h"
2
+ #include <string.h>
3
+
4
+ int
5
+ greenmat_stack_grow(struct stack *st, size_t new_size)
6
+ {
7
+ void **new_st;
8
+
9
+ if (st->asize >= new_size)
10
+ return 0;
11
+
12
+ new_st = realloc(st->item, new_size * sizeof(void *));
13
+ if (new_st == NULL)
14
+ return -1;
15
+
16
+ memset(new_st + st->asize, 0x0,
17
+ (new_size - st->asize) * sizeof(void *));
18
+
19
+ st->item = new_st;
20
+ st->asize = new_size;
21
+
22
+ if (st->size > new_size)
23
+ st->size = new_size;
24
+
25
+ return 0;
26
+ }
27
+
28
+ void
29
+ greenmat_stack_free(struct stack *st)
30
+ {
31
+ if (!st)
32
+ return;
33
+
34
+ free(st->item);
35
+
36
+ st->item = NULL;
37
+ st->size = 0;
38
+ st->asize = 0;
39
+ }
40
+
41
+ int
42
+ greenmat_stack_init(struct stack *st, size_t initial_size)
43
+ {
44
+ st->item = NULL;
45
+ st->size = 0;
46
+ st->asize = 0;
47
+
48
+ if (!initial_size)
49
+ initial_size = 8;
50
+
51
+ return greenmat_stack_grow(st, initial_size);
52
+ }
53
+
54
+ int
55
+ greenmat_stack_push(struct stack *st, void *item)
56
+ {
57
+ if (greenmat_stack_grow(st, st->size * 2) < 0)
58
+ return -1;
59
+
60
+ st->item[st->size++] = item;
61
+ return 0;
62
+ }
@@ -0,0 +1,26 @@
1
+ #ifndef STACK_H__
2
+ #define STACK_H__
3
+
4
+ #include <stdlib.h>
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ struct stack {
11
+ void **item;
12
+ size_t size;
13
+ size_t asize;
14
+ };
15
+
16
+ void greenmat_stack_free(struct stack *);
17
+ int greenmat_stack_grow(struct stack *, size_t);
18
+ int greenmat_stack_init(struct stack *, size_t);
19
+
20
+ int greenmat_stack_push(struct stack *, void *);
21
+
22
+ #ifdef __cplusplus
23
+ }
24
+ #endif
25
+
26
+ #endif
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'greenmat'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'greenmat'
8
+ s.version = Greenmat::VERSION
9
+ s.summary = "A Markdown parser for Qiita, based on Redcarpet."
10
+ s.description = s.summary
11
+ s.email = 'nkymyj@gmail.com'
12
+ s.homepage = 'https://github.com/increments/greenmat'
13
+ s.authors = ["Natacha Porté", "Vicent Martí"]
14
+ s.license = 'MIT'
15
+ s.required_ruby_version = '>= 2.0.0'
16
+ # = MANIFEST =
17
+ s.files = %w[
18
+ COPYING
19
+ Gemfile
20
+ README.md
21
+ Rakefile
22
+ bin/greenmat
23
+ ext/greenmat/autolink.c
24
+ ext/greenmat/autolink.h
25
+ ext/greenmat/buffer.c
26
+ ext/greenmat/buffer.h
27
+ ext/greenmat/extconf.rb
28
+ ext/greenmat/houdini.h
29
+ ext/greenmat/houdini_href_e.c
30
+ ext/greenmat/houdini_html_e.c
31
+ ext/greenmat/html.c
32
+ ext/greenmat/html.h
33
+ ext/greenmat/html_blocks.h
34
+ ext/greenmat/html_smartypants.c
35
+ ext/greenmat/markdown.c
36
+ ext/greenmat/markdown.h
37
+ ext/greenmat/gm_markdown.c
38
+ ext/greenmat/gm_render.c
39
+ ext/greenmat/greenmat.h
40
+ ext/greenmat/stack.c
41
+ ext/greenmat/stack.h
42
+ lib/greenmat.rb
43
+ lib/greenmat/compat.rb
44
+ lib/greenmat/render_man.rb
45
+ lib/greenmat/render_strip.rb
46
+ greenmat.gemspec
47
+ test/benchmark.rb
48
+ test/custom_render_test.rb
49
+ test/html5_test.rb
50
+ test/html_render_test.rb
51
+ test/html_toc_render_test.rb
52
+ test/markdown_test.rb
53
+ test/pathological_inputs_test.rb
54
+ test/greenmat_compat_test.rb
55
+ test/safe_render_test.rb
56
+ test/smarty_html_test.rb
57
+ test/smarty_pants_test.rb
58
+ test/stripdown_render_test.rb
59
+ test/test_helper.rb
60
+ ]
61
+ # = MANIFEST =
62
+ s.test_files = s.files.grep(%r{^test/})
63
+ s.extra_rdoc_files = ["COPYING"]
64
+ s.extensions = ["ext/greenmat/extconf.rb"]
65
+ s.executables = ["greenmat"]
66
+ s.require_paths = ["lib"]
67
+
68
+ s.add_development_dependency "rake-compiler", "~> 0.8.3"
69
+ s.add_development_dependency "rspec", "~> 3.2"
70
+ s.add_development_dependency "rubygems-xcodeproj_generator", '~> 0.1'
71
+ s.add_development_dependency "test-unit", "~> 3.0.9"
72
+ end
@@ -0,0 +1,92 @@
1
+ require 'greenmat.so'
2
+ require 'greenmat/compat'
3
+
4
+ module Greenmat
5
+ VERSION = '3.2.0.0'
6
+
7
+ class Markdown
8
+ attr_reader :renderer
9
+ end
10
+
11
+ module Render
12
+
13
+ # XHTML Renderer
14
+ class XHTML < HTML
15
+ def initialize(extensions = {})
16
+ super(extensions.merge(xhtml: true))
17
+ end
18
+ end
19
+
20
+ # HTML + SmartyPants renderer
21
+ class SmartyHTML < HTML
22
+ include SmartyPants
23
+ end
24
+
25
+ # A renderer object you can use to deal with users' input. It
26
+ # enables +escape_html+ and +safe_links_only+ by default.
27
+ #
28
+ # The +block_code+ callback is also overriden not to include
29
+ # the lang's class as the user can basically specify anything
30
+ # with the vanilla one.
31
+ class Safe < HTML
32
+ def initialize(extensions = {})
33
+ super({
34
+ escape_html: true,
35
+ safe_links_only: true
36
+ }.merge(extensions))
37
+ end
38
+
39
+ def block_code(code, lang)
40
+ "<pre>" \
41
+ "<code>#{html_escape(code)}</code>" \
42
+ "</pre>"
43
+ end
44
+
45
+ private
46
+
47
+ # TODO: This is far from ideal to have such method as we
48
+ # are duplicating existing code from Houdini. This method
49
+ # should be defined at the C level.
50
+ def html_escape(string)
51
+ string.gsub(/['&\"<>\/]/, {
52
+ '&' => '&amp;',
53
+ '<' => '&lt;',
54
+ '>' => '&gt;',
55
+ '"' => '&quot;',
56
+ "'" => '&#x27;',
57
+ "/" => '&#x2F;',
58
+ })
59
+ end
60
+ end
61
+
62
+ # SmartyPants Mixin module
63
+ #
64
+ # Implements SmartyPants.postprocess, which
65
+ # performs smartypants replacements on the HTML file,
66
+ # once it has been fully rendered.
67
+ #
68
+ # To add SmartyPants postprocessing to your custom
69
+ # renderers, just mixin the module `include SmartyPants`
70
+ #
71
+ # You can also use this as a standalone SmartyPants
72
+ # implementation.
73
+ #
74
+ # Example:
75
+ #
76
+ # # Mixin
77
+ # class CoolRenderer < HTML
78
+ # include SmartyPants
79
+ # # more code here
80
+ # end
81
+ #
82
+ # # Standalone
83
+ # Greenmat::Render::SmartyPants.render("you're")
84
+ #
85
+ module SmartyPants
86
+ extend self
87
+ def self.render(text)
88
+ postprocess text
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,73 @@
1
+ require 'greenmat'
2
+
3
+ # Creates an instance of Greenmat with the RedCloth API.
4
+ class GreenmatCompat
5
+ attr_accessor :text
6
+
7
+ def initialize(text, *exts)
8
+ exts_hash, render_hash = *parse_extensions_and_renderer_options(exts)
9
+ @text = text
10
+ renderer = Greenmat::Render::HTML.new(render_hash)
11
+ @markdown = Greenmat::Markdown.new(renderer, exts_hash)
12
+ end
13
+
14
+ def to_html(*_dummy)
15
+ @markdown.render(text)
16
+ end
17
+
18
+ private
19
+
20
+ EXTENSION_MAP = {
21
+ # old name => new name
22
+ :autolink => :autolink,
23
+ :fenced_code => :fenced_code_blocks,
24
+ :filter_html => :filter_html,
25
+ :hard_wrap => :hard_wrap,
26
+ :prettify => :prettify,
27
+ :lax_htmlblock => :lax_spacing,
28
+ :no_image => :no_images,
29
+ :no_intraemphasis => :no_intra_emphasis,
30
+ :no_links => :no_links,
31
+ :filter_styles => :no_styles,
32
+ :safelink => :safe_links_only,
33
+ :space_header => :space_after_headers,
34
+ :strikethrough => :strikethrough,
35
+ :tables => :tables,
36
+ :generate_toc => :with_toc_data,
37
+ :xhtml => :xhtml,
38
+
39
+ # old names with no new mapping
40
+ :gh_blockcode => nil,
41
+ :no_tables => nil,
42
+ :smart => nil,
43
+ :strict => nil
44
+ }
45
+
46
+ RENDERER_OPTIONS = [:filter_html, :no_images, :no_links, :no_styles,
47
+ :safe_links_only, :with_toc_data, :hard_wrap, :prettify, :xhtml]
48
+
49
+ def rename_extensions(exts)
50
+ exts.map do |old_name|
51
+ if new_name = EXTENSION_MAP[old_name]
52
+ new_name
53
+ else
54
+ old_name
55
+ end
56
+ end.compact
57
+ end
58
+
59
+ # Returns two hashes, the extensions and renderer options
60
+ # given the extension list
61
+ def parse_extensions_and_renderer_options(exts)
62
+ exts = rename_extensions(exts)
63
+ exts.partition {|ext| !RENDERER_OPTIONS.include?(ext) }.
64
+ map {|list| list_to_truthy_hash(list) }
65
+ end
66
+
67
+ # Turns a list of symbols into a hash of <tt>symbol => true</tt>.
68
+ def list_to_truthy_hash(list)
69
+ list.inject({}) {|h, k| h[k] = true; h }
70
+ end
71
+ end
72
+
73
+ Markdown = GreenmatCompat unless defined? Markdown