From 34082fbf946db5cbc175ed4785753fba7f082b8d Mon Sep 17 00:00:00 2001
From: Jacques Distler
Date: Fri, 17 Oct 2008 16:26:17 -0500
Subject: [PATCH] Theorem Environments
Implement amsthm-like Theorem environments with Maruku.
Support is based on Maruku "div"s with special class-names.
Classes
num_*
produce numbered environments, and
un_*
produce un-numbered environments, where * is one of
theorem (for Theorem)
lemma (for Lemma)
prop (for Proposition)
cor (for Corollary)
def (for Definition)
example (for Example)
remark (for Remark)
note (for Note)
In addition, the class
proof
produces a Proof environment.
The LaTeX export works as expected, and these also work in the S5 view.
Bumped version number.
---
app/controllers/application.rb | 2 +-
app/views/layouts/default.rhtml | 2 +-
app/views/wiki/s5.rhtml | 1 +
app/views/wiki/tex.rhtml | 22 +++++++++++++++
public/javascripts/page_helper.js | 24 +++++++++++++++++
public/s5/ui/core/math.css | 18 +++++++++++++
public/s5/ui/core/slides.js | 24 +++++++++++++++++
public/stylesheets/instiki.css | 20 ++++++++++++++
test/functional/wiki_controller_test.rb | 22 +++++++++++++++
test/unit/page_renderer_test.rb | 25 ++++++++---------
.../maruku/lib/maruku/output/to_latex.rb | 27 +++++++++++++++++++
.../plugins/maruku/lib/maruku/output/to_s.rb | 4 +--
12 files changed, 175 insertions(+), 16 deletions(-)
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index b141ebb8..866082bb 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -232,7 +232,7 @@ end
module Instiki
module VERSION #:nodoc:
MAJOR = 0
- MINOR = 14
+ MINOR = 15
TINY = 0
SUFFIX = '(MML+)'
PRERELEASE = 'pre' # false
diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml
index a8e511cd..a0ef4319 100644
--- a/app/views/layouts/default.rhtml
+++ b/app/views/layouts/default.rhtml
@@ -66,7 +66,7 @@
<% if @show_footer %>
<% end %>
diff --git a/app/views/wiki/s5.rhtml b/app/views/wiki/s5.rhtml
index a0ad6397..293da207 100644
--- a/app/views/wiki/s5.rhtml
+++ b/app/views/wiki/s5.rhtml
@@ -21,6 +21,7 @@
+
diff --git a/app/views/wiki/tex.rhtml b/app/views/wiki/tex.rhtml
index 2901fadd..3831be9e 100644
--- a/app/views/wiki/tex.rhtml
+++ b/app/views/wiki/tex.rhtml
@@ -3,6 +3,7 @@
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
+\usepackage{amsthm}
\usepackage{graphicx}
\usepackage{color}
\usepackage{ucs}
@@ -200,6 +201,27 @@
\newcommand{\statusline}[2]{#2}
\newcommand{\toggle}[2]{#1}
+% Theorem Environments
+\theoremstyle{plain}
+\newtheorem{theorem}{Theorem}
+\newtheorem{lemma}{Lemma}
+\newtheorem{prop}{Proposition}
+\newtheorem{cor}{Corollary}
+\newtheorem*{utheorem}{Theorem}
+\newtheorem*{ulemma}{Lemma}
+\newtheorem*{uprop}{Proposition}
+\newtheorem*{ucor}{Corollary}
+\theoremstyle{definition}
+\newtheorem{def}{Definition}
+\newtheorem{example}{Example}
+\newtheorem*{udef}{Definition}
+\newtheorem*{uexample}{Example}
+\theoremstyle{remark}
+\newtheorem{remark}{Remark}
+\newtheorem{note}{Note}
+\newtheorem*{uremark}{Remark}
+\newtheorem*{unote}{Note}
+
%-------------------------------------------------------------------
\begin{document}
diff --git a/public/javascripts/page_helper.js b/public/javascripts/page_helper.js
index 4f4be743..586750bc 100644
--- a/public/javascripts/page_helper.js
+++ b/public/javascripts/page_helper.js
@@ -18,6 +18,30 @@ function extractBlockquoteCitations() {
}
}
}
+
+function fixRunIn() {
+// work around lack of gecko support for display:run-in
+ var re = /^num_|\s+num_|^un_|\s+un_|proof/;
+ $$('div > h6').each(function(element) {
+ if(re.test($(element.parentNode).className)) {
+ var new_span = new Element('span').update(element.textContent);
+ new_span.addClassName('theorem_label');
+ var next_el = element.next().firstChild;
+ next_el.parentNode.insertBefore(new_span, next_el);
+ var period = new Element('span').update('. ');
+ next_el.parentNode.insertBefore(period, next_el);
+ element.remove();
+ }
+ });
+// add tombstone to proof, since gecko doesn't support :last-child properly
+ $$('div.proof').each(function(element) {
+ var l = element.childElements().length -1;
+ var span = new Element('span').update('\u00a0\u00a0\u25ae');
+ element.childElements()[l].insert(span);
+ });
+}
+
window.onload = function (){
extractBlockquoteCitations();
+ fixRunIn();
};
diff --git a/public/s5/ui/core/math.css b/public/s5/ui/core/math.css
index b03bcbb1..9f84ccee 100644
--- a/public/s5/ui/core/math.css
+++ b/public/s5/ui/core/math.css
@@ -17,3 +17,21 @@ table.plaintable {
margin-left:30px;
}
.noborder td, .noborder th {border:0}
+body {counter-reset: theorem lemma proposition corollary example remark}
+.un_theorem *, .num_theorem *,
+.un_lemma *, .num_lemma *,
+.un_prop *, .num_prop *,
+.un_cor *, .num_cor * {font-style: italic}
+span.theorem_label {font-style:normal; font-weight:bold;}
+.num_theorem .theorem_label:after {
+ content: " " counter(theorem); counter-increment: theorem;}
+.num_lemma .theorem_label:after {
+ content: " " counter(lemma); counter-increment: lemma;}
+.num_prop .theorem_label:after {
+ content: " " counter(proposition); counter-increment: proposition;}
+.num_cor .theorem_label:after {
+ content: " " counter(corollary); counter-increment: corollary;}
+.num_example .theorem_label:after {
+ content: " " counter(example); counter-increment: example;}
+.num_remark .theorem_label:after {
+ content: " " counter(remark); counter-increment: remark;}
diff --git a/public/s5/ui/core/slides.js b/public/s5/ui/core/slides.js
index 4c7faf0c..d2d5d013 100644
--- a/public/s5/ui/core/slides.js
+++ b/public/s5/ui/core/slides.js
@@ -809,6 +809,29 @@ function windowChange() {
fontScale();
}
+function fixRunIn() {
+// work around lack of gecko support for display:run-in
+ var re = /^num_|\s+num_|^un_|\s+un_|proof/;
+ $$('div > h6').each(function(element) {
+ if(re.test($(element.parentNode).className)) {
+ var new_span = new Element('span').update(element.textContent);
+ new_span.addClassName('theorem_label');
+ var next_el = element.next().firstChild;
+ next_el.parentNode.insertBefore(new_span, next_el);
+ var period = new Element('span').update('. ');
+ next_el.parentNode.insertBefore(period, next_el);
+ element.remove();
+ }
+ });
+// add tombstone to proof, since gecko doesn't support :last-child properly
+
+ $$('div.proof').each(function(element) {
+ var l = element.childElements().length -1;
+ var span = new Element('span').update('\u00a0\u00a0\u25ae');
+ element.childElements()[l].insert(span);
+ })
+}
+
function startup() {
defaultCheck();
createControls(); // hallvord
@@ -819,6 +842,7 @@ function startup() {
fixLinks();
externalLinks();
fontScale();
+ fixRunIn();
if (!isOp) notOperaFix();
slideJump();
if (defaultView == 'outline') {
diff --git a/public/stylesheets/instiki.css b/public/stylesheets/instiki.css
index 6cecf4a9..5597bb63 100644
--- a/public/stylesheets/instiki.css
+++ b/public/stylesheets/instiki.css
@@ -392,3 +392,23 @@ span.keyboard {
margin:auto;
text-align:center;
}
+
+body {counter-reset: theorem lemma proposition corollary example remark}
+.un_theorem *, .num_theorem *,
+.un_lemma *, .num_lemma *,
+.un_prop *, .num_prop *,
+.un_cor *, .num_cor * {font-style: italic}
+span.theorem_label {font-style:normal; font-weight:bold;}
+.num_theorem .theorem_label:after {
+ content: " " counter(theorem); counter-increment: theorem;}
+.num_lemma .theorem_label:after {
+ content: " " counter(lemma); counter-increment: lemma;}
+.num_prop .theorem_label:after {
+ content: " " counter(proposition); counter-increment: proposition;}
+.num_cor .theorem_label:after {
+ content: " " counter(corollary); counter-increment: corollary;}
+.num_example .theorem_label:after {
+ content: " " counter(example); counter-increment: example;}
+.num_remark .theorem_label:after {
+ content: " " counter(remark); counter-increment: remark;}
+
diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb
index 6562b177..13ec3440 100755
--- a/test/functional/wiki_controller_test.rb
+++ b/test/functional/wiki_controller_test.rb
@@ -726,6 +726,7 @@ class WikiControllerTest < Test::Unit::TestCase
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
+\usepackage{amsthm}
\usepackage{graphicx}
\usepackage{color}
\usepackage{ucs}
@@ -923,6 +924,27 @@ class WikiControllerTest < Test::Unit::TestCase
\newcommand{\statusline}[2]{#2}
\newcommand{\toggle}[2]{#1}
+% Theorem Environments
+\theoremstyle{plain}
+\newtheorem{theorem}{Theorem}
+\newtheorem{lemma}{Lemma}
+\newtheorem{prop}{Proposition}
+\newtheorem{cor}{Corollary}
+\newtheorem*{utheorem}{Theorem}
+\newtheorem*{ulemma}{Lemma}
+\newtheorem*{uprop}{Proposition}
+\newtheorem*{ucor}{Corollary}
+\theoremstyle{definition}
+\newtheorem{def}{Definition}
+\newtheorem{example}{Example}
+\newtheorem*{udef}{Definition}
+\newtheorem*{uexample}{Example}
+\theoremstyle{remark}
+\newtheorem{remark}{Remark}
+\newtheorem{note}{Note}
+\newtheorem*{uremark}{Remark}
+\newtheorem*{unote}{Note}
+
%-------------------------------------------------------------------
\begin{document}
diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb
index 35ac3f2c..07ce0440 100644
--- a/test/unit/page_renderer_test.rb
+++ b/test/unit/page_renderer_test.rb
@@ -65,15 +65,11 @@ class PageRendererTest < Test::Unit::TestCase
%{sin(x)
},
"equation $\\sin(x)$")
- assert_markup_parsed_as(
- %{My Headline
\n\nthat } +
- %{Smart Engine GUI?
},
- "My Headline\n===========\n\nthat SmartEngineGUI")
+ re = Regexp.new('My Headline
\n\nthat Smart Engine GUI\?
')
+
+ assert_match_markup_parsed_as(re, "My Headline\n===========\n\nthat SmartEngineGUI")
- assert_markup_parsed_as(
- %{My Headline
\n\nthat } +
- %{Smart Engine GUI?
},
- "#My Headline#\n\nthat SmartEngineGUI")
+ assert_match_markup_parsed_as(re, "#My Headline#\n\nthat SmartEngineGUI")
assert_markup_parsed_as(
%{SVG } +
@@ -159,13 +155,13 @@ class PageRendererTest < Test::Unit::TestCase
].join("\n")
set_web_property :markup, :markdown
- assert_markup_parsed_as(
- "Markdown heading
\n\n" +
+ re = Regexp.new(
+ 'Markdown heading
\n\n' +
"h2. Textile heading
\n\n" +
"some text with -styles-
\n\n" +
- "",
- textile_and_markdown)
+ "")
+ assert_match_markup_parsed_as(re, textile_and_markdown)
set_web_property :markup, :textile
assert_markup_parsed_as(
"Markdown heading
================
\n\n\n\tTextile heading
" +
@@ -526,6 +522,11 @@ class PageRendererTest < Test::Unit::TestCase
assert_equal expected_output, test_renderer(revision).display_content, 'Rendering output not as expected'
end
+ def assert_match_markup_parsed_as(expected_output, input)
+ revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
+ assert_match expected_output, test_renderer(revision).display_content, 'Rendering output not as expected'
+ end
+
def rendered_content(page)
test_renderer(page.revisions.last).display_content
end
diff --git a/vendor/plugins/maruku/lib/maruku/output/to_latex.rb b/vendor/plugins/maruku/lib/maruku/output/to_latex.rb
index d2b9e741..8379b883 100644
--- a/vendor/plugins/maruku/lib/maruku/output/to_latex.rb
+++ b/vendor/plugins/maruku/lib/maruku/output/to_latex.rb
@@ -518,6 +518,33 @@ Otherwise, a standard `verbatim` environment is used.
end
+ def to_latex_div
+ type = self.attributes[:class]
+ id = self.attributes[:id]
+ case type
+ when /^un_(\w*)/
+ s = "\\begin{u#{$1}}"
+# s += "[#{@children[0].send('children_to_latex')}]"
+ @children.delete_at(0)
+ s += "\n" + children_to_latex
+ s += "\\end{u#{$1}}\n"
+ when /^num_(\w*)/
+ s = "\\begin{#{$1}}"
+# s += "[#{@children[0].send('children_to_latex')}]"
+ @children.delete_at(0)
+ s += "\n\\label{#{id}}\\hypertarget{#{id}}{}\n"
+ s += children_to_latex
+ s += "\\end{#{$1}}\n"
+ when /^proof/
+ s = "\\begin{proof}"
+ @children.delete_at(0)
+ s += "\n" + children_to_latex
+ s += "\\end{proof}\n"
+ else
+ s = children_to_latex
+ end
+ s
+ end
# Convert each child to html
def children_to_latex
diff --git a/vendor/plugins/maruku/lib/maruku/output/to_s.rb b/vendor/plugins/maruku/lib/maruku/output/to_s.rb
index 577660e0..dc326cce 100644
--- a/vendor/plugins/maruku/lib/maruku/output/to_s.rb
+++ b/vendor/plugins/maruku/lib/maruku/output/to_s.rb
@@ -46,8 +46,8 @@ class MDElement
title = "id#{$uid}"
end
- title
+ title << "_" + rand(10000).to_s
end
end
-end
\ No newline at end of file
+end