class Metanorma::Plugin::Datastruct::BaseStructuredTextPreprocessor

Base class for processing structured data blocks(yaml, json)

Constants

BLOCK_END_REGEXP
BLOCK_START_REGEXP

Public Instance Methods

process(document, reader) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 29
def process(document, reader)
  input_lines = reader.readlines.to_enum
  Asciidoctor::Reader.new(processed_lines(document, input_lines))
end

Protected Instance Methods

content_from_file(_document, _file_path) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 36
def content_from_file(_document, _file_path)
  raise ArgumentError, "Implement `content_from_file` in your class"
end

Private Instance Methods

collect_internal_block_lines(document, input_lines, end_mark) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 72
def collect_internal_block_lines(document, input_lines, end_mark)
  current_block = []
  nested_marks = []
  while (block_line = input_lines.next) != end_mark
    if nested_match = block_line
        .match(/^\[#{config[:block_name]},(.+?),(.+?)\]/)
      current_block
        .push(*nested_context_tag(document,
                                  nested_match[1],
                                  nested_match[2]).split("\n"))
      next nested_marks.push(input_lines.next)
    end

    if nested_marks.include?(block_line)
      current_block.push("{% endwith_#{data_file_type}_nested_context %}")
      next nested_marks.delete(block_line)
    end
    current_block.push(block_line)
  end
  current_block
end
data_file_type() click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 94
def data_file_type
  @config[:block_name].split("2").first
end
nested_context_tag(document, file_path, context_name) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 98
        def nested_context_tag(document, file_path, context_name)
          absolute_file_path = relative_file_path(document, file_path)
          <<~TEMPLATE
            {% capture nested_file_path %}
            #{absolute_file_path}
            {% endcapture %}
            {% with_#{data_file_type}_nested_context nested_file_path, #{context_name}  %}
          TEMPLATE
        end
notify_render_errors(document, errors) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 166
def notify_render_errors(document, errors)
  errors.each do |error_obj|
    document
      .logger
      .warn("Liquid render error: #{error_obj.message}")
  end
end
parse_context_block(context_lines:, context_items:, context_name:, document:) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 140
def parse_context_block(context_lines:,
                        context_items:,
                        context_name:,
                        document:)
  render_result, errors = render_liquid_string(
    template_string: context_lines.join("\n"),
    context_items: context_items,
    context_name: context_name,
    document: document
  )
  notify_render_errors(document, errors)
  render_result.split("\n")
end
parse_template(document, current_block, block_match) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 108
def parse_template(document, current_block, block_match)
  transformed_liquid_lines = current_block
    .map(&method(:transform_line_liquid))
  context_items = content_from_file(document, block_match[1])
  parse_context_block(document: document,
                      context_lines: transformed_liquid_lines,
                      context_items: context_items,
                      context_name: block_match[2].strip)
rescue StandardError => e
  document.logger
    .warn("Failed to parse #{config[:block_name]} \
      block: #{e.message}")
  []
end
process_text_blocks(document, input_lines) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 59
def process_text_blocks(document, input_lines)
  line = input_lines.next
  block_match = line.match(/^\[#{config[:block_name]},(.+?),(.+?)\]/)
  return [line] if block_match.nil?

  end_mark = input_lines.next
  parse_template(document,
                 collect_internal_block_lines(document,
                                              input_lines,
                                              end_mark),
                 block_match)
end
processed_lines(document, input_lines) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 42
def processed_lines(document, input_lines)
  result = []
  loop do
    result.push(*process_text_blocks(document, input_lines))
  end
  result
end
relative_file_path(document, file_path) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 50
def relative_file_path(document, file_path)
  docfile_directory = File.dirname(
    document.attributes["docfile"] || "."
  )
  document
    .path_resolver
    .system_path(file_path, docfile_directory)
end
render_liquid_string(template_string:, context_items:, context_name:, document:) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 154
def render_liquid_string(template_string:, context_items:,
                         context_name:, document:)
  liquid_template = Liquid::Template.parse(template_string)
  # Allow includes for the template
  liquid_template.registers[:file_system] = ::Liquid::LocalFileSystem.new(relative_file_path(document, ""))
  rendered_string = liquid_template
    .render(context_name => context_items,
            strict_variables: true,
            error_mode: :warn)
  [rendered_string, liquid_template.errors]
end
transform_line_liquid(line) click to toggle source
# File lib/metanorma/plugin/datastruct/base_structured_text_preprocessor.rb, line 123
def transform_line_liquid(line)
  if line.match?(BLOCK_START_REGEXP)
    line.gsub!(BLOCK_START_REGEXP, '{% keyiterator \1, \2 %}')
  end

  if line.strip.match?(BLOCK_END_REGEXP)
    line.gsub!(BLOCK_END_REGEXP, "{% endkeyiterator %}")
  end
  line
    .gsub(/(?<!{){(?!%)([^{}]+)(?<!%)}(?!})/, '{{\1}}')
    .gsub(/[a-z\.]+\#/, "index")
    .gsub(/{{(.+)\s+\+\s+(\d+)\s*?}}/, '{{ \1 | plus: \2 }}')
    .gsub(/{{(.+)\s+\-\s+(\d+)\s*?}}/, '{{ \1 | minus: \2 }}')
    .gsub(/{{(.+)\.values(.*?)}}/,
          '{% assign custom_value = \1 | values %}{{custom_value\2}}')
end