commonmarker 1.0.0.pre.2-x64-mingw-ucrt
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +146 -0
- data/commonmarker.gemspec +41 -0
- data/ext/commonmarker/Cargo.toml +12 -0
- data/ext/commonmarker/_util.rb +102 -0
- data/ext/commonmarker/extconf.rb +6 -0
- data/ext/commonmarker/src/comrak_options.rs +136 -0
- data/ext/commonmarker/src/lib.rs +29 -0
- data/lib/commonmarker/3.1/commonmarker.so +0 -0
- data/lib/commonmarker/config.rb +73 -0
- data/lib/commonmarker/extension.rb +14 -0
- data/lib/commonmarker/renderer.rb +9 -0
- data/lib/commonmarker/version.rb +5 -0
- data/lib/commonmarker.rb +30 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9530a45496672fba1b58c4cd7521d88f055a5cb4217742ee38579020a2f401fe
|
4
|
+
data.tar.gz: 23bb2d5a1dc1a1e7c0a238aaa88246737668bd18421d579dff6c7f2a51f3fe24
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0b6cde97721d0a9ec697ec89102f44649c2e176e55743396537345c4bf375233454eaf364fadd0f65518d05efd2c40eb003e8d3f6dabdb4b6525d1d2229e2e78
|
7
|
+
data.tar.gz: 67be4b12455a8b12ca16e442447a0a84de530b40f7f8dbd90ebedd0cf50ed7b704d11f06b8d1a32c3851bbc2dfafabebbe5b85a1528c55a0fa831a78f2a6a466
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Garen J. Torikian
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
# Commonmarker
|
2
|
+
|
3
|
+
> **Note**
|
4
|
+
> This README refers to the behavior in the new 1.0.0.pre gem.
|
5
|
+
|
6
|
+
Ruby wrapper for Rust's [comrak](https://github.com/kivikakk/comrak) crate.
|
7
|
+
|
8
|
+
It passes all of the CommonMark test suite, and is therefore spec-complete. It also includes extensions to the CommonMark spec as documented in the [GitHub Flavored Markdown spec](http://github.github.com/gfm/), such as support for tables, strikethroughs, and autolinking.
|
9
|
+
|
10
|
+
For more information on available extensions, see [the documentation below](#extensions).
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
gem 'commonmarker'
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install commonmarker
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
### Converting to HTML
|
29
|
+
|
30
|
+
Call `render_html` on a string to convert it to HTML:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require 'commonmarker'
|
34
|
+
Commonmarker.to_html('"Hi *there*"', options: {
|
35
|
+
parse: { smart: true }
|
36
|
+
})
|
37
|
+
# <p>“Hi <em>there</em>”</p>\n
|
38
|
+
```
|
39
|
+
|
40
|
+
The second argument is optional--[see below](#options) for more information.
|
41
|
+
|
42
|
+
## Parse and Render Options
|
43
|
+
|
44
|
+
Commonmarker accepts the same options that comrak does, as a hash dictionary with symbol keys:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
Commonmarker.to_html('"Hi *there*"', options:{
|
48
|
+
parse: { smart: true },
|
49
|
+
render: { hardbreaks: false}
|
50
|
+
})
|
51
|
+
```
|
52
|
+
|
53
|
+
Note that there is a distinction in comrak for "parse" options and "render" options, which are represented in the tables below.
|
54
|
+
|
55
|
+
### Parse options
|
56
|
+
|
57
|
+
| Name | Description | Default |
|
58
|
+
| --------------------- | ------------------------------------------------------------------------------------ | ------- |
|
59
|
+
| `smart` | Punctuation (quotes, full-stops and hyphens) are converted into 'smart' punctuation. | `false` |
|
60
|
+
| `default_info_string` | The default info string for fenced code blocks. | `""` |
|
61
|
+
|
62
|
+
### Render options
|
63
|
+
|
64
|
+
| Name | Description | Default |
|
65
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------ | ------- |
|
66
|
+
| `hardbreaks` | [Soft line breaks](http://spec.commonmark.org/0.27/#soft-line-breaks) translate into hard line breaks. | `true` |
|
67
|
+
| `github_pre_lang` | GitHub-style `<pre lang="xyz">` is used for fenced code blocks with info tags. | `true` |
|
68
|
+
| `width` | The wrap column when outputting CommonMark. | `80` |
|
69
|
+
| `unsafe_` | Allow rendering of raw HTML and potentially dangerous links. | `false` |
|
70
|
+
| `escape` | Escape raw HTML instead of clobbering it. | `false` |
|
71
|
+
|
72
|
+
As well, there are several extensions which you can toggle in the same manner:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
Commonmarker.to_html('"Hi *there*"', options: {
|
76
|
+
extensions: { footnotes: true, description_lists: true },
|
77
|
+
render: { hardbreaks: false}
|
78
|
+
})
|
79
|
+
```
|
80
|
+
|
81
|
+
### Extension options
|
82
|
+
|
83
|
+
| Name | Description | Default |
|
84
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- | ------- |
|
85
|
+
| `strikethrough` | Enables the [strikethrough extension](https://github.github.com/gfm/#strikethrough-extension-) from the GFM spec. | `true` |
|
86
|
+
| `tagfilter` | Enables the [tagfilter extension](https://github.github.com/gfm/#disallowed-raw-html-extension-) from the GFM spec. | `true` |
|
87
|
+
| `table` | Enables the [table extension](https://github.github.com/gfm/#tables-extension-) from the GFM spec. | `true` |
|
88
|
+
| `autolink` | Enables the [autolink extension](https://github.github.com/gfm/#autolinks-extension-) from the GFM spec. | `true` |
|
89
|
+
| `tasklist` | Enables the [task list extension](https://github.github.com/gfm/#task-list-items-extension-) from the GFM spec. | `true` |
|
90
|
+
| `superscript` | Enables the superscript Comrak extension. | `false` |
|
91
|
+
| `header_ids` | Enables the header IDs Comrak extension. from the GFM spec. | `""` |
|
92
|
+
| `footnotes` | Enables the footnotes extension per `cmark-gfm`. | `false` |
|
93
|
+
| `description_lists` | Enables the description lists extension.. | `false` |
|
94
|
+
| `front_matter_delimiter` | Enables the front matter extension. | `""` |
|
95
|
+
|
96
|
+
For more information on these options, see [the comrak documentation](https://github.com/kivikakk/comrak#usage).
|
97
|
+
|
98
|
+
## Output formats
|
99
|
+
|
100
|
+
Commonmarker can currently only generate output in one format: HTML.
|
101
|
+
|
102
|
+
### HTML
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
html = CommonMarker.to_html('*Hello* world!', :DEFAULT)
|
106
|
+
puts(html)
|
107
|
+
|
108
|
+
# <p><em>Hello</em> world!</p>
|
109
|
+
```
|
110
|
+
|
111
|
+
## Developing locally
|
112
|
+
|
113
|
+
After cloning the repo:
|
114
|
+
|
115
|
+
```
|
116
|
+
script/bootstrap
|
117
|
+
bundle exec rake compile
|
118
|
+
```
|
119
|
+
|
120
|
+
If there were no errors, you're done! Otherwise, make sure to follow the comrak dependency instructions.
|
121
|
+
|
122
|
+
## Benchmarks
|
123
|
+
|
124
|
+
Some rough benchmarks:
|
125
|
+
|
126
|
+
```
|
127
|
+
$ bundle exec rake benchmark
|
128
|
+
|
129
|
+
input size = 11064832 bytes
|
130
|
+
|
131
|
+
Warming up --------------------------------------
|
132
|
+
redcarpet 2.000 i/100ms
|
133
|
+
commonmarker with to_html
|
134
|
+
1.000 i/100ms
|
135
|
+
kramdown 1.000 i/100ms
|
136
|
+
Calculating -------------------------------------
|
137
|
+
redcarpet 22.317 (± 4.5%) i/s - 112.000 in 5.036374s
|
138
|
+
commonmarker with to_html
|
139
|
+
5.815 (± 0.0%) i/s - 30.000 in 5.168869s
|
140
|
+
kramdown 0.327 (± 0.0%) i/s - 2.000 in 6.121486s
|
141
|
+
|
142
|
+
Comparison:
|
143
|
+
redcarpet: 22.3 i/s
|
144
|
+
commonmarker with to_html: 5.8 i/s - 3.84x (± 0.00) slower
|
145
|
+
kramdown: 0.3 i/s - 68.30x (± 0.00) slower
|
146
|
+
```
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "commonmarker/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "commonmarker"
|
9
|
+
spec.version = Commonmarker::VERSION
|
10
|
+
spec.summary = "CommonMark parser and renderer. Written in Rust, wrapped in Ruby."
|
11
|
+
spec.description = "A fast, safe, extensible parser for CommonMark. This wraps the comrak Rust crate."
|
12
|
+
spec.authors = ["Garen Torikian", "Ashe Connor"]
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.homepage = "https://github.com/gjtorikian/commonmarker"
|
15
|
+
|
16
|
+
spec.required_ruby_version = "~> 3.1"
|
17
|
+
# https://github.com/rubygems/rubygems/pull/5852#issuecomment-1231118509
|
18
|
+
spec.required_rubygems_version = ">= 3.3.22"
|
19
|
+
|
20
|
+
spec.files = ["LICENSE.txt", "README.md", "commonmarker.gemspec"]
|
21
|
+
spec.files += Dir.glob("lib/**/*.rb")
|
22
|
+
spec.files += Dir.glob("ext/**/*.{rs,toml,lock,rb}")
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
25
|
+
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
spec.extensions = ["ext/commonmarker/Cargo.toml"]
|
28
|
+
|
29
|
+
spec.metadata = {
|
30
|
+
"allowed_push_host" => "https://rubygems.org",
|
31
|
+
"funding_uri" => "https://github.com/sponsors/gjtorikian/",
|
32
|
+
"source_code_uri" => "https://github.com/gjtorikian/commonmarker",
|
33
|
+
"rubygems_mfa_required" => "true",
|
34
|
+
}
|
35
|
+
|
36
|
+
spec.add_dependency("rb_sys", "~> 0.9")
|
37
|
+
|
38
|
+
spec.add_development_dependency("rake", "~> 13.0")
|
39
|
+
spec.add_development_dependency("rake-compiler", "~> 1.2")
|
40
|
+
spec.add_development_dependency("rake-compiler-dock", "~> 1.2")
|
41
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
[package]
|
2
|
+
name = "commonmarker"
|
3
|
+
version = "1.0.0"
|
4
|
+
edition = "2021"
|
5
|
+
|
6
|
+
[dependencies]
|
7
|
+
magnus = { git = "https://github.com/gjtorikian/magnus", branch = "main" } # waiting for release with full rb-sys backend
|
8
|
+
comrak = "0.15.0"
|
9
|
+
|
10
|
+
[lib]
|
11
|
+
name = "commonmarker"
|
12
|
+
crate-type = ["cdylib"]
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RUBY_MAJOR, RUBY_MINOR = RUBY_VERSION.split(".").collect(&:to_i)
|
4
|
+
|
5
|
+
PACKAGE_ROOT_DIR = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
|
6
|
+
PACKAGE_EXT_DIR = File.join(PACKAGE_ROOT_DIR, "ext", "commonmarker")
|
7
|
+
|
8
|
+
OS = case os = RbConfig::CONFIG["host_os"].downcase
|
9
|
+
when /linux/
|
10
|
+
# The official ruby-alpine Docker containers pre-build Ruby. As a result,
|
11
|
+
# Ruby doesn't know that it's on a musl-based platform. `ldd` is the
|
12
|
+
# a more reliable way to detect musl.
|
13
|
+
# See https://github.com/skylightio/skylight-ruby/issues/92
|
14
|
+
if ENV["SKYLIGHT_MUSL"] || %x(ldd --version 2>&1).include?("musl")
|
15
|
+
"linux-musl"
|
16
|
+
else
|
17
|
+
"linux"
|
18
|
+
end
|
19
|
+
when /darwin/
|
20
|
+
"darwin"
|
21
|
+
when /freebsd/
|
22
|
+
"freebsd"
|
23
|
+
when /netbsd/
|
24
|
+
"netbsd"
|
25
|
+
when /openbsd/
|
26
|
+
"openbsd"
|
27
|
+
when /sunos|solaris/
|
28
|
+
"solaris"
|
29
|
+
when /mingw|mswin/
|
30
|
+
"windows"
|
31
|
+
else
|
32
|
+
os
|
33
|
+
end
|
34
|
+
|
35
|
+
# Normalize the platform CPU
|
36
|
+
ARCH = case cpu = RbConfig::CONFIG["host_cpu"].downcase
|
37
|
+
when /amd64|x86_64|x64/
|
38
|
+
"x86_64"
|
39
|
+
when /i?86|x86|i86pc/
|
40
|
+
"x86"
|
41
|
+
when /ppc|powerpc/
|
42
|
+
"powerpc"
|
43
|
+
when /^aarch/
|
44
|
+
"aarch"
|
45
|
+
when /^arm/
|
46
|
+
"arm"
|
47
|
+
else
|
48
|
+
cpu
|
49
|
+
end
|
50
|
+
|
51
|
+
def windows?
|
52
|
+
OS == "windows"
|
53
|
+
end
|
54
|
+
|
55
|
+
def solaris?
|
56
|
+
OS == solaries
|
57
|
+
end
|
58
|
+
|
59
|
+
def darwin?
|
60
|
+
OS == "darwin"
|
61
|
+
end
|
62
|
+
|
63
|
+
def macos?
|
64
|
+
darwin? || OS == "macos"
|
65
|
+
end
|
66
|
+
|
67
|
+
def openbsd?
|
68
|
+
OS == "openbsd"
|
69
|
+
end
|
70
|
+
|
71
|
+
def aix?
|
72
|
+
OS == "aix"
|
73
|
+
end
|
74
|
+
|
75
|
+
def nix?
|
76
|
+
!(windows? || solaris? || darwin?)
|
77
|
+
end
|
78
|
+
|
79
|
+
def x86_64?
|
80
|
+
ARCH == "x86_64"
|
81
|
+
end
|
82
|
+
|
83
|
+
def x86?
|
84
|
+
ARCH == "x86"
|
85
|
+
end
|
86
|
+
|
87
|
+
def abs_path(path)
|
88
|
+
File.join(PACKAGE_EXT_DIR, path)
|
89
|
+
end
|
90
|
+
|
91
|
+
def find_header_or_abort(header, *paths)
|
92
|
+
find_header(header, *paths) || abort("#{header} was expected in `#{paths.join(", ")}`, but it is missing.")
|
93
|
+
end
|
94
|
+
|
95
|
+
def find_library_or_abort(lib, func, *paths)
|
96
|
+
find_library(lib, func, *paths) || abort("#{lib} was expected in `#{paths.join(", ")}`, but it is missing.")
|
97
|
+
end
|
98
|
+
|
99
|
+
def concat_flags(*args)
|
100
|
+
args.compact.join(" ")
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,136 @@
|
|
1
|
+
use std::borrow::Cow;
|
2
|
+
|
3
|
+
use comrak::ComrakOptions;
|
4
|
+
|
5
|
+
use magnus::{class, r_hash::ForEach, Error, RHash, Symbol, Value};
|
6
|
+
|
7
|
+
const PARSE_SMART: &str = "smart";
|
8
|
+
const PARSE_DEFAULT_INFO_STRING: &str = "default_info_string";
|
9
|
+
|
10
|
+
fn iterate_parse_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
|
11
|
+
options_hash
|
12
|
+
.foreach(|key: Symbol, value: Value| {
|
13
|
+
match key.name() {
|
14
|
+
Ok(Cow::Borrowed(PARSE_SMART)) => {
|
15
|
+
comrak_options.parse.smart = value.try_convert::<bool>()?;
|
16
|
+
}
|
17
|
+
Ok(Cow::Borrowed(PARSE_DEFAULT_INFO_STRING)) => {
|
18
|
+
comrak_options.parse.default_info_string = try_convert_string(value);
|
19
|
+
}
|
20
|
+
_ => {}
|
21
|
+
}
|
22
|
+
Ok(ForEach::Continue)
|
23
|
+
})
|
24
|
+
.unwrap();
|
25
|
+
}
|
26
|
+
|
27
|
+
const RENDER_HARDBREAKS: &str = "hardbreaks";
|
28
|
+
const RENDER_GITHUB_PRE_LANG: &str = "github_pre_lang";
|
29
|
+
const RENDER_WIDTH: &str = "width";
|
30
|
+
const RENDER_UNSAFE: &str = "unsafe_";
|
31
|
+
const RENDER_ESCAPE: &str = "escape";
|
32
|
+
|
33
|
+
fn iterate_render_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
|
34
|
+
options_hash
|
35
|
+
.foreach(|key: Symbol, value: Value| {
|
36
|
+
match key.name() {
|
37
|
+
Ok(Cow::Borrowed(RENDER_HARDBREAKS)) => {
|
38
|
+
comrak_options.render.hardbreaks = value.try_convert::<bool>()?;
|
39
|
+
}
|
40
|
+
Ok(Cow::Borrowed(RENDER_GITHUB_PRE_LANG)) => {
|
41
|
+
comrak_options.render.github_pre_lang = value.try_convert::<bool>()?;
|
42
|
+
}
|
43
|
+
Ok(Cow::Borrowed(RENDER_WIDTH)) => {
|
44
|
+
comrak_options.render.width = value.try_convert::<usize>()?;
|
45
|
+
}
|
46
|
+
Ok(Cow::Borrowed(RENDER_UNSAFE)) => {
|
47
|
+
comrak_options.render.unsafe_ = value.try_convert::<bool>()?;
|
48
|
+
}
|
49
|
+
Ok(Cow::Borrowed(RENDER_ESCAPE)) => {
|
50
|
+
comrak_options.render.escape = value.try_convert::<bool>()?;
|
51
|
+
}
|
52
|
+
_ => {}
|
53
|
+
}
|
54
|
+
Ok(ForEach::Continue)
|
55
|
+
})
|
56
|
+
.unwrap();
|
57
|
+
}
|
58
|
+
|
59
|
+
const EXTENSION_STRIKETHROUGH: &str = "strikethrough";
|
60
|
+
const EXTENSION_TAGFILTER: &str = "tagfilter";
|
61
|
+
const EXTENSION_TABLE: &str = "table";
|
62
|
+
const EXTENSION_AUTOLINK: &str = "autolink";
|
63
|
+
const EXTENSION_TASKLIST: &str = "tasklist";
|
64
|
+
const EXTENSION_SUPERSCRIPT: &str = "superscript";
|
65
|
+
const EXTENSION_HEADER_IDS: &str = "header_ids";
|
66
|
+
const EXTENSION_FOOTNOTES: &str = "footnotes";
|
67
|
+
const EXTENSION_DESCRIPTION_LISTS: &str = "description_lists";
|
68
|
+
const EXTENSION_FRONT_MATTER_DELIMITER: &str = "front_matter_delimiter";
|
69
|
+
|
70
|
+
fn iterate_extension_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
|
71
|
+
options_hash
|
72
|
+
.foreach(|key: Symbol, value: Value| {
|
73
|
+
match key.name() {
|
74
|
+
Ok(Cow::Borrowed(EXTENSION_STRIKETHROUGH)) => {
|
75
|
+
comrak_options.extension.strikethrough = value.try_convert::<bool>()?;
|
76
|
+
}
|
77
|
+
Ok(Cow::Borrowed(EXTENSION_TAGFILTER)) => {
|
78
|
+
comrak_options.extension.tagfilter = value.try_convert::<bool>()?;
|
79
|
+
}
|
80
|
+
Ok(Cow::Borrowed(EXTENSION_TABLE)) => {
|
81
|
+
comrak_options.extension.table = value.try_convert::<bool>()?;
|
82
|
+
}
|
83
|
+
Ok(Cow::Borrowed(EXTENSION_AUTOLINK)) => {
|
84
|
+
comrak_options.extension.autolink = value.try_convert::<bool>()?;
|
85
|
+
}
|
86
|
+
Ok(Cow::Borrowed(EXTENSION_TASKLIST)) => {
|
87
|
+
comrak_options.extension.tasklist = value.try_convert::<bool>()?;
|
88
|
+
}
|
89
|
+
Ok(Cow::Borrowed(EXTENSION_SUPERSCRIPT)) => {
|
90
|
+
comrak_options.extension.superscript = value.try_convert::<bool>()?;
|
91
|
+
}
|
92
|
+
Ok(Cow::Borrowed(EXTENSION_HEADER_IDS)) => {
|
93
|
+
comrak_options.extension.header_ids = try_convert_string(value);
|
94
|
+
}
|
95
|
+
Ok(Cow::Borrowed(EXTENSION_FOOTNOTES)) => {
|
96
|
+
comrak_options.extension.footnotes = value.try_convert::<bool>()?;
|
97
|
+
}
|
98
|
+
Ok(Cow::Borrowed(EXTENSION_DESCRIPTION_LISTS)) => {
|
99
|
+
comrak_options.extension.description_lists = value.try_convert::<bool>()?;
|
100
|
+
}
|
101
|
+
Ok(Cow::Borrowed(EXTENSION_FRONT_MATTER_DELIMITER)) => {
|
102
|
+
comrak_options.extension.front_matter_delimiter = try_convert_string(value);
|
103
|
+
}
|
104
|
+
_ => {}
|
105
|
+
}
|
106
|
+
Ok(ForEach::Continue)
|
107
|
+
})
|
108
|
+
.unwrap();
|
109
|
+
}
|
110
|
+
|
111
|
+
pub fn iterate_options_hash(
|
112
|
+
comrak_options: &mut ComrakOptions,
|
113
|
+
key: Symbol,
|
114
|
+
value: RHash,
|
115
|
+
) -> Result<ForEach, Error> {
|
116
|
+
assert!(value.is_kind_of(class::hash()));
|
117
|
+
|
118
|
+
if key.name().unwrap() == "parse" {
|
119
|
+
iterate_parse_options(comrak_options, value);
|
120
|
+
}
|
121
|
+
if key.name().unwrap() == "render" {
|
122
|
+
iterate_render_options(comrak_options, value);
|
123
|
+
}
|
124
|
+
if key.name().unwrap() == "extension" {
|
125
|
+
iterate_extension_options(comrak_options, value);
|
126
|
+
}
|
127
|
+
Ok(ForEach::Continue)
|
128
|
+
}
|
129
|
+
|
130
|
+
fn try_convert_string(value: Value) -> Option<String> {
|
131
|
+
if value.is_kind_of(class::string()) {
|
132
|
+
Some(value.try_convert::<String>().unwrap())
|
133
|
+
} else {
|
134
|
+
None
|
135
|
+
}
|
136
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
extern crate core;
|
2
|
+
|
3
|
+
use comrak::{markdown_to_html, ComrakOptions};
|
4
|
+
use magnus::{define_module, function, r_hash::ForEach, Error, RHash, Symbol};
|
5
|
+
|
6
|
+
mod comrak_options;
|
7
|
+
use comrak_options::iterate_options_hash;
|
8
|
+
|
9
|
+
fn commonmark_to_html(rb_commonmark: String, rb_options: magnus::RHash) -> String {
|
10
|
+
let mut comrak_options = ComrakOptions::default();
|
11
|
+
|
12
|
+
rb_options
|
13
|
+
.foreach(|key: Symbol, value: RHash| {
|
14
|
+
iterate_options_hash(&mut comrak_options, key, value).unwrap();
|
15
|
+
Ok(ForEach::Continue)
|
16
|
+
})
|
17
|
+
.unwrap();
|
18
|
+
|
19
|
+
markdown_to_html(&rb_commonmark, &comrak_options)
|
20
|
+
}
|
21
|
+
|
22
|
+
#[magnus::init]
|
23
|
+
fn init() -> Result<(), Error> {
|
24
|
+
let module = define_module("Commonmarker")?;
|
25
|
+
|
26
|
+
module.define_module_function("commonmark_to_html", function!(commonmark_to_html, 2))?;
|
27
|
+
|
28
|
+
Ok(())
|
29
|
+
}
|
Binary file
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Commonmarker
|
4
|
+
module Config
|
5
|
+
# For details, see
|
6
|
+
# https://github.com/kivikakk/comrak/blob/162ef9354deb2c9b4a4e05be495aa372ba5bb696/src/main.rs#L201
|
7
|
+
OPTS = {
|
8
|
+
parse: {
|
9
|
+
smart: false,
|
10
|
+
default_info_string: "",
|
11
|
+
}.freeze,
|
12
|
+
render: {
|
13
|
+
hardbreaks: true,
|
14
|
+
github_pre_lang: true,
|
15
|
+
width: 80,
|
16
|
+
unsafe_: false,
|
17
|
+
escape: false,
|
18
|
+
}.freeze,
|
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: nil,
|
30
|
+
},
|
31
|
+
format: [:html].freeze,
|
32
|
+
}.freeze
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def merged_with_defaults(options)
|
36
|
+
Commonmarker::Config::OPTS.merge(process_options(options))
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_options(options)
|
40
|
+
{
|
41
|
+
parse: process_parse_options(options[:parse]),
|
42
|
+
render: process_render_options(options[:render]),
|
43
|
+
extension: process_extension_options(options[:extension]),
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
BOOLS = [true, false]
|
49
|
+
["parse", "render", "extension"].each do |type|
|
50
|
+
define_singleton_method :"process_#{type}_options" do |options|
|
51
|
+
Commonmarker::Config::OPTS[type.to_sym].each_with_object({}) do |(key, value), hash|
|
52
|
+
if options.nil? # option not provided, go for the default
|
53
|
+
hash[key] = value
|
54
|
+
next
|
55
|
+
end
|
56
|
+
|
57
|
+
# option explicitly not included, remove it
|
58
|
+
next if options[key].nil?
|
59
|
+
|
60
|
+
value_klass = value.class
|
61
|
+
if BOOLS.include?(value) && BOOLS.include?(options[key])
|
62
|
+
hash[key] = options[key]
|
63
|
+
elsif options[key].is_a?(value_klass)
|
64
|
+
hash[key] = options[key]
|
65
|
+
else
|
66
|
+
expected_type = BOOLS.include?(value) ? "Boolean" : value_klass.to_s
|
67
|
+
raise TypeError, "#{type}_options[:#{key}] must be a #{expected_type}; got #{options[key].class}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
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
|
data/lib/commonmarker.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "commonmarker/extension"
|
4
|
+
|
5
|
+
require "commonmarker/config"
|
6
|
+
require "commonmarker/renderer"
|
7
|
+
require "commonmarker/version"
|
8
|
+
|
9
|
+
if ENV.fetch("DEBUG", false)
|
10
|
+
require "awesome_print"
|
11
|
+
require "debug"
|
12
|
+
end
|
13
|
+
|
14
|
+
module Commonmarker
|
15
|
+
class << self
|
16
|
+
# Public: Parses a CommonMark string into an HTML string.
|
17
|
+
#
|
18
|
+
# text - A {String} of text
|
19
|
+
# option - A {Hash} of render, parse, and extension options to transform the text.
|
20
|
+
#
|
21
|
+
# Returns a {String} of converted HTML.
|
22
|
+
def to_html(text, options: Commonmarker::Config::OPTS)
|
23
|
+
raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
|
24
|
+
raise TypeError, "options must be a Hash; got a #{options.class}!" unless options.is_a?(Hash)
|
25
|
+
|
26
|
+
opts = Config.process_options(options)
|
27
|
+
commonmark_to_html(text.encode("UTF-8"), opts)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: commonmarker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre.2
|
5
|
+
platform: x64-mingw-ucrt
|
6
|
+
authors:
|
7
|
+
- Garen Torikian
|
8
|
+
- Ashe Connor
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-11-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rb_sys
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.9'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.9'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '13.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '13.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake-compiler
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.2'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.2'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rake-compiler-dock
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.2'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.2'
|
70
|
+
description: A fast, safe, extensible parser for CommonMark. This wraps the comrak
|
71
|
+
Rust crate.
|
72
|
+
email:
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- LICENSE.txt
|
78
|
+
- README.md
|
79
|
+
- commonmarker.gemspec
|
80
|
+
- ext/commonmarker/Cargo.toml
|
81
|
+
- ext/commonmarker/_util.rb
|
82
|
+
- ext/commonmarker/extconf.rb
|
83
|
+
- ext/commonmarker/src/comrak_options.rs
|
84
|
+
- ext/commonmarker/src/lib.rs
|
85
|
+
- lib/commonmarker.rb
|
86
|
+
- lib/commonmarker/3.1/commonmarker.so
|
87
|
+
- lib/commonmarker/config.rb
|
88
|
+
- lib/commonmarker/extension.rb
|
89
|
+
- lib/commonmarker/renderer.rb
|
90
|
+
- lib/commonmarker/version.rb
|
91
|
+
homepage: https://github.com/gjtorikian/commonmarker
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata:
|
95
|
+
allowed_push_host: https://rubygems.org
|
96
|
+
funding_uri: https://github.com/sponsors/gjtorikian/
|
97
|
+
source_code_uri: https://github.com/gjtorikian/commonmarker
|
98
|
+
rubygems_mfa_required: 'true'
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '3.1'
|
108
|
+
- - "<"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.2.dev
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: 3.3.22
|
116
|
+
requirements: []
|
117
|
+
rubygems_version: 3.3.22
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: CommonMark parser and renderer. Written in Rust, wrapped in Ruby.
|
121
|
+
test_files: []
|