unitsml 0.4.6 → 0.5.1
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 +4 -4
- data/docs/README.adoc +104 -2
- data/lib/unitsml/dimension.rb +1 -1
- data/lib/unitsml/fenced.rb +77 -0
- data/lib/unitsml/formula.rb +21 -8
- data/lib/unitsml/intermediate_exp_rules.rb +35 -0
- data/lib/unitsml/parse.rb +16 -25
- data/lib/unitsml/parser.rb +19 -4
- data/lib/unitsml/prefix.rb +10 -10
- data/lib/unitsml/transform.rb +31 -0
- data/lib/unitsml/unit.rb +29 -7
- data/lib/unitsml/unitsdb/dimension.rb +12 -18
- data/lib/unitsml/unitsdb/dimension_quantity.rb +2 -6
- data/lib/unitsml/unitsdb/dimensions.rb +4 -8
- data/lib/unitsml/unitsdb/prefix_reference.rb +23 -0
- data/lib/unitsml/unitsdb/prefixes.rb +19 -5
- data/lib/unitsml/unitsdb/quantities.rb +6 -4
- data/lib/unitsml/unitsdb/unit.rb +21 -0
- data/lib/unitsml/unitsdb/units.rb +20 -17
- data/lib/unitsml/unitsdb.rb +8 -4
- data/lib/unitsml/utility.rb +36 -44
- data/lib/unitsml/version.rb +1 -1
- data/lib/unitsml.rb +34 -16
- data/unitsdb/LICENSE.md +53 -0
- data/unitsdb/README.adoc +1071 -0
- data/unitsdb/RELEASE-NOTES.adoc +269 -0
- data/unitsdb/dimensions.yaml +1255 -602
- data/unitsdb/prefixes.yaml +742 -301
- data/unitsdb/quantities.yaml +3104 -2458
- data/unitsdb/scales.yaml +97 -0
- data/unitsdb/schemas/README.md +159 -0
- data/unitsdb/schemas/dimensions-schema.yaml +157 -0
- data/unitsdb/schemas/prefixes-schema.yaml +159 -0
- data/unitsdb/schemas/quantities-schema.yaml +120 -0
- data/unitsdb/schemas/scales-schema.yaml +109 -0
- data/unitsdb/schemas/unit_systems-schema.yaml +120 -0
- data/unitsdb/schemas/units-schema.yaml +219 -0
- data/unitsdb/spec/units_spec.rb +11 -10
- data/unitsdb/unit_systems.yaml +73 -15
- data/unitsdb/units.yaml +12566 -9974
- data/unitsdb/validate_schemas.rb +208 -0
- data/unitsml.gemspec +2 -1
- metadata +36 -8
- data/unitsdb/docs/README.adoc +0 -12
- data/unitsdb/docs/navigation.adoc +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edaa6904f430d793ab777f84d10c89925006c07654d769932ac17eb34e826e93
|
4
|
+
data.tar.gz: d5883a47de366c89c8e3d603aa9bfc99f307e94d73285bddcec426a34f6e963d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46d962a6cb805be3f839125dc3bbab75913e0bac277800f808908f6de81d117c54fbd163418ef35b546834b8d0d9640290664d2ceb9658aea6638c6e86b29a5d
|
7
|
+
data.tar.gz: 7d628fe1043c6dfc29b7e03844f1d2fbff50078afe344d0089682417dd441504aac9792dc6ff16cf7f340e4899e5d963375d341d7c553b0681e81d428022648b
|
data/docs/README.adoc
CHANGED
@@ -169,6 +169,104 @@ unit.to_unicode # Unicode representation
|
|
169
169
|
unit.to_xml # XML (in UnitsML) representation
|
170
170
|
----
|
171
171
|
|
172
|
+
==== Explicit parenthesis
|
173
|
+
|
174
|
+
When converting units to formats like MathML or LaTeX, you can specify whether
|
175
|
+
to use explicit parentheses for clarity in complex expressions.
|
176
|
+
|
177
|
+
A pair of parentheses is typically used for two purposes:
|
178
|
+
|
179
|
+
. For grouping to indicate operator precedence in mathematical expressions. When
|
180
|
+
expressing units, most of the time, parentheses are used to indicate operator
|
181
|
+
precedence, parentheses are only kept in cases where it indicates precedence.
|
182
|
+
When parentheses are not needed for precedence, such as in the expression
|
183
|
+
`(m/s)`, the parentheses can be removed whilch simplifies the expression into
|
184
|
+
`m/s`.
|
185
|
+
|
186
|
+
. For indicating that an expression is a compound unit. These parentheses are
|
187
|
+
explicit parentheses that cannot be removed without changing the meaning of the
|
188
|
+
expression.
|
189
|
+
|
190
|
+
UnitsML Ruby provides an option `explicit_parenthesis` to control the inclusion
|
191
|
+
of parentheses in the output.
|
192
|
+
|
193
|
+
In an expression:
|
194
|
+
|
195
|
+
* `(...)` is considered an implicit parenthesis for grouping and operator
|
196
|
+
precedence and can be removed without changing the meaning of the expression.
|
197
|
+
|
198
|
+
* `((...))` is considered an explicit parenthesis, which indicates that the
|
199
|
+
parentheses need to be preserved in the output regardless of operator
|
200
|
+
precedence.
|
201
|
+
|
202
|
+
The `explicit_parenthesis` option allows you to control how parentheses are
|
203
|
+
considered in the output formats. It can be set to `true` or `false`.
|
204
|
+
|
205
|
+
Syntax for using `explicit_parenthesis` is as follows:
|
206
|
+
|
207
|
+
[source,ruby]
|
208
|
+
----
|
209
|
+
unit.to_asciimath(explicit_parenthesis: true) # or false
|
210
|
+
unit.to_mathml(explicit_parenthesis: true) # or false
|
211
|
+
unit.to_latex(explicit_parenthesis: true) # or false
|
212
|
+
----
|
213
|
+
|
214
|
+
When `explicit_parenthesis` is set to:
|
215
|
+
|
216
|
+
`true`:: (default) the usage of `(...)` and `((...))` is differentiated as
|
217
|
+
implicit and explicit parentheses, respectively.
|
218
|
+
|
219
|
+
`false`:: all parentheses are treated as grouping parentheses, there is no
|
220
|
+
difference between `(...)` and `((...))`.
|
221
|
+
|
222
|
+
|
223
|
+
.By default `explicit_parenthesis` is `true` and double parentheses are considered explicit parentheses
|
224
|
+
[example]
|
225
|
+
====
|
226
|
+
[source, ruby]
|
227
|
+
----
|
228
|
+
Unitsml.parse("((m/s))").to_asciimath
|
229
|
+
> "(m/s^-1)" # Only one of the two pairs of parentheses are included in the output
|
230
|
+
----
|
231
|
+
====
|
232
|
+
|
233
|
+
If an extra pair of parentheses is included, it will be considered as grouping
|
234
|
+
parentheses and will not be included in the Unitsml::Formula or the output.
|
235
|
+
|
236
|
+
.By default `explicit_parenthesis` is `true` and double parentheses are considered explicit parentheses
|
237
|
+
[example]
|
238
|
+
====
|
239
|
+
[source, ruby]
|
240
|
+
----
|
241
|
+
Unitsml.parse("(((m/s)))").to_asciimath
|
242
|
+
> "(m/s^-1)" # the third pair of parentheses are ignored as grouping parentheses
|
243
|
+
Unitsml.parse("(((((m/s)))))").to_asciimath
|
244
|
+
> "((m/s^-1))" # the fifth pair of parentheses are ignored as grouping parentheses
|
245
|
+
----
|
246
|
+
|
247
|
+
[source,ruby]
|
248
|
+
----
|
249
|
+
unit = Unitsml.parse("((m/s))")
|
250
|
+
unit.to_asciimath # equivalent to (explicit_parenthesis: true) => "(m/s^-1)"
|
251
|
+
unit = Unitsml.parse("((m/s))*((m/s))")
|
252
|
+
unit.to_asciimath(explicit_parenthesis: true) # "(m/s^-1)*(m/s^-1)"
|
253
|
+
----
|
254
|
+
====
|
255
|
+
|
256
|
+
When `explicit_parenthesis` is `false`, all parentheses are treated as grouping parentheses
|
257
|
+
and therefore will be reduced to only the necessary parentheses for operator precedence.
|
258
|
+
|
259
|
+
.When `explicit_parenthesis` is `false`, all parentheses are treated as grouping parentheses
|
260
|
+
[example]
|
261
|
+
====
|
262
|
+
[source,ruby]
|
263
|
+
----
|
264
|
+
unit = Unitsml.parse("(m/s)")
|
265
|
+
unit.to_asciimath(explicit_parenthesis: false) # => "m/s"
|
266
|
+
unit = Unitsml.parse("((m/s))*((m/s))")
|
267
|
+
unit.to_asciimath(explicit_parenthesis: false) # "m/s^-1*m/s^-1"
|
268
|
+
----
|
269
|
+
====
|
172
270
|
|
173
271
|
|
174
272
|
== Installation
|
@@ -196,7 +294,9 @@ $ gem install unitsml
|
|
196
294
|
|
197
295
|
== Usage
|
198
296
|
|
199
|
-
*UnitsML* Ruby provides functionality to represent and convert units between
|
297
|
+
*UnitsML* Ruby provides functionality to represent and convert units between
|
298
|
+
different formats including *MathML*, *LaTeX*, *AsciiMath*, *HTML*, *Unicode*,
|
299
|
+
and *XML*(*Unitsml* schema based elements).
|
200
300
|
|
201
301
|
=== Basic Usage
|
202
302
|
|
@@ -275,7 +375,9 @@ repository.
|
|
275
375
|
|
276
376
|
== Development
|
277
377
|
|
278
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
378
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
379
|
+
`bundle exec spec` to run the tests. You can also run `bin/console` for an
|
380
|
+
interactive prompt that will allow you to experiment.
|
279
381
|
|
280
382
|
=== Submodules
|
281
383
|
|
data/lib/unitsml/dimension.rb
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
module Unitsml
|
2
|
+
class Fenced
|
3
|
+
attr_reader :open_paren, :value, :close_paren
|
4
|
+
|
5
|
+
def initialize(open_paren, value, close_paren)
|
6
|
+
@open_paren = open_paren
|
7
|
+
@value = value
|
8
|
+
@close_paren = close_paren
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(object)
|
12
|
+
self.class == object.class &&
|
13
|
+
open_paren == object&.open_paren &&
|
14
|
+
value == object&.value &&
|
15
|
+
close_paren == object&.close_paren
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_asciimath(options = {})
|
19
|
+
fenced_conversion_for(lang: :asciimath, options: options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_latex(options = {})
|
23
|
+
fenced_conversion_for(lang: :latex, options: options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_mathml(options = {})
|
27
|
+
mathml = value.to_mathml(options)
|
28
|
+
return mathml unless options[:explicit_parenthesis]
|
29
|
+
|
30
|
+
fenced = ::Mml::Mrow.new(mo_value: [::Mml::Mo.new(value: open_paren)])
|
31
|
+
fenced.ordered = true
|
32
|
+
fenced.element_order ||= [xml_order_element("mo")]
|
33
|
+
[mathml].flatten.each { |record| add_math_element(fenced, record) }
|
34
|
+
fenced.mo_value << ::Mml::Mo.new(value: close_paren)
|
35
|
+
fenced.element_order << xml_order_element("mo")
|
36
|
+
{ method_name: :mrow, value: fenced }
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_html(options = {})
|
40
|
+
fenced_conversion_for(lang: :html, options: options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_unicode(options = {})
|
44
|
+
fenced_conversion_for(lang: :unicode, options: options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def dimensions_extraction
|
48
|
+
case value
|
49
|
+
when Dimension
|
50
|
+
value
|
51
|
+
when Formula, Fenced
|
52
|
+
value.dimensions_extraction
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def add_math_element(instance, child_hash)
|
59
|
+
method_name = child_hash[:method_name]
|
60
|
+
method_value = instance.public_send(:"#{method_name}_value") || []
|
61
|
+
method_value += Array(child_hash[:value])
|
62
|
+
instance.public_send(:"#{method_name}_value=", method_value)
|
63
|
+
instance.element_order << xml_order_element(method_name.to_s)
|
64
|
+
end
|
65
|
+
|
66
|
+
def xml_order_element(tag_name)
|
67
|
+
Lutaml::Model::Xml::Element.new("Element", tag_name)
|
68
|
+
end
|
69
|
+
|
70
|
+
def fenced_conversion_for(lang:, options:)
|
71
|
+
lang_value = value.send(:"to_#{lang}", options)
|
72
|
+
return lang_value unless options[:explicit_parenthesis]
|
73
|
+
|
74
|
+
"#{open_paren}#{lang_value}#{close_paren}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/unitsml/formula.rb
CHANGED
@@ -29,7 +29,7 @@ module Unitsml
|
|
29
29
|
|
30
30
|
def to_mathml(options = {})
|
31
31
|
if root
|
32
|
-
update_options(options)
|
32
|
+
options = update_options(options)
|
33
33
|
nullify_mml_models if plurimath_available?
|
34
34
|
math = ::Mml::MathWithNamespace.new(display: "block")
|
35
35
|
math.ordered = true
|
@@ -61,7 +61,7 @@ module Unitsml
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def to_xml(options = {})
|
64
|
-
update_options(options)
|
64
|
+
options = update_options(options)
|
65
65
|
if (dimensions_array = extract_dimensions(value)).any?
|
66
66
|
dimensions(sort_dims(dimensions_array), options)
|
67
67
|
elsif @orig_text.match(/-$/)
|
@@ -79,18 +79,28 @@ module Unitsml
|
|
79
79
|
Plurimath::Math.parse(to_mathml(options), :mathml)
|
80
80
|
end
|
81
81
|
|
82
|
+
def dimensions_extraction
|
83
|
+
extract_dimensions(value)
|
84
|
+
end
|
85
|
+
|
82
86
|
private
|
83
87
|
|
84
88
|
def extract_dimensions(formula)
|
85
89
|
formula.each_with_object([]) do |term, dimensions|
|
86
90
|
if term.is_a?(Dimension)
|
87
91
|
dimensions << term
|
88
|
-
elsif term.is_a?(Sqrt)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
+
elsif term.is_a?(Sqrt)
|
93
|
+
if term.value.is_a?(Dimension)
|
94
|
+
sqrt_term = term.value.dup
|
95
|
+
sqrt_term.power_numerator = "0.5"
|
96
|
+
dimensions << sqrt_term
|
97
|
+
elsif term.value.is_a?(Fenced)
|
98
|
+
dimensions.concat(Array(term.value.dimensions_extraction))
|
99
|
+
end
|
92
100
|
elsif term.is_a?(Formula)
|
93
101
|
dimensions.concat(extract_dimensions(term.value))
|
102
|
+
elsif term.is_a?(Fenced)
|
103
|
+
dimensions.concat(Array(term.dimensions_extraction))
|
94
104
|
end
|
95
105
|
end
|
96
106
|
end
|
@@ -106,13 +116,15 @@ module Unitsml
|
|
106
116
|
next unless term.value.is_a?(Unit)
|
107
117
|
|
108
118
|
units_arr << term.value
|
119
|
+
when Fenced
|
120
|
+
units_arr.concat(extract_units([term.value]))
|
109
121
|
end
|
110
122
|
end
|
111
123
|
end
|
112
124
|
|
113
125
|
def units(options)
|
114
126
|
all_units = extract_units(value)
|
115
|
-
norm_text =
|
127
|
+
norm_text = all_units.map(&:xml_postprocess_name).join("*")
|
116
128
|
dims = Utility.units2dimensions(extract_units(value))
|
117
129
|
[
|
118
130
|
Utility.unit(all_units, self, dims, norm_text, explicit_value&.dig(:name), options),
|
@@ -196,7 +208,8 @@ module Unitsml
|
|
196
208
|
return options unless root
|
197
209
|
|
198
210
|
multiplier = options[:multiplier] || explicit_value&.dig(:multiplier)
|
199
|
-
options.
|
211
|
+
explicit_parenthesis = options.key?(:explicit_parenthesis) ? options[:explicit_parenthesis] : true
|
212
|
+
options.merge(multiplier: multiplier, explicit_parenthesis: explicit_parenthesis).compact
|
200
213
|
end
|
201
214
|
end
|
202
215
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Unitsml
|
2
|
+
module IntermediateExpRules
|
3
|
+
include Parslet
|
4
|
+
|
5
|
+
# Rules for slashed number
|
6
|
+
rule(:slashed_number_int_exp) { slashed_number | (str("(") >> slashed_number >> str(")")) }
|
7
|
+
|
8
|
+
# Rules for prefixes_units
|
9
|
+
rule(:prefixes_units_int_exp) { prefixes_units | (str("(") >> prefixes_units_named_exp.as(:intermediate_exp) >> str(")") >> extended_prefixed_units.maybe) }
|
10
|
+
rule(:extended_prefixed_units) { extender >> prefixes_units_int_exp.as(:sequence) }
|
11
|
+
rule(:prefixes_units_named_exp) do
|
12
|
+
prefixes_units |
|
13
|
+
((str("(").as(:open_parenthesis) >> prefixes_units_int_exp.as(:int_exp) >> str(")").as(:close_parenthesis)).as(:intermediate_exp) >> extended_prefixed_units.maybe)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Rules for dimension_rules
|
17
|
+
rule(:dimension_rules_int_exp) { dimension_rules | (str("(") >> dimension_rules_named_exp.as(:intermediate_exp) >> str(")") >> extended_dimension_rules.maybe) }
|
18
|
+
rule(:extended_dimension_rules) { extender >> dimension_rules_int_exp.as(:sequence) }
|
19
|
+
rule(:dimension_rules_named_exp) do
|
20
|
+
dimension_rules |
|
21
|
+
((str("(").as(:open_parenthesis) >> dimension_rules_int_exp.as(:int_exp) >> str(")").as(:close_parenthesis)).as(:intermediate_exp) >> extended_dimension_rules.maybe)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Rules for dimensions
|
25
|
+
rule(:sqrt_dimensions) { str("sqrt(") >> dimensions_int_exp.as(:sqrt) >> str(")") }
|
26
|
+
rule(:powered_dimensions) { dimensions >> power.maybe }
|
27
|
+
rule(:dimensions_int_exp) { powered_dimensions | (str("(") >> dimensions_named_exp.as(:intermediate_exp) >> str(")")) }
|
28
|
+
rule(:dimensions_named_exp) { powered_dimensions | (str("(").as(:open_parenthesis) >> dimensions_int_exp.as(:int_exp) >> str(")").as(:close_parenthesis)) }
|
29
|
+
|
30
|
+
# Rules for sequence
|
31
|
+
rule(:sqrt_sequence) { str("sqrt(") >> sequence_int_exp.as(:sqrt) >> str(")") }
|
32
|
+
rule(:sequence_int_exp) { sequence | (str("(") >> sequence_named_exp.as(:intermediate_exp)>> str(")")) }
|
33
|
+
rule(:sequence_named_exp) { sequence | (str("(").as(:open_parenthesis) >> sequence_int_exp.as(:int_exp) >> str(")").as(:close_parenthesis)) }
|
34
|
+
end
|
35
|
+
end
|
data/lib/unitsml/parse.rb
CHANGED
@@ -2,9 +2,12 @@
|
|
2
2
|
|
3
3
|
require "parslet"
|
4
4
|
require "unitsml/unitsdb"
|
5
|
+
require_relative "intermediate_exp_rules"
|
5
6
|
module Unitsml
|
6
7
|
class Parse < Parslet::Parser
|
7
|
-
|
8
|
+
include IntermediateExpRules
|
9
|
+
|
10
|
+
rule(:power) { str("^") >> slashed_number_int_exp }
|
8
11
|
rule(:hyphen) { str("-") }
|
9
12
|
rule(:number) { hyphen.maybe >> match(/[0-9]/).repeat(1) }
|
10
13
|
|
@@ -32,24 +35,24 @@ module Unitsml
|
|
32
35
|
end
|
33
36
|
|
34
37
|
rule(:prefixes_units) do
|
35
|
-
(
|
36
|
-
(str("1").as(:units) >>
|
37
|
-
(unit_and_power >>
|
38
|
-
unit_and_power |
|
39
|
-
(
|
40
|
-
(
|
41
|
-
(
|
42
|
-
(
|
38
|
+
(sqrt_sequence >> extended_prefixed_units.maybe) |
|
39
|
+
(str("1").as(:units) >> extended_prefixed_units.maybe) |
|
40
|
+
(unit_and_power >> extended_prefixed_units) |
|
41
|
+
unit_and_power >> (str(")").present? | any.absent?) |
|
42
|
+
(double_letter_prefixes >> unit_and_power >> extended_prefixed_units) |
|
43
|
+
(double_letter_prefixes >> unit_and_power) |
|
44
|
+
(single_letter_prefixes >> unit_and_power >> extended_prefixed_units) |
|
45
|
+
(single_letter_prefixes >> unit_and_power)
|
43
46
|
end
|
44
47
|
|
45
48
|
rule(:dimension_rules) do
|
46
|
-
(
|
47
|
-
(
|
49
|
+
(sqrt_dimensions >> extended_dimension_rules.maybe) |
|
50
|
+
(powered_dimensions >> extended_dimension_rules.maybe)
|
48
51
|
end
|
49
52
|
|
50
53
|
rule(:expression) do
|
51
|
-
|
52
|
-
|
54
|
+
prefixes_units_int_exp |
|
55
|
+
dimension_rules_int_exp |
|
53
56
|
single_letter_prefixes >> hyphen |
|
54
57
|
double_letter_prefixes >> hyphen
|
55
58
|
end
|
@@ -63,17 +66,5 @@ module Unitsml
|
|
63
66
|
expression | str(expr_string).as(file_name.to_sym)
|
64
67
|
end
|
65
68
|
end
|
66
|
-
|
67
|
-
def sqrt(rule)
|
68
|
-
str("sqrt(") >> rule.as(:sqrt) >> str(")")
|
69
|
-
end
|
70
|
-
|
71
|
-
def extend_exp(rule)
|
72
|
-
(extender >> intermediate_exp(rule).as(:sequence)).maybe
|
73
|
-
end
|
74
|
-
|
75
|
-
def intermediate_exp(rule)
|
76
|
-
rule | (str("(") >> rule >> str(")"))
|
77
|
-
end
|
78
69
|
end
|
79
70
|
end
|
data/lib/unitsml/parser.rb
CHANGED
@@ -6,7 +6,7 @@ module Unitsml
|
|
6
6
|
|
7
7
|
def initialize(text)
|
8
8
|
@regexp = %r{(quantity|name|symbol|multiplier):\s*}
|
9
|
-
@text = text
|
9
|
+
@text = extract_equation(text)
|
10
10
|
@orig_text = @text
|
11
11
|
@text = @text.gsub("−", "-")
|
12
12
|
post_extras
|
@@ -15,7 +15,7 @@ module Unitsml
|
|
15
15
|
def parse
|
16
16
|
nodes = Parse.new.parse(text)
|
17
17
|
transformed = Transform.new.apply(nodes)
|
18
|
-
formula_value = transformed.is_a?(Formula) ? transformed.value :
|
18
|
+
formula_value = transformed.is_a?(Formula) ? transformed.value : [transformed].flatten
|
19
19
|
formula = Formula.new(
|
20
20
|
formula_value,
|
21
21
|
explicit_value: @extras_hash,
|
@@ -28,21 +28,28 @@ module Unitsml
|
|
28
28
|
formula
|
29
29
|
end
|
30
30
|
|
31
|
-
def update_units_exponents(array, inverse)
|
31
|
+
def update_units_exponents(array, inverse, sqrt = false)
|
32
32
|
array.each do |object|
|
33
33
|
if object.is_a?(Sqrt)
|
34
34
|
object = object.value
|
35
|
-
object.power_numerator
|
35
|
+
if object.respond_to?(:power_numerator)
|
36
|
+
object.power_numerator = "0.5"
|
37
|
+
else
|
38
|
+
update_units_exponents([object], inverse, true)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
|
38
42
|
case object
|
39
43
|
when Unit
|
44
|
+
next object.power_numerator = "0.5" if sqrt
|
40
45
|
next unless inverse
|
41
46
|
|
42
47
|
exponent = inverse ? "-#{object&.power_numerator || '1'}" : object.power_numerator
|
43
48
|
object.power_numerator = exponent&.sub(/^--+/, "")
|
49
|
+
when Dimension then object.power_numerator = "0.5" if sqrt
|
44
50
|
when Extender then inverse = !inverse if ["/", "//"].any?(object.symbol)
|
45
51
|
when Formula then update_units_exponents(object.value, inverse)
|
52
|
+
when Fenced then update_units_exponents([object.value], inverse, sqrt)
|
46
53
|
end
|
47
54
|
end
|
48
55
|
end
|
@@ -62,5 +69,13 @@ module Unitsml
|
|
62
69
|
key, _, value = text&.partition(":")
|
63
70
|
@extras_hash[key&.to_sym] ||= value&.strip
|
64
71
|
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def extract_equation(text)
|
76
|
+
return text unless text&.start_with?("unitsml(")
|
77
|
+
|
78
|
+
text.delete_prefix("unitsml(").delete_suffix(")")
|
79
|
+
end
|
65
80
|
end
|
66
81
|
end
|
data/lib/unitsml/prefix.rb
CHANGED
@@ -20,21 +20,21 @@ module Unitsml
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def id
|
23
|
-
@prefix.id
|
23
|
+
@id ||= prefix_instance.identifiers.find { |prefix| prefix.type == "nist" }&.id
|
24
24
|
end
|
25
25
|
|
26
26
|
def name
|
27
|
-
prefix_instance.name
|
27
|
+
@name ||= prefix_instance.names.find { |name| name.lang == "en" }.value
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
prefix_instance.
|
30
|
+
def prefix_symbols
|
31
|
+
prefix_instance.symbols.last
|
32
32
|
end
|
33
33
|
|
34
34
|
def to_mathml(_)
|
35
35
|
symbol = Utility.string_to_html_entity(
|
36
36
|
Utility.html_entity_to_unicode(
|
37
|
-
|
37
|
+
prefix_symbols.html
|
38
38
|
),
|
39
39
|
)
|
40
40
|
return symbol unless only_instance
|
@@ -43,23 +43,23 @@ module Unitsml
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def to_latex(_)
|
46
|
-
|
46
|
+
prefix_symbols.latex
|
47
47
|
end
|
48
48
|
|
49
49
|
def to_asciimath(_)
|
50
|
-
|
50
|
+
prefix_symbols.ascii
|
51
51
|
end
|
52
52
|
|
53
53
|
def to_html(_)
|
54
|
-
|
54
|
+
prefix_symbols.html
|
55
55
|
end
|
56
56
|
|
57
57
|
def to_unicode(_)
|
58
|
-
|
58
|
+
prefix_symbols.unicode
|
59
59
|
end
|
60
60
|
|
61
61
|
def symbolid
|
62
|
-
|
62
|
+
prefix_symbols.ascii if prefix_symbols
|
63
63
|
end
|
64
64
|
|
65
65
|
def base
|
data/lib/unitsml/transform.rb
CHANGED
@@ -7,6 +7,7 @@ module Unitsml
|
|
7
7
|
rule(units: simple(:unit)) { Unit.new(unit.to_s) }
|
8
8
|
rule(prefixes: simple(:prefix)) { Prefix.new(prefix.to_s) }
|
9
9
|
rule(dimensions: simple(:dimension)) { Dimension.new(dimension.to_s) }
|
10
|
+
rule(intermediate_exp: simple(:int_exp)) { int_exp }
|
10
11
|
|
11
12
|
rule(units: simple(:unit),
|
12
13
|
integer: simple(:integer)) do
|
@@ -30,6 +31,36 @@ module Unitsml
|
|
30
31
|
Unit.new(unit.to_s, integer.to_s, prefix: prefix_obj)
|
31
32
|
end
|
32
33
|
|
34
|
+
rule(open_parenthesis: simple(:open_paren),
|
35
|
+
int_exp: simple(:exp),
|
36
|
+
close_parenthesis: simple(:close_paren)) do
|
37
|
+
Fenced.new(open_paren.to_s, exp, close_paren.to_s)
|
38
|
+
end
|
39
|
+
|
40
|
+
rule(open_parenthesis: simple(:open_paren),
|
41
|
+
int_exp: simple(:exp),
|
42
|
+
close_parenthesis: simple(:close_paren),
|
43
|
+
sequence: sequence(:sequence)) do
|
44
|
+
Formula.new(
|
45
|
+
[
|
46
|
+
Fenced.new(open_paren.to_s, exp, close_paren.to_s),
|
47
|
+
sequence,
|
48
|
+
],
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
rule(intermediate_exp: simple(:intermediate_exp),
|
53
|
+
extender: simple(:extender),
|
54
|
+
sequence: simple(:sequence)) do
|
55
|
+
Formula.new(
|
56
|
+
[
|
57
|
+
intermediate_exp,
|
58
|
+
Extender.new(extender.to_s),
|
59
|
+
sequence,
|
60
|
+
],
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
33
64
|
rule(prefixes: simple(:prefix),
|
34
65
|
units: simple(:unit),
|
35
66
|
integer: simple(:integer),
|
data/lib/unitsml/unit.rb
CHANGED
@@ -4,6 +4,8 @@ module Unitsml
|
|
4
4
|
class Unit
|
5
5
|
attr_accessor :unit_name, :power_numerator, :prefix
|
6
6
|
|
7
|
+
SI_UNIT_SYSTEM = %w[si_base si_derived_special si_derived_non_special].freeze
|
8
|
+
|
7
9
|
def initialize(unit_name,
|
8
10
|
power_numerator = nil,
|
9
11
|
prefix: nil)
|
@@ -24,7 +26,7 @@ module Unitsml
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def unit_symbols
|
27
|
-
unit_instance.
|
29
|
+
unit_instance.symbols.find { |symbol| symbol.id == unit_name }
|
28
30
|
end
|
29
31
|
|
30
32
|
def numerator_value(mathml = true)
|
@@ -89,7 +91,7 @@ module Unitsml
|
|
89
91
|
end
|
90
92
|
|
91
93
|
def enumerated_name
|
92
|
-
unit_instance&.
|
94
|
+
unit_instance.names.find { |name| name.lang == "en" }&.value
|
93
95
|
end
|
94
96
|
|
95
97
|
def prefix_name
|
@@ -97,15 +99,35 @@ module Unitsml
|
|
97
99
|
end
|
98
100
|
|
99
101
|
def system_type
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
def system_name
|
104
|
-
unit_instance.unit_system.name
|
102
|
+
system_reference&.first&.id
|
105
103
|
end
|
106
104
|
|
107
105
|
def si_derived_bases
|
108
106
|
unit_instance.si_derived_bases
|
109
107
|
end
|
108
|
+
|
109
|
+
def xml_postprocess_name
|
110
|
+
"#{prefix_name}#{unit_name}#{display_exp}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def si_system_type?
|
114
|
+
SI_UNIT_SYSTEM.include?(downcase_system_type)
|
115
|
+
end
|
116
|
+
|
117
|
+
def downcase_system_type
|
118
|
+
Lutaml::Model::Utils.snake_case(system_type)
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def display_exp
|
124
|
+
return unless power_numerator
|
125
|
+
|
126
|
+
"^#{power_numerator}" if power_numerator != "1"
|
127
|
+
end
|
128
|
+
|
129
|
+
def system_reference
|
130
|
+
unit_instance.unit_system_reference
|
131
|
+
end
|
110
132
|
end
|
111
133
|
end
|