metanorma-mpfa 0.4.0

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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/macos.yml +39 -0
  3. data/.github/workflows/ubuntu.yml +53 -0
  4. data/.github/workflows/windows.yml +41 -0
  5. data/.gitignore +1 -0
  6. data/.hound.yml +3 -0
  7. data/.rubocop.yml +10 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +11 -0
  10. data/LICENSE +25 -0
  11. data/README.adoc +79 -0
  12. data/Rakefile +6 -0
  13. data/bin/console +14 -0
  14. data/bin/manifest +146 -0
  15. data/bin/rspec +18 -0
  16. data/bin/setup +8 -0
  17. data/lib/asciidoctor/mpfa.rb +6 -0
  18. data/lib/asciidoctor/mpfa/basicdoc.rng +1059 -0
  19. data/lib/asciidoctor/mpfa/biblio.rng +1237 -0
  20. data/lib/asciidoctor/mpfa/converter.rb +113 -0
  21. data/lib/asciidoctor/mpfa/isodoc.rng +1504 -0
  22. data/lib/asciidoctor/mpfa/mpfd.rng +79 -0
  23. data/lib/asciidoctor/mpfa/reqt.rng +194 -0
  24. data/lib/asciidoctor/mpfa/section.rb +61 -0
  25. data/lib/asciidoctor/mpfa/validate.rb +30 -0
  26. data/lib/isodoc/mpfa/base_convert.rb +128 -0
  27. data/lib/isodoc/mpfa/html/header.html +242 -0
  28. data/lib/isodoc/mpfa/html/html_rsd_intro.html +8 -0
  29. data/lib/isodoc/mpfa/html/html_rsd_titlepage.html +58 -0
  30. data/lib/isodoc/mpfa/html/htmlstyle.scss +932 -0
  31. data/lib/isodoc/mpfa/html/logo.jpg +0 -0
  32. data/lib/isodoc/mpfa/html/logo.svg +1 -0
  33. data/lib/isodoc/mpfa/html/mpfa-logo-no-text@4x.png +0 -0
  34. data/lib/isodoc/mpfa/html/mpfa-logo@4x.png +0 -0
  35. data/lib/isodoc/mpfa/html/rsd.scss +763 -0
  36. data/lib/isodoc/mpfa/html/scripts.html +80 -0
  37. data/lib/isodoc/mpfa/html/word_rsd_intro.html +3 -0
  38. data/lib/isodoc/mpfa/html/word_rsd_titlepage.html +42 -0
  39. data/lib/isodoc/mpfa/html/wordstyle.scss +1157 -0
  40. data/lib/isodoc/mpfa/html_convert.rb +63 -0
  41. data/lib/isodoc/mpfa/i18n-en.yaml +2 -0
  42. data/lib/isodoc/mpfa/i18n-zh-Hans.yaml +2 -0
  43. data/lib/isodoc/mpfa/metadata.rb +74 -0
  44. data/lib/isodoc/mpfa/presentation_xml_convert.rb +10 -0
  45. data/lib/isodoc/mpfa/word_convert.rb +62 -0
  46. data/lib/isodoc/mpfa/xref.rb +102 -0
  47. data/lib/metanorma-mpfa.rb +11 -0
  48. data/lib/metanorma/mpfa.rb +7 -0
  49. data/lib/metanorma/mpfa/processor.rb +49 -0
  50. data/lib/metanorma/mpfa/version.rb +5 -0
  51. data/metanorma-mpfd.gemspec +46 -0
  52. metadata +280 -0
@@ -0,0 +1,63 @@
1
+ require_relative "base_convert"
2
+ require "isodoc"
3
+
4
+ module IsoDoc
5
+ module MPFA
6
+
7
+ # A {Converter} implementation that generates HTML output, and a document
8
+ # schema encapsulation of the document for validation
9
+ #
10
+ class HtmlConvert < IsoDoc::HtmlConvert
11
+ def initialize(options)
12
+ @libdir = File.dirname(__FILE__)
13
+ super
14
+ end
15
+
16
+ include BaseConvert
17
+
18
+ def default_fonts(options)
19
+ {
20
+ bodyfont: (options[:script] == "Hans" ? '"SimSun",serif' : '"Titillium Web",sans-serif'),
21
+ headerfont: (options[:script] == "Hans" ? '"SimHei",sans-serif' : '"Titillium Web",sans-serif'),
22
+ monospacefont: '"Space Mono",monospace'
23
+ }
24
+ end
25
+
26
+ def default_file_locations(_options)
27
+ {
28
+ htmlstylesheet: html_doc_path("htmlstyle.scss"),
29
+ htmlcoverpage: html_doc_path("html_rsd_titlepage.html"),
30
+ htmlintropage: html_doc_path("html_rsd_intro.html"),
31
+ scripts: html_doc_path("scripts.html"),
32
+ }
33
+ end
34
+
35
+ def googlefonts
36
+ <<~HEAD.freeze
37
+ <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i|Space+Mono:400,700" rel="stylesheet">
38
+ <link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet">
39
+ <link href="https://fonts.googleapis.com/css?family=Titillium+Web:400,400i,700,700i" rel="stylesheet">
40
+ HEAD
41
+ end
42
+
43
+ def make_body(xml, docxml)
44
+ body_attr = { lang: "EN-US", link: "blue", vlink: "#954F72", "xml:lang": "EN-US", class: "container" }
45
+ xml.body **body_attr do |body|
46
+ make_body1(body, docxml)
47
+ make_body2(body, docxml)
48
+ make_body3(body, docxml)
49
+ end
50
+ end
51
+
52
+ def make_body3(body, docxml)
53
+ body.div **{ class: "main-section" } do |div3|
54
+ preface docxml, div3
55
+ middle docxml, div3
56
+ footnotes div3
57
+ comments div3
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
@@ -0,0 +1,2 @@
1
+ clause: Paragraph
2
+ annex: Appendix
@@ -0,0 +1,2 @@
1
+ clause: 段
2
+ annex: 附录
@@ -0,0 +1,74 @@
1
+ require "isodoc"
2
+ require "twitter_cldr"
3
+ require 'date'
4
+
5
+ module IsoDoc
6
+ module MPFA
7
+
8
+ class Metadata < IsoDoc::Metadata
9
+ def initialize(lang, script, labels)
10
+ super
11
+ here = File.dirname(__FILE__)
12
+ set(:logo, File.expand_path(File.join(here, "html", "mpfa-logo-no-text@4x.png")))
13
+ end
14
+
15
+ def title(isoxml, _out)
16
+ main = isoxml&.at(ns("//bibdata/title[@language='en']"))&.text
17
+ set(:doctitle, main)
18
+ end
19
+
20
+ def subtitle(_isoxml, _out)
21
+ nil
22
+ end
23
+
24
+ def author(isoxml, _out)
25
+ publisher = isoxml.at(ns("//bibdata/contributor/organization/name"))
26
+ set(:publisher, publisher.text) if publisher
27
+ end
28
+
29
+ def docid(isoxml, _out)
30
+ docnumber = isoxml.at(ns("//bibdata/docidentifier"))
31
+ set(:docnumber, docnumber&.text)
32
+ end
33
+
34
+ def doctype(isoxml, _out)
35
+ b = isoxml&.at(ns("//bibdata/ext/doctype"))&.text || return
36
+ return unless b
37
+ t = b.split(/[- ]/).
38
+ map{ |w| w.capitalize unless w == "MPF" }.join(" ")
39
+ set(:doctype, t)
40
+ end
41
+
42
+ def stage_abbr(status)
43
+ case status
44
+ when "working-draft" then "wd"
45
+ when "committee-draft" then "cd"
46
+ when "draft-standard" then "d"
47
+ else
48
+ ""
49
+ end
50
+ end
51
+
52
+ def version(isoxml, _out)
53
+ super
54
+ edition = isoxml.at(ns("//version/edition"))
55
+ if edition
56
+ set(
57
+ :edition,
58
+ edition.text.to_i.localize.
59
+ to_rbnf_s("SpelloutRules", "spellout-ordinal").
60
+ split(/(\W)/).map(&:capitalize).join
61
+ )
62
+ end
63
+ end
64
+
65
+ def monthyr(isodate)
66
+ date = DateTime.parse(isodate)
67
+ date.strftime('%-d %B %Y') #=> "Sun 04 Feb 2001"
68
+ rescue
69
+ # invalid dates get thrown
70
+ isodate
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,10 @@
1
+ require_relative "base_convert"
2
+ require "isodoc"
3
+
4
+ module IsoDoc
5
+ module MPFA
6
+ class PresentationXMLConvert < IsoDoc::PresentationXMLConvert
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,62 @@
1
+ require_relative "base_convert"
2
+ require "isodoc"
3
+
4
+ module IsoDoc
5
+ module MPFA
6
+ # A {Converter} implementation that generates Word output, and a document
7
+ # schema encapsulation of the document for validation
8
+ class WordConvert < IsoDoc::WordConvert
9
+ def initialize(options)
10
+ @libdir = File.dirname(__FILE__)
11
+ super
12
+ end
13
+
14
+ include BaseConvert
15
+
16
+ def default_fonts(options)
17
+ {
18
+ bodyfont: (options[:script] == "Hans" ? '"SimSun",serif' : '"Arial",sans-serif'),
19
+ headerfont: (options[:script] == "Hans" ? '"SimHei",sans-serif' : '"Arial",sans-serif'),
20
+ monospacefont: '"Courier New",monospace'
21
+ }
22
+ end
23
+
24
+ def default_file_locations(options)
25
+ {
26
+ htmlstylesheet: html_doc_path("htmlstyle.scss"),
27
+ htmlcoverpage: html_doc_path("html_rsd_titlepage.html"),
28
+ htmlintropage: html_doc_path("html_rsd_intro.html"),
29
+ scripts: html_doc_path("scripts.html"),
30
+ wordstylesheet: html_doc_path("wordstyle.scss"),
31
+ standardstylesheet: html_doc_path("rsd.scss"),
32
+ header: html_doc_path("header.html"),
33
+ wordcoverpage: html_doc_path("word_rsd_titlepage.html"),
34
+ wordintropage: html_doc_path("word_rsd_intro.html"),
35
+ ulstyle: "l3",
36
+ olstyle: "l2",
37
+ }
38
+ end
39
+
40
+ def make_body(xml, docxml)
41
+ body_attr = { lang: "EN-US", link: "blue", vlink: "#954F72" }
42
+ xml.body **body_attr do |body|
43
+ make_body1(body, docxml)
44
+ make_body2(body, docxml)
45
+ make_body3(body, docxml)
46
+ end
47
+ end
48
+
49
+ def make_body2(body, docxml)
50
+ body.div **{ class: "WordSection2" } do |div2|
51
+ info docxml, div2
52
+ abstract docxml, div2
53
+ foreword docxml, div2
54
+ introduction docxml, div2
55
+ terms_defs docxml, div2, 0
56
+ div2.p { |p| p << "&nbsp;" } # placeholder
57
+ end
58
+ section_break(body)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,102 @@
1
+ module IsoDoc
2
+ module MPFA
3
+ class Xref < IsoDoc::Xref
4
+ FRONT_CLAUSE = "//*[parent::preface]".freeze
5
+
6
+ def initial_anchor_names(d)
7
+ d.xpath(ns(self.class::FRONT_CLAUSE)).each do |c|
8
+ preface_names(c)
9
+ sequential_asset_names(c)
10
+ end
11
+ middle_section_asset_names(d)
12
+ clause_names(d, 0)
13
+ termnote_anchor_names(d)
14
+ termexample_anchor_names(d)
15
+ end
16
+
17
+ def annex_name_lbl(clause, num)
18
+ l10n("<b>#{@labels['annex']} #{num}</b>")
19
+ end
20
+
21
+ def clause_names(docxml, sect_num)
22
+ q = "//clause[parent::sections]"
23
+ @topnum = nil
24
+ lvl = 0
25
+ docxml.xpath(ns(q)).each do |c|
26
+ container_names(c, 0)
27
+ sect_num, lvl = sect_names(c, nil, sect_num, 0, lvl)
28
+ end
29
+ end
30
+
31
+ def container_names(clause, lvl)
32
+ if clause["container"]
33
+ @anchors[clause["id"]] =
34
+ { label: nil, xref: clause.at(ns("./title"))&.text, level: lvl+1 }
35
+ end
36
+ clause.xpath(ns("./clause | ./term | ./terms | "\
37
+ "./definitions")).each do |c|
38
+ container_names(c, clause["container"] ? lvl+1 : lvl)
39
+ end
40
+ end
41
+
42
+ def sect_names(clause, num, i, lvl, prev_lvl)
43
+ return i if clause.nil?
44
+ curr = i
45
+ if !clause["container"]
46
+ retlvl = lvl
47
+ i+=1
48
+ curr = i
49
+ name = num.nil? ? i.to_s : "#{num}.#{i}"
50
+ @anchors[clause["id"]] = { label: name, level: lvl + 1,
51
+ xref: l10n("#{@labels['clause']} #{name}") }
52
+ end
53
+ prev = lvl
54
+ j = 0
55
+ clause.xpath(ns("./clause | ./term | ./terms | "\
56
+ "./definitions")).each do |c|
57
+ if clause["container"]
58
+ i, lvl = sect_names(c, num, i, lvl, lvl)
59
+ else
60
+ j, prev = sect_names(c, name, j, lvl+1, prev)
61
+ end
62
+ end
63
+ i = j if j >0
64
+ i = curr if lvl < prev
65
+ [i, prev]
66
+ end
67
+
68
+ def annex_naming(c, num, lvl, i)
69
+ if c["guidance"] then annex_names1(c, "#{num}E", lvl + 1)
70
+ else
71
+ i+= 1 unless c["container"]
72
+ annex_names1(c, "#{num}.#{i}", lvl + 1)
73
+ end
74
+ i
75
+ end
76
+
77
+ def annex_names(clause, num)
78
+ @anchors[clause["id"]] = { label: annex_name_lbl(clause, num),
79
+ xref: "#{@labels['annex']} #{num}", level: 1 }
80
+ if a = single_annex_special_section(clause)
81
+ annex_names1(a, "#{num}", 1)
82
+ else
83
+ i = 0
84
+ clause.xpath(ns("./clause | ./references")).each do |c|
85
+ container_names(c, 0)
86
+ i = annex_naming(c, num, 1, i)
87
+ end
88
+ end
89
+ hierarchical_asset_names(clause, num)
90
+ end
91
+
92
+ def annex_names1(clause, num, level)
93
+ clause["container"] or @anchors[clause["id"]] =
94
+ { label: num, xref: "#{@labels['annex']} #{num}", level: level }
95
+ i = 0
96
+ clause.xpath(ns("./clause | ./references")).each do |c|
97
+ i = annex_naming(c, num, level, i)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,11 @@
1
+ require "asciidoctor" unless defined? Asciidoctor::Converter
2
+ require_relative "asciidoctor/mpfa/converter"
3
+ require_relative "isodoc/mpfa/html_convert"
4
+ require_relative "isodoc/mpfa/word_convert"
5
+ require_relative "isodoc/mpfa/presentation_xml_convert"
6
+ require_relative "metanorma/mpfa/version"
7
+
8
+ if defined? Metanorma
9
+ require_relative "metanorma/mpfa"
10
+ Metanorma::Registry.instance.register(Metanorma::MPFA::Processor)
11
+ end
@@ -0,0 +1,7 @@
1
+ require_relative "./mpfa/processor"
2
+
3
+ module Metanorma
4
+ module MPFA
5
+
6
+ end
7
+ end
@@ -0,0 +1,49 @@
1
+ require "metanorma/processor"
2
+
3
+ module Metanorma
4
+ module MPFA
5
+ def self.fonts_used
6
+ {
7
+ html: ["Titillium Web", "Space Mono"],
8
+ doc: ["Arial", "Courier New"],
9
+ }
10
+ end
11
+
12
+ class Processor < Metanorma::Processor
13
+
14
+ def initialize
15
+ @short = [:mpfd, :mpfa]
16
+ @input_format = :asciidoc
17
+ @asciidoctor_backend = :mpfa
18
+ end
19
+
20
+ def output_formats
21
+ super.merge(
22
+ html: "html",
23
+ doc: "doc"
24
+ )
25
+ end
26
+
27
+ def version
28
+ "Metanorma::MPFA #{Metanorma::MPFA::VERSION}"
29
+ end
30
+
31
+ def input_to_isodoc(file, filename)
32
+ Metanorma::Input::Asciidoc.new.process(file, filename, @asciidoctor_backend)
33
+ end
34
+
35
+ def output(isodoc_node, inname, outname, format, options={})
36
+ case format
37
+ when :html
38
+ IsoDoc::MPFA::HtmlConvert.new(options).convert(inname, isodoc_node, nil, outname)
39
+ when :doc
40
+ IsoDoc::MPFA::WordConvert.new(options).convert(inname, isodoc_node, nil, outname)
41
+ when :presentation
42
+ IsoDoc::MPFA::PresentationXMLConvert.new(options).convert(inname, isodoc_node, nil, outname)
43
+ else
44
+ super
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,5 @@
1
+ module Metanorma
2
+ module MPFA
3
+ VERSION = "0.4.0"
4
+ end
5
+ end
@@ -0,0 +1,46 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "metanorma/mpfa/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "metanorma-mpfa"
7
+ spec.version = Metanorma::MPFA::VERSION
8
+ spec.authors = ["Ribose Inc."]
9
+ spec.email = ["open.source@ribose.com"]
10
+
11
+ spec.summary = "metanorma-mpfa lets you write MPFA documents in AsciiDoc."
12
+ spec.description = <<~DESCRIPTION
13
+ metanorma-mpfa lets you write MPFA documents in AsciiDoc syntax.
14
+
15
+ This gem is in active development.
16
+
17
+ Formerly known as metanorma-mpfd
18
+ DESCRIPTION
19
+
20
+ spec.homepage = "https://github.com/metanorma/metanorma-mpfa"
21
+ spec.license = "BSD-2-Clause"
22
+
23
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
24
+ f.match(%r{^(test|spec|features)/})
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
30
+
31
+ spec.add_dependency "htmlentities", "~> 4.3.4"
32
+ #spec.add_dependency "nokogiri"
33
+ spec.add_dependency "metanorma-standoc", "~> 1.4.0"
34
+ spec.add_dependency "isodoc", "~> 1.1.0"
35
+ spec.add_dependency "twitter_cldr"
36
+
37
+ spec.add_development_dependency "byebug", "~> 9.1"
38
+ spec.add_development_dependency "equivalent-xml", "~> 0.6"
39
+ spec.add_development_dependency "guard", "~> 2.14"
40
+ spec.add_development_dependency "guard-rspec", "~> 4.7"
41
+ spec.add_development_dependency "rake", "~> 12.0"
42
+ spec.add_development_dependency "rspec", "~> 3.6"
43
+ spec.add_development_dependency "rubocop", "= 0.54.0"
44
+ spec.add_development_dependency "simplecov", "~> 0.15"
45
+ spec.add_development_dependency "timecop", "~> 0.9"
46
+ end