polytexnic 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +37 -0
  3. data/.pull_requests/1371777257 +0 -0
  4. data/.pull_requests/1371927975 +0 -0
  5. data/.pull_requests/1372804345 +0 -0
  6. data/.pull_requests/1374784075 +0 -0
  7. data/.pull_requests/1375304853 +0 -0
  8. data/.pull_requests/1375408308 +0 -0
  9. data/.pull_requests/1375409462 +0 -0
  10. data/.pull_requests/1375410668 +0 -0
  11. data/.pull_requests/1375472132 +0 -0
  12. data/.pull_requests/1375485496 +0 -0
  13. data/.pull_requests/1375487548 +0 -0
  14. data/.pull_requests/1375492835 +0 -0
  15. data/.pull_requests/1375497765 +0 -0
  16. data/.pull_requests/1375559547 +0 -0
  17. data/.pull_requests/1375589063 +0 -0
  18. data/.pull_requests/1375841786 +0 -0
  19. data/.pull_requests/1376352634 +0 -0
  20. data/.pull_requests/1376353299 +0 -0
  21. data/.pull_requests/1376449284 +0 -0
  22. data/.pull_requests/1376452696 +0 -0
  23. data/.pull_requests/1376454166 +0 -0
  24. data/.pull_requests/1376532291 +0 -0
  25. data/.pull_requests/1376625487 +0 -0
  26. data/.pull_requests/1376690108 +0 -0
  27. data/.pull_requests/1376699046 +0 -0
  28. data/.pull_requests/1376707642 +0 -0
  29. data/.pull_requests/1377230284 +0 -0
  30. data/.pull_requests/1379118478 +0 -0
  31. data/.pull_requests/1379123150 +0 -0
  32. data/.pull_requests/1380221847 +0 -0
  33. data/.pull_requests/1380589654 +0 -0
  34. data/.pull_requests/1380673142 +0 -0
  35. data/.pull_requests/1380850800 +0 -0
  36. data/.pull_requests/1381001264 +0 -0
  37. data/.pull_requests/1381005204 +0 -0
  38. data/.pull_requests/1381103022 +0 -0
  39. data/.pull_requests/1381252832 +0 -0
  40. data/.pull_requests/1381276624 +0 -0
  41. data/.pull_requests/1381344234 +0 -0
  42. data/.pull_requests/1381385297 +0 -0
  43. data/.pull_requests/1381427498 +0 -0
  44. data/.pull_requests/1381429761 +0 -0
  45. data/.pull_requests/1381873684 +0 -0
  46. data/.pull_requests/1382045490 +0 -0
  47. data/.pull_requests/1382056384 +0 -0
  48. data/.pull_requests/1382405223 +0 -0
  49. data/.pull_requests/1382478400 +0 -0
  50. data/.pull_requests/1382479780 +0 -0
  51. data/.pull_requests/1382485483 +0 -0
  52. data/.pull_requests/1382569911 +0 -0
  53. data/.pull_requests/1382646199 +0 -0
  54. data/.pull_requests/1382649778 +0 -0
  55. data/.pull_requests/1382660987 +0 -0
  56. data/.pull_requests/1382743927 +0 -0
  57. data/.pull_requests/1382840347 +0 -0
  58. data/.pull_requests/1383077676 +0 -0
  59. data/.pull_requests/1383086948 +0 -0
  60. data/.pull_requests/1383161978 +0 -0
  61. data/.pull_requests/1383263695 +0 -0
  62. data/.pull_requests/1383274008 +0 -0
  63. data/.pull_requests/1383327328 +0 -0
  64. data/.rspec +2 -0
  65. data/.ruby-gemset +1 -0
  66. data/.ruby-version +1 -0
  67. data/Gemfile +15 -0
  68. data/Guardfile +15 -0
  69. data/LICENSE.txt +22 -0
  70. data/README.md +21 -0
  71. data/Rakefile +2 -0
  72. data/lib/polytexnic/literal.rb +299 -0
  73. data/lib/polytexnic/postprocessor.rb +28 -0
  74. data/lib/polytexnic/postprocessors/html.rb +1139 -0
  75. data/lib/polytexnic/postprocessors/latex.rb +18 -0
  76. data/lib/polytexnic/postprocessors/polytex.rb +44 -0
  77. data/lib/polytexnic/preprocessor.rb +23 -0
  78. data/lib/polytexnic/preprocessors/html.rb +349 -0
  79. data/lib/polytexnic/preprocessors/latex.rb +43 -0
  80. data/lib/polytexnic/preprocessors/polytex.rb +127 -0
  81. data/lib/polytexnic/utils.rb +176 -0
  82. data/lib/polytexnic/version.rb +3 -0
  83. data/lib/polytexnic.rb +92 -0
  84. data/notes/pandoc.md +41 -0
  85. data/polytexnic.gemspec +28 -0
  86. data/polytexnic_commands.sty +5 -0
  87. data/precompiled_binaries/tralics +0 -0
  88. data/spec/fixtures/code_listing.tex +14 -0
  89. data/spec/fixtures/figures.tex +8 -0
  90. data/spec/fixtures/inline_math.html +4 -0
  91. data/spec/fixtures/inline_math.tex +3 -0
  92. data/spec/fixtures/math_environments.html +50 -0
  93. data/spec/fixtures/math_environments.tex +56 -0
  94. data/spec/fixtures/section_xrefs.tex +9 -0
  95. data/spec/fixtures/sidebar.tex +10 -0
  96. data/spec/fixtures/tables.tex +8 -0
  97. data/spec/fixtures/verbatim_environments.html +11 -0
  98. data/spec/fixtures/verbatim_environments.tex +13 -0
  99. data/spec/integration_spec.rb +34 -0
  100. data/spec/markdown_to_polytex_spec.rb +192 -0
  101. data/spec/resemble_matcher_spec.rb +69 -0
  102. data/spec/spec_helper.rb +38 -0
  103. data/spec/support/resemble_matcher.rb +100 -0
  104. data/spec/to_html/asides_spec.rb +42 -0
  105. data/spec/to_html/chapters_and_sections_spec.rb +268 -0
  106. data/spec/to_html/characters_and_punctuation_spec.rb +138 -0
  107. data/spec/to_html/codelistings_spec.rb +70 -0
  108. data/spec/to_html/core_spec.rb +227 -0
  109. data/spec/to_html/eqref_spec.rb +32 -0
  110. data/spec/to_html/footnote_spec.rb +164 -0
  111. data/spec/to_html/graphics_and_figures_spec.rb +358 -0
  112. data/spec/to_html/lists_spec.rb +103 -0
  113. data/spec/to_html/literal_environments/code_spec.rb +141 -0
  114. data/spec/to_html/literal_environments/math_spec.rb +255 -0
  115. data/spec/to_html/literal_environments/unicode_spec.rb +12 -0
  116. data/spec/to_html/literal_environments/verbatim_spec.rb +168 -0
  117. data/spec/to_html/quotations_and_verse_spec.rb +86 -0
  118. data/spec/to_html/table_of_contents_spec.rb +93 -0
  119. data/spec/to_html/table_spec.rb +269 -0
  120. data/spec/to_html/text_formatting_spec.rb +50 -0
  121. data/spec/to_latex_spec.rb +197 -0
  122. data/tasks/bin/ruby_tests +41 -0
  123. data/tasks/run_tests_with_both_rubies.rake +5 -0
  124. data/tmp/.gitkeep +0 -0
  125. metadata +286 -0
@@ -0,0 +1,176 @@
1
+ require 'securerandom'
2
+
3
+ module Polytexnic
4
+ module Utils
5
+ extend self
6
+
7
+ # Returns the executable for the Tralics LaTeX-to-XML converter.
8
+ def tralics
9
+ File.join(File.dirname(__FILE__), '..', '..',
10
+ 'precompiled_binaries', 'tralics')
11
+ end
12
+
13
+ # Returns a salted hash digest of the string.
14
+ def digest(string, options = {})
15
+ salt = options[:salt] || SecureRandom.base64
16
+ Digest::SHA1.hexdigest("#{salt}--#{string}")
17
+ end
18
+
19
+ # Returns a digest for passing things through the pipeline.
20
+ def pipeline_digest(element)
21
+ value = digest("#{Time.now.to_s}::#{element}")
22
+ @literal_cache[element.to_s] ||= value
23
+ end
24
+
25
+ # Returns a digest for use in labels.
26
+ # I like to use labels of the form cha:foo_bar, but for some reason
27
+ # Tralics removes the underscore in this case.
28
+ def underscore_digest
29
+ pipeline_digest('_')
30
+ end
31
+
32
+ # Escapes backslashes.
33
+ # Interpolated backslashes need extra escaping.
34
+ # We only escape '\\' by itself, i.e., a backslash followed by spaces
35
+ # or the end of line.
36
+ def escape_backslashes(string)
37
+ string.gsub(/\\(\s+|$)/) { '\\\\' + $1.to_s }
38
+ end
39
+
40
+ # Caches URLs for \href commands.
41
+ def cache_hrefs(doc, latex=false)
42
+ doc.tap do |text|
43
+ text.gsub!(/\\href{(.*?)}/) do
44
+ key = digest($1)
45
+ literal_cache[key] = $1
46
+ "\\href{#{key}}"
47
+ end
48
+ end
49
+ end
50
+
51
+ # Returns a Tralics pseudo-LaTeX XML element.
52
+ # The use of the 'skip' flag is a hack to be able to use xmlelement
53
+ # even when generating, e.g., LaTeX, where we simply want to yield the
54
+ # block.
55
+ def xmlelement(name, skip = false)
56
+ output = (skip ? "" : "\\begin{xmlelement}{#{name}}")
57
+ output << yield if block_given?
58
+ output << (skip ? "" : "\\end{xmlelement}")
59
+ end
60
+
61
+ # Returns some commands for Tralics.
62
+ # For various reasons, we don't actually want to include these in
63
+ # the style file that gets passed to LaTeX. For example,
64
+ # the commands with 'xmlelt' aren't even valid LaTeX; they're actually
65
+ # pseudo-LaTeX that has special meaning to the Tralics processor.
66
+ def tralics_commands
67
+ <<-'EOS'
68
+ % Commands specific to Tralics
69
+ \def\hyperref[#1]#2{\xmlelt{a}{\XMLaddatt{target}{#1}#2}}
70
+ \newcommand{\heading}[1]{\xmlelt{heading}{#1}}
71
+ \newcommand{\codecaption}[1]{\xmlelt{heading}{#1}}
72
+ \newcommand{\sout}[1]{\xmlelt{sout}{#1}}
73
+ \newcommand{\kode}[1]{\xmlelt{kode}{#1}}
74
+ \newcommand{\filepath}[1]{\xmlelt{filepath}{#1}}
75
+ \newcommand{\image}[1]{\xmlelt{image}{#1}}
76
+ \newcommand{\imagebox}[1]{\xmlelt{imagebox}{#1}}
77
+
78
+ % Code listings
79
+ \usepackage{amsthm}
80
+ \theoremstyle{definition}
81
+ \newtheorem{codelisting}{Listing}[chapter]
82
+ \newtheorem{aside}{Box}[chapter]
83
+ EOS
84
+ end
85
+
86
+ # Highlights source code.
87
+ def highlight_source_code(document)
88
+ if document.is_a?(String) # LaTeX
89
+ substitutions = {}
90
+ document.tap do
91
+ code_cache.each do |key, (content, language, in_codelisting)|
92
+ code = highlight(key, content, language, 'latex')
93
+ output = code.split("\n")
94
+ horrible_backslash_kludge(add_font_info(output.first))
95
+ code = output.join("\n")
96
+ substitutions[key] = in_codelisting ? code : framed(code)
97
+ end
98
+ document.gsub!(Regexp.union(substitutions.keys), substitutions)
99
+ end
100
+ else # HTML
101
+ document.css('div.code').each do |code_block|
102
+ key = code_block.content
103
+ next unless (value = code_cache[key])
104
+ content, language = value
105
+ code_block.inner_html = highlight(key, content, language, 'html')
106
+ end
107
+ end
108
+ end
109
+
110
+ # Puts a frame around code.
111
+ def framed(code)
112
+ "\\begin{framed_shaded}\n#{code}\n\\end{framed_shaded}"
113
+ end
114
+
115
+ # Highlights a code sample.
116
+ def highlight(key, content, language, formatter)
117
+ highlight_cache[key] ||= Pygments.highlight(content,
118
+ lexer: language,
119
+ formatter: formatter)
120
+ end
121
+
122
+ # Adds some verbatim font info (including size).
123
+ # We prepend rather than replace the styles because the Pygments output
124
+ # includes a required override of the default commandchars.
125
+ # Since the substitution is only important in the context of a PDF book,
126
+ # it only gets made if there's a style in 'softcover.sty' in the
127
+ # current directory
128
+ def add_font_info(string)
129
+ if File.exist?('softcover.sty')
130
+ regex = '{code}{Verbatim}{(.*)}'
131
+ styles = File.read('softcover.sty').scan(/#{regex}/).flatten.first
132
+ string.gsub!("\\begin{Verbatim}[",
133
+ "\\begin{Verbatim}[#{styles},")
134
+ end
135
+ string
136
+ end
137
+
138
+ # Does something horrible with backslashes.
139
+ # OK, so the deal is that code highlighted for LaTeX contains the line
140
+ # \begin{Verbatim}[commandchars=\\\{\}]
141
+ # Oh crap, there are backslashes in there. This means we have no chance
142
+ # of getting things to work after interpolating, gsubbing, and so on,
143
+ # because in Ruby '\\foo' is the same as '\\\\foo', '\}' is '}', etc.
144
+ # I thought I escaped (heh) this problem with the `escape_backslashes`
145
+ # method, but here the problem is extremely specific. In particular,
146
+ # \\\{\} is really \\ and \{ and \}, but Ruby doensn't know WTF to do
147
+ # with it, and thinks that it's "\\{}", which is the same as '\{}'.
148
+ # The solution is to replace '\\\\' with some number of backslashes.
149
+ # How many? I literally had to just keep adding backslashes until
150
+ # the output was correct when running `poly build:pdf`.
151
+ def horrible_backslash_kludge(string)
152
+ string.gsub!(/commandchars=\\\\/, 'commandchars=\\\\\\\\')
153
+ end
154
+
155
+ # Returns true if we are debugging, false otherwise.
156
+ # Manually change to `true` on an as-needed basis.
157
+ def debug?
158
+ false
159
+ end
160
+
161
+ # Returns true if we are profiling the code, false otherwise.
162
+ # Manually change to `true` on an as-needed basis.
163
+ def profiling?
164
+ return false if test?
165
+ false
166
+ end
167
+
168
+ def set_test_mode!
169
+ @@test_mode = true
170
+ end
171
+
172
+ def test?
173
+ defined?(@@test_mode) && @@test_mode
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,3 @@
1
+ module Polytexnic
2
+ VERSION = "0.5.0"
3
+ end
data/lib/polytexnic.rb ADDED
@@ -0,0 +1,92 @@
1
+ # encoding=utf-8
2
+ require "polytexnic/utils"
3
+ require "polytexnic/version"
4
+ require "polytexnic/postprocessor"
5
+ require "polytexnic/preprocessor"
6
+ require 'tempfile'
7
+ require 'nokogiri'
8
+ require 'digest/sha1'
9
+ require 'pygments'
10
+ require 'msgpack'
11
+
12
+ module Polytexnic
13
+
14
+ def self.style_file
15
+ 'polytexnic_commands.sty'
16
+ end
17
+
18
+ # Writes the contents of the custom polytexnic style file.
19
+ # This is used by the `generate` method in the `softcover` gem.
20
+ # We put it here because `custom.sty` lives inside `polytexnic`
21
+ # so that core can support, e.g., '\PolyTeXnic'.
22
+ def self.write_polytexnic_style_file(dir)
23
+ csf = File.join(File.dirname(__FILE__), '..', style_file)
24
+ File.write(File.join(dir, style_file), File.read(csf))
25
+ end
26
+
27
+ class Pipeline
28
+ include Polytexnic::Preprocessor
29
+ include Polytexnic::Postprocessor
30
+ include Polytexnic::Utils
31
+
32
+ attr_accessor :literal_cache, :code_cache, :polytex, :xml, :html,
33
+ :math_label_cache, :highlight_cache, :maketitle_elements,
34
+ :custom_commands
35
+
36
+ def initialize(source, options = {})
37
+ @literal_cache = {}
38
+ @code_cache = {}
39
+ @maketitle_elements = {}
40
+ @highlight_cache_filename = '.highlight_cache'
41
+ if File.exist?(@highlight_cache_filename)
42
+ content = File.read(@highlight_cache_filename)
43
+ @highlight_cache = MessagePack.unpack(content) unless content.empty?
44
+ end
45
+ @highlight_cache ||= {}
46
+ @math_label_cache = {}
47
+ @source_format = options[:source] || :polytex
48
+ @custom_commands = File.read(Polytexnic.style_file) rescue ''
49
+ @custom_commands += "\n" + (options[:custom_commands] || '')
50
+ @source = source
51
+ if markdown?
52
+ preprocess(:polytex)
53
+ postprocess(:polytex)
54
+ end
55
+ @polytex = @source
56
+ end
57
+
58
+ def to_html
59
+ if profiling?
60
+ require 'ruby-prof'
61
+ RubyProf.start
62
+ end
63
+
64
+ preprocess(:html)
65
+ postprocess(:html)
66
+ puts @html if debug?
67
+
68
+ if profiling?
69
+ result = RubyProf.stop
70
+ printer = RubyProf::GraphPrinter.new(result)
71
+ printer.print(STDOUT, {})
72
+ end
73
+ @html.strip
74
+ end
75
+
76
+ def to_latex
77
+ preprocess(:latex)
78
+ postprocess(:latex)
79
+ @latex
80
+ end
81
+
82
+ private
83
+
84
+ def markdown?
85
+ @source_format == :markdown || @source_format == :md
86
+ end
87
+
88
+ def polytex?
89
+ @source_format == :polytex
90
+ end
91
+ end
92
+ end
data/notes/pandoc.md ADDED
@@ -0,0 +1,41 @@
1
+
2
+ ## Math
3
+
4
+ ### Inline math
5
+
6
+ pandoc -s spec/fixtures/inline_math.tex --mathjax -o tmp/inline_math.html
7
+
8
+ ### Math environments
9
+
10
+ pandoc -s spec/fixtures/math_environments --mathjax -o tmp/math_environments.html
11
+
12
+ Pandoc handles equation environments wrong; it converts
13
+
14
+ \begin{equation}
15
+ \varphi^2 = \varphi + 1.
16
+ \end{equation}
17
+
18
+ into the non-equivalent
19
+
20
+ \[
21
+ \varphi^2 = \varphi + 1.
22
+ \]
23
+
24
+
25
+ ## Verbatim environments
26
+
27
+ Pandoc does well with inline verbatim text like `\verb+$x$+`, but it doesn't handle nested verbatim environments properly. In particular, it chokes on
28
+
29
+ \begin{verbatim}
30
+ \begin{verbatim}
31
+ This is verbatim text.
32
+ \end{verbatim}
33
+ \end{verbatim}
34
+
35
+ ## Tables
36
+
37
+ Pandoc doesn't handle tables at all.
38
+
39
+ ## Sections with cross-references
40
+
41
+ Pandoc doesn't handle cross-references.
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'polytexnic/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "polytexnic"
8
+ gem.version = Polytexnic::VERSION
9
+ gem.authors = ["Michael Hartl", "Nick Merwin"]
10
+ gem.email = ["michael@softcover.io"]
11
+ gem.description = %q{Core translation engine for the polytexnic gem}
12
+ gem.summary = %q{Convert from PolyTeX & Markdown to HTML & LaTeX}
13
+ gem.homepage = "https://polytexnic.org/"
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency 'nokogiri', '~> 1.5.0'
22
+ gem.add_dependency 'pygments.rb', '~> 0.4.2'
23
+ gem.add_dependency 'msgpack', '~> 0.4.2'
24
+ gem.add_dependency 'kramdown'
25
+
26
+ gem.add_development_dependency 'rspec'
27
+ gem.add_development_dependency 'simplecov'
28
+ end
@@ -0,0 +1,5 @@
1
+ % Don't edit this file; it is overwritten every time the PDF gets built.
2
+
3
+ % Add some custom commands needed by PolyTeXnic.
4
+ \newcommand{\PolyTeX}{Poly\-\TeX}
5
+ \newcommand{\PolyTeXnic}{Poly\-{\TeX}\-nic}
Binary file
@@ -0,0 +1,14 @@
1
+ We can include code listings, as seen in Listing~\ref{code:foo}.
2
+
3
+ \begin{codelisting}
4
+ \label{code:foo}
5
+ Defining a foo function.
6
+ %= ruby
7
+ \begin{code}
8
+ def foo
9
+ "bar"
10
+ end
11
+ \end{code}
12
+ \end{codelisting}
13
+
14
+ Including the type of source code (in this case, Ruby) should result in syntax highlighting. (The type is put in a comment so that the markup is still valid \LaTeX.)
@@ -0,0 +1,8 @@
1
+ We include here a figure (Figure~\ref{fig:editor_shell}).
2
+
3
+ \begin{figure}
4
+ \begin{center}
5
+ \includegraphics{images/figures/editor_shell.png}
6
+ \end{center}
7
+ \caption{The caption includes a label for use in cross-references.\label{fig:editor_shell}}
8
+ \end{figure}
@@ -0,0 +1,4 @@
1
+
2
+ <p>This is some inline math: <span class="inline_math">\( \int_\Omega d\omega = \int_{\partial\Omega} \omega \)</span> (the general form of Stokes’s Theorem).<span class="intersentencespace"></span> Here’s some more: <span class="inline_math">\( \varphi^2 = \varphi + 1 \)</span>.</p>
3
+ <p>Our main strategy for producing HTML is to pass it through as-is and let MathJax handle the rendering.
4
+ </p>
@@ -0,0 +1,3 @@
1
+ This is some inline math: $\int_\Omega d\omega = \int_{\partial\Omega} \omega$ (the general form of Stokes's Theorem). Here's some more: \( \varphi^2 = \varphi + 1 \).
2
+
3
+ Our main strategy for producing HTML is to pass it through as-is and let MathJax handle the rendering.
@@ -0,0 +1,50 @@
1
+ <p>This is an equation environment:</p>
2
+ <div class="equation">\[
3
+ \int_\Omega d\omega = \int_{\partial\Omega} \omega \qquad\mbox{Stokes's Theorem}
4
+ \]
5
+ </div><p class="noindent">This should be a centered equation with no numbering.</p>
6
+ <p>We also want to support equation environments:</p>
7
+ <div id="uid1" data-tralics-id="uid1" data-number="1" class="equation">\begin{equation}
8
+ \int_\Omega d\omega = \int_{\partial\Omega} \omega \qquad\mbox{Stokes's Theorem}
9
+ \end{equation}
10
+ </div><p class="noindent">We’ll probably have to handle numbering and cross-references in a post-processing step.</p>
11
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
12
+ tempor incididunt ut labore et dolore magna aliqua.<span class="intersentencespace"></span> Ut enim ad minim veniam,
13
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
14
+ consequat.<span class="intersentencespace"></span> Duis aute irure dolor in reprehenderit in voluptate velit esse
15
+ cillum dolore eu fugiat nulla pariatur.<span class="intersentencespace"></span> Excepteur sint occaecat cupidatat non
16
+ proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
17
+ <p>Of course, inline math like <span class="inline_math">\( \Omega &gt; 0 \)</span> and <span class="inline_math">\( x^2 - 2 \equiv 0 \)</span> should also work fine.</p>
18
+ <div id="uid2" data-tralics-id="uid2" data-number="2" class="equation">\begin{align}
19
+ x^2 + y^2 &amp;= 1
20
+ \\ y &amp;= \sqrt{1 - x^2}.
21
+ \end{align}
22
+ </div><p class="noindent">Maxwell’s Equations:</p>
23
+ <div id="uid3" data-tralics-id="uid3" data-number="3" class="equation">\begin{equation}
24
+ \begin{aligned}
25
+ \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} &amp; = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} &amp; = 4 \pi \rho \\
26
+ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} &amp; = \vec{\mathbf{0}} \\
27
+ \nabla \cdot \vec{\mathbf{B}} &amp; = 0
28
+ \end{aligned}
29
+ \end{equation}
30
+ </div><div id="uid4" data-tralics-id="uid4" data-number="4" class="equation">\begin{equation*}
31
+ \left.\begin{aligned}
32
+ dE &amp;= \rho \\
33
+ d*E &amp;= -\dot{B} \\
34
+ dB &amp;= 0 \\
35
+ d*B &amp;= J + \dot{E}
36
+ \end{aligned}
37
+ \right\}
38
+ \qquad \text{Maxwell's equations}
39
+ \end{equation*}
40
+ </div><p class="noindent">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
41
+ tempor incididunt ut labore et dolore magna aliqua.<span class="intersentencespace"></span> Ut enim ad minim veniam,
42
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
43
+ consequat.<span class="intersentencespace"></span> Duis aute irure dolor in reprehenderit in voluptate velit esse
44
+ cillum dolore eu fugiat nulla pariatur.<span class="intersentencespace"></span> Excepteur sint occaecat cupidatat non
45
+ proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<span class="intersentencespace"></span></p>
46
+ <div id="uid5" data-tralics-id="uid5" data-number="5" class="equation">\begin{multline}
47
+ a+b+c+d+e+f\\
48
+ +i+j+k+l+m+n
49
+ \end{multline}
50
+ </div>
@@ -0,0 +1,56 @@
1
+ This is an equation environment:
2
+ \[
3
+ \int_\Omega d\omega = \int_{\partial\Omega} \omega \qquad\mbox{Stokes's Theorem}
4
+ \]
5
+ This should be a centered equation with no numbering.
6
+
7
+ We also want to support equation environments:
8
+ \begin{equation}
9
+ \int_\Omega d\omega = \int_{\partial\Omega} \omega \qquad\mbox{Stokes's Theorem}
10
+ \end{equation}
11
+ We'll probably have to handle numbering and cross-references in a post-processing step.
12
+
13
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
14
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
15
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
16
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
17
+ cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
18
+ proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
19
+
20
+ Of course, inline math like $\Omega > 0$ and \( x^2 - 2 \equiv 0 \) should also work fine.
21
+
22
+ \begin{align}
23
+ x^2 + y^2 &= 1
24
+ \\ y &= \sqrt{1 - x^2}.
25
+ \end{align}
26
+
27
+ Maxwell's Equations:
28
+ \begin{equation}
29
+ \begin{aligned}
30
+ \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
31
+ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
32
+ \nabla \cdot \vec{\mathbf{B}} & = 0
33
+ \end{aligned}
34
+ \end{equation}
35
+
36
+ \begin{equation*}
37
+ \left.\begin{aligned}
38
+ dE &= \rho \\
39
+ d*E &= -\dot{B} \\
40
+ dB &= 0 \\
41
+ d*B &= J + \dot{E}
42
+ \end{aligned}
43
+ \right\}
44
+ \qquad \text{Maxwell's equations}
45
+ \end{equation*}
46
+
47
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
48
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
49
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
50
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
51
+ cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
52
+ proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
53
+ \begin{multline}
54
+ a+b+c+d+e+f\\
55
+ +i+j+k+l+m+n
56
+ \end{multline}
@@ -0,0 +1,9 @@
1
+ \section{Foo bar}
2
+ \label{sec:foobar}
3
+
4
+ This is a section. The next section is Section~\ref{sec:bazquux}
5
+
6
+ \section{Baz quux}
7
+ \label{sec:bazquux}
8
+
9
+ This is another section. It comes immediately after Section~\ref{sec:foobar}.
@@ -0,0 +1,10 @@
1
+ We also support numbered, cross-referenced boxes, as defined by a custom ``sidebar'' environment (since ``box'' is already a built-in \LaTeX command). An example is shown in Box~\ref{sidebar:example_box}.
2
+
3
+ \begin{sidebar}{Example box}{sidebar:example_box}
4
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
5
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
6
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
7
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
8
+ cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
9
+ proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
10
+ \end{sidebar}
@@ -0,0 +1,8 @@
1
+ This is a table:
2
+
3
+ \begin{tabular}{ l c r }
4
+ 1 & 2 & 3 \\
5
+ 4 & 5 & 6 \\
6
+ 7 & 8 & 9 \\
7
+ \end{tabular}
8
+
@@ -0,0 +1,11 @@
1
+
2
+ <p>This is inline verbatim text: <span class="inline_verbatim">\LaTeX and a literal $</span>.<span class="intersentencespace"></span> This is non-inline verbatim text:
3
+ </p><pre class="verbatim"> % \begin{verbatim}
4
+ % This is verbatim text.
5
+ % \end{verbatim}</pre>
6
+ <p>It would also be nice to support the environment from the Verbatim package:
7
+ </p><pre class="verbatim"> % \begin{Verbatim}
8
+ % This is an even more powerful verbatim environment.
9
+ % \end{Verbatim}</pre>
10
+ <p>We’ll see how it goes.
11
+ </p>
@@ -0,0 +1,13 @@
1
+ This is inline verbatim text: \verb+\LaTeX and a literal $+. This is non-inline verbatim text:
2
+ \begin{verbatim}
3
+ % \begin{verbatim}
4
+ % This is verbatim text.
5
+ % \end{verbatim}
6
+ \end{verbatim}
7
+ It would also be nice to support the environment from the Verbatim package:
8
+ \begin{Verbatim}
9
+ % \begin{Verbatim}
10
+ % This is an even more powerful verbatim environment.
11
+ % \end{Verbatim}
12
+ \end{Verbatim}
13
+ We'll see how it goes.
@@ -0,0 +1,34 @@
1
+ # encoding=utf-8
2
+ require 'spec_helper'
3
+
4
+ # Returns a list of fixture filenames.
5
+ def filenames
6
+ %w[inline_math verbatim_environments math_environments]
7
+ end
8
+
9
+ # Returns the results of converting the TeX filename to HTML.
10
+ def converted(filename)
11
+ Polytexnic::Pipeline.new(contents(filename, 'tex')).to_html
12
+ end
13
+
14
+ # Returns the contents of the HTML filename fixture.
15
+ def html(filename)
16
+ contents(filename, 'html')
17
+ end
18
+
19
+ # Returns the contents of a filename using its extension.
20
+ def contents(filename, extension)
21
+ File.open(File.join('spec', 'fixtures', "#{filename}.#{extension}")).read
22
+ end
23
+
24
+ describe Polytexnic::Pipeline do
25
+
26
+ filenames.each do |filename|
27
+ it "should correctly process #{filename}" do
28
+ tmp = 'tmp'
29
+ File.mkdir(tmp) unless File.directory?(tmp)
30
+ File.write(File.join(tmp, filename), converted(filename))
31
+ expect(converted(filename)).to resemble html(filename)
32
+ end
33
+ end
34
+ end