commonmarker 2.1.0-x86_64-linux-musl
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 +353 -0
- data/lib/commonmarker/3.2/commonmarker.so +0 -0
- data/lib/commonmarker/3.4/commonmarker.so +0 -0
- data/lib/commonmarker/config.rb +106 -0
- data/lib/commonmarker/constants.rb +7 -0
- data/lib/commonmarker/extension.rb +14 -0
- data/lib/commonmarker/node/ast.rb +8 -0
- data/lib/commonmarker/node/inspect.rb +57 -0
- data/lib/commonmarker/node.rb +65 -0
- data/lib/commonmarker/renderer.rb +9 -0
- data/lib/commonmarker/utils.rb +22 -0
- data/lib/commonmarker/version.rb +5 -0
- data/lib/commonmarker.rb +47 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3f88e612b168dbb434634b94eafd4972997133d12ff465dd2e03c29329e7ad79
|
4
|
+
data.tar.gz: 875dd647a918273636035fe8f6410a5dfd792658b215703a01b44bef8a19f1e4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b83f172e794609798fc8e8e5f2fdb8eef13dd0c0ce947830d3f356f29fed4e5a440aacb3296606a6b0ffa42fb45374732107600a33da0d09d17bad42f8d2d260
|
7
|
+
data.tar.gz: 98f33609265fd773e5fd88e22519790e4795917fde6d43484d7ad5d1e0819d08aa0960c2d5b49db0c1e8c86d7b3bbe4e3e9910e4d66230f08e3b5decac58e6cc
|
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,353 @@
|
|
1
|
+
# Commonmarker
|
2
|
+
|
3
|
+
Ruby wrapper for Rust's [comrak](https://github.com/kivikakk/comrak) crate.
|
4
|
+
|
5
|
+
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.
|
6
|
+
|
7
|
+
> [!NOTE]
|
8
|
+
> By default, several extensions not in any spec have been enabled, for the sake of end user convenience when generating HTML.
|
9
|
+
>
|
10
|
+
> For more information on the available options and extensions, see [the documentation below](#options-and-plugins).
|
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
|
+
This gem expects to receive UTF-8 strings. Ensure your strings are the right encoding before passing them into `Commonmarker`.
|
29
|
+
|
30
|
+
### Converting to HTML
|
31
|
+
|
32
|
+
Call `to_html` on a string to convert it to HTML:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
require 'commonmarker'
|
36
|
+
Commonmarker.to_html('"Hi *there*"', options: {
|
37
|
+
parse: { smart: true }
|
38
|
+
})
|
39
|
+
# => <p>“Hi <em>there</em>”</p>\n
|
40
|
+
```
|
41
|
+
|
42
|
+
(The second argument is optional--[see below](#options-and-plugins) for more information.)
|
43
|
+
|
44
|
+
### Generating a document
|
45
|
+
|
46
|
+
You can also parse a string to receive a `:document` node. You can then print that node to HTML, iterate over the children, and do other fun node stuff. For example:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'commonmarker'
|
50
|
+
|
51
|
+
doc = Commonmarker.parse("*Hello* world", options: {
|
52
|
+
parse: { smart: true }
|
53
|
+
})
|
54
|
+
puts(doc.to_html) # => <p><em>Hello</em> world</p>\n
|
55
|
+
|
56
|
+
doc.walk do |node|
|
57
|
+
puts node.type # => [:document, :paragraph, :emph, :text, :text]
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
(The second argument is optional--[see below](#options-and-plugins) for more information.)
|
62
|
+
|
63
|
+
When it comes to modifying the document, you can perform the following operations:
|
64
|
+
|
65
|
+
- `insert_before`
|
66
|
+
- `insert_after`
|
67
|
+
- `prepend_child`
|
68
|
+
- `append_child`
|
69
|
+
- `delete`
|
70
|
+
|
71
|
+
You can also get the source position of a node by calling `source_position`:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
doc = Commonmarker.parse("*Hello* world")
|
75
|
+
puts doc.first_child.first_child.source_position
|
76
|
+
# => {:start_line=>1, :start_column=>1, :end_line=>1, :end_column=>7}
|
77
|
+
```
|
78
|
+
|
79
|
+
You can also modify the following attributes:
|
80
|
+
|
81
|
+
- `url`
|
82
|
+
- `title`
|
83
|
+
- `header_level`
|
84
|
+
- `list_type`
|
85
|
+
- `list_start`
|
86
|
+
- `list_tight`
|
87
|
+
- `fence_info`
|
88
|
+
|
89
|
+
#### Example: Walking the AST
|
90
|
+
|
91
|
+
You can use `walk` or `each` to iterate over nodes:
|
92
|
+
|
93
|
+
- `walk` will iterate on a node and recursively iterate on a node's children.
|
94
|
+
- `each` will iterate on a node's direct children, but no further.
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
require 'commonmarker'
|
98
|
+
|
99
|
+
# parse some string
|
100
|
+
doc = Commonmarker.parse("# The site\n\n [GitHub](https://www.github.com)")
|
101
|
+
|
102
|
+
# Walk tree and print out URLs for links
|
103
|
+
doc.walk do |node|
|
104
|
+
if node.type == :link
|
105
|
+
printf("URL = %s\n", node.url)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
# => URL = https://www.github.com
|
109
|
+
|
110
|
+
# Transform links to regular text
|
111
|
+
doc.walk do |node|
|
112
|
+
if node.type == :link
|
113
|
+
node.insert_before(node.first_child)
|
114
|
+
node.delete
|
115
|
+
end
|
116
|
+
end
|
117
|
+
# => <h1><a href=\"#the-site\"></a>The site</h1>\n<p>GitHub</p>\n
|
118
|
+
```
|
119
|
+
|
120
|
+
#### Example: Converting a document back into raw CommonMark
|
121
|
+
|
122
|
+
You can use `to_commonmark` on a node to render it as raw text:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
require 'commonmarker'
|
126
|
+
|
127
|
+
# parse some string
|
128
|
+
doc = Commonmarker.parse("# The site\n\n [GitHub](https://www.github.com)")
|
129
|
+
|
130
|
+
# Transform links to regular text
|
131
|
+
doc.walk do |node|
|
132
|
+
if node.type == :link
|
133
|
+
node.insert_before(node.first_child)
|
134
|
+
node.delete
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
doc.to_commonmark
|
139
|
+
# => # The site\n\nGitHub\n
|
140
|
+
```
|
141
|
+
|
142
|
+
## Options and plugins
|
143
|
+
|
144
|
+
### Options
|
145
|
+
|
146
|
+
Commonmarker accepts the same parse, render, and extensions options that comrak does, as a hash dictionary with symbol keys:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
Commonmarker.to_html('"Hi *there*"', options:{
|
150
|
+
parse: { smart: true },
|
151
|
+
render: { hardbreaks: false}
|
152
|
+
})
|
153
|
+
```
|
154
|
+
|
155
|
+
Note that there is a distinction in comrak for "parse" options and "render" options, which are represented in the tables below. As well, if you wish to disable any-non boolean option, pass in `nil`.
|
156
|
+
|
157
|
+
### Parse options
|
158
|
+
|
159
|
+
| Name | Description | Default |
|
160
|
+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
161
|
+
| `smart` | Punctuation (quotes, full-stops and hyphens) are converted into 'smart' punctuation. | `false` |
|
162
|
+
| `default_info_string` | The default info string for fenced code blocks. | `""` |
|
163
|
+
| `relaxed_tasklist_matching` | Enables relaxing of the tasklist extension matching, allowing any non-space to be used for the "checked" state instead of only `x` and `X`. | `false` |
|
164
|
+
| `relaxed_autolinks` | Enable relaxing of the autolink extension parsing, allowing links to be recognized when in brackets, as well as permitting any url scheme. | `false` |
|
165
|
+
|
166
|
+
### Render options
|
167
|
+
|
168
|
+
| Name | Description | Default |
|
169
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------ | ------- |
|
170
|
+
| `hardbreaks` | [Soft line breaks](http://spec.commonmark.org/0.27/#soft-line-breaks) translate into hard line breaks. | `true` |
|
171
|
+
| `github_pre_lang` | GitHub-style `<pre lang="xyz">` is used for fenced code blocks with info tags. | `true` |
|
172
|
+
| `full_info_string` | Gives info string data after a space in a `data-meta` attribute on code blocks. | `false` |
|
173
|
+
| `width` | The wrap column when outputting CommonMark. | `80` |
|
174
|
+
| `unsafe` | Allow rendering of raw HTML and potentially dangerous links. | `false` |
|
175
|
+
| `escape` | Escape raw HTML instead of clobbering it. | `false` |
|
176
|
+
| `sourcepos` | Include source position attribute in HTML and XML output. | `false` |
|
177
|
+
| `escaped_char_spans` | Wrap escaped characters in span tags. | `true` |
|
178
|
+
| `ignore_setext` | Ignores setext-style headings. | `false` |
|
179
|
+
| `ignore_empty_links` | Ignores empty links, leaving the Markdown text in place. | `false` |
|
180
|
+
| `gfm_quirks` | Outputs HTML with GFM-style quirks; namely, not nesting `<strong>` inlines. | `false` |
|
181
|
+
| `prefer_fenced` | Always output fenced code blocks, even where an indented one could be used. | `false` |
|
182
|
+
|
183
|
+
As well, there are several extensions which you can toggle in the same manner:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
Commonmarker.to_html('"Hi *there*"', options: {
|
187
|
+
extension: { footnotes: true, description_lists: true },
|
188
|
+
render: { hardbreaks: false }
|
189
|
+
})
|
190
|
+
```
|
191
|
+
|
192
|
+
### Extension options
|
193
|
+
|
194
|
+
| Name | Description | Default |
|
195
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------- |
|
196
|
+
| `strikethrough` | Enables the [strikethrough extension](https://github.github.com/gfm/#strikethrough-extension-) from the GFM spec. | `true` |
|
197
|
+
| `tagfilter` | Enables the [tagfilter extension](https://github.github.com/gfm/#disallowed-raw-html-extension-) from the GFM spec. | `true` |
|
198
|
+
| `table` | Enables the [table extension](https://github.github.com/gfm/#tables-extension-) from the GFM spec. | `true` |
|
199
|
+
| `autolink` | Enables the [autolink extension](https://github.github.com/gfm/#autolinks-extension-) from the GFM spec. | `true` |
|
200
|
+
| `tasklist` | Enables the [task list extension](https://github.github.com/gfm/#task-list-items-extension-) from the GFM spec. | `true` |
|
201
|
+
| `superscript` | Enables the superscript Comrak extension. | `false` |
|
202
|
+
| `header_ids` | Enables the header IDs Comrak extension. from the GFM spec. | `""` |
|
203
|
+
| `footnotes` | Enables the footnotes extension per `cmark-gfm`. | `false` |
|
204
|
+
| `description_lists` | Enables the description lists extension. | `false` |
|
205
|
+
| `front_matter_delimiter` | Enables the front matter extension. | `""` |
|
206
|
+
| `multiline_block_quotes` | Enables the multiline block quotes extension. | `false` |
|
207
|
+
| `math_dollars`, `math_code` | Enables the math extension. | `false` |
|
208
|
+
| `shortcodes` | Enables the shortcodes extension. | `true` |
|
209
|
+
| `wikilinks_title_before_pipe` | Enables the wikilinks extension, placing the title before the dividing pipe. | `false` |
|
210
|
+
| `wikilinks_title_after_pipe` | Enables the shortcodes extension, placing the title after the dividing pipe. | `false` |
|
211
|
+
| `underline` | Enables the underline extension. | `false` |
|
212
|
+
| `spoiler` | Enables the spoiler extension. | `false` |
|
213
|
+
| `greentext` | Enables the greentext extension. | `false` |
|
214
|
+
| `subscript` | Enables the subscript extension. | `false` |
|
215
|
+
| `alerts` | Enables the alerts extension. | `false` |
|
216
|
+
|
217
|
+
For more information on these options, see [the comrak documentation](https://github.com/kivikakk/comrak#usage).
|
218
|
+
|
219
|
+
### Plugins
|
220
|
+
|
221
|
+
In addition to the possibilities provided by generic CommonMark rendering, Commonmarker also supports plugins as a means of
|
222
|
+
providing further niceties.
|
223
|
+
|
224
|
+
#### Syntax Highlighter Plugin
|
225
|
+
|
226
|
+
The library comes with [a set of pre-existing themes](https://docs.rs/syntect/5.0.0/syntect/highlighting/struct.ThemeSet.html#implementations) for highlighting code:
|
227
|
+
|
228
|
+
- `"base16-ocean.dark"`
|
229
|
+
- `"base16-eighties.dark"`
|
230
|
+
- `"base16-mocha.dark"`
|
231
|
+
- `"base16-ocean.light"`
|
232
|
+
- `"InspiredGitHub"`
|
233
|
+
- `"Solarized (dark)"`
|
234
|
+
- `"Solarized (light)"`
|
235
|
+
|
236
|
+
````ruby
|
237
|
+
code = <<~CODE
|
238
|
+
```ruby
|
239
|
+
def hello
|
240
|
+
puts "hello"
|
241
|
+
end
|
242
|
+
```
|
243
|
+
CODE
|
244
|
+
|
245
|
+
# pass in a theme name from a pre-existing set
|
246
|
+
puts Commonmarker.to_html(code, plugins: { syntax_highlighter: { theme: "InspiredGitHub" } })
|
247
|
+
|
248
|
+
# <pre style="background-color:#ffffff;" lang="ruby"><code>
|
249
|
+
# <span style="font-weight:bold;color:#a71d5d;">def </span><span style="font-weight:bold;color:#795da3;">hello
|
250
|
+
# </span><span style="color:#62a35c;">puts </span><span style="color:#183691;">"hello"
|
251
|
+
# </span><span style="font-weight:bold;color:#a71d5d;">end
|
252
|
+
# </span>
|
253
|
+
# </code></pre>
|
254
|
+
````
|
255
|
+
|
256
|
+
By default, the plugin uses the `"base16-ocean.dark"` theme to syntax highlight code.
|
257
|
+
|
258
|
+
To disable this plugin, set the value to `nil`:
|
259
|
+
|
260
|
+
````ruby
|
261
|
+
code = <<~CODE
|
262
|
+
```ruby
|
263
|
+
def hello
|
264
|
+
puts "hello"
|
265
|
+
end
|
266
|
+
```
|
267
|
+
CODE
|
268
|
+
|
269
|
+
Commonmarker.to_html(code, plugins: { syntax_highlighter: nil })
|
270
|
+
|
271
|
+
# <pre lang="ruby"><code>def hello
|
272
|
+
# puts "hello"
|
273
|
+
# end
|
274
|
+
# </code></pre>
|
275
|
+
````
|
276
|
+
|
277
|
+
To output CSS classes instead of `style` attributes, set the `theme` key to `""`:
|
278
|
+
|
279
|
+
````ruby
|
280
|
+
code = <<~CODE
|
281
|
+
```ruby
|
282
|
+
def hello
|
283
|
+
puts "hello"
|
284
|
+
end
|
285
|
+
CODE
|
286
|
+
|
287
|
+
Commonmarker.to_html(code, plugins: { syntax_highlighter: { theme: "" } })
|
288
|
+
|
289
|
+
# <pre class="syntax-highlighting"><code><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> # <span class="entity name function ruby">hello</span></span>
|
290
|
+
# <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">"</span>hello<span class="punctuation definition string end ruby">"</span></span>
|
291
|
+
# <span class="keyword control ruby">end</span>\n</span></code></pre>
|
292
|
+
````
|
293
|
+
|
294
|
+
To use a custom theme, you can provide a `path` to a directory containing `.tmtheme` files to load:
|
295
|
+
|
296
|
+
```ruby
|
297
|
+
Commonmarker.to_html(code, plugins: { syntax_highlighter: { theme: "Monokai", path: "./themes" } })
|
298
|
+
```
|
299
|
+
|
300
|
+
## Output formats
|
301
|
+
|
302
|
+
Commonmarker can currently only generate output in one format: HTML.
|
303
|
+
|
304
|
+
### HTML
|
305
|
+
|
306
|
+
```ruby
|
307
|
+
puts Commonmarker.to_html('*Hello* world!')
|
308
|
+
|
309
|
+
# <p><em>Hello</em> world!</p>
|
310
|
+
```
|
311
|
+
|
312
|
+
## Developing locally
|
313
|
+
|
314
|
+
After cloning the repo:
|
315
|
+
|
316
|
+
```
|
317
|
+
script/bootstrap
|
318
|
+
bundle exec rake compile
|
319
|
+
```
|
320
|
+
|
321
|
+
If there were no errors, you're done! Otherwise, make sure to follow the comrak dependency instructions.
|
322
|
+
|
323
|
+
## Benchmarks
|
324
|
+
|
325
|
+
```
|
326
|
+
❯ bundle exec rake benchmark
|
327
|
+
input size = 11064832 bytes
|
328
|
+
|
329
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
|
330
|
+
Warming up --------------------------------------
|
331
|
+
Markly.render_html 1.000 i/100ms
|
332
|
+
Markly::Node#to_html 1.000 i/100ms
|
333
|
+
Commonmarker.to_html 1.000 i/100ms
|
334
|
+
Commonmarker::Node.to_html
|
335
|
+
1.000 i/100ms
|
336
|
+
Kramdown::Document#to_html
|
337
|
+
1.000 i/100ms
|
338
|
+
Calculating -------------------------------------
|
339
|
+
Markly.render_html 15.606 (±25.6%) i/s - 71.000 in 5.047132s
|
340
|
+
Markly::Node#to_html 15.692 (±25.5%) i/s - 72.000 in 5.095810s
|
341
|
+
Commonmarker.to_html 4.482 (± 0.0%) i/s - 23.000 in 5.137680s
|
342
|
+
Commonmarker::Node.to_html
|
343
|
+
5.092 (±19.6%) i/s - 25.000 in 5.072220s
|
344
|
+
Kramdown::Document#to_html
|
345
|
+
0.379 (± 0.0%) i/s - 2.000 in 5.277770s
|
346
|
+
|
347
|
+
Comparison:
|
348
|
+
Markly::Node#to_html: 15.7 i/s
|
349
|
+
Markly.render_html: 15.6 i/s - same-ish: difference falls within error
|
350
|
+
Commonmarker::Node.to_html: 5.1 i/s - 3.08x slower
|
351
|
+
Commonmarker.to_html: 4.5 i/s - 3.50x slower
|
352
|
+
Kramdown::Document#to_html: 0.4 i/s - 41.40x slower
|
353
|
+
```
|
Binary file
|
Binary file
|
@@ -0,0 +1,106 @@
|
|
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
|
+
OPTIONS = {
|
8
|
+
parse: {
|
9
|
+
smart: false,
|
10
|
+
default_info_string: "",
|
11
|
+
relaxed_tasklist_matching: false,
|
12
|
+
relaxed_autolinks: false,
|
13
|
+
}.freeze,
|
14
|
+
render: {
|
15
|
+
hardbreaks: true,
|
16
|
+
github_pre_lang: true,
|
17
|
+
full_info_string: false,
|
18
|
+
width: 80,
|
19
|
+
unsafe: false,
|
20
|
+
escape: false,
|
21
|
+
sourcepos: false,
|
22
|
+
escaped_char_spans: true,
|
23
|
+
ignore_setext: false,
|
24
|
+
ignore_empty_links: false,
|
25
|
+
gfm_quirks: false,
|
26
|
+
prefer_fenced: false,
|
27
|
+
}.freeze,
|
28
|
+
extension: {
|
29
|
+
strikethrough: true,
|
30
|
+
tagfilter: true,
|
31
|
+
table: true,
|
32
|
+
autolink: true,
|
33
|
+
tasklist: true,
|
34
|
+
superscript: false,
|
35
|
+
header_ids: "",
|
36
|
+
footnotes: false,
|
37
|
+
description_lists: false,
|
38
|
+
front_matter_delimiter: "",
|
39
|
+
multiline_block_quotes: false,
|
40
|
+
math_dollars: false,
|
41
|
+
math_code: false,
|
42
|
+
shortcodes: true,
|
43
|
+
wikilinks_title_before_pipe: false,
|
44
|
+
wikilinks_title_after_pipe: false,
|
45
|
+
underline: false,
|
46
|
+
spoiler: false,
|
47
|
+
greentext: false,
|
48
|
+
subscript: false,
|
49
|
+
alerts: false,
|
50
|
+
}.freeze,
|
51
|
+
format: [:html].freeze,
|
52
|
+
}.freeze
|
53
|
+
|
54
|
+
PLUGINS = {
|
55
|
+
syntax_highlighter: {
|
56
|
+
theme: "base16-ocean.dark",
|
57
|
+
path: "",
|
58
|
+
},
|
59
|
+
}
|
60
|
+
|
61
|
+
class << self
|
62
|
+
include Commonmarker::Utils
|
63
|
+
|
64
|
+
def process_options(options)
|
65
|
+
{
|
66
|
+
parse: process_parse_options(options[:parse].dup),
|
67
|
+
render: process_render_options(options[:render].dup),
|
68
|
+
extension: process_extension_options(options[:extension].dup),
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def process_plugins(plugins)
|
73
|
+
{
|
74
|
+
syntax_highlighter: process_syntax_highlighter_plugin(plugins&.fetch(:syntax_highlighter, nil)),
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
[:parse, :render, :extension].each do |type|
|
80
|
+
define_singleton_method :"process_#{type}_options" do |options|
|
81
|
+
Commonmarker::Config::OPTIONS[type].each_with_object({}) do |(key, value), hash|
|
82
|
+
if options.nil? || !options.key?(key) # option not provided, use the default
|
83
|
+
hash[key] = value
|
84
|
+
next
|
85
|
+
end
|
86
|
+
|
87
|
+
if options[key].nil? # # option explicitly not included, remove it
|
88
|
+
options.delete(key)
|
89
|
+
next
|
90
|
+
end
|
91
|
+
|
92
|
+
hash[key] = fetch_kv(options, key, value, type)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
define_singleton_method :process_syntax_highlighter_plugin do |options|
|
98
|
+
return if options.nil? # plugin explicitly nil, remove it
|
99
|
+
|
100
|
+
raise TypeError, "Expected a Hash for syntax_highlighter plugin, got #{options.class}" unless options.is_a?(Hash)
|
101
|
+
raise TypeError, "Expected a Hash for syntax_highlighter plugin, got nothing" if options.empty?
|
102
|
+
|
103
|
+
Commonmarker::Config::PLUGINS[:syntax_highlighter].merge(options)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
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
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pp"
|
4
|
+
|
5
|
+
module Commonmarker
|
6
|
+
class Node
|
7
|
+
module Inspect
|
8
|
+
PP_INDENT_SIZE = 2
|
9
|
+
|
10
|
+
def inspect
|
11
|
+
PP.pp(self, +"", Float::INFINITY)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param printer [PrettyPrint] pp
|
15
|
+
def pretty_print(printer)
|
16
|
+
printer.group(PP_INDENT_SIZE, "#<#{self.class}(#{type}):", ">") do
|
17
|
+
printer.breakable
|
18
|
+
|
19
|
+
attrs = [
|
20
|
+
:source_position,
|
21
|
+
:string_content,
|
22
|
+
:url,
|
23
|
+
:title,
|
24
|
+
:header_level,
|
25
|
+
:list_type,
|
26
|
+
:list_start,
|
27
|
+
:list_tight,
|
28
|
+
:fence_info,
|
29
|
+
].filter_map do |name|
|
30
|
+
[name, __send__(name)]
|
31
|
+
rescue StandardError
|
32
|
+
nil
|
33
|
+
end.compact
|
34
|
+
|
35
|
+
printer.seplist(attrs) do |name, value|
|
36
|
+
printer.text("#{name}=")
|
37
|
+
printer.pp(value)
|
38
|
+
end
|
39
|
+
|
40
|
+
if first_child
|
41
|
+
printer.breakable
|
42
|
+
printer.group(PP_INDENT_SIZE) do
|
43
|
+
children = []
|
44
|
+
node = first_child
|
45
|
+
while node
|
46
|
+
children << node
|
47
|
+
node = node.next_sibling
|
48
|
+
end
|
49
|
+
printer.text("children=")
|
50
|
+
printer.pp(children)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "commonmarker/node/ast"
|
4
|
+
require "commonmarker/node/inspect"
|
5
|
+
|
6
|
+
module Commonmarker
|
7
|
+
class Node
|
8
|
+
include Enumerable
|
9
|
+
include Inspect
|
10
|
+
|
11
|
+
# Public: An iterator that "walks the tree," descending into children recursively.
|
12
|
+
#
|
13
|
+
# blk - A {Proc} representing the action to take for each child
|
14
|
+
def walk(&block)
|
15
|
+
return enum_for(:walk) unless block
|
16
|
+
|
17
|
+
yield self
|
18
|
+
each do |child|
|
19
|
+
child.walk(&block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: Iterate over the children (if any) of the current pointer.
|
24
|
+
def each
|
25
|
+
return enum_for(:each) unless block_given?
|
26
|
+
|
27
|
+
child = first_child
|
28
|
+
while child
|
29
|
+
next_child = child.next_sibling
|
30
|
+
yield child
|
31
|
+
child = next_child
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Public: Converts a node to an HTML string.
|
36
|
+
#
|
37
|
+
# options - A {Hash} of render, parse, and extension options to transform the text.
|
38
|
+
# plugins - A {Hash} of additional plugins.
|
39
|
+
#
|
40
|
+
# Returns a {String} of HTML.
|
41
|
+
def to_html(options: Commonmarker::Config::OPTIONS, plugins: Commonmarker::Config::PLUGINS)
|
42
|
+
raise TypeError, "options must be a Hash; got a #{options.class}!" unless options.is_a?(Hash)
|
43
|
+
|
44
|
+
opts = Config.process_options(options)
|
45
|
+
plugins = Config.process_plugins(plugins)
|
46
|
+
|
47
|
+
node_to_html(options: opts, plugins: plugins).force_encoding("utf-8")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Public: Convert the node to a CommonMark string.
|
51
|
+
#
|
52
|
+
# options - A {Symbol} or {Array of Symbol}s indicating the render options
|
53
|
+
# plugins - A {Hash} of additional plugins.
|
54
|
+
#
|
55
|
+
# Returns a {String}.
|
56
|
+
def to_commonmark(options: Commonmarker::Config::OPTIONS, plugins: Commonmarker::Config::PLUGINS)
|
57
|
+
raise TypeError, "options must be a Hash; got a #{options.class}!" unless options.is_a?(Hash)
|
58
|
+
|
59
|
+
opts = Config.process_options(options)
|
60
|
+
plugins = Config.process_plugins(plugins)
|
61
|
+
|
62
|
+
node_to_commonmark(options: opts, plugins: plugins).force_encoding("utf-8")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
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(options, key, value, type)
|
10
|
+
value_klass = value.class
|
11
|
+
|
12
|
+
if Constants::BOOLS.include?(value) && BOOLS.include?(options[key])
|
13
|
+
options[key]
|
14
|
+
elsif options[key].is_a?(value_klass)
|
15
|
+
options[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 #{options[key].class}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/commonmarker.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "commonmarker/extension"
|
4
|
+
|
5
|
+
require "commonmarker/utils"
|
6
|
+
require "commonmarker/node"
|
7
|
+
require "commonmarker/config"
|
8
|
+
require "commonmarker/renderer"
|
9
|
+
require "commonmarker/version"
|
10
|
+
|
11
|
+
module Commonmarker
|
12
|
+
class << self
|
13
|
+
# Public: Parses a CommonMark string into an HTML string.
|
14
|
+
#
|
15
|
+
# text - A {String} of text
|
16
|
+
# options - A {Hash} of render, parse, and extension options to transform the text.
|
17
|
+
#
|
18
|
+
# Returns the `parser` node.
|
19
|
+
def parse(text, options: Commonmarker::Config::OPTIONS)
|
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)
|
23
|
+
|
24
|
+
opts = Config.process_options(options)
|
25
|
+
|
26
|
+
commonmark_parse(text, options: opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: Parses a CommonMark string into an HTML string.
|
30
|
+
#
|
31
|
+
# text - A {String} of text
|
32
|
+
# options - A {Hash} of render, parse, and extension options to transform the text.
|
33
|
+
# plugins - A {Hash} of additional plugins.
|
34
|
+
#
|
35
|
+
# Returns a {String} of converted HTML.
|
36
|
+
def to_html(text, options: Commonmarker::Config::OPTIONS, plugins: Commonmarker::Config::PLUGINS)
|
37
|
+
raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
|
38
|
+
raise TypeError, "text must be UTF-8 encoded; got #{text.encoding}!" unless text.encoding.name == "UTF-8"
|
39
|
+
raise TypeError, "options must be a Hash; got a #{options.class}!" unless options.is_a?(Hash)
|
40
|
+
|
41
|
+
opts = Config.process_options(options)
|
42
|
+
plugins = Config.process_plugins(plugins)
|
43
|
+
|
44
|
+
commonmark_to_html(text, options: opts, plugins: plugins)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: commonmarker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.1.0
|
5
|
+
platform: x86_64-linux-musl
|
6
|
+
authors:
|
7
|
+
- Garen Torikian
|
8
|
+
- Ashe Connor
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2025-02-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '13.0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '13.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake-compiler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.2'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.2'
|
42
|
+
description: A fast, safe, extensible parser for CommonMark. This wraps the comrak
|
43
|
+
Rust crate.
|
44
|
+
email:
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- LICENSE.txt
|
50
|
+
- README.md
|
51
|
+
- lib/commonmarker.rb
|
52
|
+
- lib/commonmarker/3.2/commonmarker.so
|
53
|
+
- lib/commonmarker/3.4/commonmarker.so
|
54
|
+
- lib/commonmarker/config.rb
|
55
|
+
- lib/commonmarker/constants.rb
|
56
|
+
- lib/commonmarker/extension.rb
|
57
|
+
- lib/commonmarker/node.rb
|
58
|
+
- lib/commonmarker/node/ast.rb
|
59
|
+
- lib/commonmarker/node/inspect.rb
|
60
|
+
- lib/commonmarker/renderer.rb
|
61
|
+
- lib/commonmarker/utils.rb
|
62
|
+
- lib/commonmarker/version.rb
|
63
|
+
homepage: https://github.com/gjtorikian/commonmarker
|
64
|
+
licenses:
|
65
|
+
- MIT
|
66
|
+
metadata:
|
67
|
+
allowed_push_host: https://rubygems.org
|
68
|
+
funding_uri: https://github.com/sponsors/gjtorikian/
|
69
|
+
source_code_uri: https://github.com/gjtorikian/commonmarker
|
70
|
+
rubygems_mfa_required: 'true'
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '3.2'
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.5.dev
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '3.4'
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 3.3.22
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.5.23
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: CommonMark parser and renderer. Written in Rust, wrapped in Ruby.
|
96
|
+
test_files: []
|