markly 0.15.1 → 0.15.2
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/context/abstract-syntax-tree.md +3 -4
- data/context/headings.md +19 -20
- data/ext/markly/blocks.c +19 -6
- data/lib/markly/node.rb +1 -0
- data/lib/markly/renderer/generic.rb +3 -3
- data/lib/markly/renderer/html.rb +11 -5
- data/lib/markly/version.rb +1 -1
- data/license.md +3 -1
- data/readme.md +4 -8
- data.tar.gz.sig +0 -0
- metadata +4 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 78c9ac76ac7421696ae270097bcf7e960f78b3ae8850232fa9d7c1d6a5e5d893
|
|
4
|
+
data.tar.gz: eb0e5d5ebcfb8cf4f128dc61ac3989eb789a31ae1f9ec7e99ecd6c9482859edc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2c68b3899e33d96fcfeb9ad0c2458f67dffd9b9f8d5a1e2f1b2cd8a158faf74d5b4e1246f59b7257606b8b2218175a3563ad048824878ae6b04f6a1f5b7bfc28
|
|
7
|
+
data.tar.gz: 27d4228f0c7f158d1397117ce744f4c00ed7a59fff8253756281dc3f87d01aa642759a71187e9ee137d051d91a9d059a739addaa8b9f8f3b23b544f7ebb3f18b
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -39,7 +39,7 @@ You can use `walk` or `each` to iterate over nodes:
|
|
|
39
39
|
<!-- end list -->
|
|
40
40
|
|
|
41
41
|
``` ruby
|
|
42
|
-
require
|
|
42
|
+
require "markly"
|
|
43
43
|
|
|
44
44
|
document = Markly.parse("# The site\n\n [GitHub](https://www.github.com)")
|
|
45
45
|
|
|
@@ -80,11 +80,10 @@ class MyHtmlRenderer < Markly::Renderer::HTML
|
|
|
80
80
|
super
|
|
81
81
|
@header_id = 1
|
|
82
82
|
end
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
def header(node)
|
|
85
85
|
block do
|
|
86
|
-
out("<h", node.header_level, " id=\"", @header_id, "\">",
|
|
87
|
-
:children, "</h", node.header_level, ">")
|
|
86
|
+
out("<h", node.header_level, " id=\"", @header_id, "\">", :children, "</h", node.header_level, ">")
|
|
88
87
|
@header_id += 1
|
|
89
88
|
end
|
|
90
89
|
end
|
data/context/headings.md
CHANGED
|
@@ -38,7 +38,7 @@ document = Markly.parse(markdown)
|
|
|
38
38
|
headings = Markly::Renderer::Headings.extract(document, min_level: 2, max_level: 3)
|
|
39
39
|
|
|
40
40
|
headings.each do |heading|
|
|
41
|
-
|
|
41
|
+
puts "#{heading.level}: #{heading.text} (#{heading.anchor})"
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# Output:
|
|
@@ -90,25 +90,24 @@ Subclass `Headings` to implement alternative ID generation strategies:
|
|
|
90
90
|
|
|
91
91
|
``` ruby
|
|
92
92
|
class HierarchicalHeadings < Markly::Renderer::Headings
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
end
|
|
93
|
+
def initialize
|
|
94
|
+
super
|
|
95
|
+
@parent_context = []
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def anchor_for(node)
|
|
99
|
+
base = base_anchor_for(node)
|
|
100
|
+
|
|
101
|
+
# Custom logic: could incorporate parent heading context to generate IDs like "kubernetes-deployment" instead of "deployment-2"
|
|
102
|
+
|
|
103
|
+
if @ids.key?(base)
|
|
104
|
+
@ids[base] += 1
|
|
105
|
+
"#{base}-#{@ids[base]}"
|
|
106
|
+
else
|
|
107
|
+
@ids[base] = 1
|
|
108
|
+
base
|
|
109
|
+
end
|
|
110
|
+
end
|
|
112
111
|
end
|
|
113
112
|
|
|
114
113
|
renderer = Markly::Renderer::HTML.new(headings: HierarchicalHeadings.new)
|
data/ext/markly/blocks.c
CHANGED
|
@@ -72,6 +72,20 @@ static CMARK_INLINE bool S_is_space_or_tab(char c) {
|
|
|
72
72
|
return (c == ' ' || c == '\t');
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
// Returns true if block is being finalized on the same line it ends.
|
|
76
|
+
// This happens for:
|
|
77
|
+
// - Document node (special case)
|
|
78
|
+
// - Fenced code blocks (end on the closing fence line)
|
|
79
|
+
// - Setext headings (end on the underline)
|
|
80
|
+
// - Any block finalized on the same line it started (e.g., single-line HTML blocks)
|
|
81
|
+
static CMARK_INLINE bool S_ends_on_current_line(cmark_parser *parser, cmark_node *b) {
|
|
82
|
+
return S_type(b) == CMARK_NODE_DOCUMENT ||
|
|
83
|
+
(S_type(b) == CMARK_NODE_CODE_BLOCK && b->as.code.fenced) ||
|
|
84
|
+
(S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext) ||
|
|
85
|
+
// Single-line blocks: finalized on same line they started
|
|
86
|
+
b->start_line == parser->line_number;
|
|
87
|
+
}
|
|
88
|
+
|
|
75
89
|
static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
|
|
76
90
|
size_t len, bool eof);
|
|
77
91
|
|
|
@@ -288,17 +302,15 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
|
288
302
|
bool has_content;
|
|
289
303
|
|
|
290
304
|
parent = b->parent;
|
|
291
|
-
assert(b->flags &
|
|
292
|
-
CMARK_NODE__OPEN); // shouldn't call finalize on closed blocks
|
|
305
|
+
assert(b->flags & CMARK_NODE__OPEN); // shouldn't call finalize on closed blocks
|
|
293
306
|
b->flags &= ~CMARK_NODE__OPEN;
|
|
294
307
|
|
|
295
308
|
if (parser->curline.size == 0) {
|
|
296
|
-
// end of input - line number has not been incremented
|
|
309
|
+
// end of input - line number has not been incremented:
|
|
297
310
|
b->end_line = parser->line_number;
|
|
298
311
|
b->end_column = parser->last_line_length;
|
|
299
|
-
} else if (
|
|
300
|
-
|
|
301
|
-
(S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext)) {
|
|
312
|
+
} else if (S_ends_on_current_line(parser, b)) {
|
|
313
|
+
// Block ends on current line (line_number already incremented):
|
|
302
314
|
b->end_line = parser->line_number;
|
|
303
315
|
b->end_column = parser->curline.size;
|
|
304
316
|
if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\n')
|
|
@@ -306,6 +318,7 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
|
|
|
306
318
|
if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\r')
|
|
307
319
|
b->end_column -= 1;
|
|
308
320
|
} else {
|
|
321
|
+
// Block ended on a previous line:
|
|
309
322
|
b->end_line = parser->line_number - 1;
|
|
310
323
|
b->end_column = parser->last_line_length;
|
|
311
324
|
}
|
data/lib/markly/node.rb
CHANGED
|
@@ -26,9 +26,9 @@ module Markly
|
|
|
26
26
|
def out(*args)
|
|
27
27
|
args.each do |arg|
|
|
28
28
|
if arg == :children
|
|
29
|
-
@node.each
|
|
29
|
+
@node.each{|child| out(child)}
|
|
30
30
|
elsif arg.is_a?(Array)
|
|
31
|
-
arg.each
|
|
31
|
+
arg.each{|x| render(x)}
|
|
32
32
|
elsif arg.is_a?(Node)
|
|
33
33
|
render(arg)
|
|
34
34
|
else
|
|
@@ -43,7 +43,7 @@ module Markly
|
|
|
43
43
|
document(node)
|
|
44
44
|
@stream.string
|
|
45
45
|
elsif @in_plain && node.type != :text && node.type != :softbreak
|
|
46
|
-
node.each
|
|
46
|
+
node.each{|child| render(child)}
|
|
47
47
|
else
|
|
48
48
|
send(node.type, node)
|
|
49
49
|
end
|
data/lib/markly/renderer/html.rb
CHANGED
|
@@ -10,7 +10,13 @@
|
|
|
10
10
|
|
|
11
11
|
require_relative "generic"
|
|
12
12
|
require_relative "headings"
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
require "cgi/escape"
|
|
15
|
+
|
|
16
|
+
# Compatibility for older Ruby versions where escape_html alias doesn't exist:
|
|
17
|
+
unless CGI.respond_to?(:escape_html)
|
|
18
|
+
require "cgi"
|
|
19
|
+
end
|
|
14
20
|
|
|
15
21
|
module Markly
|
|
16
22
|
module Renderer
|
|
@@ -256,10 +262,10 @@ module Markly
|
|
|
256
262
|
end
|
|
257
263
|
|
|
258
264
|
TABLE_CELL_ALIGNMENT = {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
265
|
+
left: ' align="left"',
|
|
266
|
+
right: ' align="right"',
|
|
267
|
+
center: ' align="center"'
|
|
268
|
+
}.freeze
|
|
263
269
|
|
|
264
270
|
def table_cell(node)
|
|
265
271
|
align = TABLE_CELL_ALIGNMENT.fetch(@alignments[@column_index], "")
|
data/lib/markly/version.rb
CHANGED
data/license.md
CHANGED
|
@@ -17,9 +17,11 @@ Copyright, 2018, by Akira Matsuda.
|
|
|
17
17
|
Copyright, 2018, by Danny Iachini.
|
|
18
18
|
Copyright, 2019-2020, by Tomoya Chiba.
|
|
19
19
|
Copyright, 2019, by Brett Walker.
|
|
20
|
-
Copyright, 2020, by Olle Jonsson.
|
|
20
|
+
Copyright, 2020-2025, by Olle Jonsson.
|
|
21
21
|
Copyright, 2020-2025, by Samuel Williams.
|
|
22
22
|
Copyright, 2024, by Ross Kaffenberger.
|
|
23
|
+
Copyright, 2025, by Henrik Nyh.
|
|
24
|
+
Copyright, 2025, by Peter H. Boling.
|
|
23
25
|
|
|
24
26
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
25
27
|
of this software and associated documentation files (the "Software"), to deal
|
data/readme.md
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
# Markly
|
|
2
2
|
|
|
3
|
-
A parser and abstract syntax tree for Markdown documents (CommonMark compatible) in Ruby. Originally forked from
|
|
4
|
-
[CommonMarker](https://github.com/gjtorikian/commonmarker). It also includes extensions to the CommonMark spec as
|
|
5
|
-
documented in the [GitHub Flavored Markdown spec](http://github.github.com/gfm/), such as support for tables,
|
|
6
|
-
strikethroughs, and autolinking.
|
|
3
|
+
A parser and abstract syntax tree for Markdown documents (CommonMark compatible) in Ruby. Originally forked from [CommonMarker](https://github.com/gjtorikian/commonmarker). 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.
|
|
7
4
|
|
|
8
5
|
[](https://github.com/ioquatix/markly/actions?workflow=Test)
|
|
9
6
|
|
|
10
7
|
## Motivation
|
|
11
8
|
|
|
12
|
-
This code base was originally forked from [Commonmarker](https://github.com/gjtorikian/commonmarker) before
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
functionality, and so this fork was created to continue to provide these (and more) features.
|
|
9
|
+
This code base was originally forked from [Commonmarker](https://github.com/gjtorikian/commonmarker) before theyswitched from `cmark-gfm` (C) to `comrak` (Rust). The original implementation provided access to the abstract syntaxtree (AST), which is useful for building tools on top of Markdown. The Rust implementation did not provide thisfunctionality, and so this fork was created to continue to provide these (and more) features.
|
|
10
|
+
|
|
11
|
+
It should be noted that `commonmarker` re-introduced AST access, but the original C implementation in this fork is [3-4x faster at processing Markdown into HTML](https://github.com/gjtorikian/commonmarker?tab=readme-ov-file#benchmarks) and has a more advanced HTML generation and AST processing features.
|
|
16
12
|
|
|
17
13
|
## Usage
|
|
18
14
|
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: markly
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.15.
|
|
4
|
+
version: 0.15.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Garen Torikian
|
|
@@ -14,13 +14,15 @@ authors:
|
|
|
14
14
|
- Andrew Anderson
|
|
15
15
|
- Ben Woosley
|
|
16
16
|
- Goro Fuji
|
|
17
|
+
- Olle Jonsson
|
|
17
18
|
- Tomoya Chiba
|
|
18
19
|
- Akira Matsuda
|
|
19
20
|
- Danny Iachini
|
|
21
|
+
- Henrik Nyh
|
|
20
22
|
- Jerry van Leeuwen
|
|
21
23
|
- Michael Camilleri
|
|
22
24
|
- Mu-An Chiou
|
|
23
|
-
-
|
|
25
|
+
- Peter H. Boling
|
|
24
26
|
- Roberto Hidalgo
|
|
25
27
|
- Ross Kaffenberger
|
|
26
28
|
- Vitaliy Klachkov
|
metadata.gz.sig
CHANGED
|
Binary file
|