isodoc 1.3.1 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29fb94d37c013e802491e2c1266e8b39d607ea3050f272f1a7bcd398e57c0283
4
- data.tar.gz: 85ea530071d54477f462d34a5b18dbf9ba500b71a4d5ea858b62530757a6b795
3
+ metadata.gz: 691e16d8f19de5c4008d22686af0f70594dea57d039e7d4e265763a02cc8eea3
4
+ data.tar.gz: 4aca2f6a4b06fa9c6dd3235ee8581e94060f47eb3fe8dc9de9a6b6aa5ee356f2
5
5
  SHA512:
6
- metadata.gz: 9539cdc3d0fac50a04aa3cdf93581016306b660f1d0681a8a1e06255ed839ac9362c887b9a6f0ef7480711122c5275e0936fab640efff76c84aaa5ad84831f84
7
- data.tar.gz: b05012f1f7189becfa14871de424ae5713a8791a9c0b520cdcca591d3f733d996c776d2f37d2c1ff23fdff6b2c146b6e09d2f9c5b97dcbeec43edafd9785dfcb
6
+ metadata.gz: 1ac28f83694610bab479de1bed5921c3d5807ab337dd2926555b66a7e5c1f5912c320a335089a4c7a617e816f1d8957bf923c986813e3374316ef472f825f7c2
7
+ data.tar.gz: d472986686451eab5674ce530a2a8fb2a82660d345280ae4ce57425c8920f135a789536ae4d0b05b952a8ea44efcaaf5122bc266cb6f17aee2fb6b4d79d1ca79
@@ -16,17 +16,17 @@ jobs:
16
16
  strategy:
17
17
  fail-fast: false
18
18
  matrix:
19
- ruby: [ '2.6', '2.5', '2.4' ]
19
+ ruby: [ '2.7', '2.6', '2.5', '2.4' ]
20
20
  os: [ ubuntu-latest, windows-latest, macos-latest ]
21
21
  experimental: [ false ]
22
22
  include:
23
- - ruby: '2.7'
23
+ - ruby: '3.0'
24
24
  os: 'ubuntu-latest'
25
25
  experimental: true
26
- - ruby: '2.7'
26
+ - ruby: '3.0'
27
27
  os: 'windows-latest'
28
28
  experimental: true
29
- - ruby: '2.7'
29
+ - ruby: '3.0'
30
30
  os: 'macos-latest'
31
31
  experimental: true
32
32
  steps:
@@ -35,35 +35,19 @@ jobs:
35
35
  - uses: ruby/setup-ruby@v1
36
36
  with:
37
37
  ruby-version: ${{ matrix.ruby }}
38
+ bundler-cache: true
38
39
 
39
- - uses: actions/cache@v2
40
- with:
41
- path: vendor/bundle
42
- key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
43
- restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
44
-
45
- - run: bundle config set path 'vendor/bundle'
46
-
47
- - run: bundle install --jobs 4 --retry 3
48
-
49
- - name: Install Inkscape macOS
50
- if: matrix.os == 'macos-latest'
51
- run: |
52
- brew cask install inkscape
53
- inkscape --version
54
-
55
- - name: Install Inkscape Ubuntu
56
- if: matrix.os == 'ubuntu-latest'
57
- run: |
58
- sudo add-apt-repository ppa:inkscape.dev/stable
59
- sudo apt update
60
- sudo apt install inkscape
61
- inkscape --version
62
-
63
- - name: Install Inkscape Windows
64
- if: matrix.os == 'windows-latest'
65
- run: |
66
- choco install --no-progress -y inkscape
67
- inkscape --version
40
+ - uses: metanorma/metanorma-build-scripts/inkscape-setup-action@master
68
41
 
69
42
  - run: bundle exec rake
43
+
44
+ tests-passed:
45
+ needs: rake
46
+ runs-on: ubuntu-latest
47
+ steps:
48
+ - uses: peter-evans/repository-dispatch@v1
49
+ with:
50
+ token: ${{ secrets.METANORMA_CI_PAT_TOKEN || secrets.GITHUB_TOKEN }}
51
+ repository: ${{ github.repository }}
52
+ event-type: notify
53
+ client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'
data/isodoc.gemspec CHANGED
@@ -30,11 +30,11 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_dependency "asciimath"
32
32
  spec.add_dependency "htmlentities", "~> 4.3.4"
33
- spec.add_dependency "nokogiri", ">= 1.10.4"
33
+ spec.add_dependency "nokogiri", "~> 1.10.4"
34
34
  spec.add_dependency "thread_safe"
35
35
  spec.add_dependency "uuidtools"
36
36
  spec.add_dependency "html2doc", "~> 1.0.0"
37
- spec.add_dependency "liquid"
37
+ spec.add_dependency "liquid", "~> 4"
38
38
  spec.add_dependency "twitter_cldr"
39
39
  spec.add_dependency "roman-numerals"
40
40
  spec.add_dependency "metanorma", "~> 1.2.0"
@@ -50,4 +50,5 @@ Gem::Specification.new do |spec|
50
50
  spec.add_development_dependency "rubocop", "= 0.54.0"
51
51
  spec.add_development_dependency "simplecov", "~> 0.15"
52
52
  spec.add_development_dependency "timecop", "~> 0.9"
53
+ spec.add_development_dependency "rexml"
53
54
  end
@@ -97,3 +97,58 @@ locality: {
97
97
  note: Note,
98
98
  formula: Formula
99
99
  }
100
+ inflection:
101
+ Clause:
102
+ sg: Clause
103
+ pl: Clauses
104
+ Annex:
105
+ sg: Annex
106
+ pl: Annexes
107
+ Appendix:
108
+ sg: Appendix
109
+ pl: Appendixes
110
+ Note:
111
+ sg: Note
112
+ pl: Notes
113
+ "Note % to entry":
114
+ sg: Note % to entry
115
+ pl: Notes % to entry
116
+ List:
117
+ sg: List
118
+ pl: Lists
119
+ Figure:
120
+ sg: Figure
121
+ pl: Figures
122
+ Formula:
123
+ sg: Formula
124
+ pl: Formulas
125
+ Table:
126
+ sg: Table
127
+ pl: Tables
128
+ Requirement:
129
+ sg: Requirement
130
+ pl: Requirements
131
+ Recommendation:
132
+ sg: Recommendation
133
+ pl: Recommendations
134
+ Permission:
135
+ sg: Permission
136
+ pl: Permissions
137
+ Example:
138
+ sg: Example
139
+ pl: Examples
140
+ Part:
141
+ sg: Part
142
+ pl: Parts
143
+ Section:
144
+ sg: Section
145
+ pl: Sections
146
+ Paragraph:
147
+ sg: Paragraph
148
+ pl: Paragraphs
149
+ Chapter:
150
+ sg: Chapter
151
+ pl: Chapters
152
+ Page:
153
+ sg: Page
154
+ pl: Pages
@@ -90,3 +90,59 @@ locality: {
90
90
  note: Note,
91
91
  formula: Formule
92
92
  }
93
+ inflection:
94
+ Clause:
95
+ sg: Article
96
+ pl: Articles
97
+ Annex:
98
+ sg: Annexe
99
+ pl: Annexes
100
+ Appendix:
101
+ sg: Appendice
102
+ pl: Appendices
103
+ Note:
104
+ sg: Note
105
+ pl: Notes
106
+ "Note % à l’article":
107
+ sg: Note % à l’article
108
+ pl: Notes % à l’article
109
+ List:
110
+ sg: Liste
111
+ pl: Listes
112
+ Figure:
113
+ sg: Figure
114
+ pl: Figures
115
+ Formula:
116
+ sg: Formule
117
+ pl: Formules
118
+ Table:
119
+ sg: Tableau
120
+ pl: Tableaux
121
+ Requirement:
122
+ sg: Exigence
123
+ pl: Exigences
124
+ Recommendation:
125
+ sg: Recommandation
126
+ pl: Recommandations
127
+ Permission:
128
+ sg: Autorisation
129
+ pl: Autorisations
130
+ Example:
131
+ sg: Exemple
132
+ pl: Exemples
133
+ Part:
134
+ sg: Partie
135
+ pl: Parties
136
+ Section:
137
+ sg: Section
138
+ pl: Sections
139
+ Paragraph:
140
+ sg: Alinéa
141
+ pl: Alinéas
142
+ Chapter:
143
+ sg: Chapitre
144
+ pl: Chapitres
145
+ Page:
146
+ sg: Page
147
+ pl: Pages
148
+
@@ -9,6 +9,7 @@ module IsoDoc
9
9
  class Convert < ::IsoDoc::Common
10
10
  attr_accessor :options
11
11
  attr_accessor :i18n
12
+ attr_accessor :meta
12
13
 
13
14
  # htmlstylesheet: Generic stylesheet for HTML
14
15
  # wordstylesheet: Generic stylesheet for Word
@@ -157,7 +158,7 @@ module IsoDoc
157
158
  FileUtils.rm_rf dir
158
159
  end
159
160
 
160
- def middle_clause
161
+ def middle_clause(docxml = nil)
161
162
  "//clause[parent::sections][not(@type = 'scope')]"\
162
163
  '[not(descendant::terms)]'
163
164
  end
@@ -39,7 +39,7 @@ module IsoDoc::Function
39
39
  "uri[@type = 'citation']"))
40
40
  return href unless url
41
41
  href = suffix_url(url.text)
42
- anchor = node&.at(ns(".//locality[@type = 'anchor']"))&.text
42
+ anchor = node&.at(ns(".//locality[@type = 'anchor']"))&.text&.strip
43
43
  anchor and href += "##{anchor}"
44
44
  href
45
45
  end
@@ -71,5 +71,11 @@ module IsoDoc::Function
71
71
  node.children.each { |n| parse(n, e) }
72
72
  end
73
73
  end
74
+
75
+ def underline_parse(node, out)
76
+ out.u do |e|
77
+ node.children.each { |n| parse(n, e) }
78
+ end
79
+ end
74
80
  end
75
81
  end
@@ -56,7 +56,7 @@ module IsoDoc::Function
56
56
  end
57
57
 
58
58
  def clause(isoxml, out)
59
- isoxml.xpath(ns(middle_clause)).each do |c|
59
+ isoxml.xpath(ns(middle_clause(isoxml))).each do |c|
60
60
  out.div **attr_code(clause_attrs(c)) do |s|
61
61
  clause_name(nil, c&.at(ns("./title")), s, nil)
62
62
  c.elements.reject { |c1| c1.name == "title" }.each do |c1|
@@ -109,7 +109,7 @@ module IsoDoc::Function
109
109
  @meta.get
110
110
  end
111
111
 
112
- def middle_title(out)
112
+ def middle_title(_isoxml, out)
113
113
  out.p(**{ class: "zzSTDTitle1" }) { |p| p << @meta.get[:doctitle] }
114
114
  end
115
115
 
@@ -120,7 +120,7 @@ module IsoDoc::Function
120
120
  end
121
121
 
122
122
  def middle(isoxml, out)
123
- middle_title(out)
123
+ middle_title(isoxml, out)
124
124
  middle_admonitions(isoxml, out)
125
125
  i = scope isoxml, out, 0
126
126
  i = norm_ref isoxml, out, i
@@ -157,6 +157,7 @@ module IsoDoc::Function
157
157
  when "sub" then sub_parse(node, out)
158
158
  when "tt" then tt_parse(node, out)
159
159
  when "strike" then strike_parse(node, out)
160
+ when "underline" then underline_parse(node, out)
160
161
  when "keyword" then keyword_parse(node, out)
161
162
  when "smallcap" then smallcap_parse(node, out)
162
163
  when "br" then br_parse(node, out)
@@ -152,8 +152,8 @@ module IsoDoc::Function
152
152
  def populate_template(docxml, _format = nil)
153
153
  meta = @meta
154
154
  .get
155
- .merge(@labels || {})
156
- .merge(@meta.labels || {})
155
+ .merge(@labels ? {labels: @labels} : {})
156
+ .merge(@meta.labels ? {labels: @meta.labels} : {})
157
157
  .merge(fonts_options || {})
158
158
  template = liquid(docxml)
159
159
  template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
@@ -161,7 +161,7 @@ module IsoDoc::Function
161
161
  end
162
162
 
163
163
  def save_dataimage(uri, _relative_dir = true)
164
- %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
164
+ %r{^data:(image|application)/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
165
165
  imgtype.sub!(/\+[a-z0-9]+$/, '') # svg+xml
166
166
  imgtype = 'png' unless /^[a-z0-9]+$/.match imgtype
167
167
  Tempfile.open(['image', ".#{imgtype}"]) do |f|
@@ -173,7 +173,7 @@ module IsoDoc::Function
173
173
  end
174
174
 
175
175
  def image_localfile(i)
176
- if /^data:image/.match? i['src']
176
+ if /^data:/.match? i['src']
177
177
  save_dataimage(i['src'], false)
178
178
  elsif %r{^([A-Z]:)?/}.match? i['src']
179
179
  i['src']
@@ -111,6 +111,12 @@ module IsoDoc::HtmlFunction
111
111
  sourcecode_name_parse(node, out, name)
112
112
  end
113
113
 
114
+ def underline_parse(node, out)
115
+ out.span **{ style: "text-decoration: underline;" } do |e|
116
+ node.children.each { |n| parse(n, e) }
117
+ end
118
+ end
119
+
114
120
  def table_long_strings_cleanup(docxml)
115
121
  end
116
122
  end
@@ -0,0 +1,82 @@
1
+ module IsoDoc
2
+ module HtmlFunction
3
+ # Class for recursively converting mathvariant text into plain text symbols
4
+ class MathvariantToPlain
5
+ MATHML = { "m" => "http://www.w3.org/1998/Math/MathML" }.freeze
6
+ MATHVARIANT_SPECIAL_CASE_MAPPINGS_1 = %w[bold italic sans-serif]
7
+ .permutation
8
+ .each_with_object(:sansbolditalic)
9
+ .map { |n, y| [n, y] }
10
+ .to_h
11
+ .freeze
12
+ MATHVARIANT_SPECIAL_CASE_MAPPINGS_2 = {
13
+ %w[bold fraktur] => :frakturbold,
14
+ %w[bold script] => :scriptbold,
15
+ %w[sans-serif bold] => :sansbold,
16
+ %w[sans-serif italic] => :sansitalic,
17
+ %w[sans-serif bold-italic] => :sansbolditalic,
18
+ %w[bold-sans-serif italic] => :sansbolditalic,
19
+ %w[sans-serif-italic bold] => :sansbolditalic,
20
+ }.freeze
21
+ MATHVARIANT_TO_PLANE_MAPPINGS = {
22
+ %w[double-struck] => :doublestruck,
23
+ %w[bold-fraktur] => :frakturbold,
24
+ %w[script] => :script,
25
+ %w[bold-script] => :scriptbold,
26
+ %w[fraktur] => :fraktur,
27
+ %w[sans-serif] => :sans,
28
+ %w[bold-sans-serif] => :sansbold,
29
+ %w[sans-serif-italic] => :sansitalic,
30
+ %w[sans-serif-bold-italic] => :sansbolditalic,
31
+ %w[monospace] => :monospace,
32
+ }.freeze
33
+
34
+ attr_reader :docxml
35
+
36
+ # @param [Nokogiri::Document] docxml
37
+ def initialize(docxml)
38
+ @docxml = docxml
39
+ end
40
+
41
+ def convert
42
+ docxml.xpath("//m:math", MATHML).each do |elem|
43
+ next if nothing_to_style(elem)
44
+ mathml1(elem)
45
+ end
46
+ docxml
47
+ end
48
+
49
+ private
50
+
51
+ def nothing_to_style(elem)
52
+ !elem.at("./*[@mathvariant][not(@mathvariant = 'normal')][not(@mathvariant = 'italic')]")
53
+ end
54
+
55
+ def mathml1(base_elem)
56
+ MATHVARIANT_SPECIAL_CASE_MAPPINGS_1
57
+ .merge(MATHVARIANT_SPECIAL_CASE_MAPPINGS_2)
58
+ .merge(MATHVARIANT_TO_PLANE_MAPPINGS)
59
+ .each_pair do |mathvariant_list, plain_font|
60
+ base_elem.xpath(mathvariant_xpath(mathvariant_list)).each do |elem|
61
+ toPlane(elem, plain_font)
62
+ end
63
+ end
64
+ end
65
+
66
+ def mathvariant_xpath(list)
67
+ list
68
+ .map { |variant| "//*[@mathvariant = '#{variant}']" }
69
+ .join
70
+ end
71
+
72
+ def toPlane(elem, font)
73
+ elem.traverse do |n|
74
+ next unless n.text?
75
+
76
+ n.replace(Plane1Converter.conv(HTMLEntities.new.decode(n.text), font))
77
+ end
78
+ elem
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,35 +1,47 @@
1
+ require "isodoc/html_function/mathvariant_to_plain"
2
+
1
3
  module IsoDoc::HtmlFunction
2
4
  module Html
3
- def postprocess(result, filename, dir)
5
+ def postprocess(result, filename, _dir)
4
6
  result = from_xhtml(cleanup(to_xhtml(textcleanup(result))))
5
7
  toHTML(result, filename)
6
8
  @files_to_delete.each { |f| FileUtils.rm_rf f }
7
9
  end
8
10
 
9
11
  def script_cdata(result)
10
- result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>").
11
- gsub(%r{\]\]>\s*</script>}, "</script>").
12
- gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>").
13
- gsub(%r{</script>\s*\]\]>}, "</script>")
12
+ result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>")
13
+ .gsub(%r{\]\]>\s*</script>}, "</script>")
14
+ .gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>")
15
+ .gsub(%r{</script>\s*\]\]>}, "</script>")
14
16
  end
15
17
 
16
18
  def toHTML(result, filename)
17
- result = (from_xhtml(html_cleanup(to_xhtml(result))))
18
- #result = populate_template(result, :html)
19
+ result = from_xhtml(html_cleanup(to_xhtml(result)))
20
+ # result = populate_template(result, :html)
19
21
  result = from_xhtml(move_images(to_xhtml(result)))
20
22
  result = html5(script_cdata(inject_script(result)))
21
23
  File.open(filename, "w:UTF-8") { |f| f.write(result) }
22
24
  end
23
25
 
24
26
  def html5(doc)
25
- doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>").
26
- sub(%r{<\?xml[^>]+>}, "")
27
+ doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>")
28
+ .sub(%r{<\?xml[^>]+>}, "")
27
29
  end
28
30
 
29
31
  def html_cleanup(x)
30
- footnote_format(footnote_backlinks(html_toc(
31
- term_header((html_footnote_filter(html_preface(htmlstyle(x))))))
32
- ))
32
+ mathml(
33
+ footnote_format(
34
+ footnote_backlinks(
35
+ html_toc(
36
+ term_header(html_footnote_filter(html_preface(htmlstyle(x))))
37
+ )
38
+ )
39
+ )
40
+ )
41
+ end
42
+
43
+ def mathml(docxml)
44
+ IsoDoc::HtmlFunction::MathvariantToPlain.new(docxml).convert
33
45
  end
34
46
 
35
47
  def htmlstylesheet
@@ -76,14 +88,14 @@ module IsoDoc::HtmlFunction
76
88
  def html_cover(docxml)
77
89
  doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
78
90
  d = docxml.at('//div[@class="title-section"]')
79
- #d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
91
+ # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
80
92
  d.children.first.add_previous_sibling populate_template(doc.to_xml(encoding: "US-ASCII"), :html)
81
93
  end
82
94
 
83
95
  def html_intro(docxml)
84
96
  doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
85
97
  d = docxml.at('//div[@class="prefatory-section"]')
86
- #d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
98
+ # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
87
99
  d.children.first.add_previous_sibling populate_template(doc.to_xml(encoding: "US-ASCII"), :html)
88
100
  end
89
101
 
@@ -93,19 +105,19 @@ module IsoDoc::HtmlFunction
93
105
  end
94
106
 
95
107
  def toclevel_classes
96
- (1..@htmlToClevels).inject([]) { |m, i| m << "h#{i}" }
108
+ (1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
97
109
  end
98
110
 
99
111
  def toclevel
100
112
  ret = toclevel_classes.map { |l| "#{l}:not(:empty):not(.TermNum):not(.noTOC)" }
101
113
  <<~HEAD.freeze
102
- function toclevel() { return "#{ret.join(',')}";}
114
+ function toclevel() { return "#{ret.join(',')}";}
103
115
  HEAD
104
116
  end
105
117
 
106
118
  # needs to be same output as toclevel
107
119
  def html_toc(docxml)
108
- idx = docxml.at("//div[@id = 'toc']") or return docxml
120
+ (idx = docxml.at("//div[@id = 'toc']")) or (return docxml)
109
121
  toc = "<ul>"
110
122
  path = toclevel_classes.map do |l|
111
123
  "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][text()]"
@@ -125,7 +137,7 @@ module IsoDoc::HtmlFunction
125
137
  docxml.xpath("//*[local-name() = 'img']").each do |i|
126
138
  i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i),
127
139
  @maxheight, @maxwidth)
128
- next if /^data:image/.match i["src"]
140
+ next if /^data:/.match i["src"]
129
141
  @datauriimage ? datauri(i) : move_image1(i)
130
142
  end
131
143
  docxml
@@ -133,9 +145,10 @@ module IsoDoc::HtmlFunction
133
145
 
134
146
  def datauri(i)
135
147
  type = i["src"].split(".")[-1]
148
+ supertype = type == "xml" ? "application" : "image"
136
149
  bin = IO.binread(image_localfile(i))
137
150
  data = Base64.strict_encode64(bin)
138
- i["src"] = "data:image/#{type};base64,#{data}"
151
+ i["src"] = "data:#{supertype}/#{type};base64,#{data}"
139
152
  end
140
153
 
141
154
  def image_suffix(i)