Index: test/test_parser.rb
===================================================================
--- test/test_parser.rb (revision 244)
+++ test/test_parser.rb (working copy)
@@ -7,13 +7,19 @@
def red str
SuperRedCloth.new(str).to_html
end
+
+ def red_latex str
+ SuperRedCloth.new(str).to_latex
+ end
+
Dir[File.join(DIR, "*.yml")].each do |testfile|
testgroup = File.basename(testfile, '.yml')
num = 0
YAML::load_documents(File.open(testfile)) do |doc|
name = doc['name'] ? doc['name'].downcase.gsub(/[- ]/, '_') : num
- define_method("test_#{testgroup}_#{name}") do
- assert_html_equal doc['out'], red(doc['in'])
+ define_method("test_#{testgroup}_#{name}") do
+ assert_html_equal doc['out'], red(doc['in']) if doc['out']
+ assert_equal doc['latex'], red_latex(doc['in']) if doc['latex']
end
num += 1
end
Index: test/textism.yml
===================================================================
--- test/textism.yml (revision 244)
+++ test/textism.yml (working copy)
@@ -2,14 +2,16 @@
name: header one
in: h1. Header 1
out:
Header 1
+latex: \section*{Header 1}
---
name: header two
in: h2. Header 2
out: Header 2
+latex: \subsection*{Header 2}
---
name: header three
in: h3. Header 3
-out: Header 3
+latex: \subsubsection*{Header 3}
---
name: blockquote
in: |-
@@ -28,6 +30,16 @@
Any old text.
+latex: |+
+ Any old text.
+
+ \begin{quotation}
+ A block quotation.
+
+ \end{quotation}
+
+ Any old text.
+
---
in: |-
# A first item
@@ -41,7 +53,14 @@
A third item
A fourth item
-
+latex: |+
+ \begin{enumerate}
+ \item A first item
+ \item A second item
+ \item A third item
+ \item A fourth item
+ \end{enumerate}
+
---
in: |-
* A first item
@@ -56,22 +75,34 @@
A third item
A fourth item
-
+latex: |+
+ \begin{itemize}
+ \item A first item
+ \item A second item
+ \item A third item
+ \item A fourth item
+ \end{itemize}
+
---
in: _a phrase_
out: a phrase
+latex: "\\emph{a phrase}\n\n"
---
in: __a phrase__
out: a phrase
+latex: "\\emph{a phrase}\n\n"
---
in: '*a phrase*'
out: a phrase
+latex: "\\textbf{a phrase}\n\n"
---
in: '**a phrase**'
out: a phrase
+latex: "\\textbf{a phrase}\n\n"
---
in: Nabokov's ??Pnin??
out: Nabokov’s Pnin
+latex: "Nabokov's \\begin{quote}Pnin\\end{quote}\n\n"
---
name: del part of word
in: 'A very [-extra-]ordinary day.'
Index: ext/superredcloth_scan/superredcloth_scan.rl
===================================================================
--- ext/superredcloth_scan/superredcloth_scan.rl (revision 244)
+++ ext/superredcloth_scan/superredcloth_scan.rl (working copy)
@@ -11,7 +11,7 @@
#include
#include "superredcloth.h"
-VALUE super_ParseError, super_RedCloth, super_HTML;
+VALUE super_ParseError, super_RedCloth, super_HTML, super_LATEX;
%%{
@@ -203,7 +203,18 @@
return superredcloth_transform2(super_HTML, self);
}
+
static VALUE
+superredcloth_to_latex(self)
+ VALUE self;
+{
+ char *pe, *p;
+ int len = 0;
+
+ return superredcloth_transform2(super_LATEX, self);
+}
+
+static VALUE
superredcloth_to(self, formatter)
VALUE self, formatter;
{
@@ -217,7 +228,9 @@
{
super_RedCloth = rb_define_class("SuperRedCloth", rb_cString);
rb_define_method(super_RedCloth, "to_html", superredcloth_to_html, 0);
+ rb_define_method(super_RedCloth, "to_latex", superredcloth_to_latex, 0);
rb_define_method(super_RedCloth, "to", superredcloth_to, 1);
super_ParseError = rb_define_class_under(super_RedCloth, "ParseError", rb_eException);
- super_HTML = rb_define_module_under(super_RedCloth, "HTML");
+ super_HTML = rb_define_module_under(super_RedCloth, "HTML");
+ super_LATEX = rb_define_module_under(super_RedCloth, "LATEX");
}
Index: lib/superredcloth.rb
===================================================================
--- lib/superredcloth.rb (revision 244)
+++ lib/superredcloth.rb (working copy)
@@ -192,3 +192,217 @@
txt.gsub(/&/, '&')
end
end
+
+
+class << SuperRedCloth::LATEX
+ def pba(opts)
+ atts = ''
+ opts[:"text-align"] = opts.delete(:align)
+ opts[:style] += ';' if opts[:style] && (opts[:style][-1..-1] != ';')
+ [:float, :"text-align", :"vertical-align"].each do |a|
+ opts[:style] = "#{a}:#{opts[a]};#{opts[:style]}" if opts[a]
+ end
+ [:"padding-right", :"padding-left"].each do |a|
+ opts[:style] = "#{a}:#{opts[a]}em;#{opts[:style]}" if opts[a]
+ end
+ [:style, :class, :lang, :id, :colspan, :rowspan, :title, :start, :align].each do |a|
+ atts << " #{a}=\"#{ opts[a] }\"" if opts[a]
+ end
+ atts
+ end
+
+ # commands
+ { :h1 => 'section*',
+ :h2 => 'subsection*',
+ :h3 => 'subsubsection*',
+ :h4 => 'textbf',
+ :h5 => 'textbf',
+ :h6 => 'textbf',
+ :strong => 'textbf',
+ :em => 'emph',
+ :i => 'emph',
+ :b => 'textbf',
+ :ins => 'underline',
+ :del => 'sout',
+ :acronym => 'MakeUppercase',
+ :caps => 'MakeUppercase',
+ }.each do |m,tag|
+ define_method(m) do |opts|
+ "\\#{tag}{#{opts[:text]}}"
+ end
+ end
+
+ { :sup => '\ensuremath{^\textrm{#1}}',
+ :sub => '\ensuremath{_\textrm{#1}}',
+ }.each do |m, expr|
+ define_method(m) do |opts|
+ expr.sub('#1', opts[:text])
+ end
+ end
+
+ # environments
+ { :pre => 'verbatim',
+ :code => 'verbatim',
+ :cite => 'quote',
+ }.each do |m, env|
+ define_method(m) do |opts|
+ "\\begin{#{env}}#{opts[:text]}\\end{#{env}}"
+ end
+ end
+
+ # ignore (or find a good solution later)
+ [ :span,
+ :div,
+ ].each do |m|
+ define_method(m) do |opts|
+ opts[:text].to_s
+ end
+ end
+
+ def del_phrase(opts)
+ " #{del(opts)}"
+ end
+
+ { :ol => 'enumerate',
+ :ul => 'itemize',
+ }.each do |m, env|
+ define_method("#{m}_open") do |opts|
+ opts[:block] = true
+ "\\begin{#{env}}\n"
+ end
+ define_method("#{m}_close") do |opts|
+ "#{li_close}\\end{#{env}}\n\n"
+ end
+ end
+
+ def li_open(opts)
+ "#{li_close unless opts.delete(:first)}\t\\item #{opts[:text]}"
+ end
+
+ def li_close(opts=nil)
+ "\n"
+ end
+
+ def ignore(opts)
+ opts[:text]
+ end
+ alias_method :notextile, :ignore
+
+ def para(txt)
+ txt
+ end
+
+ def p(opts)
+ opts[:text] + "\n\n"
+ end
+
+ def td(opts)
+ "\t\t\t#{opts[:text]} &\n"
+ end
+
+ def tr_open(opts)
+ "\t\t"
+ end
+
+ def tr_close(opts)
+ "\t\t\\\\\n"
+ end
+
+ # FIXME: we need to know the column count before opening tabular context.
+ def table_open(opts)
+ "\\begin{align*}\n"
+ end
+
+ def table_close(opts)
+ "\t\\end{align*}\n"
+ end
+
+ def bc_open(opts)
+ opts[:block] = true
+ "\\begin{verbatim}\n"
+ end
+
+ def bc_close(opts)
+ "\\end{verbatim}\n"
+ end
+
+ def bq_open(opts)
+ opts[:block] = true
+ "\\begin{quotation}\n"
+ end
+
+ def bq_close(opts)
+ "\\end{quotation}\n\n"
+ end
+
+ def link(opts)
+ "\\href{#{opts[:href]}}{#{opts[:name]}}"
+ end
+
+ # FIXME: use includegraphics with security verification
+ def image(opts)
+ ""
+ end
+
+ def footno(opts)
+ # TODO: insert a placeholder until we know the footnote content.
+ # For this to work, we need some kind of post-processing...
+ "\\footnotemark[#{opts[:text]}]"
+ end
+
+ def fn(opts)
+ "\\footnotetext[#{opts[:id]}]{#{opts[:text]}}"
+ end
+
+ def snip(opts)
+ "\\begin{verbatim}#{opts[:text]}\\end{verbatim}"
+ end
+
+ def quote1(opts)
+ "`#{opts[:text]}'"
+ end
+
+ def quote2(opts)
+ "``#{opts[:text]}\""
+ end
+
+ def ellipsis(opts)
+ "#{opts[:text]}\\ldots"
+ end
+
+ # TODO: these should use Latex equivalents
+ def emdash(opts)
+ "--"
+ end
+
+ def endash(opts)
+ " - "
+ end
+
+ def arrow(opts)
+ "\\rightarrow"
+ end
+
+ def trademark(opts)
+ "\\texttrademark"
+ end
+
+ def registered(opts)
+ "\\textregistered"
+ end
+
+ def copyright(opts)
+ "\\copyright"
+ end
+
+ # TODO: what do we do with unicode entities ?
+ def entity(opts)
+ "{opts[:text]}"
+ end
+
+ # ?
+ def dim(opts)
+ space = opts[:space] ? " " : ''
+ "#{opts[:x]}#{space}×#{space}"
+ end
+end