middleman-commonmarker 0.1.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 +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +75 -0
- data/Rakefile +18 -0
- data/features/commonmarker.feature +97 -0
- data/features/support/env.rb +5 -0
- data/fixtures/markdown-app/config.rb +1 -0
- data/fixtures/markdown-app/source/autolink.html.markdown +5 -0
- data/fixtures/markdown-app/source/fenced_code_blocks.html.markdown +7 -0
- data/fixtures/markdown-app/source/filter_html.html.markdown +1 -0
- data/fixtures/markdown-app/source/footnote.html.markdown +3 -0
- data/fixtures/markdown-app/source/hard_wrap.html.markdown +2 -0
- data/fixtures/markdown-app/source/highlighted.html.markdown +1 -0
- data/fixtures/markdown-app/source/images/blank.gif +0 -0
- data/fixtures/markdown-app/source/img.html.markdown +1 -0
- data/fixtures/markdown-app/source/indented_code_blocks.html.markdown +5 -0
- data/fixtures/markdown-app/source/index.html.markdown +4 -0
- data/fixtures/markdown-app/source/lax_spacing.html.markdown +3 -0
- data/fixtures/markdown-app/source/link.html.markdown +1 -0
- data/fixtures/markdown-app/source/mailto.html.markdown +1 -0
- data/fixtures/markdown-app/source/no_intra_emphasis.html.markdown +5 -0
- data/fixtures/markdown-app/source/prettify.html.markdown +3 -0
- data/fixtures/markdown-app/source/quote.html.markdown +1 -0
- data/fixtures/markdown-app/source/safe_links.html.markdown +1 -0
- data/fixtures/markdown-app/source/smarty_pants.html.markdown +5 -0
- data/fixtures/markdown-app/source/space_after_headers.html.markdown +5 -0
- data/fixtures/markdown-app/source/strikethrough.html.markdown +5 -0
- data/fixtures/markdown-app/source/superscript.html.markdown +5 -0
- data/fixtures/markdown-app/source/tables.html.markdown +8 -0
- data/fixtures/markdown-app/source/underline.html.markdown +1 -0
- data/fixtures/markdown-app/source/with_toc_data.html.markdown +3 -0
- data/lib/middleman-commonmarker/commonmarker_template.rb +117 -0
- data/lib/middleman-commonmarker/extension.rb +31 -0
- data/lib/middleman-commonmarker/version.rb +7 -0
- data/lib/middleman-commonmarker.rb +9 -0
- data/sig/middleman-commonmarker/commonmarker_template.rbs +23 -0
- data/sig/middleman-commonmarker/extension.rbs +7 -0
- data/sig/middleman-commonmarker/version.rbs +5 -0
- data/test/commonmarker_template_test.rb +56 -0
- data/test/test_helper.rb +5 -0
- metadata +115 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2843575c04f2b516147d5aaaa62789482ead5e3e65950ac268b824759883c1bf
|
|
4
|
+
data.tar.gz: 9e90c64fba5895575d957c0d9ad174254f7242d06e648405f7a84b01e9e7703c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 18e343279365e8a11a2ace792f8441cf5f4f8753c40d4a8772389117937346428d8461474c77888cca55dc117e95277f62e64d54dc0bca77aaa735bf999cf49f
|
|
7
|
+
data.tar.gz: 60024dfa0cc18d349f5b93f8d2a1ddaa2b60e6cba42fa83c53b710196d6268db4629ef24360d71d2ff511f876804c1e80f12b4066a026e90bd1ba0f9e4600672
|
data/CHANGELOG.md
ADDED
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
"middleman-commonmarker" follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
|
|
4
|
+
|
|
5
|
+
* Participants will be tolerant of opposing views.
|
|
6
|
+
* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
|
|
7
|
+
* When interpreting the words and actions of others, participants should always assume good intentions.
|
|
8
|
+
* Behaviour which can be reasonably considered harassment will not be tolerated.
|
|
9
|
+
|
|
10
|
+
If you have any concerns about behaviour within this project, please contact us at ["yusuke1994525@gmail.com"](mailto:"yusuke1994525@gmail.com").
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yusuke Nakamura
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Middleman::Commonmarker
|
|
2
|
+
|
|
3
|
+
A [Middleman](https://middlemanapp.com/) extension that renders Markdown with [commonmarker](https://github.com/gjtorikian/commonmarker) (the Rust/comrak based CommonMark renderer).
|
|
4
|
+
|
|
5
|
+
It walks the parsed AST and rewrites image and link nodes through Middleman's `image_tag` and `url_for` helpers, so you get sitemap-aware links and `automatic_image_sizes` support — on par with the Redcarpet engine.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add the gem to your Middleman project's `Gemfile`:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem "middleman-commonmarker"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then run `bundle install`.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
Activate the extension in `config.rb`:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
activate :commonmarker
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
That's it — Markdown files (`.markdown`, `.md`, `.mkd`, …) are now rendered with commonmarker.
|
|
26
|
+
|
|
27
|
+
> **Important:** Enable the engine with `activate :commonmarker`, **not** with
|
|
28
|
+
> `set :markdown_engine, :commonmarker`. On a released middleman-core the latter
|
|
29
|
+
> makes the generic markdown branch look for `Tilt::CommonmarkerTemplate` and
|
|
30
|
+
> raise a `NameError`. Always use `activate :commonmarker`.
|
|
31
|
+
|
|
32
|
+
### Options
|
|
33
|
+
|
|
34
|
+
Pass commonmarker options either through `set :markdown` (the usual Markdown engine convention) or through the extension's `options:` hash:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
# via set :markdown
|
|
38
|
+
activate :commonmarker
|
|
39
|
+
set :markdown, table: true, strikethrough: true, smartypants: true
|
|
40
|
+
|
|
41
|
+
# via activate
|
|
42
|
+
activate :commonmarker, options: { table: true, strikethrough: true }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Note that flat keys on `activate` (e.g. `activate :commonmarker, table: true`) are **not** supported — Middleman validates extension options against declared names, so commonmarker options must be nested under `options:`. Options given to `activate` take precedence over `set :markdown` on conflicting keys.
|
|
46
|
+
|
|
47
|
+
These flat options are mapped onto commonmarker's `parse` / `render` / `extension` option groups (and `smartypants` maps to `parse.smart`).
|
|
48
|
+
|
|
49
|
+
### Raw HTML is enabled during rendering
|
|
50
|
+
|
|
51
|
+
To emit the `<img>` HTML produced by `image_tag`, the renderer forces commonmarker's `unsafe: true` during transformation.
|
|
52
|
+
As a result, raw HTML in your Markdown is passed through (consistent with Redcarpet's default, where `filter_html` is opt-in).
|
|
53
|
+
|
|
54
|
+
## Scope
|
|
55
|
+
|
|
56
|
+
This extension covers helper integration (`image_tag` / `url_for`), `automatic_image_sizes`, and commonmarker's native parse/render/extension options (`table`, `strikethrough`, `autolink`, `smartypants`, `tasklist`, …).
|
|
57
|
+
Redcarpet-specific options such as `no_images`, `no_links`, `link_attributes`, and `filter_html` are out of scope.
|
|
58
|
+
|
|
59
|
+
## Development
|
|
60
|
+
|
|
61
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then run
|
|
62
|
+
`bundle exec rake` to run StandardRB, the minitest unit tests, and the cucumber
|
|
63
|
+
features. You can also run `bin/console` for an interactive prompt.
|
|
64
|
+
|
|
65
|
+
## Contributing
|
|
66
|
+
|
|
67
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/unasuke/middleman-commonmarker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/unasuke/middleman-commonmarker/blob/main/CODE_OF_CONDUCT.md).
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
72
|
+
|
|
73
|
+
## Code of Conduct
|
|
74
|
+
|
|
75
|
+
Everyone interacting in the Middleman::Commonmarker project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/unasuke/middleman-commonmarker/blob/main/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "standard/rake"
|
|
5
|
+
require "rake/testtask"
|
|
6
|
+
require "cucumber/rake/task"
|
|
7
|
+
|
|
8
|
+
Rake::TestTask.new(:test) do |t|
|
|
9
|
+
t.libs << "test"
|
|
10
|
+
t.libs << "lib"
|
|
11
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Cucumber::Rake::Task.new(:cucumber) do |t|
|
|
15
|
+
t.cucumber_opts = "--require features --color --strict --format #{ENV["CUCUMBER_FORMAT"] || "pretty"}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
task default: %i[standard test cucumber]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Feature: Markdown (Commonmarker) support
|
|
2
|
+
In order to render Markdown with commonmarker via the middleman-commonmarker extension
|
|
3
|
+
|
|
4
|
+
Scenario: Commonmarker basic rendering
|
|
5
|
+
Given a fixture app "markdown-app"
|
|
6
|
+
And a file named "config.rb" with:
|
|
7
|
+
"""
|
|
8
|
+
activate :commonmarker
|
|
9
|
+
"""
|
|
10
|
+
Given the Server is running at "markdown-app"
|
|
11
|
+
When I go to "/index.html"
|
|
12
|
+
Then I should see "<p>"
|
|
13
|
+
|
|
14
|
+
Scenario: Commonmarker smartypants extension
|
|
15
|
+
Given a fixture app "markdown-app"
|
|
16
|
+
And a file named "config.rb" with:
|
|
17
|
+
"""
|
|
18
|
+
activate :commonmarker
|
|
19
|
+
set :markdown, smartypants: true
|
|
20
|
+
"""
|
|
21
|
+
Given the Server is running at "markdown-app"
|
|
22
|
+
When I go to "/smarty_pants.html"
|
|
23
|
+
Then I should see "“Hello”"
|
|
24
|
+
|
|
25
|
+
Scenario: Commonmarker fenced code blocks
|
|
26
|
+
Given a fixture app "markdown-app"
|
|
27
|
+
And a file named "config.rb" with:
|
|
28
|
+
"""
|
|
29
|
+
activate :commonmarker
|
|
30
|
+
"""
|
|
31
|
+
Given the Server is running at "markdown-app"
|
|
32
|
+
When I go to "/fenced_code_blocks.html"
|
|
33
|
+
Then I should see "<code>"
|
|
34
|
+
|
|
35
|
+
Scenario: Commonmarker table extension
|
|
36
|
+
Given a fixture app "markdown-app"
|
|
37
|
+
And a file named "config.rb" with:
|
|
38
|
+
"""
|
|
39
|
+
activate :commonmarker
|
|
40
|
+
set :markdown, table: true
|
|
41
|
+
"""
|
|
42
|
+
Given the Server is running at "markdown-app"
|
|
43
|
+
When I go to "/tables.html"
|
|
44
|
+
Then I should see "<table>"
|
|
45
|
+
|
|
46
|
+
Scenario: Commonmarker strikethrough extension
|
|
47
|
+
Given a fixture app "markdown-app"
|
|
48
|
+
And a file named "config.rb" with:
|
|
49
|
+
"""
|
|
50
|
+
activate :commonmarker
|
|
51
|
+
set :markdown, strikethrough: true
|
|
52
|
+
"""
|
|
53
|
+
Given the Server is running at "markdown-app"
|
|
54
|
+
When I go to "/strikethrough.html"
|
|
55
|
+
Then I should see "<del>"
|
|
56
|
+
|
|
57
|
+
Scenario: Commonmarker autolink extension
|
|
58
|
+
Given a fixture app "markdown-app"
|
|
59
|
+
And a file named "config.rb" with:
|
|
60
|
+
"""
|
|
61
|
+
activate :commonmarker
|
|
62
|
+
set :markdown, autolink: true
|
|
63
|
+
"""
|
|
64
|
+
Given the Server is running at "markdown-app"
|
|
65
|
+
When I go to "/autolink.html"
|
|
66
|
+
Then I should see "<a href"
|
|
67
|
+
|
|
68
|
+
Scenario: Commonmarker passes options through activate
|
|
69
|
+
Given a fixture app "markdown-app"
|
|
70
|
+
And a file named "config.rb" with:
|
|
71
|
+
"""
|
|
72
|
+
activate :commonmarker, options: { table: true }
|
|
73
|
+
"""
|
|
74
|
+
Given the Server is running at "markdown-app"
|
|
75
|
+
When I go to "/tables.html"
|
|
76
|
+
Then I should see "<table>"
|
|
77
|
+
|
|
78
|
+
Scenario: Commonmarker uses our link_to and image_tag helpers
|
|
79
|
+
Given a fixture app "markdown-app"
|
|
80
|
+
And a file named "config.rb" with:
|
|
81
|
+
"""
|
|
82
|
+
activate :commonmarker
|
|
83
|
+
activate :automatic_image_sizes
|
|
84
|
+
activate :directory_indexes
|
|
85
|
+
"""
|
|
86
|
+
And a file named "source/link_and_image.html.markdown" with:
|
|
87
|
+
"""
|
|
88
|
+
[A link](/smarty_pants.html)
|
|
89
|
+
|
|
90
|
+

|
|
91
|
+
"""
|
|
92
|
+
Given the Server is running at "markdown-app"
|
|
93
|
+
When I go to "/link_and_image/"
|
|
94
|
+
Then I should see "/smarty_pants/"
|
|
95
|
+
Then I should see 'width="1"'
|
|
96
|
+
And I should see 'height="1"'
|
|
97
|
+
And I should see 'src="/images/blank.gif"'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
set :markdown, smartypants: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I <em>shouldn't</em> be emphasised
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
this is ==highlighted==
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
 <img src="image.png" />
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[This link](http://example.net/) <a href="links.html">links</a>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# ✉ [Mail](mailto:mail@mail.com)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
this is "quote"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[IRC](irc://chat.freenode.org/#freenode)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hello _underlined_ text
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "commonmarker"
|
|
4
|
+
require "active_support/core_ext/module/attribute_accessors"
|
|
5
|
+
|
|
6
|
+
module Middleman
|
|
7
|
+
module Renderers
|
|
8
|
+
# Tilt template that renders Markdown with commonmarker, walking the AST to
|
|
9
|
+
# transform image and link nodes through Middleman's helpers.
|
|
10
|
+
class CommonmarkerTemplate < ::Tilt::Template
|
|
11
|
+
self.default_mime_type = "text/html"
|
|
12
|
+
cattr_accessor :scope
|
|
13
|
+
|
|
14
|
+
DEFAULT_PARSE_OPTIONS = {smart: false, default_info_string: nil}.freeze
|
|
15
|
+
DEFAULT_RENDER_OPTIONS = {hardbreaks: false, github_pre_lang: false, width: 80,
|
|
16
|
+
unsafe: false, escape: false, sourcepos: false}.freeze
|
|
17
|
+
DEFAULT_EXTENSION_OPTIONS = {strikethrough: false, tagfilter: false, table: false,
|
|
18
|
+
autolink: false, tasklist: false, superscript: false,
|
|
19
|
+
header_ids: nil, footnotes: false, description_lists: false,
|
|
20
|
+
front_matter_delimiter: nil, shortcodes: false}.freeze
|
|
21
|
+
|
|
22
|
+
def prepare
|
|
23
|
+
@context = options.delete(:context)
|
|
24
|
+
@commonmarker_options = build_commonmarker_options
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def evaluate(scope, _locals, &_block)
|
|
28
|
+
self.class.scope = @context || scope
|
|
29
|
+
doc = ::Commonmarker.parse(data, options: @commonmarker_options)
|
|
30
|
+
|
|
31
|
+
if self.class.scope
|
|
32
|
+
doc.walk do |node|
|
|
33
|
+
case node.type
|
|
34
|
+
when :image then transform_image_node(node)
|
|
35
|
+
when :link then transform_link_node(node)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
# Force unsafe so the injected raw <img> HTML is emitted.
|
|
39
|
+
return doc.to_html(options: render_options_with_unsafe)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
doc.to_html(options: @commonmarker_options)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Replace the image node with the HTML produced by image_tag (an
|
|
48
|
+
# html_inline/html_block node). When html_node_from returns nil (no such
|
|
49
|
+
# node), skip the replacement and keep the original image node, falling
|
|
50
|
+
# back to commonmarker's default <img> output.
|
|
51
|
+
def transform_image_node(node)
|
|
52
|
+
alt = extract_text(node)
|
|
53
|
+
html = scope.image_tag(node.url, alt: alt, title: node.title)
|
|
54
|
+
replacement = html_node_from(html)
|
|
55
|
+
node.replace(replacement) if replacement
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Only rewrite the URL of a link (the inner inline elements are kept;
|
|
59
|
+
# commonmarker preserves the title).
|
|
60
|
+
def transform_link_node(node)
|
|
61
|
+
return if node.url.start_with?("mailto:")
|
|
62
|
+
|
|
63
|
+
node.url = scope.url_for(node.url)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Concatenate the descendant text nodes to build the alt text.
|
|
67
|
+
def extract_text(node)
|
|
68
|
+
text = +""
|
|
69
|
+
node.walk { |n| text << n.string_content if n.type == :text }
|
|
70
|
+
text
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Turn the HTML string returned by image_tag into a Commonmarker node.
|
|
74
|
+
def html_node_from(html)
|
|
75
|
+
parsed = ::Commonmarker.parse(html)
|
|
76
|
+
parsed.walk { |n| return n if %i[html_inline html_block].include?(n.type) }
|
|
77
|
+
nil
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def render_options_with_unsafe
|
|
81
|
+
@commonmarker_options.merge(
|
|
82
|
+
render: @commonmarker_options[:render].merge(unsafe: true)
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Distribute the flat `set :markdown, ...` options into the
|
|
87
|
+
# parse/render/extension nested structure, mapping `smartypants` to
|
|
88
|
+
# parse.smart.
|
|
89
|
+
def build_commonmarker_options
|
|
90
|
+
opts = {
|
|
91
|
+
parse: DEFAULT_PARSE_OPTIONS.dup,
|
|
92
|
+
render: DEFAULT_RENDER_OPTIONS.dup,
|
|
93
|
+
extension: DEFAULT_EXTENSION_OPTIONS.dup
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# smartypants maps to commonmarker's parse.smart.
|
|
97
|
+
opts[:parse][:smart] = true if options.delete(:smartypants)
|
|
98
|
+
|
|
99
|
+
# Distribute flat options into the nested structure.
|
|
100
|
+
options.each do |key, value|
|
|
101
|
+
key_sym = key.to_sym
|
|
102
|
+
if DEFAULT_PARSE_OPTIONS.key?(key_sym)
|
|
103
|
+
opts[:parse][key_sym] = value
|
|
104
|
+
elsif DEFAULT_RENDER_OPTIONS.key?(key_sym)
|
|
105
|
+
opts[:render][key_sym] = value
|
|
106
|
+
elsif DEFAULT_EXTENSION_OPTIONS.key?(key_sym)
|
|
107
|
+
opts[:extension][key_sym] = value
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
opts
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
::Tilt.register CommonmarkerTemplate, "markdown", "mkd", "md"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "middleman-core"
|
|
4
|
+
|
|
5
|
+
module Middleman
|
|
6
|
+
class CommonmarkerExtension < ::Middleman::Extension
|
|
7
|
+
# Options forwarded to commonmarker. Accepts the same flat keys as
|
|
8
|
+
# `set :markdown` (e.g. table: true) nested in a Hash, and merges them into
|
|
9
|
+
# the `set :markdown` config (app.config[:markdown]) in after_configuration.
|
|
10
|
+
option :options, {}, "Options forwarded to commonmarker (merged into `set :markdown`)"
|
|
11
|
+
|
|
12
|
+
def initialize(app, options_hash = {}, &block)
|
|
13
|
+
super
|
|
14
|
+
require "commonmarker"
|
|
15
|
+
require "middleman-commonmarker/commonmarker_template"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Runs after core's :markdown_renderer (before_configuration), so this
|
|
19
|
+
# Tilt.prefer overrides the default Kramdown engine.
|
|
20
|
+
# app.config is still writable here (it is not finalized, since core itself
|
|
21
|
+
# writes cli_options after after_configuration).
|
|
22
|
+
def after_configuration
|
|
23
|
+
unless options.options.empty?
|
|
24
|
+
app.config[:markdown] = (app.config[:markdown] || {}).merge(options.options)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
exts = %w[markdown mdown md mkd mkdn]
|
|
28
|
+
::Tilt.prefer(::Middleman::Renderers::CommonmarkerTemplate, *exts)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Middleman
|
|
2
|
+
module Renderers
|
|
3
|
+
class CommonmarkerTemplate < ::Tilt::Template
|
|
4
|
+
DEFAULT_PARSE_OPTIONS: Hash[Symbol, untyped]
|
|
5
|
+
DEFAULT_RENDER_OPTIONS: Hash[Symbol, untyped]
|
|
6
|
+
DEFAULT_EXTENSION_OPTIONS: Hash[Symbol, untyped]
|
|
7
|
+
|
|
8
|
+
attr_accessor self.scope: untyped
|
|
9
|
+
|
|
10
|
+
def prepare: () -> void
|
|
11
|
+
def evaluate: (untyped scope, untyped locals) ?{ () -> void } -> String
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def transform_image_node: (untyped node) -> void
|
|
16
|
+
def transform_link_node: (untyped node) -> void
|
|
17
|
+
def extract_text: (untyped node) -> String
|
|
18
|
+
def html_node_from: (String html) -> untyped
|
|
19
|
+
def render_options_with_unsafe: () -> Hash[Symbol, untyped]
|
|
20
|
+
def build_commonmarker_options: () -> Hash[Symbol, untyped]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class CommonmarkerTemplateTest < Minitest::Test
|
|
6
|
+
# Build a template instance; prepare runs on init and computes
|
|
7
|
+
# @commonmarker_options from the given options.
|
|
8
|
+
def build(opts = {})
|
|
9
|
+
Middleman::Renderers::CommonmarkerTemplate.new(nil, 1, opts) { "" }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def options_for(opts)
|
|
13
|
+
build(opts).instance_variable_get(:@commonmarker_options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def image_node(markdown)
|
|
17
|
+
node = Commonmarker.parse(markdown)
|
|
18
|
+
found = nil
|
|
19
|
+
node.walk { |n| found = n if n.type == :image }
|
|
20
|
+
found
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_build_options_distributes_into_nested_structure
|
|
24
|
+
opts = options_for(table: true, hardbreaks: true)
|
|
25
|
+
assert_equal true, opts[:extension][:table]
|
|
26
|
+
assert_equal true, opts[:render][:hardbreaks]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_smartypants_maps_to_parse_smart
|
|
30
|
+
assert_equal true, options_for(smartypants: true)[:parse][:smart]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_unknown_keys_are_ignored
|
|
34
|
+
opts = options_for(unknown_key: "x")
|
|
35
|
+
refute opts[:parse].key?(:unknown_key)
|
|
36
|
+
refute opts[:render].key?(:unknown_key)
|
|
37
|
+
refute opts[:extension].key?(:unknown_key)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_extract_text_concatenates_descendant_text
|
|
41
|
+
assert_equal "an alt text", build.send(:extract_text, image_node(""))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_extract_text_returns_empty_string_for_empty_alt
|
|
45
|
+
assert_equal "", build.send(:extract_text, image_node(""))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def test_html_node_from_returns_an_html_node
|
|
49
|
+
node = build.send(:html_node_from, %(<img src="/x.gif" />))
|
|
50
|
+
assert_includes %i[html_inline html_block], node.type
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_html_node_from_returns_nil_when_no_html_present
|
|
54
|
+
assert_nil build.send(:html_node_from, "just plain text")
|
|
55
|
+
end
|
|
56
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: middleman-commonmarker
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Yusuke Nakamura
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: middleman-core
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: commonmarker
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
description: A Middleman extension that renders Markdown with commonmarker, walking
|
|
41
|
+
the AST to integrate Middleman's image_tag and url_for helpers.
|
|
42
|
+
email:
|
|
43
|
+
- yusuke1994525@gmail.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- CHANGELOG.md
|
|
49
|
+
- CODE_OF_CONDUCT.md
|
|
50
|
+
- LICENSE.txt
|
|
51
|
+
- README.md
|
|
52
|
+
- Rakefile
|
|
53
|
+
- features/commonmarker.feature
|
|
54
|
+
- features/support/env.rb
|
|
55
|
+
- fixtures/markdown-app/config.rb
|
|
56
|
+
- fixtures/markdown-app/source/autolink.html.markdown
|
|
57
|
+
- fixtures/markdown-app/source/fenced_code_blocks.html.markdown
|
|
58
|
+
- fixtures/markdown-app/source/filter_html.html.markdown
|
|
59
|
+
- fixtures/markdown-app/source/footnote.html.markdown
|
|
60
|
+
- fixtures/markdown-app/source/hard_wrap.html.markdown
|
|
61
|
+
- fixtures/markdown-app/source/highlighted.html.markdown
|
|
62
|
+
- fixtures/markdown-app/source/images/blank.gif
|
|
63
|
+
- fixtures/markdown-app/source/img.html.markdown
|
|
64
|
+
- fixtures/markdown-app/source/indented_code_blocks.html.markdown
|
|
65
|
+
- fixtures/markdown-app/source/index.html.markdown
|
|
66
|
+
- fixtures/markdown-app/source/lax_spacing.html.markdown
|
|
67
|
+
- fixtures/markdown-app/source/link.html.markdown
|
|
68
|
+
- fixtures/markdown-app/source/mailto.html.markdown
|
|
69
|
+
- fixtures/markdown-app/source/no_intra_emphasis.html.markdown
|
|
70
|
+
- fixtures/markdown-app/source/prettify.html.markdown
|
|
71
|
+
- fixtures/markdown-app/source/quote.html.markdown
|
|
72
|
+
- fixtures/markdown-app/source/safe_links.html.markdown
|
|
73
|
+
- fixtures/markdown-app/source/smarty_pants.html.markdown
|
|
74
|
+
- fixtures/markdown-app/source/space_after_headers.html.markdown
|
|
75
|
+
- fixtures/markdown-app/source/strikethrough.html.markdown
|
|
76
|
+
- fixtures/markdown-app/source/superscript.html.markdown
|
|
77
|
+
- fixtures/markdown-app/source/tables.html.markdown
|
|
78
|
+
- fixtures/markdown-app/source/underline.html.markdown
|
|
79
|
+
- fixtures/markdown-app/source/with_toc_data.html.markdown
|
|
80
|
+
- lib/middleman-commonmarker.rb
|
|
81
|
+
- lib/middleman-commonmarker/commonmarker_template.rb
|
|
82
|
+
- lib/middleman-commonmarker/extension.rb
|
|
83
|
+
- lib/middleman-commonmarker/version.rb
|
|
84
|
+
- sig/middleman-commonmarker/commonmarker_template.rbs
|
|
85
|
+
- sig/middleman-commonmarker/extension.rbs
|
|
86
|
+
- sig/middleman-commonmarker/version.rbs
|
|
87
|
+
- test/commonmarker_template_test.rb
|
|
88
|
+
- test/test_helper.rb
|
|
89
|
+
homepage: https://github.com/unasuke/middleman-commonmarker
|
|
90
|
+
licenses:
|
|
91
|
+
- MIT
|
|
92
|
+
metadata:
|
|
93
|
+
allowed_push_host: https://rubygems.org
|
|
94
|
+
homepage_uri: https://github.com/unasuke/middleman-commonmarker
|
|
95
|
+
source_code_uri: https://github.com/unasuke/middleman-commonmarker
|
|
96
|
+
changelog_uri: https://github.com/unasuke/middleman-commonmarker/blob/main/CHANGELOG.md
|
|
97
|
+
rubygems_mfa_required: 'true'
|
|
98
|
+
rdoc_options: []
|
|
99
|
+
require_paths:
|
|
100
|
+
- lib
|
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
102
|
+
requirements:
|
|
103
|
+
- - ">="
|
|
104
|
+
- !ruby/object:Gem::Version
|
|
105
|
+
version: 3.2.0
|
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
requirements: []
|
|
112
|
+
rubygems_version: 4.0.10
|
|
113
|
+
specification_version: 4
|
|
114
|
+
summary: Commonmarker (CommonMark) markdown engine extension for Middleman
|
|
115
|
+
test_files: []
|