metanorma-bsi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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