diff --git a/lib/markd/.github/workflows/linux-ci.yml b/lib/markd/.github/workflows/linux-ci.yml index 3d2c934b17ec..18cd80aae54d 100644 --- a/lib/markd/.github/workflows/linux-ci.yml +++ b/lib/markd/.github/workflows/linux-ci.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - crystal: [ '1.0.0', 'latest', 'nightly' ] + crystal: [ '1.0.0', '1.1.0', '1.2.0', 'latest', 'nightly' ] name: Crystal ${{ matrix.crystal }} tests steps: - uses: actions/checkout@master diff --git a/lib/markd/CHANGELOG.md b/lib/markd/CHANGELOG.md index dfc7a68abd11..e2d4626f0a9a 100644 --- a/lib/markd/CHANGELOG.md +++ b/lib/markd/CHANGELOG.md @@ -11,6 +11,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - GFM support +## [0.4.2] (2021-10-19) + +### Added + +- Enable Table of Content (TOC) #[41](https://github.com/icyleaf/markd/pull/41) thanks @[Nephos](https://github.com/Nephos). + +### Fixed + +- Fix byte slice negative #[43](https://github.com/icyleaf/markd/pull/43). +- Compatibility with Crystal 1.2. + +## [0.4.1] (2021-09-27) + +### Added + +- Refactor Options and change to a class #[36](https://github.com/icyleaf/markd/pull/36) thanks @[straight-shoota](https://github.com/straight-shoota). +- Add `lang` parameter to to `HTMLRenderer#code_block_body` #[38](https://github.com/icyleaf/markd/pull/38) thanks @[straight-shoota](https://github.com/straight-shoota). + ## [0.4.0] (2021-03-23) - Compatibility with Crystal 1.0. #[34](https://github.com/icyleaf/markd/pull/34) thanks @[bcardiff](https://github.com/bcardiff). @@ -53,7 +71,10 @@ No changelog. - [initial implementation](https://github.com/icyleaf/markd/milestone/1?closed=1) -[Unreleased]: https://github.com/icyleaf/markd/compare/v0.3.0...HEAD +[Unreleased]: https://github.com/icyleaf/markd/compare/v0.4.2...HEAD +[0.4.2]: https://github.com/icyleaf/halite/compare/v0.4.1...v0.4.2 +[0.4.1]: https://github.com/icyleaf/halite/compare/v0.4.0...v0.4.1 +[0.4.0]: https://github.com/icyleaf/halite/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/icyleaf/halite/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/icyleaf/halite/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/icyleaf/halite/compare/v0.1.2...v0.2.0 diff --git a/lib/markd/shard.yml b/lib/markd/shard.yml index 4f1aff60233f..005d2c74ac63 100644 --- a/lib/markd/shard.yml +++ b/lib/markd/shard.yml @@ -1,9 +1,9 @@ name: markd -version: 0.4.0 +version: 0.4.2 authors: - icyleaf -crystal: 1.0.0 +crystal: ">= 0.36.1, < 2.0.0" license: MIT diff --git a/lib/markd/src/markd/options.cr b/lib/markd/src/markd/options.cr index 8f57b910f074..7605a261e939 100644 --- a/lib/markd/src/markd/options.cr +++ b/lib/markd/src/markd/options.cr @@ -1,8 +1,41 @@ require "uri" module Markd - struct Options - property time, gfm, toc, smart, source_pos, safe, prettyprint + # Markdown rendering options. + class Options + property time, gfm, toc + + # If `true`: + # - straight quotes will be made curly + # - `--` will be changed to an en dash + # - `---` will be changed to an em dash + # - `...` will be changed to ellipses + property? smart : Bool + + @[Deprecated("Use `#smart?` instead.")] + getter smart + + # If `true`, source position information for block-level elements + # will be rendered in the `data-sourcepos` attribute (for HTML). + property? source_pos : Bool + + @[Deprecated("Use `#source_pos?` instead.")] + getter source_pos + + # If `true`, raw HTML will not be passed through to HTML output + # (it will be replaced by comments). + property? safe : Bool + + @[Deprecated("Use `#safe?` instead.")] + getter safe + + # If `true`, code tags generated by code blocks will have a + # prettyprint class added to them, to be used by + # [Google code-prettify](https://github.com/google/code-prettify). + property? prettyprint : Bool + + @[Deprecated("Use `#prettyprint?` instead.")] + getter prettyprint # If `base_url` is not `nil`, it is used to resolve URLs of relative # links. It act's like HTML's `` in the context diff --git a/lib/markd/src/markd/parsers/inline.cr b/lib/markd/src/markd/parsers/inline.cr index 92592b53dbd6..fb2f1d28ccac 100644 --- a/lib/markd/src/markd/parsers/inline.cr +++ b/lib/markd/src/markd/parsers/inline.cr @@ -43,7 +43,7 @@ module Markd::Parser when '*', '_' handle_delim(char, node) when '\'', '"' - @options.smart && handle_delim(char, node) + @options.smart? && handle_delim(char, node) when '[' open_bracket(node) when '!' @@ -226,7 +226,8 @@ module Markd::Parser elsif !opener.bracket_after # Empty or missing second label means to use the first label as the reference. # The reference must not contain a bracket. If we know there's a bracket, we don't even bother checking it. - ref_label = normalize_refernence(@text.byte_slice(opener.index, start_pos - opener.index)) + byte_count = start_pos - opener.index + ref_label = byte_count > 0 ? normalize_refernence(@text.byte_slice(opener.index, byte_count)) : nil end if label_size == 0 @@ -445,7 +446,7 @@ module Markd::Parser private def string(node : Node) if text = match_main - if @options.smart + if @options.smart? text = text.gsub(Rule::ELLIPSIS, '\u{2026}') .gsub(Rule::DASH) do |chars| en_count = em_count = 0 diff --git a/lib/markd/src/markd/renderers/html_renderer.cr b/lib/markd/src/markd/renderers/html_renderer.cr index c5f878dbe81a..334e0d2b5c42 100644 --- a/lib/markd/src/markd/renderers/html_renderer.cr +++ b/lib/markd/src/markd/renderers/html_renderer.cr @@ -12,7 +12,7 @@ module Markd if entering newline tag(tag_name, attrs(node)) - # toc(node) if @options.toc + toc(node) if @options.toc else tag(tag_name, end_tag: true) newline @@ -21,33 +21,46 @@ module Markd def code(node : Node, entering : Bool) tag("code") do - output(node.text) + code_body(node) end end + def code_body(node : Node) + output(node.text) + end + def code_block(node : Node, entering : Bool) languages = node.fence_language ? node.fence_language.split : nil code_tag_attrs = attrs(node) - pre_tag_attrs = if @options.prettyprint + pre_tag_attrs = if @options.prettyprint? {"class" => "prettyprint"} else nil end - if languages && languages.size > 0 && (lang = languages[0]) && !lang.empty? + lang = code_block_language(languages) + if lang code_tag_attrs ||= {} of String => String - code_tag_attrs["class"] = "language-#{escape(lang.strip)}" + code_tag_attrs["class"] = "language-#{escape(lang)}" end newline tag("pre", pre_tag_attrs) do tag("code", code_tag_attrs) do - output(node.text) + code_block_body(node, lang) end end newline end + def code_block_language(languages) + languages.try(&.first?).try(&.strip.presence) + end + + def code_block_body(node : Node, lang : String?) + output(node.text) + end + def thematic_break(node : Node, entering : Bool) newline tag("hr", attrs(node), self_closing: true) @@ -97,7 +110,7 @@ module Markd attrs = attrs(node) destination = node.data["destination"].as(String) - unless @options.safe && potentially_unsafe(destination) + unless @options.safe? && potentially_unsafe(destination) attrs ||= {} of String => String destination = resolve_uri(destination, node) attrs["href"] = escape(destination) @@ -128,7 +141,7 @@ module Markd if entering if @disable_tag == 0 destination = node.data["destination"].as(String) - if @options.safe && potentially_unsafe(destination) + if @options.safe? && potentially_unsafe(destination) literal(%(" : node.text + content = @options.safe? ? "" : node.text literal(content) newline end def html_inline(node : Node, entering : Bool) - content = @options.safe ? "" : node.text + content = @options.safe? ? "" : node.text literal(content) end @@ -222,14 +235,18 @@ module Markd private def toc(node : Node) return unless node.type.heading? - title = URI.encode(node.text) - - @output_io << %() + {% if Crystal::VERSION < "1.2.0" %} + title = URI.encode(node.first_child.text) + @output_io << %() + {% else %} + title = URI.encode_path(node.first_child.text) + @output_io << %() + {% end %} @last_output = ">" end private def attrs(node : Node) - if @options.source_pos && (pos = node.source_pos) + if @options.source_pos? && (pos = node.source_pos) {"data-source-pos" => "#{pos[0][0]}:#{pos[0][1]}-#{pos[1][0]}:#{pos[1][1]}"} else nil diff --git a/lib/markd/src/markd/version.cr b/lib/markd/src/markd/version.cr index 353bf563d86f..4bb13a7e84f9 100644 --- a/lib/markd/src/markd/version.cr +++ b/lib/markd/src/markd/version.cr @@ -1,3 +1,3 @@ module Markd - VERSION = "0.4.0" + VERSION = "0.4.2" end