asciimath2unitsml 0.3.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfcf63b9b9f9f447f63f744608bb19423025756a5f174a123acb5fbecb2143a4
4
- data.tar.gz: a45ba18eb0b8090ba886453bedf91ed18f531afc31061a90e9f33a6bc6e0085b
3
+ metadata.gz: b4d619489e5063d9e3616163d69c6c1f4796615412ee40f0a92f356603f0e366
4
+ data.tar.gz: 0465ac8a99f8929d1d4f8f2db152821e4d1fae7ac66af1a8a3e2feb6092e0c3a
5
5
  SHA512:
6
- metadata.gz: 61c26594d8ab5b4ab07439085ce23de798b8f4e38c0272790a60d64a247f10a19778e4d0cbdb37b9a3a79d6994a6a14ebf97c0dd031551366019ebe2905c5612
7
- data.tar.gz: e60ff3e91ff37a31ac3d5ac0beccb30c5f05c9c9590e1cc0dd01915ff1c9b57520af1d11b14c1b718173d7258a41b318f67db4a509ccd3ed3b4af43501b50d87
6
+ metadata.gz: 3de256a40d7eb24439409664a8b7bb14f1893403a4cfc762b70bd9693a15c0304766a7d20491de4094571fd5b117695350a5ad56100cf67bde1e7c61c4e99004
7
+ data.tar.gz: 4f053e85ff192f040856d0f63ff2d1ffb7a49eb72735f668785a3396e82ff145b8d678d754b8a26b26deee4c3072de4f8af8686f7ee60cb9e339dfe3f7be08c3
@@ -16,21 +16,11 @@ jobs:
16
16
  strategy:
17
17
  fail-fast: false
18
18
  matrix:
19
- ruby: [ '2.7', '2.6', '2.5', '2.4' ]
19
+ ruby: [ '3.0', '2.7', '2.6', '2.5' ]
20
20
  os: [ ubuntu-latest, windows-latest, macos-latest ]
21
21
  experimental: [ false ]
22
- include:
23
- - ruby: '3.0'
24
- os: 'ubuntu-latest'
25
- experimental: true
26
- - ruby: '3.0'
27
- os: 'windows-latest'
28
- experimental: true
29
- - ruby: '3.0'
30
- os: 'macos-latest'
31
- experimental: true
32
22
  steps:
33
- - uses: actions/checkout@master
23
+ - uses: actions/checkout@v2
34
24
  with:
35
25
  submodules: true
36
26
 
@@ -40,14 +30,3 @@ jobs:
40
30
  bundler-cache: true
41
31
 
42
32
  - 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/.hound.yml ADDED
@@ -0,0 +1,5 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ ruby:
4
+ enabled: true
5
+ config_file: .rubocop.yml
data/.rubocop.yml CHANGED
@@ -1,14 +1,10 @@
1
- # This project follows the Ribose OSS style guide.
2
- # https://github.com/riboseinc/oss-guides
3
- # All project-specific additions and overrides should be specified in this file.
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
4
3
  inherit_from:
5
4
  - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
6
5
 
7
6
  # local repo-specific modifications
7
+ # ...
8
8
 
9
9
  AllCops:
10
- DisplayCopNames: false
11
- StyleGuideCopsOnly: false
12
- TargetRubyVersion: 2.4
13
- Rails:
14
- Enabled: true
10
+ TargetRubyVersion: 2.5
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source "https://rubygems.org"
2
-
2
+
3
3
  # Specify your gem's dependencies in ruby-vobject.gemspec
4
4
  gemspec
data/README.adoc CHANGED
@@ -59,6 +59,24 @@ units. The options are an XML entity, or the values `space` or `nospace` (for wh
59
59
  Standalone prefixes can be recognised by replacing the unit with hyphen; so `unitsml(p-)` corresponds
60
60
  to the standalone prefix "pico" (and is rendered as "p").
61
61
 
62
+ The gem also supports fundamental units, e.g. `unitsml(e)` for the atomic unit of charge, _e_,
63
+ and symbols for dimensions. The latter are entered as `dim_XXX`, where `XXX` is their established symbol:
64
+
65
+ |===
66
+ |Symbol | Dimension
67
+
68
+ |dim_L | Length
69
+ |dim_M | Mass
70
+ |dim_T | Time
71
+ |dim_I | Electric Current
72
+ |dim_Theta | Thermodynamic Temperature
73
+ |dim_N | Amount of Substance
74
+ |dim_J | Luminous Intensity
75
+ |dim_phi | Plane Angle (dimensionless)
76
+ |===
77
+
78
+ e.g. `unitsml(dim_I)` for the dimension of electric current, 𝖨.
79
+
62
80
  == Rendering
63
81
 
64
82
  The output of the gem is MathML, with MathML unit expressions (expressed as `<mi>`,
@@ -141,7 +159,7 @@ The converter is run as:
141
159
  [source,ruby]
142
160
  ----
143
161
  c = Asciimath2UnitsML::Conv.new()
144
- c.Asciimath2UnitsML(1 "unitsml(mm*s^-2)") # AsciiMath string containing UnitsML
162
+ c.Asciimath2UnitsML('1 "unitsml(mm*s^-2)"') # AsciiMath string containing UnitsML
145
163
  c.MathML2UnitsML("<math xmlns='http://www.w3.org/1998/Math/MathML'><mn>7</mn>"\
146
164
  "<mtext>unitsml(kg^-2)</mtext></math>") # AsciiMath string containing <mtext>unitsml()</mtext>
147
165
  c.MathML2UnitsML(Nokogiri::XML("<math xmlns='http://www.w3.org/1998/Math/MathML'><mn>7</mn>"\
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path("lib", __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require "asciimath2unitsml/version"
6
6
 
@@ -22,32 +22,30 @@ Gem::Specification.new do |spec|
22
22
  spec.require_paths = ["lib"]
23
23
  spec.files = `git ls-files`.split("\n")
24
24
  spec.test_files = `git ls-files -- {spec}/*`.split("\n")
25
- spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
25
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
26
26
 
27
27
  # get an array of submodule dirs relatively to root repo
28
28
  `git config --file .gitmodules --get-regexp '\\.path$'`
29
29
  .split("\n")
30
30
  .map { |kv_str| kv_str.split(" ") }
31
31
  .each do |(_, submodule_path)|
32
+ # for each submodule, change working directory to that submodule
33
+ Dir.chdir(submodule_path) do
34
+ # issue git ls-files in submodule's directory
35
+ submodule_files = `git ls-files | grep -i '.yaml$'`.split($\)
32
36
 
33
- # for each submodule, change working directory to that submodule
34
- Dir.chdir(submodule_path) do
35
-
36
- # issue git ls-files in submodule's directory
37
- submodule_files = `git ls-files | grep -i '.yaml$'`.split($\)
38
-
39
- submodule_files_paths = submodule_files.map do |filename|
40
- File.join submodule_path, filename
41
- end
42
-
43
- # add relative paths to gem.files
44
- spec.files += submodule_files_paths
37
+ submodule_files_paths = submodule_files.map do |filename|
38
+ File.join submodule_path, filename
45
39
  end
40
+
41
+ # add relative paths to gem.files
42
+ spec.files += submodule_files_paths
43
+ end
46
44
  end
47
45
 
48
46
  spec.add_dependency "asciimath"
49
47
  spec.add_dependency "htmlentities"
50
- spec.add_dependency "nokogiri", "~> 1.10.4"
48
+ spec.add_dependency "nokogiri", "~> 1.11"
51
49
  spec.add_dependency "rsec", "~> 1.0.0"
52
50
 
53
51
  spec.add_development_dependency "bundler"
@@ -56,10 +54,9 @@ Gem::Specification.new do |spec|
56
54
  spec.add_development_dependency "guard", "~> 2.14"
57
55
  spec.add_development_dependency "guard-rspec", "~> 4.7"
58
56
  spec.add_development_dependency "rake", "~> 12.0"
57
+ spec.add_development_dependency "rexml"
59
58
  spec.add_development_dependency "rspec", "~> 3.6"
60
59
  spec.add_development_dependency "rubocop", "~> 1.5.2"
61
60
  spec.add_development_dependency "simplecov", "~> 0.15"
62
61
  spec.add_development_dependency "timecop", "~> 0.9"
63
- spec.add_development_dependency "rexml"
64
62
  end
65
-
data/bin/rspec CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
-
2
+
3
3
  # This file was generated by Bundler.
4
4
  #
5
5
  # The application 'rspec' is installed as part of a gem, and
@@ -15,4 +15,3 @@ require "rubygems"
15
15
  require "bundler/setup"
16
16
 
17
17
  load Gem.bin_path("rspec-core", "rspec")
18
-
@@ -1,4 +1,3 @@
1
1
  require_relative "asciimath2unitsml/version"
2
2
  require_relative "asciimath2unitsml/conv"
3
3
  require_relative "unitsdb_ruby/unitsdb"
4
-
@@ -3,10 +3,13 @@ require "nokogiri"
3
3
  require "htmlentities"
4
4
  require "yaml"
5
5
  require "rsec"
6
+ require_relative "read"
7
+ require_relative "dimensions"
6
8
  require_relative "string"
7
9
  require_relative "parse"
8
10
  require_relative "render"
9
11
  require_relative "unit"
12
+ require_relative "validate"
10
13
 
11
14
  module Asciimath2UnitsML
12
15
  MATHML_NS = "http://www.w3.org/1998/Math/MathML".freeze
@@ -14,120 +17,86 @@ module Asciimath2UnitsML
14
17
 
15
18
  class Conv
16
19
  def initialize(options = {})
17
- @dimensions_id = read_yaml("../unitsdb/dimensions.yaml").
18
- each_with_object({}) do |(k, v), m|
20
+ @dimensions_id = read_yaml("../unitsdb/dimensions.yaml")
21
+ .each_with_object({}) do |(k, v), m|
19
22
  m[k.to_s] = UnitsDB::Dimension.new(k, v)
20
23
  end
21
- @prefixes_id = read_yaml("../unitsdb/prefixes.yaml").
22
- each_with_object({}) do |(k, v), m|
24
+ @dimensions = flip_name_and_symbols(@dimensions_id)
25
+ @prefixes_id = read_yaml("../unitsdb/prefixes.yaml")
26
+ .each_with_object({}) do |(k, v), m|
23
27
  m[k] = UnitsDB::Prefix.new(k, v)
24
28
  end
25
29
  @prefixes = flip_name_and_symbol(@prefixes_id)
26
- @quantities = read_yaml("../unitsdb/quantities.yaml").
27
- each_with_object({}) do |(k, v), m|
30
+ @quantities = read_yaml("../unitsdb/quantities.yaml")
31
+ .each_with_object({}) do |(k, v), m|
28
32
  m[k.to_s] = UnitsDB::Quantity.new(k, v)
29
33
  end
30
- @units_id = read_yaml("../unitsdb/units.yaml").
31
- each_with_object({}) do |(k, v), m|
34
+ @units_id = read_yaml("../unitsdb/units.yaml")
35
+ .each_with_object({}) do |(k, v), m|
32
36
  m[k.to_s] = UnitsDB::Unit.new(k.to_s, v)
33
37
  end
34
38
  @units = flip_name_and_symbols(@units_id)
35
- @symbols = @units.each_with_object({}) do |(k, v), m|
39
+ @symbols = @units.merge(@dimensions).each_with_object({}) do |(_k, v), m|
36
40
  v.symbolids.each { |x| m[x] = v.symbols_hash[x] }
37
41
  end
38
- @parser = parser
39
- @multiplier = multiplier(options[:multiplier] || "\u00b7")
42
+ @parser, @dim_parser = parsers
43
+ @multiplier = multiplier(options[:multiplier] || "\u22c5")
40
44
  end
41
45
 
42
- def float_to_display(f)
43
- ret = f.to_f.round(1).to_s.sub(/\.0$/, "")
46
+ def float_to_display(float)
47
+ float.to_f.round(1).to_s.sub(/\.0$/, "")
44
48
  end
45
49
 
46
50
  def prefix(units)
47
- units.map { |u| u[:prefix] }.reject { |u| u.nil? }.uniq.map do |p|
48
- <<~END
49
- <Prefix xmlns='#{UNITSML_NS}' prefixBase='#{@prefixes[p].base}'
50
- prefixPower='#{@prefixes[p].power}' xml:id='#{@prefixes[p].id}'>
51
- <PrefixName xml:lang="en">#{@prefixes[p].name}</PrefixName>
52
- <PrefixSymbol type="ASCII">#{@prefixes[p].ascii}</PrefixSymbol>
53
- <PrefixSymbol type="unicode">#{@prefixes[p].unicode}</PrefixSymbol>
54
- <PrefixSymbol type="LaTeX">#{@prefixes[p].latex}</PrefixSymbol>
55
- <PrefixSymbol type="HTML">#{htmlent @prefixes[p].html}</PrefixSymbol>
56
- </Prefix>
57
- END
51
+ units.map { |u| u[:prefix] }.reject(&:nil?).uniq.map do |p|
52
+ <<~XML
53
+ <Prefix xmlns='#{UNITSML_NS}' prefixBase='#{@prefixes[p].base}'
54
+ prefixPower='#{@prefixes[p].power}' xml:id='#{@prefixes[p].id}'>
55
+ <PrefixName xml:lang="en">#{@prefixes[p].name}</PrefixName>
56
+ <PrefixSymbol type="ASCII">#{@prefixes[p].ascii}</PrefixSymbol>
57
+ <PrefixSymbol type="unicode">#{@prefixes[p].unicode}</PrefixSymbol>
58
+ <PrefixSymbol type="LaTeX">#{@prefixes[p].latex}</PrefixSymbol>
59
+ <PrefixSymbol type="HTML">#{htmlent @prefixes[p].html}</PrefixSymbol>
60
+ </Prefix>
61
+ XML
58
62
  end.join("\n")
59
63
  end
60
64
 
61
- def dimension_components(dims)
62
- return if dims.nil? || dims.empty?
63
- <<~END
64
- <Dimension xmlns='#{UNITSML_NS}' xml:id="#{dim_id(dims)}">
65
- #{dims.map { |u| dimension1(u) }.join("\n") }
66
- </Dimension>
67
- END
68
- end
69
-
70
- U2D = {
71
- "m" => { dimension: "Length", order: 1, symbol: "L" },
72
- "g" => { dimension: "Mass", order: 2, symbol: "M" },
73
- "kg" => { dimension: "Mass", order: 2, symbol: "M" },
74
- "s" => { dimension: "Time", order: 3, symbol: "T" },
75
- "A" => { dimension: "ElectricCurrent", order: 4, symbol: "I" },
76
- "K" => { dimension: "ThermodynamicTemperature", order: 5,
77
- symbol: "Theta" },
78
- "degK" => { dimension: "ThermodynamicTemperature", order: 5,
79
- symbol: "Theta" },
80
- "mol" => { dimension: "AmountOfSubstance", order: 6, symbol: "N" },
81
- "cd" => { dimension: "LuminousIntensity", order: 7, symbol: "J" },
82
- "deg" => { dimension: "PlaneAngle", order: 8, symbol: "Phi" },
83
- }.freeze
84
-
85
- def units2dimensions(units)
86
- norm = decompose_units(units)
87
- return if norm.any? do |u|
88
- u[:unit] == "unknown" || u[:prefix] == "unknown" || u[:unit].nil?
89
- end
90
- norm.map do |u|
91
- { dimension: U2D[u[:unit]][:dimension],
92
- unit: u[:unit],
93
- exponent: u[:exponent] || 1,
94
- symbol: U2D[u[:unit]][:symbol] }
95
- end.sort { |a, b| U2D[a[:unit]][:order] <=> U2D[b[:unit]][:order] }
96
- end
97
-
98
- def dimension1(u)
99
- %(<#{u[:dimension]} symbol="#{u[:symbol]}"
100
- powerNumerator="#{float_to_display(u[:exponent])}"/>)
101
- end
102
-
103
- def dim_id(dims)
104
- return nil if dims.nil? || dims.empty?
105
- dimhash = dims.each_with_object({}) { |h, m| m[h[:dimension]] = h }
106
- dimsvector = %w(Length Mass Time ElectricCurrent ThermodynamicTemperature
107
- AmountOfSubstance LuminousIntensity PlaneAngle)
108
- .map { |h| dimhash.dig(h, :exponent) }.join(":")
109
- id = @dimensions_id&.values&.select { |d| d.vector == dimsvector }&.
110
- first&.id and return id.to_s
111
- "D_" + dims.map do |d|
112
- U2D[d[:unit]][:symbol] +
113
- (d[:exponent] == 1 ? "" : float_to_display(d[:exponent]))
114
- end.join("")
115
- end
116
-
117
65
  def decompose_units(units)
118
66
  gather_units(units_only(units).map { |u| decompose_unit(u) }.flatten)
119
67
  end
120
68
 
121
69
  def gather_units(units)
122
- units.sort { |a, b| a[:unit] <=> b[:unit] }.each_with_object([]) do |k, m|
70
+ if units[0][:dim] then gather_dimensions(units)
71
+ else gather_units1(units)
72
+ end
73
+ end
74
+
75
+ def gather_units1(units)
76
+ units.sort_by { |a| a[:unit] }.each_with_object([]) do |k, m|
123
77
  if m.empty? || m[-1][:unit] != k[:unit] then m << k
124
78
  else
125
79
  m[-1] = {
126
80
  prefix: combine_prefixes(
127
- @prefixes[m[-1][:prefix]], @prefixes[k[:prefix]]),
81
+ @prefixes[m[-1][:prefix]], @prefixes[k[:prefix]]
82
+ ),
128
83
  unit: m[-1][:unit],
129
84
  exponent: (k[:exponent]&.to_f || 1) +
130
- (m[-1][:exponent]&.to_f || 1) }
85
+ (m[-1][:exponent]&.to_f || 1),
86
+ }
87
+ end
88
+ end
89
+ end
90
+
91
+ def gather_dimensions(units)
92
+ units.sort_by { |a| a[:dim] }.each_with_object([]) do |k, m|
93
+ if m.empty? || m[-1][:dim] != k[:dim] then m << k
94
+ else
95
+ m[-1] = {
96
+ dim: m[-1][:dim],
97
+ exponent: (k[:exponent]&.to_f || 1) +
98
+ (m[-1][:exponent]&.to_f || 1),
99
+ }
131
100
  end
132
101
  end
133
102
  end
@@ -135,16 +104,18 @@ module Asciimath2UnitsML
135
104
  # treat g not kg as base unit: we have stripped the prefix k in parsing
136
105
  # reduce units down to basic units
137
106
  def decompose_unit(u)
138
- if u[:unit].nil? then u
139
- elsif u[:unit] == "g" then u
140
- elsif @units[u[:unit]].system_type == "SI_base" then u
107
+ if u[:unit].nil? || u[:unit] == "g" ||
108
+ @units[u[:unit]].system_type == "SI_base" then u
141
109
  elsif !@units[u[:unit]].si_derived_bases
142
110
  { prefix: u[:prefix], unit: "unknown", exponent: u[:exponent] }
143
111
  else
144
112
  @units[u[:unit]].si_derived_bases.each_with_object([]) do |k, m|
145
- prefix = !k[:prefix].nil? && !k[:prefix].empty? ?
146
- combine_prefixes(@prefixes_id[k[:prefix]], @prefixes[u[:prefix]]) :
147
- u[:prefix]
113
+ prefix = if !k[:prefix].nil? && !k[:prefix].empty?
114
+ combine_prefixes(@prefixes_id[k[:prefix]],
115
+ @prefixes[u[:prefix]])
116
+ else
117
+ u[:prefix]
118
+ end
148
119
  m << { prefix: prefix,
149
120
  unit: @units_id[k[:id]].symbolid,
150
121
  exponent: (k[:power]&.to_i || 1) * (u[:exponent]&.to_f || 1) }
@@ -157,6 +128,7 @@ module Asciimath2UnitsML
157
128
  return p1.symbolid if p2.nil?
158
129
  return p2.symbolid if p1.nil?
159
130
  return "unknown" if p1.base != p2.base
131
+
160
132
  @prefixes.each do |_, p|
161
133
  return p.symbolid if p.base == p1.base && p.power == p1.power + p2.power
162
134
  end
@@ -174,43 +146,26 @@ module Asciimath2UnitsML
174
146
  def quantity(normtext, quantity)
175
147
  return unless @units[normtext] && @units[normtext].quantities.size == 1 ||
176
148
  @quantities[quantity]
149
+
177
150
  id = quantity || @units[normtext].quantities.first
178
151
  @units[normtext]&.dimension and
179
152
  dim = %( dimensionURL="##{@units[normtext].dimension}")
180
- <<~END
181
- <Quantity xmlns='#{UNITSML_NS}' xml:id="#{id}"#{dim} quantityType="base">
182
- #{quantityname(id)}
183
- </Quantity>
184
- END
185
- end
186
-
187
- def dimid2dimensions(normtext)
188
- @dimensions_id[normtext].keys.map do |k|
189
- { dimension: k,
190
- symbol: U2D.values.select { |v| v[:dimension] == k }.first[:symbol],
191
- exponent: @dimensions_id[normtext].exponent(k) }
192
- end
193
- end
194
-
195
- def dimension(normtext)
196
- return unless @units[normtext]&.dimension
197
- dims = dimid2dimensions(@units[normtext]&.dimension)
198
- <<~END
199
- <Dimension xmlns='#{UNITSML_NS}' xml:id="#{@units[normtext]&.dimension}">
200
- #{dims.map { |u| dimension1(u) }.join("\n") }
201
- </Dimension>
202
- END
153
+ <<~XML
154
+ <Quantity xmlns='#{UNITSML_NS}' xml:id="#{id}"#{dim} quantityType="base">
155
+ #{quantityname(id)}
156
+ </Quantity>
157
+ XML
203
158
  end
204
159
 
205
160
  def unitsml(units, origtext, normtext, quantity, name)
206
161
  dims = units2dimensions(units)
207
- <<~END
208
- #{unit(units, origtext, normtext, dims, name)}
209
- #{prefix(units)}
210
- #{dimension(normtext)}
211
- #{dimension_components(dims)}
212
- #{quantity(normtext, quantity)}
213
- END
162
+ <<~XML
163
+ #{unit(units, origtext, normtext, dims, name)}
164
+ #{prefix(units)}
165
+ #{dimension(normtext)}
166
+ #{dimension_components(dims)}
167
+ #{quantity(normtext, quantity)}
168
+ XML
214
169
  end
215
170
  end
216
171
  end