# -*- coding: utf-8 -*-
require 'nora_mark/html/util'
require 'nora_mark/html/pages'
require 'nora_mark/html/context'
require 'nora_mark/html/tag_writer'
require 'nora_mark/html/frontmatter_writer'
require 'nora_mark/html/paragraph_writer'
require 'nora_mark/html/abstract_node_writer'
require 'nora_mark/html/default_transformer'
module NoraMark
module Html
class Generator
include Util
attr_reader :context
def self.name
:html
end
def initialize(param = {})
@context = Context.new(param)
frontmatter_writer = FrontmatterWriter.new self
paragraph_writer = ParagraphWriter.new self
abstract_node_writer = AbstractNodeWriter.new self
page_writer = TagWriter.create('body', self,
node_preprocessor: proc do |node|
@context.end_html
if node.first_child.class == Frontmatter
frontmatter = node.first_child
frontmatter_writer.write frontmatter
frontmatter.remove
end
node
end);
@writers = {
Paragraph => paragraph_writer,
ParagraphGroup => paragraph_writer,
Inline =>TagWriter.create(nil, self, trailer: ''),
Block => TagWriter.create(nil, self),
Document => abstract_node_writer,
Page => page_writer,
Frontmatter => frontmatter_writer,
}
end
def collect_id_and_headings
@id_pool = {}
@headings = []
all_nodes = @parsed_result.all_nodes
all_nodes.each do
|x|
x.ids ||= []
x.ids.each do
|id|
if !@id_pool[id].nil?
warn "duplicate id #{id}"
end
@id_pool[id] = x
end
@headings << x if (x.kind_of?(Block) && x.name =~ /h[1-6]/)
end
end
def assign_id_to_headings
collect_id_and_headings
count = 1
@headings.each do
|heading|
if heading.ids.size == 0
begin
id = "heading_index_#{count}"
count = count + 1
end while @id_pool[id]
heading.ids << id
end
end
end
def convert(parsed_result, render_parameter = {})
transformer = Html.default_transformer
transformer.options[:render_parameter] = render_parameter
@parsed_result = transformer.transform parsed_result
assign_id_to_headings
children = parsed_result.children
@context.file_basename = parsed_result.document_name
@context.render_parameter = render_parameter
children.each {
|node|
to_html(node)
}
@context.set_toc generate_toc
@context.result
end
def generate_toc
@headings.map do
|heading|
{ page: heading.ancestors(type: :Page)[0].page_no }.merge heading.heading_info
end
end
def to_html(node)
if node.kind_of? Text
if node.noescape
@context << node.content
else
@context << escape_html(node.content)
end
else
writer = @writers[node.class]
if writer.nil?
warn "can't find html generator for \"#{node.class}\""
else
writer.write(node)
end
end
end
end
end
end