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\n

that } + - %{Smart Engine GUI?

}, - "My Headline\n===========\n\nthat SmartEngineGUI") + re = Regexp.new('

My Headline

\n\n

that Smart Engine GUI\?

') + + assert_match_markup_parsed_as(re, "My Headline\n===========\n\nthat SmartEngineGUI") - assert_markup_parsed_as( - %{

My Headline

\n\n

that } + - %{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\t

Textile 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