metanorma-standoc 3.0.6 → 3.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 982e6533abd03671b4c76ba32204915843cdc0c644b06ec0e8a34798a5d50d1d
4
- data.tar.gz: c12cb3a77574fef2d8aa219dae15470ed14ee50e3d7ca55c527f54dc73242a4e
3
+ metadata.gz: ab57258611b63bcabb64f17d1fe44bf74d8169ffd707ce96db6fa4f074a0f007
4
+ data.tar.gz: 3c39749483d8687dbcaea874d3d1e37a90b61e54d45fba10346025eef2378a7a
5
5
  SHA512:
6
- metadata.gz: eec8efe148aeef9f65007f135aed6ad0a91c7c8c0a94749d75c1946d53e0877a3c8840c32679e20d01048fee434d35949453dcfd7335417f049f225eab31afdf
7
- data.tar.gz: 8e2dc0a69568e2f460dcf39fa081756ed0d5610b00c02516c02ffd14bb84682a03dc07a29dc261651f65576175c36561d53a80cea8889c9519b8053c3051c612
6
+ metadata.gz: c0cff4afac83b0a64838f23be4895f3dc6b5f02d986fd6d08706cb2dd8fc03ef2f5a446bb06e81c3a5a3d30a1a086a3e703af6d074f8dc14f0a93d524407334a
7
+ data.tar.gz: 37ebfa958164eca83ddd835efbb50da1d36b7fcba0dc0c350abbf0da3833a132bfc9680c036367ff288c9163230e5c0a7852cded007c9ac50d73fe2117b3bade
@@ -51,7 +51,7 @@ module Metanorma
51
51
  case: %w(capital lowercase).detect { |x| attrs.key?(x) },
52
52
  label: attrs["label"],
53
53
  style: attrs["style"] || @xrefstyle,
54
- droploc: attrs.key?("droploc") ? true : nil,
54
+ droploc: attrs.key?("droploc") || nil,
55
55
  text: }.compact
56
56
  end
57
57
 
@@ -84,7 +84,8 @@ module Metanorma
84
84
  end
85
85
 
86
86
  def boilerplate_file(_xmldoc)
87
- File.join(@libdir, "boilerplate.xml")
87
+ ret = File.join(@libdir, "boilerplate.xml")
88
+ File.exist?(ret) ? ret : ""
88
89
  end
89
90
 
90
91
  def boilerplate(xml, conv)
@@ -92,14 +93,23 @@ module Metanorma
92
93
  xml.at("//metanorma-extension/semantic-metadata/" \
93
94
  "headless[text() = 'true']") and return nil
94
95
  file = boilerplate_file(xml)
95
- @boilerplateauthority and
96
+ file2 = @boilerplateauthority
97
+ @boilerplateauthority &&
98
+ !(Pathname.new @boilerplateauthority).absolute? and
96
99
  file2 = File.join(@localdir, @boilerplateauthority)
97
100
  resolve_boilerplate_files(process_boilerplate_file(file, conv),
98
101
  process_boilerplate_file(file2, conv))
99
102
  end
100
103
 
101
104
  def process_boilerplate_file(filename, conv)
102
- (!filename.nil? and File.exist?(filename)) or return
105
+ filename.nil? || filename.empty? and return
106
+ filename = filename.strip
107
+ unless File.exist?(filename)
108
+ msg = "Specified boilerplate file does not exist: #{filename}"
109
+ @log.add("Include", nil, msg, severity: 0)
110
+ return
111
+ end
112
+
103
113
  b = conv.populate_template(boilerplate_read(filename), nil)
104
114
  boilerplate_file_convert(b)
105
115
  end
@@ -5,12 +5,13 @@ module Metanorma
5
5
  module Cleanup
6
6
  def make_preface(xml, sect)
7
7
  if xml.at("//foreword | //introduction | //acknowledgements | " \
8
- "//*[@preface]")
8
+ "//executivesummary | //*[@preface]")
9
9
  preface = sect.add_previous_sibling("<preface/>").first
10
10
  f = xml.at("//foreword") and to_preface(preface, f)
11
11
  f = xml.at("//introduction") and to_preface(preface, f)
12
12
  move_clauses_into_preface(xml, preface)
13
13
  f = xml.at("//acknowledgements") and to_preface(preface, f)
14
+ f = xml.at("//executivesummary") and to_preface(preface, f)
14
15
  end
15
16
  make_abstract(xml, sect)
16
17
  end
@@ -148,7 +149,8 @@ module Metanorma
148
149
 
149
150
  def obligations_cleanup_info(xml)
150
151
  xml.xpath("//foreword | //introduction | //acknowledgements | " \
151
- "//references | //preface//clause").each do |r|
152
+ "//executivesummary | //references | //preface//clause")
153
+ .each do |r|
152
154
  r["obligation"] = "informative"
153
155
  end
154
156
  end
@@ -42,6 +42,7 @@ module Metanorma
42
42
  replace_title(xml, "//foreword", @i18n&.foreword)
43
43
  replace_title(xml, "//introduction", @i18n&.introduction)
44
44
  replace_title(xml, "//acknowledgements", @i18n&.acknowledgements)
45
+ replace_title(xml, "//executivesummary", @i18n&.executivesummary)
45
46
  end
46
47
 
47
48
  def section_names_refs_cleanup(xml)
@@ -32,16 +32,16 @@ module Metanorma
32
32
  e[:skip] and next
33
33
  lines = lines_strip_textspan(e, block[i + 1])
34
34
  out = Metanorma::Utils.line_sanitise(lines)
35
- e[:last] or out.pop
35
+ # e[:last] or out.pop
36
36
  e[:elem].replace(out.join)
37
37
  end
38
38
  end
39
39
 
40
- def lines_strip_textspan(span, nextspan)
40
+ def lines_strip_textspan(span, _nextspan)
41
41
  lines = span[:text].lines[0..-2].map(&:rstrip) <<
42
42
  span[:text].lines[-1]&.sub(/\n$/, "")
43
43
  # no final line rstrip: can be space linking to next line
44
- span[:last] or lines << nextspan[:text].lines.first # next token context
44
+ # span[:last] or lines << nextspan[:text].lines.first # next token context
45
45
  lines
46
46
  end
47
47
 
@@ -137,11 +137,12 @@ module Metanorma
137
137
 
138
138
  def block?(elem)
139
139
  %w(title name variant-title clause figure annex example introduction
140
- foreword acknowledgements note li th td dt dd p quote label
141
- abstract preferred admitted related deprecates field-of-application
142
- usage-info expression pronunciation grammar-value domain
143
- definition termnote termexample modification description
144
- newcontent floating-title tab review admonition annotation).include? elem.name
140
+ foreword acknowledgements executivesummary note li th td dt dd p
141
+ quote label abstract preferred admitted related deprecates
142
+ field-of-application usage-info expression pronunciation
143
+ grammar-value domain definition termnote termexample modification
144
+ description newcontent floating-title tab review admonition
145
+ annotation).include? elem.name
145
146
  end
146
147
 
147
148
  def empty_tag_with_text_content?(elem)
@@ -39,6 +39,7 @@ module Metanorma
39
39
  preprocessor Metanorma::Standoc::Datamodel::DiagramPreprocessor
40
40
  preprocessor Metanorma::Plugin::Datastruct::Json2TextPreprocessor
41
41
  preprocessor Metanorma::Plugin::Datastruct::Yaml2TextPreprocessor
42
+ preprocessor Metanorma::Plugin::Datastruct::Data2TextPreprocessor
42
43
  preprocessor Metanorma::Plugin::Glossarist::DatasetPreprocessor
43
44
  preprocessor Metanorma::Standoc::NamedEscapePreprocessor
44
45
  inline_macro Metanorma::Standoc::PreferredTermInlineMacro
@@ -14,16 +14,24 @@ module Metanorma
14
14
  end
15
15
 
16
16
  def organization(org, orgname, node = nil, default_org = nil, attrs = {})
17
- abbrevs = org_abbrev
18
- n = abbrevs.invert[orgname] and orgname = n
17
+ orgname, abbr = org_name_and_abbrev(attrs, orgname)
19
18
  org.name orgname
20
19
  default_org && (a = node&.attr("subdivision")) && !attrs[:subdiv] and
21
20
  subdivision(a, node&.attr("subdivision-abbr"), org)
22
21
  a = attrs[:subdiv] and subdivision(a, nil, org)
23
- abbr = org_abbrev[orgname]
24
22
  abbr and org.abbreviation abbr
25
23
  end
26
24
 
25
+ def org_name_and_abbrev(org, orgname)
26
+ if org[:abbrev]
27
+ [orgname, org[:abbrev]]
28
+ else
29
+ abbrevs = org_abbrev
30
+ n = abbrevs.invert[orgname] and orgname = n
31
+ [orgname, org_abbrev[orgname]]
32
+ end
33
+ end
34
+
27
35
  def subdivision(attr, abbr, org)
28
36
  abbrs = csv_split(abbr) || []
29
37
  subdivs = csv_split(attr, ";")
@@ -50,7 +58,7 @@ module Metanorma
50
58
  list.empty? and return
51
59
  org.subdivision **attr_code(type: list[0][:type]) do |s|
52
60
  s.name { |n| n << list[0][:value] }
53
- subdiv_build(list[1..-1], s)
61
+ subdiv_build(list[1..], s)
54
62
  a = list[0][:abbr] and s.abbreviation { |n| n << a }
55
63
  end
56
64
  end
@@ -180,6 +188,7 @@ module Metanorma
180
188
 
181
189
  def extract_org_attrs_complex(node, opts, source, suffix)
182
190
  { name: node.attr(source + suffix),
191
+ abbrev: node.attr("#{source}_abbr#{suffix}"),
183
192
  role: opts[:role], desc: opts[:desc],
184
193
  subdiv: node.attr("#{source}_subdivision#{suffix}"),
185
194
  logo: node.attr("#{source}_logo#{suffix}") }.compact
@@ -77,7 +77,9 @@ module Metanorma
77
77
  end
78
78
 
79
79
  def highlight_parse(text, xml)
80
- xml << text
80
+ xml.span **{ class: "fmt-hi" } do |s|
81
+ s << text
82
+ end
81
83
  end
82
84
 
83
85
  def inline_quoted(node)
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
3
- <!-- VERSION v2.0.3 -->
3
+ <!-- VERSION v2.0.4 -->
4
4
 
5
5
  <!--
6
6
  ALERT: cannot have root comments, because of https://github.com/metanorma/metanorma/issues/437
@@ -1328,6 +1328,7 @@ numbers</a:documentation>
1328
1328
  <ref name="foreword"/>
1329
1329
  <ref name="introduction"/>
1330
1330
  <ref name="acknowledgements"/>
1331
+ <ref name="executivesummary"/>
1331
1332
  </choice>
1332
1333
  </oneOrMore>
1333
1334
  </element>
@@ -1351,6 +1352,11 @@ numbers</a:documentation>
1351
1352
  <ref name="Content-Section"/>
1352
1353
  </element>
1353
1354
  </define>
1355
+ <define name="executivesummary">
1356
+ <element name="executivesummary">
1357
+ <ref name="Content-Section"/>
1358
+ </element>
1359
+ </define>
1354
1360
  <define name="indexsect">
1355
1361
  <element name="indexsect">
1356
1362
  <ref name="Content-Section"/>
@@ -1576,6 +1582,15 @@ used in document amendments</a:documentation>
1576
1582
  <define name="annex">
1577
1583
  <element name="annex">
1578
1584
  <ref name="Annex-Section"/>
1585
+ <zeroOrMore>
1586
+ <ref name="annex-appendix"/>
1587
+ </zeroOrMore>
1588
+ </element>
1589
+ </define>
1590
+ <define name="annex-appendix">
1591
+ <a:documentation>Appendix, distinct subclause type for annexes (annex to annex, rather than subclause to annex)</a:documentation>
1592
+ <element name="appendix">
1593
+ <ref name="Clause-Section"/>
1579
1594
  </element>
1580
1595
  </define>
1581
1596
  <define name="terms">
@@ -208,7 +208,7 @@ module Metanorma
208
208
  fmt = format(out, target)
209
209
  fmt.empty? and fmt = "default"
210
210
  fmt = %( number-format="#{fmt}")
211
- <<~OUTPUT
211
+ <<~OUTPUT.strip
212
212
  <stem type="MathML"#{fmt}><math xmlns='#{MATHML_NS}'><mn>#{number(target)}</mn></math></stem>
213
213
  OUTPUT
214
214
  end
@@ -1,6 +1,7 @@
1
1
  require "uri" if /^2\./.match?(RUBY_VERSION)
2
2
  require_relative "ref_sect"
3
3
  require_relative "terms"
4
+ require_relative "sectiontype"
4
5
 
5
6
  module Metanorma
6
7
  module Standoc
@@ -9,77 +10,6 @@ module Metanorma
9
10
  @term_def = false
10
11
  @norm_ref = false
11
12
 
12
- def sectiontype1(node)
13
- node.attr("style") == "abstract" and return "abstract"
14
- node.attr("heading")&.downcase ||
15
- node.title
16
- .gsub(%r{<index>.*?</index>}m, "")
17
- .gsub(%r{<fn[^<>]*>.*?</fn>}m, "")
18
- .gsub(/<[^<>]+>/, "")
19
- .strip.downcase.sub(/\.$/, "")
20
- end
21
-
22
- def sectiontype(node, level = true)
23
- ret = sectiontype1(node)
24
- ret1 = preface_main_filter(sectiontype_streamline(ret), node)
25
- ret1 == "symbols and abbreviated terms" and return ret1
26
- !level || node.level == 1 || node.attr("heading") or return nil
27
- !node.attr("heading") && @seen_headers.include?(ret) and return nil
28
- @seen_headers << ret unless ret1.nil?
29
- @seen_headers_canonical << ret1 unless ret1.nil?
30
- ret1
31
- end
32
-
33
- def sectiontype_streamline(ret)
34
- case ret
35
- when "terms and definitions",
36
- "terms, definitions, symbols and abbreviated terms",
37
- "terms, definitions, symbols and abbreviations",
38
- "terms, definitions and symbols",
39
- "terms, definitions and abbreviations",
40
- "terms, definitions and abbreviated terms"
41
- "terms and definitions"
42
- when "symbols and abbreviated terms",
43
- "symbols", "abbreviated terms", "abbreviations",
44
- "symbols and abbreviations"
45
- "symbols and abbreviated terms"
46
- when "acknowledgements", "acknowledgments"
47
- "acknowledgements"
48
- else
49
- ret
50
- end
51
- end
52
-
53
- PREFACE_CLAUSE_NAMES =
54
- %w(abstract foreword introduction metanorma-extension termdocsource
55
- misc-container metanorma-extension acknowledgements).freeze
56
-
57
- MAIN_CLAUSE_NAMES =
58
- ["normative references", "terms and definitions", "scope",
59
- "symbols and abbreviated terms", "clause", "bibliography"].freeze
60
-
61
- def role_style(node, value)
62
- node.role == value || node.attr("style") == value
63
- end
64
-
65
- def start_main_section(ret, node)
66
- role_style(node, "preface") and return
67
- @preface = false if self.class::MAIN_CLAUSE_NAMES.include?(ret)
68
- @preface = false if self.class::PREFACE_CLAUSE_NAMES
69
- .intersection(@seen_headers_canonical + [ret]).empty?
70
- end
71
-
72
- def preface_main_filter(ret, node)
73
- start_main_section(ret, node)
74
- if @preface
75
- self.class::MAIN_CLAUSE_NAMES.include?(ret) and return nil
76
- else
77
- self.class::PREFACE_CLAUSE_NAMES.include?(ret) and return nil
78
- end
79
-
80
- ret
81
- end
82
-
83
13
  def section_attributes(node)
84
14
  ret =
85
15
  { id: Metanorma::Utils::anchor_or_uuid(node),
@@ -120,6 +50,8 @@ module Metanorma
120
50
  symbols_parse(symbols_attrs(node, a), xml, node)
121
51
  when "acknowledgements"
122
52
  acknowledgements_parse(a, xml, node)
53
+ when "executivesummary"
54
+ executivesummary_parse(a, xml, node)
123
55
  when "bibliography"
124
56
  bibliography_parse(a, xml, node)
125
57
  else
@@ -188,47 +120,74 @@ module Metanorma
188
120
  clause_parse(attrs.merge(type: "scope"), xml, node)
189
121
  end
190
122
 
191
- def clause_parse(attrs, xml, node)
123
+ def clause_attrs_preprocess(attrs, node)
192
124
  attrs[:"inline-header"] = node.option? "inline-header"
193
125
  attrs[:bibitem] = true if node.option? "bibitem"
194
126
  attrs[:level] = node.attr("level")
195
127
  set_obligation(attrs, node)
128
+ end
129
+
130
+ def clause_parse(attrs, xml, node)
131
+ clause_attrs_preprocess(attrs, node)
132
+ node.option?("appendix") && support_appendix?(node) and
133
+ return appendix_parse(attrs, xml, node)
196
134
  xml.send :clause, **attr_code(attrs) do |xml_section|
197
135
  xml_section.title { |n| n << node.title } unless node.title.nil?
198
136
  xml_section << node.content
199
137
  end
200
138
  end
201
139
 
202
- def annex_parse(attrs, xml, node)
140
+ def annex_attrs_preprocess(attrs, node)
203
141
  attrs[:"inline-header"] = node.option? "inline-header"
204
142
  set_obligation(attrs, node)
143
+ end
144
+
145
+ def annex_parse(attrs, xml, node)
146
+ annex_attrs_preprocess(attrs, node)
205
147
  xml.annex **attr_code(attrs) do |xml_section|
206
148
  xml_section.title { |name| name << node.title }
207
149
  xml_section << node.content
208
150
  end
209
151
  end
210
152
 
153
+ def support_appendix?(_node)
154
+ false
155
+ end
156
+
157
+ def appendix_parse(attrs, xml, node)
158
+ attrs[:"inline-header"] = node.option? "inline-header"
159
+ set_obligation(attrs, node)
160
+ xml.appendix **attr_code(attrs) do |xml_section|
161
+ xml_section.title { |name| name << node.title }
162
+ xml_section << node.content
163
+ end
164
+ end
165
+
211
166
  def introduction_parse(attrs, xml, node)
212
167
  xml.introduction **attr_code(attrs) do |xml_section|
213
168
  xml_section.title { |t| t << @i18n.introduction }
214
- content = node.content
215
- xml_section << content
169
+ xml_section << node.content
216
170
  end
217
171
  end
218
172
 
219
173
  def foreword_parse(attrs, xml, node)
220
174
  xml.foreword **attr_code(attrs) do |xml_section|
221
175
  xml_section.title { |t| t << node.title }
222
- content = node.content
223
- xml_section << content
176
+ xml_section << node.content
224
177
  end
225
178
  end
226
179
 
227
180
  def acknowledgements_parse(attrs, xml, node)
228
181
  xml.acknowledgements **attr_code(attrs) do |xml_section|
229
182
  xml_section.title { |t| (t << node.title) || @i18n.acknowledgements }
230
- content = node.content
231
- xml_section << content
183
+ xml_section << node.content
184
+ end
185
+ end
186
+
187
+ def executivesummary_parse(attrs, xml, node)
188
+ xml.executivesummary **attr_code(attrs) do |xml_section|
189
+ xml_section.title { |t| (t << node.title) || @i18n.executivesummary }
190
+ xml_section << node.content
232
191
  end
233
192
  end
234
193
 
@@ -0,0 +1,76 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Section
4
+ def sectiontype1(node)
5
+ node.attr("style") == "abstract" and return "abstract"
6
+ node.attr("heading")&.downcase ||
7
+ node.title
8
+ .gsub(%r{<index>.*?</index>}m, "")
9
+ .gsub(%r{<fn[^<>]*>.*?</fn>}m, "")
10
+ .gsub(/<[^<>]+>/, "")
11
+ .strip.downcase.sub(/\.$/, "")
12
+ end
13
+
14
+ def sectiontype(node, level = true)
15
+ ret = sectiontype1(node)
16
+ ret1 = preface_main_filter(sectiontype_streamline(ret), node)
17
+ ret1 == "symbols and abbreviated terms" and return ret1
18
+ !level || node.level == 1 || node.attr("heading") or return nil
19
+ !node.attr("heading") && @seen_headers.include?(ret) and return nil
20
+ @seen_headers << ret unless ret1.nil?
21
+ @seen_headers_canonical << ret1 unless ret1.nil?
22
+ ret1
23
+ end
24
+
25
+ def sectiontype_streamline(ret)
26
+ case ret
27
+ when "terms and definitions",
28
+ "terms, definitions, symbols and abbreviated terms",
29
+ "terms, definitions, symbols and abbreviations",
30
+ "terms, definitions and symbols",
31
+ "terms, definitions and abbreviations",
32
+ "terms, definitions and abbreviated terms"
33
+ "terms and definitions"
34
+ when "symbols and abbreviated terms",
35
+ "symbols", "abbreviated terms", "abbreviations",
36
+ "symbols and abbreviations"
37
+ "symbols and abbreviated terms"
38
+ when "acknowledgements", "acknowledgments"
39
+ "acknowledgements"
40
+ when "executive summary", "executive-summary", "executive_summary"
41
+ "executivesummary"
42
+ else
43
+ ret
44
+ end
45
+ end
46
+
47
+ PREFACE_CLAUSE_NAMES =
48
+ %w(abstract foreword introduction metanorma-extension termdocsource
49
+ misc-container metanorma-extension acknowledgements executivesummary)
50
+ .freeze
51
+
52
+ MAIN_CLAUSE_NAMES =
53
+ ["normative references", "terms and definitions", "scope",
54
+ "symbols and abbreviated terms", "clause", "bibliography"].freeze
55
+
56
+ def role_style(node, value)
57
+ node.role == value || node.attr("style") == value
58
+ end
59
+
60
+ def start_main_section(ret, node)
61
+ role_style(node, "preface") and return
62
+ @preface = false if self.class::MAIN_CLAUSE_NAMES.include?(ret)
63
+ @preface = false if self.class::PREFACE_CLAUSE_NAMES
64
+ .intersection(@seen_headers_canonical + [ret]).empty?
65
+ end
66
+
67
+ def preface_main_filter(ret, node)
68
+ start_main_section(ret, node)
69
+ @preface && self.class::MAIN_CLAUSE_NAMES.include?(ret) and return nil
70
+ !@preface && self.class::PREFACE_CLAUSE_NAMES.include?(ret) and
71
+ return nil
72
+ ret
73
+ end
74
+ end
75
+ end
76
+ end
@@ -119,7 +119,7 @@ module Metanorma
119
119
  end
120
120
 
121
121
  SECTION_CONTAINERS =
122
- %w(foreword introduction acknowledgements abstract
122
+ %w(foreword introduction acknowledgements executivesummary abstract
123
123
  clause references terms definitions annex appendix indexsect
124
124
  executivesummary).freeze
125
125
 
@@ -163,27 +163,66 @@ module Metanorma
163
163
  @log.add("Anchors", elem,
164
164
  "Anchor #{elem['id']} has already been " \
165
165
  "used at line #{@doc_ids[elem['id']]}", severity: 0)
166
+ else
167
+ @doc_ids[elem["id"]] = elem.line
166
168
  end
167
- @doc_ids[elem["id"]] = elem.line
168
169
  end
169
170
 
170
171
  def repeat_id_validate(doc)
171
- @doc_ids = {}
172
+ @doc_ids = {} # hash of all ids in document to line number
173
+ @doc_id_seq = [] # ordered list of all ids in document
172
174
  doc.xpath("//*[@id]").each do |x|
175
+ @doc_id_seq << x["id"]
173
176
  repeat_id_validate1(x)
174
177
  end
178
+ @doc_id_seq.sort!
175
179
  end
176
180
 
177
- # manually check for xref/@target, xref/@to integrity
181
+ # Retrieve IDs between two nominated values
182
+ # (exclusive of start_id AND exclusive of end_id)
183
+ def get_ids_between(start_id, end_id)
184
+ start_index = @doc_id_seq.bsearch_index { |id| id > start_id }
185
+ end_index = @doc_id_seq.bsearch_index { |id| id >= end_id }
186
+ # start_id is greater than or equal to all elements
187
+ start_index.nil? and return []
188
+ # end_id is greater than all elements
189
+ end_index.nil? and end_index = @doc_id_seq.length
190
+ start_index >= end_index and return []
191
+ @doc_id_seq[start_index...end_index]
192
+ end
193
+
194
+ # manually check for xref/@target et sim. integrity
178
195
  def xref_validate(doc)
179
- @doc_xrefs = doc.xpath("//xref/@target | //xref/@to | //index/@to")
180
- .each_with_object({}) do |x, m|
181
- m[x.text] = x
182
- @doc_ids[x.text] and next
183
- @log.add("Anchors", x.parent,
184
- "Crossreference target #{x} is undefined", severity: 1)
196
+ xref_validate_exists(doc)
197
+ xref_range_record(doc)
198
+ end
199
+
200
+ def xref_validate_exists(doc)
201
+ @doc_xrefs =
202
+ doc.xpath("//xref/@target | //xref//location/@target | //index/@to")
203
+ .each_with_object({}) do |x, m|
204
+ m[x.text] = x.parent
205
+ @doc_ids[x.text] and next
206
+ @log.add("Anchors", x.parent,
207
+ "Crossreference target #{x} is undefined", severity: 1)
208
+ end
209
+ end
210
+
211
+ # If there is an xref range, record the IDs between the two targets
212
+ def xref_range_record(doc)
213
+ doc.xpath("//xref//location[@connective = 'to']").each do |to|
214
+ process_range_location(to)
185
215
  end
186
216
  end
217
+
218
+ def process_range_location(to_location)
219
+ # Get the preceding location element if it exists
220
+ from = to_location.previous_element
221
+ from && from.name == "location" or return
222
+ from["target"] && to_location["target"] or return
223
+ get_ids_between(from["target"], to_location["target"])
224
+ .each { |id| @doc_xrefs[id] = from }
225
+ end
187
226
  end
188
227
  end
189
228
  end
@@ -46,12 +46,11 @@ module Metanorma
46
46
 
47
47
  def hanging_para_style(root)
48
48
  root.xpath("//clause | //annex | //foreword | //introduction | " \
49
- "//acknowledgements").each do |c|
50
- next unless c.at("./clause")
51
- next if c.elements.reject do |n|
52
- %w(clause title).include? n.name
53
- end.empty?
54
-
49
+ "//acknowledgements | //executivesummary").each do |c|
50
+ c.at("./clause") or next
51
+ c.elements.reject do |n|
52
+ %w(clause title).include? n.name
53
+ end.empty? and next
55
54
  style_warning(c, "Hanging paragraph in clause")
56
55
  end
57
56
  end
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "3.0.6".freeze
22
+ VERSION = "3.0.7".freeze
23
23
  end
24
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-standoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.6
4
+ version: 3.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-15 00:00:00.000000000 Z
11
+ date: 2025-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -560,6 +560,7 @@ files:
560
560
  - lib/metanorma/standoc/reqt.rb
561
561
  - lib/metanorma/standoc/reqt.rng
562
562
  - lib/metanorma/standoc/section.rb
563
+ - lib/metanorma/standoc/sectiontype.rb
563
564
  - lib/metanorma/standoc/spans_to_bibitem.rb
564
565
  - lib/metanorma/standoc/spans_to_bibitem_preprocessing.rb
565
566
  - lib/metanorma/standoc/table.rb