class DocTemplate::Template

Attributes

content[RW]
css_styles[R]
metadata_service[R]
toc[R]

Public Class Methods

new(type = :document) click to toggle source
# File lib/doc_template/template.rb, line 62
def initialize(type = :document)
  @type = type
  @documents = {}
end
parse(source, type: :document) click to toggle source
# File lib/doc_template/template.rb, line 37
def parse(source, type: :document)
  new(type).parse(source)
end
register_tag(name, klass) click to toggle source
# File lib/doc_template/template.rb, line 41
def register_tag(name, klass)
  tags[key_for(name)] = klass
end
tags() click to toggle source
# File lib/doc_template/template.rb, line 45
def tags
  @tags ||= TagRegistry.new
end
unregister_tag(name) click to toggle source
# File lib/doc_template/template.rb, line 49
def unregister_tag(name)
  tags.delete(key_for(name))
end

Private Class Methods

key_for(name) click to toggle source
# File lib/doc_template/template.rb, line 57
def key_for(name)
  name.is_a?(Regexp) ? name : name.to_s
end

Public Instance Methods

material?() click to toggle source
# File lib/doc_template/template.rb, line 67
def material?
  @type.to_sym == :material
end
metadata() click to toggle source
# File lib/doc_template/template.rb, line 71
def metadata
  metadata_service.metadata.data.presence || {}
end
parse(source) click to toggle source
# File lib/doc_template/template.rb, line 75
def parse(source)
  doc = Nokogiri::HTML(source)
  # get css styles from head to keep classes for lists (preserve list-style-type)
  doc = DocTemplate.sanitizer.process_list_styles doc
  @css_styles = DocTemplate.sanitizer.sanitize_css(doc.xpath('//html/head/style/text()').to_s)

  # initial content sanitization
  body_node = ::DocTemplate
                .config['sanitizer'].constantize
                .sanitize(doc.xpath('//html/body/*').to_s)
  @content = Nokogiri::HTML.fragment(body_node)

  @metadata_service = ::DocTemplate
                        .config.dig('metadata', 'service').constantize
                        .parse(@content, material: material?)

  ::DocTemplate.context_types.each do |context_type|
    options = @metadata_service.options_for context_type
    @documents[context_type] = ::DocTemplate::Document.parse(@content.dup, options)
    @documents[context_type].parts << {
      content: render(options),
      context_type: context_type,
      data: {},
      materials: [],
      optional: false,
      part_type: :layout,
      placeholder: nil
    }

    @toc ||= ::DocTemplate::DocumentTOC.parse(options) unless material?
  end

  self
end
parts() click to toggle source
# File lib/doc_template/template.rb, line 110
def parts
  @documents.values.flat_map(&:parts)
end
prereq?() click to toggle source
# File lib/doc_template/template.rb, line 114
def prereq?
  metadata['type'].to_s.casecmp('prereq').zero?
end
remove_part(type, context_type) click to toggle source
# File lib/doc_template/template.rb, line 118
def remove_part(type, context_type)
  result = nil
  @documents.each_key do |k|
    result = @documents[k].parts.detect { |p| p[:part_type] == type && p[:context_type] == context_type }
    @documents[k].parts.delete(result) && break if result.present?
  end
  result
end
render(options = {}) click to toggle source
# File lib/doc_template/template.rb, line 127
def render(options = {})
  type = options.fetch(:context_type, ::DocTemplate.context_types.first)
  DocTemplate.sanitizer.post_processing(@documents[type]&.render.presence || '', options)
end