mathematical 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9fad17d831541b401f9eda17a2bcac80e41dd490
4
+ data.tar.gz: da0a7b96a1e43f8cd9a49e5bcf01a83a26881749
5
+ SHA512:
6
+ metadata.gz: 973f40da8c62e2f7c16df0e846c72252abebb022ae6465e85714ccf3af743642664573980ffc016e308aa07a9c2a2aa04161a3dcfe133bc32b186392abab762d
7
+ data.tar.gz: c20e0733a2efac5d629104bddecd3bb306ad04f677d2e371bf4d1f90691867eeb5746ebc88bd87a801b8d0e1ec73970726eb74cb6e884b97fd3f37f08a2b0c51
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ /vendor/gems/
19
+ bin/
20
+ ext/blahtexml/Source/extconf.rb
21
+ ext/blahtexml/Source/makefile
22
+ ext/blahtexml/bin-blahtex
23
+ ext/blahtexml/blahtex
data/.gitmodules ADDED
@@ -0,0 +1,4 @@
1
+ [submodule "ext/blahtexml"]
2
+ path = ext/blahtexml
3
+ url = git@github.com:gvanas/blahtexml.git
4
+ ignore = dirty
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mathematical.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Garen Torikian
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Mathematical
2
+
3
+ Convert mathematical equations to base64 encoded images.
4
+
5
+ ![](https://i.imgur.com/JC7HT32.gif)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'mathematical'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install mathematical
20
+
21
+ ## Usage
22
+
23
+ The simplest way to do this is
24
+
25
+ ``` ruby
26
+ Mathematical::Render.new.render(contents)
27
+ ```
28
+
29
+ `contents` should just be a block of text, containing inline or display style math.
30
+
31
+ ## Dependencies
32
+
33
+ Two dependencies are needed:
34
+
35
+ * [blahtexml](https://github.com/gvanas/blahtexml). This does all the conversion
36
+ from math to PNG. It's available for OS X (`make blahtex-mac`) and Linux (`make blahtex-linux`).
37
+ * [dvipng](http://sourceforge.net/projects/dvipng/). I'm on a Mac, and could not
38
+ for the life of me figure out how to build this. I ended up downloading [MacTex](https://www.tug.org/mactex/),
39
+ which is a *huge* package. `dvipng` is installed under */usr/texbin/dvipng*.
40
+
41
+ ## Why did you...?
42
+
43
+ There are a smattering of Ruby, C, and Ruby+C libraries out there for converting
44
+ math equations to a variety of formats. There needs to be a sane way to show math
45
+ equations in the browser. The options are:
46
+
47
+ * MathML: With browser support for MathML under attack, it's unfortunately not a sustainable
48
+ solution
49
+ * MathJax. While extremely popular, I dislike the "stuttering" effect caused by
50
+ pages loading math. JavaScript shouldn't be used in situations where server-rendering
51
+ is a possibility, in my opinion.
52
+ * SVG: This would be a great choice, but, unfortunately, there are some [security concerns](http://www.hgi.ruhr-uni-bochum.de/media/hgi/veroeffentlichungen/2011/10/19/svgSecurity-ccs11.pdf) [PDF]
53
+ that make me nervous
54
+ * PNG: This is the format which `blahtexml` is capable of outputting. Working
55
+ with a binary format has the downside of requiring it to be *hosted* somewhere.
56
+
57
+ After considering these choices, I thought that a base64 encoded image made
58
+ the most sense. You get the benefit of browser compatibility without needing
59
+ to serve an image somewhere online.
60
+
61
+ ## Further readings
62
+
63
+ * ftp://ftp.ams.org/ams/doc/amsmath/short-math-guide.pdf - a short math guide
64
+ * http://gva.noekeon.org/blahtexml/blahtexml-0.9-doc.pdf - the blahtex documentation
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+ require 'rbconfig'
5
+ require 'fileutils'
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs << "test"
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ t.verbose = true
11
+ end
12
+
13
+ task :default => [:test]
14
+
15
+ namespace :git do
16
+ namespace :submodules do
17
+ desc "Initialize git submodules"
18
+ task :init do
19
+ system "git submodule init"
20
+ system "git submodule update"
21
+ end
22
+ end
23
+ end
24
+
25
+ task :makebin do
26
+ host_os = RbConfig::CONFIG['host_os']
27
+ Dir.chdir "ext/blahtexml" do
28
+ case host_os
29
+ # when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
30
+ # :windows
31
+ when /darwin|mac os/
32
+ `make blahtex-mac`
33
+ FileUtils.mkdir_p "../../bin/blahtex/macosx/"
34
+ FileUtils.cp "blahtex", "../../bin/blahtex/macosx/"
35
+ when /linux/
36
+ `make blahtex-linux`
37
+ FileUtils.mkdir_p "../../bin/blahtex/linux/"
38
+ FileUtils.cp "blahtex", "../../bin/blahtex/linux/"
39
+ # when /solaris|bsd/
40
+ # :unix
41
+ else
42
+ raise Error, "unknown os: #{host_os.inspect}"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ require "mathematical/parser"
2
+ require "mathematical/render"
3
+ require "mathematical/version"
4
+
5
+ module Mathematical
6
+ # Raised when missing binaries for images rendering.
7
+ class CommandNotFoundError < Exception; end
8
+ end
@@ -0,0 +1,30 @@
1
+ module Mathematical
2
+ class Parser
3
+ # https://stackoverflow.com/questions/14182879/regex-to-match-latex-equations
4
+ REGEX = /
5
+ (?<!\\) # negative look-behind to make sure start is not escaped
6
+ (?: # start non-capture group for all possible match starts
7
+ # group 1, match dollar signs only
8
+ # single or double dollar sign enforced by look-arounds
9
+ ((?<!\$)\${1,2}(?!\$))|
10
+ # group 2, match escaped parenthesis
11
+ (\\\()|
12
+ # group 3, match escaped bracket
13
+ (\\\[)|
14
+ # group 4, match begin equation
15
+ (\\begin\{equation\})
16
+ )
17
+ (.*(\g<1>)?.*) # match everything in between including nested LaTeX equations
18
+ (?<!\\) # negative look-behind to make sure end is not escaped
19
+ # if group 1 was start, match \1
20
+ (?(1)(?<!\$)\1(?!\$)|
21
+ # if group 2 was start, escaped parenthesis is end
22
+ (?(2)\\\)|
23
+ # if group 3 was start, escaped bracket is end
24
+ (?(3)\\\]|
25
+ # otherwise group 4 was start, match end equation
26
+ \\end\{equation\}
27
+ )))
28
+ /x
29
+ end
30
+ end
@@ -0,0 +1,101 @@
1
+ require 'rbconfig'
2
+ require 'fileutils'
3
+ require 'tmpdir'
4
+ require 'shellwords'
5
+ require 'base64'
6
+
7
+ module Mathematical
8
+ class Render
9
+ DEFAULT_OPTS = {
10
+ :html_png_resolution => 200
11
+ }
12
+
13
+ def initialize(opts = {})
14
+ @os ||= (
15
+ host_os = RbConfig::CONFIG['host_os']
16
+ case host_os
17
+ when /darwin|mac os/
18
+ "macosx"
19
+ when /linux/
20
+ "linux"
21
+ else
22
+ raise Error, "unknown os: #{host_os.inspect}"
23
+ end
24
+ )
25
+
26
+ opts = DEFAULT_OPTS.merge(opts)
27
+ @temp_dir = Dir.mktmpdir
28
+ @args = [
29
+ '--png',
30
+ '--use-preview-package',
31
+ # '--shell-dvipng',
32
+ # "'dvipng -D #{Shellwords.shellescape opts[:html_png_resolution].to_s}'",
33
+ ]
34
+ end
35
+
36
+
37
+ def render(contents)
38
+ in_tmpdir do |tmpdir|
39
+ @args << "--temp-directory #{Shellwords.shellescape tmpdir.first}"
40
+ @args << "--png-directory #{Shellwords.shellescape tmpdir.first}"
41
+
42
+ contents.gsub(Mathematical::Parser::REGEX) do |maths|
43
+ if maths =~ /^\$(?!\$)/
44
+ maths = maths[1..-2]
45
+ type = :inline
46
+ else
47
+ type = :display
48
+ end
49
+
50
+ data = run_blahtex(maths, type)
51
+ if filename = data.match("<md5>(.+?)</md5>")[1]
52
+ "<img class=\"#{type.to_s}-math\" src=\"data:image/png;base64,#{png_to_base64(File.join(tmpdir, "#{filename}.png"))}\"/>"
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def run_blahtex(tex, type)
59
+ raise CommandNotFoundError, "Required commands missing: #{missing_commands.join(', ')} in PATH. (#{ENV['PATH']})" unless missing_commands.empty?
60
+ @args << '--displaymath' if type == :equation
61
+
62
+ IO.popen(["bin/blahtex/#{@os}/blahtex", *@args].join(' '), 'w+') do |blahtex|
63
+ blahtex.write tex
64
+ blahtex.close_write
65
+
66
+ output = blahtex.read
67
+ blahtex.close_read
68
+
69
+ raise "Error running blahtex" unless $?.success?
70
+
71
+ output
72
+ end
73
+ end
74
+
75
+ def png_to_base64(path)
76
+ File.open(path, 'r') { |image_file| Base64.encode64(image_file.read).gsub(/\n/, '') }
77
+ end
78
+
79
+ private
80
+
81
+ # Check toolchain availability and returns array of missing tools
82
+ def missing_commands
83
+ commands = []
84
+ commands << "dvipng" unless can_run?("dvipng -v")
85
+ commands
86
+ end
87
+
88
+ # Trial command and check if return code is zero
89
+ def can_run?(command)
90
+ `#{command} 2>&1`
91
+ $?.exitstatus.zero?
92
+ end
93
+
94
+ def in_tmpdir
95
+ path = FileUtils.mkdir_p Dir.tmpdir
96
+ yield path
97
+ ensure
98
+ FileUtils.rm_rf( path )
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,3 @@
1
+ module Mathematical
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mathematical/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mathematical"
8
+ spec.version = Mathematical::VERSION
9
+ spec.authors = ["Garen Torikian"]
10
+ spec.email = ["gjtorikian@gmail.com"]
11
+ spec.summary = %q{Turn maths into PNGs.}
12
+ spec.description = %q{Turn maths into PNGs.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ end
data/script/bootstrap ADDED
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+ export CC=gcc
5
+
6
+ echo "==> Installing gem dependencies…"
7
+ bundle check --path vendor/gems 2>&1 > /dev/null || {
8
+ bundle install --binstubs bin --path vendor/gems --quiet
9
+ }
@@ -0,0 +1,9 @@
1
+ require "test_helper"
2
+ require "mathematical"
3
+
4
+ class Mathematical::BasicTest < Test::Unit::TestCase
5
+
6
+ def test_it_has_a_version
7
+ assert Mathematical::VERSION
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ When <img class="inline-math" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAUCAMAAAAusUTNAAAANlBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHL6OuAAAAEXRSTlMAQKOPaOEsfMNW+dMW7bPx81p55n0AAADiSURBVCgVtVLZAoQgCCSPrM0O//9ndyA1tK235YE4holDoheJL7lbypkailuwl1fD2vAX9zoSuUkne1tRWwF+hh6ifEXtpQtvVbYzg+ozBU5OnvVgrL3PoKhjcozbViiHkvGslpgX2Q98Fg5w9kR/2MS8JEpSWTFPkYyegJZuZhiNWD1R7mQBQ+K4yf+sFZoaGJly8WhkBkQtZ+O2j12aLxx1g5E7jiiR8sItuyoOkZWyhOus4DYpzvpQpikFG18+cMmIB0OmyceO+gSpa11/hWVkvU3o2blTP2P/Sk38En7LF60+BSj8TilKAAAAAElFTkSuQmCC"/>, there are two solutions...
@@ -0,0 +1 @@
1
+ When $a \ne 0$, there are two solutions...
@@ -0,0 +1,31 @@
1
+ require "test_helper"
2
+
3
+ class Mathematical::FixturesTest < Test::Unit::TestCase
4
+
5
+ Dir['test/mathematical/fixtures/before/*.text'].each do |before|
6
+ name = before.split('/').last
7
+
8
+ define_method "test_#{name}" do
9
+ source = File.read(before)
10
+
11
+ expected_file = before.sub(/before/, "after").sub(/text/, "html")
12
+ expected = File.read(expected_file).rstrip
13
+ actual = Mathematical::Render.new.render(source).rstrip
14
+
15
+ if source != expected
16
+ assert(source != actual, "#{name} did not render anything")
17
+ end
18
+
19
+ diff = IO.popen("diff -u - #{expected_file}", 'r+') do |f|
20
+ f.write actual
21
+ f.close_write
22
+ f.read
23
+ end
24
+
25
+ assert expected == actual, <<message
26
+ #{File.basename expected_file}'s contents don't match command output:
27
+ #{diff}
28
+ message
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ require 'bundler/setup'
2
+ require 'mathematical'
3
+ require 'test/unit'
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mathematical
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Garen Torikian
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Turn maths into PNGs.
42
+ email:
43
+ - gjtorikian@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .gitmodules
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - lib/mathematical.rb
55
+ - lib/mathematical/parser.rb
56
+ - lib/mathematical/render.rb
57
+ - lib/mathematical/version.rb
58
+ - mathematical.gemspec
59
+ - script/bootstrap
60
+ - test/mathematical/basic_test.rb
61
+ - test/mathematical/fixtures/after/basic.html
62
+ - test/mathematical/fixtures/before/basic.text
63
+ - test/mathematical/fixtures_test.rb
64
+ - test/test_helper.rb
65
+ homepage: ''
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.0.3
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Turn maths into PNGs.
89
+ test_files:
90
+ - test/mathematical/basic_test.rb
91
+ - test/mathematical/fixtures/after/basic.html
92
+ - test/mathematical/fixtures/before/basic.text
93
+ - test/mathematical/fixtures_test.rb
94
+ - test/test_helper.rb