asciidoctor-gb 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.hound.yml +3 -0
  3. data/.oss-guides.rubocop.yml +1077 -0
  4. data/.rubocop.ribose.yml +65 -0
  5. data/.rubocop.tb.yml +640 -0
  6. data/.rubocop.yml +15 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +11 -0
  9. data/README.adoc +77 -0
  10. data/Rakefile +6 -0
  11. data/asciidoctor-gb.gemspec +52 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/lib/asciidoctor/gb/agencies.rb +186 -0
  15. data/lib/asciidoctor/gb/converter.rb +179 -0
  16. data/lib/asciidoctor/gb/front.rb +179 -0
  17. data/lib/asciidoctor/gb/gbconvert.rb +86 -0
  18. data/lib/asciidoctor/gb/gbstandard.rng +297 -0
  19. data/lib/asciidoctor/gb/html/blank.png +0 -0
  20. data/lib/asciidoctor/gb/html/footer.png +0 -0
  21. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-db.gif +0 -0
  22. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-db.png +0 -0
  23. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-db.svg +1 -0
  24. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gb.gif +0 -0
  25. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gb.png +0 -0
  26. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gb.svg +1 -0
  27. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gjb.gif +0 -0
  28. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gjb.png +0 -0
  29. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gjb.svg +1 -0
  30. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gm.gif +0 -0
  31. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gm.png +0 -0
  32. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-gm.svg +1 -0
  33. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-jjf.gif +0 -0
  34. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-jjf.png +0 -0
  35. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-jjf.svg +1 -0
  36. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-zb.gif +0 -0
  37. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-zb.png +0 -0
  38. data/lib/asciidoctor/gb/html/gb-logos/gb-standard-zb.svg +13 -0
  39. data/lib/asciidoctor/gb/html/gb.css +642 -0
  40. data/lib/asciidoctor/gb/html/header.html +216 -0
  41. data/lib/asciidoctor/gb/html/html_gb_intro.html +45 -0
  42. data/lib/asciidoctor/gb/html/html_gb_titlepage.html +98 -0
  43. data/lib/asciidoctor/gb/html/htmlstyle.css +187 -0
  44. data/lib/asciidoctor/gb/html/logo.png +0 -0
  45. data/lib/asciidoctor/gb/html/word_gb_intro.html +3 -0
  46. data/lib/asciidoctor/gb/html/word_gb_titlepage.html +234 -0
  47. data/lib/asciidoctor/gb/html/wordstyle.css +2367 -0
  48. data/lib/asciidoctor/gb/isodoc.rng +1563 -0
  49. data/lib/asciidoctor/gb/isostandard.rng +845 -0
  50. data/lib/asciidoctor/gb/metadata.rb +186 -0
  51. data/lib/asciidoctor/gb/section_input.rb +168 -0
  52. data/lib/asciidoctor/gb/section_output.rb +38 -0
  53. data/lib/asciidoctor/gb/version.rb +5 -0
  54. data/lib/asciidoctor/gb/xref_gen.rb +25 -0
  55. data/lib/asciidoctor/gb.rb +7 -0
  56. data/lib/asciidoctor-gb.rb +4 -0
  57. metadata +411 -0
@@ -0,0 +1,186 @@
1
+ require "isodoc"
2
+
3
+ module Asciidoctor
4
+ module Gb
5
+ # A {Converter} implementation that generates GB output, and a document
6
+ # schema encapsulation of the document for validation
7
+ class GbConvert < IsoDoc::Convert
8
+ def init_metadata
9
+ super
10
+ set_metadata(:docmaintitlezh, "")
11
+ set_metadata(:docsubtitlezh, "XXXX")
12
+ set_metadata(:docparttitlezh, "")
13
+ set_metadata(:docmaintitleen, "")
14
+ set_metadata(:docsubtitleen, "XXXX")
15
+ set_metadata(:docparttitleen, "")
16
+ set_metadata(:gbequivalence, "")
17
+ set_metadata(:isostandard, nil)
18
+ set_metadata(:isostandardtitle, "")
19
+ set_metadata(:doctitle, "XXXX")
20
+ set_metadata(:obsoletes, nil)
21
+ set_metadata(:obsoletes_part, nil)
22
+ end
23
+
24
+ def title(isoxml, _out)
25
+ intro = isoxml.at(ns("//title-intro[@language='zh']"))
26
+ main = isoxml.at(ns("//title-main[@language='zh']"))
27
+ part = isoxml.at(ns("//title-part[@language='zh']"))
28
+ partnumber = isoxml.at(ns("//project-number/@part"))
29
+ intro.nil? || set_metadata(:docmaintitlezh, intro.text + "&mdash;")
30
+ main.nil? || set_metadata(:docsubtitlezh, main.text)
31
+ partnum = partnumber ? "#{part_label(partnumber, 'zh')}: " : ""
32
+ part.nil? || set_metadata(:docparttitlezh,
33
+ "&mdash;#{partnum} #{part.text}")
34
+ set_metadata(:doctitle, get_metadata[:docmaintitlezh] +
35
+ get_metadata[:docsubtitlezh] +
36
+ get_metadata[:docparttitlezh])
37
+ end
38
+
39
+ def subtitle(isoxml, _out)
40
+ intro = isoxml.at(ns("//title-intro[@language='en']"))
41
+ main = isoxml.at(ns("//title-main[@language='en']"))
42
+ part = isoxml.at(ns("//title-part[@language='en']"))
43
+ partnumber = isoxml.at(ns("//project-number/@part"))
44
+ intro.nil? || set_metadata(:docmaintitleen, intro.text + "&mdash;")
45
+ main.nil? || set_metadata(:docsubtitleen, main.text)
46
+ partnum = partnumber ? "#{part_label(partnumber, 'en')}: " : ""
47
+ part.nil? || set_metadata(:docparttitleen,
48
+ "&mdash;#{partnum} #{part.text}")
49
+ end
50
+
51
+ def author(isoxml, _out)
52
+ gbcommittee = isoxml.at(ns("//bibdata/gbcommittee"))
53
+ set_metadata(:committee, gbcommittee.text)
54
+ end
55
+
56
+ def id(isoxml, _out)
57
+ super
58
+ gb_identifier(isoxml)
59
+ gb_library_identifier(isoxml)
60
+ gb_equivalence(isoxml)
61
+ end
62
+
63
+ ISO_STD_XPATH = "//bibdata/relation[@type = 'equivalent' or "\
64
+ "@type = 'identical' or @type = 'nonequivalent']/bibitem".freeze
65
+
66
+ def gb_equivalence(isoxml)
67
+ isostdid = isoxml.at(ns("#{ISO_STD_XPATH}/docidentifier")) || return
68
+ set_metadata(:isostandard, isostdid.text)
69
+ isostdtitle = isoxml.at(ns("#{ISO_STD_XPATH}/title"))
70
+ set_metadata(:isostandardtitle, isostdtitle.text) if isostdtitle
71
+ eq = isoxml.at(ns("//bibdata/relation/@type"))
72
+ case eq.text
73
+ when "equivalent" then set_metadata(:gbequivalence, "MOD")
74
+ when "nonequivalent" then set_metadata(:gbequivalence, "NEQ")
75
+ when "identical" then set_metadata(:gbequivalence, "IDT")
76
+ end
77
+ end
78
+
79
+ def docidentifier(gbscope, gbprefix, gbmandate)
80
+ docnum = get_metadata[:docnumber]
81
+ dn = if gbscope == "local"
82
+ "DB#{mandate_suffix(gbprefix, gbmandate)}/#{docnum}".
83
+ gsub(%r{/([TZ])/}, "/\\1 ")
84
+ else
85
+ "#{mandate_suffix(gbprefix, gbmandate)} #{docnum}"
86
+ end
87
+ set_metadata(:docidentifier, dn)
88
+ end
89
+
90
+ def gb_identifier(isoxml)
91
+ scope = isoxml.at(ns("//gbscope"))&.text || "national"
92
+ mandate = isoxml.at(ns("//gbmandate"))&.text || "mandatory"
93
+ prefix = isoxml.at(ns("//gbprefix"))&.text || "XXX"
94
+ docidentifier(scope, prefix, mandate)
95
+ set_metadata(:standard_class, standard_class(scope, prefix, mandate))
96
+ set_metadata(:standard_agency, standard_agency(scope, prefix, mandate))
97
+ set_metadata(:gbprefix, scope == "local" ? "DB" : prefix)
98
+ end
99
+
100
+ def standard_logo(gbprefix)
101
+ case gbprefix.downcase
102
+ when "db" then "gb-standard-db"
103
+ when "gb" then "gb-standard-gb"
104
+ when "gjb" then "gb-standard-gjb"
105
+ when "gm" then "gb-standard-gm"
106
+ when "jjf" then "gb-standard-jjf"
107
+ when "zb" then "gb-standard-zb"
108
+ end
109
+ end
110
+
111
+ def gb_library_identifier(isoxml)
112
+ ics = isoxml.at(ns("//gblibraryids/ics"))
113
+ l = isoxml.at(ns("//gblibraryids/l"))
114
+ set_metadata(:libraryid_ics, ics ? ics.text : "XXX")
115
+ set_metadata(:libraryid_l, l ? l.text : "XXX")
116
+ end
117
+
118
+ def part_label(partnumber, lang)
119
+ case lang
120
+ when "en" then "Part #{partnumber}"
121
+ when "zh" then "第#{partnumber}部"
122
+ end
123
+ end
124
+
125
+ def format_logo(prefix, _format)
126
+ logo = standard_logo(prefix)
127
+ if logo.nil?
128
+ "<span style='font-size:36pt;font-weight:bold'>#{prefix}</span>"
129
+ else
130
+ logo += ".gif"
131
+ system "cp #{fileloc(File.join('html/gb-logos', logo))} #{logo}"
132
+ "<img width='113' height='56' src='#{logo}' alt='#{prefix}'>"
133
+ end
134
+ end
135
+
136
+ def format_agency(agency, format)
137
+ return agency unless agency.is_a?(Array)
138
+ ret = "<table><tr><td>#{agency[0]}</td>"\
139
+ "<td rowspan='#{agency.size}'>发布</td></tr>"
140
+ agency[1..-1].each { |a| ret += "<tr><td>#{a}</td></tr>" }
141
+ ret += "</table>"
142
+ ret.gsub!(/<table>/, "<table width='100%'>") if format == :word
143
+ ret
144
+ end
145
+
146
+ def termref_render(x)
147
+ parts = x.split(%r{(\s*\[MODIFICATION\]|,)}m)
148
+ parts[1] = ",定义" if parts.size > 1 && parts[1] == ","
149
+ parts.map do |p|
150
+ /\s*\[MODIFICATION\]/.match?(p) ? ", 改写 &mdash; " : p
151
+ end.join.sub(/\A\s*/m, "【").sub(/\s*\z/m, "】")
152
+ end
153
+
154
+ def termref_resolve(docxml)
155
+ docxml.split(%r{(\[TERMREF\]|\[/TERMREF\])}).each_slice(4).
156
+ map do |a|
157
+ a.size < 3 ? a[0] : a[0] + termref_render(a[2])
158
+ end.join
159
+ end
160
+
161
+ def populate_template(docxml, format)
162
+ meta = get_metadata
163
+ logo = format_logo(meta[:gbprefix], format)
164
+ docxml = termref_resolve(docxml)
165
+ docxml.gsub!(/\s*\[ISOSECTION\]/, ", ?~Z?~I")
166
+ meta[:standard_agency_formatted] =
167
+ format_agency(meta[:standard_agency], format)
168
+ meta[:standard_logo] = logo
169
+ template = Liquid::Template.parse(docxml)
170
+ template.render(meta.map { |k, v| [k.to_s, v] }.to_h)
171
+ end
172
+
173
+ STAGE_ABBRS = {
174
+ "00": "PWI",
175
+ "10": "NWIP",
176
+ "20": "WD",
177
+ "30": "CD",
178
+ "40": "DIS",
179
+ "50": "FDIS",
180
+ "60": "IS",
181
+ "90": "(Review)",
182
+ "95": "(Withdrawal)",
183
+ }.freeze
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,168 @@
1
+ module Asciidoctor
2
+ module Gb
3
+
4
+ # A {Converter} implementation that generates GB output, and a document
5
+ # schema encapsulation of the document for validation
6
+ class Converter < ISO::Converter
7
+
8
+ def term_def_subclause_parse(attrs, xml, node)
9
+ # subclause contains subclauses
10
+ sub = node.find_by(context: :section) {|s| s.level == node.level + 1 }
11
+ sub.empty? || (return term_def_parse(attrs, xml, node, false))
12
+ (node.title.downcase == "symbols and abbreviated terms" ||
13
+ node.title == "符号、代号和缩略语") &&
14
+ (return symbols_parse(attrs, xml, node))
15
+ xml.term **attr_code(attrs) do |xml_section|
16
+ xml_section.preferred { |name| name << node.title }
17
+ xml_section << node.content
18
+ end
19
+ end
20
+
21
+ def section(node)
22
+ a = { id: Asciidoctor::ISO::Utils::anchor_or_uuid(node) }
23
+ noko do |xml|
24
+ case sectiontype(node)
25
+ when "引言" then
26
+ if node.level == 1 then introduction_parse(a, xml, node)
27
+ else
28
+ clause_parse(a, xml, node)
29
+ end
30
+ when "patent notice" then patent_notice_parse(xml, node)
31
+ when "范围", "scope" then scope_parse(a, xml, node)
32
+ when "规范性引用文件", "normative references"
33
+ norm_ref_parse(a, xml, node)
34
+ when "术语和定义", "terms and definitions",
35
+ "术语、定义、符号、代号和缩略语",
36
+ "terms, definitions, symbols and abbreviated terms"
37
+ @term_def = true
38
+ term_def_parse(a, xml, node, true)
39
+ @term_def = false
40
+ when "符号、代号和缩略语", "symbols and abbreviated terms"
41
+ symbols_parse(a, xml, node)
42
+ when "参考文献", "bibliography"
43
+ bibliography_parse(a, xml, node)
44
+ else
45
+ if @term_def then term_def_subclause_parse(a, xml, node)
46
+ elsif @biblio then bibliography_parse(a, xml, node)
47
+ elsif node.attr("style") == "appendix" && node.level == 1
48
+ annex_parse(a, xml, node)
49
+ else
50
+ clause_parse(a, xml, node)
51
+ end
52
+ end
53
+ end.join("\n")
54
+ end
55
+
56
+ =begin
57
+ def preamble(node)
58
+ noko do |xml|
59
+ xml.foreword do |xml_abstract|
60
+ xml_abstract.title { |t| t << "前言" }
61
+ content = node.content
62
+ xml_abstract << content
63
+ text = Asciidoctor::ISO::Utils::flatten_rawtext(content).join("\n")
64
+ foreword_style(node, text)
65
+ end
66
+ end.join("\n")
67
+ end
68
+ =end
69
+
70
+ def normref_cleanup(xmldoc)
71
+ q = "//references[title = '规范性引用文件']"
72
+ r = xmldoc.at(q)
73
+ if r.nil?
74
+ warn "You have no normative references!"
75
+ return
76
+ end
77
+ r.elements.each do |n|
78
+ n.remove unless ["title", "bibitem"].include? n.name
79
+ end
80
+ end
81
+
82
+ def normref_validate(root)
83
+ f = root.at("//references[title = '规范性引用文件']") ||
84
+ return
85
+ f.at("./references") &&
86
+ warn("ISO style: normative references contains subsections")
87
+ end
88
+
89
+ def symbols_validate(root)
90
+ f = root.at("//clause[title = '符号、代号和缩略语']")
91
+ return if f.nil?
92
+ f.elements do |e|
93
+ unless e.name == "dl"
94
+ warn "ISO style: Symbols and Abbreviations can only contain "\
95
+ "a definition list"
96
+ return
97
+ end
98
+ end
99
+ end
100
+
101
+ # spec of permissible section sequence
102
+ SEQ = [
103
+ { msg: "Initial section must be (content) 前言",
104
+ val: [{ tag: "foreword", title: "前言" }], },
105
+ { msg: "Prefatory material must be followed by (clause) 范围",
106
+ val: [{ tag: "introduction", title: "引言" },
107
+ { tag: "clause", title: "范围" }], },
108
+ { msg: "Prefatory material must be followed by (clause) 范围",
109
+ val: [{ tag: "clause", title: "范围" }], },
110
+ { msg: "规范性引用文件 must be followed by "\
111
+ "术语和定义",
112
+ val: [
113
+ { tag: "terms", title: "术语和定义" },
114
+ { tag: "terms",
115
+ title: "术语、定义、符号、代号和缩略语" }
116
+ ] },
117
+ ]
118
+
119
+ def sections_sequence_validate(root)
120
+ f = root.xpath(" //foreword | //introduction | //sections/terms | "\
121
+ "//sections/clause | ./references | "\
122
+ "./annex")
123
+ names = f.map { |s| { tag: s.name, title: s.at("./title").text } }
124
+ names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val]) || return
125
+ n = names[0]
126
+ names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val]) || return
127
+ if n == { tag: "introduction", title: "引言" }
128
+ names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val]) || return
129
+ end
130
+ names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val]) || return
131
+ n = names.shift
132
+ if n == { tag: "clause", title: "符号、代号和缩略语" }
133
+ n = names.shift
134
+ end
135
+ unless n
136
+ warn "ISO style: Document must contain at least one clause"
137
+ return
138
+ end
139
+ n[:tag] == "clause" or
140
+ warn "ISO style: Document must contain at least one clause"
141
+ (n == { tag: "clause", title: "范围" }) &&
142
+ warn("ISO style: 范围 must occur before 术语和定义")
143
+ n = names.shift or return
144
+ while n[:tag] == "clause"
145
+ (n[:title] == "范围") &&
146
+ warn("ISO style: 范围 must occur before 术语和定义")
147
+ n[:title] == "符号、代号和缩略语" and
148
+ warn "ISO style: 符号、代号和缩略语 must occur "\
149
+ "right after Terms and Definitions"
150
+ n = names.shift or return
151
+ end
152
+ unless n[:tag] == "annex" or n[:tag] == "references"
153
+ warn "ISO style: Only annexes and references can follow clauses"
154
+ end
155
+ while n[:tag] == "annex"
156
+ n = names.shift or return
157
+ end
158
+ n == { tag: "references", title: "规范性引用文件" } or
159
+ warn "ISO style: Document must include (references) 规范性引用文件"
160
+ n = names.shift
161
+ n == { tag: "references", title: "参考文献" } or
162
+ warn "ISO style: Final section must be (references) 参考文献"
163
+ names.empty? or
164
+ warn "ISO style: There are sections after the final Bibliography"
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,38 @@
1
+ module Asciidoctor
2
+ module Gb
3
+ class GbConvert < IsoDoc::Convert
4
+ # putting in tab so that ToC aligns
5
+ def foreword(isoxml, out)
6
+ f = isoxml.at(ns("//foreword")) || return
7
+ page_break(out)
8
+ out.div do |s|
9
+ s.h1 **{ class: "ForewordTitle" } do |h1|
10
+ h1 << "#{@foreword_lbl}&nbsp;"
11
+ # insert_tab(h1, 1)
12
+ end
13
+ f.elements.each { |e| parse(e, s) unless e.name == "title" }
14
+ end
15
+ end
16
+
17
+ def clause_name_header(num, title, div, header_class)
18
+ header_class = {} if header_class.nil?
19
+ div.h1 **attr_code(header_class) do |h1|
20
+ if num
21
+ h1 << num
22
+ h1 << "&nbsp;"
23
+ end
24
+ h1 << title
25
+ end
26
+ div.parent.at(".//h1")
27
+ end
28
+
29
+ def annex_name(annex, name, div)
30
+ div.h1 **{ class: "Annex" } do |t|
31
+ t << "#{get_anchors[annex['id']][:label]}<br/><br/>"
32
+ t << name.text
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ module Asciidoctor
2
+ module Gb
3
+ VERSION = "0.1.5"
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ require "isodoc"
2
+
3
+ module Asciidoctor
4
+ module Gb
5
+ # A {Converter} implementation that generates GB output, and a document
6
+ # schema encapsulation of the document for validation
7
+ class GbConvert < IsoDoc::Convert
8
+ def format_ref(ref, isopub)
9
+ return "ISO #{ref}" if isopub
10
+ return "[#{ref}]" if /^\d+$/.match?(ref) && !/^\[.*\]$/.match?(ref)
11
+ ref
12
+ end
13
+
14
+ def reference_names(ref)
15
+ isopub = ref.at(ns(ISO_PUBLISHER_XPATH))
16
+ docid = ref.at(ns("./docidentifier"))
17
+ return ref_names(ref) unless docid
18
+ date = ref.at(ns("./date[@type = 'published']"))
19
+ reference = format_ref(docid.text, isopub)
20
+ reference += ": #{date.text}" if date && isopub
21
+ @anchors[ref["id"]] = { xref: reference }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ require "asciidoctor/gb/version"
2
+
3
+ module Asciidoctor
4
+ module Gb
5
+ # Your code goes here...
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ require "asciidoctor" unless defined? Asciidoctor::Converter
2
+ require_relative "asciidoctor/gb/converter"
3
+ require_relative "asciidoctor/gb/gbconvert"
4
+ require_relative "asciidoctor/gb/version"