Class: Metanorma::Requirements::Default

Inherits:
Object
  • Object
show all
Defined in:
lib/metanorma/default/utils.rb,
lib/metanorma/default/xrefs.rb,
lib/metanorma/default/isodoc.rb,
lib/metanorma/default/cleanup.rb,
lib/metanorma/default/default.rb

Direct Known Subclasses

Modspec

Constant Summary collapse

REQS =
%w(recommendation requirement permission).freeze

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Default

Returns a new instance of Default.



11
12
13
14
15
16
17
# File 'lib/metanorma/default/default.rb', line 11

def initialize(options)
  @c = HTMLEntities.new
  @parent = options[:parent]
  @i18n = @parent.i18n
  @labels = @parent.labels
  @isodoc = options[:isodoc]
end

Instance Method Details

#attr_code(attributes) ⇒ Object



10
11
12
# File 'lib/metanorma/default/utils.rb', line 10

def attr_code(attributes)
  Metanorma::Utils.attr_code(attributes)
end

#copy_style_attributes(node) ⇒ Object



164
165
166
167
168
169
170
# File 'lib/metanorma/default/isodoc.rb', line 164

def copy_style_attributes(node)
  t = ""
  %w(style keep-with-next keep-lines-together).each do |x|
    node[x] and t += " #{x}='#{node[x]}'"
  end
  t
end

#csv_split(text, delim = ";") ⇒ Object



14
15
16
# File 'lib/metanorma/default/utils.rb', line 14

def csv_split(text, delim = ";")
  Metanorma::Utils.csv_split(text, delim)
end

#descr_classif_extract(desc, ins) ⇒ Object



180
181
182
183
184
185
186
187
# File 'lib/metanorma/default/isodoc.rb', line 180

def descr_classif_extract(desc, ins)
  dlist = desc.xpath(ns("./classification"))
  dlist.each do |x|
    dt = semx_fmt_dup(x.at(ns("./tag")))
    dd = semx_fmt_dup(x.at(ns("./value")))
    ins << "<dt>#{to_xml dt}</dt><dd>#{to_xml dd}</dd>"
  end
end

#descr_classif_render(node, reqt) ⇒ Object



172
173
174
175
176
177
178
# File 'lib/metanorma/default/isodoc.rb', line 172

def descr_classif_render(node, reqt)
  c = reqt.xpath(ns("./classification"))
  c.empty? and return
  ins = reqt.at(ns("./classification")).before("<dl/>").previous
  descr_classif_extract(node, ins)
  c.each(&:remove)
end

#dl_to_attrs(elem, dlist, name) ⇒ Object



87
88
89
# File 'lib/metanorma/default/cleanup.rb', line 87

def dl_to_attrs(elem, dlist, name)
  Metanorma::Utils::dl_to_attrs(elem, dlist, name)
end

#dl_to_elems(ins, elem, dlist, name) ⇒ Object



91
92
93
# File 'lib/metanorma/default/cleanup.rb', line 91

def dl_to_elems(ins, elem, dlist, name)
  Metanorma::Utils::dl_to_elems(ins, elem, dlist, name)
end

#l10n(text) ⇒ Object



6
7
8
# File 'lib/metanorma/default/isodoc.rb', line 6

def l10n(text)
  @i18n.l10n(text)
end

#noko(&block) ⇒ Object



6
7
8
# File 'lib/metanorma/default/utils.rb', line 6

def noko(&block)
  Metanorma::Utils.noko(&block)
end

#ns(xpath) ⇒ Object



22
23
24
# File 'lib/metanorma/default/utils.rb', line 22

def ns(xpath)
  Metanorma::Utils.ns(xpath)
end

#permission_parts(_block, _block_id, _label, _klass) ⇒ Object



4
5
6
# File 'lib/metanorma/default/xrefs.rb', line 4

def permission_parts(_block, _block_id, _label, _klass)
  []
end

#postprocess_anchor_struct(_block, anchor) ⇒ Object



30
31
32
# File 'lib/metanorma/default/xrefs.rb', line 30

def postprocess_anchor_struct(_block, anchor)
  anchor
end

#recommendation_attr_keyvalue(node, key, value) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/metanorma/default/isodoc.rb', line 131

def recommendation_attr_keyvalue(node, key, value)
  tag = node.at(ns("./#{key}")) or return nil
  value = node.at(ns("./#{value}")) or return nil
  lbl = semx_fmt_dup(tag)
  lbl.children = Metanorma::Utils.strict_capitalize_first(lbl.text)
  l10n("#{to_xml(lbl)}: #{to_xml(semx_fmt_dup(value))}")
end

#recommendation_attr_parse(node, label) ⇒ Object



127
128
129
# File 'lib/metanorma/default/isodoc.rb', line 127

def recommendation_attr_parse(node, label)
  l10n("#{label}: #{to_xml(semx_fmt_dup(node))}")
end

#recommendation_attributes(node, out) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/metanorma/default/isodoc.rb', line 139

def recommendation_attributes(node, out)
  ret = recommendation_attributes1(node, [])
    .map { |a| "<em>#{a}</em>" }
  ret.empty? or
    out << "<p>#{ret.join("<br/>\n")}</p>"
  out
end

#recommendation_attributes1(node, out) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/metanorma/default/isodoc.rb', line 112

def recommendation_attributes1(node, out)
  oblig = node["obligation"] and
    out << l10n("#{@labels['default']['obligation']}: #{oblig}")
  node.xpath(ns("./subject")).each do |subj|
    out << l10n("#{@labels['default']['subject']}: #{to_xml(semx_fmt_dup(subj))}")
  end
  node.xpath(ns("./inherit")).each do |i|
    out << recommendation_attr_parse(i, @labels["default"]["inherits"])
  end
  node.xpath(ns("./classification")).each do |c|
    out << recommendation_attr_keyvalue(c, "tag", "value")
  end
  out
end

#recommendation_base(node, klass) ⇒ Object



97
98
99
100
101
102
103
# File 'lib/metanorma/default/isodoc.rb', line 97

def recommendation_base(node, klass)
  out = node.document.create_element(klass)
  node.attributes.each do |k, v|
    out[k] = v
  end
  out
end

#recommendation_header(_node, out) ⇒ Object



93
94
95
# File 'lib/metanorma/default/isodoc.rb', line 93

def recommendation_header(_node, out)
  out
end

#recommendation_label(elem, type, xrefs) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/metanorma/default/isodoc.rb', line 14

def recommendation_label(elem, type, xrefs)
  label, title = recommendation_labels(elem)
  type = "<span class='fmt-element-name'>#{type}</span>"
  num = xrefs.anchor(elem["id"], :label, false)
  num &&= "<semx element='autonum' source='#{elem['id']}'>#{num}</semx>"
  ret = num
  ret&.include?("<span class='fmt-element-name'>") or
    ret = "#{type} #{num}".strip
  label || title and
    ret += recommendation_label_add(elem, label, title)
  ret
end

#recommendation_label_add(elem, label, title) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/metanorma/default/isodoc.rb', line 27

def recommendation_label_add(elem, label, title)
  r = recommendation_label_caption_delim
  label and
    r += "<semx element='identifier' source='#{elem['id']}'>#{label}</semx>"
  label && title and r += ". "
  title and
    r += "<semx element='title' source='#{elem['id']}'>#{title}</semx>"
  r
end

#recommendation_label_caption_delimObject



37
38
39
# File 'lib/metanorma/default/isodoc.rb', line 37

def recommendation_label_caption_delim
  "<span class='fmt-caption-delim'>:<br/></span>"
end

#recommendation_labels(node) ⇒ Object



105
106
107
108
109
110
# File 'lib/metanorma/default/isodoc.rb', line 105

def recommendation_labels(node)
  [node.at(ns("./identifier")), node.at(ns("./title"))]
    .map do |n|
    to_xml(n&.children)
  end
end

#req_class_pathsObject



8
9
10
11
12
13
14
15
16
17
# File 'lib/metanorma/default/xrefs.rb', line 8

def req_class_paths
  [
    { klass: "permission", label: @labels["default"]["permission"],
      xpath: "permission" },
    { klass: "requirement", label: @labels["default"]["requirement"],
      xpath: "requirement" },
    { klass: "recommendation", label: @labels["default"]["recommendation"],
      xpath: "recommendation" },
  ]
end

#req_classif_parse(classif) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/metanorma/default/default.rb', line 41

def req_classif_parse(classif)
  ret = []
  @c.decode(classif).split(/;\s*/).each do |c|
    c1 = c.split(/:\s*/)
    next unless c1.size == 2

    c1[1].split(/,\s*/).each { |v| ret << [c1[0], v] }
  end
  ret
end

#req_nested_class_pathsObject



19
20
21
22
23
24
25
26
27
28
# File 'lib/metanorma/default/xrefs.rb', line 19

def req_nested_class_paths
  [
    { klass: "permission", label: @labels["default"]["permission"],
      xpath: "permission" },
    { klass: "requirement", label: @labels["default"]["requirement"],
      xpath: "requirement" },
    { klass: "recommendation", label: @labels["default"]["recommendation"],
      xpath: "recommendation" },
  ]
end

#reqt_attrs(node, attrs) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/metanorma/default/default.rb', line 61

def reqt_attrs(node, attrs)
  anchor = node&.id
  attr_code(attrs.merge(
              id: "_#{UUIDTools::UUID.random_create}",
              anchor: anchor && !anchor.empty? ? anchor : nil,
              unnumbered: node.option?("unnumbered") ? "true" : nil,
              number: node.attr("number"),
              subsequence: node.attr("subsequence"),
              obligation: node.attr("obligation"),
              filename: node.attr("filename"),
              type: node.attr("type"),
              class: node.attr("class"),
            ))
end

#reqt_component_type(node) ⇒ Object



147
148
149
150
151
# File 'lib/metanorma/default/isodoc.rb', line 147

def reqt_component_type(node)
  klass = node.name
  klass == "component" and klass = node["class"]
  "requirement-#{klass}"
end

#reqt_dl_to_classif(ins, reqt, dlist) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/metanorma/default/cleanup.rb', line 119

def reqt_dl_to_classif(ins, reqt, dlist)
  if a = reqt.at("./classification[last()]") then ins = a end
  dlist.xpath("./dt[text()='classification']").each do |e|
    val = e.at("./following::dd").text.strip
    req_classif_parse(val).each do |r|
      ins.next = "<classification><tag>#{r[0]}</tag>" \
                 "<value>#{r[1]}</value></classification>"
      ins = ins.next
    end
  end
  ins
end

#reqt_dl_to_classif1(ins, reqt, dlist) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
# File 'lib/metanorma/default/cleanup.rb', line 132

def reqt_dl_to_classif1(ins, reqt, dlist)
  if a = reqt.at("./classification[last()]") then ins = a end
  dlist.xpath("./dt").each do |e|
    next if (requirement_metadata1_attrs + requirement_metadata1_tags +
              + %w(classification))
      .include?(e.text)

    ins = reqt_dl_to_classif2(e, ins)
  end
  ins
end

#reqt_dl_to_classif2(term, ins) ⇒ Object



144
145
146
147
148
149
# File 'lib/metanorma/default/cleanup.rb', line 144

def reqt_dl_to_classif2(term, ins)
  val = unwrap_para(term.at("./following::dd"))
  ins.next = "<classification><tag>#{term.text}</tag>" \
             "<value>#{val}</value></classification>"
  ins.next
end

#reqt_metadata_node?(node) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
44
# File 'lib/metanorma/default/isodoc.rb', line 41

def (node)
  %w(identifier title subject classification tag value
     inherit name fmt-name fmt-xref-label fmt-title).include? node.name
end

#reqt_subpart?(name) ⇒ Boolean

Returns:

  • (Boolean)


19
20
21
22
# File 'lib/metanorma/default/default.rb', line 19

def reqt_subpart?(name)
  %w[specification measurement-target verification import identifier title
     description component subject inherit classification].include? name
end

#reqt_subpart_attrs(node, name, attrs) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/metanorma/default/default.rb', line 24

def reqt_subpart_attrs(node, name, attrs)
  klass = node.attr("class") || "component"
  attr_code(attrs
    .merge(exclude: node.option?("exclude"),
           type: node.attr("type"),
           class: name == "component" ? klass : nil))
end

#requirement(node, obligation, attrs) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/metanorma/default/default.rb', line 94

def requirement(node, obligation, attrs)
  noko do |xml|
    xml.send obligation, **reqt_attrs(node, attrs) do |ex|
      requirement_elems(node, ex)
      wrap_in_para(node, ex)
    end
  end
end

#requirement_classification(classif, out) ⇒ Object



52
53
54
55
56
57
58
59
# File 'lib/metanorma/default/default.rb', line 52

def requirement_classification(classif, out)
  req_classif_parse(classif).each do |r|
    out.classification do |c|
      c.tag { |t| t << r[0] }
      c.value { |v| v << r[1] }
    end
  end
end

#requirement_component_parse(node, out) ⇒ Object



153
154
155
156
157
158
159
160
161
162
# File 'lib/metanorma/default/isodoc.rb', line 153

def requirement_component_parse(node, out)
  node["exclude"] == "true" and return out
  reqt_subpart?(node.name) and type = reqt_component_type(node)
  ret = semx_fmt_dup(node)
  descr_classif_render(node, ret)
  t = copy_style_attributes(node)
  type and t += " type='#{type}'"
  out << "<div#{t}>#{to_xml(ret)}</div>"
  out
end

#requirement_description_cleanup1(reqt) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/metanorma/default/cleanup.rb', line 59

def requirement_description_cleanup1(reqt)
  while d = reqt.at("./description[following-sibling::*[1]" \
                    "[self::description]]")
    n = d.next.remove
    d << n.children
  end
  reqt.xpath("./description[normalize-space(.)='']").each do |r|
    r.replace("\n")
  end
end

#requirement_description_wrap(reqt, text) ⇒ Object



48
49
50
51
52
53
54
55
56
57
# File 'lib/metanorma/default/cleanup.rb', line 48

def requirement_description_wrap(reqt, text)
  return if (text.element? && (reqt_subpart?(text.name) ||
          REQS.include?(text.name))) ||
    (text.text.strip.empty? &&
     !text.at(".//xref | .//eref | .//link | .//origin"))

  t = Nokogiri::XML::Element.new("description", reqt.document)
  text.before(t)
  t.children = text.remove
end

#requirement_descriptions_cleanup(reqt) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/metanorma/default/cleanup.rb', line 38

def requirement_descriptions_cleanup(reqt)
  reqt.xpath(".//p[not(./*)][normalize-space(.)='']").each(&:remove)
  reqt.children.each do |e|
    requirement_description_wrap(reqt, e)
  end
  requirement_description_cleanup1(reqt)
end

#requirement_elems(node, out) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/metanorma/default/default.rb', line 76

def requirement_elems(node, out)
  node.title and out.title { |t| t << node.title }
  a = node.attr("identifier") and out.identifier do |l|
    l << out.text(a)
  end
  a = node.attr("subject") and csv_split(a)&.each do |subj|
    out.subject { |s| s << out.text(subj) }
  end
  a = @c.decode(node.attr("inherit")) and
    csv_split(a)&.each do |i|
      out.inherit do |inh|
        inh << @c.encode(i, :hexadecimal)
      end
    end
  classif = node.attr("classification") and
    requirement_classification(classif, out)
end

#requirement_identifier_cleanup(reqt) ⇒ Object



6
7
8
9
10
# File 'lib/metanorma/default/cleanup.rb', line 6

def requirement_identifier_cleanup(reqt)
  reqt.xpath("./identifier[link] | ./inherit[link]").each do |i|
    i.children = i.at("./link/@target").text
  end
end

#requirement_inherit_cleanup(reqt) ⇒ Object



12
13
14
15
# File 'lib/metanorma/default/cleanup.rb', line 12

def requirement_inherit_cleanup(reqt)
  ins = requirement_inherit_insert(reqt)
  reqt.xpath("./*//inherit").each { |i| ins.previous = i }
end

#requirement_inherit_insert(reqt) ⇒ Object



17
18
19
20
21
22
23
24
# File 'lib/metanorma/default/cleanup.rb', line 17

def requirement_inherit_insert(reqt)
  ins = reqt.at("./classification") || reqt.at(
    "./description | ./measurementtarget | ./specification | " \
    "./verification | ./import | ./component | " \
    "./requirement | ./recommendation | ./permission",
  ) and return ins
  requirement_inherit_insert1(reqt)
end

#requirement_inherit_insert1(reqt) ⇒ Object



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

def requirement_inherit_insert1(reqt)
  if t = reqt.at("./title")
    t.next = " "
    t.next
  else
    if reqt.children.empty? then reqt.add_child(" ")
    else reqt.children.first.previous = " "
    end
    reqt.children.first
  end
end

#requirement_metadata1(reqt, dlist, ins) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/metanorma/default/cleanup.rb', line 95

def requirement_metadata1(reqt, dlist, ins)
  ins = requirement_metadata1_set_insert(reqt, ins)
  requirement_metadata1_attrs.each do |a|
    dl_to_attrs(reqt, dlist, a)
  end
  requirement_metadata1_tags.each do |a|
    ins = dl_to_elems(ins, reqt, dlist, a)
  end
  ins = reqt_dl_to_classif(ins, reqt, dlist)
  reqt_dl_to_classif1(ins, reqt, dlist)
end

#requirement_metadata1_attrsObject



75
76
77
# File 'lib/metanorma/default/cleanup.rb', line 75

def requirement_metadata1_attrs
  %w(obligation model type class render)
end

#requirement_metadata1_set_insert(reqt, ins) ⇒ Object



107
108
109
110
111
# File 'lib/metanorma/default/cleanup.rb', line 107

def requirement_metadata1_set_insert(reqt, ins)
  ins and return ins
  reqt.children.first.previous = " "
  reqt.children.first
end

#requirement_metadata1_tagsObject



79
80
81
# File 'lib/metanorma/default/cleanup.rb', line 79

def requirement_metadata1_tags
  %w(identifier subject inherit)
end

#requirement_metadata_cleanup(reqt) ⇒ Object



70
71
72
73
# File 'lib/metanorma/default/cleanup.rb', line 70

def (reqt)
  dl = reqt.at("./dl[@metadata = 'true']")&.remove or return
  requirement_metadata1(reqt, dl, reqt.at("./title"))
end

#requirement_metadata_component_tagsObject



83
84
85
# File 'lib/metanorma/default/cleanup.rb', line 83

def 
  []
end

#requirement_presentation(node, out) ⇒ Object



84
85
86
87
88
89
90
91
# File 'lib/metanorma/default/isodoc.rb', line 84

def requirement_presentation(node, out)
  out.default_namespace = node.namespace.href
  node.xpath(ns("./*//fmt-name | ./*//fmt-xref-label")).each(&:remove)
  node.xpath(ns(".//fmt-sourcecode")).each(&:remove)
  ret = node.dup
  ret << out
  ret
end

#requirement_render1(node) ⇒ Object



46
47
48
49
50
51
# File 'lib/metanorma/default/isodoc.rb', line 46

def requirement_render1(node)
  case node["render"]
  when "inline" then requirement_render1_inline(node)
  else requirement_render1_default(node)
  end
end

#requirement_render1_default(node) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'lib/metanorma/default/isodoc.rb', line 74

def requirement_render1_default(node)
  out = recommendation_base(node, "fmt-provision")
  ins = recommendation_header(node, out)
  ins = recommendation_attributes(node, ins)
  node.elements.reject do |n|
    (n)
  end.each { |n| ins = requirement_component_parse(n, ins) }
  requirement_presentation(node, out)
end

#requirement_render1_inline(node) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/metanorma/default/isodoc.rb', line 53

def requirement_render1_inline(node)
  out = recommendation_base(node, "fmt-provision")
  lbl, body = requirement_render1_inline_prep(node)
  if ins = body&.at(ns(".//p"))
    ins.children.first.previous = lbl
    out << body
  else
    lbl and out << lbl
    body and out << body
  end
  requirement_presentation(node, out)
end

#requirement_render1_inline_prep(node) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/metanorma/default/isodoc.rb', line 66

def requirement_render1_inline_prep(node)
  ident = node.at(ns("./identifier")) and
    lbl = "[#{to_xml(semx_fmt_dup(ident))}] "
  body =  node.at(ns("./title | ./specification | ./description"))
  body &&= semx_fmt_dup(body)
  [lbl, body]
end

#requirement_subpart(node, attrs) ⇒ Object



32
33
34
35
36
37
38
39
# File 'lib/metanorma/default/default.rb', line 32

def requirement_subpart(node, attrs)
  name = node.role || node.attr("style")
  noko do |xml|
    xml.send name, **reqt_subpart_attrs(node, name, attrs) do |o|
      o << node.content
    end
  end
end

#requirement_type_cleanup(reqt) ⇒ Object



4
# File 'lib/metanorma/default/cleanup.rb', line 4

def requirement_type_cleanup(reqt); end

#semx_fmt_dup(elem) ⇒ Object



10
11
12
# File 'lib/metanorma/default/isodoc.rb', line 10

def semx_fmt_dup(elem)
  @isodoc.semx_fmt_dup(elem)
end

#to_xml(node) ⇒ Object



26
27
28
29
# File 'lib/metanorma/default/utils.rb', line 26

def to_xml(node)
  node&.to_xml(encoding: "UTF-8", indent: 0,
             save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)
end

#unwrap_para(ddef) ⇒ Object



113
114
115
116
117
# File 'lib/metanorma/default/cleanup.rb', line 113

def unwrap_para(ddef)
  e = ddef.elements and e.size == 1 && e.first.name == "p" and
    ddef = e.first
  to_xml(ddef.children)
end

#validate(_reqt, _log) ⇒ Object



103
104
105
# File 'lib/metanorma/default/default.rb', line 103

def validate(_reqt, _log)
  []
end

#wrap_in_para(node, out) ⇒ Object



18
19
20
# File 'lib/metanorma/default/utils.rb', line 18

def wrap_in_para(node, out)
  Metanorma::Utils.wrap_in_para(node, out)
end