commonmarker 1.0.0.pre.2-x64-mingw-ucrt
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 +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: []
|