Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions .github/workflows/npm.yml

This file was deleted.

41 changes: 41 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: test

on:
push:
branches:
- main
pull_request:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
node-version: [16, 18, 20, 22]

steps:
- uses: actions/checkout@v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: npm install

- name: Build bundle
run: |
npm run podman:build
npm run podman:bundle

Comment thread
suleman-uzair marked this conversation as resolved.
- name: Run JavaScript tests
run: npx jest
Comment thread
suleman-uzair marked this conversation as resolved.

- name: Run native Ruby tests
run: npm run test:rb
7 changes: 4 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ gem 'equivalent-xml', path: 'vendor/equivalent-xml'
gem 'ruby-ll', path: 'vendor/ruby-ll'
gem 'htmlentities', path: 'vendor/htmlentities'
gem 'opal', path: 'vendor/opal'
gem 'plurimath', path: 'vendor/plurimath'

gem 'opal-rspec', '>= 1.1.0a'

gem 'nokogiri'
gem 'rake'
gem 'rspec'
gem 'ae'
Expand All @@ -22,6 +22,7 @@ gem 'rack'
gem 'rackup'
gem 'simplecov'
gem 'ox'
gem 'unitsml'
gem 'monitor'
gem 'mml'
gem 'unitsml', git: 'https://github.com/unitsml/unitsml-ruby.git', branch: 'fix/opal-database-payload-loader'
gem 'lutaml-model', github: "lutaml/lutaml-model", branch: "fix/opal-runtime-compatibility-changes"
gem 'omml', github: "plurimath/omml", branch: "fix/opal-runtime-compatibility-changes"
11 changes: 11 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
#!/bin/sh
set -e

rm -rf tmp/
mkdir -p tmp/
cp src/* tmp/

echo "** Generating UnitsML Opal payload"
bundle exec ruby scripts/generate_unitsml_opal_payload.rb tmp/unitsml_opal_payload.rb

echo "** Compiling Plurimath-Opal from Ruby with Opal"
bundle exec opal --esm -sjruby \
-qerb \
-rcorelib/array/pack \
-ropal-parser \
-qoga/setup_opal \
-qll/setup_opal \
-Itmp/ \
-runitsml_opal_payload \
-gplurimath \
-gunitsml \
-ghtmlentities \
-gparslet \
-gmonitor \
-snokogiri \
-sox \
-sox/ox \
-sox.so \
Expand Down
2 changes: 2 additions & 0 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
<option>html</option>
<option>mathml</option>
<option>latex</option>
<option>unicodemath</option>
</select>
<select id="tofmt">
<option>Asciimath</option>
<option>Omml</option>
<option>Html</option>
<option>Mathml</option>
<option>Latex</option>
<option>Unicodemath</option>
</select>

<button>Convert</button>
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
"scripts": {
"test": "npm run test:js && npm run test:rb",
"test:js": "npm run build && jest",
"test:rb": "podman run --rm -it -v $(pwd):/srv:z plurimath-js /bin/bash -c './setup.sh && env/plurimath'",
"test:rb": "npm run test:rb:native",
"test:rb:opal": "podman run --rm -i -e OPAL_PREFORK_DISABLE=1 -v .:/srv:z plurimath-js /bin/bash -c './setup.sh && env/plurimath'",
"test:rb:native": "podman run --rm -i -e OPAL_PREFORK_DISABLE=1 -v .:/srv:z plurimath-js /bin/bash -c './setup.sh && bundle exec rspec spec/unitsml_opal_payload_generator_spec.rb'",
"podman:build": "podman build -t plurimath-js .",
"podman:shell": "podman run --rm -it -v $(pwd):/srv:z plurimath-js",
"podman:bundle": "podman run --rm -it -v $(pwd):/srv:z plurimath-js /bin/bash -c './setup.sh && ./build.sh'",
"podman:shell": "podman run --rm -it -e OPAL_PREFORK_DISABLE=1 -v .:/srv:z plurimath-js",
"podman:bundle": "podman run --rm -i -e OPAL_PREFORK_DISABLE=1 -v .:/srv:z plurimath-js /bin/bash -c './setup.sh && ./build.sh'",
"build": "npm run podman:build && npm run podman:bundle",
"submodule:init": "git submodule init && npm run submodule:update",
"submodule:update": "git submodule update"
Expand Down
50 changes: 50 additions & 0 deletions scripts/generate_unitsml_opal_payload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

require "ox"
require "unitsdb"

module PlurimathJs
module UnitsmlOpalPayloadGenerator
module_function

def build_payload_hash(database_path: nil)
source_path = database_path || Unitsdb.data_dir
::Unitsdb::Database.from_db(source_path).to_hash
end

def to_ruby_source(database_hash)
rendered_hash = database_hash.inspect

<<~RUBY
# frozen_string_literal: true

require "unitsml"
require "unitsml/unitsdb"

Unitsml::Unitsdb::Database.load_opal_payload(
#{rendered_hash}.freeze,
)
RUBY
end

def write_to(file_path, database_hash: nil, database_path: nil)
payload_hash = database_hash || build_payload_hash(database_path: database_path)
absolute_path = File.expand_path(file_path)

File.write(absolute_path, to_ruby_source(payload_hash))
absolute_path
end
end
end

if $PROGRAM_NAME == __FILE__
output_path = ARGV[0]
database_path = ARGV[1]

abort "Usage: ruby scripts/generate_unitsml_opal_payload.rb OUTPUT_PATH [DATABASE_PATH]" unless output_path

PlurimathJs::UnitsmlOpalPayloadGenerator.write_to(
output_path,
database_path: database_path,
)
end
2 changes: 1 addition & 1 deletion setup.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
set -e

git submodule init
git submodule update
Expand All @@ -14,4 +15,3 @@ env/oga rake

rm -rf vendor/*/tmp/*
rm -rf vendor/ruby-ll/lib/libll.so vendor/oga/lib/liboga.so

15 changes: 13 additions & 2 deletions spec/to-mathml-intent.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import Plurimath from "../dist"

describe('to mathml with intent', () => {
it('', () => {
it('adds MathML intent metadata when requested', () => {
const math = new Plurimath('∑_𝑥^𝑦 𝑧', 'unicode')
const mathml = math.toMathml(true).trim()

expect(math.toMathml(true).trim()).toBe('<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">\n <mstyle displaystyle="true">\n <mrow intent=":sum(𝑥,𝑦,$naryand)">\n <munderover>\n <mo>&#x2211;</mo>\n <mi>&#x1d465;</mi>\n <mi>&#x1d466;</mi>\n </munderover>\n <mrow arg="naryand">\n <mi>&#x1d467;</mi>\n </mrow>\n </mrow>\n </mstyle>\n</math>')
expect(mathml).toContain('intent=":sum(𝑥,𝑦,$naryand)"')
expect(mathml).toContain('<munderover>')
expect(mathml).toMatch(/<mo>(&#x2211;|∑)<\/mo>/)
expect(mathml).toMatch(/<mrow arg="naryand">\s*<mi>(&#x1d467;|𝑧)<\/mi>\s*<\/mrow>/)
})

it('omits MathML intent metadata by default', () => {
const math = new Plurimath('∑_𝑥^𝑦 𝑧', 'unicode')

expect(math.toMathml()).not.toContain(' intent=')
expect(math.toMathml()).not.toBe(math.toMathml(true))
})
})
14 changes: 13 additions & 1 deletion spec/to-unicodemath.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import Plurimath from "../dist"

describe('to unicodemath', () => {
it('', () => {
it('matches conversion of UnicodeMath equation to UnicodeMath', () => {
const math = new Plurimath('∑_𝑥^𝑦 𝑧', 'unicode')

expect(math.toUnicodemath().trim()).toBe('∑_(𝑥)^(𝑦)▒〖𝑧〗')
})

it('matches conversion of LaTeX equation to UnicodeMath', () => {
const math = new Plurimath('M \\= \\begin{bmatrix} \\-\\sin λ_0 \\& \\cos λ_0 \\& 0 \\\\ \\-\\sin φ_0 \\cos λ_0 \\& \\-\\sin φ_0 \\sin λ_0 \\& \\cos φ_0 \\\\ \\cos φ_0 \\cos λ_0 \\& \\cos φ_0 \\sin λ_0 \\& \\sin φ_0 \\end{bmatrix}', 'latex')

expect(math.toUnicodemath()).toBe('M = ⓢ(− sin⁡λ_(0)&cos⁡λ_(0)&0@− sin⁡φ_(0)cos⁡λ_(0)&− sin⁡φ_(0)sin⁡λ_(0)&cos⁡φ_(0)@cos⁡φ_(0)cos⁡λ_(0)&cos⁡φ_(0)sin⁡λ_(0)&sin⁡φ_(0))')
})

it('tests basic equation performing plus operation', () => {
const math = new Plurimath('M \\= a \\+ b', 'latex')

expect(math.toUnicodemath()).toBe('M = a + b')
})
})
53 changes: 53 additions & 0 deletions spec/unitsml.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Plurimath from "../dist"

describe('unitsml asciimath', () => {
it('converts simple unit: kg', () => {
const math = new Plurimath('"unitsml(kg)"', 'asciimath')

expect(math.toAsciimath()).toBe('rm(kg)')
expect(math.toLatex()).toBe('\\mathrm{kg}')
expect(math.toMathml()).toMatch(/<mstyle mathvariant="normal">\s*<mi>kg<\/mi>\s*<\/mstyle>/)
})

it('converts unit with value: 9.8 m/s^2', () => {
const math = new Plurimath('9.8 "unitsml(m/s^2)"', 'asciimath')

expect(math.toAsciimath()).toBe('9.8 rm(m) * rm(s)^(- 2)')
expect(math.toLatex()).toBe('9.8 \\mathrm{m} \\cdot \\mathrm{s}^{- 2}')
})

it('converts frequency unit: Hz', () => {
const math = new Plurimath('"unitsml(Hz)"', 'asciimath')

expect(math.toAsciimath()).toBe('rm(Hz)')
expect(math.toLatex()).toBe('\\mathrm{Hz}')
})

it('converts prefixed unit: MHz', () => {
const math = new Plurimath('"unitsml(MHz)"', 'asciimath')

expect(math.toAsciimath()).toBe('rm(MHz)')
expect(math.toLatex()).toBe('\\mathrm{MHz}')
})

it('converts compound unit: g/mol', () => {
const math = new Plurimath('"unitsml(g/mol)"', 'asciimath')

expect(math.toAsciimath()).toBe('rm(g) * rm(mol)^(- 1)')
expect(math.toLatex()).toBe('\\mathrm{g} \\cdot \\mathrm{mol}^{- 1}')
})

it('converts unit in expression context', () => {
const math = new Plurimath('1 "unitsml(A)"', 'asciimath')

expect(math.toAsciimath()).toBe('1 rm(A)')
expect(math.toLatex()).toBe('1 \\mathrm{A}')
})

it('converts Hz in complex expression', () => {
const math = new Plurimath('540 xx 10^(12) "unitsml(Hz)"', 'asciimath')

expect(math.toAsciimath()).toContain('rm(Hz)')
expect(math.toLatex()).toContain('\\mathrm{Hz}')
})
})
66 changes: 66 additions & 0 deletions spec/unitsml_opal_payload_generator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# frozen_string_literal: true

require "tmpdir"
require_relative "../scripts/generate_unitsml_opal_payload"

RSpec.describe PlurimathJs::UnitsmlOpalPayloadGenerator do
let(:database_hash) do
{
"schema_version" => "2.0.0",
"units" => [],
"prefixes" => [],
"quantities" => [],
"dimensions" => [],
"unit_systems" => [],
}
end

describe ".to_ruby_source" do
it "renders a Ruby payload file that loads the Opal database payload" do
source = described_class.to_ruby_source(database_hash)

expect(source).to include('require "unitsml"')
expect(source).to include("Unitsml::Unitsdb::Database.load_opal_payload(")
expect(source).not_to include("class OpalDatabase")
expect(source).not_to include("def self.from_db")
expect(source).to match(/"schema_version"\s*=>\s*"2\.0\.0"/)
expect(source).to include(".freeze")
end

it "renders unit symbols as a Ruby literal" do
source = described_class.to_ruby_source(
database_hash.merge(
"units" => [
{
"id" => "ohm",
"symbols" => ["Ω", "µΩ"],
},
],
),
)

rendered_hash = source.match(/load_opal_payload\(\n (.*)\.freeze,/m)[1]
payload = eval(rendered_hash) # rubocop:disable Security/Eval

expect(payload["units"].first["symbols"]).to eq(["Ω", "µΩ"])
end
end

describe ".write_to" do
it "writes the generated payload file to the requested path" do
file_path = nil

Dir.mktmpdir do |dir|
file_path = described_class.write_to(
File.join(dir, "unitsml_opal_payload.rb"),
database_hash: database_hash,
)

generated_source = File.read(file_path)
expect(generated_source).to eq(described_class.to_ruby_source(database_hash))
end

expect(file_path).to end_with("unitsml_opal_payload.rb")
end
end
end
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import "./plurimath-opal.js";

Opal.require("plurimath");

export default class Plurimath {
Expand Down
2 changes: 1 addition & 1 deletion vendor/plurimath
Submodule plurimath updated 3215 files
Loading