markly 0.14.1 → 0.15.1

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: 7eb58c81c8fca95217e5a1469baf3034785126d6ff42e9929a7d074e358b9508
4
- data.tar.gz: f28760fe0280ce1ab132d7ec639584284dde3ba8077e68f2cd3617715d1211cb
3
+ metadata.gz: 712a0a7ad856598eb83b20c370e7613896596af5c76cc2379a368382802f09db
4
+ data.tar.gz: f775598d6fc6e4d5e340bf68518816d3bd23bc44facd209fcd59bd4f0d429639
5
5
  SHA512:
6
- metadata.gz: ded6fff6a6355a8e78b2daa19a1581d982a35ddbcbddc38efe25d1866e9ce6136ea6eea62c1638874ff9953546a176df11e6ce462c9131ab38648185dec50a7a
7
- data.tar.gz: ccc6eb379235978b3a512dee8553a425ca456b01e9f60b10d16927ae1862cda069152fcc62a02a1a60d46b274a1c8aa760183a636c528b8cdc7fdf43a367abd8
6
+ metadata.gz: f13cbaaba186b5716efb05567721ea024633f0c353f7296721406dd7d4f7918625e5518ae4836371a784808ae99de8d4831bf938df6595ed26da462398c6e39f
7
+ data.tar.gz: a92d4ee382baaf2bea98defccfd318142f0fdccf42ff5fca5293c17bf611e432d21e178f3d69a272f0c021309d3725454e93ea401d7473495ff4620490071d5d
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,95 @@
1
+ # Abstract Syntax Tree
2
+
3
+ This guide explains how to use Markly's abstract syntax tree (AST) to parse and manipulate Markdown documents.
4
+
5
+ ## Parsing
6
+
7
+ You can parse Markdown to a `Document` node using `Markly.parse`:
8
+
9
+ ~~~ ruby
10
+ require 'markly'
11
+
12
+ document = Markly.parse('*Hello* world')
13
+
14
+ pp document
15
+ ~~~
16
+
17
+ This will print out the following:
18
+
19
+ ~~~
20
+ #<Markly::Node(document):
21
+ source_position={:start_line=>1, :start_column=>1, :end_line=>1, :end_column=>13}
22
+ children=[#<Markly::Node(paragraph):
23
+ source_position={:start_line=>1, :start_column=>1, :end_line=>1, :end_column=>13}
24
+ children=[#<Markly::Node(emph):
25
+ source_position={:start_line=>1, :start_column=>1, :end_line=>1, :end_column=>7}
26
+ children=[#<Markly::Node(text): source_position={:start_line=>1, :start_column=>2, :end_line=>1, :end_column=>6}, string_content="Hello">]>,
27
+ #<Markly::Node(text): source_position={:start_line=>1, :start_column=>8, :end_line=>1, :end_column=>13}, string_content=" world">]>]>
28
+ ~~~
29
+
30
+ As you can see, a document consists of a root node, which contains several children, they themselves containing children, and so on. We refer to this as the abstract syntax tree (AST).
31
+
32
+ ## Example: Walking the AST
33
+
34
+ You can use `walk` or `each` to iterate over nodes:
35
+
36
+ - `walk` will iterate on a node and recursively iterate on a node's children.
37
+ - `each` will iterate on a node and its children, but no further.
38
+
39
+ <!-- end list -->
40
+
41
+ ``` ruby
42
+ require 'markly'
43
+
44
+ document = Markly.parse("# The site\n\n [GitHub](https://www.github.com)")
45
+
46
+ # Walk tree and print out URLs for links:
47
+ document.walk do |node|
48
+ if node.type == :link
49
+ puts "URL = #{node.url}"
50
+ end
51
+ end
52
+
53
+ # Capitalize all regular text in headers:
54
+ document.walk do |node|
55
+ if node.type == :header
56
+ node.each do |subnode|
57
+ if subnode.type == :text
58
+ subnode.string_content = subnode.string_content.upcase
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # Transform links to regular text:
65
+ document.walk do |node|
66
+ if node.type == :link
67
+ node.insert_before(node.first_child)
68
+ node.delete
69
+ end
70
+ end
71
+ ```
72
+
73
+ ### Creating a Custom Renderer
74
+
75
+ You can also derive a class from {ruby Markly::Renderer::HTML} class. Using a pure Ruby renderer is slower, but allows you to customize the output. For example:
76
+
77
+ ``` ruby
78
+ class MyHtmlRenderer < Markly::Renderer::HTML
79
+ def initialize
80
+ super
81
+ @header_id = 1
82
+ end
83
+
84
+ def header(node)
85
+ block do
86
+ out("<h", node.header_level, " id=\"", @header_id, "\">",
87
+ :children, "</h", node.header_level, ">")
88
+ @header_id += 1
89
+ end
90
+ end
91
+ end
92
+
93
+ my_renderer = MyHtmlRenderer.new
94
+ puts my_renderer.render(document)
95
+ ```
@@ -0,0 +1,101 @@
1
+ # Getting Started
2
+
3
+ This guide explains now to install and use Markly.
4
+
5
+ ## Installation
6
+
7
+ Add the gem to your project:
8
+
9
+ $ bundle add markly
10
+
11
+ ## Usage
12
+
13
+ Markly's most basic usage is to convert Markdown to HTML. You can do this in a few ways:
14
+
15
+ ~~~ ruby
16
+ require 'markly'
17
+
18
+ Markly.render_html('Hi *there*')
19
+ # <p>Hi <em>there</em></p>\n
20
+ ~~~
21
+
22
+ You can also parse a string to receive a `Document` node. You can then print that node to HTML, iterate over the children, and other fun node stuff. For example:
23
+
24
+ ~~~ ruby
25
+ require 'markly'
26
+
27
+ document = Markly.parse('*Hello* world')
28
+ puts(document.to_html) # <p>Hi <em>there</em></p>\n
29
+
30
+ document.walk do |node|
31
+ puts node.type # [:document, :paragraph, :text, :emph, :text]
32
+ end
33
+ ~~~
34
+
35
+ ## Options
36
+
37
+ Markly accepts integer flags which control how the Markdown is parsed and rendered.
38
+
39
+ ### Parse Options
40
+
41
+ | Name | Description
42
+ | ------------------------------------ | -----------
43
+ | `Markly::DEFAULT` | The default parsing system.
44
+ | `Markly::UNSAFE` | Allow raw/custom HTML and unsafe links.
45
+ | `Markly::FOOTNOTES` | Parse footnotes.
46
+ | `Markly::LIBERAL_HTML_TAG` | Support liberal parsing of inline HTML tags.
47
+ | `Markly::SMART` | Use smart punctuation (curly quotes, etc.).
48
+ | `Markly::STRIKETHROUGH_DOUBLE_TILDE` | Parse strikethroughs by double tildes (compatibility with [redcarpet](https://github.com/vmg/redcarpet))
49
+ | `Markly::VALIDATE_UTF8` | Replace illegal sequences with the replacement character `U+FFFD`.
50
+
51
+ ### Render Options
52
+
53
+ | Name | Description |
54
+ | --------------------------------------- | --------------------------------------------------------------- |
55
+ | `Markly::DEFAULT` | The default rendering system. |
56
+ | `Markly::UNSAFE` | Allow raw/custom HTML and unsafe links. |
57
+ | `Markly::GITHUB_PRE_LANG` | Use GitHub-style `<pre lang>` for fenced code blocks. |
58
+ | `Markly::HARD_BREAKS` | Treat `\n` as hardbreaks (by adding `<br/>`). |
59
+ | `Markly::NO_BREAKS` | Translate `\n` in the source to a single whitespace. |
60
+ | `Markly::SOURCE_POSITION` | Include source position in rendered HTML. |
61
+ | `Markly::TABLE_PREFER_STYLE_ATTRIBUTES` | Use `style` insted of `align` for table cells. |
62
+ | `Markly::FULL_INFO_STRING` | Include full info strings of code blocks in separate attribute. |
63
+
64
+ ### Passing Options
65
+
66
+ To apply a single option, pass it in as a flags option:
67
+
68
+ ``` ruby
69
+ Markly.parse("\"Hello,\" said the spider.", flags: Markly::SMART)
70
+ # <p>“Hello,” said the spider.</p>\n
71
+ ```
72
+
73
+ To have multiple options applied, `|` (or) the flags together:
74
+
75
+ ``` ruby
76
+ Markly.render_html("\"'Shelob' is my name.\"", flags: Markly::HARD_BREAKS|Markly::SOURCE_POSITION)
77
+ ```
78
+
79
+ ## Extensions
80
+
81
+ Both `render_html` and `parse` take an optional `extensions:` argument defining the extensions you want enabled as your CommonMark document is being processed:
82
+
83
+ ``` ruby
84
+ Markly.render_html("<script>hi</script>", flags: Markly::UNSAFE, extensions: [:tagfilter])
85
+ ```
86
+
87
+ The documentation for these extensions are [defined in this spec](https://github.github.com/gfm/), and the rationale is provided [in this blog post](https://githubengineering.com/a-formal-spec-for-github-markdown/).
88
+
89
+ The available extensions are:
90
+
91
+ - `:table` - This provides support for tables.
92
+ - `:tasklist` - This provides support for task list items.
93
+ - `:strikethrough` - This provides support for strikethroughs.
94
+ - `:autolink` - This provides support for automatically converting URLs to anchor tags.
95
+ - `:tagfilter` - This escapes [several "unsafe" HTML tags](https://github.github.com/gfm/#disallowed-raw-html-extension-), causing them to not have any effect.
96
+
97
+ ## Developing Locally
98
+
99
+ After cloning the repo:
100
+
101
+ $ bake build test
@@ -0,0 +1,116 @@
1
+ # Headings
2
+
3
+ This guide explains how to work with headings in Markly, including extracting them for navigation and handling duplicate heading text.
4
+
5
+ ## Unique ID Generation
6
+
7
+ When rendering HTML with `ids: true`, duplicate heading text automatically gets unique IDs to avoid collisions. This is particularly useful when multiple sections have the same title (e.g., multiple "Deployment" sections under different parent headings).
8
+
9
+ ``` ruby
10
+ markdown = <<~MARKDOWN
11
+ ## Kubernetes
12
+
13
+ ### Deployment
14
+
15
+ ## Systemd
16
+
17
+ ### Deployment
18
+ MARKDOWN
19
+
20
+ renderer = Markly::Renderer::HTML.new(ids: true)
21
+ html = renderer.render(Markly.parse(markdown))
22
+
23
+ # Generates:
24
+ # <section id="kubernetes">...</section>
25
+ # <section id="deployment">...</section>
26
+ # <section id="systemd">...</section>
27
+ # <section id="deployment-2">...</section>
28
+ ```
29
+
30
+ The first occurrence gets the clean ID, subsequent duplicates get numbered suffixes (`-2`, `-3`, etc.).
31
+
32
+ ## Extracting Headings for Table of Contents
33
+
34
+ The `Headings` class can extract headings for building navigation or table of contents:
35
+
36
+ ``` ruby
37
+ document = Markly.parse(markdown)
38
+ headings = Markly::Renderer::Headings.extract(document, min_level: 2, max_level: 3)
39
+
40
+ headings.each do |heading|
41
+ puts "#{heading.level}: #{heading.text} (#{heading.anchor})"
42
+ end
43
+
44
+ # Output:
45
+ # 2: Kubernetes (kubernetes)
46
+ # 3: Deployment (deployment)
47
+ # 2: Systemd (systemd)
48
+ # 3: Deployment (deployment-2)
49
+ ```
50
+
51
+ Each `Heading` object has:
52
+ - `level` - The heading level (1-6)
53
+ - `text` - The plain text content
54
+ - `anchor` - The unique ID/anchor
55
+ - `node` - The original Markly AST node
56
+
57
+ ### Level Filtering
58
+
59
+ Use `min_level` and `max_level` to filter which heading levels to extract:
60
+
61
+ ``` ruby
62
+ # Only extract h2 and h3 headings
63
+ headings = Markly::Renderer::Headings.extract(document, min_level: 2, max_level: 3)
64
+
65
+ # Only h1 headings
66
+ headings = Markly::Renderer::Headings.extract(document, min_level: 1, max_level: 1)
67
+ ```
68
+
69
+ ## Custom Heading Strategies
70
+
71
+ For advanced use cases, you can provide a custom `Headings` instance to the HTML renderer:
72
+
73
+ ### Sharing State Across Documents
74
+
75
+ To ensure IDs remain unique across multiple documents:
76
+
77
+ ``` ruby
78
+ # Share heading state across multiple documents
79
+ headings = Markly::Renderer::Headings.new
80
+ renderer = Markly::Renderer::HTML.new(headings: headings)
81
+
82
+ doc1_html = renderer.render(Markly.parse(doc1_markdown))
83
+ doc2_html = renderer.render(Markly.parse(doc2_markdown))
84
+ # IDs remain unique across both documents
85
+ ```
86
+
87
+ ### Custom ID Generation
88
+
89
+ Subclass `Headings` to implement alternative ID generation strategies:
90
+
91
+ ``` ruby
92
+ class HierarchicalHeadings < Markly::Renderer::Headings
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
102
+ # to generate IDs like "kubernetes-deployment" instead of "deployment-2"
103
+
104
+ if @ids.key?(base)
105
+ @ids[base] += 1
106
+ "#{base}-#{@ids[base]}"
107
+ else
108
+ @ids[base] = 1
109
+ base
110
+ end
111
+ end
112
+ end
113
+
114
+ renderer = Markly::Renderer::HTML.new(headings: HierarchicalHeadings.new)
115
+ ```
116
+
@@ -0,0 +1,20 @@
1
+ # Automatically generated context index for Utopia::Project guides.
2
+ # Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
3
+ ---
4
+ description: CommonMark parser and renderer. Written in C, wrapped in Ruby.
5
+ metadata:
6
+ documentation_uri: https://ioquatix.github.io/markly/
7
+ funding_uri: https://github.com/sponsors/ioquatix/
8
+ source_code_uri: https://github.com/ioquatix/markly.git
9
+ files:
10
+ - path: getting-started.md
11
+ title: Getting Started
12
+ description: This guide explains now to install and use Markly.
13
+ - path: abstract-syntax-tree.md
14
+ title: Abstract Syntax Tree
15
+ description: This guide explains how to use Markly's abstract syntax tree (AST)
16
+ to parse and manipulate Markdown documents.
17
+ - path: headings.md
18
+ title: Headings
19
+ description: This guide explains how to work with headings in Markly, including
20
+ extracting them for navigation and handling duplicate heading text.
data/lib/markly/node.rb CHANGED
@@ -29,7 +29,7 @@ module Markly
29
29
 
30
30
  # Public: An iterator that "walks the tree," descending into children recursively.
31
31
  #
32
- # blk - A {Proc} representing the action to take for each child
32
+ # block - A {Proc} representing the action to take for each child
33
33
  def walk(&block)
34
34
  return enum_for(:walk) unless block_given?
35
35
 
@@ -41,7 +41,7 @@ module Markly
41
41
 
42
42
  # Public: Convert the node to an HTML string.
43
43
  #
44
- # options - A {Symbol} or {Array of Symbol}s indicating the render options
44
+ # flags - A {Symbol} or {Array of Symbol}s indicating the render options
45
45
  # extensions - An {Array of Symbol}s indicating the extensions to use
46
46
  #
47
47
  # Returns a {String}.
@@ -51,7 +51,7 @@ module Markly
51
51
 
52
52
  # Public: Convert the node to a CommonMark string.
53
53
  #
54
- # options - A {Symbol} or {Array of Symbol}s indicating the render options
54
+ # flags - A {Symbol} or {Array of Symbol}s indicating the render options
55
55
  # width - Column to wrap the output at
56
56
  #
57
57
  # Returns a {String}.
@@ -63,7 +63,7 @@ module Markly
63
63
 
64
64
  # Public: Convert the node to a plain text string.
65
65
  #
66
- # options - A {Symbol} or {Array of Symbol}s indicating the render options
66
+ # flags - A {Symbol} or {Array of Symbol}s indicating the render options
67
67
  # width - Column to wrap the output at
68
68
  #
69
69
  # Returns a {String}.
@@ -106,7 +106,6 @@ module Markly
106
106
 
107
107
  # Replace a section (header + content) with a new node.
108
108
  #
109
- # @parameter title [String] the title of the section to replace.
110
109
  # @parameter new_node [Markly::Node] the node to replace the section with.
111
110
  # @parameter replace_header [Boolean] whether to replace the header itself or not.
112
111
  # @parameter remove_subsections [Boolean] whether to remove subsections or not.
@@ -132,7 +131,7 @@ module Markly
132
131
 
133
132
  # Append the given node after the current node.
134
133
  #
135
- # It's okay to provide a document node, it's children will be appended.
134
+ # It's okay to provide a document node, its children will be appended.
136
135
  #
137
136
  # @parameter node [Markly::Node] the node to append.
138
137
  def append_after(node)
@@ -151,7 +150,7 @@ module Markly
151
150
 
152
151
  # Append the given node before the current node.
153
152
  #
154
- # It's okay to provide a document node, it's children will be appended.
153
+ # It's okay to provide a document node, its children will be appended.
155
154
  #
156
155
  # @parameter node [Markly::Node] the node to append.
157
156
  def append_before(node)
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ module Markly
7
+ module Renderer
8
+ # Extracts headings from a markdown document with unique anchor IDs.
9
+ # Handles duplicate heading text by appending counters (e.g., "deployment", "deployment-2", "deployment-3").
10
+ class Headings
11
+ def initialize
12
+ @ids = {}
13
+ end
14
+
15
+ # Generate a unique anchor for a node.
16
+ # @parameter node [Markly::Node] The heading node
17
+ # @returns [String] A unique anchor ID
18
+ def anchor_for(node)
19
+ base = base_anchor_for(node)
20
+
21
+ if @ids.key?(base)
22
+ @ids[base] += 1
23
+ "#{base}-#{@ids[base]}"
24
+ else
25
+ @ids[base] = 1
26
+ base
27
+ end
28
+ end
29
+
30
+ # Extract all headings from a document root with unique anchors.
31
+ # @parameter root [Markly::Node] The document root node
32
+ # @parameter min_level [Integer] Minimum heading level to extract (default: 1)
33
+ # @parameter max_level [Integer] Maximum heading level to extract (default: 6)
34
+ # @returns [Array<Heading>] Array of heading objects with unique anchors
35
+ def extract(root, min_level: 1, max_level: 6)
36
+ headings = []
37
+ root.walk do |node|
38
+ if node.type == :header
39
+ level = node.header_level
40
+ next if level < min_level || level > max_level
41
+
42
+ headings << Heading.new(
43
+ node: node,
44
+ level: level,
45
+ text: node.to_plaintext.chomp,
46
+ anchor: anchor_for(node)
47
+ )
48
+ end
49
+ end
50
+ headings
51
+ end
52
+
53
+ # Class method for convenience - creates a new instance and extracts headings.
54
+ # @parameter root [Markly::Node] The document root node
55
+ # @parameter min_level [Integer] Minimum heading level to extract (default: 1)
56
+ # @parameter max_level [Integer] Maximum heading level to extract (default: 6)
57
+ # @returns [Array<Heading>] Array of heading objects with unique anchors
58
+ def self.extract(root, min_level: 1, max_level: 6)
59
+ new.extract(root, min_level: min_level, max_level: max_level)
60
+ end
61
+
62
+ private
63
+
64
+ # Generate a base anchor from a node's text content.
65
+ # @parameter node [Markly::Node] The heading node
66
+ # @returns [String] The base anchor (lowercase, hyphenated)
67
+ def base_anchor_for(node)
68
+ text = node.to_plaintext.chomp.downcase
69
+ text.gsub(/\s+/, "-")
70
+ end
71
+ end
72
+
73
+ # Represents a heading extracted from a document.
74
+ # @attribute node [Markly::Node] The original heading node
75
+ # @attribute level [Integer] The heading level (1-6)
76
+ # @attribute text [String] The plain text content of the heading
77
+ # @attribute anchor [String] The unique anchor ID for this heading
78
+ Heading = Struct.new(:node, :level, :text, :anchor, keyword_init: true)
79
+ end
80
+ end
81
+
@@ -9,15 +9,18 @@
9
9
  # Copyright, 2020-2025, by Samuel Williams.
10
10
 
11
11
  require_relative "generic"
12
+ require_relative "headings"
12
13
  require "cgi"
13
14
 
14
15
  module Markly
15
16
  module Renderer
16
17
  class HTML < Generic
17
- def initialize(ids: false, tight: false, **options)
18
+ def initialize(ids: false, headings: nil, tight: false, **options)
18
19
  super(**options)
19
20
 
20
- @ids = ids
21
+ # Initialize heading tracker if IDs are enabled
22
+ @headings = headings || (ids ? Headings.new : nil)
23
+
21
24
  @section = nil
22
25
  @tight = tight
23
26
 
@@ -32,8 +35,8 @@ module Markly
32
35
  end
33
36
 
34
37
  def id_for(node)
35
- if @ids
36
- anchor = self.class.anchor_for(node)
38
+ if @headings
39
+ anchor = @headings.anchor_for(node)
37
40
  return " id=\"#{CGI.escape_html anchor}\""
38
41
  end
39
42
  end
@@ -54,7 +57,7 @@ module Markly
54
57
 
55
58
  def header(node)
56
59
  block do
57
- if @ids
60
+ if @headings
58
61
  out("</section>") if @section
59
62
  @section = true
60
63
  out("<section#{id_for(node)}>")
@@ -253,10 +256,10 @@ module Markly
253
256
  end
254
257
 
255
258
  TABLE_CELL_ALIGNMENT = {
256
- left: ' align="left"',
257
- right: ' align="right"',
258
- center: ' align="center"'
259
- }.freeze
259
+ left: ' align="left"',
260
+ right: ' align="right"',
261
+ center: ' align="center"'
262
+ }.freeze
260
263
 
261
264
  def table_cell(node)
262
265
  align = TABLE_CELL_ALIGNMENT.fetch(@alignments[@column_index], "")
@@ -7,5 +7,5 @@
7
7
  # Copyright, 2020-2025, by Samuel Williams.
8
8
 
9
9
  module Markly
10
- VERSION = "0.14.1"
10
+ VERSION = "0.15.1"
11
11
  end
data/readme.md CHANGED
@@ -22,10 +22,20 @@ Please see the [project documentation](https://ioquatix.github.io/markly/) for m
22
22
 
23
23
  - [Abstract Syntax Tree](https://ioquatix.github.io/markly/guides/abstract-syntax-tree/index) - This guide explains how to use Markly's abstract syntax tree (AST) to parse and manipulate Markdown documents.
24
24
 
25
+ - [Headings](https://ioquatix.github.io/markly/guides/headings/index) - This guide explains how to work with headings in Markly, including extracting them for navigation and handling duplicate heading text.
26
+
25
27
  ## Releases
26
28
 
27
29
  Please see the [project releases](https://ioquatix.github.io/markly/releases/index) for all releases.
28
30
 
31
+ ### v0.15.1
32
+
33
+ - Add agent context.
34
+
35
+ ### v0.15.0
36
+
37
+ - Introduced `Markly::Renderer::Headings` class for extracting headings from markdown documents with automatic duplicate ID resolution. When rendering HTML with `ids: true`, duplicate heading text now automatically gets unique IDs (`deployment`, `deployment-2`, `deployment-3`). The `Headings` class can also be used to extract headings for building navigation or table of contents.
38
+
29
39
  ### v0.14.0
30
40
 
31
41
  - Expose `Markly::Renderer::HTML.anchor_for` method to generate URL-safe anchors from headers.
data/releases.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Releases
2
2
 
3
+ ## v0.15.1
4
+
5
+ - Add agent context.
6
+
7
+ ## v0.15.0
8
+
9
+ - Introduced `Markly::Renderer::Headings` class for extracting headings from markdown documents with automatic duplicate ID resolution. When rendering HTML with `ids: true`, duplicate heading text now automatically gets unique IDs (`deployment`, `deployment-2`, `deployment-3`). The `Headings` class can also be used to extract headings for building navigation or table of contents.
10
+
3
11
  ## v0.14.0
4
12
 
5
13
  - Expose `Markly::Renderer::HTML.anchor_for` method to generate URL-safe anchors from headers.
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.14.1
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen Torikian
@@ -62,6 +62,10 @@ extensions:
62
62
  - ext/markly/extconf.rb
63
63
  extra_rdoc_files: []
64
64
  files:
65
+ - context/abstract-syntax-tree.md
66
+ - context/getting-started.md
67
+ - context/headings.md
68
+ - context/index.yaml
65
69
  - ext/markly/arena.c
66
70
  - ext/markly/autolink.c
67
71
  - ext/markly/autolink.h
@@ -138,6 +142,7 @@ files:
138
142
  - lib/markly/node.rb
139
143
  - lib/markly/node/inspect.rb
140
144
  - lib/markly/renderer/generic.rb
145
+ - lib/markly/renderer/headings.rb
141
146
  - lib/markly/renderer/html.rb
142
147
  - lib/markly/version.rb
143
148
  - license.md
metadata.gz.sig CHANGED
Binary file