iev 0.3.0 → 0.3.3

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: 556b84a09693c2ee27bbe3db275abeec90227e563b7c8c456d2efe913c784e5a
4
- data.tar.gz: 8736ff88f0283016ae05afda14f497bf5da19b4d3792473d8853ee4a6617f56c
3
+ metadata.gz: a5909046a19d741d4242dd6823366923efb0607de3ebf89fdcb99465310b6150
4
+ data.tar.gz: 55812547af56e58d9ea68a1cc7413632558c51a8d3b0d22b48ee61e81afef390
5
5
  SHA512:
6
- metadata.gz: 54b212104edfd071c2be493b20d8bc6c0c3398fffbd1d16c08f838b1200737f370d91d69f84ae5dc5ce1b9e70eb5d155a7d981acfb96ba7949ddbbf9a7d232d3
7
- data.tar.gz: 22cd4fcb158f674362a9319ee98b7e973b92fbe2176cdbbd3659b069eb0c9cee3b5d432134e224db8d4100a39a99c6ab1bff68040c90371bf69614efaefb0fe9
6
+ metadata.gz: 6e5cca48906d1f65292cc58887b89564ae293da6cd081e47e70495d11f43c606b6db11d7d99db92210909b4fc3ccfcb54ffdb003191c17134f15c921cbded6c0
7
+ data.tar.gz: 02f500f0bf2c1da875402a5f26f709d86ee7a4924fd4dd61796e653e260cd52d6c88fc37c9403bf4db479bdeb59664bc2cd599eaa00f40012ca0893a35a96164
@@ -10,23 +10,6 @@ on:
10
10
 
11
11
  jobs:
12
12
  rake:
13
- name: Test on Ruby ${{ matrix.ruby }} ${{ matrix.os }}
14
- runs-on: ${{ matrix.os }}
15
- continue-on-error: ${{ matrix.experimental }}
16
- strategy:
17
- fail-fast: false
18
- matrix:
19
- ruby: [ '3.0', '2.7', '2.6', '2.5' ]
20
- os: [ ubuntu-latest, windows-latest, macos-latest ]
21
- experimental: [ false ]
22
- steps:
23
- - uses: actions/checkout@v2
24
- with:
25
- submodules: true
26
-
27
- - uses: ruby/setup-ruby@v1
28
- with:
29
- ruby-version: ${{ matrix.ruby }}
30
- bundler-cache: true
31
-
32
- - run: bundle exec rake
13
+ uses: metanorma/ci/.github/workflows/generic-rake.yml@main
14
+ secrets:
15
+ pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
@@ -0,0 +1,25 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ name: release
4
+
5
+ on:
6
+ workflow_dispatch:
7
+ inputs:
8
+ next_version:
9
+ description: |
10
+ Next release version. Possible values: x.y.z, major, minor, patch (or pre|rc|etc).
11
+ Also, you can pass 'skip' to skip 'git tag' and do 'gem push' for the current version
12
+ required: true
13
+ default: 'skip'
14
+ repository_dispatch:
15
+ types: [ do-release ]
16
+
17
+ jobs:
18
+ release:
19
+ uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
20
+ with:
21
+ next_version: ${{ github.event.inputs.next_version }}
22
+ secrets:
23
+ rubygems-api-key: ${{ secrets.METANORMA_CI_RUBYGEMS_API_KEY }}
24
+ pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
25
+
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  /.yardoc
3
3
  /_yardoc/
4
4
  /coverage/
5
+ /db/
5
6
  /doc/
6
7
  /pkg/
7
8
  /spec/reports/
@@ -11,3 +12,6 @@
11
12
 
12
13
  # rspec failure tracking
13
14
  .rspec_status
15
+ .vscode/
16
+
17
+ concepts/
data/.rubocop.yml CHANGED
@@ -6,5 +6,3 @@ inherit_from:
6
6
  # local repo-specific modifications
7
7
  # ...
8
8
 
9
- AllCops:
10
- TargetRubyVersion: 2.5
data/README.adoc CHANGED
@@ -1,4 +1,4 @@
1
- = Iev
1
+ = IEV
2
2
 
3
3
  image:https://img.shields.io/gem/v/iev.svg["Gem Version", link="https://rubygems.org/gems/iev"]
4
4
  image:https://github.com/metanorma/iev/workflows/rake/badge.svg["Build Status", link="https://github.com/metanorma/iev/actions?query=workflow%3Arake"]
@@ -31,15 +31,15 @@ Or install it yourself as:
31
31
  ----
32
32
  # Get term
33
33
 
34
- Iev.get("103-01-02", "en")
34
+ IEV.get("103-01-02", "en")
35
35
  => "functional"
36
36
 
37
37
  # If code not found
38
- Iev.get("111-11-11", "en")
38
+ IEV.get("111-11-11", "en")
39
39
  => ""
40
40
 
41
41
  # If language not found
42
- Iev.get("103-01-02", "eee")
42
+ IEV.get("103-01-02", "eee")
43
43
  => nil
44
44
  ----
45
45
 
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # resolve bin path, ignoring symlinks
5
+ require "pathname"
6
+ bin_file = Pathname.new(__FILE__).realpath
7
+
8
+ # add self to libpath
9
+ $:.unshift File.expand_path("../../lib", bin_file)
10
+
11
+ # Fixes https://github.com/rubygems/rubygems/issues/1420
12
+ require "rubygems/specification"
13
+
14
+ class Gem::Specification
15
+ def this; self; end
16
+ end
17
+
18
+ require "iev"
19
+ require "iev/cli"
20
+
21
+ IEV::CLI.start(ARGV)
data/iev.gemspec CHANGED
@@ -4,7 +4,7 @@ require "iev/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "iev"
7
- spec.version = Iev::VERSION
7
+ spec.version = IEV::VERSION
8
8
  spec.authors = ["Ribose Inc."]
9
9
  spec.email = ["open.source@ribose.com"]
10
10
 
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.bindir = "exe"
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
22
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
23
23
 
24
24
  spec.add_development_dependency "bundler"
25
25
  spec.add_development_dependency "debug"
@@ -27,5 +27,14 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rspec", "~> 3.0"
28
28
  spec.add_development_dependency "simplecov"
29
29
 
30
- spec.add_dependency "nokogiri", "~> 1.12"
30
+ spec.add_dependency "creek", "~> 2.5"
31
+ spec.add_dependency "glossarist", "~> 2.0.6"
32
+ spec.add_dependency "unitsml"
33
+ spec.add_dependency "plurimath"
34
+ spec.add_dependency "nokogiri", ">= 1.16.5"
35
+ spec.add_dependency "relaton", "~> 1.18"
36
+ spec.add_dependency "sequel", "~> 5.40"
37
+ spec.add_dependency "sqlite3", "~> 1.7.0"
38
+ spec.add_dependency "thor", "~> 1.0"
39
+ spec.add_dependency "zeitwerk", "~> 2.4"
31
40
  end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2020 Ribose Inc.
4
+ #
5
+
6
+ module IEV
7
+ module CLI
8
+ class Command < Thor
9
+ include CommandHelper
10
+
11
+ desc "xlsx2yaml FILE", "Converts Excel IEV exports to YAMLs."
12
+ def xlsx2yaml(file)
13
+ handle_generic_options(options)
14
+ db = Sequel.sqlite
15
+ DbWriter.new(db).import_spreadsheet(file)
16
+ ds = filter_dataset(db, options)
17
+ collection = build_collection_from_dataset(ds)
18
+ save_collection_to_files(collection, options[:output])
19
+ summary
20
+ end
21
+
22
+ desc "xlsx2db FILE", "Imports Excel to SQLite database."
23
+ def xlsx2db(file)
24
+ handle_generic_options(options)
25
+ # Instantiating an in-memory db and dumping it later is faster than
26
+ # just working on file db.
27
+ db = Sequel.sqlite
28
+ DbWriter.new(db).import_spreadsheet(file)
29
+ save_db_to_file(db, options[:output])
30
+ summary
31
+ end
32
+
33
+ desc "db2yaml DB_FILE", "Exports SQLite to IEV YAMLs."
34
+ def db2yaml(dbfile)
35
+ handle_generic_options(options)
36
+ db = Sequel.sqlite(dbfile)
37
+ ds = filter_dataset(db, options)
38
+ collection = build_collection_from_dataset(ds)
39
+ save_collection_to_files(collection, options[:output])
40
+ summary
41
+ end
42
+
43
+ def self.exit_on_failure?
44
+ true
45
+ end
46
+
47
+ # Options must be declared at the bottom because Thor must have commands
48
+ # defined in advance.
49
+
50
+ def self.shared_option(name, methods:, **kwargs)
51
+ [*methods].each { |m| option name, for: m, **kwargs }
52
+ end
53
+
54
+ shared_option :only_concepts,
55
+ desc: "Only process concepts with IEVREF matching this argument, " +
56
+ "'%' and '_' wildcards are supported and have meaning as in SQL " +
57
+ "LIKE operator",
58
+ methods: %i[xlsx2yaml db2yaml]
59
+
60
+ shared_option :only_languages,
61
+ desc: "Only export these languages, skip concepts which aren't " +
62
+ "translated to any of them (comma-separated list, language " +
63
+ "codes must be as in spreadsheet)",
64
+ methods: %i[xlsx2yaml db2yaml]
65
+
66
+ shared_option :output,
67
+ desc: "Output directory",
68
+ aliases: :o,
69
+ default: Dir.pwd,
70
+ methods: %i[xlsx2yaml db2yaml]
71
+
72
+ shared_option :output,
73
+ desc: "Output file",
74
+ aliases: :o,
75
+ default: File.join(Dir.pwd, "concepts.sqlite3"),
76
+ methods: :xlsx2db
77
+
78
+ shared_option :progress,
79
+ type: :boolean,
80
+ desc: "Enables or disables progress indicator. By default disabled " +
81
+ "when 'CI' environment variable is set and enabled otherwise",
82
+ methods: %i[xlsx2yaml xlsx2db db2yaml]
83
+
84
+ shared_option :debug_term_attributes,
85
+ desc: "Enables debug messages about term attributes recognition",
86
+ type: :boolean,
87
+ default: false,
88
+ methods: %i[xlsx2yaml db2yaml]
89
+
90
+ shared_option :debug_sources,
91
+ desc: "Enables debug messages about authoritative sources recognition",
92
+ type: :boolean,
93
+ default: false,
94
+ methods: %i[xlsx2yaml db2yaml]
95
+
96
+ shared_option :debug_relaton,
97
+ desc: "Enables debug messages about Relaton integration",
98
+ type: :boolean,
99
+ default: false,
100
+ methods: %i[xlsx2yaml db2yaml]
101
+
102
+ shared_option :profile,
103
+ desc: "Generates profiler reports for this program, requires ruby-prof",
104
+ type: :boolean,
105
+ default: false,
106
+ methods: %i[xlsx2yaml xlsx2db db2yaml]
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2020 Ribose Inc.
4
+ #
5
+
6
+ module IEV
7
+ module CLI
8
+ module CommandHelper
9
+ include CLI::UI
10
+
11
+ protected
12
+
13
+ def save_collection_to_files(collection, output_dir)
14
+ Profiler.measure("writing-yamls") do
15
+ info "Writing concepts to files..."
16
+ path = File.expand_path("./concepts", output_dir)
17
+ FileUtils.mkdir_p(path)
18
+ collection.save_to_files(path)
19
+ end
20
+ end
21
+
22
+ # Note: Implementation examples here:
23
+ # https://www.rubydoc.info/github/luislavena/sqlite3-ruby/SQLite3/Backup
24
+ def save_db_to_file(src_db, dbfile)
25
+ info "Saving database to a file..."
26
+ src_db.synchronize do |src_conn|
27
+ dest_conn = SQLite3::Database.new(dbfile)
28
+ b = SQLite3::Backup.new(dest_conn, "main", src_conn, "main")
29
+ b.step(-1)
30
+ b.finish
31
+ end
32
+ end
33
+
34
+ def summary
35
+ info "Done!"
36
+ end
37
+
38
+ def collection_file_path(file, output_dir)
39
+ output_dir.join(Pathname.new(file).basename.sub_ext(".yaml"))
40
+ end
41
+
42
+ # Handles various generic options, e.g. detailed debug switches.
43
+ # Assigns some global variables accordingly, so these settings are
44
+ # available throughout the program.
45
+ def handle_generic_options(options)
46
+ $IEV_PROFILE = options[:profile]
47
+ $IEV_PROGRESS = options.fetch(:progress, !ENV["CI"])
48
+
49
+ $IEV_DEBUG = options.to_h.
50
+ select { |k, _| k.to_s.start_with? "debug_" }.
51
+ transform_keys { |k| k.to_s.sub("debug_", "").to_sym }
52
+ end
53
+
54
+ def filter_dataset(db, options)
55
+ query = db[:concepts]
56
+
57
+ if options[:only_concepts]
58
+ query = query.where(Sequel.ilike(:ievref, options[:only_concepts]))
59
+ end
60
+
61
+ if options[:only_languages]
62
+ query = query.where(language: options[:only_languages].split(","))
63
+ end
64
+
65
+ query
66
+ end
67
+
68
+ def build_collection_from_dataset(dataset)
69
+ Profiler.measure("building-collection") do
70
+ Glossarist::ManagedConceptCollection.new.tap do |concept_collection|
71
+ dataset.each do |row|
72
+ term = TermBuilder.build_from(row)
73
+ if term
74
+ concept = concept_collection.fetch_or_initialize(term.id)
75
+ concept.add_l10n(term)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
data/lib/iev/cli/ui.rb ADDED
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2020 Ribose Inc.
4
+ #
5
+
6
+ module IEV
7
+ module CLI
8
+ # @todo
9
+ # Make it thread-safe. Currently, calling UI methods from different
10
+ # threads may result with mangled output. At first glance it seems like
11
+ # something is wrong with carriage returns, but more research is needed.
12
+ module UI
13
+ module_function
14
+
15
+ def debug(*args)
16
+ Helper.cli_out(:debug, *args)
17
+ end
18
+
19
+ def warn(*args)
20
+ Helper.cli_out(:warn, *args)
21
+ end
22
+
23
+ # Prints progress message which will be replaced on next call.
24
+ def progress(message)
25
+ return unless $IEV_PROGRESS
26
+
27
+ print "#{Helper.clear_progress}#{message} "
28
+ end
29
+
30
+ # Prints generic message.
31
+ def info(message)
32
+ print "#{Helper.clear_progress}#{message}\n"
33
+ end
34
+
35
+ # Sets an UI tag which will be prepended to messages printed with
36
+ # #debug and #warn.
37
+ def set_ui_tag(str)
38
+ Thread.current[:iev_ui_tag] = str
39
+ end
40
+
41
+ module Helper
42
+ module_function
43
+
44
+ def clear_progress
45
+ $IEV_PROGRESS ? "\r#{" " * 40}\r" : ""
46
+ end
47
+
48
+ def cli_out(level, *args)
49
+ topic = Symbol === args[0] ? args.shift : nil
50
+ message = args.map(&:to_s).join(" ").chomp
51
+ ui_tag = Thread.current[:iev_ui_tag]
52
+
53
+ return unless should_out?(level, topic)
54
+
55
+ print [
56
+ clear_progress,
57
+ ui_tag,
58
+ ui_tag && ": ",
59
+ message,
60
+ "\n",
61
+ ].join
62
+ end
63
+
64
+ def should_out?(level, topic)
65
+ topic.nil? || level == :warn || $IEV_DEBUG[topic]
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
data/lib/iev/cli.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # (c) Copyright 2020 Ribose Inc.
4
+ #
5
+
6
+ module IEV
7
+ module CLI
8
+ def self.start(arguments)
9
+ Signal.trap("INT") do
10
+ UI.info "Signal SIGINT received, quitting!"
11
+ Kernel.exit(1)
12
+ end
13
+
14
+ Signal.trap("TERM") do
15
+ UI.info "Signal SIGTERM received, quitting!"
16
+ Kernel.exit(1)
17
+ end
18
+
19
+ IEV::CLI::Command.start(arguments)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IEV
4
+ module Converter
5
+ class MathmlToAsciimath
6
+ using DataConversions
7
+
8
+ def self.convert(input)
9
+ new.convert(input)
10
+ end
11
+
12
+ def convert(input)
13
+ mathml_to_asciimath(input)
14
+ end
15
+
16
+ private
17
+
18
+ def mathml_to_asciimath(input)
19
+ # If given string does not include '<' (for elements) nor '&'
20
+ # (for entities), then it's certain that it doesn't contain
21
+ # any MathML or HTML formula.
22
+ return input unless input&.match?(/<|&/)
23
+
24
+ unless input.include?("<math>")
25
+ return html_to_asciimath(input)
26
+ end
27
+
28
+ # puts "GOING TO MATHML MATH"
29
+ # puts input
30
+ to_asciimath = Nokogiri::HTML.fragment(input, "UTF-8")
31
+ # to_asciimath.remove_namespaces!
32
+
33
+ to_asciimath.css("math").each do |math_element|
34
+ asciimath = Plurimath::Math.parse(
35
+ text_to_asciimath(math_element.to_xml), :mathml
36
+ ).to_asciimath.strip
37
+ # puts"ASCIIMATH!! #{asciimath}"
38
+
39
+ if asciimath.empty?
40
+ math_element.remove
41
+ else
42
+ math_element.replace "stem:[#{asciimath}]"
43
+ end
44
+ end
45
+
46
+ html_to_asciimath(
47
+ to_asciimath.children.to_s,
48
+ )
49
+ end
50
+
51
+ def html_to_asciimath(input)
52
+ return input if input.nil? || input.empty?
53
+
54
+ to_asciimath = Nokogiri::HTML.fragment(input, "UTF-8")
55
+
56
+ to_asciimath.css("i").each do |math_element|
57
+ # puts "HTML MATH!! #{math_element.to_xml}"
58
+ # puts "HTML MATH!! #{math_element.text}"
59
+ decoded = text_to_asciimath(math_element.text)
60
+ case decoded.length
61
+ when 1..12
62
+ # puts "(#{math_element.text} to => #{decoded})"
63
+ math_element.replace "stem:[#{decoded}]"
64
+ when 0
65
+ math_element.remove
66
+ else
67
+ math_element.replace "_#{decoded}_"
68
+ end
69
+ end
70
+
71
+ to_asciimath.css("sub").each do |math_element|
72
+ case math_element.text.length
73
+ when 0
74
+ math_element.remove
75
+ else
76
+ math_element.replace "~#{text_to_asciimath(math_element.text)}~"
77
+ end
78
+ end
79
+
80
+ to_asciimath.css("sup").each do |math_element|
81
+ case math_element.text.length
82
+ when 0
83
+ math_element.remove
84
+ else
85
+ math_element.replace "^#{text_to_asciimath(math_element.text)}^"
86
+ end
87
+ end
88
+
89
+ to_asciimath.css("ol").each do |element|
90
+ element.css("li").each do |li|
91
+ li.replace ". #{li.text}"
92
+ end
93
+ end
94
+
95
+ to_asciimath.css("ul").each do |element|
96
+ element.css("li").each do |li|
97
+ li.replace "* #{li.text}"
98
+ end
99
+ end
100
+
101
+ # Replace sans-serif font with monospace
102
+ to_asciimath.css('font[style*="sans-serif"]').each do |x|
103
+ x.replace "`#{x.text}`"
104
+ end
105
+
106
+ html_entities_to_stem(
107
+ to_asciimath
108
+ .children.to_s
109
+ .gsub(/\]stem:\[/, "")
110
+ .gsub(/<\/?[uo]l>/, ""),
111
+ )
112
+ end
113
+
114
+ def text_to_asciimath(text)
115
+ html_entities_to_asciimath(text.decode_html)
116
+ end
117
+
118
+ def html_entities_to_asciimath(input)
119
+ input.gsub("&alpha;", "alpha").
120
+ gsub("&beta;", "beta").
121
+ gsub("&gamma;", "gamma").
122
+ gsub("&Gamma;", "Gamma").
123
+ gsub("&delta;", "delta").
124
+ gsub("&Delta;", "Delta").
125
+ gsub("&epsilon;", "epsilon").
126
+ gsub("&varepsilon;", "varepsilon").
127
+ gsub("&zeta;", "zeta").
128
+ gsub("&eta;", "eta").
129
+ gsub("&theta;", "theta").
130
+ gsub("&Theta;", "Theta").
131
+ gsub("&vartheta;", "vartheta").
132
+ gsub("&iota;", "iota").
133
+ gsub("&kappa;", "kappa").
134
+ gsub("&lambda;", "lambda").
135
+ gsub("&Lambda;", "Lambda").
136
+ gsub("&mu;", "mu").
137
+ gsub("&nu;", "nu").
138
+ gsub("&xi;", "xi").
139
+ gsub("&Xi;", "Xi").
140
+ gsub("&pi;", "pi").
141
+ gsub("&Pi;", "Pi").
142
+ gsub("&rho;", "rho").
143
+ gsub("&beta;", "beta").
144
+ gsub("&sigma;", "sigma").
145
+ gsub("&Sigma;", "Sigma").
146
+ gsub("&tau;", "tau").
147
+ gsub("&upsilon;", "upsilon").
148
+ gsub("&phi;", "phi").
149
+ gsub("&Phi;", "Phi").
150
+ gsub("&varphi;", "varphi").
151
+ gsub("&chi;", "chi").
152
+ gsub("&psi;", "psi").
153
+ gsub("&Psi;", "Psi").
154
+ gsub("&omega;", "omega")
155
+ end
156
+
157
+ def html_entities_to_stem(input)
158
+ input.gsub("&alpha;", "stem:[alpha]").
159
+ gsub("&beta;", "stem:[beta]").
160
+ gsub("&gamma;", "stem:[gamma]").
161
+ gsub("&Gamma;", "stem:[Gamma]").
162
+ gsub("&delta;", "stem:[delta]").
163
+ gsub("&Delta;", "stem:[Delta]").
164
+ gsub("&epsilon;", "stem:[epsilon]").
165
+ gsub("&varepsilon;", "stem:[varepsilon]").
166
+ gsub("&zeta;", "stem:[zeta]").
167
+ gsub("&eta;", "stem:[eta]").
168
+ gsub("&theta;", "stem:[theta]").
169
+ gsub("&Theta;", "stem:[Theta]").
170
+ gsub("&vartheta;", "stem:[vartheta]").
171
+ gsub("&iota;", "stem:[iota]").
172
+ gsub("&kappa;", "stem:[kappa]").
173
+ gsub("&lambda;", "stem:[lambda]").
174
+ gsub("&Lambda;", "stem:[Lambda]").
175
+ gsub("&mu;", "stem:[mu]").
176
+ gsub("&nu;", "stem:[nu]").
177
+ gsub("&xi;", "stem:[xi]").
178
+ gsub("&Xi;", "stem:[Xi]").
179
+ gsub("&pi;", "stem:[pi]").
180
+ gsub("&Pi;", "stem:[Pi]").
181
+ gsub("&rho;", "stem:[rho]").
182
+ gsub("&beta;", "stem:[beta]").
183
+ gsub("&sigma;", "stem:[sigma]").
184
+ gsub("&Sigma;", "stem:[Sigma]").
185
+ gsub("&tau;", "stem:[tau]").
186
+ gsub("&upsilon;", "stem:[upsilon]").
187
+ gsub("&phi;", "stem:[phi]").
188
+ gsub("&Phi;", "stem:[Phi]").
189
+ gsub("&varphi;", "stem:[varphi]").
190
+ gsub("&chi;", "stem:[chi]").
191
+ gsub("&psi;", "stem:[psi]").
192
+ gsub("&Psi;", "stem:[Psi]").
193
+ gsub("&omega;", "stem:[omega]")
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IEV
4
+ module Converter
5
+ def self.mathml_to_asciimath(input)
6
+ IEV::Converter::MathmlToAsciimath.convert(input)
7
+ end
8
+ end
9
+ end