Class: Metanorma::Standoc::EmbedIncludeProcessor

Inherits:
Asciidoctor::Extensions::Preprocessor
  • Object
show all
Defined in:
lib/metanorma/standoc/macros_embed.rb

Instance Method Summary collapse

Instance Method Details

#embed(line, doc, reader, headings) ⇒ Object



68
69
70
71
72
73
74
75
# File 'lib/metanorma/standoc/macros_embed.rb', line 68

def embed(line, doc, reader, headings)
  inc_path = filename(line, doc, reader) or return line
  lines = filter_sections(read(inc_path), headings)
  doc = Asciidoctor::Document.new [], { safe: :safe }
  reader = ::Asciidoctor::PreprocessorReader.new doc, lines
  ret = embed_acc(doc, reader).merge(strip_header(reader.read_lines))
  embed_recurse(ret, doc, reader, headings)
end

#embed_acc(doc, reader) ⇒ Object



14
15
16
17
# File 'lib/metanorma/standoc/macros_embed.rb', line 14

def embed_acc(doc, reader)
  { lines: [], hdr: [], id: [],
    doc: doc, reader: reader, prev: nil }
end

#embed_recurse(ret, doc, reader, headings) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/metanorma/standoc/macros_embed.rb', line 77

def embed_recurse(ret, doc, reader, headings)
  ret1 = ret[:lines].each_with_object(embed_acc(doc, reader)) do |line, m|
    process_line(line, m, headings)
  end
  { lines: ret1[:lines], id: ret[:id] + ret1[:id],
    hdr: { text: ret[:hdr].join("\n"), child: ret1[:hdr] } }
end

#filename(line, doc, reader) ⇒ Object



49
50
51
52
53
54
# File 'lib/metanorma/standoc/macros_embed.rb', line 49

def filename(line, doc, reader)
  m = /^embed::([^\[]+)\[/.match(line)
  f = doc.normalize_system_path m[1], reader.dir, nil,
                                target_name: "include file"
  File.exist?(f) ? f : nil
end

#filter_sections(lines, headings) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/metanorma/standoc/macros_embed.rb', line 96

def filter_sections(lines, headings)
  skip = false
  lines.each_with_index.with_object([]) do |(l, i), m|
    if headings.include?(l.strip)
      skip = true
      m.pop while !m.empty? && /^\S/.match?(m[-1])
    elsif skip && /^== |^embed::|^include::/.match?(l)
      skip = false
      j = i
      j -= 1 while j >= 0 && /^\S/.match?(m[j])
      lines[j..i].each { |n| m << n }
    else skip or m << l
    end
  end
end

#process(doc, reader) ⇒ Object



4
5
6
7
8
9
10
11
12
# File 'lib/metanorma/standoc/macros_embed.rb', line 4

def process(doc, reader)
  reader.eof? and return reader
  lines = reader.readlines
  headings = lines.grep(/^== /).map(&:strip)
  ret = lines.each_with_object(embed_acc(doc, reader)) do |line, m|
    process_line(line, m, headings)
  end
  return_to_document(doc, ret)
end

#process_embed(acc, embed, prev) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/metanorma/standoc/macros_embed.rb', line 37

def process_embed(acc, embed, prev)
  if /^\[\[.+\]\]/.match?(prev) # anchor
    acc[:id] << prev.sub(/^\[\[/, "").sub(/\]\]$/, "")
    i = embed[:lines].index { |x| /^== /.match?(x) } and
      embed[:lines][i] += " #{prev}" # => bookmark
  end
  acc[:lines] << embed[:lines]
  acc[:hdr] << embed[:hdr]
  acc[:id] += embed[:id]
  acc
end

#process_line(line, acc, headings) ⇒ Object



26
27
28
29
30
31
32
33
34
35
# File 'lib/metanorma/standoc/macros_embed.rb', line 26

def process_line(line, acc, headings)
  if /^embed::/.match?(line)
    e = embed(line, acc[:doc], acc[:reader], headings)
    acc = process_embed(acc, e, acc[:prev])
  else
    acc[:lines] << line
  end
  acc[:prev] = line
  acc
end

#read(inc_path) ⇒ Object



62
63
64
65
66
# File 'lib/metanorma/standoc/macros_embed.rb', line 62

def read(inc_path)
  ::File.open inc_path, "r" do |fd|
    readlines_safe(fd).map(&:chomp)
  end
end

#readlines_safe(file) ⇒ Object



56
57
58
59
60
# File 'lib/metanorma/standoc/macros_embed.rb', line 56

def readlines_safe(file)
  if file.eof? then []
  else file.readlines
  end
end

#return_to_document(doc, ret) ⇒ Object

presupposes single embed



20
21
22
23
24
# File 'lib/metanorma/standoc/macros_embed.rb', line 20

def return_to_document(doc, ret)
  doc.attributes["embed_hdr"] = ret[:hdr]
  doc.attributes["embed_id"] = ret[:id]
  ::Asciidoctor::Reader.new ret[:lines].flatten
end

#strip_header(lines) ⇒ Object



85
86
87
88
89
90
91
92
93
94
# File 'lib/metanorma/standoc/macros_embed.rb', line 85

def strip_header(lines)
  return { lines: lines, hdr: nil } unless !lines.empty? &&
    lines.first.start_with?("= ")

  skip = true
  lines.each_with_object({ hdr: [], lines: [] }) do |l, m|
    m[skip ? :hdr : :lines] << l
    skip = false if !/\S/.match?(l)
  end
end