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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +75 -0
  6. data/Rakefile +18 -0
  7. data/features/commonmarker.feature +97 -0
  8. data/features/support/env.rb +5 -0
  9. data/fixtures/markdown-app/config.rb +1 -0
  10. data/fixtures/markdown-app/source/autolink.html.markdown +5 -0
  11. data/fixtures/markdown-app/source/fenced_code_blocks.html.markdown +7 -0
  12. data/fixtures/markdown-app/source/filter_html.html.markdown +1 -0
  13. data/fixtures/markdown-app/source/footnote.html.markdown +3 -0
  14. data/fixtures/markdown-app/source/hard_wrap.html.markdown +2 -0
  15. data/fixtures/markdown-app/source/highlighted.html.markdown +1 -0
  16. data/fixtures/markdown-app/source/images/blank.gif +0 -0
  17. data/fixtures/markdown-app/source/img.html.markdown +1 -0
  18. data/fixtures/markdown-app/source/indented_code_blocks.html.markdown +5 -0
  19. data/fixtures/markdown-app/source/index.html.markdown +4 -0
  20. data/fixtures/markdown-app/source/lax_spacing.html.markdown +3 -0
  21. data/fixtures/markdown-app/source/link.html.markdown +1 -0
  22. data/fixtures/markdown-app/source/mailto.html.markdown +1 -0
  23. data/fixtures/markdown-app/source/no_intra_emphasis.html.markdown +5 -0
  24. data/fixtures/markdown-app/source/prettify.html.markdown +3 -0
  25. data/fixtures/markdown-app/source/quote.html.markdown +1 -0
  26. data/fixtures/markdown-app/source/safe_links.html.markdown +1 -0
  27. data/fixtures/markdown-app/source/smarty_pants.html.markdown +5 -0
  28. data/fixtures/markdown-app/source/space_after_headers.html.markdown +5 -0
  29. data/fixtures/markdown-app/source/strikethrough.html.markdown +5 -0
  30. data/fixtures/markdown-app/source/superscript.html.markdown +5 -0
  31. data/fixtures/markdown-app/source/tables.html.markdown +8 -0
  32. data/fixtures/markdown-app/source/underline.html.markdown +1 -0
  33. data/fixtures/markdown-app/source/with_toc_data.html.markdown +3 -0
  34. data/lib/middleman-commonmarker/commonmarker_template.rb +117 -0
  35. data/lib/middleman-commonmarker/extension.rb +31 -0
  36. data/lib/middleman-commonmarker/version.rb +7 -0
  37. data/lib/middleman-commonmarker.rb +9 -0
  38. data/sig/middleman-commonmarker/commonmarker_template.rbs +23 -0
  39. data/sig/middleman-commonmarker/extension.rbs +7 -0
  40. data/sig/middleman-commonmarker/version.rbs +5 -0
  41. data/test/commonmarker_template_test.rb +56 -0
  42. data/test/test_helper.rb +5 -0
  43. 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
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2026-05-27
4
+
5
+ - Initial release
@@ -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
+ ![image](blank.gif)
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,5 @@
1
+ PROJECT_ROOT_PATH = File.dirname(__FILE__, 3)
2
+ ENV["TEST"] = "true"
3
+ require "middleman-core"
4
+ require "middleman-core/step_definitions"
5
+ require File.join(PROJECT_ROOT_PATH, "lib", "middleman-commonmarker")
@@ -0,0 +1 @@
1
+ set :markdown, smartypants: true
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ http://example.com
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ ~~~~~~~~~~~~~~~~~~~~~
6
+ a one-line code block
7
+ ~~~~~~~~~~~~~~~~~~~~~
@@ -0,0 +1 @@
1
+ I <em>shouldn't</em> be emphasised
@@ -0,0 +1,3 @@
1
+ This is a footnote.[^1]
2
+
3
+ [^1]: It provides additional information.
@@ -0,0 +1,2 @@
1
+ hard
2
+ wrap
@@ -0,0 +1 @@
1
+ this is ==highlighted==
@@ -0,0 +1 @@
1
+ ![dust mite](http://dust.mite/image.png) <img src="image.png" />
@@ -0,0 +1,5 @@
1
+ Hello
2
+
3
+ Something that would be flagged as code
4
+
5
+ World
@@ -0,0 +1,4 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+ Hello World
@@ -0,0 +1,3 @@
1
+ hello
2
+ <div>world</div>
3
+ again
@@ -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,5 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ foo_bar_baz
@@ -0,0 +1,3 @@
1
+ ```
2
+ code block
3
+ ```
@@ -0,0 +1 @@
1
+ this is "quote"
@@ -0,0 +1 @@
1
+ [IRC](irc://chat.freenode.org/#freenode)
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ "Hello"
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ #this is my header
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ ~~Nope~~
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ this is the 2^(nd) time
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: false
3
+ ---
4
+
5
+ First Header | Second Header
6
+ ------------- | -------------
7
+ Content Cell | Content Cell
8
+ Content Cell | Content Cell
@@ -0,0 +1 @@
1
+ hello _underlined_ text
@@ -0,0 +1,3 @@
1
+ # First Header
2
+
3
+ ## Second Header
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Middleman
4
+ module Commonmarker
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "middleman-core"
4
+ require "middleman-commonmarker/version"
5
+
6
+ Middleman::Extensions.register :commonmarker do
7
+ require "middleman-commonmarker/extension"
8
+ Middleman::CommonmarkerExtension
9
+ 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,7 @@
1
+ module Middleman
2
+ class CommonmarkerExtension < ::Middleman::Extension
3
+ def initialize: (untyped app, ?Hash[Symbol, untyped] options_hash) ?{ (untyped, untyped) -> void } -> void
4
+
5
+ def after_configuration: () -> void
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Middleman
2
+ module Commonmarker
3
+ VERSION: String
4
+ end
5
+ 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("![an *alt* text](x.gif)"))
42
+ end
43
+
44
+ def test_extract_text_returns_empty_string_for_empty_alt
45
+ assert_equal "", build.send(:extract_text, image_node("![](x.gif)"))
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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "minitest/autorun"
4
+ require "middleman-commonmarker"
5
+ require "middleman-commonmarker/commonmarker_template"
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: []