require 'd-mark' module DMarkBook module Translators class HTML < DMark::Translator def handle_string(node) [html_escape(node)] end def handle_element(node, path) case node.name when 'p', 'dl', 'dt', 'dd', 'ol', 'ul', 'li', 'code', 'kbd', 'blockquote' wrap(node.name) { handle_children(node, path) } when 'h' depth = path.count { |node| node.name == 'section' } + 1 wrap("h#{depth}") { handle_children(node, path) } when 'section' wrap('section', id: id_for_section(node)) { handle_children(node, path) } when 'em' wrap('em') { handle_children(node, path) } when 'link' wrap('a', href: node.attributes['target']) { handle_children(node, path) } when 'listing' wrap('pre') { wrap('code') { handle_children(node, path) } } else raise DMark::Translator::UnhandledNode.new(node) end end def wrap(name, params = {}) params_string = params.map { |k, v| " #{k}=\"#{html_escape(v)}\"" }.join('') ["<#{name}#{params_string}>", yield, ""] end def html_escape(s) s.gsub('&', '&').gsub('<', '<') end def id_for_section(node) header = node.children.find { |c| c.name == 'h' } text = header.children.join('') text.downcase.gsub(/[^a-zA-Z-]/, '-') end end end end class SpecialHTML < DMarkBook::Translators::HTML def handle_element(node, depths) case node.name when 'firstterm', 'prompt', 'filename' wrap('span', class: node.name) { handle_children(node, depths) } when 'note', 'todo' wrap('div', class: node.name) { handle_children(node, depths) } else super end end end content = File.readlines('site/content/index.dmark').drop(4).join parser = DMark::Parser.new(content) tree = parser.parse puts SpecialHTML.new.translate(tree)