Module: IsoDoc::Function::Utils

Included in:
Common
Defined in:
lib/isodoc/function/utils.rb

Constant Summary collapse

NOKOHEAD =

add namespaces for Word fragments

<<~HERE
  <!DOCTYPE html SYSTEM
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head> <title></title> <meta charset="UTF-8" /> </head>
  <body> </body> </html>
HERE
DOCTYPE_HDR =
'<!DOCTYPE html SYSTEM '\
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
CLAUSE_ANCESTOR =
".//ancestor::*[local-name() = 'annex' or "\
"local-name() = 'acknowledgements' or local-name() = 'term' or "\
"local-name() = 'appendix' or local-name() = 'foreword' or "\
"local-name() = 'introduction' or local-name() = 'terms' or "\
"local-name() = 'clause' or local-name() = 'references']/@id"
NOTE_CONTAINER_ANCESTOR =
".//ancestor::*[local-name() = 'annex' or "\
"local-name() = 'foreword' or local-name() = 'appendix' or "\
"local-name() = 'introduction' or local-name() = 'terms' or "\
"local-name() = 'acknowledgements' or local-name() = 'term' or "\
"local-name() = 'clause' or local-name() = 'references' or "\
"local-name() = 'figure' or local-name() = 'formula' or "\
"local-name() = 'table' or local-name() = 'example']/@id"

Instance Method Summary collapse

Instance Method Details

#attr_code(attributes) ⇒ Object



38
39
40
41
42
43
# File 'lib/isodoc/function/utils.rb', line 38

def attr_code(attributes)
  attributes = attributes.reject { |_, val| val.nil? }.map
  attributes.map do |k, v|
    [k, v.is_a?(String) ? HTMLEntities.new.decode(v) : v]
  end.to_h
end

#date_range(date) ⇒ Object



5
6
7
# File 'lib/isodoc/function/utils.rb', line 5

def date_range(date)
  self.class.date_range(date)
end

#empty2nil(v) ⇒ Object



147
148
149
150
# File 'lib/isodoc/function/utils.rb', line 147

def empty2nil(v)
  return nil if !v.nil? && v.is_a?(String) && v.empty?
  v
end

#extract_delims(text) ⇒ Object

avoid ‘; avoid {{ (Liquid Templates); avoid [[ (Javascript)



110
111
112
113
114
115
116
117
118
# File 'lib/isodoc/function/utils.rb', line 110

def extract_delims(text)
  @openmathdelim = '(#('
  @closemathdelim = ')#)'
  while text.include?(@openmathdelim) || text.include?(@closemathdelim)
    @openmathdelim += '('
    @closemathdelim += ')'
  end
  [@openmathdelim, @closemathdelim]
end

#from_xhtml(xml) ⇒ Object



69
70
71
# File 'lib/isodoc/function/utils.rb', line 69

def from_xhtml(xml)
  xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, '')
end

#get_clause_id(node) ⇒ Object



80
81
82
83
# File 'lib/isodoc/function/utils.rb', line 80

def get_clause_id(node)
  clause = node.xpath(CLAUSE_ANCESTOR)
  clause&.last&.text || nil
end

#get_note_container_id(node) ⇒ Object



94
95
96
97
# File 'lib/isodoc/function/utils.rb', line 94

def get_note_container_id(node)
  container = node.xpath(NOTE_CONTAINER_ANCESTOR)
  container&.last&.text || nil
end

#header_strip(h) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/isodoc/function/utils.rb', line 120

def header_strip(h)
  h = h.to_s.gsub(%r{<br\s*/>}, ' ').gsub(/<\/?h[123456][^>]*>/, '')
       .gsub(/<\/?b[^>]*>/, '')
  h1 = to_xhtml_fragment(h.dup)
  h1.traverse do |x|
    x.replace(' ') if x.name == 'span' && /mso-tab-count/.match(x['style'])
    x.remove if x.name == 'span' && x['class'] == 'MsoCommentReference'
    x.remove if x.name == 'a' && x['class'] == 'FootnoteRef'
    x.remove if x.name == 'span' && /mso-bookmark/.match(x['style'])
    x.replace(x.children) if x.name == 'a'
  end
  from_xhtml(h1)
end

#image_localfile(i) ⇒ Object



175
176
177
178
179
180
181
182
183
# File 'lib/isodoc/function/utils.rb', line 175

def image_localfile(i)
  if /^data:image/.match? i['src']
    save_dataimage(i['src'], false)
  elsif %r{^([A-Z]:)?/}.match? i['src']
    i['src']
  else
    File.join(@localdir, i['src'])
  end
end

#insert_tab(out, n) ⇒ Object



13
14
15
16
# File 'lib/isodoc/function/utils.rb', line 13

def insert_tab(out, n)
  tab = %w(Hans Hant).include?(@script) ? "&#x3000;" : "&nbsp; "
  [1..n].each { out << tab }
end

#labelled_ancestor(node) ⇒ Object



185
186
187
188
# File 'lib/isodoc/function/utils.rb', line 185

def labelled_ancestor(node)
  !node.ancestors('example, requirement, recommendation, permission, '\
                         'note, table, figure, sourcecode').empty?
end

#liquid(doc) ⇒ Object



134
135
136
# File 'lib/isodoc/function/utils.rb', line 134

def liquid(doc)
  self.class.liquid(doc)
end

#noko(&block) ⇒ Object

block for processing XML document fragments as XHTML, to allow for HTMLentities



29
30
31
32
33
34
35
36
# File 'lib/isodoc/function/utils.rb', line 29

def noko(&block)
  doc = ::Nokogiri::XML.parse(NOKOHEAD)
  fragment = doc.fragment('')
  ::Nokogiri::XML::Builder.with fragment, &block
  fragment.to_xml(encoding: 'US-ASCII').lines.map do |l|
    l.gsub(/\s*\n/, '')
  end
end

#ns(xpath) ⇒ Object



9
10
11
# File 'lib/isodoc/function/utils.rb', line 9

def ns(xpath)
  self.class.ns(xpath)
end

#populate_template(docxml, _format = nil) ⇒ Object



152
153
154
155
156
157
158
159
160
161
# File 'lib/isodoc/function/utils.rb', line 152

def populate_template(docxml, _format = nil)
  meta = @meta
         .get
         .merge(@labels || {})
         .merge(@meta.labels || {})
         .merge(fonts_options || {})
  template = liquid(docxml)
  template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
          .gsub('&lt;', '&#x3c;').gsub('&gt;', '&#x3e;').gsub('&amp;', '&#x26;')
end

#save_dataimage(uri, _relative_dir = true) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/isodoc/function/utils.rb', line 163

def save_dataimage(uri, _relative_dir = true)
  %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
  imgtype.sub!(/\+[a-z0-9]+$/, '') # svg+xml
  imgtype = 'png' unless /^[a-z0-9]+$/.match imgtype
  Tempfile.open(['image', ".#{imgtype}"]) do |f|
    f.binmode
    f.write(Base64.strict_decode64(imgdata))
    @tempfile_cache << f # persist to the end
    f.path
  end
end

#sentence_join(array) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/isodoc/function/utils.rb', line 99

def sentence_join(array)
  return '' if array.nil? || array.empty?
  if array.length == 1 then array[0]
  else
    @i18n.l10n("#{array[0..-2].join(', ')} "\
               "#{@i18n.and} #{array.last}",
                                 @lang, @script)
  end
end

#to_xhtml(xml) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/isodoc/function/utils.rb', line 48

def to_xhtml(xml)
  xml.gsub!(/<\?xml[^>]*>/, '')
  /<!DOCTYPE /.match(xml) || (xml = DOCTYPE_HDR + xml)
  xml = xml.split(/(\&[^ \r\n\t#;]+;)/).map do |t|
    /^(\&[^ \t\r\n#;]+;)/.match?(t) ?
      HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal) : t
  end.join('')
  begin
    Nokogiri::XML.parse(xml, &:strict)
  rescue Nokogiri::XML::SyntaxError => e
    File.open("#{@filename}.#{@format}.err", 'w:UTF-8') { |f| f.write xml }
    abort "Malformed Output XML for #{@format}: #{e} (see #{@filename}.#{@format}.err)"
  end
end

#to_xhtml_fragment(xml) ⇒ Object



63
64
65
66
67
# File 'lib/isodoc/function/utils.rb', line 63

def to_xhtml_fragment(xml)
  doc = ::Nokogiri::XML.parse(NOKOHEAD)
  fragment = doc.fragment(xml)
  fragment
end