metanorma-standoc 1.11.2 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +3 -31
  3. data/.gitignore +23 -0
  4. data/Gemfile +1 -0
  5. data/lib/asciidoctor/standoc/base.rb +2 -241
  6. data/lib/asciidoctor/standoc/blocks.rb +2 -238
  7. data/lib/asciidoctor/standoc/blocks_notes.rb +2 -100
  8. data/lib/asciidoctor/standoc/cleanup.rb +2 -207
  9. data/lib/asciidoctor/standoc/cleanup_amend.rb +2 -53
  10. data/lib/asciidoctor/standoc/cleanup_block.rb +2 -173
  11. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +2 -212
  12. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +2 -108
  13. data/lib/asciidoctor/standoc/cleanup_image.rb +2 -69
  14. data/lib/asciidoctor/standoc/cleanup_inline.rb +2 -179
  15. data/lib/asciidoctor/standoc/cleanup_maths.rb +2 -221
  16. data/lib/asciidoctor/standoc/cleanup_ref.rb +2 -169
  17. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +2 -103
  18. data/lib/asciidoctor/standoc/cleanup_reqt.rb +2 -110
  19. data/lib/asciidoctor/standoc/cleanup_section.rb +2 -184
  20. data/lib/asciidoctor/standoc/cleanup_section_names.rb +2 -91
  21. data/lib/asciidoctor/standoc/cleanup_symbols.rb +2 -47
  22. data/lib/asciidoctor/standoc/cleanup_table.rb +2 -67
  23. data/lib/asciidoctor/standoc/cleanup_terms.rb +2 -117
  24. data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +2 -178
  25. data/lib/asciidoctor/standoc/cleanup_text.rb +2 -95
  26. data/lib/asciidoctor/standoc/cleanup_toc.rb +3 -0
  27. data/lib/asciidoctor/standoc/cleanup_xref.rb +2 -106
  28. data/lib/asciidoctor/standoc/converter.rb +2 -123
  29. data/lib/asciidoctor/standoc/datamodel/attributes_table_preprocessor.rb +2 -56
  30. data/lib/asciidoctor/standoc/datamodel/diagram_preprocessor.rb +2 -102
  31. data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +3 -404
  32. data/lib/asciidoctor/standoc/deprecated.rb +5 -0
  33. data/lib/asciidoctor/standoc/front.rb +2 -219
  34. data/lib/asciidoctor/standoc/front_contributor.rb +2 -191
  35. data/lib/asciidoctor/standoc/inline.rb +2 -231
  36. data/lib/asciidoctor/standoc/lists.rb +2 -119
  37. data/lib/asciidoctor/standoc/macros.rb +2 -203
  38. data/lib/asciidoctor/standoc/macros_form.rb +2 -62
  39. data/lib/asciidoctor/standoc/macros_note.rb +2 -44
  40. data/lib/asciidoctor/standoc/macros_plantuml.rb +2 -112
  41. data/lib/asciidoctor/standoc/macros_terms.rb +2 -180
  42. data/lib/asciidoctor/standoc/ref.rb +2 -251
  43. data/lib/asciidoctor/standoc/ref_sect.rb +2 -153
  44. data/lib/asciidoctor/standoc/ref_utility.rb +2 -0
  45. data/lib/asciidoctor/standoc/render.rb +3 -0
  46. data/lib/asciidoctor/standoc/reqt.rb +2 -89
  47. data/lib/asciidoctor/standoc/section.rb +2 -190
  48. data/lib/asciidoctor/standoc/table.rb +2 -84
  49. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +2 -178
  50. data/lib/asciidoctor/standoc/terms.rb +2 -153
  51. data/lib/asciidoctor/standoc/utils.rb +2 -116
  52. data/lib/asciidoctor/standoc/validate.rb +2 -157
  53. data/lib/asciidoctor/standoc/validate_section.rb +2 -54
  54. data/lib/isodoc/html/htmlstyle.css +44 -29
  55. data/lib/isodoc/html/htmlstyle.scss +17 -12
  56. data/lib/metanorma/standoc/base.rb +163 -0
  57. data/lib/{asciidoctor → metanorma}/standoc/basicdoc.rng +0 -0
  58. data/lib/{asciidoctor → metanorma}/standoc/biblio.rng +0 -0
  59. data/lib/metanorma/standoc/blocks.rb +239 -0
  60. data/lib/metanorma/standoc/blocks_notes.rb +101 -0
  61. data/lib/metanorma/standoc/cleanup.rb +157 -0
  62. data/lib/metanorma/standoc/cleanup_amend.rb +54 -0
  63. data/lib/metanorma/standoc/cleanup_block.rb +173 -0
  64. data/lib/metanorma/standoc/cleanup_boilerplate.rb +213 -0
  65. data/lib/metanorma/standoc/cleanup_footnotes.rb +109 -0
  66. data/lib/metanorma/standoc/cleanup_image.rb +70 -0
  67. data/lib/metanorma/standoc/cleanup_inline.rb +190 -0
  68. data/lib/metanorma/standoc/cleanup_maths.rb +222 -0
  69. data/lib/metanorma/standoc/cleanup_ref.rb +170 -0
  70. data/lib/metanorma/standoc/cleanup_ref_dl.rb +104 -0
  71. data/lib/metanorma/standoc/cleanup_reqt.rb +111 -0
  72. data/lib/metanorma/standoc/cleanup_section.rb +212 -0
  73. data/lib/metanorma/standoc/cleanup_section_names.rb +92 -0
  74. data/lib/metanorma/standoc/cleanup_symbols.rb +48 -0
  75. data/lib/metanorma/standoc/cleanup_table.rb +68 -0
  76. data/lib/metanorma/standoc/cleanup_terms.rb +140 -0
  77. data/lib/metanorma/standoc/cleanup_terms_designations.rb +199 -0
  78. data/lib/metanorma/standoc/cleanup_text.rb +96 -0
  79. data/lib/metanorma/standoc/cleanup_toc.rb +98 -0
  80. data/lib/metanorma/standoc/cleanup_xref.rb +107 -0
  81. data/lib/metanorma/standoc/converter.rb +125 -0
  82. data/lib/metanorma/standoc/datamodel/attributes_table_preprocessor.rb +57 -0
  83. data/lib/metanorma/standoc/datamodel/diagram_preprocessor.rb +103 -0
  84. data/lib/metanorma/standoc/datamodel/plantuml_renderer.rb +409 -0
  85. data/lib/metanorma/standoc/front.rb +224 -0
  86. data/lib/metanorma/standoc/front_contributor.rb +192 -0
  87. data/lib/metanorma/standoc/inline.rb +232 -0
  88. data/lib/{asciidoctor → metanorma}/standoc/isodoc.rng +49 -2
  89. data/lib/metanorma/standoc/lists.rb +120 -0
  90. data/lib/metanorma/standoc/macros.rb +204 -0
  91. data/lib/metanorma/standoc/macros_form.rb +63 -0
  92. data/lib/metanorma/standoc/macros_note.rb +45 -0
  93. data/lib/metanorma/standoc/macros_plantuml.rb +113 -0
  94. data/lib/metanorma/standoc/macros_terms.rb +194 -0
  95. data/lib/metanorma/standoc/ref.rb +243 -0
  96. data/lib/metanorma/standoc/ref_sect.rb +153 -0
  97. data/lib/{asciidoctor/standoc/ref_date_id.rb → metanorma/standoc/ref_utility.rb} +43 -5
  98. data/lib/metanorma/standoc/render.rb +115 -0
  99. data/lib/metanorma/standoc/reqt.rb +90 -0
  100. data/lib/{asciidoctor → metanorma}/standoc/reqt.rng +0 -0
  101. data/lib/metanorma/standoc/section.rb +209 -0
  102. data/lib/metanorma/standoc/table.rb +85 -0
  103. data/lib/metanorma/standoc/term_lookup_cleanup.rb +179 -0
  104. data/lib/metanorma/standoc/terms.rb +160 -0
  105. data/lib/metanorma/standoc/utils.rb +101 -0
  106. data/lib/metanorma/standoc/validate.rb +158 -0
  107. data/lib/metanorma/standoc/validate_section.rb +55 -0
  108. data/lib/metanorma/standoc/version.rb +1 -1
  109. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/model_representation.adoc.erb +0 -0
  110. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/plantuml_representation.adoc.erb +0 -0
  111. data/lib/metanorma-standoc.rb +1 -1
  112. data/metanorma-standoc.gemspec +2 -2
  113. data/spec/{asciidoctor → metanorma}/base_spec.rb +499 -407
  114. data/spec/{asciidoctor → metanorma}/blank_spec.rb +1 -1
  115. data/spec/{asciidoctor → metanorma}/blocks_spec.rb +34 -5
  116. data/spec/{asciidoctor → metanorma}/cleanup_blocks_spec.rb +25 -1
  117. data/spec/{asciidoctor → metanorma}/cleanup_sections_spec.rb +1 -1
  118. data/spec/{asciidoctor → metanorma}/cleanup_spec.rb +5 -5
  119. data/spec/{asciidoctor → metanorma}/cleanup_terms_spec.rb +281 -29
  120. data/spec/{asciidoctor → metanorma}/datamodel/attributes_table_preprocessor_spec.rb +1 -1
  121. data/spec/{asciidoctor → metanorma}/datamodel/diagram_preprocessor_spec.rb +1 -1
  122. data/spec/{asciidoctor → metanorma}/inline_spec.rb +170 -1
  123. data/spec/{asciidoctor → metanorma}/isobib_cache_spec.rb +1 -1
  124. data/spec/{asciidoctor → metanorma}/lists_spec.rb +1 -1
  125. data/spec/{asciidoctor → metanorma}/macros_json2text_spec.rb +0 -0
  126. data/spec/{asciidoctor → metanorma}/macros_plantuml_spec.rb +3 -3
  127. data/spec/{asciidoctor → metanorma}/macros_spec.rb +8 -6
  128. data/spec/{asciidoctor → metanorma}/macros_yaml2text_spec.rb +0 -0
  129. data/spec/metanorma/refs_dl_spec.rb +863 -0
  130. data/spec/{asciidoctor → metanorma}/refs_spec.rb +522 -15
  131. data/spec/{asciidoctor → metanorma}/section_spec.rb +88 -1
  132. data/spec/{asciidoctor → metanorma}/table_spec.rb +1 -1
  133. data/spec/{asciidoctor → metanorma}/validate_spec.rb +2 -2
  134. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +53 -53
  135. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +14 -14
  136. data/spec/vcr_cassettes/hide_refs.yml +599 -0
  137. data/spec/vcr_cassettes/isobib_get_123.yml +14 -14
  138. data/spec/vcr_cassettes/isobib_get_123_1.yml +99 -99
  139. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +109 -109
  140. data/spec/vcr_cassettes/isobib_get_123_2001.yml +13 -13
  141. data/spec/vcr_cassettes/isobib_get_124.yml +12 -12
  142. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
  143. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
  144. metadata +87 -35
  145. data/spec/asciidoctor/refs_dl_spec.rb +0 -864
@@ -0,0 +1,115 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Base
4
+ def html_extract_attributes(node)
5
+ {
6
+ script: node.attr("script"),
7
+ bodyfont: node.attr("body-font"),
8
+ headerfont: node.attr("header-font"),
9
+ monospacefont: node.attr("monospace-font"),
10
+ i18nyaml: node.attr("i18nyaml"),
11
+ scope: node.attr("scope"),
12
+ htmlstylesheet: node.attr("htmlstylesheet"),
13
+ htmlstylesheet_override: node.attr("htmlstylesheet-override"),
14
+ htmlcoverpage: node.attr("htmlcoverpage"),
15
+ htmlintropage: node.attr("htmlintropage"),
16
+ scripts: node.attr("scripts"),
17
+ scripts_override: node.attr("scripts-override"),
18
+ scripts_pdf: node.attr("scripts-pdf"),
19
+ datauriimage: node.attr("data-uri-image") != "false",
20
+ htmltoclevels: node.attr("htmltoclevels") || node.attr("toclevels"),
21
+ doctoclevels: node.attr("doctoclevels") || node.attr("toclevels"),
22
+ break_up_urls_in_tables: node.attr("break-up-urls-in-tables"),
23
+ suppressasciimathdup: node.attr("suppress-asciimath-dup"),
24
+ bare: node.attr("bare"),
25
+ sectionsplit: node.attr("sectionsplit"),
26
+ baseassetpath: node.attr("base-asset-path"),
27
+ aligncrosselements: node.attr("align-cross-elements"),
28
+ }
29
+ end
30
+
31
+ def html_converter(node)
32
+ IsoDoc::HtmlConvert.new(html_extract_attributes(node))
33
+ end
34
+
35
+ def pdf_converter(node)
36
+ return nil if node.attr("no-pdf")
37
+
38
+ IsoDoc::Standoc::PdfConvert.new(pdf_extract_attributes(node))
39
+ end
40
+
41
+ def doc_extract_attributes(node)
42
+ attrs = {
43
+ script: node.attr("script"),
44
+ bodyfont: node.attr("body-font"),
45
+ headerfont: node.attr("header-font"),
46
+ monospacefont: node.attr("monospace-font"),
47
+ i18nyaml: node.attr("i18nyaml"),
48
+ scope: node.attr("scope"),
49
+ wordstylesheet: node.attr("wordstylesheet"),
50
+ wordstylesheet_override: node.attr("wordstylesheet-override"),
51
+ standardstylesheet: node.attr("standardstylesheet"),
52
+ header: node.attr("header"),
53
+ wordcoverpage: node.attr("wordcoverpage"),
54
+ wordintropage: node.attr("wordintropage"),
55
+ ulstyle: node.attr("ulstyle"),
56
+ olstyle: node.attr("olstyle"),
57
+ htmltoclevels: node.attr("htmltoclevels") || node.attr("toclevels"),
58
+ doctoclevels: node.attr("doctoclevels") || node.attr("toclevels"),
59
+ break_up_urls_in_tables: node.attr("break-up-urls-in-tables"),
60
+ suppressasciimathdup: node.attr("suppress-asciimath-dup"),
61
+ bare: node.attr("bare"),
62
+ baseassetpath: node.attr("base-asset-path"),
63
+ aligncrosselements: node.attr("align-cross-elements"),
64
+ }
65
+
66
+ if fonts_manifest = node.attr(FONTS_MANIFEST)
67
+ attrs[IsoDoc::XslfoPdfConvert::MN2PDF_OPTIONS] = {
68
+ IsoDoc::XslfoPdfConvert::MN2PDF_FONT_MANIFEST => fonts_manifest,
69
+ }
70
+ end
71
+
72
+ attrs
73
+ end
74
+
75
+ def pdf_extract_attributes(node)
76
+ %w(pdf-encrypt pdf-encryption-length pdf-user-password
77
+ pdf-owner-password pdf-allow-copy-content pdf-allow-edit-content
78
+ pdf-allow-assemble-document pdf-allow-edit-annotations
79
+ pdf-allow-print pdf-allow-print-hq pdf-allow-fill-in-forms
80
+ pdf-allow-access-content pdf-encrypt-metadata)
81
+ .each_with_object({}) do |x, m|
82
+ m[x.gsub(/-/, "").to_i] = node.attr(x)
83
+ end
84
+ end
85
+
86
+ def doc_converter(node)
87
+ IsoDoc::WordConvert.new(doc_extract_attributes(node))
88
+ end
89
+
90
+ def presentation_xml_converter(node)
91
+ IsoDoc::PresentationXMLConvert.new(html_extract_attributes(node))
92
+ end
93
+
94
+ def default_fonts(node)
95
+ b = node.attr("body-font") ||
96
+ (node.attr("script") == "Hans" ? '"Source Han Sans",serif' : '"Cambria",serif')
97
+ h = node.attr("header-font") ||
98
+ (node.attr("script") == "Hans" ? '"Source Han Sans",sans-serif' : '"Cambria",serif')
99
+ m = node.attr("monospace-font") || '"Courier New",monospace'
100
+ "$bodyfont: #{b};\n$headerfont: #{h};\n$monospacefont: #{m};\n"
101
+ end
102
+
103
+ def outputs(node, ret)
104
+ File.open("#{@filename}.xml", "w:UTF-8") { |f| f.write(ret) }
105
+ presentation_xml_converter(node).convert("#{@filename}.xml")
106
+ html_converter(node).convert("#{@filename}.presentation.xml",
107
+ nil, false, "#{@filename}.html")
108
+ doc_converter(node).convert("#{@filename}.presentation.xml",
109
+ nil, false, "#{@filename}.doc")
110
+ pdf_converter(node)&.convert("#{@filename}.presentation.xml",
111
+ nil, false, "#{@filename}.pdf")
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,90 @@
1
+ require "htmlentities"
2
+ require "uri" if /^2\./.match?(RUBY_VERSION)
3
+ require "mime/types"
4
+ require "base64"
5
+
6
+ module Metanorma
7
+ module Standoc
8
+ module Blocks
9
+ def reqt_subpart(name)
10
+ %w(specification measurement-target verification import label title
11
+ description component subject inherit classification).include? name
12
+ end
13
+
14
+ def reqt_subpart_attrs(node, name)
15
+ klass = node.attr("class") || "component"
16
+ attr_code(keep_attrs(node)
17
+ .merge(exclude: node.option?("exclude"),
18
+ type: node.attr("type"),
19
+ class: name == "component" ? klass : nil))
20
+ end
21
+
22
+ def requirement_subpart(node)
23
+ name = node.role || node.attr("style")
24
+ noko do |xml|
25
+ xml.send name, **reqt_subpart_attrs(node, name) do |o|
26
+ o << node.content
27
+ end
28
+ end
29
+ end
30
+
31
+ def req_classif_parse(classif)
32
+ ret = []
33
+ HTMLEntities.new.decode(classif).split(/;\s*/).each do |c|
34
+ c1 = c.split(/:\s*/)
35
+ next unless c1.size == 2
36
+
37
+ c1[1].split(/,\s*/).each { |v| ret << [c1[0], v] }
38
+ end
39
+ ret
40
+ end
41
+
42
+ def requirement_classification(classif, out)
43
+ req_classif_parse(classif).each do |r|
44
+ out.classification do |c|
45
+ c.tag { |t| t << r[0] }
46
+ c.value { |v| v << r[1] }
47
+ end
48
+ end
49
+ end
50
+
51
+ def reqt_attrs(node)
52
+ attr_code(keep_attrs(node).merge(id_unnum_attrs(node)).merge(
53
+ id: Metanorma::Utils::anchor_or_uuid(node),
54
+ unnumbered: node.option?("unnumbered") ? "true" : nil,
55
+ number: node.attr("number"),
56
+ subsequence: node.attr("subsequence"),
57
+ obligation: node.attr("obligation"),
58
+ filename: node.attr("filename"),
59
+ type: node.attr("type"),
60
+ model: node.attr("model"),
61
+ ))
62
+ end
63
+
64
+ def requirement_elems(node, out)
65
+ node.title and out.title { |t| t << node.title }
66
+ a = node.attr("label") and out.label do |l|
67
+ l << a
68
+ end
69
+ a = node.attr("subject") and csv_split(a)&.each do |subj|
70
+ out.subject { |s| s << subj }
71
+ end
72
+ a = HTMLEntities.new.decode(node.attr("inherit")) and
73
+ csv_split(a)&.each do |i|
74
+ out.inherit { |inh| inh << i }
75
+ end
76
+ classif = node.attr("classification") and
77
+ requirement_classification(classif, out)
78
+ end
79
+
80
+ def requirement(node, obligation)
81
+ noko do |xml|
82
+ xml.send obligation, **reqt_attrs(node) do |ex|
83
+ requirement_elems(node, ex)
84
+ wrap_in_para(node, ex)
85
+ end
86
+ end.join("\n")
87
+ end
88
+ end
89
+ end
90
+ end
File without changes
@@ -0,0 +1,209 @@
1
+ require "uri" if /^2\./.match?(RUBY_VERSION)
2
+ require_relative "ref_sect"
3
+ require_relative "terms"
4
+
5
+ module Metanorma
6
+ module Standoc
7
+ module Section
8
+ @biblio = false
9
+ @term_def = false
10
+ @norm_ref = false
11
+
12
+ def sectiontype1(node)
13
+ node&.attr("heading")&.downcase ||
14
+ node.title.gsub(%r{<index>.*?</index>}m, "").gsub(/<[^>]+>/, "")
15
+ .strip.downcase
16
+ end
17
+
18
+ def sectiontype(node, level = true)
19
+ ret = sectiontype1(node)
20
+ ret1 = sectiontype_streamline(ret)
21
+ return ret1 if ret1 == "symbols and abbreviated terms"
22
+ return nil unless !level || node.level == 1
23
+ return nil if @seen_headers.include? ret
24
+
25
+ @seen_headers << ret
26
+ ret1
27
+ end
28
+
29
+ def sectiontype_streamline(ret)
30
+ case ret
31
+ when "terms and definitions",
32
+ "terms, definitions, symbols and abbreviated terms",
33
+ "terms, definitions, symbols and abbreviations",
34
+ "terms, definitions and symbols",
35
+ "terms, definitions and abbreviations",
36
+ "terms, definitions and abbreviated terms"
37
+ "terms and definitions"
38
+ when "symbols and abbreviated terms",
39
+ "symbols", "abbreviated terms", "abbreviations"
40
+ "symbols and abbreviated terms"
41
+ else
42
+ ret
43
+ end
44
+ end
45
+
46
+ def section_attributes(node)
47
+ ret = { id: Metanorma::Utils::anchor_or_uuid(node),
48
+ language: node.attributes["language"],
49
+ script: node.attributes["script"],
50
+ number: node.attributes["number"],
51
+ type: node.attributes["type"],
52
+ annex: (if (node.attr("style") == "appendix" ||
53
+ node.role == "appendix") &&
54
+ node.level == 1
55
+ true
56
+ end),
57
+ tag: node&.attr("tag"),
58
+ "multilingual-rendering": node&.attr("multilingual-rendering"),
59
+ preface: (if node.role == "preface" ||
60
+ node.attr("style") == "preface"
61
+ true
62
+ end) }
63
+ return ret unless node.attributes["change"]
64
+
65
+ ret.merge(change: node.attributes["change"],
66
+ path: node.attributes["path"],
67
+ path_end: node.attributes["path_end"],
68
+ title: node.attributes["title"])
69
+ end
70
+
71
+ def section(node)
72
+ a = section_attributes(node)
73
+ noko do |xml|
74
+ case sectiontype(node)
75
+ when "introduction" then introduction_parse(a, xml, node)
76
+ when "foreword" then foreword_parse(a, xml, node)
77
+ when "scope" then scope_parse(a, xml, node)
78
+ when "normative references" then norm_ref_parse(a, xml, node)
79
+ when "terms and definitions"
80
+ @term_def = true
81
+ term_def_parse(a, xml, node, true)
82
+ @term_def = false
83
+ when "symbols and abbreviated terms"
84
+ symbols_parse(symbols_attrs(node, a), xml, node)
85
+ when "acknowledgements"
86
+ acknowledgements_parse(a, xml, node)
87
+ when "bibliography"
88
+ bibliography_parse(a, xml, node)
89
+ else
90
+ if @term_def then term_def_subclause_parse(a, xml, node)
91
+ elsif @definitions then symbols_parse(a, xml, node)
92
+ elsif @norm_ref ||
93
+ (node.attr("style") == "bibliography" &&
94
+ sectiontype(node, false) == "normative references")
95
+ norm_ref_parse(a, xml, node)
96
+ elsif @biblio || node.attr("style") == "bibliography"
97
+ bibliography_parse(a, xml, node)
98
+ elsif node.attr("style") == "abstract"
99
+ abstract_parse(a, xml, node)
100
+ elsif node.attr("style") == "index"
101
+ indexsect_parse(a, xml, node)
102
+ elsif node.attr("style") == "appendix" && node.level == 1
103
+ annex_parse(a, xml, node)
104
+ else
105
+ clause_parse(a, xml, node)
106
+ end
107
+ end
108
+ end.join("\n")
109
+ end
110
+
111
+ def set_obligation(attrs, node)
112
+ attrs[:obligation] = if node.attributes.has_key?("obligation")
113
+ node.attr("obligation")
114
+ elsif node.parent.attributes.has_key?("obligation")
115
+ node.parent.attr("obligation")
116
+ else
117
+ "normative"
118
+ end
119
+ end
120
+
121
+ def preamble(node)
122
+ noko do |xml|
123
+ xml.foreword **attr_code(section_attributes(node)) do |xml_abstract|
124
+ xml_abstract.title do |t|
125
+ t << (node.blocks[0].title || @i18n.foreword)
126
+ end
127
+ content = node.content
128
+ xml_abstract << content
129
+ end
130
+ end.join("\n")
131
+ end
132
+
133
+ def indexsect_parse(attrs, xml, node)
134
+ xml.indexsect **attr_code(attrs) do |xml_section|
135
+ xml_section.title { |name| name << node.title }
136
+ xml_section << node.content
137
+ end
138
+ end
139
+
140
+ def abstract_parse(attrs, xml, node)
141
+ xml.abstract **attr_code(attrs) do |xml_section|
142
+ xml_section << node.content
143
+ end
144
+ end
145
+
146
+ def scope_parse(attrs, xml, node)
147
+ clause_parse(attrs.merge(type: "scope"), xml, node)
148
+ end
149
+
150
+ def clause_parse(attrs, xml, node)
151
+ attrs[:"inline-header"] = node.option? "inline-header"
152
+ attrs[:bibitem] = true if node.option? "bibitem"
153
+ attrs[:level] = node.attr("level")
154
+ set_obligation(attrs, node)
155
+ xml.send "clause", **attr_code(attrs) do |xml_section|
156
+ xml_section.title { |n| n << node.title } unless node.title.nil?
157
+ xml_section << node.content
158
+ end
159
+ end
160
+
161
+ def annex_parse(attrs, xml, node)
162
+ attrs[:"inline-header"] = node.option? "inline-header"
163
+ set_obligation(attrs, node)
164
+ xml.annex **attr_code(attrs) do |xml_section|
165
+ xml_section.title { |name| name << node.title }
166
+ xml_section << node.content
167
+ end
168
+ end
169
+
170
+ def introduction_parse(attrs, xml, node)
171
+ xml.introduction **attr_code(attrs) do |xml_section|
172
+ xml_section.title { |t| t << @i18n.introduction }
173
+ content = node.content
174
+ xml_section << content
175
+ end
176
+ end
177
+
178
+ def foreword_parse(attrs, xml, node)
179
+ xml.foreword **attr_code(attrs) do |xml_section|
180
+ xml_section.title { |t| t << node.title }
181
+ content = node.content
182
+ xml_section << content
183
+ end
184
+ end
185
+
186
+ def acknowledgements_parse(attrs, xml, node)
187
+ xml.acknowledgements **attr_code(attrs) do |xml_section|
188
+ xml_section.title { |t| (t << node.title) || @i18n.acknowledgements }
189
+ content = node.content
190
+ xml_section << content
191
+ end
192
+ end
193
+
194
+ def floating_title_attrs(node)
195
+ attr_code(id_attr(node).merge(align: node.attr("align"),
196
+ depth: node.level,
197
+ type: "floating-title"))
198
+ end
199
+
200
+ def floating_title(node)
201
+ noko do |xml|
202
+ xml.floating_title **floating_title_attrs(node) do |xml_t|
203
+ xml_t << node.title
204
+ end
205
+ end.join("\n")
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,85 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Table
4
+ def table_attrs(node)
5
+ keep_attrs(node)
6
+ .merge(id: Metanorma::Utils::anchor_or_uuid(node),
7
+ headerrows: node.attr("headerrows"),
8
+ unnumbered: node.option?("unnumbered") ? "true" : nil,
9
+ number: node.attr("number"),
10
+ subsequence: node.attr("subsequence"),
11
+ alt: node.attr("alt"),
12
+ summary: node.attr("summary"),
13
+ width: node.attr("width"))
14
+ end
15
+
16
+ def table(node)
17
+ @table_fn_number = "a"
18
+ noko do |xml|
19
+ xml.table **attr_code(table_attrs(node)) do |xml_table|
20
+ colgroup(node, xml_table)
21
+ table_name(node, xml_table)
22
+ %i(head body foot).reject do |tblsec|
23
+ node.rows[tblsec].empty?
24
+ end
25
+ table_head_body_and_foot node, xml_table
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def colgroup(node, xml_table)
33
+ return if node.option? "autowidth"
34
+
35
+ cols = node&.attr("cols")&.split(/,/) or return
36
+ return unless (cols.size > 1) && cols.all? { |c| /\d/.match(c) }
37
+
38
+ xml_table.colgroup do |cg|
39
+ node.columns.each do |col|
40
+ cg.col **{ width: "#{col.attr 'colpcwidth'}%" }
41
+ end
42
+ end
43
+ end
44
+
45
+ def table_name(node, xml_table)
46
+ if node.title?
47
+ xml_table.name do |n|
48
+ n << node.title
49
+ end
50
+ end
51
+ end
52
+
53
+ def table_cell1(cell, thd)
54
+ thd << if cell.style == :asciidoc
55
+ cell.content
56
+ else
57
+ cell.text
58
+ end
59
+ end
60
+
61
+ def table_cell(node, xml_tr, tblsec)
62
+ cell_attributes =
63
+ { id: node.id, colspan: node.colspan, valign: node.attr("valign"),
64
+ rowspan: node.rowspan, align: node.attr("halign") }
65
+ cell_tag = "td"
66
+ cell_tag = "th" if tblsec == :head || node.style == :header
67
+ xml_tr.send cell_tag, **attr_code(cell_attributes) do |thd|
68
+ table_cell1(node, thd)
69
+ end
70
+ end
71
+
72
+ def table_head_body_and_foot(node, xml)
73
+ %i(head body foot).reject { |s| node.rows[s].empty? }.each do |s|
74
+ xml.send "t#{s}" do |xml_tblsec|
75
+ node.rows[s].each do |row|
76
+ xml_tblsec.tr do |xml_tr|
77
+ row.each { |cell| table_cell(cell, xml_tr, s) }
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true.
2
+ require "metanorma/standoc/utils"
3
+
4
+
5
+ module Metanorma
6
+ module Standoc
7
+ # Intelligent term lookup xml modifier
8
+ class TermLookupCleanup
9
+ AUTOMATIC_GENERATED_ID_REGEXP = /\A_/.freeze
10
+ EXISTING_TERM_REGEXP = /\Aterm-/.freeze
11
+ EXISTING_SYMBOL_REGEXP = /\Asymbol-/.freeze
12
+
13
+ attr_reader :xmldoc, :termlookup, :log
14
+
15
+ def initialize(xmldoc, log)
16
+ @xmldoc = xmldoc
17
+ @log = log
18
+ @termlookup = { term: {}, symbol: {}, secondary2primary: {} }
19
+ @idhash = {}
20
+ end
21
+
22
+ def call
23
+ @idhash = populate_idhash
24
+ @termlookup = replace_automatic_generated_ids_terms
25
+ set_termxref_tags_target
26
+ concept_cleanup
27
+ related_cleanup
28
+ end
29
+
30
+ private
31
+
32
+ def concept_cleanup
33
+ xmldoc.xpath("//concept").each do |n|
34
+ n.delete("type")
35
+ refterm = n.at("./refterm") or next
36
+ p = @termlookup[:secondary2primary][refterm.text] and
37
+ refterm.children = p
38
+ end
39
+ end
40
+
41
+ def related_cleanup
42
+ xmldoc.xpath("//related").each do |n|
43
+ refterm = n.at("./refterm") or next
44
+ p = @termlookup[:secondary2primary][refterm.text] and
45
+ refterm.children = p
46
+ refterm.replace("<preferred><expression><name>#{refterm.children.to_xml}"\
47
+ "</name></expression></preferred>")
48
+ end
49
+ end
50
+
51
+ def populate_idhash
52
+ xmldoc.xpath("//*[@id]").each_with_object({}) do |n, mem|
53
+ next unless /^(term|symbol)-/.match?(n["id"])
54
+
55
+ mem[n["id"]] = true
56
+ end
57
+ end
58
+
59
+ def set_termxref_tags_target
60
+ xmldoc.xpath("//termxref").each do |node|
61
+ target = normalize_ref_id(node.text)
62
+ if termlookup[:term][target].nil? && termlookup[:symbol][target].nil?
63
+ remove_missing_ref(node, target)
64
+ next
65
+ end
66
+ x = node.at("../xrefrender") and modify_ref_node(x, target)
67
+ node.name = "refterm"
68
+ end
69
+ end
70
+
71
+ def remove_missing_ref(node, target)
72
+ if node.at("../concept[@type = 'symbol']")
73
+ remove_missing_ref_symbol(node, target)
74
+ else
75
+ remove_missing_ref_term(node, target)
76
+ end
77
+ end
78
+
79
+ def remove_missing_ref_term(node, target)
80
+ log.add("AsciiDoc Input", node,
81
+ %(Error: Term reference in `term[#{target}]` missing: \
82
+ "#{target}" is not defined in document))
83
+ node.name = "strong"
84
+ node&.at("../xrefrender")&.remove
85
+ display = node&.at("../renderterm")&.remove&.children
86
+ display = [] if display.nil? || display&.to_xml == node.text
87
+ d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
88
+ node.children = "term <tt>#{node.text}</tt>#{d} "\
89
+ "not resolved via ID <tt>#{target}</tt>"
90
+ end
91
+
92
+ def remove_missing_ref_symbol(node, target)
93
+ log.add("AsciiDoc Input", node,
94
+ %(Error: Symbol reference in `symbol[#{target}]` missing: \
95
+ "#{target}" is not defined in document))
96
+ node.name = "strong"
97
+ node&.at("../xrefrender")&.remove
98
+ display = node&.at("../renderterm")&.remove&.children
99
+ display = [] if display.nil? || display&.to_xml == node.text
100
+ d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
101
+ node.children = "symbol <tt>#{node.text}</tt>#{d} "\
102
+ "not resolved via ID <tt>#{target}</tt>"
103
+ end
104
+
105
+ def modify_ref_node(node, target)
106
+ node.name = "xref"
107
+ s = termlookup[:symbol][target]
108
+ t = termlookup[:term][target]
109
+ type = node.parent["type"]
110
+ if type == "term" || ((!type || node.parent.name == "related") && t)
111
+ node["target"] = t
112
+ elsif type == "symbol" ||
113
+ ((!type || node.parent.name == "related") && s)
114
+ node["target"] = s
115
+ end
116
+ end
117
+
118
+ def replace_automatic_generated_ids_terms
119
+ r = xmldoc.xpath("//term").each.with_object({}) do |n, res|
120
+ normalize_id_and_memorize(n, res, "./preferred//name",
121
+ "term")
122
+ end
123
+ s = xmldoc.xpath("//definitions//dt").each.with_object({}) do |n, res|
124
+ normalize_id_and_memorize(n, res, ".", "symbol")
125
+ end
126
+ { term: r, symbol: s, secondary2primary: pref_secondary2primary }
127
+ end
128
+
129
+ def pref_secondary2primary
130
+ xmldoc.xpath("//term").each.with_object({}) do |n, res|
131
+ n.xpath("./preferred//name").each_with_index do |p, i|
132
+ i.zero? and term = p.text
133
+ i.positive? and res[p.text] = term
134
+ end
135
+ end
136
+ end
137
+
138
+ def normalize_id_and_memorize(node, res_table, text_selector, prefix)
139
+ normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
140
+ memorize_other_pref_terms(node, res_table, text_selector)
141
+ end
142
+
143
+ def normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
144
+ term_text = normalize_ref_id(node.at(text_selector).text)
145
+ unless AUTOMATIC_GENERATED_ID_REGEXP.match(node["id"]).nil? &&
146
+ !node["id"].nil?
147
+ id = unique_text_id(term_text, prefix)
148
+ node["id"] = id
149
+ @idhash[id] = true
150
+ end
151
+ res_table[term_text] = node["id"]
152
+ end
153
+
154
+ def memorize_other_pref_terms(node, res_table, text_selector)
155
+ node.xpath(text_selector).each_with_index do |p, i|
156
+ next unless i.positive?
157
+
158
+ res_table[normalize_ref_id(p.text)] = node["id"]
159
+ end
160
+ end
161
+
162
+ def normalize_ref_id(text)
163
+ Metanorma::Utils::to_ncname(text.downcase.gsub(/[[:space:]]/, "-"))
164
+ end
165
+
166
+ def unique_text_id(text, prefix)
167
+ unless @idhash["#{prefix}-#{text}"]
168
+ return "#{prefix}-#{text}"
169
+ end
170
+
171
+ (1..Float::INFINITY).lazy.each do |index|
172
+ unless @idhash["#{prefix}-#{text}-#{index}"]
173
+ break("#{prefix}-#{text}-#{index}")
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end