# encoding=utf-8 require 'spec_helper' describe Polytexnic::Pipeline do before(:all) do FileUtils.rm('.highlight_cache') if File.exist?('.highlight_cache') end describe '#to_polytex' do subject(:processed_text) do Polytexnic::Pipeline.new(source, source: :markdown).polytex end context "for vanilla Markdown" do let(:source) { '*foo* **bar**' } it { should include '\emph{foo} \textbf{bar}' } it { should_not include '\begin{document}' } end context "for multiline Markdown" do let(:source) do <<-EOS # A chapter Hello, *world*! ## A section Lorem ipsum EOS end it { should include '\chapter{A chapter}' } it { should include '\section{A section}' } it { should_not include '\hypertarget' } end describe "hyphenation" do let(:source) { 'profes\-sional' } it { should include source } end describe "with math" do context "inline math" do let(:source) do <<-'EOS' This is inline math: {$$} x^2 {/$$}. EOS end it { should include '\( x^2 \)' } end context "block math" do let(:source) do <<-'EOS' This is block math: {$$} x^2 {/$$}. EOS end it { should resemble '\[ x^2 \]' } end end context "asides with internal lists" do let(:source) do <<-'EOS' \begin{aside} \label{aside:softcover_uses} \heading{How to use Softcover} * Producing ebooks with `softcover` and giving them away * Producing ebooks with `softcover` and selling them from your own website \end{aside} EOS end it { should include '\begin{aside}' } it { should_not include "\\end{aside}\n\\end{itemize}" } end describe "tables" do let(:source) do <<-'EOS' \begin{table} |**option**|**size**|**actual size**| | k | kilobytes | (1024 bytes) | | M | megabytes | (1024 kilobytes) | | G | gigabytes | (1024 megabytes) | | T | terabytes | (1024 gigabytes) | | P | petabytes | (1024 terabytes) | \end{table} \begin{table} |**option**|**size**|**actual size**| | k | kilobytes | (1024 bytes) | | M | megabytes | (1024 kilobytes) | | G | gigabytes | (1024 megabytes) | | T | terabytes | (1024 gigabytes) | | P | petabytes | (1024 terabytes) | \caption{A caption.} \end{table} EOS end it { should include '\begin{table}' } it { should include '\begin{longtable}' } it { should_not include '\textbar' } end describe "footnotes" do subject do Polytexnic::Pipeline.new(markdown, source: :markdown).polytex end context "first chapter with footnotes" do let(:markdown) do <<-'EOS' To add a footnote, you insert a footnote tag like this.[^foo] Then you add the footnote content later in the text, using the same tag, with a colon and a space:[^foo2] [^foo]: This is the footnote content. That is it. You can keep writing your text after the footnote content. [^foo2]: This is the footnote text. We are now going to add a second line after typing in four spaces. EOS end it { should include '\footnote{This is the footnote content.}' } it { should include 'after typing in four spaces.}' } end end describe "images" do subject do Polytexnic::Pipeline.new(markdown, source: :markdown).polytex end context "with a caption and a label" do let(:markdown) do <<-'EOS' ![Running the Softcover server in a separate tab.\label{fig:softcover_server}](images/figures/softcover_server.png) EOS end it { should include '\caption{Running the Softcover server in a separate tab.\label{fig:softcover_server}}' } it { should include '\image' } it { should_not include '\includegraphics' } end context "using an example that failed" do let(:markdown) do <<-'EOS' a screenshot from [Lowdown](http://lowdownapp.com/), a web application that developers use for organizing user stories. ![Lowdown for user stories](https://tutorials.railsapps.org/assets/learn-rails-lowdown-partial.png) Just like Rails provides a structure for building a web application, user stories provide a structure for organizing your product plan. EOS end it { should include '\caption{Lowdown for user stories}' } it { should include '\image{https://tutorials.railsapps.org' } end end context "with LaTeX containing" do context "a normal command" do let(:source) { 'This is a command: \foobar' } it { should include source } end context "backslash space" do let(:source) { 'Dr.\ No' } it { should include source } end context "escaped special characters" do let(:source) { '\% \& \$ \# \@ \_' } it { should include source } end context "an accented character" do let(:source) { "\\`{e}" } it { should include source } end context "a label and cross-reference" do let(:source) do <<-'EOS' # Chapter One \label{cha:one} Chapter~\ref{cha:one} EOS end it { should include '\label{cha:one}' } it { should include 'Chapter~\ref{cha:one}' } end context "an inline equation" do let(:source) { '\( x \) is a variable' } it { should include source } end context "a centered equation" do let(:source) { '\[ x^2 - 2 = 0 \] is an equation' } it { should resemble source } end context "an equation environment" do let(:source) do <<-'EOS' foo \begin{equation} \label{eq:maxwell} \left.\begin{aligned} \nabla\cdot\mathbf{E} & = \rho \\ \nabla\cdot\mathbf{B} & = 0 \\ \nabla\times\mathbf{E} & = -\dot{\mathbf{B}} \\ \nabla\times\mathbf{B} & = \mathbf{J} + \dot{\mathbf{E}} \end{aligned} \right\} \quad\text{Maxwell equations} \end{equation} bar EOS end it { should resemble source } end context "a codelisting environment, including a nested command" do let(:source) do <<-'EOS' \begin{codelisting} \codecaption{Lorem \emph{ipsum}.} \label{code:lorem} ```ruby def foo; "bar"; end ``` \end{codelisting} EOS end it { should resemble '\begin{codelisting}' } it { should resemble '\codecaption{Lorem \emph{ipsum}.}' } it { should resemble '\label{code:lorem}' } it { should resemble '\end{codelisting}' } end context "a commented-out codelisting" do let(:source) do <<-'EOS' %= foo:bar EOS end it { should include '%= foo:bar' } it { should_not resemble '\begin{codelisting}' } end context "code inclusion inside codelisting" do let(:source) do <<-'EOS' \begin{codelisting} \codecaption{Lorem ipsum.} \label{code:lorem} <<(/path/to/code) \end{codelisting} EOS end it { should resemble '%= <<(/path/to/code)' } end context "codelisting followed by a section" do let(:source) do <<-'EOS' \begin{codelisting} \codecaption{Lorem ipsum.} \label{code:lorem} <<(/path/to/code) \end{codelisting} # Foo EOS end it { should resemble '\chapter{Foo}' } end end describe "source code" do context "inline" do let(:source) { '`foo bar`' } it { should include '\kode{foo bar}' } end context "without highlighting" do let(:source) do <<-EOS def foo "bar" end EOS end let(:output) do <<-'EOS' \begin{verbatim} def foo "bar" end \end{verbatim} EOS end it { should eq output } end context "with highlighting" do let(:source) do <<-EOS {lang="ruby"} def foo "bar" end lorem EOS end let(:output) do <<-'EOS' %= lang:ruby \begin{code} def foo "bar" end \end{code} lorem EOS end it { should resemble output } end describe "code inclusion" do let(:source) { '<<(/path/to/code)' } it { should resemble '%= <<(/path/to/code)' } context "with an alternate lang and options" do let(:source) { '<<(/path/to/code.md, lang: text, options: "hl_lines": [1, 2], "linenos": true)' } it { should resemble '%= <<(/path/to/code.md, lang: text, options: "hl_lines": [1, 2], "linenos": true)' } end end describe "GitHub-flavored code fencing" do context "without highlighting" do let(:source) do <<-EOS ``` def foo "bar" end ``` lorem EOS end let(:output) do <<-'EOS' \begin{verbatim} def foo "bar" end \end{verbatim} lorem EOS end it { should resemble output } end context "with highlighting and options" do let(:source) do <<-EOS ```ruby, options: "hl_lines": [1, 2], "linenos": true def foo "bar" end ``` lorem EOS end let(:output) do <<-'EOS' %= lang:ruby, options: "hl_lines": [1, 2], "linenos": true \begin{code} def foo "bar" end \end{code} lorem EOS end it { should resemble output } end context "with a code listing from Urbit that broke" do let(:source) do <<-'EOS' ```text 'Foo \'bar' 0x27 ``` foo EOS end it { should_not include "\\begin{code}\n'Foo \n"} end end end end end