Skip to content

Instantly share code, notes, and snippets.

@zhangkaizhao
Last active November 30, 2020 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhangkaizhao/ef9554886a7b0e7d02a1b6cd058691ea to your computer and use it in GitHub Desktop.
Save zhangkaizhao/ef9554886a7b0e7d02a1b6cd058691ea to your computer and use it in GitHub Desktop.
Crystal version (tested on 0.35.1) of Heading Linker https://github.com/wezm/pkb/blob/master/lib/heading_linker.rb
require "html"
require "uri"
require "xml"
class HeadingLinker
HTML_PARSER_OPTIONS = XML::HTMLParserOptions.default | XML::HTMLParserOptions::NODEFDTD
XML_SAVE_OPTIONS = XML::SaveOptions::FORMAT | XML::SaveOptions::AS_HTML
getter doc
def initialize(@doc : XML::Node)
end
def link_headings!
add_anchors_to_headers!
# XXX escaped HTML. How to append children nodes?
content = HTML.unescape(doc.to_xml(options: XML_SAVE_OPTIONS))
@doc = XML.parse_html(content, options: HTML_PARSER_OPTIONS)
end
private def add_anchors_to_headers!
doc.xpath_nodes("//h1 | //h2 | //h3 | //h4 | //h5 | //h6").each do |heading|
identifier = URI.encode(heading.text)
hstr = XML.build_fragment do |xml|
xml.element("a", id: identifier, class: "anchor", href: "##{identifier}") do
xml.element("span", class: "link-icon monospace") do
xml.text "#"
end
end
xml.text heading.text
end
# XXX escaped HTML. How to append children nodes?
heading.text = hstr.chomp
end
end
end
html = <<-HTML
<html>
<body>
<h1>Test title</h1>
<p>Hello1</p>
<h2>Chapter1</h2>
<div>Content1</div>
<h2>Chapter2</h2>
<ul>
<li>Crystal</li>
<li>Rust</li>
<li>Go</li>
</ul>
<h2>Chapter3</h2>
<h3>你好,世界!</h3>
<h2>Chapter4</h2>
<h2>Chapter5</h2>
<h2>Chapter6</h2>
<h2>Chapter7</h2>
<h2>Chapter8</h2>
<h2>Chapter9</h2>
<p>Done</p>
</body>
</html>
HTML
doc = XML.parse_html(html, options: HeadingLinker::HTML_PARSER_OPTIONS)
HeadingLinker.new(doc).link_headings!
puts HTML.unescape(doc.to_xml(options: HeadingLinker::XML_SAVE_OPTIONS))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment