protos-markdown 1.0.0 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d484c25c78ff88494568a3342fb83f0ccedbe30f2d1b6f29d92f9d9e56ba49d9
4
- data.tar.gz: 8ad09da4197ecdcab8a260a6140a727742b65bde66f22c25796187d74dd8e11a
3
+ metadata.gz: 149154ed4ed5d1bff8bcf411e6e8cae01b35f2103586420154bd6180096299d0
4
+ data.tar.gz: 7ec3a0c2fa97be4d83d5adcea88726c59a94b136ee13b2601ef09e3d4f05ff2d
5
5
  SHA512:
6
- metadata.gz: fb088a0c93b8ffccffa81e60e256d7028bc569993dd53f8329867a354e7f594901f3d6134e451335851b13d4f70436aaf03f552e6f6ba84ebd8df8d91ca82f60
7
- data.tar.gz: 15989f1b3d75e06983af2be29f28ce92f07224f315c55ba87a310d04bf2da3f0c5618302235df1ac7670b0f83f66838d44e36bfbb8961cbeada93b5144a7e2dd
6
+ metadata.gz: 8c690286a4117d42ec8cc7e65406a16c2bb53a2b27a91a7b00526b6dc2adf13dc9fd26eaf001f1a652e159725cdf5bd6703f403e07fd9c4654fc5dc20272d4fd
7
+ data.tar.gz: a62bf4a662a89ed16e714b824df65e2f12874f62e73a3b7b09c29efdc7eac8afb89d9950d699795886bbe1bacd175cffd339ed7c3c93cde4893914e7bff8b644
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## 1.2.0 - 2025-12-25
4
+
5
+ - Adds handling inline html elements
6
+ - Adds handling more nodes for markdown tables
7
+ - Adds handling inline html blocks
8
+
9
+ ## [1.1.0] - 2024-05-28
10
+
11
+ - Changes from `markly` to `commonmarker` which has better support
12
+ - Adds IDs to headings by default
13
+ - Adds ability to override common marker options with `markdown_options`
14
+
3
15
  ## [0.1.1] - 2024-08-14
4
16
 
5
17
  - Adds `rouge` to gem dependencies
data/README.md CHANGED
@@ -22,8 +22,8 @@ using the standard protos conventions:
22
22
 
23
23
  ```ruby
24
24
  class Markdown < Protos::Markdown
25
- def h1 = super(class: css[:title])
26
- def ul = super(class: "ml-4 pt-2")
25
+ def h1(**) = super(class: css[:title], **)
26
+ def ul(**) = super(class: "ml-4 pt-2", **)
27
27
 
28
28
  private
29
29
 
@@ -52,7 +52,7 @@ output = Markdown.new(content).call
52
52
  Which outputs the following html:
53
53
 
54
54
  ```html
55
- <h1 class="font-bold text-xl">Hello World</h1>
55
+ <h1 class="font-bold text-xl" id="hello-world">Hello World</h1>
56
56
  <ul class="ml-4 pt-2">
57
57
  <li>A</li>
58
58
  <li>B</li>
@@ -17,14 +17,15 @@ module Protos
17
17
  end
18
18
  end
19
19
 
20
- def self.parse(content, **kwargs)
20
+ def self.parse(content, markdown_options: {})
21
21
  options = {
22
- flags: Markly::GITHUB_PRE_LANG,
23
- extensions: [:table]
24
- }.merge(kwargs)
22
+ render: { gfm_quirks: true },
23
+ extension: { table: true },
24
+ **markdown_options
25
+ }
25
26
 
26
- Markly
27
- .parse(content, **options)
27
+ Commonmarker
28
+ .parse(content, options:)
28
29
  .then { |node| new(Node.new(node)) }
29
30
  end
30
31
 
@@ -3,12 +3,17 @@
3
3
  module Protos
4
4
  class Markdown
5
5
  class Table < Protos::Table
6
- option :inside_header, default: -> { false }, reader: false
6
+ option :inside_header, default: -> { true }, reader: false
7
+ option :sanitize, default: -> { true }
7
8
 
8
9
  def visit_table(node)
9
10
  visit_children(node)
10
11
  end
11
12
 
13
+ def visit_image(node)
14
+ img(src: node.url, alt: node.first&.string_content)
15
+ end
16
+
12
17
  def visit_table_header(node)
13
18
  @inside_header = true
14
19
 
@@ -30,11 +35,11 @@ module Protos
30
35
  end
31
36
 
32
37
  def visit_table_row(node)
33
- @inside_header = false
34
-
35
38
  row do
36
39
  visit_children(node)
37
40
  end
41
+
42
+ @inside_header = false
38
43
  end
39
44
 
40
45
  def visit_code(node)
@@ -45,6 +50,20 @@ module Protos
45
50
  strong { visit_children(node) }
46
51
  end
47
52
 
53
+ def visit_emph(node)
54
+ em { visit_children(node) }
55
+ end
56
+
57
+ def visit_html_inline(node)
58
+ return if @sanitize
59
+
60
+ raw safe(node.to_html(options: { render: { unsafe: true } }))
61
+ end
62
+
63
+ def visit_link(node)
64
+ a(href: node.url, title: node.title) { visit_children(node) }
65
+ end
66
+
48
67
  private
49
68
 
50
69
  def visit_children(node)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "protos"
4
- require "markly"
4
+ require "commonmarker"
5
5
  require "rouge"
6
6
  require "delegate"
7
7
 
@@ -10,8 +10,29 @@ require_relative "markdown/table"
10
10
 
11
11
  module Protos
12
12
  class Markdown < ::Protos::Component # rubocop:disable Metrics/ClassLength
13
- param :content, reader: false
14
- option :sanitize, default: -> { true }, reader: false
13
+ param :content
14
+ option :sanitize, default: -> { true }
15
+ option :markdown_options, default: -> { {} }
16
+
17
+ Heading = Data.define(:node) do
18
+ def id
19
+ text.downcase.gsub(/[^a-z0-9]+/, "-").chomp("-")
20
+ end
21
+
22
+ def text
23
+ buffer = +""
24
+ node.walk do |node|
25
+ buffer << node.string_content
26
+ rescue TypeError
27
+ # Ignore non-text nodes
28
+ end
29
+ buffer
30
+ end
31
+
32
+ def header_level
33
+ node.header_level
34
+ end
35
+ end
15
36
 
16
37
  def view_template
17
38
  return unless root
@@ -23,8 +44,12 @@ module Protos
23
44
  # Do nothing
24
45
  end
25
46
 
47
+ def visit_linebreak(_node)
48
+ br
49
+ end
50
+
26
51
  def visit_table(node)
27
- render Markdown::Table.new do |table|
52
+ render Markdown::Table.new(sanitize:) do |table|
28
53
  node.accept(table)
29
54
  end
30
55
  end
@@ -37,14 +62,16 @@ module Protos
37
62
  plain(node.string_content)
38
63
  end
39
64
 
40
- def visit_header(node)
41
- case node.header_level
42
- in 1 then h1 { visit_children(node) }
43
- in 2 then h2 { visit_children(node) }
44
- in 3 then h3 { visit_children(node) }
45
- in 4 then h4 { visit_children(node) }
46
- in 5 then h5 { visit_children(node) }
47
- in 6 then h6 { visit_children(node) }
65
+ def visit_heading(node)
66
+ heading = Heading.new(node)
67
+
68
+ case heading.header_level
69
+ in 1 then h1(id: heading.id) { visit_children(node) }
70
+ in 2 then h2(id: heading.id) { visit_children(node) }
71
+ in 3 then h3(id: heading.id) { visit_children(node) }
72
+ in 4 then h4(id: heading.id) { visit_children(node) }
73
+ in 5 then h5(id: heading.id) { visit_children(node) }
74
+ in 6 then h6(id: heading.id) { visit_children(node) }
48
75
  end
49
76
  end
50
77
 
@@ -80,12 +107,13 @@ module Protos
80
107
 
81
108
  def visit_list(node)
82
109
  case node.list_type
83
- when :ordered_list then ol { visit_children(node) }
84
- when :bullet_list then ul { visit_children(node) }
110
+ when :ordered then ol { visit_children(node) }
111
+ when :bullet then ul { visit_children(node) }
112
+ else raise ArgumentError, "Unknown list type: #{node.list_type}"
85
113
  end
86
114
  end
87
115
 
88
- def visit_list_item(node)
116
+ def visit_item(node)
89
117
  li { visit_children(node) }
90
118
  end
91
119
 
@@ -105,11 +133,11 @@ module Protos
105
133
  end
106
134
  end
107
135
 
108
- def visit_hrule(_node)
136
+ def visit_thematic_break(_node)
109
137
  hr
110
138
  end
111
139
 
112
- def visit_blockquote(node)
140
+ def visit_block_quote(node)
113
141
  blockquote { visit_children(node) }
114
142
  end
115
143
 
@@ -119,16 +147,26 @@ module Protos
119
147
  raw safe(node.string_content)
120
148
  end
121
149
 
122
- def visit_inline_html(node)
150
+ def visit_html_inline(node)
123
151
  return if @sanitize
124
152
 
125
- raw safe(node.string_content)
153
+ raw safe(node.to_html(options: { render: { unsafe: true } }))
154
+ end
155
+
156
+ def visit_html_block(node)
157
+ return if @sanitize
158
+
159
+ raw safe(node.to_html(options: { render: { unsafe: true } }))
160
+ end
161
+
162
+ def visit_escaped(node)
163
+ plain(node.first_child&.string_content)
126
164
  end
127
165
 
128
166
  private
129
167
 
130
168
  def root
131
- AST.parse(@content)
169
+ AST.parse(@content, markdown_options: @markdown_options)
132
170
  end
133
171
 
134
172
  def formatter
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "protos-markdown"
5
- spec.version = "1.0.0"
5
+ spec.version = "1.2.0"
6
6
  spec.authors = ["Nolan Tait"]
7
7
  spec.email = ["nolanjtait@gmail.com"]
8
8
 
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
32
 
33
- spec.add_dependency "markly", "~> 0.9"
33
+ spec.add_dependency "commonmarker", "~> 2.3"
34
34
  spec.add_dependency "protos", "~> 1"
35
35
  spec.add_dependency "rouge", "~> 4"
36
36
 
metadata CHANGED
@@ -1,28 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protos-markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nolan Tait
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-02 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: markly
13
+ name: commonmarker
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '0.9'
18
+ version: '2.3'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '0.9'
25
+ version: '2.3'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: protos
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
94
  requirements: []
95
- rubygems_version: 3.6.2
95
+ rubygems_version: 4.0.3
96
96
  specification_version: 4
97
97
  summary: A markdown renderer with Phlex and Protos
98
98
  test_files: []