require_relative "xrefs" require_relative "reqt_label" require_relative "table_cleanup" module Metanorma class Requirements class Modspec < Default def requirement_render1(node) init_lookups(node.document) ret = requirement_guidance_parse(node, super) requirement_table_cleanup(node, ret) end def recommendation_base(node, _klass) out = node.document.create_element("table") out.default_namespace = node.namespace.href %w(id keep-with-next keep-lines-together unnumbered).each do |x| out[x] = node[x] if node[x] end out["class"] = "modspec" out["type"] = recommend_class(node) recommendation_component_labels(node) out end def recommendation_component_labels(node) node.xpath(ns("./component[@class = 'part']")).each_with_index do |c, i| c["label"] = (i + "A".ord).chr.to_s end node.xpath(ns("./component[not(@class = 'part')]")).each do |c| c["label"] = recommend_component_label(c) end end def recommendation_header(reqt, out) n = recommendation_name(reqt, nil) x = if reqt.ancestors("requirement, recommendation, permission").empty? "" \ "

#{n}

" \ "" else "#{recommendation_class_label(reqt)}" \ "#{n}" end out << x out end def recommendation_name(node, _out) ret = "" name = node.at(ns("./name")) and ret += name.children.to_xml title = node.at(ns("./title")) return ret unless title && node.ancestors("requirement, recommendation, permission").empty? ret += ": " unless !name || name.text.empty? ret += title.children.to_xml l10n(ret) end def recommendation_attributes(node, out) ins = out.add_child("").first recommend_title(node, ins) recommendation_attributes1(node).each do |i| ins.add_child("#{i[0]}#{i[1]}") end ins end def recommend_title(node, out) label = node.at(ns("./identifier")) or return out.add_child("#{@labels['modspec']['identifier']}" \ "#{label.children.to_xml}") end def recommendation_attributes1(node) ret = recommendation_attributes1_head(node, []) node.xpath(ns("./classification")).each do |c| line = recommendation_attr_keyvalue(c, "tag", "value") and ret << line end ret end def recommendation_attributes1_head(node, head) oblig = node["obligation"] and head << [@labels["default"]["obligation"], oblig] subj = node.at(ns("./subject"))&.children and head << [rec_subj(node), subj] head = recommendation_attributes1_target(node, head) head += recommendation_backlinks(node) recommendation_attributes1_dependencies(node, head) end def recommendation_attributes1_target(node, head) node.xpath(ns("./classification[tag][value]")).each do |c| c.at(ns("./tag")).text.casecmp("target").zero? or next xref = recommendation_id(c.at(ns("./value")).text) and head << [rec_target(node), xref] end head end def recommendation_backlinks(node) ret = [] id = node.at(ns("./identifier")) or return ret ret = recommendation_backlinks_test(node, id, ret) recommendation_backlinks_class(node, id, ret) end def recommendation_attributes1_dependencies(node, head) head = recommendation_attributes1_inherit(node, head) recommendation_attributes_dependencies2(node, head) end def recommendation_attributes1_inherit(node, head) node.xpath(ns("./inherit")).each do |i| head << [@labels["modspec"]["dependency"], recommendation_id(i.children.to_xml)] end head end def recommendation_attributes_dependencies2(node, head) %w(indirect-dependency implements).each do |x| node.xpath(ns("./classification[tag][value]")).each do |c| c.at(ns("./tag")).text.casecmp(x).zero? or next xref = recommendation_id(c.at(ns("./value")).children.to_xml) and head << [@labels["modspec"][x.gsub(/-/, "")], xref] end end head end def id_attr(node) node["id"] ? " id='#{node['id']}'" : "" end def recommendation_steps(node) node.elements.each { |e| recommendation_steps(e) } return node unless node.at(ns("./component[@class = 'step']")) d = node.at(ns("./component[@class = 'step']")) d = d.replace("
    " \ "#{d.children.to_xml}
").first node.xpath(ns("./component[@class = 'step']")).each do |f| f = f.replace("#{f.children.to_xml}").first d << f end node end def recommendation_attributes1_component(node, out) return out if node["class"] == "guidance" node = recommendation_steps(node) out << "#{node['label']}" \ "#{node.children}" out end def recommendation_attr_keyvalue(node, key, value) tag = node.at(ns("./#{key}")) or return nil value = node.at(ns("./#{value}")) or return nil !%w(target indirect-dependency implements).include?(tag.text.downcase) or return nil [Metanorma::Utils.strict_capitalize_first(tag.text), value.children] end def reqt_component_type(node) klass = node.name klass == "component" and klass = node["class"] "requirement-#{klass}" end def preserve_in_nested_table?(node) %w(recommendation requirement permission table ol dl ul).include?(node.name) end def requirement_component_parse(node, out) node["exclude"] == "true" and return out node.elements.size == 1 && node.first_element_child.name == "dl" and return reqt_dl(node.first_element_child, out) node.name == "component" and return recommendation_attributes1_component(node, out) node.name == "description" and return requirement_description_parse(node, out) out.add_child("").first .at(ns(".//td")) << (preserve_in_nested_table?(node) ? node : node.children) out end def requirement_description_parse(node, out) lbl = "statement" recommend_class(node.parent) == "recommendclass" and lbl = "description" out << "#{@labels['modspec'][lbl]}" \ "#{node.children.to_xml}" out end def requirement_guidance_parse(node, out) ins = out.at(ns("./tbody")) node.xpath(ns("./component[@class = 'guidance']")).each do |f| ins << "#{@labels['modspec']['guidance']}" \ "#{f.children}" end out end def reqt_dl(node, out) node.xpath(ns("./dt")).each do |dt| dd = dt.next_element dd&.name == "dd" or next out.add_child("#{dt.children.to_xml}" \ "#{dd.children.to_xml}") end out end end end end