commonmarker 0.23.10 → 1.0.0
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/Cargo.lock +1049 -0
- data/Cargo.toml +6 -0
- data/README.md +144 -203
- data/ext/commonmarker/Cargo.toml +13 -0
- data/ext/commonmarker/extconf.rb +3 -6
- data/ext/commonmarker/src/lib.rs +153 -0
- data/ext/commonmarker/src/options.rs +140 -0
- data/ext/commonmarker/src/plugins/syntax_highlighting.rs +74 -0
- data/ext/commonmarker/src/plugins.rs +3 -0
- data/ext/commonmarker/src/utils.rs +8 -0
- data/lib/commonmarker/config.rb +84 -40
- data/lib/commonmarker/constants.rb +7 -0
- data/lib/commonmarker/extension.rb +14 -0
- data/lib/commonmarker/renderer.rb +1 -127
- data/lib/commonmarker/utils.rb +22 -0
- data/lib/commonmarker/version.rb +2 -2
- data/lib/commonmarker.rb +14 -29
- metadata +36 -188
- data/Rakefile +0 -109
- data/bin/commonmarker +0 -118
- data/commonmarker.gemspec +0 -38
- data/ext/commonmarker/arena.c +0 -104
- data/ext/commonmarker/autolink.c +0 -508
- data/ext/commonmarker/autolink.h +0 -8
- data/ext/commonmarker/blocks.c +0 -1622
- data/ext/commonmarker/buffer.c +0 -278
- data/ext/commonmarker/buffer.h +0 -116
- data/ext/commonmarker/case_fold_switch.inc +0 -4327
- data/ext/commonmarker/chunk.h +0 -135
- data/ext/commonmarker/cmark-gfm-core-extensions.h +0 -54
- data/ext/commonmarker/cmark-gfm-extension_api.h +0 -737
- data/ext/commonmarker/cmark-gfm-extensions_export.h +0 -42
- data/ext/commonmarker/cmark-gfm.h +0 -833
- data/ext/commonmarker/cmark-gfm_export.h +0 -42
- data/ext/commonmarker/cmark-gfm_version.h +0 -7
- data/ext/commonmarker/cmark.c +0 -55
- data/ext/commonmarker/cmark_ctype.c +0 -44
- data/ext/commonmarker/cmark_ctype.h +0 -33
- data/ext/commonmarker/commonmark.c +0 -514
- data/ext/commonmarker/commonmarker.c +0 -1308
- data/ext/commonmarker/commonmarker.h +0 -16
- data/ext/commonmarker/config.h +0 -76
- data/ext/commonmarker/core-extensions.c +0 -27
- data/ext/commonmarker/entities.inc +0 -2138
- data/ext/commonmarker/ext_scanners.c +0 -879
- data/ext/commonmarker/ext_scanners.h +0 -24
- data/ext/commonmarker/footnotes.c +0 -63
- data/ext/commonmarker/footnotes.h +0 -27
- data/ext/commonmarker/houdini.h +0 -57
- data/ext/commonmarker/houdini_href_e.c +0 -100
- data/ext/commonmarker/houdini_html_e.c +0 -66
- data/ext/commonmarker/houdini_html_u.c +0 -149
- data/ext/commonmarker/html.c +0 -502
- data/ext/commonmarker/html.h +0 -27
- data/ext/commonmarker/inlines.c +0 -1788
- data/ext/commonmarker/inlines.h +0 -29
- data/ext/commonmarker/iterator.c +0 -159
- data/ext/commonmarker/iterator.h +0 -26
- data/ext/commonmarker/latex.c +0 -468
- data/ext/commonmarker/linked_list.c +0 -37
- data/ext/commonmarker/man.c +0 -274
- data/ext/commonmarker/map.c +0 -129
- data/ext/commonmarker/map.h +0 -44
- data/ext/commonmarker/node.c +0 -1045
- data/ext/commonmarker/node.h +0 -167
- data/ext/commonmarker/parser.h +0 -59
- data/ext/commonmarker/plaintext.c +0 -218
- data/ext/commonmarker/plugin.c +0 -36
- data/ext/commonmarker/plugin.h +0 -34
- data/ext/commonmarker/references.c +0 -43
- data/ext/commonmarker/references.h +0 -26
- data/ext/commonmarker/registry.c +0 -63
- data/ext/commonmarker/registry.h +0 -24
- data/ext/commonmarker/render.c +0 -213
- data/ext/commonmarker/render.h +0 -62
- data/ext/commonmarker/scanners.c +0 -14056
- data/ext/commonmarker/scanners.h +0 -70
- data/ext/commonmarker/scanners.re +0 -341
- data/ext/commonmarker/strikethrough.c +0 -167
- data/ext/commonmarker/strikethrough.h +0 -9
- data/ext/commonmarker/syntax_extension.c +0 -149
- data/ext/commonmarker/syntax_extension.h +0 -34
- data/ext/commonmarker/table.c +0 -917
- data/ext/commonmarker/table.h +0 -12
- data/ext/commonmarker/tagfilter.c +0 -60
- data/ext/commonmarker/tagfilter.h +0 -8
- data/ext/commonmarker/tasklist.c +0 -156
- data/ext/commonmarker/tasklist.h +0 -8
- data/ext/commonmarker/utf8.c +0 -317
- data/ext/commonmarker/utf8.h +0 -35
- data/ext/commonmarker/xml.c +0 -182
- data/lib/commonmarker/node/inspect.rb +0 -47
- data/lib/commonmarker/node.rb +0 -83
- data/lib/commonmarker/renderer/html_renderer.rb +0 -256
@@ -0,0 +1,140 @@
|
|
1
|
+
use std::borrow::Cow;
|
2
|
+
|
3
|
+
use comrak::ComrakOptions;
|
4
|
+
|
5
|
+
use magnus::value::ReprValue;
|
6
|
+
use magnus::TryConvert;
|
7
|
+
use magnus::{class, r_hash::ForEach, Error, RHash, Symbol, Value};
|
8
|
+
|
9
|
+
use crate::utils::try_convert_string;
|
10
|
+
|
11
|
+
const PARSE_SMART: &str = "smart";
|
12
|
+
const PARSE_DEFAULT_INFO_STRING: &str = "default_info_string";
|
13
|
+
|
14
|
+
fn iterate_parse_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
|
15
|
+
options_hash
|
16
|
+
.foreach(|key: Symbol, value: Value| {
|
17
|
+
match key.name() {
|
18
|
+
Ok(Cow::Borrowed(PARSE_SMART)) => {
|
19
|
+
comrak_options.parse.smart = TryConvert::try_convert(value)?;
|
20
|
+
}
|
21
|
+
Ok(Cow::Borrowed(PARSE_DEFAULT_INFO_STRING)) => {
|
22
|
+
comrak_options.parse.default_info_string = try_convert_string(value);
|
23
|
+
}
|
24
|
+
_ => {}
|
25
|
+
}
|
26
|
+
Ok(ForEach::Continue)
|
27
|
+
})
|
28
|
+
.unwrap();
|
29
|
+
}
|
30
|
+
|
31
|
+
const RENDER_HARDBREAKS: &str = "hardbreaks";
|
32
|
+
const RENDER_GITHUB_PRE_LANG: &str = "github_pre_lang";
|
33
|
+
const RENDER_WIDTH: &str = "width";
|
34
|
+
const RENDER_UNSAFE: &str = "unsafe";
|
35
|
+
const RENDER_ESCAPE: &str = "escape";
|
36
|
+
|
37
|
+
fn iterate_render_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
|
38
|
+
options_hash
|
39
|
+
.foreach(|key: Symbol, value: Value| {
|
40
|
+
match key.name() {
|
41
|
+
Ok(Cow::Borrowed(RENDER_HARDBREAKS)) => {
|
42
|
+
comrak_options.render.hardbreaks = TryConvert::try_convert(value)?;
|
43
|
+
}
|
44
|
+
Ok(Cow::Borrowed(RENDER_GITHUB_PRE_LANG)) => {
|
45
|
+
comrak_options.render.github_pre_lang = TryConvert::try_convert(value)?;
|
46
|
+
}
|
47
|
+
Ok(Cow::Borrowed(RENDER_WIDTH)) => {
|
48
|
+
comrak_options.render.width = TryConvert::try_convert(value)?;
|
49
|
+
}
|
50
|
+
Ok(Cow::Borrowed(RENDER_UNSAFE)) => {
|
51
|
+
comrak_options.render.unsafe_ = TryConvert::try_convert(value)?;
|
52
|
+
}
|
53
|
+
Ok(Cow::Borrowed(RENDER_ESCAPE)) => {
|
54
|
+
comrak_options.render.escape = TryConvert::try_convert(value)?;
|
55
|
+
}
|
56
|
+
_ => {}
|
57
|
+
}
|
58
|
+
Ok(ForEach::Continue)
|
59
|
+
})
|
60
|
+
.unwrap();
|
61
|
+
}
|
62
|
+
|
63
|
+
const EXTENSION_STRIKETHROUGH: &str = "strikethrough";
|
64
|
+
const EXTENSION_TAGFILTER: &str = "tagfilter";
|
65
|
+
const EXTENSION_TABLE: &str = "table";
|
66
|
+
const EXTENSION_AUTOLINK: &str = "autolink";
|
67
|
+
const EXTENSION_TASKLIST: &str = "tasklist";
|
68
|
+
const EXTENSION_SUPERSCRIPT: &str = "superscript";
|
69
|
+
const EXTENSION_HEADER_IDS: &str = "header_ids";
|
70
|
+
const EXTENSION_FOOTNOTES: &str = "footnotes";
|
71
|
+
const EXTENSION_DESCRIPTION_LISTS: &str = "description_lists";
|
72
|
+
const EXTENSION_FRONT_MATTER_DELIMITER: &str = "front_matter_delimiter";
|
73
|
+
const EXTENSION_SHORTCODES: &str = "shortcodes";
|
74
|
+
|
75
|
+
fn iterate_extension_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
|
76
|
+
options_hash
|
77
|
+
.foreach(|key: Symbol, value: Value| {
|
78
|
+
match key.name() {
|
79
|
+
Ok(Cow::Borrowed(EXTENSION_STRIKETHROUGH)) => {
|
80
|
+
comrak_options.extension.strikethrough = TryConvert::try_convert(value)?;
|
81
|
+
}
|
82
|
+
Ok(Cow::Borrowed(EXTENSION_TAGFILTER)) => {
|
83
|
+
comrak_options.extension.tagfilter = TryConvert::try_convert(value)?;
|
84
|
+
}
|
85
|
+
Ok(Cow::Borrowed(EXTENSION_TABLE)) => {
|
86
|
+
comrak_options.extension.table = TryConvert::try_convert(value)?;
|
87
|
+
}
|
88
|
+
Ok(Cow::Borrowed(EXTENSION_AUTOLINK)) => {
|
89
|
+
comrak_options.extension.autolink = TryConvert::try_convert(value)?;
|
90
|
+
}
|
91
|
+
Ok(Cow::Borrowed(EXTENSION_TASKLIST)) => {
|
92
|
+
comrak_options.extension.tasklist = TryConvert::try_convert(value)?;
|
93
|
+
}
|
94
|
+
Ok(Cow::Borrowed(EXTENSION_SUPERSCRIPT)) => {
|
95
|
+
comrak_options.extension.superscript = TryConvert::try_convert(value)?;
|
96
|
+
}
|
97
|
+
Ok(Cow::Borrowed(EXTENSION_HEADER_IDS)) => {
|
98
|
+
comrak_options.extension.header_ids = try_convert_string(value);
|
99
|
+
}
|
100
|
+
Ok(Cow::Borrowed(EXTENSION_FOOTNOTES)) => {
|
101
|
+
comrak_options.extension.footnotes = TryConvert::try_convert(value)?;
|
102
|
+
}
|
103
|
+
Ok(Cow::Borrowed(EXTENSION_DESCRIPTION_LISTS)) => {
|
104
|
+
comrak_options.extension.description_lists = TryConvert::try_convert(value)?;
|
105
|
+
}
|
106
|
+
Ok(Cow::Borrowed(EXTENSION_FRONT_MATTER_DELIMITER)) => {
|
107
|
+
if let Some(option) = try_convert_string(value) {
|
108
|
+
if !option.is_empty() {
|
109
|
+
comrak_options.extension.front_matter_delimiter = Some(option);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
Ok(Cow::Borrowed(EXTENSION_SHORTCODES)) => {
|
114
|
+
comrak_options.extension.shortcodes = TryConvert::try_convert(value)?;
|
115
|
+
}
|
116
|
+
_ => {}
|
117
|
+
}
|
118
|
+
Ok(ForEach::Continue)
|
119
|
+
})
|
120
|
+
.unwrap();
|
121
|
+
}
|
122
|
+
|
123
|
+
pub fn iterate_options_hash(
|
124
|
+
comrak_options: &mut ComrakOptions,
|
125
|
+
key: Symbol,
|
126
|
+
value: RHash,
|
127
|
+
) -> Result<ForEach, Error> {
|
128
|
+
assert!(value.is_kind_of(class::hash()));
|
129
|
+
|
130
|
+
if key.name().unwrap() == "parse" {
|
131
|
+
iterate_parse_options(comrak_options, value);
|
132
|
+
}
|
133
|
+
if key.name().unwrap() == "render" {
|
134
|
+
iterate_render_options(comrak_options, value);
|
135
|
+
}
|
136
|
+
if key.name().unwrap() == "extension" {
|
137
|
+
iterate_extension_options(comrak_options, value);
|
138
|
+
}
|
139
|
+
Ok(ForEach::Continue)
|
140
|
+
}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
use std::path::PathBuf;
|
2
|
+
|
3
|
+
use magnus::value::ReprValue;
|
4
|
+
use magnus::{RHash, Symbol, TryConvert, Value};
|
5
|
+
|
6
|
+
use crate::EMPTY_STR;
|
7
|
+
|
8
|
+
pub const SYNTAX_HIGHLIGHTER_PLUGIN_THEME_KEY: &str = "theme";
|
9
|
+
pub const SYNTAX_HIGHLIGHTER_PLUGIN_PATH_KEY: &str = "path";
|
10
|
+
|
11
|
+
pub fn fetch_syntax_highlighter_theme(value: Value) -> Result<Option<String>, magnus::Error> {
|
12
|
+
if value.is_nil() {
|
13
|
+
// `syntax_highlighter: nil`
|
14
|
+
return Ok(None);
|
15
|
+
}
|
16
|
+
|
17
|
+
let syntax_highlighter_plugin: RHash = match TryConvert::try_convert(value) {
|
18
|
+
Ok(plugin) => plugin, // `syntax_highlighter: { theme: "<something>" }`
|
19
|
+
Err(e) => {
|
20
|
+
// not a hash!
|
21
|
+
return Err(e);
|
22
|
+
}
|
23
|
+
};
|
24
|
+
|
25
|
+
if syntax_highlighter_plugin.is_nil() || syntax_highlighter_plugin.is_empty() {
|
26
|
+
return Err(magnus::Error::new(
|
27
|
+
magnus::exception::type_error(),
|
28
|
+
"theme cannot be blank hash",
|
29
|
+
));
|
30
|
+
}
|
31
|
+
|
32
|
+
let theme_key = Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN_THEME_KEY);
|
33
|
+
|
34
|
+
match syntax_highlighter_plugin.get(theme_key) {
|
35
|
+
Some(theme) => {
|
36
|
+
if theme.is_nil() {
|
37
|
+
return Err(magnus::Error::new(
|
38
|
+
magnus::exception::type_error(),
|
39
|
+
"theme cannot be nil",
|
40
|
+
));
|
41
|
+
}
|
42
|
+
Ok(TryConvert::try_convert(theme)?)
|
43
|
+
}
|
44
|
+
None => {
|
45
|
+
// `syntax_highlighter: { theme: nil }`
|
46
|
+
Ok(None)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
pub fn fetch_syntax_highlighter_path(value: Value) -> Result<PathBuf, magnus::Error> {
|
52
|
+
if value.is_nil() {
|
53
|
+
// `syntax_highlighter: nil`
|
54
|
+
return Ok(PathBuf::from(EMPTY_STR));
|
55
|
+
}
|
56
|
+
|
57
|
+
let syntax_highlighter_plugin: RHash = TryConvert::try_convert(value)?;
|
58
|
+
let path_key = Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN_PATH_KEY);
|
59
|
+
|
60
|
+
match syntax_highlighter_plugin.get(path_key) {
|
61
|
+
Some(path) => {
|
62
|
+
if path.is_nil() {
|
63
|
+
// `syntax_highlighter: { path: nil }`
|
64
|
+
return Ok(PathBuf::from(EMPTY_STR));
|
65
|
+
}
|
66
|
+
let val: String = TryConvert::try_convert(path)?;
|
67
|
+
Ok(PathBuf::from(val))
|
68
|
+
}
|
69
|
+
None => {
|
70
|
+
// `syntax_highlighter: { }`
|
71
|
+
Ok(PathBuf::from(EMPTY_STR))
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
data/lib/commonmarker/config.rb
CHANGED
@@ -1,54 +1,98 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
4
|
-
# For Ruby::Enum, these must be classes, not modules
|
3
|
+
module Commonmarker
|
5
4
|
module Config
|
6
|
-
#
|
7
|
-
|
5
|
+
# For details, see
|
6
|
+
# https://github.com/kivikakk/comrak/blob/162ef9354deb2c9b4a4e05be495aa372ba5bb696/src/main.rs#L201
|
7
|
+
OPTIONS = {
|
8
8
|
parse: {
|
9
|
-
|
10
|
-
|
11
|
-
UNSAFE: (1 << 17),
|
12
|
-
VALIDATE_UTF8: (1 << 9),
|
13
|
-
SMART: (1 << 10),
|
14
|
-
LIBERAL_HTML_TAG: (1 << 12),
|
15
|
-
FOOTNOTES: (1 << 13),
|
16
|
-
STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
|
9
|
+
smart: false,
|
10
|
+
default_info_string: "",
|
17
11
|
}.freeze,
|
18
12
|
render: {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
VALIDATE_UTF8: (1 << 9),
|
25
|
-
SMART: (1 << 10),
|
26
|
-
GITHUB_PRE_LANG: (1 << 11),
|
27
|
-
LIBERAL_HTML_TAG: (1 << 12),
|
28
|
-
FOOTNOTES: (1 << 13),
|
29
|
-
STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
|
30
|
-
TABLE_PREFER_STYLE_ATTRIBUTES: (1 << 15),
|
31
|
-
FULL_INFO_STRING: (1 << 16),
|
13
|
+
hardbreaks: true,
|
14
|
+
github_pre_lang: true,
|
15
|
+
width: 80,
|
16
|
+
unsafe: false,
|
17
|
+
escape: false,
|
32
18
|
}.freeze,
|
33
|
-
|
19
|
+
extension: {
|
20
|
+
strikethrough: true,
|
21
|
+
tagfilter: true,
|
22
|
+
table: true,
|
23
|
+
autolink: true,
|
24
|
+
tasklist: true,
|
25
|
+
superscript: false,
|
26
|
+
header_ids: "",
|
27
|
+
footnotes: false,
|
28
|
+
description_lists: false,
|
29
|
+
front_matter_delimiter: "",
|
30
|
+
shortcodes: true,
|
31
|
+
},
|
32
|
+
format: [:html].freeze,
|
34
33
|
}.freeze
|
35
34
|
|
35
|
+
PLUGINS = {
|
36
|
+
syntax_highlighter: {
|
37
|
+
theme: "base16-ocean.dark",
|
38
|
+
path: "",
|
39
|
+
},
|
40
|
+
}
|
41
|
+
|
36
42
|
class << self
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
include Commonmarker::Utils
|
44
|
+
|
45
|
+
def merged_with_defaults(options)
|
46
|
+
Commonmarker::Config::OPTIONS.merge(process_options(options))
|
47
|
+
end
|
48
|
+
|
49
|
+
def process_options(options)
|
50
|
+
{
|
51
|
+
parse: process_parse_options(options[:parse]),
|
52
|
+
render: process_render_options(options[:render]),
|
53
|
+
extension: process_extension_options(options[:extension]),
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def process_plugins(plugins)
|
58
|
+
{
|
59
|
+
syntax_highlighter: process_syntax_highlighter_plugin(plugins&.fetch(:syntax_highlighter, nil)),
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
[:parse, :render, :extension].each do |type|
|
65
|
+
define_singleton_method :"process_#{type}_options" do |option|
|
66
|
+
Commonmarker::Config::OPTIONS[type].each_with_object({}) do |(key, value), hash|
|
67
|
+
if option.nil? # option not provided, go for the default
|
68
|
+
hash[key] = value
|
69
|
+
next
|
70
|
+
end
|
71
|
+
|
72
|
+
# option explicitly not included, remove it
|
73
|
+
next if option[key].nil?
|
74
|
+
|
75
|
+
hash[key] = fetch_kv(option, key, value, type)
|
48
76
|
end
|
49
|
-
rescue KeyError => e
|
50
|
-
raise TypeError, "option ':#{e.key}' does not exist for #{name}::OPTS[:#{type}]"
|
51
77
|
end
|
52
|
-
|
78
|
+
end
|
79
|
+
|
80
|
+
[:syntax_highlighter].each do |type|
|
81
|
+
define_singleton_method :"process_#{type}_plugin" do |plugin|
|
82
|
+
return if plugin.nil? # plugin explicitly nil, remove it
|
83
|
+
|
84
|
+
Commonmarker::Config::PLUGINS[type].each_with_object({}) do |(key, value), hash|
|
85
|
+
if plugin.nil? # option not provided, go for the default
|
86
|
+
hash[key] = value
|
87
|
+
next
|
88
|
+
end
|
89
|
+
|
90
|
+
# option explicitly not included, remove it
|
91
|
+
next if plugin[key].nil?
|
92
|
+
|
93
|
+
hash[key] = fetch_kv(plugin, key, value, type)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
53
97
|
end
|
54
98
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
# native precompiled gems package shared libraries in <gem_dir>/lib/commonmarker/<ruby_version>
|
5
|
+
# load the precompiled extension file
|
6
|
+
ruby_version = /\d+\.\d+/.match(RUBY_VERSION)
|
7
|
+
require_relative "#{ruby_version}/commonmarker"
|
8
|
+
rescue LoadError
|
9
|
+
# fall back to the extension compiled upon installation.
|
10
|
+
# use "require" instead of "require_relative" because non-native gems will place C extension files
|
11
|
+
# in Gem::BasicSpecification#extension_dir after compilation (during normal installation), which
|
12
|
+
# is in $LOAD_PATH but not necessarily relative to this file (see nokogiri#2300)
|
13
|
+
require "commonmarker/commonmarker"
|
14
|
+
end
|
@@ -3,133 +3,7 @@
|
|
3
3
|
require "set"
|
4
4
|
require "stringio"
|
5
5
|
|
6
|
-
module
|
6
|
+
module Commonmarker
|
7
7
|
class Renderer
|
8
|
-
attr_accessor :in_tight, :warnings, :in_plain
|
9
|
-
|
10
|
-
def initialize(options: :DEFAULT, extensions: [])
|
11
|
-
@opts = Config.process_options(options, :render)
|
12
|
-
@stream = StringIO.new(+"")
|
13
|
-
@need_blocksep = false
|
14
|
-
@warnings = Set.new([])
|
15
|
-
@in_tight = false
|
16
|
-
@in_plain = false
|
17
|
-
@tagfilter = extensions.include?(:tagfilter)
|
18
|
-
end
|
19
|
-
|
20
|
-
def out(*args)
|
21
|
-
args.each do |arg|
|
22
|
-
case arg
|
23
|
-
when :children
|
24
|
-
@node.each { |child| out(child) }
|
25
|
-
when Array
|
26
|
-
arg.each { |x| render(x) }
|
27
|
-
when Node
|
28
|
-
render(arg)
|
29
|
-
else
|
30
|
-
@stream.write(arg)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def render(node)
|
36
|
-
@node = node
|
37
|
-
if node.type == :document
|
38
|
-
document(node)
|
39
|
-
@stream.string
|
40
|
-
elsif @in_plain && node.type != :text && node.type != :softbreak
|
41
|
-
node.each { |child| render(child) }
|
42
|
-
else
|
43
|
-
begin
|
44
|
-
send(node.type, node)
|
45
|
-
rescue NoMethodError => e
|
46
|
-
@warnings.add("WARNING: #{node.type} not implemented.")
|
47
|
-
raise e
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def document(_node)
|
53
|
-
out(:children)
|
54
|
-
end
|
55
|
-
|
56
|
-
def code_block(node)
|
57
|
-
code_block(node)
|
58
|
-
end
|
59
|
-
|
60
|
-
def reference_def(_node); end
|
61
|
-
|
62
|
-
def cr
|
63
|
-
return if @stream.string.empty? || @stream.string[-1] == "\n"
|
64
|
-
|
65
|
-
out("\n")
|
66
|
-
end
|
67
|
-
|
68
|
-
def blocksep
|
69
|
-
out("\n")
|
70
|
-
end
|
71
|
-
|
72
|
-
def containersep
|
73
|
-
cr unless @in_tight
|
74
|
-
end
|
75
|
-
|
76
|
-
def block
|
77
|
-
cr
|
78
|
-
yield
|
79
|
-
cr
|
80
|
-
end
|
81
|
-
|
82
|
-
def container(starter, ender)
|
83
|
-
out(starter)
|
84
|
-
yield
|
85
|
-
out(ender)
|
86
|
-
end
|
87
|
-
|
88
|
-
def plain
|
89
|
-
old_in_plain = @in_plain
|
90
|
-
@in_plain = true
|
91
|
-
yield
|
92
|
-
@in_plain = old_in_plain
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def escape_href(str)
|
98
|
-
@node.html_escape_href(str)
|
99
|
-
end
|
100
|
-
|
101
|
-
def escape_html(str)
|
102
|
-
@node.html_escape_html(str)
|
103
|
-
end
|
104
|
-
|
105
|
-
def tagfilter(str)
|
106
|
-
if @tagfilter
|
107
|
-
str.gsub(
|
108
|
-
%r{
|
109
|
-
<
|
110
|
-
(
|
111
|
-
title|textarea|style|xmp|iframe|
|
112
|
-
noembed|noframes|script|plaintext
|
113
|
-
)
|
114
|
-
(?=\s|>|/>)
|
115
|
-
}xi,
|
116
|
-
'<\1',
|
117
|
-
)
|
118
|
-
else
|
119
|
-
str
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def sourcepos(node)
|
124
|
-
return "" unless option_enabled?(:SOURCEPOS)
|
125
|
-
|
126
|
-
s = node.sourcepos
|
127
|
-
" data-sourcepos=\"#{s[:start_line]}:#{s[:start_column]}-" \
|
128
|
-
"#{s[:end_line]}:#{s[:end_column]}\""
|
129
|
-
end
|
130
|
-
|
131
|
-
def option_enabled?(opt)
|
132
|
-
(@opts & CommonMarker::Config::OPTS.dig(:render, opt)) != 0
|
133
|
-
end
|
134
8
|
end
|
135
9
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "commonmarker/constants"
|
4
|
+
|
5
|
+
module Commonmarker
|
6
|
+
module Utils
|
7
|
+
include Commonmarker::Constants
|
8
|
+
|
9
|
+
def fetch_kv(option, key, value, type)
|
10
|
+
value_klass = value.class
|
11
|
+
|
12
|
+
if Constants::BOOLS.include?(value) && BOOLS.include?(option[key])
|
13
|
+
option[key]
|
14
|
+
elsif option[key].is_a?(value_klass)
|
15
|
+
option[key]
|
16
|
+
else
|
17
|
+
expected_type = Constants::BOOLS.include?(value) ? "Boolean" : value_klass.to_s
|
18
|
+
raise TypeError, "#{type} option `:#{key}` must be #{expected_type}; got #{option[key].class}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/commonmarker/version.rb
CHANGED
data/lib/commonmarker.rb
CHANGED
@@ -1,45 +1,30 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
require_relative "commonmarker/extension"
|
4
|
+
|
5
|
+
require "commonmarker/utils"
|
5
6
|
require "commonmarker/config"
|
6
|
-
require "commonmarker/node"
|
7
7
|
require "commonmarker/renderer"
|
8
|
-
require "commonmarker/renderer/html_renderer"
|
9
8
|
require "commonmarker/version"
|
10
9
|
|
11
|
-
|
12
|
-
require "awesome_print"
|
13
|
-
rescue LoadError; end # rubocop:disable Lint/SuppressedException
|
14
|
-
module CommonMarker
|
10
|
+
module Commonmarker
|
15
11
|
class << self
|
16
|
-
# Public:
|
12
|
+
# Public: Parses a CommonMark string into an HTML string.
|
17
13
|
#
|
18
14
|
# text - A {String} of text
|
19
|
-
#
|
20
|
-
#
|
15
|
+
# options - A {Hash} of render, parse, and extension options to transform the text.
|
16
|
+
# plugins - A {Hash} of additional plugins.
|
21
17
|
#
|
22
18
|
# Returns a {String} of converted HTML.
|
23
|
-
def
|
19
|
+
def to_html(text, options: Commonmarker::Config::OPTIONS, plugins: Commonmarker::Config::PLUGINS)
|
24
20
|
raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
|
21
|
+
raise TypeError, "text must be UTF-8 encoded; got #{text.encoding}!" unless text.encoding.name == "UTF-8"
|
22
|
+
raise TypeError, "options must be a Hash; got a #{options.class}!" unless options.is_a?(Hash)
|
25
23
|
|
26
|
-
opts = Config.process_options(options
|
27
|
-
|
28
|
-
end
|
24
|
+
opts = Config.process_options(options)
|
25
|
+
plugins = Config.process_plugins(plugins)
|
29
26
|
|
30
|
-
|
31
|
-
#
|
32
|
-
# string - {String} to be parsed
|
33
|
-
# option - A {Symbol} or {Array of Symbol}s indicating the parse options
|
34
|
-
# extensions - An {Array of Symbol}s indicating the extensions to use
|
35
|
-
#
|
36
|
-
# Returns the `document` node.
|
37
|
-
def render_doc(text, options = :DEFAULT, extensions = [])
|
38
|
-
raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
|
39
|
-
|
40
|
-
opts = Config.process_options(options, :parse)
|
41
|
-
text = text.encode("UTF-8")
|
42
|
-
Node.parse_document(text, text.bytesize, opts, extensions)
|
27
|
+
commonmark_to_html(text, options: opts, plugins: plugins)
|
43
28
|
end
|
44
|
-
end
|
29
|
+
end
|
45
30
|
end
|