metanorma-bsi 0.0.1

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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.hound.yml +3 -0
  4. data/.rubocop.yml +14 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +25 -0
  8. data/README.adoc +199 -0
  9. data/Rakefile +8 -0
  10. data/bin/rspec +18 -0
  11. data/lib/asciidoctor/bsi/basicdoc.rng +1131 -0
  12. data/lib/asciidoctor/bsi/biblio.rng +1235 -0
  13. data/lib/asciidoctor/bsi/bsi.rng +120 -0
  14. data/lib/asciidoctor/bsi/bsi_intro_en.xml +105 -0
  15. data/lib/asciidoctor/bsi/cleanup.rb +78 -0
  16. data/lib/asciidoctor/bsi/cleanup_ref.rb +183 -0
  17. data/lib/asciidoctor/bsi/converter.rb +83 -0
  18. data/lib/asciidoctor/bsi/front.rb +67 -0
  19. data/lib/asciidoctor/bsi/isodoc.rng +1870 -0
  20. data/lib/asciidoctor/bsi/isostandard.rng +477 -0
  21. data/lib/asciidoctor/bsi/reqt.rng +194 -0
  22. data/lib/asciidoctor/bsi/validate.rb +224 -0
  23. data/lib/asciidoctor/bsi/validate_list.rb +72 -0
  24. data/lib/asciidoctor/bsi/validate_requirement.rb +163 -0
  25. data/lib/isodoc/bsi/base_convert.rb +91 -0
  26. data/lib/isodoc/bsi/bsi.international-standard.xsl +6540 -0
  27. data/lib/isodoc/bsi/html/html_bsi_intro.html +8 -0
  28. data/lib/isodoc/bsi/html/html_bsi_titlepage.html +50 -0
  29. data/lib/isodoc/bsi/html/htmlstyle.css +968 -0
  30. data/lib/isodoc/bsi/html/htmlstyle.scss +699 -0
  31. data/lib/isodoc/bsi/html_convert.rb +56 -0
  32. data/lib/isodoc/bsi/i18n-en.yaml +56 -0
  33. data/lib/isodoc/bsi/i18n.rb +15 -0
  34. data/lib/isodoc/bsi/init.rb +24 -0
  35. data/lib/isodoc/bsi/metadata.rb +33 -0
  36. data/lib/isodoc/bsi/pdf_convert.rb +17 -0
  37. data/lib/isodoc/bsi/presentation_xml_convert.rb +72 -0
  38. data/lib/isodoc/bsi/sts_convert.rb +30 -0
  39. data/lib/isodoc/bsi/xref.rb +134 -0
  40. data/lib/metanorma-bsi.rb +15 -0
  41. data/lib/metanorma/bsi.rb +6 -0
  42. data/lib/metanorma/bsi/processor.rb +51 -0
  43. data/lib/metanorma/bsi/version.rb +6 -0
  44. data/metanorma-bsi.gemspec +47 -0
  45. data/spec/asciidoctor/base_spec.rb +778 -0
  46. data/spec/asciidoctor/blocks_spec.rb +553 -0
  47. data/spec/asciidoctor/cleanup_spec.rb +547 -0
  48. data/spec/asciidoctor/inline_spec.rb +176 -0
  49. data/spec/asciidoctor/lists_spec.rb +194 -0
  50. data/spec/asciidoctor/refs_spec.rb +318 -0
  51. data/spec/asciidoctor/section_spec.rb +382 -0
  52. data/spec/asciidoctor/validate_spec.rb +858 -0
  53. data/spec/assets/header.html +7 -0
  54. data/spec/assets/html.css +2 -0
  55. data/spec/assets/iso.xml +71 -0
  56. data/spec/assets/rice_image1.png +0 -0
  57. data/spec/assets/word.css +2 -0
  58. data/spec/assets/wordintro.html +4 -0
  59. data/spec/assets/xref_error.adoc +7 -0
  60. data/spec/isodoc/blocks_spec.rb +259 -0
  61. data/spec/isodoc/i18n_spec.rb +442 -0
  62. data/spec/isodoc/inline_spec.rb +287 -0
  63. data/spec/isodoc/iso_spec.rb +116 -0
  64. data/spec/isodoc/metadata_spec.rb +262 -0
  65. data/spec/isodoc/postproc_spec.rb +137 -0
  66. data/spec/isodoc/ref_spec.rb +376 -0
  67. data/spec/isodoc/section_spec.rb +467 -0
  68. data/spec/isodoc/terms_spec.rb +246 -0
  69. data/spec/isodoc/xref_spec.rb +1730 -0
  70. data/spec/metanorma/processor_spec.rb +76 -0
  71. data/spec/spec_helper.rb +291 -0
  72. data/spec/vcr_cassettes/iso-639.yml +182 -0
  73. data/spec/vcr_cassettes/isobib_get_639_1967.yml +136 -0
  74. data/spec/vcr_cassettes/multistandard.yml +352 -0
  75. metadata +343 -0
@@ -0,0 +1,56 @@
1
+ require "isodoc"
2
+ require "metanorma-iso"
3
+ require_relative "base_convert"
4
+ require_relative "init"
5
+
6
+ module IsoDoc
7
+ module BSI
8
+ class HtmlConvert < IsoDoc::Iso::HtmlConvert
9
+ def initialize(options)
10
+ super
11
+ @libdir = File.dirname(__FILE__)
12
+ end
13
+
14
+ # TODO : true font is BSI Gesta, which is a webfont
15
+ def default_fonts(options)
16
+ {
17
+ bodyfont: (options[:script] == "Hans" ? '"Source Han Sans",serif' : '"Tahoma",sans-serif'),
18
+ headerfont: (options[:script] == "Hans" ? '"Source Han Sans",sans-serif' : '"Tahoma",sans-serif'),
19
+ monospacefont: '"Courier New",monospace',
20
+ monospacefontsize: "1.0em",
21
+ footnotefontsize: "0.9em",
22
+ }
23
+ end
24
+
25
+ def default_file_locations(_options)
26
+ @libdir = File.dirname(__FILE__)
27
+ {
28
+ htmlstylesheet: html_doc_path("htmlstyle.scss"),
29
+ htmlcoverpage: html_doc_path("html_bsi_titlepage.html"),
30
+ htmlintropage: html_doc_path("html_bsi_intro.html"),
31
+ }
32
+ end
33
+
34
+ def htmlstyle(docxml)
35
+ ret = super
36
+ b = ret.at("div[@class = 'boilerplate_legal']/ol")
37
+ b and b["type"] = "1"
38
+ ret
39
+ end
40
+
41
+ def authority_cleanup(docxml)
42
+ auth = docxml.at("//div[@id = 'boilerplate-feedback' or @class = 'boilerplate-feedback']")
43
+ auth&.remove
44
+ super
45
+ end
46
+
47
+ def insert_tab(out, n)
48
+ tab = "&#x2003;"
49
+ [1..n].each { out << tab }
50
+ end
51
+
52
+ include BaseConvert
53
+ include Init
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,56 @@
1
+ introduction: INTRODUCTION
2
+ introduction_iev: INTRODUCTION<br/>Principles and rules followed
3
+ foreword: FOREWORD
4
+ BSI: BRITISH STANDARDS INSTITUTE
5
+ formula: Equation
6
+ inequality: Inequality
7
+ section_iev: Section
8
+ price-code: Price Code
9
+ term_def_boilerplate: |
10
+ <p>ISO and IEC maintain terminological databases for use in
11
+ standardization at the following addresses:</p>
12
+
13
+ <ul>
14
+ <li> <p>IEC Electropedia: available at
15
+ <link target="http://www.electropedia.org"/>
16
+ </p> </li>
17
+ <li> <p>ISO Online browsing platform: available at
18
+ <link target="http://www.iso.org/obp"/></p> </li>
19
+ </ul>
20
+ norm_with_refs_pref:
21
+ The following documents are referred to in the text in such a way
22
+ that some or all of their content constitutes provisions of this
23
+ document. For dated references, only the edition cited applies.
24
+ For undated references, the latest edition of the referenced
25
+ document (including any amendments) applies.
26
+ biblio_pref:
27
+ For dated references, only the edition cited applies.
28
+ For undated references, the latest edition of the referenced
29
+ document (including any amendments) applies.
30
+ internal_terms_boilerplate: |
31
+ <p>For the purposes of this British Standard,
32
+ the following terms and definitions apply.</p>
33
+ external_terms_boilerplate: |
34
+ <p>For the purposes of this British Standard,
35
+ the terms and definitions given in % apply.</p>
36
+ internal_external_terms_boilerplate: |
37
+ <p>For the purposes of this British Standard, the terms and definitions
38
+ given in % and the following apply.</p>
39
+ commentary: COMMENTARY %1 ON %2
40
+ commentary_xref: Commentary %1 on %2
41
+ doctype_dict:
42
+ international-standard: International Standard
43
+ technical-specification: Technical Specification
44
+ technical-report: Technical Report
45
+ publicly-available-specification: Publicly Available Specification
46
+ international-workshop-agreement: International Workshop Agreement
47
+ guide: Guide
48
+ interpretation-sheet: Interpretation Sheet
49
+ function_dict:
50
+ emc: Basic EMC Publication
51
+ safety: Basic Safety Publication
52
+ environment: Basic Environment Publication
53
+ quality-assurance: Basic Quality Assurance Publication
54
+ horizontal_dict:
55
+ "true": Horizontal Standard
56
+ "false":
@@ -0,0 +1,15 @@
1
+ module IsoDoc
2
+ module BSI
3
+ class I18n < IsoDoc::Iso::I18n
4
+ def load_yaml1(lang, script)
5
+ y = if lang == "en"
6
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
7
+ else
8
+ YAML.load_file(File.join(File.dirname(__FILE__), "i18n-en.yaml"))
9
+ end
10
+ super.merge(y)
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,24 @@
1
+ require "isodoc"
2
+ require_relative "metadata"
3
+ require_relative "xref"
4
+ require_relative "i18n"
5
+
6
+ module IsoDoc
7
+ module BSI
8
+ module Init
9
+ def metadata_init(lang, script, labels)
10
+ @meta = Metadata.new(lang, script, labels)
11
+ end
12
+
13
+ def xref_init(lang, script, _klass, labels, options)
14
+ @xrefs = Xref.new(lang, script,
15
+ HtmlConvert.new(language: lang, script: script),
16
+ labels, options)
17
+ end
18
+
19
+ def i18n_init(lang, script, i18nyaml = nil)
20
+ @i18n = I18n.new(lang, script, i18nyaml || @i18nyaml)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require "isodoc"
2
+ require "metanorma-iso"
3
+
4
+ module IsoDoc
5
+ module BSI
6
+ class Metadata < IsoDoc::Iso::Metadata
7
+ def docstatus(isoxml, _out)
8
+ docstatus = isoxml.at(ns("//bibdata/status/stage"))
9
+ substage = isoxml.at(ns("//bibdata/status/substage"))
10
+ set(:unpublished, false)
11
+ if docstatus
12
+ set(:stage, docstatus.text)
13
+ set(:stage_int, docstatus.text.to_i)
14
+ set(:unpublished, unpublished(docstatus.text))
15
+ set(:statusabbr, substage["abbreviation"])
16
+ unpublished(docstatus.text) and
17
+ set(:stageabbr, docstatus["abbreviation"])
18
+ end
19
+ revdate = isoxml.at(ns("//version/revision-date"))
20
+ set(:revdate, revdate&.text)
21
+ end
22
+
23
+ def unpublished(status)
24
+ status.to_i.positive? && status.to_i < 60
25
+ end
26
+
27
+ def docid(isoxml, _out)
28
+ dn = isoxml.at(ns("//bibdata/docidentifier[@type = 'BS']"))
29
+ set(:docnumber, dn&.text)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "base_convert"
2
+ require "isodoc"
3
+
4
+ module IsoDoc
5
+ module BSI
6
+ class PdfConvert < IsoDoc::XslfoPdfConvert
7
+ def initialize(options)
8
+ @libdir = File.dirname(__FILE__)
9
+ super
10
+ end
11
+
12
+ def pdf_stylesheet(_docxml)
13
+ "bsi.international-standard.xsl"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,72 @@
1
+ require_relative "init"
2
+ require "isodoc"
3
+
4
+ module IsoDoc
5
+ module BSI
6
+ class PresentationXMLConvert < IsoDoc::Iso::PresentationXMLConvert
7
+ def block(docxml)
8
+ super
9
+ commentary(docxml)
10
+ end
11
+
12
+ def termnote1(termnote)
13
+ note1(termnote)
14
+ end
15
+
16
+ def commentary(docxml)
17
+ docxml.xpath(ns("//admonition[@type = 'commentary']")).each do |f|
18
+ commentary1(f)
19
+ end
20
+ end
21
+
22
+ # introduce name element
23
+ def commentary1(node)
24
+ n = @xrefs.get[node["id"]]
25
+ prefix_name(node, "", n[:label].upcase, "name")
26
+ end
27
+
28
+ def eref_localities1_zh(target, type, from, to, n, delim)
29
+ subsection = from&.text&.match(/\./)
30
+ ret = if delim == ";"
31
+ ";"
32
+ else
33
+ type == "list" ? "" : delim
34
+ end
35
+ ret += " 第#{from.text}" if from
36
+ ret += "&ndash;#{to.text}" if to
37
+ ret = "<strong>#{ret}</strong>" if type == "clause"
38
+ loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize)
39
+ ret += " #{loc}" unless subsection && type == "clause" ||
40
+ type == "list" || target.match(/^IEV$|^IEC 60050-/) ||
41
+ n["droploc"] == "true"
42
+ ret += ")" if type == "list"
43
+ ret
44
+ end
45
+
46
+ def eref_localities1(target, type, from, to, delim, n, lang = "en")
47
+ return "" if type == "anchor"
48
+
49
+ subsection = from&.text&.match(/\./)
50
+ type = type.downcase
51
+ lang == "zh" and
52
+ return l10n(eref_localities1_zh(target, type, from, to, n, delim))
53
+ ret = if delim == ";"
54
+ ";"
55
+ else
56
+ type == "list" ? "" : delim
57
+ end
58
+ ret += eref_locality_populate(type, n) unless subsection &&
59
+ type == "clause" || type == "list" ||
60
+ target.match(/^IEV$|^IEC 60050-/)
61
+ range = " #{from.text}" if from
62
+ range += "&ndash;#{to.text}" if to
63
+ range &&= "<strong>#{range}</strong>" if type == "clause"
64
+ ret += " #{range}"
65
+ ret += ")" if type == "list"
66
+ l10n(ret)
67
+ end
68
+
69
+ include Init
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,30 @@
1
+ require "isodoc"
2
+ require "mn2sts"
3
+
4
+ module IsoDoc
5
+ module BSI
6
+
7
+ # A {Converter} implementation that generates HTML output, and a document
8
+ # schema encapsulation of the document for validation
9
+ #
10
+ class StsConvert < IsoDoc::XslfoPdfConvert
11
+ def initialize(options)
12
+ @libdir = File.dirname(__FILE__)
13
+ @format = :isosts
14
+ @suffix = "isosts.xml"
15
+ end
16
+
17
+ def convert(input_filename, file = nil, debug = false, output_filename = nil)
18
+ file = File.read(input_filename, encoding: "utf-8") if file.nil?
19
+ docxml, filename, dir = convert_init(file, input_filename, debug)
20
+ /\.xml$/.match(input_filename) or
21
+ input_filename = Tempfile.open([filename, ".xml"], encoding: "utf-8") do |f|
22
+ f.write file
23
+ f.path
24
+ end
25
+ FileUtils.rm_rf dir
26
+ Mn2sts.convert(input_filename, output_filename || "#{filename}.#{@suffix}", iso: true)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,134 @@
1
+ module IsoDoc
2
+ module BSI
3
+ class Xref < IsoDoc::Iso::Xref
4
+ def parse(docxml)
5
+ super
6
+ commentary_anchor_names(docxml)
7
+ end
8
+
9
+ def commentary_anchor_names(docxml)
10
+ commentary_anchors(docxml).each do |target, comms|
11
+ link = commentary_link(target, docxml)
12
+ comms.each_with_index do |id, i|
13
+ idx = comms.size == 1 ? "" : " #{i + 1}"
14
+ label = @labels["commentary"].sub(/ %1/, idx).sub(/%2/, link)
15
+ xref = @labels["commentary_xref"].sub(/ %1/, idx).sub(/%2/, link)
16
+ @anchors[id] = { type: "commentary", label: label, xref: xref }
17
+ end
18
+ end
19
+ end
20
+
21
+ def commentary_link(target, docxml)
22
+ link = @anchors.dig(target, :xref) || "???"
23
+ if @anchors.dig(target, :type) == "clause" ||
24
+ docxml.at(ns("//clause[@id = '#{target}']"))
25
+ link = "#{@labels['clause']} #{@anchors[target][:label]}"
26
+ end
27
+ link
28
+ end
29
+
30
+ def commentary_anchors(docxml)
31
+ docxml.xpath(ns("//admonition[@type = 'commentary']"))
32
+ .each_with_object({}) do |a, m|
33
+ m[a["target"]] ||= []
34
+ m[a["target"]] << a["id"]
35
+ end
36
+ end
37
+
38
+ def annex_name_lbl(clause, num)
39
+ obl = if clause["obligation"] == "normative"
40
+ l10n("(#{@labels['norm_annex']})")
41
+ else
42
+ l10n("(#{@labels['inform_annex']})")
43
+ end
44
+ l10n("<strong>#{@labels['annex']} #{num}</strong><br/>#{obl}")
45
+ end
46
+
47
+ def termnote_anchor_names(docxml)
48
+ docxml.xpath(ns("//term[descendant::termnote]")).each do |t|
49
+ c = ::IsoDoc::XrefGen::Counter.new
50
+ notes = t.xpath(ns(".//termnote"))
51
+ notes.each do |n|
52
+ next if n["id"].nil? || n["id"].empty?
53
+
54
+ idx =
55
+ notes.size == 1 && !n["number"] ? "" : " #{c.increment(n).print}"
56
+ @anchors[n["id"]] = anchor_struct(idx, n, @labels["note_xref"],
57
+ "note", false)
58
+ end
59
+ end
60
+ end
61
+
62
+ def section_names(clause, num, lvl)
63
+ return num if clause.nil?
64
+
65
+ num.increment(clause)
66
+ @anchors[clause["id"]] =
67
+ { label: num.print, level: lvl, type: "clause",
68
+ xref: l10n("#{@labels['clause']} <strong>#{num.print}</strong>") }
69
+ i = ::IsoDoc::XrefGen::Counter.new
70
+ clause.xpath(ns(SUBCLAUSES)).each do |c|
71
+ i.increment(c)
72
+ section_names1(c, "#{num.print}.#{i.print}", lvl + 1)
73
+ end
74
+ num
75
+ end
76
+
77
+ def section_names1(clause, num, level)
78
+ @anchors[clause["id"]] =
79
+ { xref: "<strong>#{num}</strong>", level: level, label: num }
80
+ # subclauses are not prefixed with "Clause"
81
+ i = ::IsoDoc::XrefGen::Counter.new
82
+ clause.xpath(ns("./clause | ./terms | ./term | ./definitions | "\
83
+ "./references"))
84
+ .each do |c|
85
+ i.increment(c)
86
+ section_names1(c, "#{num}.#{i.print}", level + 1)
87
+ end
88
+ end
89
+
90
+ def annex_names1(clause, num, level)
91
+ @anchors[clause["id"]] =
92
+ { xref: "<strong>#{num}</strong>", label: num, level: level }
93
+ i = ::IsoDoc::XrefGen::Counter.new
94
+ clause.xpath(ns("./clause | ./references")).each do |c|
95
+ i.increment(c)
96
+ annex_names1(c, "#{num}.#{i.print}", level + 1)
97
+ end
98
+ end
99
+
100
+ def list_anchor_names(sections)
101
+ sections.each do |s|
102
+ notes = s.xpath(ns(".//ol")) - s.xpath(ns(".//clause//ol")) -
103
+ s.xpath(ns(".//appendix//ol")) - s.xpath(ns(".//ol//ol"))
104
+ c = ::IsoDoc::XrefGen::Counter.new
105
+ notes.each do |n|
106
+ next if n["id"].nil? || n["id"].empty?
107
+
108
+ idx = notes.size == 1 && !n["number"] ? "" : " #{c.increment(n).print}"
109
+ @anchors[n["id"]] = anchor_struct(idx, n, @labels["list"], "list",
110
+ false)
111
+ list_item_anchor_names(n, @anchors[n["id"]], 1, "", notes.size > 3)
112
+ end
113
+ list_anchor_names(s.xpath(ns(CHILD_SECTIONS)))
114
+ end
115
+ end
116
+
117
+ def list_item_anchor_names(list, list_anchor, depth, prev_label, refer_list)
118
+ c = ::IsoDoc::XrefGen::Counter
119
+ .new(list["start"] ? list["start"].to_i - 1 : 0)
120
+ list.xpath(ns("./li")).each do |li|
121
+ label = c.increment(li).listlabel(list, depth)
122
+ label = "#{prev_label}.#{label}" unless prev_label.empty?
123
+ label = "#{list_anchor[:xref]} #{label}" if refer_list
124
+ li["id"] and @anchors[li["id"]] =
125
+ { xref: "#{label})", type: "listitem",
126
+ container: @klass.get_clause_id(li) }
127
+ li.xpath(ns("./ol")).each do |ol|
128
+ list_item_anchor_names(ol, list_anchor, depth + 1, label, false)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end