Merge branch 'bzr/golem' of /Users/distler/Sites/code/instiki
This commit is contained in:
commit
c4e2afa01a
36 changed files with 1871 additions and 3100 deletions
|
@ -955,7 +955,7 @@ class WikiControllerTest < ActionController::TestCase
|
|||
end
|
||||
|
||||
def test_recursive_include
|
||||
@wiki.write_page('wiki1', 'HomePage', 'Self-include: [[!include HomePage]]', Time.now,
|
||||
@wiki.write_page('wiki1', 'HomePage', "Self-include:\n\n [[!include HomePage]] ", Time.now,
|
||||
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
|
||||
|
||||
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
|
||||
|
|
261
vendor/plugins/maruku/data/entities.xml
vendored
Normal file
261
vendor/plugins/maruku/data/entities.xml
vendored
Normal file
|
@ -0,0 +1,261 @@
|
|||
<!-- A conversion chart for html elements, courtesy of text2html -->
|
||||
<chars>
|
||||
<char num='913' name='Alpha' convertTo='$A$' />
|
||||
<char num='914' name='Beta' convertTo='$B$' />
|
||||
<char num='915' name='Gamma' convertTo='$\Gamma$' />
|
||||
<char num='916' name='Delta' convertTo='$\Delta$' />
|
||||
<char num='917' name='Epsilon' convertTo='$E$' />
|
||||
<char num='918' name='Zeta' convertTo='$Z$' />
|
||||
<char num='919' name='Eta' convertTo='$H$' />
|
||||
<char num='920' name='Theta' convertTo='$\Theta$' />
|
||||
<char num='921' name='Iota' convertTo='$I$' />
|
||||
<char num='922' name='Kappa' convertTo='$K$' />
|
||||
<char num='923' name='Lambda' convertTo='$\Lambda$' />
|
||||
<char num='924' name='Mu' convertTo='$M$' />
|
||||
<char num='925' name='Nu' convertTo='$N$' />
|
||||
<char num='926' name='Xi' convertTo='$\Xi$' />
|
||||
<char num='927' name='Omicron' convertTo='$O$' />
|
||||
<char num='928' name='Pi' convertTo='$\Pi$' />
|
||||
<char num='929' name='Rho' convertTo='$P$' />
|
||||
<char num='931' name='Sigma' convertTo='$\Sigma$' />
|
||||
<char num='932' name='Tau' convertTo='$T$' />
|
||||
<char num='933' name='Upsilon' convertTo='$Y$' />
|
||||
<char num='934' name='Phi' convertTo='$\Phi$' />
|
||||
<char num='935' name='Chi' convertTo='$X$' />
|
||||
<char num='936' name='Psi' convertTo='$\Psi$' />
|
||||
<char num='937' name='Omega' convertTo='$\Omega$' />
|
||||
<char num='945' name='alpha' convertTo='$\alpha$' />
|
||||
<char num='946' name='beta' convertTo='$\beta$' />
|
||||
<char num='947' name='gamma' convertTo='$\gamma$' />
|
||||
<char num='948' name='delta' convertTo='$\delta$' />
|
||||
<char num='949' name='epsilon' convertTo='$\epsilon$' />
|
||||
<char num='950' name='zeta' convertTo='$\zeta$' />
|
||||
<char num='951' name='eta' convertTo='$\eta$' />
|
||||
<char num='952' name='theta' convertTo='$\theta$' />
|
||||
<char num='953' name='iota' convertTo='$\iota$' />
|
||||
<char num='954' name='kappa' convertTo='$\kappa$' />
|
||||
<char num='955' name='lambda' convertTo='$\lambda$' />
|
||||
<char num='956' name='mu' convertTo='$\mu$' />
|
||||
|
||||
<char num='957' name='nu' convertTo='$\nu$' />
|
||||
<char num='958' name='xi' convertTo='$\xi$' />
|
||||
<char num='959' name='omicron' convertTo='$o$' />
|
||||
<char num='960' name='pi' convertTo='$\pi$' />
|
||||
<char num='961' name='rho' convertTo='$\rho$' />
|
||||
<char num='963' name='sigma' convertTo='$\sigma$' />
|
||||
<char num='964' name='tau' convertTo='$\tau$' />
|
||||
<char num='965' name='upsilon' convertTo='$\upsilon$' />
|
||||
<char num='966' name='phi' convertTo='$\phi$' />
|
||||
|
||||
<char num='967' name='chi' convertTo='$\chi$' />
|
||||
<char num='968' name='psi' convertTo='$\psi$' />
|
||||
<char num='969' name='omega' convertTo='$\omega$' />
|
||||
<char num='962' name='sigmaf' convertTo='$\varsigma$' />
|
||||
<char num='977' name='thetasym' convertTo='$\vartheta$' />
|
||||
<char num='982' name='piv' convertTo='$\varpi$' />
|
||||
<char num='8230' name='hellip' convertTo='\ldots' />
|
||||
<char num='8242' name='prime' convertTo='$\prime$' />
|
||||
<char num='8254' name='oline' convertTo='-' />
|
||||
|
||||
<char num='8260' name='frasl' convertTo='/' />
|
||||
<char num='8472' name='weierp' convertTo='$\wp$' />
|
||||
<char num='8465' name='image' convertTo='$\Im$' />
|
||||
<char num='8476' name='real' convertTo='$\Re$' />
|
||||
<char num='8501' name='alefsym' convertTo='$\aleph$' />
|
||||
<char num='8226' name='bull' convertTo='$\bullet$' />
|
||||
<char num='8482' name='trade' convertTo='$^{\rm TM}$' /> <!-- exttrademark -->
|
||||
<char num='8592' name='larr' convertTo='$\leftarrow$' />
|
||||
|
||||
<char num='8594' name='rarr' convertTo='$\rightarrow$' />
|
||||
<char num='8593' name='uarr' convertTo='$\uparrow$' />
|
||||
<char num='8595' name='darr' convertTo='$\downarrow$' />
|
||||
<char num='8596' name='harr' convertTo='$\leftrightarrow$' />
|
||||
<char num='8629' name='crarr' convertTo='$\hookleftarrow$' />
|
||||
<char num='8657' name='uArr' convertTo='$\Uparrow$' />
|
||||
<char num='8659' name='dArr' convertTo='$\Downarrow$' />
|
||||
<char num='8656' name='lArr' convertTo='$\Leftarrow$' />
|
||||
<char num='8658' name='rArr' convertTo='$\Rightarrow$' />
|
||||
|
||||
<char num='8660' name='hArr' convertTo='$\Leftrightarrow$' />
|
||||
<char num='8704' name='forall' convertTo='$\forall$' />
|
||||
<char num='8706' name='part' convertTo='$\partial$' />
|
||||
<char num='8707' name='exist' convertTo='$\exists$' />
|
||||
<char num='8709' name='empty' convertTo='$\emptyset$' />
|
||||
<char num='8711' name='nabla' convertTo='$\nabla$' />
|
||||
<char num='8712' name='isin' convertTo='$\in$' />
|
||||
<char num='8715' name='ni' convertTo='$\ni$' />
|
||||
<char num='8713' name='notin' convertTo='$\notin$' />
|
||||
|
||||
<char num='8721' name='sum' convertTo='$\sum$' />
|
||||
<char num='8719' name='prod' convertTo='$\prod$' />
|
||||
<char num='8722' name='minus' convertTo='$-$' />
|
||||
<char num='8727' name='lowast' convertTo='$\ast$' />
|
||||
<char num='8730' name='radic' convertTo='$\surd$' />
|
||||
<char num='8733' name='prop' convertTo='$\propto$' />
|
||||
<char num='8734' name='infin' convertTo='$\infty$' />
|
||||
<char num='8736' name='ang' convertTo='$\angle$' />
|
||||
<char num='8743' name='and' convertTo='$\wedge$' />
|
||||
|
||||
<char num='8744' name='or' convertTo='$\vee$' />
|
||||
<char num='8745' name='cup' convertTo='$\cup$' />
|
||||
<char num='8746' name='cap' convertTo='$\cap$' />
|
||||
<char num='8747' name='int' convertTo='$\int$' />
|
||||
<char num='8756' name='there4' convertTo='$\therefore$' package='amssymb' /> <!-- only AMS -->
|
||||
<char num='8764' name='sim' convertTo='$\sim$' />
|
||||
<char num='8776' name='asymp' convertTo='$\approx$' />
|
||||
<char num='8773' name='cong' convertTo='$\cong$' />
|
||||
|
||||
<char num='8800' name='ne' convertTo='$\neq$' />
|
||||
<char num='8801' name='equiv' convertTo='$\equiv$' />
|
||||
<char num='8804' name='le' convertTo='$\leq$' />
|
||||
<char num='8805' name='ge' convertTo='$\geq$' />
|
||||
<char num='8834' name='sub' convertTo='$\subset$' />
|
||||
<char num='8835' name='sup' convertTo='$\supset$' />
|
||||
<!-- <char num='8838' name='sube' convertTo='$\subseteq$' />-->
|
||||
<char num='8839' name='supe' convertTo='$\supseteq$' />
|
||||
<!-- <char num='8836' name='nsub' convertTo='$\nsubset$' /> only AMS -->
|
||||
|
||||
<char num='8853' name='oplus' convertTo='$\oplus$' />
|
||||
<char num='8855' name='otimes' convertTo='$\otimes$' />
|
||||
<char num='8869' name='perp' convertTo='$\perp$' />
|
||||
<char num='8901' name='sdot' convertTo='$\cdot$' />
|
||||
<char num='8968' name='rceil' convertTo='$\rceil$' />
|
||||
<char num='8969' name='lceil' convertTo='$\lceil$' />
|
||||
<char num='8970' name='lfloor' convertTo='$\lfloor$' />
|
||||
<char num='8971' name='rfloor' convertTo='$\rfloor$' />
|
||||
<char num='9001' name='rang' convertTo='$\rangle$' />
|
||||
|
||||
<char num='9002' name='lang' convertTo='$\langle$' />
|
||||
<char num='9674' name='loz' convertTo='$\lozenge$' package='amssymb' /> <!-- only AMS -->
|
||||
<char num='9824' name='spades' convertTo='$\spadesuit$' />
|
||||
<char num='9827' name='clubs' convertTo='$\clubsuit$' />
|
||||
<char num='9829' name='hearts' convertTo='$\heartsuit$' />
|
||||
<char num='9830' name='diams' convertTo='$\diamondsuit$' />
|
||||
<char num='38' name='amp' convertTo='\@AMP' />
|
||||
<!-- <char num='34' name='quot' convertTo='\@DOUBLEQUOT' /> XXX -->
|
||||
<char num='34' name='quot' convertTo='"' />
|
||||
<char num='39' name='apos' convertTo="'" />
|
||||
<char num='169' name='copy' convertTo='\copyright' />
|
||||
|
||||
<char num='60' name='lt' convertTo='$@LT$' />
|
||||
<char num='62' name='gt' convertTo='$@GT$' />
|
||||
<char num='338' name='OElig' convertTo='\OE' />
|
||||
<char num='339' name='oelig' convertTo='\oe' />
|
||||
<char num='352' name='Scaron' convertTo='\v{S}' />
|
||||
<char num='353' name='scaron' convertTo='\v{s}' />
|
||||
<char num='376' name='Yuml' convertTo='\"Y' />
|
||||
<char num='710' name='circ' convertTo='\textasciicircum' />
|
||||
<char num='732' name='tilde' convertTo='\textasciitilde' />
|
||||
|
||||
<char num='8211' name='ndash' convertTo='--' />
|
||||
<char num='8212' name='mdash' convertTo='---' />
|
||||
<char num='8216' name='lsquo' convertTo='`' />
|
||||
<char num='8217' name='rsquo' convertTo="'" /> <!-- XXXX -->
|
||||
<char num='8220' name='ldquo' convertTo='``' />
|
||||
<char num='8221' name='rdquo' convertTo="''" /> <!-- XXXX -->
|
||||
<char num='8224' name='dagger' convertTo='\dag' />
|
||||
<char num='8225' name='Dagger' convertTo='\ddag' />
|
||||
<char num='8240' name='permil' convertTo='\permil' package='wasysym' /> <!-- wasysym package -->
|
||||
|
||||
<char num='8364' name='euro' convertTo='\euro' package='eurosym' /> <!-- eurosym package -->
|
||||
<char num='8249' name='lsaquo' convertTo='\guilsinglleft' package='aeguill'/>
|
||||
<char num='8250' name='rsaquo' convertTo='\guilsinglright' package='aeguill' />
|
||||
<!-- <char num='160' name='nbsp' convertTo='\nolinebreak' />-->
|
||||
<char num='160' name='nbsp' convertTo='~' />
|
||||
<char num='161' name='iexcl' convertTo='\textexclamdown' />
|
||||
<char num='163' name='pound' convertTo='\pounds' />
|
||||
<char num='164' name='curren' convertTo='\currency' package='wasysym' /> <!-- wasysym package -->
|
||||
<char num='165' name='yen' convertTo='\textyen' package='textcomp'/> <!-- textcomp -->
|
||||
|
||||
<char num='166' name='brvbar' convertTo='\brokenvert' /> <!-- wasysym -->
|
||||
<char num='167' name='sect' convertTo='\S' />
|
||||
<char num='171' name='laquo' convertTo='\guillemotleft' package='aeguill'/>
|
||||
<char num='187' name='raquo' convertTo='\guillemotright' package='aeguill'/>
|
||||
<char num='174' name='reg' convertTo='\textregistered' />
|
||||
<char num='170' name='ordf' convertTo='\textordfeminine' />
|
||||
<char num='172' name='not' convertTo='$\neg$' />
|
||||
<!-- <char num='176' name='deg' convertTo='$\degree$' /> mathabx -->
|
||||
<char num='176' name='deg' convertTo='\textdegree' package='textcomp'/>
|
||||
|
||||
<char num='177' name='plusmn' convertTo='$\pm$' />
|
||||
<char num='180' name='acute' convertTo='@QUOT' />
|
||||
<char num='181' name='micro' convertTo='$\mu$' />
|
||||
<char num='182' name='para' convertTo='\P' />
|
||||
<char num='183' name='middot' convertTo='$\cdot$' />
|
||||
<char num='186' name='ordm' convertTo='\textordmasculine' />
|
||||
<char num='162' name='cent' convertTo='\cent' package='wasysym' />
|
||||
<char num='185' name='sup1' convertTo='$^1$' />
|
||||
|
||||
<char num='178' name='sup2' convertTo='$^2$' />
|
||||
<char num='179' name='sup3' convertTo='$^3$' />
|
||||
<char num='189' name='frac12' convertTo='$\frac{1}{2}$' />
|
||||
<char num='188' name='frac14' convertTo='$\frac{1}{4}$' />
|
||||
<char num='190' name='frac34' convertTo='$\frac{3}{4}$' />
|
||||
<char num='192' name='Agrave' convertTo='\`A' />
|
||||
<char num='193' name='Aacute' convertTo='\@QUOTA' />
|
||||
<char num='194' name='Acirc' convertTo='\^A' />
|
||||
<char num='195' name='Atilde' convertTo='\~A' />
|
||||
|
||||
<char num='196' name='Auml' convertTo='\@DOUBLEQUOTA' />
|
||||
<char num='197' name='Aring' convertTo='\AA' />
|
||||
<char num='198' name='AElig' convertTo='\AE' />
|
||||
<char num='199' name='Ccedil' convertTo='\c{C}' />
|
||||
<char num='200' name='Egrave' convertTo='\`E' />
|
||||
<char num='201' name='Eacute' convertTo='\@QUOTE' />
|
||||
<char num='202' name='Ecirc' convertTo='\^E' />
|
||||
<char num='203' name='Euml' convertTo='\@DOUBLEQUOTE' />
|
||||
<char num='204' name='Igrave' convertTo='\`I' />
|
||||
<char num='205' name='Iacute' convertTo='\@QUOTI' />
|
||||
<char num='206' name='Icirc' convertTo='\^I' />
|
||||
<char num='207' name='Iuml' convertTo='\"I' />
|
||||
<char num='208' name='ETH' convertTo='$\eth$' /> <!-- AMS -->
|
||||
<char num='209' name='Ntilde' convertTo='\~N' />
|
||||
<char num='210' name='Ograve' convertTo='\`O' />
|
||||
<char num='211' name='Oacute' convertTo='\@QUOT O' />
|
||||
<char num='212' name='Ocirc' convertTo='\^O' />
|
||||
<char num='213' name='Otilde' convertTo='\~O' />
|
||||
<char num='214' name='Ouml' convertTo='\@DOUBLEQUOTO' />
|
||||
<char num='215' name='times' convertTo='$\times$' />
|
||||
<char num='216' name='Oslash' convertTo='\O' />
|
||||
<char num='217' name='Ugrave' convertTo='\`U' />
|
||||
<char num='218' name='Uacute' convertTo='\@QUOTU' />
|
||||
<char num='219' name='Ucirc' convertTo='\^U' />
|
||||
<char num='220' name='Uuml' convertTo='\@DOUBLEQUOTU' />
|
||||
<char num='221' name='Yacute' convertTo='\@QUOTY' />
|
||||
<char num='223' name='szlig' convertTo='\ss' />
|
||||
<char num='224' name='agrave' convertTo='\`a' />
|
||||
<char num='225' name='aacute' convertTo='\@QUOTa' />
|
||||
<char num='226' name='acirc' convertTo='\^a' />
|
||||
<char num='227' name='atilde' convertTo='\~a' />
|
||||
<char num='228' name='auml' convertTo='\@DOUBLEQUOTa' />
|
||||
<char num='229' name='aring' convertTo='\aa' />
|
||||
<char num='230' name='aelig' convertTo='\ae' />
|
||||
<char num='231' name='ccedil' convertTo='\c{c}' />
|
||||
<char num='232' name='egrave' convertTo='\`e' />
|
||||
<char num='233' name='eacute' convertTo='\@QUOTe' />
|
||||
<char num='234' name='ecirc' convertTo='\^e' />
|
||||
<char num='235' name='euml' convertTo='\@DOUBLEQUOTe' />
|
||||
<char num='236' name='igrave' convertTo='\`i' />
|
||||
<char num='237' name='iacute' convertTo='\@QUOTi' />
|
||||
<char num='238' name='icirc' convertTo='\^i' />
|
||||
<char num='239' name='iuml' convertTo='\@DOUBLEQUOTi' />
|
||||
<char num='240' name='eth' convertTo='$\eth$' package='amssymb'/> <!-- -->
|
||||
<char num='241' name='ntilde' convertTo='\~n' />
|
||||
<char num='242' name='ograve' convertTo='\`o' />
|
||||
<char num='243' name='oacute' convertTo='\@QUOTo' />
|
||||
<char num='244' name='ocirc' convertTo='\^o' />
|
||||
<char num='245' name='otilde' convertTo='\~o' />
|
||||
<char num='246' name='ouml' convertTo='\@DOUBLEQUOTo' />
|
||||
<!-- <char num='247' name='divide' convertTo='$\divide$' /> -->
|
||||
<char num='248' name='oslash' convertTo='\o' />
|
||||
<char num='249' name='ugrave' convertTo='\`u' />
|
||||
<char num='250' name='uacute' convertTo='\@QUOTu' />
|
||||
<char num='251' name='ucirc' convertTo='\^u' />
|
||||
<char num='252' name='uuml' convertTo='\@DOUBLEQUOTu' />
|
||||
<char num='253' name='yacute' convertTo='\@QUOTy' />
|
||||
|
||||
<char num='255' name='yuml' convertTo='\@DOUBLEQUOTy' />
|
||||
|
||||
<char num='222' name='THORN' convertTo='\Thorn' package='wasysym' />
|
||||
<char num='254' name='thorn' convertTo='\thorn' package='wasysym' />
|
||||
</chars>
|
89
vendor/plugins/maruku/lib/maruku.rb
vendored
89
vendor/plugins/maruku/lib/maruku.rb
vendored
|
@ -1,78 +1,68 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
dir = File.dirname(__FILE__)
|
||||
$LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
|
||||
|
||||
require 'rexml/document'
|
||||
|
||||
# :include:MaRuKu.txt
|
||||
module MaRuKu
|
||||
module In
|
||||
module Markdown
|
||||
module SpanLevelParser; end
|
||||
module BlockLevelParser; end
|
||||
end
|
||||
end
|
||||
|
||||
module In
|
||||
module Markdown
|
||||
module SpanLevelParser; end
|
||||
module BlockLevelParser; end
|
||||
end
|
||||
# more to come?
|
||||
end
|
||||
module Out
|
||||
module Markdown; end
|
||||
module HTML; end
|
||||
module Latex; end
|
||||
end
|
||||
|
||||
module Out
|
||||
# Functions for exporting to MarkDown.
|
||||
module Markdown; end
|
||||
# Functions for exporting to HTML.
|
||||
module HTML; end
|
||||
# Functions for exporting to Latex
|
||||
module Latex; end
|
||||
end
|
||||
|
||||
# These are strings utilities.
|
||||
module Strings; end
|
||||
module Strings; end
|
||||
|
||||
module Helpers; end
|
||||
module Helpers; end
|
||||
|
||||
module Errors; end
|
||||
|
||||
class MDElement
|
||||
include REXML
|
||||
include MaRuKu
|
||||
include Out::Markdown
|
||||
include Out::HTML
|
||||
include Out::Latex
|
||||
include Strings
|
||||
include Helpers
|
||||
include Errors
|
||||
end
|
||||
|
||||
|
||||
class MDDocument < MDElement
|
||||
include In::Markdown
|
||||
include In::Markdown::SpanLevelParser
|
||||
include In::Markdown::BlockLevelParser
|
||||
end
|
||||
module Errors; end
|
||||
|
||||
class MDElement
|
||||
include REXML
|
||||
include MaRuKu
|
||||
include Out::Markdown
|
||||
include Out::HTML
|
||||
include Out::Latex
|
||||
include Strings
|
||||
include Helpers
|
||||
include Errors
|
||||
end
|
||||
|
||||
|
||||
class MDDocument < MDElement
|
||||
include In::Markdown
|
||||
include In::Markdown::SpanLevelParser
|
||||
include In::Markdown::BlockLevelParser
|
||||
end
|
||||
end
|
||||
|
||||
# This is the public interface
|
||||
class Maruku < MaRuKu::MDDocument; end
|
||||
|
||||
|
||||
|
||||
require 'rexml/document'
|
||||
|
||||
# Structures definition
|
||||
require 'maruku/structures'
|
||||
require 'maruku/structures_inspect'
|
||||
|
@ -106,7 +96,7 @@ require 'maruku/attributes'
|
|||
|
||||
require 'maruku/structures_iterators'
|
||||
|
||||
require 'maruku/errors_management'
|
||||
require 'maruku/errors'
|
||||
|
||||
# Code for creating a table of contents
|
||||
require 'maruku/toc'
|
||||
|
@ -140,4 +130,3 @@ require 'maruku/output/to_s'
|
|||
|
||||
# class Maruku is the global interface
|
||||
require 'maruku/maruku'
|
||||
|
||||
|
|
|
@ -1,462 +0,0 @@
|
|||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
|
||||
|
||||
# NOTE: this is the old span-level regexp-based parser.
|
||||
#
|
||||
# The new parser is a real parser and is defined with functions in parse_span_better.rb
|
||||
# The new parser is faster, handles syntax errors, but it's absolutely not readable.
|
||||
#
|
||||
# Also, regexp parsers simply CANNOT handle inline HTML properly.
|
||||
|
||||
|
||||
|
||||
# There are two black-magic methods `match_couple_of` and `map_match`,
|
||||
# defined at the end of the file, that make the function
|
||||
# `parse_lines_as_span` so elegant.
|
||||
|
||||
class Maruku
|
||||
|
||||
# Takes care of all span-level formatting, links, images, etc.
|
||||
#
|
||||
# Lines must not contain block-level elements.
|
||||
def parse_lines_as_span(lines)
|
||||
|
||||
# first, get rid of linebreaks
|
||||
res = resolve_linebreaks(lines)
|
||||
|
||||
span = MDElement.new(:dummy, res)
|
||||
|
||||
# encode all escapes
|
||||
span.replace_each_string { |s| s.escape_md_special }
|
||||
|
||||
|
||||
# The order of processing is significant:
|
||||
# 1. inline code
|
||||
# 2. immediate links
|
||||
# 3. inline HTML
|
||||
# 4. everything else
|
||||
|
||||
# search for ``code`` markers
|
||||
span.match_couple_of('``') { |children, match1, match2|
|
||||
e = create_md_element(:inline_code)
|
||||
# this is now opaque to processing
|
||||
e.meta[:raw_code] = children.join('').it_was_a_code_block
|
||||
e
|
||||
}
|
||||
|
||||
# Search for `single tick` code markers
|
||||
span.match_couple_of('`') { |children, match1, match2|
|
||||
e = create_md_element(:inline_code)
|
||||
# this is now opaque to processing
|
||||
e.meta[:raw_code] = children.join('').it_was_a_code_block
|
||||
# this is now opaque to processing
|
||||
e
|
||||
}
|
||||
|
||||
# Detect any immediate link: <http://www.google.com>
|
||||
# we expect an http: or something: at the beginning
|
||||
span.map_match( /<(\w+:[^\>]+)>/) { |match|
|
||||
url = match[1]
|
||||
|
||||
e = create_md_element(:immediate_link, [])
|
||||
e.meta[:url] = url
|
||||
e
|
||||
}
|
||||
|
||||
# Search for inline HTML (the support is pretty basic for now)
|
||||
|
||||
# this searches for a matching block
|
||||
inlineHTML1 = %r{
|
||||
( # put everything in 1
|
||||
< # open
|
||||
(\w+) # opening tag in 2
|
||||
> # close
|
||||
.* # anything
|
||||
</\2> # match closing tag
|
||||
)
|
||||
}x
|
||||
|
||||
# this searches for only one block
|
||||
inlineHTML2 = %r{
|
||||
( # put everything in 1
|
||||
< # open
|
||||
\w+ #
|
||||
# close
|
||||
[^<>]* # anything except
|
||||
/> # closing tag
|
||||
)
|
||||
}x
|
||||
|
||||
for reg in [inlineHTML1, inlineHTML2]
|
||||
span.map_match(reg) { |match|
|
||||
raw_html = match[1]
|
||||
convert_raw_html_in_list(raw_html)
|
||||
}
|
||||
end
|
||||
|
||||
# Detect footnotes references: [^1]
|
||||
span.map_match(/\[(\^[^\]]+)\]/) { |match|
|
||||
id = match[1].strip.downcase
|
||||
e = create_md_element(:footnote_reference)
|
||||
e.meta[:footnote_id] = id
|
||||
e
|
||||
}
|
||||
|
||||
# Detect any image like ![Alt text][url]
|
||||
span.map_match(/\!\[([^\]]+)\]\s?\[([^\]]*)\]/) { |match|
|
||||
alt = match[1]
|
||||
id = match[2].strip.downcase
|
||||
|
||||
if id.size == 0
|
||||
id = text.strip.downcase
|
||||
end
|
||||
|
||||
e = create_md_element(:image)
|
||||
e.meta[:ref_id] = id
|
||||
e
|
||||
}
|
||||
|
||||
# Detect any immage with immediate url: ![Alt](url "title")
|
||||
# a dummy ref is created and put in the symbol table
|
||||
link1 = /!\[([^\]]+)\]\s?\(([^\s\)]*)(?:\s+["'](.*)["'])?\)/
|
||||
span.map_match(link1) { |match|
|
||||
alt = match[1]
|
||||
url = match[2]
|
||||
title = match[3]
|
||||
|
||||
url = url.strip
|
||||
# create a dummy id
|
||||
id="dummy_#{@refs.size}"
|
||||
@refs[id] = {:url=>url, :title=>title}
|
||||
|
||||
e = create_md_element(:image)
|
||||
e.meta[:ref_id] = id
|
||||
e
|
||||
}
|
||||
|
||||
# an id reference: "[id]", "[ id ]"
|
||||
reg_id_ref = %r{
|
||||
\[ # opening bracket
|
||||
([^\]]*) # 0 or more non-closing bracket (this is too permissive)
|
||||
\] # closing bracket
|
||||
}x
|
||||
|
||||
|
||||
# validates a url, only $1 is set to the url
|
||||
reg_url =
|
||||
/((?:\w+):\/\/(?:\w+:{0,1}\w*@)?(?:\S+)(?::[0-9]+)?(?:\/|\/([\w#!:.?+=&%@!\-\/]))?)/
|
||||
reg_url = %r{([^\s\]\)]+)}
|
||||
|
||||
# A string enclosed in quotes.
|
||||
reg_title = %r{
|
||||
" # opening
|
||||
[^"]* # anything = 1
|
||||
" # closing
|
||||
}x
|
||||
|
||||
# [bah](http://www.google.com "Google.com"),
|
||||
# [bah](http://www.google.com),
|
||||
# [empty]()
|
||||
reg_url_and_title = %r{
|
||||
\( # opening
|
||||
\s* # whitespace
|
||||
#{reg_url}? # url = 1 might be empty
|
||||
(?:\s+["'](.*)["'])? # optional title = 2
|
||||
\s* # whitespace
|
||||
\) # closing
|
||||
}x
|
||||
|
||||
# Detect a link like ![Alt text][id]
|
||||
span.map_match(/\[([^\]]+)\]\s?\[([^\]]*)\]/) { |match|
|
||||
text = match[1]
|
||||
id = match[2].strip.downcase
|
||||
|
||||
if id.size == 0
|
||||
id = text.strip.downcase
|
||||
end
|
||||
|
||||
children = parse_lines_as_span(text)
|
||||
e = create_md_element(:link, children)
|
||||
e.meta[:ref_id] = id
|
||||
e
|
||||
}
|
||||
|
||||
# Detect any immage with immediate url: ![Alt](url "title")
|
||||
# a dummy ref is created and put in the symbol table
|
||||
link1 = /!\[([^\]]+)\]\s?\(([^\s\)]*)(?:\s+["'](.*)["'])?\)/
|
||||
span.map_match(link1) { |match|
|
||||
text = match[1]
|
||||
children = parse_lines_as_span(text)
|
||||
|
||||
url = match[2]
|
||||
title = match[3]
|
||||
|
||||
url = url.strip
|
||||
# create a dummy id
|
||||
id="dummy_#{@refs.size}"
|
||||
@refs[id] = {:url=>url, :title=>title}
|
||||
@refs[id][:title] = title if title
|
||||
|
||||
e = create_md_element(:link, children)
|
||||
e.meta[:ref_id] = id
|
||||
e
|
||||
}
|
||||
|
||||
|
||||
# Detect any link like [Google engine][google]
|
||||
span.match_couple_of('[', # opening bracket
|
||||
%r{\] # closing bracket
|
||||
[ ]? # optional whitespace
|
||||
#{reg_id_ref} # ref id, with $1 being the reference
|
||||
}x
|
||||
) { |children, match1, match2|
|
||||
id = match2[1]
|
||||
id = id.strip.downcase
|
||||
|
||||
if id.size == 0
|
||||
id = children.join.strip.downcase
|
||||
end
|
||||
|
||||
e = create_md_element(:link, children)
|
||||
e.meta[:ref_id] = id
|
||||
e
|
||||
}
|
||||
|
||||
# Detect any link with immediate url: [Google](http://www.google.com)
|
||||
# XXX Note that the url can be empty: [Empty]()
|
||||
# a dummy ref is created and put in the symbol table
|
||||
span.match_couple_of('[', # opening bracket
|
||||
%r{\] # closing bracket
|
||||
[ ]? # optional whitespace
|
||||
#{reg_url_and_title} # ref id, with $1 being the url and $2 being the title
|
||||
}x
|
||||
) { |children, match1, match2|
|
||||
|
||||
url = match2[1]
|
||||
title = match2[3] # XXX? Is it a bug? I would use [2]
|
||||
|
||||
# create a dummy id
|
||||
id="dummy_#{@refs.size}"
|
||||
@refs[id] = {:url=>url}
|
||||
@refs[id][:title] = title if title
|
||||
|
||||
e = create_md_element(:link, children)
|
||||
e.meta[:ref_id] = id
|
||||
e
|
||||
}
|
||||
|
||||
# Detect an email address <andrea@invalid.it>
|
||||
span.map_match(EMailAddress) { |match|
|
||||
email = match[1]
|
||||
e = create_md_element(:email_address, [])
|
||||
e.meta[:email] = email
|
||||
e
|
||||
}
|
||||
|
||||
# Detect HTML entitis
|
||||
span.map_match(/&([\w\d]+);/) { |match|
|
||||
entity_name = match[1]
|
||||
|
||||
e = create_md_element(:entity, [])
|
||||
e.meta[:entity_name] = entity_name
|
||||
e
|
||||
}
|
||||
|
||||
|
||||
# And now the easy stuff
|
||||
|
||||
# search for ***strong and em***
|
||||
span.match_couple_of('***') { |children,m1,m2|
|
||||
create_md_element(:strong, [create_md_element(:emphasis, children)] ) }
|
||||
|
||||
span.match_couple_of('___') { |children,m1,m2|
|
||||
create_md_element(:strong, [create_md_element(:emphasis, children)] ) }
|
||||
|
||||
# search for **strong**
|
||||
span.match_couple_of('**') { |children,m1,m2| create_md_element(:strong, children) }
|
||||
|
||||
# search for __strong__
|
||||
span.match_couple_of('__') { |children,m1,m2| create_md_element(:strong, children) }
|
||||
|
||||
# search for *emphasis*
|
||||
span.match_couple_of('*') { |children,m1,m2| create_md_element(:emphasis, children) }
|
||||
|
||||
# search for _emphasis_
|
||||
span.match_couple_of('_') { |children,m1,m2| create_md_element(:emphasis, children) }
|
||||
|
||||
# finally, unescape the special characters
|
||||
span.replace_each_string { |s| s.unescape_md_special}
|
||||
|
||||
span.children
|
||||
end
|
||||
|
||||
# returns array containing Strings or :linebreak elements
|
||||
def resolve_linebreaks(lines)
|
||||
res = []
|
||||
s = ""
|
||||
lines.each do |l|
|
||||
s += (s.size>0 ? " " : "") + l.strip
|
||||
if force_linebreak?(l)
|
||||
res << s
|
||||
res << create_md_element(:linebreak)
|
||||
s = ""
|
||||
end
|
||||
end
|
||||
res << s if s.size > 0
|
||||
res
|
||||
end
|
||||
|
||||
# raw_html is something like
|
||||
# <em> A</em> dopwkk *maruk* <em>A</em>
|
||||
def convert_raw_html_in_list(raw_html)
|
||||
e = create_md_element(:raw_html)
|
||||
e.meta[:raw_html] = raw_html
|
||||
begin
|
||||
e.meta[:parsed_html] = Document.new(raw_html)
|
||||
rescue
|
||||
$stderr.puts "convert_raw_html_in_list Malformed HTML:\n#{raw_html}"
|
||||
end
|
||||
e
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# And now the black magic that makes the part above so elegant
|
||||
class MDElement
|
||||
|
||||
# Try to match the regexp to each string in the hierarchy
|
||||
# (using `replace_each_string`). If the regexp match, eliminate
|
||||
# the matching string and substitute it with the pre_match, the
|
||||
# result of the block, and the post_match
|
||||
#
|
||||
# ..., matched_string, ... -> ..., pre_match, block.call(match), post_match
|
||||
#
|
||||
# the block might return arrays.
|
||||
#
|
||||
def map_match(regexp, &block)
|
||||
replace_each_string { |s|
|
||||
processed = []
|
||||
while (match = regexp.match(s))
|
||||
# save the pre_match
|
||||
processed << match.pre_match if match.pre_match && match.pre_match.size>0
|
||||
# transform match
|
||||
result = block.call(match)
|
||||
# and append as processed
|
||||
[*result].each do |e| processed << e end
|
||||
# go on with the rest of the string
|
||||
s = match.post_match
|
||||
end
|
||||
processed << s if s.size > 0
|
||||
processed
|
||||
}
|
||||
end
|
||||
|
||||
# Finds couple of delimiters in a hierarchy of Strings and MDElements
|
||||
#
|
||||
# Open and close are two delimiters (like '[' and ']'), or two Regexp.
|
||||
#
|
||||
# If you don't pass close, it defaults to open.
|
||||
#
|
||||
# Each block is called with |contained children, match1, match2|
|
||||
def match_couple_of(open, close=nil, &block)
|
||||
close = close || open
|
||||
open_regexp = open.kind_of?(Regexp) ? open : Regexp.new(Regexp.escape(open))
|
||||
close_regexp = close.kind_of?(Regexp) ? close : Regexp.new(Regexp.escape(close))
|
||||
|
||||
# Do the same to children first
|
||||
for c in @children; if c.kind_of? MDElement
|
||||
c.match_couple_of(open_regexp, close_regexp, &block)
|
||||
end end
|
||||
|
||||
processed_children = []
|
||||
|
||||
until @children.empty?
|
||||
c = @children.shift
|
||||
if c.kind_of? String
|
||||
match1 = open_regexp.match(c)
|
||||
if not match1
|
||||
processed_children << c
|
||||
else # we found opening, now search closing
|
||||
# puts "Found opening (#{marker}) in #{c.inspect}"
|
||||
# pre match is processed
|
||||
processed_children.push match1.pre_match if
|
||||
match1.pre_match && match1.pre_match.size > 0
|
||||
# we will process again the post_match
|
||||
@children.unshift match1.post_match if
|
||||
match1.post_match && match1.post_match.size>0
|
||||
|
||||
contained = []; found_closing = false
|
||||
until @children.empty? || found_closing
|
||||
c = @children.shift
|
||||
if c.kind_of? String
|
||||
match2 = close_regexp.match(c)
|
||||
if not match2
|
||||
contained << c
|
||||
else
|
||||
# we found closing
|
||||
found_closing = true
|
||||
# pre match is contained
|
||||
contained.push match2.pre_match if
|
||||
match2.pre_match && match2.pre_match.size>0
|
||||
# we will process again the post_match
|
||||
@children.unshift match2.post_match if
|
||||
match2.post_match && match2.post_match.size>0
|
||||
|
||||
# And now we call the block
|
||||
substitute = block.call(contained, match1, match2)
|
||||
processed_children << substitute
|
||||
|
||||
# puts "Found closing (#{marker}) in #{c.inspect}"
|
||||
# puts "Children: #{contained.inspect}"
|
||||
# puts "Substitute: #{substitute.inspect}"
|
||||
end
|
||||
else
|
||||
contained << c
|
||||
end
|
||||
end
|
||||
|
||||
if not found_closing
|
||||
# $stderr.puts "##### Could not find closing for #{open}, #{close} -- ignoring"
|
||||
processed_children << match1.to_s
|
||||
contained.reverse.each do |c|
|
||||
@children.unshift c
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
processed_children << c
|
||||
end
|
||||
end
|
||||
|
||||
raise "BugBug" unless @children.empty?
|
||||
|
||||
rebuilt = []
|
||||
# rebuild strings
|
||||
processed_children.each do |c|
|
||||
if c.kind_of?(String) && rebuilt.last && rebuilt.last.kind_of?(String)
|
||||
rebuilt.last << c
|
||||
else
|
||||
rebuilt << c
|
||||
end
|
||||
end
|
||||
@children = rebuilt
|
||||
end
|
||||
end
|
279
vendor/plugins/maruku/lib/maruku/attributes.rb
vendored
279
vendor/plugins/maruku/lib/maruku/attributes.rb
vendored
|
@ -1,175 +1,138 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
class String
|
||||
def quote_if_needed
|
||||
if /[\s\'\"]/.match self
|
||||
inspect
|
||||
else
|
||||
self
|
||||
end
|
||||
end
|
||||
module MaRuKu
|
||||
# This represents a list of attributes specified in the Markdown document
|
||||
# that apply to a Markdown-generated tag.
|
||||
# What was `{#id .class key="val" ref}` in the Markdown
|
||||
# is parsed into `[[:id, 'id'], [:class, 'id'], ['key', 'val'], [:ref, 'ref']]`.
|
||||
class AttributeList < Array
|
||||
def to_s
|
||||
map do |k, v|
|
||||
case k
|
||||
when :id; "#" + quote_if_needed(v)
|
||||
when :class; "." + quote_if_needed(v)
|
||||
when :ref; quote_if_needed(v)
|
||||
else quote_if_needed(k) + "=" + quote_if_needed(v)
|
||||
end
|
||||
end.join(' ')
|
||||
end
|
||||
alias to_md to_s
|
||||
|
||||
private
|
||||
|
||||
def quote_if_needed(str)
|
||||
return str unless str =~ /[\s'"]/
|
||||
str.inspect
|
||||
end
|
||||
end
|
||||
|
||||
module In::Markdown::SpanLevelParser
|
||||
def md_al(s = []); AttributeList.new(s); end
|
||||
|
||||
# @return [AttributeList, nil]
|
||||
def read_attribute_list(src, con, break_on_chars)
|
||||
separators = break_on_chars + [?=, ?\s, ?\t]
|
||||
escaped = Maruku::EscapedCharInQuotes
|
||||
|
||||
al = AttributeList.new
|
||||
loop do
|
||||
src.consume_whitespace
|
||||
break if break_on_chars.include? src.cur_char
|
||||
|
||||
case src.cur_char
|
||||
when nil
|
||||
maruku_error "Attribute list terminated by EOF:\n #{al.inspect}", src, con
|
||||
tell_user "Returning partial attribute list:\n #{al.inspect}"
|
||||
break
|
||||
when ?= # error
|
||||
src.ignore_char
|
||||
maruku_error "In attribute lists, cannot start identifier with `=`."
|
||||
tell_user "Ignoring and continuing."
|
||||
when ?# # id definition
|
||||
src.ignore_char
|
||||
if id = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
al << [:id, id]
|
||||
else
|
||||
maruku_error 'Could not read `id` attribute.', src, con
|
||||
tell_user 'Ignoring bad `id` attribute.'
|
||||
end
|
||||
when ?. # class definition
|
||||
src.ignore_char
|
||||
if klass = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
al << [:class, klass]
|
||||
else
|
||||
maruku_error 'Could not read `class` attribute.', src, con
|
||||
tell_user 'Ignoring bad `class` attribute.'
|
||||
end
|
||||
else
|
||||
unless key = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
maruku_error 'Could not read key or reference.'
|
||||
next
|
||||
end
|
||||
|
||||
if src.cur_char != ?=
|
||||
al << [:ref, key]
|
||||
next
|
||||
end
|
||||
|
||||
src.ignore_char # skip the =
|
||||
if val = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
al << [key, val]
|
||||
else
|
||||
maruku_error "Could not read value for key #{key.inspect}.", src, con
|
||||
tell_user "Ignoring key #{key.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
al
|
||||
end
|
||||
|
||||
def merge_ial(elements, src, con)
|
||||
# Apply each IAL to the element before
|
||||
(elements + [nil]).each_cons(3) do |before, e, after|
|
||||
next unless ial?(e)
|
||||
|
||||
if before.kind_of? MDElement
|
||||
before.al = e.ial
|
||||
elsif after.kind_of? MDElement
|
||||
after.al = e.ial
|
||||
else
|
||||
maruku_error <<ERR, src, con
|
||||
It's unclear which element the attribute list {:#{e.ial.to_md}}
|
||||
is referring to. The element before is a #{before.class},
|
||||
the element after is a #{after.class}.
|
||||
before: #{before.inspect}
|
||||
after: #{after.inspect}
|
||||
ERR
|
||||
end
|
||||
end
|
||||
|
||||
unless Globals[:debug_keep_ials]
|
||||
elements.delete_if {|x| ial?(x) && x != elements.first}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ial?(e)
|
||||
e.is_a?(MDElement) && e.node_type == :ial
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module MaRuKu;
|
||||
MagicChar = ':'
|
||||
|
||||
class AttributeList < Array
|
||||
|
||||
# An attribute list becomes
|
||||
# {#id .cl key="val" ref}
|
||||
# [ [:id, 'id'], [:class, 'id'], ['key', 'val'], [ :ref, 'ref' ]]
|
||||
|
||||
private :push
|
||||
|
||||
def push_key_val(key, val);
|
||||
raise "Bad #{key.inspect}=#{val.inspect}" if not key and val
|
||||
push [key, val]
|
||||
end
|
||||
def push_ref(ref_id);
|
||||
|
||||
raise "Bad :ref #{ref_id.inspect}" if not ref_id
|
||||
push [:ref, ref_id+""]
|
||||
|
||||
# p "Now ", self ########################################
|
||||
end
|
||||
def push_class(val);
|
||||
raise "Bad :id #{val.inspect}" if not val
|
||||
push [:class, val]
|
||||
end
|
||||
def push_id(val);
|
||||
raise "Bad :id #{val.inspect}" if not val
|
||||
push [:id, val]
|
||||
end
|
||||
|
||||
def to_s
|
||||
map do |k,v|
|
||||
case k
|
||||
when :id; "#" + v.quote_if_needed
|
||||
when :class; "." + v.quote_if_needed
|
||||
when :ref; v.quote_if_needed
|
||||
else k.quote_if_needed + "=" + v.quote_if_needed
|
||||
end
|
||||
end . join(' ')
|
||||
end
|
||||
alias to_md to_s
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module MaRuKu; module In; module Markdown; module SpanLevelParser
|
||||
|
||||
def md_al(s=[]); AttributeList.new(s) end
|
||||
|
||||
# returns nil or an AttributeList
|
||||
def read_attribute_list(src, con, break_on_chars)
|
||||
|
||||
separators = break_on_chars + [?=,?\ ,?\t]
|
||||
escaped = Maruku::EscapedCharInQuotes
|
||||
|
||||
al = AttributeList.new
|
||||
while true
|
||||
src.consume_whitespace
|
||||
break if break_on_chars.include? src.cur_char
|
||||
|
||||
case src.cur_char
|
||||
when nil
|
||||
maruku_error "Attribute list terminated by EOF:\n "+
|
||||
"#{al.inspect}" , src, con
|
||||
tell_user "I try to continue and return partial attribute list:\n"+
|
||||
al.inspect
|
||||
break
|
||||
when ?= # error
|
||||
maruku_error "In attribute lists, cannot start identifier with `=`."
|
||||
tell_user "I try to continue"
|
||||
src.ignore_char
|
||||
when ?# # id definition
|
||||
src.ignore_char
|
||||
if id = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
al.push_id id
|
||||
else
|
||||
maruku_error 'Could not read `id` attribute.', src, con
|
||||
tell_user 'Trying to ignore bad `id` attribute.'
|
||||
end
|
||||
when ?. # class definition
|
||||
src.ignore_char
|
||||
if klass = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
al.push_class klass
|
||||
else
|
||||
maruku_error 'Could not read `class` attribute.', src, con
|
||||
tell_user 'Trying to ignore bad `class` attribute.'
|
||||
end
|
||||
else
|
||||
if key = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
if src.cur_char == ?=
|
||||
src.ignore_char # skip the =
|
||||
if val = read_quoted_or_unquoted(src, con, escaped, separators)
|
||||
al.push_key_val(key, val)
|
||||
else
|
||||
maruku_error "Could not read value for key #{key.inspect}.",
|
||||
src, con
|
||||
tell_user "Ignoring key #{key.inspect}."
|
||||
end
|
||||
else
|
||||
al.push_ref key
|
||||
end
|
||||
else
|
||||
maruku_error 'Could not read key or reference.'
|
||||
end
|
||||
end # case
|
||||
end # while true
|
||||
al
|
||||
end
|
||||
|
||||
|
||||
# We need a helper
|
||||
def is_ial(e); e.kind_of? MDElement and e.node_type == :ial end
|
||||
|
||||
def merge_ial(elements, src, con)
|
||||
|
||||
# Apply each IAL to the element before
|
||||
elements.each_with_index do |e, i|
|
||||
if is_ial(e) && i>= 1 then
|
||||
before = elements[i-1]
|
||||
after = elements[i+1]
|
||||
if before.kind_of? MDElement
|
||||
before.al = e.ial
|
||||
elsif after.kind_of? MDElement
|
||||
after.al = e.ial
|
||||
else
|
||||
maruku_error "It is not clear to me what element this IAL {:#{e.ial.to_md}} \n"+
|
||||
"is referring to. The element before is a #{before.class.to_s}, \n"+
|
||||
"the element after is a #{after.class.to_s}.\n"+
|
||||
"\n before: #{before.inspect}"+
|
||||
"\n after: #{after.inspect}",
|
||||
src, con
|
||||
# xxx dire se c'è empty vicino
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not Globals[:debug_keep_ials]
|
||||
elements.delete_if {|x| is_ial(x) unless x == elements.first}
|
||||
end
|
||||
end
|
||||
|
||||
end end end end
|
||||
#module MaRuKu; module In; module Markdown; module SpanLevelParser
|
||||
|
|
95
vendor/plugins/maruku/lib/maruku/defaults.rb
vendored
95
vendor/plugins/maruku/lib/maruku/defaults.rb
vendored
|
@ -1,71 +1,64 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
module MaRuKu
|
||||
|
||||
Globals = {
|
||||
:unsafe_features => false,
|
||||
:on_error => :warning,
|
||||
|
||||
|
||||
:use_numbered_headers => false,
|
||||
|
||||
:maruku_signature => false,
|
||||
:code_background_color => '#fef',
|
||||
:code_show_spaces => false,
|
||||
|
||||
:filter_html => false,
|
||||
|
||||
:html_math_output_mathml => true, # also set :html_math_engine
|
||||
:html_math_engine => 'itex2mml', #ritex, itex2mml, none
|
||||
|
||||
:html_math_output_png => false,
|
||||
:html_png_engine => 'none',
|
||||
:html_png_dir => 'pngs',
|
||||
:html_png_url => 'pngs/',
|
||||
:html_png_resolution => 200,
|
||||
|
||||
:html_use_syntax => true,
|
||||
|
||||
:latex_use_listings => false,
|
||||
:latex_cjk => false,
|
||||
:latex_cache_file => "blahtex_cache.pstore", # cache file for blahtex filter
|
||||
|
||||
:debug_keep_ials => false,
|
||||
:doc_prefix => ''
|
||||
}
|
||||
|
||||
class MDElement
|
||||
def get_setting(sym)
|
||||
if self.attributes.has_key?(sym) then
|
||||
return self.attributes[sym]
|
||||
elsif self.doc && self.doc.attributes.has_key?(sym) then
|
||||
return self.doc.attributes[sym]
|
||||
elsif MaRuKu::Globals.has_key?(sym)
|
||||
return MaRuKu::Globals[sym]
|
||||
else
|
||||
$stderr.puts "Bug: no default for #{sym.inspect}"
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
Globals = {
|
||||
:unsafe_features => false,
|
||||
:on_error => :warning,
|
||||
|
||||
:use_numbered_headers => false,
|
||||
|
||||
:maruku_signature => false,
|
||||
:code_background_color => '#fef',
|
||||
:code_show_spaces => false,
|
||||
|
||||
:filter_html => false,
|
||||
|
||||
:html_math_output_mathml => true, # also set :html_math_engine
|
||||
:html_math_engine => 'itex2mml', #ritex, itex2mml, none
|
||||
|
||||
:html_math_output_png => false,
|
||||
:html_png_engine => 'none',
|
||||
:html_png_dir => 'pngs',
|
||||
:html_png_url => 'pngs/',
|
||||
:html_png_resolution => 200,
|
||||
|
||||
:html_use_syntax => true,
|
||||
|
||||
:latex_use_listings => false,
|
||||
:latex_cjk => false,
|
||||
:latex_cache_file => "blahtex_cache.pstore", # cache file for blahtex filter
|
||||
|
||||
:debug_keep_ials => false,
|
||||
:doc_prefix => ''
|
||||
}
|
||||
|
||||
class MDElement
|
||||
def get_setting(sym)
|
||||
return attributes[sym] if attributes.has_key?(sym)
|
||||
return doc.attributes[sym] if doc && doc.attributes.has_key?(sym)
|
||||
return MaRuKu::Globals[sym] if MaRuKu::Globals.has_key?(sym)
|
||||
|
||||
$stderr.puts "Bug: no default for #{sym.inspect}"
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
89
vendor/plugins/maruku/lib/maruku/errors.rb
vendored
Normal file
89
vendor/plugins/maruku/lib/maruku/errors.rb
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
module MaRuKu
|
||||
class Exception < RuntimeError; end
|
||||
|
||||
module Errors
|
||||
FRAME_WIDTH = 75
|
||||
|
||||
# Properly handles a formatting error.
|
||||
# All such errors go through this method.
|
||||
#
|
||||
# The behavior depends on {MaRuKu::Globals `MaRuKu::Globals[:on_error]`}.
|
||||
# If this is `:warning`, this prints the error to stderr
|
||||
# (or `@error_stream if` it's defined) and tries to continue.
|
||||
# If `:on_error` is `:ignore`, this doesn't print anything
|
||||
# and tries to continue. If it's `:raise`, this raises a {MaRuKu::Exception}.
|
||||
#
|
||||
# By default, `:on_error` is set to `:warning`.
|
||||
#
|
||||
# @overload def maruku_error(s, src = nil, con = nil)
|
||||
# @param s [String] The text of the error
|
||||
# @param src [#describe, nil] The source of the error
|
||||
# @param con [#describe, nil] The context of the error
|
||||
# @raise [MaRuKu::Exception] If `:on_error` is set to `:raise`
|
||||
def maruku_error(*args)
|
||||
policy = get_setting(:on_error)
|
||||
|
||||
case policy
|
||||
when :ignore
|
||||
when :raise
|
||||
raise_error create_frame(describe_error(*args))
|
||||
when :warning
|
||||
tell_user create_frame(describe_error(*args))
|
||||
else
|
||||
raise "Unknown on_error policy: #{policy.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def maruku_recover(*args)
|
||||
tell_user create_frame(describe_error(*args))
|
||||
end
|
||||
alias error maruku_error
|
||||
|
||||
def raise_error(s)
|
||||
raise MaRuKu::Exception, s, caller
|
||||
end
|
||||
|
||||
def tell_user(s)
|
||||
(self.attributes[:error_stream] || $stderr) << s
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_frame(s)
|
||||
"\n" + <<FRAME
|
||||
#{"_" * FRAME_WIDTH}
|
||||
| Maruku tells you:
|
||||
+#{"-" * FRAME_WIDTH}
|
||||
#{s.gsub(/^/, '| ').rstrip}
|
||||
+#{"-" * FRAME_WIDTH}
|
||||
#{caller[0...5].join("\n").gsub(/^/, '!')}
|
||||
\\#{"_" * FRAME_WIDTH}
|
||||
FRAME
|
||||
end
|
||||
|
||||
def describe_error(s, src = nil, con = nil)
|
||||
s += "\n#{src.describe}\n" if src
|
||||
s += "\n#{con.describe}\n" if con
|
||||
s
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,92 +0,0 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
|
||||
#m Any method that detects formatting error calls the
|
||||
#m maruku_error() method.
|
||||
#m if @meta[:on_error] ==
|
||||
#m
|
||||
#m - :warning write on the standard err (or @error_stream if defined),
|
||||
#m then do your best.
|
||||
#m - :ignore be shy and try to continue
|
||||
#m - :raise raises a MarukuException
|
||||
#m
|
||||
#m default is :raise
|
||||
|
||||
module MaRuKu
|
||||
|
||||
class Exception < RuntimeError
|
||||
end
|
||||
|
||||
module Errors
|
||||
|
||||
def maruku_error(s,src=nil,con=nil)
|
||||
policy = get_setting(:on_error)
|
||||
|
||||
case policy
|
||||
when :ignore
|
||||
when :raise
|
||||
raise_error create_frame(describe_error(s,src,con))
|
||||
when :warning
|
||||
tell_user create_frame(describe_error(s,src,con))
|
||||
else
|
||||
raise "BugBug: policy = #{policy.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
def maruku_recover(s,src=nil,con=nil)
|
||||
tell_user create_frame(describe_error(s,src,con))
|
||||
end
|
||||
|
||||
alias error maruku_error
|
||||
|
||||
def raise_error(s)
|
||||
raise MaRuKu::Exception, s, caller
|
||||
end
|
||||
|
||||
def tell_user(s)
|
||||
error_stream = self.attributes[:error_stream] || $stderr
|
||||
error_stream << s
|
||||
end
|
||||
|
||||
def create_frame(s)
|
||||
n = 75
|
||||
"\n" +
|
||||
" "+"_"*n + "\n"+
|
||||
"| Maruku tells you:\n" +
|
||||
"+" + ("-"*n) +"\n"+
|
||||
add_tabs(s,1,'| ') + "\n" +
|
||||
"+" + ("-"*n) + "\n" +
|
||||
add_tabs(caller[0, 5].join("\n"),1,'!') + "\n" +
|
||||
"\\" + ("_"*n) + "\n"
|
||||
end
|
||||
|
||||
def describe_error(s,src,con)
|
||||
t = s
|
||||
src && (t += "\n#{src.describe}\n")
|
||||
con && (t += "\n#{con.describe}\n")
|
||||
t
|
||||
end
|
||||
|
||||
end # Errors
|
||||
end # MaRuKu
|
||||
|
||||
|
209
vendor/plugins/maruku/lib/maruku/ext/div.rb
vendored
209
vendor/plugins/maruku/lib/maruku/ext/div.rb
vendored
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
#+-----------------------------------{.warning}------
|
||||
#| this is the last warning!
|
||||
#|
|
||||
|
@ -10,123 +8,114 @@
|
|||
#| +--------------------------------------------------
|
||||
#+---------------------------------------------------
|
||||
|
||||
#OpenDiv = /^[ ]{0,3}\+\-\-+\s*(.*)$/
|
||||
#CloseDiv = /^[ ]{0,3}\=\-\-+\s*(.*)$/
|
||||
# TODO: Scope these properly
|
||||
OpenDiv = /^[ ]{0,3}\+\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/
|
||||
CloseDiv = /^[ ]{0,3}\=\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/
|
||||
StartPipe = /^[ ]{0,3}\|(.*)$/ # $1 is rest of line
|
||||
DecorativeClosing = OpenDiv
|
||||
|
||||
MaRuKu::In::Markdown::register_block_extension(
|
||||
:regexp => OpenDiv,
|
||||
:handler => lambda { |doc, src, context|
|
||||
# return false if not doc.is_math_enabled?
|
||||
first = src.shift_line
|
||||
first =~ OpenDiv
|
||||
ial_at_beginning = $1
|
||||
ial_at_end = nil
|
||||
|
||||
lines = []
|
||||
# if second line starts with "|"
|
||||
if src.cur_line =~ StartPipe
|
||||
# then we read until no more "|"
|
||||
while src.cur_line && (src.cur_line =~ StartPipe)
|
||||
content = $1
|
||||
lines.push content
|
||||
src.shift_line
|
||||
end
|
||||
if src.cur_line =~ DecorativeClosing
|
||||
ial_at_end = $1
|
||||
src.shift_line
|
||||
end
|
||||
else
|
||||
# else we read until CloseDiv
|
||||
divs_open = 1
|
||||
while src.cur_line && (divs_open>0)
|
||||
if src.cur_line =~ CloseDiv
|
||||
divs_open -= 1
|
||||
if divs_open == 0
|
||||
ial_at_end = $1
|
||||
src.shift_line
|
||||
break
|
||||
else
|
||||
lines.push src.shift_line
|
||||
end
|
||||
else
|
||||
if src.cur_line =~ OpenDiv
|
||||
divs_open += 1
|
||||
end
|
||||
lines.push src.shift_line
|
||||
end
|
||||
end
|
||||
|
||||
if divs_open > 0
|
||||
e = "At end of input, I still have #{divs_open} DIVs open."
|
||||
doc.maruku_error(e, src, context)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
ial_at_beginning = nil unless
|
||||
(ial_at_beginning&&ial_at_beginning.size > 0)
|
||||
ial_at_end = nil unless (ial_at_end && ial_at_end.size > 0)
|
||||
MaRuKu::In::Markdown.register_block_extension(
|
||||
:regexp => OpenDiv,
|
||||
:handler => lambda do |doc, src, context|
|
||||
first = src.shift_line
|
||||
ial_at_beginning = first[OpenDiv, 1]
|
||||
ial_at_end = nil
|
||||
|
||||
if ial_at_beginning && ial_at_end
|
||||
e = "Found two conflicting IALs: #{ial_at_beginning.inspect} and #{ial_at_end.inspect}"
|
||||
doc.maruku_error(e, src, context)
|
||||
end
|
||||
|
||||
al_string = ial_at_beginning || ial_at_end
|
||||
al = nil
|
||||
|
||||
if al_string =~ /^\{(.*)\}\s*$/
|
||||
inside = $1
|
||||
cs = MaRuKu::In::Markdown::SpanLevelParser::CharSource
|
||||
al = al_string &&
|
||||
doc.read_attribute_list(cs.new(inside), its_context=nil, break_on=[nil])
|
||||
end
|
||||
|
||||
src = MaRuKu::In::Markdown::BlockLevelParser::LineSource.new(lines)
|
||||
children = doc.parse_blocks(src)
|
||||
lines = []
|
||||
# if second line starts with "|"
|
||||
if src.cur_line =~ StartPipe
|
||||
# then we read until no more "|"
|
||||
while src.cur_line && src.cur_line =~ StartPipe
|
||||
lines.push $1
|
||||
src.shift_line
|
||||
end
|
||||
if src.cur_line =~ DecorativeClosing
|
||||
ial_at_end = $1
|
||||
src.shift_line
|
||||
end
|
||||
else
|
||||
# else we read until CloseDiv
|
||||
divs_open = 1
|
||||
while src.cur_line && divs_open > 0
|
||||
if src.cur_line =~ CloseDiv
|
||||
divs_open -= 1
|
||||
if divs_open == 0
|
||||
ial_at_end = $1
|
||||
src.shift_line
|
||||
break
|
||||
else
|
||||
lines.push src.shift_line
|
||||
end
|
||||
else
|
||||
if src.cur_line =~ OpenDiv
|
||||
divs_open += 1
|
||||
end
|
||||
lines.push src.shift_line
|
||||
end
|
||||
end
|
||||
|
||||
context.push doc.md_div(children, al)
|
||||
true
|
||||
})
|
||||
|
||||
if divs_open > 0
|
||||
doc.maruku_error("At end of input, I still have #{divs_open} DIVs open.",
|
||||
src, context)
|
||||
next true
|
||||
end
|
||||
end
|
||||
|
||||
module MaRuKu; class MDElement
|
||||
ial_at_beginning = nil unless ial_at_beginning && ial_at_beginning.size > 0
|
||||
ial_at_end = nil unless ial_at_end && ial_at_end.size > 0
|
||||
|
||||
def md_div(children, al=nil)
|
||||
type = label = num = nil
|
||||
doc.refid2ref ||= {}
|
||||
if al
|
||||
al.each do |k, v|
|
||||
case k
|
||||
when :class
|
||||
type = $1 if v =~ /^num_(\w*)/
|
||||
when :id
|
||||
label = v
|
||||
end
|
||||
end
|
||||
end
|
||||
if type
|
||||
doc.refid2ref[type] ||= {}
|
||||
num = doc.refid2ref[type].length + 1 || 1
|
||||
end
|
||||
e = self.md_el(:div, children, meta={:label => label, :type => type, :num => num}, al)
|
||||
if type && label
|
||||
doc.refid2ref[type].update({label => e})
|
||||
end
|
||||
e
|
||||
end
|
||||
|
||||
end end
|
||||
if ial_at_beginning && ial_at_end
|
||||
doc.maruku_error("Found two conflicting IALs: #{ial_at_beginning.inspect} and #{ial_at_end.inspect}",
|
||||
src, context)
|
||||
end
|
||||
|
||||
al_string = ial_at_beginning || ial_at_end
|
||||
al = nil
|
||||
|
||||
module MaRuKu; module Out; module HTML
|
||||
if al_string =~ /^\{(.*)\}\s*$/
|
||||
al = al_string && doc.read_attribute_list(
|
||||
MaRuKu::In::Markdown::SpanLevelParser::CharSource.new($1),
|
||||
nil, [nil])
|
||||
end
|
||||
|
||||
def to_html_div
|
||||
add_ws wrap_as_element('div')
|
||||
end
|
||||
|
||||
end end end
|
||||
context.push(
|
||||
doc.md_div(
|
||||
doc.parse_blocks(
|
||||
MaRuKu::In::Markdown::BlockLevelParser::LineSource.new(lines)),
|
||||
al))
|
||||
true
|
||||
end)
|
||||
|
||||
module MaRuKu
|
||||
class MDElement
|
||||
def md_div(children, al = nil)
|
||||
type = label = num = nil
|
||||
doc.refid2ref ||= {}
|
||||
if al
|
||||
al.each do |k, v|
|
||||
case k
|
||||
when :class; type = $1 if v =~ /^num_(\w*)/
|
||||
when :id; label = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if type
|
||||
doc.refid2ref[type] ||= {}
|
||||
num = doc.refid2ref[type].length + 1
|
||||
end
|
||||
|
||||
e = self.md_el(:div, children, {:label => label, :type => type, :num => num}, al)
|
||||
doc.refid2ref[type].update(label => e) if type && label
|
||||
e
|
||||
end
|
||||
end
|
||||
|
||||
module Out
|
||||
module HTML
|
||||
def to_html_div
|
||||
add_ws wrap_as_element('div')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
4
vendor/plugins/maruku/lib/maruku/ext/math.rb
vendored
4
vendor/plugins/maruku/lib/maruku/ext/math.rb
vendored
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
require 'maruku/ext/math/elements'
|
||||
require 'maruku/ext/math/parsing'
|
||||
require 'maruku/ext/math/to_latex'
|
||||
|
@ -10,7 +8,6 @@ require 'maruku/ext/math/mathml_engines/ritex'
|
|||
require 'maruku/ext/math/mathml_engines/itex2mml'
|
||||
require 'maruku/ext/math/mathml_engines/blahtex'
|
||||
|
||||
|
||||
=begin maruku_doc
|
||||
Attribute: math_enabled
|
||||
Scope: global, document
|
||||
|
@ -37,5 +34,4 @@ Array containing any of `'\\['`, `'\\begin{equation}'`, `'$$'`.
|
|||
|
||||
=end
|
||||
|
||||
|
||||
MaRuKu::Globals[:math_numbered] = []
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
module MaRuKu; class MDElement
|
||||
|
||||
def md_inline_math(math)
|
||||
self.md_el(:inline_math, [], meta={:math=>math})
|
||||
end
|
||||
module MaRuKu
|
||||
class MDElement
|
||||
def md_inline_math(math)
|
||||
self.md_el(:inline_math, [], :math => math)
|
||||
end
|
||||
|
||||
def md_equation(math, label, numerate)
|
||||
reglabel= /\\label\{(\w+)\}/
|
||||
if math =~ reglabel
|
||||
label = $1
|
||||
math.gsub!(reglabel,'')
|
||||
end
|
||||
# puts "Found label = #{label} math #{math.inspect} "
|
||||
num = nil
|
||||
if (label || numerate) && @doc #take number
|
||||
@doc.eqid2eq ||= {}
|
||||
num = @doc.eqid2eq.size + 1
|
||||
label = "eq#{num}" if not label # FIXME do id for document
|
||||
end
|
||||
e = self.md_el(:equation, [], meta={:math=>math, :label=>label,:num=>num})
|
||||
if label && @doc #take number
|
||||
@doc.eqid2eq[label] = e
|
||||
end
|
||||
e
|
||||
end
|
||||
|
||||
end end
|
||||
def md_equation(math, label, numerate)
|
||||
reglabel = /\\label\{(\w+)\}/
|
||||
math = math.gsub(reglabel, '') if label = math[reglabel, 1]
|
||||
num = nil
|
||||
if (label || numerate) && @doc # take number
|
||||
@doc.eqid2eq ||= {}
|
||||
num = @doc.eqid2eq.size + 1
|
||||
label = "eq#{num}" if not label # TODO do id for document
|
||||
end
|
||||
e = self.md_el(:equation, [], :math => math, :label => label, :num => num)
|
||||
@doc.eqid2eq[label] = e if label && @doc # take number
|
||||
e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,107 +1,93 @@
|
|||
|
||||
require 'tempfile'
|
||||
require 'fileutils'
|
||||
require 'digest/md5'
|
||||
require 'pstore'
|
||||
|
||||
module MaRuKu; module Out; module HTML
|
||||
|
||||
PNG = Struct.new(:src,:depth,:height)
|
||||
|
||||
def convert_to_png_blahtex(kind, tex)
|
||||
begin
|
||||
FileUtils::mkdir_p get_setting(:html_png_dir)
|
||||
module MaRuKu
|
||||
module Out
|
||||
module HTML
|
||||
PNG = Struct.new(:src, :depth, :height)
|
||||
|
||||
# first, we check whether this image has already been processed
|
||||
md5sum = Digest::MD5.hexdigest(tex+" params: ")
|
||||
result_file = File.join(get_setting(:html_png_dir), md5sum+".txt")
|
||||
def convert_to_png_blahtex(kind, tex)
|
||||
FileUtils.mkdir_p get_setting(:html_png_dir)
|
||||
|
||||
if not File.exists?(result_file)
|
||||
tmp_in = Tempfile.new('maruku_blahtex')
|
||||
f = tmp_in.open
|
||||
f.write tex
|
||||
f.close
|
||||
# first, we check whether this image has already been processed
|
||||
md5sum = Digest::MD5.hexdigest(tex + " params: ")
|
||||
result_file = File.join(get_setting(:html_png_dir), md5sum + ".txt")
|
||||
|
||||
resolution = get_setting(:html_png_resolution)
|
||||
if not File.exists?(result_file)
|
||||
Tempfile.open('maruku_blahtex') do |tmp_in|
|
||||
tmp_in.write tex
|
||||
tmp_in.close
|
||||
|
||||
options = "--png --use-preview-package --shell-dvipng 'dvipng -D #{resolution}' "
|
||||
options += "--displaymath " if kind == :equation
|
||||
options += ("--temp-directory '%s' " % get_setting(:html_png_dir))
|
||||
options += ("--png-directory '%s'" % get_setting(:html_png_dir))
|
||||
# It's important taht we don't replace *all* newlines,
|
||||
# because newlines in arguments get escaped as "'\n'".
|
||||
system <<COMMAND.gsub("\n ", " ")
|
||||
blahtex --png --use-preview-package
|
||||
--shell-dvipng #{shellescape("dvipng -D #{shellescape(get_setting(:html_png_resolution).to_s)}")}
|
||||
#{'--displaymath' if kind == :equation}
|
||||
--temp-directory #{shellescape(get_setting(:html_png_dir))}
|
||||
--png-directory #{shellescape(get_setting(:html_png_dir))}
|
||||
< #{shellescape(tmp_in.path)}
|
||||
> #{shellescape(result_file)}
|
||||
COMMAND
|
||||
end
|
||||
end
|
||||
|
||||
cmd = "blahtex #{options} < #{tmp_in.path} > #{result_file}"
|
||||
#$stderr.puts "$ #{cmd}"
|
||||
system cmd
|
||||
tmp_in.delete
|
||||
end
|
||||
|
||||
result = File.read(result_file)
|
||||
if result.nil? || result.empty?
|
||||
raise "Blahtex error: empty output"
|
||||
result = File.read(result_file)
|
||||
if result.nil? || result.empty?
|
||||
maruku_error "Blahtex error: empty output"
|
||||
return
|
||||
end
|
||||
|
||||
doc = Document.new(result, :respect_whitespace => :all)
|
||||
png = doc.root.elements[1]
|
||||
if png.name != 'png'
|
||||
maruku_error "Blahtex error: \n#{doc}"
|
||||
return
|
||||
end
|
||||
|
||||
raise "No depth element in:\n #{doc}" unless depth = png.elements['depth']
|
||||
raise "No height element in:\n #{doc}" unless height = png.elements['height']
|
||||
raise "No md5 element in:\n #{doc}" unless md5 = png.elements['md5']
|
||||
|
||||
depth = depth.text.to_f
|
||||
height = height.text.to_f # TODO: check != 0
|
||||
md5 = md5.text
|
||||
|
||||
PNG.new("#{get_setting(:html_png_url)}#{md5}.png", depth, height)
|
||||
rescue Exception => e
|
||||
maruku_error "Error: #{e}"
|
||||
end
|
||||
|
||||
doc = Document.new(result, {:respect_whitespace =>:all})
|
||||
png = doc.root.elements[1]
|
||||
if png.name != 'png'
|
||||
raise "Blahtex error: \n#{doc}"
|
||||
end
|
||||
depth = png.elements['depth'] || (raise "No depth element in:\n #{doc}")
|
||||
height = png.elements['height'] || (raise "No height element in:\n #{doc}")
|
||||
md5 = png.elements['md5'] || (raise "No md5 element in:\n #{doc}")
|
||||
|
||||
depth = depth.text.to_f
|
||||
height = height.text.to_f # XXX check != 0
|
||||
md5 = md5.text
|
||||
|
||||
dir_url = get_setting(:html_png_url)
|
||||
return PNG.new("#{dir_url}#{md5}.png", depth, height)
|
||||
rescue Exception => e
|
||||
maruku_error "Error: #{e}"
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
|
||||
def convert_to_mathml_blahtex(kind, tex)
|
||||
@@BlahtexCache = PStore.new(get_setting(:latex_cache_file))
|
||||
|
||||
begin
|
||||
@@BlahtexCache.transaction do
|
||||
if @@BlahtexCache[tex].nil?
|
||||
tmp_in = Tempfile.new('maruku_blahtex')
|
||||
f = tmp_in.open
|
||||
f.write tex
|
||||
f.close
|
||||
tmp_out = Tempfile.new('maruku_blahtex')
|
||||
|
||||
options = "--mathml"
|
||||
cmd = "blahtex #{options} < #{tmp_in.path} > #{tmp_out.path}"
|
||||
#$stderr.puts "$ #{cmd}"
|
||||
system cmd
|
||||
tmp_in.delete
|
||||
|
||||
result = nil
|
||||
File.open(tmp_out.path) do |f| result=f.read end
|
||||
puts result
|
||||
|
||||
@@BlahtexCache[tex] = result
|
||||
end
|
||||
|
||||
blahtex = @@BlahtexCache[tex]
|
||||
doc = Document.new(blahtex, {:respect_whitespace =>:all})
|
||||
mathml = doc.root.elements['mathml']
|
||||
if not mathml
|
||||
maruku_error "Blahtex error: \n#{doc}"
|
||||
return nil
|
||||
else
|
||||
return mathml
|
||||
end
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
maruku_error "Error: #{e}"
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
end end end
|
||||
def convert_to_mathml_blahtex(kind, tex)
|
||||
@@BlahtexCache ||= PStore.new(get_setting(:latex_cache_file))
|
||||
|
||||
@@BlahtexCache.transaction do
|
||||
if @@BlahtexCache[tex].nil?
|
||||
Tempfile.open('maruku_blahtex') do |tmp_in|
|
||||
tmp_in.write tex
|
||||
|
||||
Tempfile.new('maruku_blahtex') do |tmp_out|
|
||||
system "blahtex --mathml < #{shellescape(tmp_in.path)} > #{shellescape(tmp_out.path)}"
|
||||
@@BlahtexCache[tex] = tmp_out.read
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
blahtex = @@BlahtexCache[tex]
|
||||
doc = Document.new(blahtex, :respect_whitespace => :all)
|
||||
unless mathml = doc.root.elements['mathml']
|
||||
maruku_error "Blahtex error: \n#{doc}"
|
||||
return
|
||||
end
|
||||
|
||||
return mathml
|
||||
end
|
||||
rescue Exception => e
|
||||
maruku_error "Error: #{e}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,30 +1,34 @@
|
|||
module MaRuKu
|
||||
module Out
|
||||
module HTML
|
||||
def convert_to_mathml_itex2mml(kind, tex)
|
||||
return if $already_warned_itex2mml
|
||||
require 'itextomml'
|
||||
require 'stringsupport'
|
||||
|
||||
module MaRuKu; module Out; module HTML
|
||||
parser = Itex2MML::Parser.new
|
||||
mathml =
|
||||
case kind
|
||||
when :equation; parser.block_filter(tex)
|
||||
when :inline; parser.inline_filter(tex)
|
||||
else
|
||||
maruku_error "Unknown itex2mml kind: #{kind}"
|
||||
return
|
||||
end
|
||||
|
||||
def convert_to_mathml_itex2mml(kind, tex)
|
||||
begin
|
||||
if not $itex2mml_parser
|
||||
require 'stringsupport'
|
||||
require 'itextomml'
|
||||
$itex2mml_parser = Itex2MML::Parser.new
|
||||
end
|
||||
|
||||
itex_method = {:equation=>:block_filter,:inline=>:inline_filter}
|
||||
|
||||
mathml = $itex2mml_parser.send(itex_method[kind], tex).to_utf8
|
||||
doc = Document.new(mathml, {:respect_whitespace =>:all}).root
|
||||
return doc
|
||||
rescue LoadError => e
|
||||
maruku_error "Could not load package 'itex2mml'.\n"+ "Please install it." unless $already_warned_itex2mml
|
||||
$already_warned_itex2mml = true
|
||||
rescue REXML::ParseException => e
|
||||
maruku_error "Invalid MathML TeX: \n#{add_tabs(tex,1,'tex>')}"+
|
||||
"\n\n #{e.inspect}"
|
||||
rescue
|
||||
maruku_error "Could not produce MathML TeX: \n#{tex}"+
|
||||
"\n\n #{e.inspect}"
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
end end end
|
||||
return Document.new(mathml.to_utf8, :respect_whitespace => :all).root
|
||||
rescue LoadError => e
|
||||
# TODO: Properly scope this global
|
||||
maruku_error "Could not load package 'itex2mml'.\nPlease install it." unless $already_warned_itex2mml
|
||||
$already_warned_itex2mml = true
|
||||
nil
|
||||
rescue REXML::ParseException => e
|
||||
maruku_error "Invalid MathML TeX: \n#{tex.gsub(/^/, 'tex>')}\n\n #{e.inspect}"
|
||||
nil
|
||||
rescue
|
||||
maruku_error "Could not produce MathML TeX: \n#{tex}\n\n #{e.inspect}"
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
218
vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb
vendored
218
vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb
vendored
|
@ -1,119 +1,111 @@
|
|||
module MaRuKu
|
||||
|
||||
class MDDocument
|
||||
# Hash equation id (String) to equation element (MDElement)
|
||||
attr_accessor :eqid2eq
|
||||
|
||||
def is_math_enabled?
|
||||
get_setting :math_enabled
|
||||
end
|
||||
end
|
||||
class MDDocument
|
||||
# A hash of equation ids to equation elements
|
||||
#
|
||||
# @return [String => MDElement]
|
||||
attr_accessor :eqid2eq
|
||||
|
||||
def is_math_enabled?
|
||||
get_setting :math_enabled
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Properly scope all these regexps
|
||||
# Everything goes; takes care of escaping the "\$" inside the expression
|
||||
RegInlineMath = /\${1}((?:[^\$]|\\\$)+)\$/
|
||||
|
||||
# Everything goes; takes care of escaping the "\$" inside the expression
|
||||
RegInlineMath = /\${1}((?:[^\$]|\\\$)+)\$/
|
||||
|
||||
MaRuKu::In::Markdown::register_span_extension(
|
||||
:chars => ?$,
|
||||
:regexp => RegInlineMath,
|
||||
:handler => lambda { |doc, src, con|
|
||||
return false if not doc.is_math_enabled?
|
||||
|
||||
if m = src.read_regexp(RegInlineMath)
|
||||
math = m.captures.compact.first
|
||||
con.push doc.md_inline_math(math)
|
||||
true
|
||||
else
|
||||
#puts "not math: #{src.cur_chars 10}"
|
||||
false
|
||||
end
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
MathOpen1 = Regexp.escape('\\begin{equation}')
|
||||
MathClose1 = Regexp.escape('\\end{equation}')
|
||||
MathOpen2 = Regexp.escape('\\[')
|
||||
MathClose2 = Regexp.escape('\\]')
|
||||
MathOpen3 = Regexp.escape('$$')
|
||||
MathClose3 = Regexp.escape('$$')
|
||||
|
||||
EqLabel = /(?:\((\w+)\))/
|
||||
EquationOpen = /#{MathOpen1}|#{MathOpen2}|#{MathOpen3}/
|
||||
EquationClose = /#{MathClose1}|#{MathClose2}|#{MathClose3}/
|
||||
|
||||
# $1 is opening, $2 is tex
|
||||
EquationStart = /^[ ]{0,3}(#{EquationOpen})(.*)$/
|
||||
# $1 is tex, $2 is closing, $3 is tex
|
||||
EquationEnd = /^(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
||||
# $1 is opening, $2 is tex, $3 is closing, $4 is label
|
||||
OneLineEquation = /^[ ]{0,3}(#{EquationOpen})(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
||||
MaRuKu::In::Markdown.register_span_extension(
|
||||
:chars => ?$,
|
||||
:regexp => RegInlineMath,
|
||||
:handler => lambda do |doc, src, con|
|
||||
next false unless doc.is_math_enabled?
|
||||
next false unless m = src.read_regexp(RegInlineMath)
|
||||
math = m.captures.compact.first
|
||||
con.push doc.md_inline_math(math)
|
||||
true
|
||||
end)
|
||||
|
||||
MaRuKu::In::Markdown::register_block_extension(
|
||||
:regexp => EquationStart,
|
||||
:handler => lambda { |doc, src, con|
|
||||
return false if not doc.is_math_enabled?
|
||||
first = src.shift_line
|
||||
if first =~ OneLineEquation
|
||||
opening, tex, closing, label = $1, $2, $3, $4
|
||||
numerate = doc.get_setting(:math_numbered).include?(opening)
|
||||
con.push doc.md_equation(tex, label, numerate)
|
||||
else
|
||||
first =~ EquationStart
|
||||
opening, tex = $1, $2
|
||||
|
||||
numerate = doc.get_setting(:math_numbered).include?(opening)
|
||||
label = nil
|
||||
while true
|
||||
if not src.cur_line
|
||||
doc.maruku_error("Stream finished while reading equation\n\n"+
|
||||
doc.add_tabs(tex,1,'$> '), src, con)
|
||||
break
|
||||
end
|
||||
line = src.shift_line
|
||||
if line =~ EquationEnd
|
||||
tex_line, closing = $1, $2
|
||||
label = $3 if $3
|
||||
tex += tex_line + "\n"
|
||||
break
|
||||
else
|
||||
tex += line + "\n"
|
||||
end
|
||||
end
|
||||
con.push doc.md_equation(tex, label, numerate)
|
||||
end
|
||||
true
|
||||
})
|
||||
|
||||
|
||||
# This adds support for \eqref
|
||||
RegEqrefLatex = /\\eqref\{(\w+)\}/
|
||||
RegEqPar = /\(eq:(\w+)\)/
|
||||
RegEqref = Regexp::union(RegEqrefLatex, RegEqPar)
|
||||
|
||||
MaRuKu::In::Markdown::register_span_extension(
|
||||
:chars => [?\\, ?(],
|
||||
:regexp => RegEqref,
|
||||
:handler => lambda { |doc, src, con|
|
||||
return false if not doc.is_math_enabled?
|
||||
eqid = src.read_regexp(RegEqref).captures.compact.first
|
||||
r = doc.md_el(:eqref, [], meta={:eqid=>eqid})
|
||||
con.push r
|
||||
true
|
||||
}
|
||||
)
|
||||
|
||||
# This adds support for \ref
|
||||
RegRef = /\\ref\{(\w*)\}/
|
||||
MaRuKu::In::Markdown::register_span_extension(
|
||||
:chars => [?\\, ?(],
|
||||
:regexp => RegRef,
|
||||
:handler => lambda { |doc, src, con|
|
||||
return false if not doc.is_math_enabled?
|
||||
refid = src.read_regexp(RegRef).captures.compact.first
|
||||
r = doc.md_el(:divref, [], meta={:refid=>refid})
|
||||
con.push r
|
||||
true
|
||||
}
|
||||
)
|
||||
MathOpen1 = Regexp.escape('\\begin{equation}')
|
||||
MathClose1 = Regexp.escape('\\end{equation}')
|
||||
MathOpen2 = Regexp.escape('\\[')
|
||||
MathClose2 = Regexp.escape('\\]')
|
||||
MathOpen3 = Regexp.escape('$$')
|
||||
MathClose3 = Regexp.escape('$$')
|
||||
|
||||
EqLabel = /(?:\((\w+)\))/
|
||||
EquationOpen = /#{MathOpen1}|#{MathOpen2}|#{MathOpen3}/
|
||||
EquationClose = /#{MathClose1}|#{MathClose2}|#{MathClose3}/
|
||||
|
||||
# $1 is opening, $2 is tex
|
||||
EquationStart = /^[ ]{0,3}(#{EquationOpen})(.*)$/
|
||||
# $1 is tex, $2 is closing, $3 is tex
|
||||
EquationEnd = /^(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
||||
# $1 is opening, $2 is tex, $3 is closing, $4 is label
|
||||
OneLineEquation = /^[ ]{0,3}(#{EquationOpen})(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
||||
|
||||
MaRuKu::In::Markdown.register_block_extension(
|
||||
:regexp => EquationStart,
|
||||
:handler => lambda do |doc, src, con|
|
||||
next false unless doc.is_math_enabled?
|
||||
first = src.shift_line
|
||||
if first =~ OneLineEquation
|
||||
opening, tex, closing, label = $1, $2, $3, $4
|
||||
numerate = doc.get_setting(:math_numbered).include?(opening)
|
||||
con.push doc.md_equation(tex, label, numerate)
|
||||
next true
|
||||
end
|
||||
|
||||
opening, tex = first.scan(EquationStart).first
|
||||
numerate = doc.get_setting(:math_numbered).include?(opening)
|
||||
label = nil
|
||||
loop do
|
||||
unless src.cur_line
|
||||
doc.maruku_error(
|
||||
"Stream finished while reading equation\n\n" + tex.gsub(/^/, '$> '),
|
||||
src, con)
|
||||
break
|
||||
end
|
||||
|
||||
line = src.shift_line
|
||||
if line =~ EquationEnd
|
||||
tex_line, closing = $1, $2
|
||||
label = $3 if $3
|
||||
tex << tex_line << "\n"
|
||||
break
|
||||
end
|
||||
|
||||
tex << line << "\n"
|
||||
end
|
||||
con.push doc.md_equation(tex, label, numerate)
|
||||
true
|
||||
end)
|
||||
|
||||
|
||||
# This adds support for \eqref
|
||||
RegEqrefLatex = /\\eqref\{(\w+)\}/
|
||||
RegEqPar = /\(eq:(\w+)\)/
|
||||
RegEqref = Regexp.union(RegEqrefLatex, RegEqPar)
|
||||
|
||||
MaRuKu::In::Markdown.register_span_extension(
|
||||
:chars => [?\\, ?(],
|
||||
:regexp => RegEqref,
|
||||
:handler => lambda do |doc, src, con|
|
||||
return false unless doc.is_math_enabled?
|
||||
eqid = src.read_regexp(RegEqref).captures.compact.first
|
||||
con.push doc.md_el(:eqref, [], :eqid => eqid)
|
||||
true
|
||||
end)
|
||||
|
||||
# This adds support for \ref
|
||||
RegRef = /\\ref\{(\w*)\}/
|
||||
MaRuKu::In::Markdown.register_span_extension(
|
||||
:chars => [?\\, ?(],
|
||||
:regexp => RegRef,
|
||||
:handler => lambda do |doc, src, con|
|
||||
return false unless doc.is_math_enabled?
|
||||
refid = src.read_regexp(RegRef).captures.compact.first
|
||||
con.push doc.md_el(:divref, [], :refid => refid)
|
||||
true
|
||||
end)
|
||||
|
|
303
vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb
vendored
303
vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb
vendored
|
@ -1,4 +1,3 @@
|
|||
|
||||
=begin maruku_doc
|
||||
Extension: math
|
||||
Attribute: html_math_engine
|
||||
|
@ -11,14 +10,14 @@ Select the rendering engine for math.
|
|||
|
||||
If you want to use your custom engine `foo`, then set:
|
||||
|
||||
HTML math engine: foo
|
||||
HTML math engine: foo
|
||||
{:lang=markdown}
|
||||
|
||||
and then implement two functions:
|
||||
|
||||
def convert_to_mathml_foo(kind, tex)
|
||||
...
|
||||
end
|
||||
def convert_to_mathml_foo(kind, tex)
|
||||
...
|
||||
end
|
||||
=end
|
||||
|
||||
=begin maruku_doc
|
||||
|
@ -31,165 +30,159 @@ Default: <?mrk Globals[:html_math_engine].to_s ?>
|
|||
|
||||
Same thing as `html_math_engine`, only for PNG output.
|
||||
|
||||
def convert_to_png_foo(kind, tex)
|
||||
# same thing
|
||||
...
|
||||
end
|
||||
def convert_to_png_foo(kind, tex)
|
||||
# same thing
|
||||
...
|
||||
end
|
||||
{:lang=ruby}
|
||||
|
||||
=end
|
||||
|
||||
module MaRuKu; module Out; module HTML
|
||||
module MaRuKu
|
||||
module Out
|
||||
module HTML
|
||||
# Creates an xml Mathml document of this node's TeX code.
|
||||
#
|
||||
# @return [REXML::Document]
|
||||
def render_mathml(kind, tex)
|
||||
engine = get_setting(:html_math_engine)
|
||||
method = "convert_to_mathml_#{engine}"
|
||||
if self.respond_to? method
|
||||
mathml = self.send(method, kind, tex)
|
||||
return mathml || convert_to_mathml_none(kind, tex)
|
||||
end
|
||||
|
||||
# TODO: Warn here
|
||||
puts "A method called #{method} should be defined."
|
||||
return convert_to_mathml_none(kind, tex)
|
||||
end
|
||||
|
||||
|
||||
# Creates an xml Mathml document of self.math
|
||||
def render_mathml(kind, tex)
|
||||
engine = get_setting(:html_math_engine)
|
||||
method = "convert_to_mathml_#{engine}".to_sym
|
||||
if self.respond_to? method
|
||||
mathml = self.send(method, kind, tex)
|
||||
return mathml || convert_to_mathml_none(kind, tex)
|
||||
else
|
||||
puts "A method called #{method} should be defined."
|
||||
return convert_to_mathml_none(kind, tex)
|
||||
end
|
||||
end
|
||||
# Renders a PNG image of this node's TeX code.
|
||||
# Returns
|
||||
#
|
||||
# @return [MaRuKu::Out::HTML::PNG, nil]
|
||||
# A struct describing the location and size of the image,
|
||||
# or nil if no library is loaded that can render PNGs.
|
||||
def render_png(kind, tex)
|
||||
engine = get_setting(:html_png_engine)
|
||||
method = "convert_to_png_#{engine}".to_sym
|
||||
return self.send(method, kind, tex) if self.respond_to? method
|
||||
|
||||
# Creates an xml Mathml document of self.math
|
||||
def render_png(kind, tex)
|
||||
engine = get_setting(:html_png_engine)
|
||||
method = "convert_to_png_#{engine}".to_sym
|
||||
if self.respond_to? method
|
||||
return self.send(method, kind, tex)
|
||||
else
|
||||
puts "A method called #{method} should be defined."
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def pixels_per_ex
|
||||
if not $pixels_per_ex
|
||||
x = render_png(:inline, "x")
|
||||
$pixels_per_ex = x.height # + x.depth
|
||||
end
|
||||
$pixels_per_ex
|
||||
end
|
||||
|
||||
def adjust_png(png, use_depth)
|
||||
src = png.src
|
||||
|
||||
height_in_px = png.height
|
||||
depth_in_px = png.depth
|
||||
height_in_ex = height_in_px / pixels_per_ex
|
||||
depth_in_ex = depth_in_px / pixels_per_ex
|
||||
total_height_in_ex = height_in_ex + depth_in_ex
|
||||
style = ""
|
||||
style += "vertical-align: -#{depth_in_ex}ex;" if use_depth
|
||||
style += "height: #{total_height_in_ex}ex;"
|
||||
img = Element.new 'img'
|
||||
img.attributes['src'] = src
|
||||
img.attributes['style'] = style
|
||||
img.attributes['alt'] = "$#{self.math.strip}$"
|
||||
img
|
||||
end
|
||||
|
||||
def to_html_inline_math
|
||||
mathml = get_setting(:html_math_output_mathml) && render_mathml(:inline, self.math)
|
||||
png = get_setting(:html_math_output_png) && render_png(:inline, self.math)
|
||||
puts "A method called #{method} should be defined."
|
||||
return nil
|
||||
end
|
||||
|
||||
span = create_html_element 'span'
|
||||
add_class_to(span, 'maruku-inline')
|
||||
|
||||
if mathml
|
||||
add_class_to(mathml, 'maruku-mathml')
|
||||
return mathml
|
||||
end
|
||||
|
||||
if png
|
||||
img = adjust_png(png, use_depth=true)
|
||||
add_class_to(img, 'maruku-png')
|
||||
span << img
|
||||
end
|
||||
span
|
||||
|
||||
end
|
||||
def pixels_per_ex
|
||||
$pixels_per_ex ||= render_png(:inline, "x").height
|
||||
end
|
||||
|
||||
def to_html_equation
|
||||
mathml = get_setting(:html_math_output_mathml) && render_mathml(:equation, self.math)
|
||||
png = get_setting(:html_math_output_png) && render_png(:equation, self.math)
|
||||
|
||||
div = create_html_element 'div'
|
||||
add_class_to(div, 'maruku-equation')
|
||||
if mathml
|
||||
if self.label # then numerate
|
||||
span = Element.new 'span'
|
||||
span.attributes['class'] = 'maruku-eq-number'
|
||||
num = self.num
|
||||
span << Text.new("(#{num})")
|
||||
div << span
|
||||
div.attributes['id'] = "eq:#{self.label}"
|
||||
end
|
||||
add_class_to(mathml, 'maruku-mathml')
|
||||
div << mathml
|
||||
end
|
||||
|
||||
if png
|
||||
img = adjust_png(png, use_depth=false)
|
||||
add_class_to(img, 'maruku-png')
|
||||
div << img
|
||||
if self.label # then numerate
|
||||
span = Element.new 'span'
|
||||
span.attributes['class'] = 'maruku-eq-number'
|
||||
num = self.num
|
||||
span << Text.new("(#{num})")
|
||||
div << span
|
||||
div.attributes['id'] = "eq:#{self.label}"
|
||||
end
|
||||
end
|
||||
|
||||
source_span = Element.new 'span'
|
||||
add_class_to(source_span, 'maruku-eq-tex')
|
||||
code = convert_to_mathml_none(:equation, self.math.strip)
|
||||
code.attributes['style'] = 'display: none'
|
||||
source_span << code
|
||||
div << source_span
|
||||
|
||||
div
|
||||
end
|
||||
|
||||
def to_html_eqref
|
||||
if eq = self.doc.eqid2eq[self.eqid]
|
||||
num = eq.num
|
||||
a = Element.new 'a'
|
||||
a.attributes['class'] = 'maruku-eqref'
|
||||
a.attributes['href'] = "#eq:#{self.eqid}"
|
||||
a << Text.new("(#{num})")
|
||||
a
|
||||
else
|
||||
maruku_error "Cannot find equation #{self.eqid.inspect}"
|
||||
Text.new "(eq:#{self.eqid})"
|
||||
end
|
||||
end
|
||||
def adjust_png(png, use_depth)
|
||||
src = png.src
|
||||
|
||||
def to_html_divref
|
||||
ref= nil
|
||||
self.doc.refid2ref.each_value { |h|
|
||||
ref = h[self.refid] if h.has_key?(self.refid)
|
||||
}
|
||||
if ref
|
||||
num = ref.num
|
||||
a = Element.new 'a'
|
||||
a.attributes['class'] = 'maruku-ref'
|
||||
a.attributes['href'] = "#" + self.refid
|
||||
a << Text.new(num.to_s)
|
||||
a
|
||||
else
|
||||
maruku_error "Cannot find div #{self.refid.inspect}"
|
||||
Text.new "\\ref{#{self.refid}}"
|
||||
end
|
||||
end
|
||||
|
||||
end end end
|
||||
height_in_px = png.height
|
||||
depth_in_px = png.depth
|
||||
height_in_ex = height_in_px / pixels_per_ex
|
||||
depth_in_ex = depth_in_px / pixels_per_ex
|
||||
total_height_in_ex = height_in_ex + depth_in_ex
|
||||
style = ""
|
||||
style << "vertical-align: -#{depth_in_ex}ex;" if use_depth
|
||||
style << "height: #{total_height_in_ex}ex;"
|
||||
|
||||
img = Element.new 'img'
|
||||
img.attributes['src'] = src
|
||||
img.attributes['style'] = style
|
||||
img.attributes['alt'] = "$#{self.math.strip}$"
|
||||
img
|
||||
end
|
||||
|
||||
def to_html_inline_math
|
||||
mathml = get_setting(:html_math_output_mathml) && render_mathml(:inline, self.math)
|
||||
png = get_setting(:html_math_output_png) && render_png(:inline, self.math)
|
||||
|
||||
span = create_html_element 'span'
|
||||
add_class_to(span, 'maruku-inline')
|
||||
|
||||
if mathml
|
||||
add_class_to(mathml, 'maruku-mathml')
|
||||
return mathml
|
||||
end
|
||||
|
||||
if png
|
||||
img = adjust_png(png, true)
|
||||
add_class_to(img, 'maruku-png')
|
||||
span << img
|
||||
end
|
||||
|
||||
span
|
||||
end
|
||||
|
||||
def to_html_equation
|
||||
mathml = get_setting(:html_math_output_mathml) && render_mathml(:equation, self.math)
|
||||
png = get_setting(:html_math_output_png) && render_png(:equation, self.math)
|
||||
|
||||
div = create_html_element 'div'
|
||||
add_class_to(div, 'maruku-equation')
|
||||
if mathml
|
||||
if self.label # then numerate
|
||||
span = Element.new 'span'
|
||||
span.attributes['class'] = 'maruku-eq-number'
|
||||
span << Text.new("(#{self.num})")
|
||||
div << span
|
||||
div.attributes['id'] = "eq:#{self.label}"
|
||||
end
|
||||
add_class_to(mathml, 'maruku-mathml')
|
||||
div << mathml
|
||||
end
|
||||
|
||||
if png
|
||||
img = adjust_png(png, false)
|
||||
add_class_to(img, 'maruku-png')
|
||||
div << img
|
||||
if self.label # then numerate
|
||||
span = Element.new 'span'
|
||||
span.attributes['class'] = 'maruku-eq-number'
|
||||
span << Text.new("(#{self.num})")
|
||||
div << span
|
||||
div.attributes['id'] = "eq:#{self.label}"
|
||||
end
|
||||
end
|
||||
|
||||
source_span = Element.new 'span'
|
||||
add_class_to(source_span, 'maruku-eq-tex')
|
||||
code = convert_to_mathml_none(:equation, self.math.strip)
|
||||
code.attributes['style'] = 'display: none'
|
||||
source_span << code
|
||||
div << source_span
|
||||
|
||||
div
|
||||
end
|
||||
|
||||
def to_html_eqref
|
||||
unless eq = self.doc.eqid2eq[self.eqid]
|
||||
maruku_error "Cannot find equation #{self.eqid.inspect}"
|
||||
return Text.new("(eq:#{self.eqid})")
|
||||
end
|
||||
|
||||
a = Element.new 'a'
|
||||
a.attributes['class'] = 'maruku-eqref'
|
||||
a.attributes['href'] = "#eq:#{self.eqid}"
|
||||
a << Text.new("(#{eq.num})")
|
||||
a
|
||||
end
|
||||
|
||||
def to_html_divref
|
||||
unless hash = self.doc.refid2ref.values.find {|h| h.has_key?(self.refid)}
|
||||
maruku_error "Cannot find div #{self.refid.inspect}"
|
||||
return Text.new("\\ref{#{self.refid}}")
|
||||
end
|
||||
ref= hash[self.refid]
|
||||
|
||||
a = Element.new 'a'
|
||||
a.attributes['class'] = 'maruku-ref'
|
||||
a.attributes['href'] = "#" + self.refid
|
||||
a << Text.new(ref.num.to_s)
|
||||
a
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,26 +1,36 @@
|
|||
require 'maruku/ext/math/latex_fix'
|
||||
|
||||
module MaRuKu; module Out; module Latex
|
||||
module MaRuKu
|
||||
module Out
|
||||
module Latex
|
||||
def to_latex_inline_math
|
||||
fix_latex("$#{self.math.strip}$")
|
||||
end
|
||||
|
||||
def to_latex_inline_math
|
||||
"$#{self.math.strip}$".fix_latex
|
||||
end
|
||||
def to_latex_equation
|
||||
if self.label
|
||||
fix_latex("\\begin{equation}\n#{self.math.strip}\n\\label{#{self.label}}\\end{equation}\n")
|
||||
else
|
||||
fix_latex("\\begin{displaymath}\n#{self.math.strip}\n\\end{displaymath}\n")
|
||||
end
|
||||
end
|
||||
|
||||
def to_latex_equation
|
||||
if self.label
|
||||
l = "\\label{#{self.label}}"
|
||||
"\\begin{equation}\n#{self.math.strip}\n#{l}\\end{equation}\n".fix_latex
|
||||
else
|
||||
"\\begin{displaymath}\n#{self.math.strip}\n\\end{displaymath}\n".fix_latex
|
||||
end
|
||||
end
|
||||
|
||||
def to_latex_eqref
|
||||
"\\eqref{#{self.eqid}}"
|
||||
end
|
||||
def to_latex_eqref
|
||||
"\\eqref{#{self.eqid}}"
|
||||
end
|
||||
|
||||
def to_latex_divref
|
||||
"\\ref{#{self.refid}}"
|
||||
end
|
||||
def to_latex_divref
|
||||
"\\ref{#{self.refid}}"
|
||||
end
|
||||
|
||||
end end end
|
||||
private
|
||||
|
||||
def fix_latex(str)
|
||||
return str unless self.get_setting(:html_math_engine) == 'itex2mml'
|
||||
s = str.gsub("\\mathop{", "\\operatorname{")
|
||||
s.gsub!(/\\begin\{svg\}.*?\\end\{svg\}/m, " ")
|
||||
s.gsub("\\space{", "\\itexspace{")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
404
vendor/plugins/maruku/lib/maruku/helpers.rb
vendored
404
vendor/plugins/maruku/lib/maruku/helpers.rb
vendored
|
@ -1,260 +1,214 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
|
||||
|
||||
# A series of helper functions for creating elements: they hide the
|
||||
# particular internal representation.
|
||||
#
|
||||
# Please, always use these instead of creating MDElement.
|
||||
#
|
||||
|
||||
module MaRuKu
|
||||
module Helpers
|
||||
# A collection of helper functions for creating Markdown elements.
|
||||
# They hide the particular internal representations.
|
||||
#
|
||||
# Always use these rather than creating an {MDElement} directly.
|
||||
module Helpers
|
||||
# @param children [Array<MDElement, String>]
|
||||
# The child nodes.
|
||||
# If the first child is a \{#md\_ial}, it's merged with `al`
|
||||
def md_el(node_type, children = [], meta = {}, al = nil)
|
||||
first = children.first
|
||||
if first.is_a?(MDElement) && first.node_type == :ial
|
||||
if al
|
||||
al += first.ial
|
||||
else
|
||||
al = first.ial
|
||||
end
|
||||
children.shift
|
||||
end
|
||||
|
||||
# if the first is a md_ial, it is used as such
|
||||
def md_el(node_type, children=[], meta={}, al=nil)
|
||||
if (e=children.first).kind_of?(MDElement) and
|
||||
e.node_type == :ial then
|
||||
if al
|
||||
al += e.ial
|
||||
else
|
||||
al = e.ial
|
||||
end
|
||||
children.shift
|
||||
end
|
||||
e = MDElement.new(node_type, children, meta, al)
|
||||
e.doc = @doc
|
||||
return e
|
||||
end
|
||||
e = MDElement.new(node_type, children, meta, al)
|
||||
e.doc = @doc
|
||||
e
|
||||
end
|
||||
|
||||
def md_header(level, children, al=nil)
|
||||
md_el(:header, children, {:level => level}, al)
|
||||
end
|
||||
|
||||
# Inline code
|
||||
def md_code(code, al=nil)
|
||||
md_el(:inline_code, [], {:raw_code => code}, al)
|
||||
end
|
||||
def md_header(level, children, al = nil)
|
||||
md_el(:header, children, {:level => level}, al)
|
||||
end
|
||||
|
||||
# Code block
|
||||
def md_codeblock(source, al=nil)
|
||||
md_el(:code, [], {:raw_code => source}, al)
|
||||
end
|
||||
# Inline code
|
||||
def md_code(code, al = nil)
|
||||
md_el(:inline_code, [], {:raw_code => code}, al)
|
||||
end
|
||||
|
||||
def md_quote(children, al=nil)
|
||||
md_el(:quote, children, {}, al)
|
||||
end
|
||||
# Code block
|
||||
def md_codeblock(source, al = nil)
|
||||
md_el(:code, [], {:raw_code => source}, al)
|
||||
end
|
||||
|
||||
def md_li(children, want_my_par, al=nil)
|
||||
md_el(:li, children, {:want_my_paragraph=>want_my_par}, al)
|
||||
end
|
||||
def md_quote(children, al = nil)
|
||||
md_el(:quote, children, {}, al)
|
||||
end
|
||||
|
||||
def md_footnote(footnote_id, children, al=nil)
|
||||
md_el(:footnote, children, {:footnote_id=>footnote_id}, al)
|
||||
end
|
||||
def md_li(children, want_my_par, al = nil)
|
||||
md_el(:li, children, {:want_my_paragraph => want_my_par}, al)
|
||||
end
|
||||
|
||||
def md_abbr_def(abbr, text, al=nil)
|
||||
md_el(:abbr_def, [], {:abbr=>abbr, :text=>text}, al)
|
||||
end
|
||||
def md_footnote(footnote_id, children, al = nil)
|
||||
md_el(:footnote, children, {:footnote_id => footnote_id}, al)
|
||||
end
|
||||
|
||||
def md_abbr(abbr, title)
|
||||
md_el(:abbr, [abbr], {:title=>title})
|
||||
end
|
||||
|
||||
def md_html(raw_html, al=nil)
|
||||
e = md_el(:raw_html, [], {:raw_html=>raw_html})
|
||||
begin
|
||||
# remove newlines and whitespace at begin
|
||||
# end end of string, or else REXML gets confused
|
||||
raw_html = raw_html.gsub(/\A\s*</,'<').
|
||||
gsub(/>[\s\n]*\Z/,'>')
|
||||
|
||||
raw_html = "<marukuwrap>#{raw_html}</marukuwrap>"
|
||||
e.instance_variable_set :@parsed_html,
|
||||
REXML::Document.new(raw_html)
|
||||
rescue REXML::ParseException => ex
|
||||
e.instance_variable_set :@parsed_html, nil
|
||||
maruku_recover "REXML cannot parse this block of HTML/XML:\n"+
|
||||
add_tabs(raw_html,1,'|') + "\n"+ex.inspect
|
||||
# " #{raw_html.inspect}\n\n"+ex.inspect
|
||||
end
|
||||
e
|
||||
end
|
||||
|
||||
def md_link(children, ref_id, al=nil)
|
||||
md_el(:link, children, {:ref_id=>ref_id.downcase}, al)
|
||||
end
|
||||
|
||||
def md_im_link(children, url, title=nil, al=nil)
|
||||
md_el(:im_link, children, {:url=>url,:title=>title}, al)
|
||||
end
|
||||
|
||||
def md_image(children, ref_id, al=nil)
|
||||
md_el(:image, children, {:ref_id=>ref_id}, al)
|
||||
end
|
||||
|
||||
def md_im_image(children, url, title=nil, al=nil)
|
||||
md_el(:im_image, children, {:url=>url,:title=>title},al)
|
||||
end
|
||||
def md_abbr_def(abbr, text, al = nil)
|
||||
md_el(:abbr_def, [], {:abbr => abbr, :text => text}, al)
|
||||
end
|
||||
|
||||
def md_em(children, al=nil)
|
||||
md_el(:emphasis, [children].flatten, {}, al)
|
||||
end
|
||||
def md_abbr(abbr, title)
|
||||
md_el(:abbr, [abbr], :title => title)
|
||||
end
|
||||
|
||||
def md_br()
|
||||
md_el(:linebreak, [], {}, nil)
|
||||
end
|
||||
def md_html(raw_html, al = nil)
|
||||
e = md_el(:raw_html, [], :raw_html => raw_html)
|
||||
begin
|
||||
e.instance_variable_set("@parsed_html",
|
||||
REXML::Document.new("<marukuwrap>#{raw_html.strip}</marukuwrap>"))
|
||||
rescue REXML::ParseException => ex
|
||||
e.instance_variable_set "@parsed_html", nil
|
||||
maruku_recover <<ERR
|
||||
REXML cannot parse this block of HTML/XML:
|
||||
#{raw_html.gsub(/^/, '|').rstrip}
|
||||
#{ex.inspect}
|
||||
ERR
|
||||
end
|
||||
e
|
||||
end
|
||||
|
||||
def md_hrule()
|
||||
md_el(:hrule, [], {}, nil)
|
||||
end
|
||||
def md_link(children, ref_id, al = nil)
|
||||
md_el(:link, children, {:ref_id => ref_id.downcase}, al)
|
||||
end
|
||||
|
||||
def md_strong(children, al=nil)
|
||||
md_el(:strong, [children].flatten, {}, al)
|
||||
end
|
||||
def md_im_link(children, url, title = nil, al = nil)
|
||||
md_el(:im_link, children, {:url => url, :title => title}, al)
|
||||
end
|
||||
|
||||
def md_emstrong(children, al=nil)
|
||||
md_strong(md_em(children), al)
|
||||
end
|
||||
def md_image(children, ref_id, al = nil)
|
||||
md_el(:image, children, {:ref_id => ref_id}, al)
|
||||
end
|
||||
|
||||
# <http://www.example.com/>
|
||||
def md_url(url, al=nil)
|
||||
md_el(:immediate_link, [], {:url=>url}, al)
|
||||
end
|
||||
|
||||
# <andrea@rubyforge.org>
|
||||
# <mailto:andrea@rubyforge.org>
|
||||
def md_email(email, al=nil)
|
||||
md_el(:email_address, [], {:email=>email}, al)
|
||||
end
|
||||
|
||||
def md_entity(entity_name, al=nil)
|
||||
md_el(:entity, [], {:entity_name=>entity_name}, al)
|
||||
end
|
||||
|
||||
# Markdown extra
|
||||
def md_foot_ref(ref_id, al=nil)
|
||||
md_el(:footnote_reference, [], {:footnote_id=>ref_id}, al)
|
||||
end
|
||||
|
||||
def md_par(children, al=nil)
|
||||
md_el(:paragraph, children, meta={}, al)
|
||||
end
|
||||
def md_im_image(children, url, title = nil, al = nil)
|
||||
md_el(:im_image, children, {:url => url, :title => title}, al)
|
||||
end
|
||||
|
||||
# [1]: http://url [properties]
|
||||
def md_ref_def(ref_id, url, title=nil, meta={}, al=nil)
|
||||
meta[:url] = url
|
||||
meta[:ref_id] = ref_id
|
||||
meta[:title] = title if title
|
||||
md_el(:ref_definition, [], meta, al)
|
||||
end
|
||||
|
||||
# inline attribute list
|
||||
def md_ial(al)
|
||||
al = Maruku::AttributeList.new(al) if
|
||||
not al.kind_of?Maruku::AttributeList
|
||||
md_el(:ial, [], {:ial=>al})
|
||||
end
|
||||
def md_em(children, al = nil)
|
||||
md_el(:emphasis, [children].flatten, {}, al)
|
||||
end
|
||||
|
||||
# Attribute list definition
|
||||
def md_ald(id, al)
|
||||
md_el(:ald, [], {:ald_id=>id,:ald=>al})
|
||||
end
|
||||
|
||||
# Server directive <?target code... ?>
|
||||
def md_xml_instr(target, code)
|
||||
md_el(:xml_instr, [], {:target=>target, :code=>code})
|
||||
end
|
||||
def md_br
|
||||
md_el(:linebreak, [], {}, nil)
|
||||
end
|
||||
|
||||
def md_hrule
|
||||
md_el(:hrule, [], {}, nil)
|
||||
end
|
||||
|
||||
def md_strong(children, al = nil)
|
||||
md_el(:strong, [children].flatten, {}, al)
|
||||
end
|
||||
|
||||
def md_emstrong(children, al = nil)
|
||||
md_strong(md_em(children), al)
|
||||
end
|
||||
|
||||
# A URL to be linkified (e.g. `<http://www.example.com/>`).
|
||||
def md_url(url, al = nil)
|
||||
md_el(:immediate_link, [], {:url => url}, al)
|
||||
end
|
||||
|
||||
# An email to be linkified
|
||||
# (e.g. `<andrea@rubyforge.org>` or `<mailto:andrea@rubyforge.org>`).
|
||||
def md_email(email, al = nil)
|
||||
md_el(:email_address, [], {:email => email}, al)
|
||||
end
|
||||
|
||||
def md_entity(entity_name, al = nil)
|
||||
md_el(:entity, [], {:entity_name => entity_name}, al)
|
||||
end
|
||||
|
||||
# Markdown extra
|
||||
def md_foot_ref(ref_id, al = nil)
|
||||
md_el(:footnote_reference, [], {:footnote_id => ref_id}, al)
|
||||
end
|
||||
|
||||
def md_par(children, al = nil)
|
||||
md_el(:paragraph, children, meta = {}, al)
|
||||
end
|
||||
|
||||
# A definition of a reference (e.g. `[1]: http://url [properties]`).
|
||||
def md_ref_def(ref_id, url, title = nil, meta = {}, al = nil)
|
||||
meta[:url] = url
|
||||
meta[:ref_id] = ref_id
|
||||
meta[:title] = title if title
|
||||
md_el(:ref_definition, [], meta, al)
|
||||
end
|
||||
|
||||
# inline attribute list
|
||||
def md_ial(al)
|
||||
al = Maruku::AttributeList.new(al) unless al.is_a?(Maruku::AttributeList)
|
||||
md_el(:ial, [], :ial => al)
|
||||
end
|
||||
|
||||
# Attribute list definition
|
||||
def md_ald(id, al)
|
||||
md_el(:ald, [], :ald_id => id, :ald => al)
|
||||
end
|
||||
|
||||
# A server directive (e.g. `<?target code... ?>`)
|
||||
def md_xml_instr(target, code)
|
||||
md_el(:xml_instr, [], :target => target, :code => code)
|
||||
end
|
||||
end
|
||||
|
||||
class MDElement
|
||||
INSPECT2_FORMS = {
|
||||
:paragraph => ["par", :children],
|
||||
:footnote_reference => ["foot_ref", :footnote_id],
|
||||
:entity => ["entity", :entity_name],
|
||||
:email_address => ["email", :email],
|
||||
:inline_code => ["code", :raw_code],
|
||||
:raw_html => ["html", :raw_html],
|
||||
:emphasis => ["em", :children],
|
||||
:strong => ["strong", :children],
|
||||
:immediate_link => ["url", :url],
|
||||
:image => ["image", :children, :ref_id],
|
||||
:im_image => ["im_image", :children, :url, :title],
|
||||
:link => ["link", :children, :ref_id],
|
||||
:im_link => ["im_link", :children, :url, :title],
|
||||
:ref_definition => ["ref_def", :ref_id, :url, :title],
|
||||
:ial => ["ial", :ial]
|
||||
}
|
||||
|
||||
# Outputs the abbreviated form of an element
|
||||
# (this should be `eval`-able to get a copy of the original element).
|
||||
def inspect2
|
||||
name, *params = INSPECT2_FORMS[@node_type]
|
||||
return nil unless name
|
||||
|
||||
params = params.map do |p|
|
||||
next children_inspect if p == :children
|
||||
send(p).inspect
|
||||
end
|
||||
params << @al.inspect if @al && !@al.empty?
|
||||
|
||||
"md_#{name}(#{params.join(', ')})"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module MaRuKu
|
||||
|
||||
class MDElement
|
||||
# outputs abbreviated form (this should be eval()uable to get the document)
|
||||
def inspect2
|
||||
s =
|
||||
case @node_type
|
||||
when :paragraph
|
||||
"md_par(%s)" % children_inspect
|
||||
when :footnote_reference
|
||||
"md_foot_ref(%s)" % self.footnote_id.inspect
|
||||
when :entity
|
||||
"md_entity(%s)" % self.entity_name.inspect
|
||||
when :email_address
|
||||
"md_email(%s)" % self.email.inspect
|
||||
when :inline_code
|
||||
"md_code(%s)" % self.raw_code.inspect
|
||||
when :raw_html
|
||||
"md_html(%s)" % self.raw_html.inspect
|
||||
when :emphasis
|
||||
"md_em(%s)" % children_inspect
|
||||
when :strong
|
||||
"md_strong(%s)" % children_inspect
|
||||
when :immediate_link
|
||||
"md_url(%s)" % self.url.inspect
|
||||
when :image
|
||||
"md_image(%s, %s)" % [
|
||||
children_inspect,
|
||||
self.ref_id.inspect]
|
||||
when :im_image
|
||||
"md_im_image(%s, %s, %s)" % [
|
||||
children_inspect,
|
||||
self.url.inspect,
|
||||
self.title.inspect]
|
||||
when :link
|
||||
"md_link(%s,%s)" % [
|
||||
children_inspect, self.ref_id.inspect]
|
||||
when :im_link
|
||||
"md_im_link(%s, %s, %s)" % [
|
||||
children_inspect,
|
||||
self.url.inspect,
|
||||
self.title.inspect,
|
||||
]
|
||||
when :ref_definition
|
||||
"md_ref_def(%s, %s, %s)" % [
|
||||
self.ref_id.inspect,
|
||||
self.url.inspect,
|
||||
self.title.inspect
|
||||
]
|
||||
when :ial
|
||||
"md_ial(%s)" % self.ial.inspect
|
||||
else
|
||||
return nil
|
||||
end
|
||||
if @al and not @al.empty? then
|
||||
s = s.chop + ", #{@al.inspect})"
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ class CharSourceManual
|
|||
|
||||
def consume_whitespace
|
||||
while c = cur_char
|
||||
if (c == ?\s || c == ?\t)
|
||||
if (c == ?\s || c == ?\t)
|
||||
# puts "ignoring #{c}"
|
||||
ignore_char
|
||||
else
|
||||
|
@ -191,7 +191,7 @@ def describe_pos(buffer, buffer_index)
|
|||
pre + "+--- Byte #{buffer_index}\n"+
|
||||
|
||||
"Shown bytes [#{index_start} to #{size}] of #{buffer.size}:\n"+
|
||||
add_tabs(buffer,1,">")
|
||||
buffer.gsub(/^/, ">")
|
||||
|
||||
# "CharSource: At character #{@buffer_index} of block "+
|
||||
# " beginning with:\n #{@buffer[0,50].inspect} ...\n"+
|
||||
|
|
|
@ -168,9 +168,9 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
|
|||
"match=#{@m.to_s.inspect}\n"+
|
||||
"Tag stack = #{@tag_stack.inspect} \n"+
|
||||
"Before:\n"+
|
||||
add_tabs(@already,1,'|')+"\n"+
|
||||
@already.gsub(/^/, '|')+"\n"+
|
||||
"After:\n"+
|
||||
add_tabs(@rest,1,'|')+"\n"
|
||||
@rest.gsub(/^/, '|')+"\n"
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class LineSource
|
|||
|
||||
# if @parent
|
||||
# s << "Parent context is: \n"
|
||||
# s << add_tabs(@parent.describe,1,'|')
|
||||
# s << @parent.describe.gsub(/^/, '|')
|
||||
# end
|
||||
s
|
||||
end
|
||||
|
|
|
@ -198,8 +198,8 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
ial = $2
|
||||
al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil])
|
||||
end
|
||||
level = num_leading_hashes(line)
|
||||
text = parse_lines_as_span [strip_hashes(line)]
|
||||
level = line[/^#+/].size
|
||||
text = parse_lines_as_span [line.gsub(/\A#+|#+\Z/, '')]
|
||||
return md_header(level, text, al)
|
||||
end
|
||||
|
||||
|
@ -214,7 +214,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
if not code =~ (/\?>\s*$/)
|
||||
garbage = (/\?>(.*)$/.match(code))[1]
|
||||
maruku_error "Trailing garbage on last line: #{garbage.inspect}:\n"+
|
||||
add_tabs(code, 1, '|'), src
|
||||
code.gsub(/^/, '|'), src
|
||||
end
|
||||
code.gsub!(/\?>\s*$/, '')
|
||||
|
||||
|
@ -244,7 +244,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
end
|
||||
rescue Exception => e
|
||||
ex = e.inspect + e.backtrace.join("\n")
|
||||
maruku_error "Bad block-level HTML:\n#{add_tabs(ex,1,'|')}\n", src
|
||||
maruku_error "Bad block-level HTML:\n#{ex.gsub(/^/, '|')}\n", src
|
||||
end
|
||||
if not (h.rest =~ /^\s*$/)
|
||||
maruku_error "Could you please format this better?\n"+
|
||||
|
@ -271,7 +271,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
|
||||
lines << src.shift_line
|
||||
end
|
||||
# dbg_describe_ary(lines, 'PAR')
|
||||
children = parse_lines_as_span(lines, src)
|
||||
|
||||
return md_par(children)
|
||||
|
@ -296,7 +295,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
stripped = first[indentation, first.size-1]
|
||||
lines.unshift stripped
|
||||
|
||||
# dbg_describe_ary(lines, 'LIST ITEM ')
|
||||
|
||||
src2 = LineSource.new(lines, src, parent_offset)
|
||||
children = parse_blocks(src2)
|
||||
|
@ -347,7 +345,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
# add first line
|
||||
if text && text.strip != "" then lines.unshift text end
|
||||
|
||||
# dbg_describe_ary(lines, 'FOOTNOTE')
|
||||
src2 = LineSource.new(lines, src, parent_offset)
|
||||
children = parse_blocks(src2)
|
||||
|
||||
|
@ -405,7 +402,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
want_my_paragraph = saw_anything_after ||
|
||||
(saw_empty && (src.cur_line && (src.cur_line.md_type == item_type)))
|
||||
|
||||
# dbg_describe_ary(lines, 'LI')
|
||||
# create a new context
|
||||
|
||||
while lines.last && (lines.last.md_type == :empty)
|
||||
|
@ -424,7 +420,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
while src.cur_line && src.cur_line.md_type == :quote
|
||||
lines << unquote(src.shift_line)
|
||||
end
|
||||
# dbg_describe_ary(lines, 'QUOTE')
|
||||
|
||||
src2 = LineSource.new(lines, src, parent_offset)
|
||||
children = parse_blocks(src2)
|
||||
|
@ -451,7 +446,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
|
||||
source = lines.join("\n")
|
||||
|
||||
# dbg_describe_ary(lines, 'CODE')
|
||||
|
||||
return md_codeblock(source)
|
||||
end
|
||||
|
@ -568,7 +562,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
while src.cur_line && src.cur_line.md_type == :text
|
||||
terms << md_el(:definition_term, parse_lines_as_span([src.shift_line]))
|
||||
end
|
||||
# dbg_describe_ary(terms, 'DT')
|
||||
|
||||
want_my_paragraph = false
|
||||
|
||||
|
@ -599,7 +592,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
|
||||
lines.unshift first
|
||||
|
||||
# dbg_describe_ary(lines, 'DD')
|
||||
src2 = LineSource.new(lines, src, parent_offset)
|
||||
children = parse_blocks(src2)
|
||||
definitions << md_el(:definition_data, children)
|
||||
|
@ -613,4 +605,4 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|||
end # BlockLevelParser
|
||||
end # MaRuKu
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -141,19 +141,19 @@ Disabled by default because of security concerns.
|
|||
return object.instance_eval(code)
|
||||
rescue Exception => e
|
||||
maruku_error "Exception while executing this:\n"+
|
||||
add_tabs(code, 1, ">")+
|
||||
code.gsub(/^/, ">")+
|
||||
"\nThe error was:\n"+
|
||||
add_tabs(e.inspect+"\n"+e.caller.join("\n"), 1, "|")
|
||||
(e.inspect+"\n"+e.caller.join("\n")).gsub(/^/, "|")
|
||||
rescue RuntimeError => e
|
||||
maruku_error "2: Exception while executing this:\n"+
|
||||
add_tabs(code, 1, ">")+
|
||||
code.gsub(/^/, ">")+
|
||||
"\nThe error was:\n"+
|
||||
add_tabs(e.inspect, 1, "|")
|
||||
e.inspect.gsub(/^/, "|")
|
||||
rescue SyntaxError => e
|
||||
maruku_error "2: Exception while executing this:\n"+
|
||||
add_tabs(code, 1, ">")+
|
||||
code.gsub(/^/, ">")+
|
||||
"\nThe error was:\n"+
|
||||
add_tabs(e.inspect, 1, "|")
|
||||
e.inspect.gsub(/^/, "|")
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -500,7 +500,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
|
|||
# end
|
||||
rescue Exception => e
|
||||
maruku_error "Bad html: \n" +
|
||||
add_tabs(e.inspect+e.backtrace.join("\n"),1,'>'),
|
||||
(e.inspect+e.backtrace.join("\n")).gsub(/^/, '>'),
|
||||
src,con
|
||||
maruku_recover "I will try to continue after bad HTML.", src, con
|
||||
con.push_char src.shift_char
|
||||
|
@ -733,7 +733,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
|
|||
def describe
|
||||
lines = @elements.map{|x| x.inspect}.join("\n")
|
||||
s = "Elements read in span: \n" +
|
||||
add_tabs(lines,1, ' -')+"\n"
|
||||
lines.gsub(/^/, ' -')+"\n"
|
||||
|
||||
if @cur_string.size > 0
|
||||
s += "Current string: \n #{@cur_string.inspect}\n"
|
||||
|
|
28
vendor/plugins/maruku/lib/maruku/maruku.rb
vendored
28
vendor/plugins/maruku/lib/maruku/maruku.rb
vendored
|
@ -1,33 +1,31 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
# The Maruku class is the public interface
|
||||
# The public interface for Maruku.
|
||||
#
|
||||
|
||||
class Maruku
|
||||
def initialize(s=nil, meta={})
|
||||
super(nil)
|
||||
self.attributes.merge! meta
|
||||
if s
|
||||
parse_doc(s)
|
||||
end
|
||||
end
|
||||
# @example Render a document fragment
|
||||
# Maruku.new("## Header ##").to_html
|
||||
# # => "<h2 id='header'>header</h2>"
|
||||
class Maruku < MaRuKu::MDDocument
|
||||
def initialize(s = nil, meta = {})
|
||||
super(nil)
|
||||
self.attributes.merge! meta
|
||||
parse_doc(s) if s
|
||||
end
|
||||
end
|
||||
|
|
|
@ -578,7 +578,7 @@ and
|
|||
code = Document.new(html, {:respect_whitespace =>:all}).root
|
||||
code.name = 'code'
|
||||
code.attributes['lang'] = lang
|
||||
|
||||
|
||||
pre = Element.new 'pre'
|
||||
pre.attributes['class'] = lang
|
||||
pre << code
|
||||
|
@ -828,7 +828,7 @@ If true, raw HTML is discarded from the output.
|
|||
else # invalid
|
||||
# Creates red box with offending HTML
|
||||
tell_user "Wrapping bad html in a PRE with class 'markdown-html-error'\n"+
|
||||
add_tabs(raw_html,1,'|')
|
||||
raw_html.gsub(/^/, '|')
|
||||
pre = Element.new('pre')
|
||||
pre.attributes['style'] = 'border: solid 3px red; background-color: pink'
|
||||
pre.attributes['class'] = 'markdown-html-error'
|
||||
|
|
|
@ -55,10 +55,10 @@ module MaRuKu; module Out; module Latex
|
|||
end
|
||||
|
||||
class LatexEntity
|
||||
safe_attr_accessor :html_num, Fixnum
|
||||
safe_attr_accessor :html_entity, String
|
||||
safe_attr_accessor :latex_string, String
|
||||
safe_attr_accessor :latex_packages, Array
|
||||
attr_accessor :html_num
|
||||
attr_accessor :html_entity
|
||||
attr_accessor :latex_string
|
||||
attr_accessor :latex_packages
|
||||
end
|
||||
|
||||
def Latex.need_entity_table
|
||||
|
@ -69,7 +69,7 @@ module MaRuKu; module Out; module Latex
|
|||
def Latex.init_entity_table
|
||||
# $stderr.write "Creating entity table.."
|
||||
# $stderr.flush
|
||||
doc = Document.new XML_TABLE
|
||||
doc = Document.new(File.read(File.dirname(__FILE__) + "/../../../data/entities.xml"))
|
||||
doc.elements.each("//char") do |c|
|
||||
num = c.attributes['num'].to_i
|
||||
name = c.attributes['name']
|
||||
|
@ -97,271 +97,5 @@ module MaRuKu; module Out; module Latex
|
|||
|
||||
ENTITY_TABLE = {}
|
||||
|
||||
# The following is a conversion chart for html elements, courtesy of
|
||||
# text2html
|
||||
|
||||
XML_TABLE ="
|
||||
<chars>
|
||||
<char num='913' name='Alpha' convertTo='$A$' />
|
||||
<char num='914' name='Beta' convertTo='$B$' />
|
||||
<char num='915' name='Gamma' convertTo='$\\Gamma$' />
|
||||
<char num='916' name='Delta' convertTo='$\\Delta$' />
|
||||
<char num='917' name='Epsilon' convertTo='$E$' />
|
||||
<char num='918' name='Zeta' convertTo='$Z$' />
|
||||
<char num='919' name='Eta' convertTo='$H$' />
|
||||
<char num='920' name='Theta' convertTo='$\\Theta$' />
|
||||
<char num='921' name='Iota' convertTo='$I$' />
|
||||
<char num='922' name='Kappa' convertTo='$K$' />
|
||||
<char num='923' name='Lambda' convertTo='$\\Lambda$' />
|
||||
<char num='924' name='Mu' convertTo='$M$' />
|
||||
<char num='925' name='Nu' convertTo='$N$' />
|
||||
<char num='926' name='Xi' convertTo='$\\Xi$' />
|
||||
<char num='927' name='Omicron' convertTo='$O$' />
|
||||
<char num='928' name='Pi' convertTo='$\\Pi$' />
|
||||
<char num='929' name='Rho' convertTo='$P$' />
|
||||
<char num='931' name='Sigma' convertTo='$\\Sigma$' />
|
||||
<char num='932' name='Tau' convertTo='$T$' />
|
||||
<char num='933' name='Upsilon' convertTo='$Y$' />
|
||||
<char num='934' name='Phi' convertTo='$\\Phi$' />
|
||||
<char num='935' name='Chi' convertTo='$X$' />
|
||||
<char num='936' name='Psi' convertTo='$\\Psi$' />
|
||||
<char num='937' name='Omega' convertTo='$\\Omega$' />
|
||||
<char num='945' name='alpha' convertTo='$\\alpha$' />
|
||||
<char num='946' name='beta' convertTo='$\\beta$' />
|
||||
<char num='947' name='gamma' convertTo='$\\gamma$' />
|
||||
<char num='948' name='delta' convertTo='$\\delta$' />
|
||||
<char num='949' name='epsilon' convertTo='$\\epsilon$' />
|
||||
<char num='950' name='zeta' convertTo='$\\zeta$' />
|
||||
<char num='951' name='eta' convertTo='$\\eta$' />
|
||||
<char num='952' name='theta' convertTo='$\\theta$' />
|
||||
<char num='953' name='iota' convertTo='$\\iota$' />
|
||||
<char num='954' name='kappa' convertTo='$\\kappa$' />
|
||||
<char num='955' name='lambda' convertTo='$\\lambda$' />
|
||||
<char num='956' name='mu' convertTo='$\\mu$' />
|
||||
|
||||
<char num='957' name='nu' convertTo='$\\nu$' />
|
||||
<char num='958' name='xi' convertTo='$\\xi$' />
|
||||
<char num='959' name='omicron' convertTo='$o$' />
|
||||
<char num='960' name='pi' convertTo='$\\pi$' />
|
||||
<char num='961' name='rho' convertTo='$\\rho$' />
|
||||
<char num='963' name='sigma' convertTo='$\\sigma$' />
|
||||
<char num='964' name='tau' convertTo='$\\tau$' />
|
||||
<char num='965' name='upsilon' convertTo='$\\upsilon$' />
|
||||
<char num='966' name='phi' convertTo='$\\phi$' />
|
||||
|
||||
<char num='967' name='chi' convertTo='$\\chi$' />
|
||||
<char num='968' name='psi' convertTo='$\\psi$' />
|
||||
<char num='969' name='omega' convertTo='$\\omega$' />
|
||||
<char num='962' name='sigmaf' convertTo='$\\varsigma$' />
|
||||
<char num='977' name='thetasym' convertTo='$\\vartheta$' />
|
||||
<char num='982' name='piv' convertTo='$\\varpi$' />
|
||||
<char num='8230' name='hellip' convertTo='\\ldots' />
|
||||
<char num='8242' name='prime' convertTo='$\\prime$' />
|
||||
<char num='8254' name='oline' convertTo='-' />
|
||||
|
||||
<char num='8260' name='frasl' convertTo='/' />
|
||||
<char num='8472' name='weierp' convertTo='$\\wp$' />
|
||||
<char num='8465' name='image' convertTo='$\\Im$' />
|
||||
<char num='8476' name='real' convertTo='$\\Re$' />
|
||||
<char num='8501' name='alefsym' convertTo='$\\aleph$' />
|
||||
<char num='8226' name='bull' convertTo='$\\bullet$' />
|
||||
<char num='8482' name='trade' convertTo='$^{\\rm TM}$' /> <!-- \texttrademark -->
|
||||
<char num='8592' name='larr' convertTo='$\\leftarrow$' />
|
||||
|
||||
<char num='8594' name='rarr' convertTo='$\\rightarrow$' />
|
||||
<char num='8593' name='uarr' convertTo='$\\uparrow$' />
|
||||
<char num='8595' name='darr' convertTo='$\\downarrow$' />
|
||||
<char num='8596' name='harr' convertTo='$\\leftrightarrow$' />
|
||||
<char num='8629' name='crarr' convertTo='$\\hookleftarrow$' />
|
||||
<char num='8657' name='uArr' convertTo='$\\Uparrow$' />
|
||||
<char num='8659' name='dArr' convertTo='$\\Downarrow$' />
|
||||
<char num='8656' name='lArr' convertTo='$\\Leftarrow$' />
|
||||
<char num='8658' name='rArr' convertTo='$\\Rightarrow$' />
|
||||
|
||||
<char num='8660' name='hArr' convertTo='$\\Leftrightarrow$' />
|
||||
<char num='8704' name='forall' convertTo='$\\forall$' />
|
||||
<char num='8706' name='part' convertTo='$\\partial$' />
|
||||
<char num='8707' name='exist' convertTo='$\\exists$' />
|
||||
<char num='8709' name='empty' convertTo='$\\emptyset$' />
|
||||
<char num='8711' name='nabla' convertTo='$\\nabla$' />
|
||||
<char num='8712' name='isin' convertTo='$\\in$' />
|
||||
<char num='8715' name='ni' convertTo='$\\ni$' />
|
||||
<char num='8713' name='notin' convertTo='$\\notin$' />
|
||||
|
||||
<char num='8721' name='sum' convertTo='$\\sum$' />
|
||||
<char num='8719' name='prod' convertTo='$\\prod$' />
|
||||
<char num='8722' name='minus' convertTo='$-$' />
|
||||
<char num='8727' name='lowast' convertTo='$\\ast$' />
|
||||
<char num='8730' name='radic' convertTo='$\\surd$' />
|
||||
<char num='8733' name='prop' convertTo='$\\propto$' />
|
||||
<char num='8734' name='infin' convertTo='$\\infty$' />
|
||||
<char num='8736' name='ang' convertTo='$\\angle$' />
|
||||
<char num='8743' name='and' convertTo='$\\wedge$' />
|
||||
|
||||
<char num='8744' name='or' convertTo='$\\vee$' />
|
||||
<char num='8745' name='cup' convertTo='$\\cup$' />
|
||||
<char num='8746' name='cap' convertTo='$\\cap$' />
|
||||
<char num='8747' name='int' convertTo='$\\int$' />
|
||||
<char num='8756' name='there4' convertTo='$\\therefore$' package='amssymb' /> <!-- only AMS -->
|
||||
<char num='8764' name='sim' convertTo='$\\sim$' />
|
||||
<char num='8776' name='asymp' convertTo='$\\approx$' />
|
||||
<char num='8773' name='cong' convertTo='$\\cong$' />
|
||||
|
||||
<char num='8800' name='ne' convertTo='$\\neq$' />
|
||||
<char num='8801' name='equiv' convertTo='$\\equiv$' />
|
||||
<char num='8804' name='le' convertTo='$\\leq$' />
|
||||
<char num='8805' name='ge' convertTo='$\\geq$' />
|
||||
<char num='8834' name='sub' convertTo='$\\subset$' />
|
||||
<char num='8835' name='sup' convertTo='$\\supset$' />
|
||||
<!-- <char num='8838' name='sube' convertTo='$\\subseteq$' />-->
|
||||
<char num='8839' name='supe' convertTo='$\\supseteq$' />
|
||||
<!-- <char num='8836' name='nsub' convertTo='$\\nsubset$' /> --><!-- only AMS -->
|
||||
|
||||
<char num='8853' name='oplus' convertTo='$\\oplus$' />
|
||||
<char num='8855' name='otimes' convertTo='$\\otimes$' />
|
||||
<char num='8869' name='perp' convertTo='$\\perp$' />
|
||||
<char num='8901' name='sdot' convertTo='$\\cdot$' />
|
||||
<char num='8968' name='rceil' convertTo='$\\rceil$' />
|
||||
<char num='8969' name='lceil' convertTo='$\\lceil$' />
|
||||
<char num='8970' name='lfloor' convertTo='$\\lfloor$' />
|
||||
<char num='8971' name='rfloor' convertTo='$\\rfloor$' />
|
||||
<char num='9001' name='rang' convertTo='$\\rangle$' />
|
||||
|
||||
<char num='9002' name='lang' convertTo='$\\langle$' />
|
||||
<char num='9674' name='loz' convertTo='$\\lozenge$' package='amssymb' /> <!-- only AMS -->
|
||||
<char num='9824' name='spades' convertTo='$\\spadesuit$' />
|
||||
<char num='9827' name='clubs' convertTo='$\\clubsuit$' />
|
||||
<char num='9829' name='hearts' convertTo='$\\heartsuit$' />
|
||||
<char num='9830' name='diams' convertTo='$\\diamondsuit$' />
|
||||
<char num='38' name='amp' convertTo='\\@AMP' />
|
||||
<!-- <char num='34' name='quot' convertTo='\\@DOUBLEQUOT' /> XXX -->
|
||||
<char num='34' name='quot' convertTo='\"' />
|
||||
<char num='39' name='apos' convertTo=\"'\" />
|
||||
<char num='169' name='copy' convertTo='\\copyright' />
|
||||
|
||||
<char num='60' name='lt' convertTo='$@LT$' />
|
||||
<char num='62' name='gt' convertTo='$@GT$' />
|
||||
<char num='338' name='OElig' convertTo='\\OE' />
|
||||
<char num='339' name='oelig' convertTo='\\oe' />
|
||||
<char num='352' name='Scaron' convertTo='\\v{S}' />
|
||||
<char num='353' name='scaron' convertTo='\\v{s}' />
|
||||
<char num='376' name='Yuml' convertTo='\\\"Y' />
|
||||
<char num='710' name='circ' convertTo='\\textasciicircum' />
|
||||
<char num='732' name='tilde' convertTo='\\textasciitilde' />
|
||||
|
||||
<char num='8211' name='ndash' convertTo='--' />
|
||||
<char num='8212' name='mdash' convertTo='---' />
|
||||
<char num='8216' name='lsquo' convertTo='`' />
|
||||
<char num='8217' name='rsquo' convertTo=\"'\" /> <!-- XXXX -->
|
||||
<char num='8220' name='ldquo' convertTo='``' />
|
||||
<char num='8221' name='rdquo' convertTo=\"''\" /> <!-- XXXX -->
|
||||
<char num='8224' name='dagger' convertTo='\\dag' />
|
||||
<char num='8225' name='Dagger' convertTo='\\ddag' />
|
||||
<char num='8240' name='permil' convertTo='\\permil' package='wasysym' /> <!-- wasysym package -->
|
||||
|
||||
<char num='8364' name='euro' convertTo='\\euro' package='eurosym' /> <!-- eurosym package -->
|
||||
<char num='8249' name='lsaquo' convertTo='\\guilsinglleft' package='aeguill'/>
|
||||
<char num='8250' name='rsaquo' convertTo='\\guilsinglright' package='aeguill' />
|
||||
<!-- <char num='160' name='nbsp' convertTo='\\nolinebreak' />-->
|
||||
<char num='160' name='nbsp' convertTo='~' />
|
||||
<char num='161' name='iexcl' convertTo='\\textexclamdown' />
|
||||
<char num='163' name='pound' convertTo='\\pounds' />
|
||||
<char num='164' name='curren' convertTo='\\currency' package='wasysym' /> <!-- wasysym package -->
|
||||
<char num='165' name='yen' convertTo='\\textyen' package='textcomp'/> <!-- textcomp -->
|
||||
|
||||
<char num='166' name='brvbar' convertTo='\\brokenvert' /> <!-- wasysym -->
|
||||
<char num='167' name='sect' convertTo='\\S' />
|
||||
<char num='171' name='laquo' convertTo='\\guillemotleft' package='aeguill'/>
|
||||
<char num='187' name='raquo' convertTo='\\guillemotright' package='aeguill'/>
|
||||
<char num='174' name='reg' convertTo='\\textregistered' />
|
||||
<char num='170' name='ordf' convertTo='\\textordfeminine' />
|
||||
<char num='172' name='not' convertTo='$\\neg$' />
|
||||
<!-- <char num='176' name='deg' convertTo='$\\degree$' /> --><!-- mathabx -->
|
||||
<char num='176' name='deg' convertTo='\\textdegree' package='textcomp'/>
|
||||
|
||||
<char num='177' name='plusmn' convertTo='$\\pm$' />
|
||||
<char num='180' name='acute' convertTo='@QUOT' />
|
||||
<char num='181' name='micro' convertTo='$\\mu$' />
|
||||
<char num='182' name='para' convertTo='\\P' />
|
||||
<char num='183' name='middot' convertTo='$\\cdot$' />
|
||||
<char num='186' name='ordm' convertTo='\\textordmasculine' />
|
||||
<char num='162' name='cent' convertTo='\\cent' package='wasysym' />
|
||||
<char num='185' name='sup1' convertTo='$^1$' />
|
||||
|
||||
<char num='178' name='sup2' convertTo='$^2$' />
|
||||
<char num='179' name='sup3' convertTo='$^3$' />
|
||||
<char num='189' name='frac12' convertTo='$\\frac{1}{2}$' />
|
||||
<char num='188' name='frac14' convertTo='$\\frac{1}{4}$' />
|
||||
<char num='190' name='frac34' convertTo='$\\frac{3}{4}$' />
|
||||
<char num='192' name='Agrave' convertTo='\\`A' />
|
||||
<char num='193' name='Aacute' convertTo='\\@QUOTA' />
|
||||
<char num='194' name='Acirc' convertTo='\\^A' />
|
||||
<char num='195' name='Atilde' convertTo='\\~A' />
|
||||
|
||||
<char num='196' name='Auml' convertTo='\\@DOUBLEQUOTA' />
|
||||
<char num='197' name='Aring' convertTo='\\AA' />
|
||||
<char num='198' name='AElig' convertTo='\\AE' />
|
||||
<char num='199' name='Ccedil' convertTo='\\c{C}' />
|
||||
<char num='200' name='Egrave' convertTo='\\`E' />
|
||||
<char num='201' name='Eacute' convertTo='\\@QUOTE' />
|
||||
<char num='202' name='Ecirc' convertTo='\\^E' />
|
||||
<char num='203' name='Euml' convertTo='\\@DOUBLEQUOTE' />
|
||||
<char num='204' name='Igrave' convertTo='\\`I' />
|
||||
<char num='205' name='Iacute' convertTo='\\@QUOTI' />
|
||||
<char num='206' name='Icirc' convertTo='\\^I' />
|
||||
<char num='207' name='Iuml' convertTo='\\\"I' />
|
||||
<char num='208' name='ETH' convertTo='$\\eth$' /> <!-- AMS -->
|
||||
<char num='209' name='Ntilde' convertTo='\\~N' />
|
||||
<char num='210' name='Ograve' convertTo='\\`O' />
|
||||
<char num='211' name='Oacute' convertTo='\\@QUOT O' />
|
||||
<char num='212' name='Ocirc' convertTo='\\^O' />
|
||||
<char num='213' name='Otilde' convertTo='\\~O' />
|
||||
<char num='214' name='Ouml' convertTo='\\@DOUBLEQUOTO' />
|
||||
<char num='215' name='times' convertTo='$\\times$' />
|
||||
<char num='216' name='Oslash' convertTo='\\O' />
|
||||
<char num='217' name='Ugrave' convertTo='\\`U' />
|
||||
<char num='218' name='Uacute' convertTo='\\@QUOTU' />
|
||||
<char num='219' name='Ucirc' convertTo='\\^U' />
|
||||
<char num='220' name='Uuml' convertTo='\\@DOUBLEQUOTU' />
|
||||
<char num='221' name='Yacute' convertTo='\\@QUOTY' />
|
||||
<char num='223' name='szlig' convertTo='\\ss' />
|
||||
<char num='224' name='agrave' convertTo='\\`a' />
|
||||
<char num='225' name='aacute' convertTo='\\@QUOTa' />
|
||||
<char num='226' name='acirc' convertTo='\\^a' />
|
||||
<char num='227' name='atilde' convertTo='\\~a' />
|
||||
<char num='228' name='auml' convertTo='\\@DOUBLEQUOTa' />
|
||||
<char num='229' name='aring' convertTo='\\aa' />
|
||||
<char num='230' name='aelig' convertTo='\\ae' />
|
||||
<char num='231' name='ccedil' convertTo='\\c{c}' />
|
||||
<char num='232' name='egrave' convertTo='\\`e' />
|
||||
<char num='233' name='eacute' convertTo='\\@QUOTe' />
|
||||
<char num='234' name='ecirc' convertTo='\\^e' />
|
||||
<char num='235' name='euml' convertTo='\\@DOUBLEQUOTe' />
|
||||
<char num='236' name='igrave' convertTo='\\`i' />
|
||||
<char num='237' name='iacute' convertTo='\\@QUOTi' />
|
||||
<char num='238' name='icirc' convertTo='\\^i' />
|
||||
<char num='239' name='iuml' convertTo='\\@DOUBLEQUOTi' />
|
||||
<char num='240' name='eth' convertTo='$\\eth$' package='amssymb'/> <!-- -->
|
||||
<char num='241' name='ntilde' convertTo='\\~n' />
|
||||
<char num='242' name='ograve' convertTo='\\`o' />
|
||||
<char num='243' name='oacute' convertTo='\\@QUOTo' />
|
||||
<char num='244' name='ocirc' convertTo='\\^o' />
|
||||
<char num='245' name='otilde' convertTo='\\~o' />
|
||||
<char num='246' name='ouml' convertTo='\\@DOUBLEQUOTo' />
|
||||
<!-- <char num='247' name='divide' convertTo='$\\divide$' /> -->
|
||||
<char num='248' name='oslash' convertTo='\\o' />
|
||||
<char num='249' name='ugrave' convertTo='\\`u' />
|
||||
<char num='250' name='uacute' convertTo='\\@QUOTu' />
|
||||
<char num='251' name='ucirc' convertTo='\\^u' />
|
||||
<char num='252' name='uuml' convertTo='\\@DOUBLEQUOTu' />
|
||||
<char num='253' name='yacute' convertTo='\\@QUOTy' />
|
||||
|
||||
<char num='255' name='yuml' convertTo='\\@DOUBLEQUOTy' />
|
||||
|
||||
<char num='222' name='THORN' convertTo='\\Thorn' package='wasysym' />
|
||||
<char num='254' name='thorn' convertTo='\\thorn' package='wasysym' />
|
||||
</chars>"
|
||||
|
||||
|
||||
end end end
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ module MaRuKu; module Out; module Markdown
|
|||
|
||||
def to_md_li_span(context)
|
||||
len = (context[:line_length] || DefaultLineLength) - 2
|
||||
s = add_tabs(wrap(@children, len-2, context), 1, ' ')
|
||||
s = wrap(@children, len-2, context).rstrip.gsub(/^/, ' ')
|
||||
s[0] = ?*
|
||||
s + "\n"
|
||||
end
|
||||
|
@ -60,7 +60,7 @@ module MaRuKu; module Out; module Markdown
|
|||
len = (context[:line_length] || DefaultLineLength) - 2
|
||||
md = ""
|
||||
self.children.each_with_index do |li, i|
|
||||
s = add_tabs(w=wrap(li.children, len-2, context), 1, ' ')+"\n"
|
||||
s = (w=wrap(li.children, len-2, context)).rstrip.gsub(/^/, ' ')+"\n"
|
||||
s[0,4] = "#{i+1}. "[0,4]
|
||||
# puts w.inspect
|
||||
md += s
|
||||
|
@ -161,4 +161,4 @@ module MaRuKu; class MDDocument
|
|||
# puts s
|
||||
s
|
||||
end
|
||||
end end
|
||||
end end
|
||||
|
|
304
vendor/plugins/maruku/lib/maruku/string_utils.rb
vendored
304
vendor/plugins/maruku/lib/maruku/string_utils.rb
vendored
|
@ -2,166 +2,192 @@
|
|||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
require 'strscan'
|
||||
|
||||
# Boring stuff with strings.
|
||||
module MaRuKu; module Strings
|
||||
|
||||
def add_tabs(s,n=1,char="\t")
|
||||
s.split("\n").map{|x| char*n+x }.join("\n")
|
||||
end
|
||||
|
||||
TabSize = 4;
|
||||
|
||||
def split_lines(s)
|
||||
s.gsub("\r","").split("\n")
|
||||
end
|
||||
|
||||
# This parses email headers. Returns an hash.
|
||||
#
|
||||
# +hash['data']+ is the message.
|
||||
#
|
||||
# Keys are downcased, space becomes underscore, converted to symbols.
|
||||
#
|
||||
# My key: true
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# {:my_key => true}
|
||||
#
|
||||
def parse_email_headers(s)
|
||||
keys={}
|
||||
match = (s =~ /\A((\w[\w \t\_\-]+: .*?\n)+)\s*?\n/)
|
||||
if match != 0
|
||||
keys[:data] = s
|
||||
else
|
||||
keys[:data] = $'
|
||||
headers = $1
|
||||
headers.split("\n").each do |l|
|
||||
# Fails if there are other ':' characters.
|
||||
# k, v = l.split(':')
|
||||
k, v = l.split(':', 2)
|
||||
k, v = normalize_key_and_value(k, v)
|
||||
k = k.to_sym
|
||||
# puts "K = #{k}, V=#{v}"
|
||||
keys[k] = v
|
||||
end
|
||||
end
|
||||
keys
|
||||
end
|
||||
module MaRuKu
|
||||
# Utility functions for dealing with strings.
|
||||
module Strings
|
||||
TAB_SIZE = 4
|
||||
|
||||
# Keys are downcased, space becomes underscore, converted to symbols.
|
||||
def normalize_key_and_value(k,v)
|
||||
v = v ? v.strip : true # no value defaults to true
|
||||
k = k.strip
|
||||
|
||||
# check synonyms
|
||||
v = true if ['yes','true'].include?(v.to_s.downcase)
|
||||
v = false if ['no','false'].include?(v.to_s.downcase)
|
||||
|
||||
k = k.downcase.gsub(' ','_')
|
||||
return k, v
|
||||
end
|
||||
|
||||
# Returns the number of leading spaces, considering that
|
||||
# a tab counts as `TabSize` spaces.
|
||||
def number_of_leading_spaces(s)
|
||||
s[/^[ \t]*/].gsub("\t", ' '*TabSize).length
|
||||
end
|
||||
# Split a string into multiple lines,
|
||||
# on line feeds and/or carriage returns.
|
||||
#
|
||||
# @param s [String]
|
||||
# @return [String]
|
||||
def split_lines(s)
|
||||
s.split(/\r\n|\r|\n/)
|
||||
end
|
||||
|
||||
# This returns the position of the first real char in a list item
|
||||
#
|
||||
# For example:
|
||||
# '*Hello' # => 1
|
||||
# '* Hello' # => 2
|
||||
# ' * Hello' # => 3
|
||||
# ' * Hello' # => 5
|
||||
# '1.Hello' # => 2
|
||||
# ' 1. Hello' # => 5
|
||||
|
||||
def spaces_before_first_char(s)
|
||||
case s.md_type
|
||||
when :ulist
|
||||
# whitespace, followed by ('*'|'+'|'-') followed by
|
||||
# more whitespace, followed by an optional IAL, followed
|
||||
# by yet more whitespace
|
||||
h=s[/^\s*(\*|\+|\-)\s*(\{.*?\})?\s*/]
|
||||
when :olist
|
||||
# whitespace, followed by a number, followed by a period,
|
||||
# more whitespace, an optional IAL, and more whitespace
|
||||
h=s[/^\s*\d+\.\s*(\{.*?\})?\s*/]
|
||||
else
|
||||
tell_user "BUG (my bad): '#{s}' is not a list"
|
||||
h=''
|
||||
end
|
||||
ial = h[/\{.*\}/]
|
||||
return [h.length, ial]
|
||||
end
|
||||
# Parses email headers, returning a hash.
|
||||
# `hash[:data]` is the message;
|
||||
# that is, anything past the headers.
|
||||
#
|
||||
# Keys are downcased and converted to symbols;
|
||||
# spaces become underscores. For example:
|
||||
#
|
||||
# !!!plain
|
||||
# My key: true
|
||||
#
|
||||
# becomes:
|
||||
#
|
||||
# {:my_key => true}
|
||||
#
|
||||
# @param s [String] The email
|
||||
# @return [Symbol => String] The header values
|
||||
def parse_email_headers(s)
|
||||
headers = {}
|
||||
scanner = StringScanner.new(s)
|
||||
|
||||
# Counts the number of leading '#' in the string
|
||||
def num_leading_hashes(s)
|
||||
h = s[/^#*/]
|
||||
h ? h.length : 0
|
||||
end
|
||||
|
||||
# Strips initial and final hashes
|
||||
def strip_hashes(s)
|
||||
s.sub(/^#*(.*?)(#|\s)*$/, '\1').strip
|
||||
end
|
||||
|
||||
# change space to "_" and remove any non-word character
|
||||
def sanitize_ref_id(x)
|
||||
x.downcase.gsub(' ','_').gsub(/[^\w]/,'')
|
||||
end
|
||||
while scanner.scan(/(\w[\w\s\-]+): +(.*)\n/)
|
||||
k, v = normalize_key_and_value(scanner[1], scanner[2])
|
||||
headers[k.to_sym] = v
|
||||
end
|
||||
|
||||
headers[:data] = scanner.rest
|
||||
headers
|
||||
end
|
||||
|
||||
# removes initial quote
|
||||
def unquote(s)
|
||||
s.gsub(/^>\s?/,'')
|
||||
end
|
||||
# Returns the number of leading spaces,
|
||||
# considering that a tab counts as {TAB_SIZE} spaces.
|
||||
#
|
||||
# @param s [String]
|
||||
# @return [Fixnum]
|
||||
def number_of_leading_spaces(s)
|
||||
spaces = s.scan(/^\s*/).first
|
||||
spaces.count(" ") + spaces.count("\t") * TAB_SIZE
|
||||
end
|
||||
|
||||
# toglie al massimo n caratteri
|
||||
def strip_indent(s, n)
|
||||
i = 0
|
||||
while i < s.size && n>0
|
||||
c = s[i,1]
|
||||
if c == ' '
|
||||
n-=1;
|
||||
elsif c == "\t"
|
||||
n-=TabSize;
|
||||
else
|
||||
break
|
||||
end
|
||||
i+=1
|
||||
end
|
||||
s[i, s.size]
|
||||
end
|
||||
# This returns the position of the first non-list character
|
||||
# in a list item.
|
||||
#
|
||||
# @example
|
||||
# spaces_before_first_char('*Hello') #=> 1
|
||||
# spaces_before_first_char('* Hello') #=> 2
|
||||
# spaces_before_first_char(' * Hello') #=> 3
|
||||
# spaces_before_first_char(' * Hello') #=> 5
|
||||
# spaces_before_first_char('1.Hello') #=> 2
|
||||
# spaces_before_first_char(' 1. Hello') #=> 5
|
||||
#
|
||||
# @param s [String]
|
||||
# @return [Fixnum]
|
||||
def spaces_before_first_char(s)
|
||||
match =
|
||||
case s.md_type
|
||||
when :ulist
|
||||
# whitespace, followed by ('*'|'+'|'-') followed by
|
||||
# more whitespace, followed by an optional IAL, followed
|
||||
# by yet more whitespace
|
||||
s[/^\s*(\*|\+|\-)\s*(\{.*?\})?\s*/]
|
||||
when :olist
|
||||
# whitespace, followed by a number, followed by a period,
|
||||
# more whitespace, an optional IAL, and more whitespace
|
||||
s[/^\s*\d+\.\s*(\{.*?\})?\s*/]
|
||||
else
|
||||
tell_user "BUG (my bad): '#{s}' is not a list"
|
||||
''
|
||||
end
|
||||
ial = match[/\{.*\}/]
|
||||
return [match.length, ial]
|
||||
end
|
||||
|
||||
def dbg_describe_ary(a, prefix='')
|
||||
i = 0
|
||||
a.each do |l|
|
||||
puts "#{prefix} (#{i+=1})# #{l.inspect}"
|
||||
end
|
||||
end
|
||||
# Replace spaces with underscores and remove non-word characters.
|
||||
#
|
||||
# @param s [String]
|
||||
# @return [String]
|
||||
def sanitize_ref_id(s)
|
||||
s.strip.downcase.gsub(' ', '_').gsub(/[^\w]/, '')
|
||||
end
|
||||
|
||||
def force_linebreak?(l)
|
||||
l =~ / $/
|
||||
end
|
||||
# Remove line-initial `>` characters for a quotation.
|
||||
#
|
||||
# @param s [String]
|
||||
# @return [String]
|
||||
def unquote(s)
|
||||
s.gsub(/^>\s?/, '')
|
||||
end
|
||||
|
||||
end
|
||||
# Removes indentation from the beginning of `s`,
|
||||
# up to at most `n` spaces.
|
||||
# Tabs are counted as {TAB_SIZE} spaces.
|
||||
#
|
||||
# @param s [String]
|
||||
# @param n [Fixnum]
|
||||
# @return [String]
|
||||
def strip_indent(s, n)
|
||||
while n > 0
|
||||
case s[0]
|
||||
when ?\s; n -= 1
|
||||
when ?\t; n -= TAB_SIZE
|
||||
else; return s
|
||||
end
|
||||
s = s[1..-1]
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
# Escapes a string so that it can be safely used in a Bourne shell command line.
|
||||
#
|
||||
# Note that a resulted string should be used unquoted
|
||||
# and is not intended for use in double quotes nor in single quotes.
|
||||
#
|
||||
# This is a copy of the Shellwords.shellescape function in Ruby 1.8.7.
|
||||
# It's included for Ruby 1.8.6 compatibility.
|
||||
#
|
||||
# @param str [String]
|
||||
# @return [String]
|
||||
def shellescape(str)
|
||||
# An empty argument will be skipped, so return empty quotes.
|
||||
return "''" if str.empty?
|
||||
|
||||
str = str.dup
|
||||
|
||||
# Process as a single byte sequence because not all shell
|
||||
# implementations are multibyte aware.
|
||||
str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
|
||||
|
||||
# A LF cannot be escaped with a backslash because a backslash + LF
|
||||
# combo is regarded as line continuation and simply ignored.
|
||||
str.gsub!(/\n/, "'\n'")
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Normalize the key/value pairs for email headers.
|
||||
# Keys are downcased and converted to symbols;
|
||||
# spaces become underscores.
|
||||
#
|
||||
# Values of `"yes"`, `"true"`, `"no"`, and `"false"`
|
||||
# are converted to appropriate booleans.
|
||||
#
|
||||
# @param k [String]
|
||||
# @param v [String]
|
||||
# @return [Array(String, String or Boolean)]
|
||||
def normalize_key_and_value(k, v)
|
||||
k = k.strip.downcase.gsub(/\s+/, '_')
|
||||
v = v.strip
|
||||
|
||||
# check synonyms
|
||||
return k, true if %w[yes true].include?(v.downcase)
|
||||
return k, false if %w[no false].include?(v.downcase)
|
||||
return k, v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
273
vendor/plugins/maruku/lib/maruku/structures.rb
vendored
273
vendor/plugins/maruku/lib/maruku/structures.rb
vendored
|
@ -1,170 +1,143 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
|
||||
class Module
|
||||
def safe_attr_accessor1(symbol, klass)
|
||||
attr_reader symbol
|
||||
code = <<-EOF
|
||||
def #{symbol}=(val)
|
||||
if not val.kind_of? #{klass}
|
||||
s = "\nCould not assign an object of type \#{val.class} to #{symbol}.\n\n"
|
||||
s += "Tried to assign object of class \#{val.class}:\n"+
|
||||
"\#{val.inspect}\n"+
|
||||
"to \#{self.class}::#{symbol} constrained to be of class #{klass}.\n"
|
||||
raise s
|
||||
end
|
||||
@#{symbol} = val
|
||||
end
|
||||
|
||||
EOF
|
||||
module_eval code
|
||||
end
|
||||
|
||||
def safe_attr_accessor2(symbol, klass)
|
||||
attr_accessor symbol
|
||||
end
|
||||
|
||||
alias safe_attr_accessor safe_attr_accessor2
|
||||
end
|
||||
|
||||
module MaRuKu
|
||||
|
||||
# I did not want to have a class for each possible element.
|
||||
# Instead I opted to have only the class "MDElement"
|
||||
# that represents eveything in the document (paragraphs, headers, etc).
|
||||
#
|
||||
# You can tell what it is by the variable `node_type`.
|
||||
#
|
||||
# In the instance-variable `children` there are the children. These
|
||||
# can be of class 1) String or 2) MDElement.
|
||||
#
|
||||
# The @doc variable points to the document to which the MDElement
|
||||
# belongs (which is an instance of Maruku, subclass of MDElement).
|
||||
#
|
||||
# Attributes are contained in the hash `attributes`.
|
||||
# Keys are symbols (downcased, with spaces substituted by underscores)
|
||||
#
|
||||
# For example, if you write in the source document.
|
||||
#
|
||||
# Title: test document
|
||||
# My property: value
|
||||
#
|
||||
# content content
|
||||
#
|
||||
# You can access `value` by writing:
|
||||
#
|
||||
# @doc.attributes[:my_property] # => 'value'
|
||||
#
|
||||
# from whichever MDElement in the hierarchy.
|
||||
#
|
||||
class MDElement
|
||||
# See helpers.rb for the list of allowed #node_type values
|
||||
safe_attr_accessor :node_type, Symbol
|
||||
|
||||
# Children are either Strings or MDElement
|
||||
safe_attr_accessor :children, Array
|
||||
|
||||
# An attribute list, may not be nil
|
||||
safe_attr_accessor :al, Array #Maruku::AttributeList
|
||||
# Rather than having a separate class for every possible element,
|
||||
# Maruku has a single {MDElement} class
|
||||
# that represents eveything in the document (paragraphs, headers, etc).
|
||||
# The type of each element is available via \{#node\_type}.
|
||||
class MDElement
|
||||
# The type of this node (e.g. `:quote`, `:image`, `:abbr`).
|
||||
# See {Helpers} for a list of possible values.
|
||||
#
|
||||
# @return [Symbol]
|
||||
attr_accessor :node_type
|
||||
|
||||
# These are the processed attributes
|
||||
safe_attr_accessor :attributes, Hash
|
||||
|
||||
# Reference of the document (which is of class Maruku)
|
||||
attr_accessor :doc
|
||||
|
||||
def initialize(node_type=:unset, children=[], meta={},
|
||||
al=MaRuKu::AttributeList.new )
|
||||
super();
|
||||
self.children = children
|
||||
self.node_type = node_type
|
||||
|
||||
@attributes = {}
|
||||
|
||||
meta.each do |symbol, value|
|
||||
self.instance_eval "
|
||||
def #{symbol}; @#{symbol}; end
|
||||
def #{symbol}=(val); @#{symbol}=val; end"
|
||||
self.send "#{symbol}=", value
|
||||
end
|
||||
|
||||
self.al = al || AttributeList.new
|
||||
# The child nodes of this element.
|
||||
#
|
||||
# @return [Array<String or MDElement>]
|
||||
attr_accessor :children
|
||||
|
||||
self.meta_priv = meta
|
||||
end
|
||||
|
||||
attr_accessor :meta_priv
|
||||
|
||||
def ==(o)
|
||||
ok = o.kind_of?(MDElement) &&
|
||||
(self.node_type == o.node_type) &&
|
||||
(self.meta_priv == o.meta_priv) &&
|
||||
(self.children == o.children)
|
||||
|
||||
if not ok
|
||||
# puts "This:\n"+self.inspect+"\nis different from\n"+o.inspect+"\n\n"
|
||||
end
|
||||
ok
|
||||
end
|
||||
# An attribute list. May not be nil.
|
||||
#
|
||||
# @return [AttributeList]
|
||||
attr_accessor :al
|
||||
|
||||
# The processed attributes.
|
||||
#
|
||||
# For the {Maruku document root},
|
||||
# this contains properties listed
|
||||
# at the beginning of the document.
|
||||
# The properties will be downcased and any spaces
|
||||
# will be converted to underscores.
|
||||
# For example, if you write in the source document:
|
||||
#
|
||||
# !!!text
|
||||
# Title: test document
|
||||
# My property: value
|
||||
#
|
||||
# content content
|
||||
#
|
||||
# Then \{#attributes} will return:
|
||||
#
|
||||
# {:title => "test document", :my_property => "value"}
|
||||
#
|
||||
# @return [{Symbol => String}]
|
||||
attr_accessor :attributes
|
||||
|
||||
# The root element of the document
|
||||
# to which this element belongs.
|
||||
#
|
||||
# @return [Maruku]
|
||||
attr_accessor :doc
|
||||
|
||||
def initialize(node_type = :unset, children = [], meta = {}, al = nil)
|
||||
self.children = children
|
||||
self.node_type = node_type
|
||||
self.attributes = {}
|
||||
|
||||
meta.each do |symbol, value|
|
||||
self.instance_eval <<RUBY
|
||||
def #{symbol}; @#{symbol}; end
|
||||
def #{symbol}=(val); @#{symbol} = val; end
|
||||
RUBY
|
||||
self.send "#{symbol}=", value
|
||||
end
|
||||
|
||||
self.al = al || AttributeList.new
|
||||
self.meta_priv = meta
|
||||
end
|
||||
|
||||
# @private
|
||||
attr_accessor :meta_priv
|
||||
|
||||
def ==(o)
|
||||
o.is_a?(MDElement) &&
|
||||
self.node_type == o.node_type &&
|
||||
self.meta_priv == o.meta_priv &&
|
||||
self.children == o.children
|
||||
end
|
||||
end
|
||||
|
||||
# This represents the whole document and holds global data.
|
||||
class MDDocument
|
||||
# @return [{String => {:url => String, :title => String}}]
|
||||
attr_accessor :refs
|
||||
|
||||
# @return [{String => MDElement}]
|
||||
attr_accessor :footnotes
|
||||
|
||||
# @return [{String => String}]
|
||||
attr_accessor :abbreviations
|
||||
|
||||
# Attribute definition lists.
|
||||
#
|
||||
# @return [{String => AttributeList}]
|
||||
attr_accessor :ald
|
||||
|
||||
# The order in which footnotes are used. Contains the id.
|
||||
#
|
||||
# @return [Array<String>]
|
||||
attr_accessor :footnotes_order
|
||||
|
||||
# @return [Array<String>]
|
||||
attr_accessor :latex_required_packages
|
||||
|
||||
# @return [{String => {String => MDElement}}]
|
||||
attr_accessor :refid2ref
|
||||
|
||||
# A counter for generating unique IDs [Integer]
|
||||
attr_accessor :id_counter
|
||||
|
||||
def initialize(s=nil)
|
||||
super(:document)
|
||||
|
||||
self.doc = self
|
||||
self.refs = {}
|
||||
self.footnotes = {}
|
||||
self.footnotes_order = []
|
||||
self.abbreviations = {}
|
||||
self.ald = {}
|
||||
self.latex_required_packages = []
|
||||
self.id_counter = 0
|
||||
|
||||
parse_doc(s) if s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This represents the whole document and holds global data.
|
||||
|
||||
class MDDocument
|
||||
|
||||
safe_attr_accessor :refs, Hash
|
||||
safe_attr_accessor :footnotes, Hash
|
||||
|
||||
# This is an hash. The key might be nil.
|
||||
safe_attr_accessor :abbreviations, Hash
|
||||
|
||||
# Attribute lists definition
|
||||
safe_attr_accessor :ald, Hash
|
||||
|
||||
# The order in which footnotes are used. Contains the id.
|
||||
safe_attr_accessor :footnotes_order, Array
|
||||
|
||||
safe_attr_accessor :latex_required_packages, Array
|
||||
|
||||
safe_attr_accessor :refid2ref, Hash
|
||||
# A counter for generating unique IDs
|
||||
safe_attr_accessor :id_counter, Integer
|
||||
|
||||
def initialize(s=nil)
|
||||
super(:document)
|
||||
@doc = self
|
||||
|
||||
self.refs = {}
|
||||
self.footnotes = {}
|
||||
self.footnotes_order = []
|
||||
self.abbreviations = {}
|
||||
self.ald = {}
|
||||
self.latex_required_packages = []
|
||||
self.id_counter = 0
|
||||
|
||||
parse_doc(s) if s
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end # MaRuKu
|
||||
|
||||
|
|
|
@ -1,87 +1,51 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
|
||||
class String
|
||||
def inspect_more(a=nil,b=nil)
|
||||
inspect
|
||||
end
|
||||
end
|
||||
|
||||
class Object
|
||||
def inspect_more(a=nil,b=nil)
|
||||
inspect
|
||||
end
|
||||
end
|
||||
|
||||
class Array
|
||||
def inspect_more(compact, join_string, add_brackets=true)
|
||||
s = map {|x|
|
||||
x.kind_of?(String) ? x.inspect :
|
||||
x.kind_of?(MaRuKu::MDElement) ? x.inspect(compact) :
|
||||
(raise "WTF #{x.class} #{x.inspect}")
|
||||
}.join(join_string)
|
||||
|
||||
add_brackets ? "[#{s}]" : s
|
||||
end
|
||||
end
|
||||
|
||||
class Hash
|
||||
def inspect_ordered(a=nil,b=nil)
|
||||
"{"+keys.map{|x|x.to_s}.sort.map{|x|x.to_sym}.
|
||||
map{|k| k.inspect + "=>"+self[k].inspect}.join(',')+"}"
|
||||
end
|
||||
end
|
||||
|
||||
module MaRuKu
|
||||
class MDElement
|
||||
def inspect(compact=true)
|
||||
if compact
|
||||
i2 = inspect2
|
||||
return i2 if i2
|
||||
end
|
||||
|
||||
"md_el(:%s,%s,%s,%s)" %
|
||||
[
|
||||
self.node_type,
|
||||
children_inspect(compact),
|
||||
@meta_priv.inspect_ordered,
|
||||
self.al.inspect
|
||||
]
|
||||
end
|
||||
class MDElement
|
||||
def inspect(compact=true)
|
||||
if compact
|
||||
i2 = inspect2
|
||||
return i2 if i2
|
||||
end
|
||||
|
||||
def children_inspect(compact=true)
|
||||
s = @children.inspect_more(compact,', ')
|
||||
if @children.empty?
|
||||
"[]"
|
||||
elsif s.size < 70
|
||||
s
|
||||
else
|
||||
"[\n"+
|
||||
add_tabs(@children.inspect_more(compact,",\n",false))+
|
||||
"\n]"
|
||||
end
|
||||
end
|
||||
|
||||
# Make sure the attributes are lexically ordered
|
||||
meta_ordered = "{" + @meta_priv.keys.
|
||||
map {|x| x.to_s}.sort.map {|x| x.to_sym}.
|
||||
map {|k| k.inspect + "=>" + @meta_priv[k].inspect}.
|
||||
join(',') + "}"
|
||||
|
||||
"md_el(%s,%s,%s,%s)" % [
|
||||
self.node_type.inspect,
|
||||
children_inspect(compact),
|
||||
meta_ordered,
|
||||
self.al.inspect
|
||||
]
|
||||
end
|
||||
|
||||
def children_inspect(compact=true)
|
||||
kids = @children.map {|x| x.is_a?(MDElement) ? x.inspect(compact) : x.inspect}
|
||||
comma = kids.join(", ")
|
||||
|
||||
return "[#{comma}]" if comma.size < 70
|
||||
"[\n\t#{kids.join(",\n\t")}\n]"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,61 +1,48 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
module MaRuKu
|
||||
class MDElement
|
||||
# Iterates through each {MDElement} child node of this element.
|
||||
# This includes deeply-nested child nodes.
|
||||
# If `e_node_type` is specified, only yields nodes of that type.
|
||||
def each_element(e_node_type=nil, &block)
|
||||
@children.each do |c|
|
||||
next unless c.is_a? MDElement
|
||||
yield c if e_node_type.nil? || c.node_type == e_node_type
|
||||
c.each_element(e_node_type, &block)
|
||||
end
|
||||
end
|
||||
|
||||
class MDElement
|
||||
|
||||
# Yields to each element of specified node_type
|
||||
# All elements if e_node_type is nil.
|
||||
def each_element(e_node_type=nil, &block)
|
||||
@children.each do |c|
|
||||
if c.kind_of? MDElement
|
||||
if (not e_node_type) || (e_node_type == c.node_type)
|
||||
block.call c
|
||||
end
|
||||
c.each_element(e_node_type, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Apply passed block to each String in the hierarchy.
|
||||
def replace_each_string(&block)
|
||||
for c in @children
|
||||
if c.kind_of? MDElement
|
||||
c.replace_each_string(&block)
|
||||
end
|
||||
end
|
||||
|
||||
processed = []
|
||||
until @children.empty?
|
||||
c = @children.shift
|
||||
if c.kind_of? String
|
||||
result = block.call(c)
|
||||
[*result].each do |e| processed << e end
|
||||
else
|
||||
processed << c
|
||||
end
|
||||
end
|
||||
@children = processed
|
||||
end
|
||||
|
||||
# Iterates through each String child node of this element,
|
||||
# replacing it with the result of the block.
|
||||
# This includes deeply-nested child nodes.
|
||||
#
|
||||
# This destructively modifies this node and its children.
|
||||
#
|
||||
# @todo Make this non-destructive
|
||||
def replace_each_string(&block)
|
||||
@children.map! do |c|
|
||||
next yield c unless c.is_a?(MDElement)
|
||||
c.replace_each_string(&block)
|
||||
c
|
||||
end.flatten!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,82 +0,0 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
require 'maruku'
|
||||
#require 'bluecloth'
|
||||
|
||||
|
||||
data = $stdin.read
|
||||
|
||||
num = 10
|
||||
|
||||
if ARGV.size > 0 && ((n=ARGV[0].to_i) != 0)
|
||||
num = n
|
||||
end
|
||||
|
||||
methods =
|
||||
[
|
||||
|
||||
[Maruku, :to_html],
|
||||
# [BlueCloth, :to_html],
|
||||
[Maruku, :to_latex]
|
||||
|
||||
]
|
||||
|
||||
#methods = [[Maruku, :class]]
|
||||
#num = 10
|
||||
|
||||
stats =
|
||||
methods .map do |c, method|
|
||||
puts "Computing for #{c}"
|
||||
|
||||
start = Time.now
|
||||
doc = nil
|
||||
for i in 1..num
|
||||
$stdout.write "#{i} "; $stdout.flush
|
||||
doc = c.new(data)
|
||||
end
|
||||
stop = Time.now
|
||||
parsing = (stop-start)/num
|
||||
|
||||
start = Time.now
|
||||
for i in 1..num
|
||||
$stdout.write "#{i} "; $stdout.flush
|
||||
s = doc.send method
|
||||
end
|
||||
stop = Time.now
|
||||
rendering = (stop-start)/num
|
||||
|
||||
puts ("%s (%s): parsing %0.2f sec + rendering %0.2f sec "+
|
||||
"= %0.2f sec ") % [c, method, parsing,rendering,parsing+rendering]
|
||||
|
||||
[c, method, parsing, rendering]
|
||||
end
|
||||
|
||||
puts "\n\n\n"
|
||||
stats.each do |x| x.push(x[2]+x[3]) end
|
||||
max = stats.map{|x|x[4]}.max
|
||||
stats.sort! { |x,y| x[4] <=> y[4] } . reverse!
|
||||
for c, method, parsing, rendering, tot in stats
|
||||
puts ("%20s: parsing %0.2f sec + rendering %0.2f sec "+
|
||||
"= %0.2f sec (%0.2fx)") %
|
||||
["#{c} (#{method})", parsing,rendering,tot,max/tot]
|
||||
end
|
||||
|
373
vendor/plugins/maruku/lib/maruku/tests/new_parser.rb
vendored
373
vendor/plugins/maruku/lib/maruku/tests/new_parser.rb
vendored
|
@ -1,373 +0,0 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
require 'maruku'
|
||||
require 'maruku/ext/math'
|
||||
|
||||
module MaRuKu; module Tests
|
||||
# 5 accented letters in italian, encoded as UTF-8
|
||||
AccIta8 = "\303\240\303\250\303\254\303\262\303\271"
|
||||
|
||||
# Same letters, written in ISO-8859-1 (one byte per letter)
|
||||
AccIta1 = "\340\350\354\362\371"
|
||||
|
||||
# The word MA-RU-KU, written in katakana using UTF-8
|
||||
Maruku8 = "\343\203\236\343\203\253\343\202\257"
|
||||
|
||||
def test_span_parser(verbose, break_on_first_error, quiet)
|
||||
good_cases = [
|
||||
|
||||
["", [], 'Empty string gives empty list'],
|
||||
["a", ["a"], 'Easy char'],
|
||||
[" a", ["a"], 'First space in the paragraph is ignored'],
|
||||
["a\n \n", ["a"], 'Last spaces in the paragraphs are ignored'],
|
||||
[' ', [], 'One char => nothing'],
|
||||
[' ', [], 'Two chars => nothing'],
|
||||
['a b', ['a b'], 'Spaces are compressed'],
|
||||
['a b', ['a b'], 'Newlines are spaces'],
|
||||
["a\nb", ['a b'], 'Newlines are spaces'],
|
||||
["a\n b", ['a b'], 'Compress newlines 1'],
|
||||
["a \nb", ['a b'], 'Compress newlines 2'],
|
||||
[" \nb", ['b'], 'Compress newlines 3'],
|
||||
["\nb", ['b'], 'Compress newlines 4'],
|
||||
["b\n", ['b'], 'Compress newlines 5'],
|
||||
["\n", [], 'Compress newlines 6'],
|
||||
["\n\n\n", [], 'Compress newlines 7'],
|
||||
|
||||
[nil, :throw, "Should throw on nil input"],
|
||||
|
||||
# Code blocks
|
||||
["`" , :throw, 'Unclosed single ticks'],
|
||||
["``" , :throw, 'Unclosed double ticks'],
|
||||
["`a`" , [md_code('a')], 'Simple inline code'],
|
||||
["`` ` ``" , [md_code('`')], ],
|
||||
["`` \\` ``" , [md_code('\\`')], ],
|
||||
["``a``" , [md_code('a')], ],
|
||||
["`` a ``" , [md_code('a')], ],
|
||||
|
||||
# Newlines
|
||||
["a \n", ['a',md_el(:linebreak)], 'Two spaces give br.'],
|
||||
["a \n", ['a'], 'Newlines 2'],
|
||||
[" \n", [md_el(:linebreak)], 'Newlines 3'],
|
||||
[" \n \n", [md_el(:linebreak),md_el(:linebreak)],'Newlines 3'],
|
||||
[" \na \n", [md_el(:linebreak),'a',md_el(:linebreak)],'Newlines 3'],
|
||||
|
||||
# Inline HTML
|
||||
["a < b", ['a < b'], '< can be on itself'],
|
||||
["<hr>", [md_html('<hr />')], 'HR will be sanitized'],
|
||||
["<hr/>", [md_html('<hr />')], 'Closed tag is ok'],
|
||||
["<hr />", [md_html('<hr />')], 'Closed tag is ok 2'],
|
||||
["<hr/>a", [md_html('<hr />'),'a'], 'Closed tag is ok 2'],
|
||||
["<em></em>a", [md_html('<em></em>'),'a'], 'Inline HTML 1'],
|
||||
["<em>e</em>a", [md_html('<em>e</em>'),'a'], 'Inline HTML 2'],
|
||||
["a<em>e</em>b", ['a',md_html('<em>e</em>'),'b'], 'Inline HTML 3'],
|
||||
["<em>e</em>a<em>f</em>",
|
||||
[md_html('<em>e</em>'),'a',md_html('<em>f</em>')],
|
||||
'Inline HTML 4'],
|
||||
["<em>e</em><em>f</em>a",
|
||||
[md_html('<em>e</em>'),md_html('<em>f</em>'),'a'],
|
||||
'Inline HTML 5'],
|
||||
|
||||
["<img src='a' />", [md_html("<img src='a' />")], 'Attributes'],
|
||||
["<img src='a'/>"],
|
||||
|
||||
# emphasis
|
||||
["**", :throw, 'Unclosed double **'],
|
||||
["\\*", ['*'], 'Escaping of *'],
|
||||
["a *b* ", ['a ', md_em('b')], 'Emphasis 1'],
|
||||
["a *b*", ['a ', md_em('b')], 'Emphasis 2'],
|
||||
["a * b", ['a * b'], 'Emphasis 3'],
|
||||
["a * b*", :throw, 'Unclosed emphasis'],
|
||||
# same with underscore
|
||||
["__", :throw, 'Unclosed double __'],
|
||||
["\\_", ['_'], 'Escaping of _'],
|
||||
["a _b_ ", ['a ', md_em('b')], 'Emphasis 4'],
|
||||
["a _b_", ['a ', md_em('b')], 'Emphasis 5'],
|
||||
["a _ b", ['a _ b'], 'Emphasis 6'],
|
||||
["a _ b_", :throw, 'Unclosed emphasis'],
|
||||
["_b_", [md_em('b')], 'Emphasis 7'],
|
||||
["_b_ _c_", [md_em('b'),' ',md_em('c')], 'Emphasis 8'],
|
||||
["_b__c_", [md_em('b'),md_em('c')], 'Emphasis 9'],
|
||||
# underscores in word
|
||||
["mod_ruby", ['mod_ruby'], 'Word with underscore'],
|
||||
# strong
|
||||
["**a*", :throw, 'Unclosed double ** 2'],
|
||||
["\\**a*", ['*', md_em('a')], 'Escaping of *'],
|
||||
["a **b** ", ['a ', md_strong('b')], 'Emphasis 1'],
|
||||
["a **b**", ['a ', md_strong('b')], 'Emphasis 2'],
|
||||
["a ** b", ['a ** b'], 'Emphasis 3'],
|
||||
["a ** b**", :throw, 'Unclosed emphasis'],
|
||||
["**b****c**", [md_strong('b'),md_strong('c')], 'Emphasis 9'],
|
||||
# strong (with underscore)
|
||||
["__a_", :throw, 'Unclosed double __ 2'],
|
||||
|
||||
# ["\\__a_", ['_', md_em('a')], 'Escaping of _'],
|
||||
["a __b__ ", ['a ', md_strong('b')], 'Emphasis 1'],
|
||||
["a __b__", ['a ', md_strong('b')], 'Emphasis 2'],
|
||||
["a __ b", ['a __ b'], 'Emphasis 3'],
|
||||
["a __ b__", :throw, 'Unclosed emphasis'],
|
||||
["__b____c__", [md_strong('b'),md_strong('c')], 'Emphasis 9'],
|
||||
# extra strong
|
||||
["***a**", :throw, 'Unclosed triple *** '],
|
||||
["\\***a**", ['*', md_strong('a')], 'Escaping of *'],
|
||||
["a ***b*** ", ['a ', md_emstrong('b')], 'Strong elements'],
|
||||
["a ***b***", ['a ', md_emstrong('b')]],
|
||||
["a *** b", ['a *** b']],
|
||||
["a ** * b", ['a ** * b']],
|
||||
["***b******c***", [md_emstrong('b'),md_emstrong('c')]],
|
||||
["a *** b***", :throw, 'Unclosed emphasis'],
|
||||
# same with underscores
|
||||
["___a__", :throw, 'Unclosed triple *** '],
|
||||
# ["\\___a__", ['_', md_strong('a')], 'Escaping of _'],
|
||||
["a ___b___ ", ['a ', md_emstrong('b')], 'Strong elements'],
|
||||
["a ___b___", ['a ', md_emstrong('b')]],
|
||||
["a ___ b", ['a ___ b']],
|
||||
["a __ _ b", ['a __ _ b']],
|
||||
["___b______c___", [md_emstrong('b'),md_emstrong('c')]],
|
||||
["a ___ b___", :throw, 'Unclosed emphasis'],
|
||||
# mixing is bad
|
||||
["*a_", :throw, 'Mixing is bad'],
|
||||
["_a*", :throw],
|
||||
["**a__", :throw],
|
||||
["__a**", :throw],
|
||||
["___a***", :throw],
|
||||
["***a___", :throw],
|
||||
# links of the form [text][ref]
|
||||
["\\[a]", ["[a]"], 'Escaping 1'],
|
||||
["\\[a\\]", ["[a]"], 'Escaping 2'],
|
||||
# This is valid in the new Markdown version
|
||||
# ["[a]", ["a"], 'Not a link'],
|
||||
["[a]", [ md_link(["a"],'a')], 'Empty link'],
|
||||
["[a][]", ],
|
||||
["[a][]b", [ md_link(["a"],'a'),'b'], 'Empty link'],
|
||||
["[a\\]][]", [ md_link(["a]"],'a')], 'Escape inside link (throw ?] away)'],
|
||||
|
||||
["[a", :throw, 'Link not closed'],
|
||||
["[a][", :throw, 'Ref not closed'],
|
||||
|
||||
# links of the form [text](url)
|
||||
["\\[a](b)", ["[a](b)"], 'Links'],
|
||||
["[a](url)c", [md_im_link(['a'],'url'),'c'], 'url'],
|
||||
["[a]( url )c" ],
|
||||
["[a] ( url )c" ],
|
||||
["[a] ( url)c" ],
|
||||
|
||||
["[a](ur:/l/ 'Title')", [md_im_link(['a'],'ur:/l/','Title')],
|
||||
'url and title'],
|
||||
["[a] ( ur:/l/ \"Title\")" ],
|
||||
["[a] ( ur:/l/ \"Title\")" ],
|
||||
["[a]( ur:/l/ Title)", :throw, "Must quote title" ],
|
||||
|
||||
["[a](url 'Tit\\\"l\\\\e')", [md_im_link(['a'],'url','Tit"l\\e')],
|
||||
'url and title escaped'],
|
||||
["[a] ( url \"Tit\\\"l\\\\e\")" ],
|
||||
["[a] ( url \"Tit\\\"l\\\\e\" )" ],
|
||||
['[a] ( url "Tit\\"l\\\\e" )' ],
|
||||
["[a]()", [md_im_link(['a'],'')], 'No URL is OK'],
|
||||
|
||||
["[a](\"Title\")", :throw, "No url specified" ],
|
||||
["[a](url \"Title)", :throw, "Unclosed quotes" ],
|
||||
["[a](url \"Title\\\")", :throw],
|
||||
["[a](url \"Title\" ", :throw],
|
||||
|
||||
["[a](url \'Title\")", :throw, "Mixing is bad" ],
|
||||
["[a](url \"Title\')"],
|
||||
|
||||
["[a](/url)", [md_im_link(['a'],'/url')], 'Funny chars in url'],
|
||||
["[a](#url)", [md_im_link(['a'],'#url')]],
|
||||
["[a](</script?foo=1&bar=2>)", [md_im_link(['a'],'/script?foo=1&bar=2')]],
|
||||
|
||||
|
||||
# Images
|
||||
["\\![a](url)", ['!', md_im_link(['a'],'url') ], 'Escaping images'],
|
||||
|
||||
["![a](url)", [md_im_image(['a'],'url')], 'Image no title'],
|
||||
["![a]( url )" ],
|
||||
["![a] ( url )" ],
|
||||
["![a] ( url)" ],
|
||||
|
||||
["![a](url 'ti\"tle')", [md_im_image(['a'],'url','ti"tle')], 'Image with title'],
|
||||
['![a]( url "ti\\"tle")' ],
|
||||
|
||||
["![a](url", :throw, 'Invalid images'],
|
||||
["![a( url )" ],
|
||||
["![a] ('url )" ],
|
||||
|
||||
["![a][imref]", [md_image(['a'],'imref')], 'Image with ref'],
|
||||
["![a][ imref]"],
|
||||
["![a][ imref ]"],
|
||||
["![a][\timref\t]"],
|
||||
|
||||
|
||||
['<http://example.com/?foo=1&bar=2>',
|
||||
[md_url('http://example.com/?foo=1&bar=2')], 'Immediate link'],
|
||||
['a<http://example.com/?foo=1&bar=2>b',
|
||||
['a',md_url('http://example.com/?foo=1&bar=2'),'b'] ],
|
||||
['<andrea@censi.org>',
|
||||
[md_email('andrea@censi.org')], 'Email address'],
|
||||
['<mailto:andrea@censi.org>'],
|
||||
["Developmen <http://rubyforge.org/projects/maruku/>",
|
||||
["Developmen ", md_url("http://rubyforge.org/projects/maruku/")]],
|
||||
["a<!-- -->b", ['a',md_html('<!-- -->'),'b'],
|
||||
'HTML Comment'],
|
||||
|
||||
["a<!--", :throw, 'Bad HTML Comment'],
|
||||
["a<!-- ", :throw, 'Bad HTML Comment'],
|
||||
|
||||
["<?xml <?!--!`3 ?>", [md_xml_instr('xml','<?!--!`3')], 'XML processing instruction'],
|
||||
["<? <?!--!`3 ?>", [md_xml_instr('','<?!--!`3')] ],
|
||||
|
||||
["<? ", :throw, 'Bad Server directive'],
|
||||
|
||||
["a <b", :throw, 'Bad HTML 1'],
|
||||
["<b", :throw, 'Bad HTML 2'],
|
||||
["<b!", :throw, 'Bad HTML 3'],
|
||||
['`<div>`, `<table>`, `<pre>`, `<p>`',
|
||||
[md_code('<div>'),', ',md_code('<table>'),', ',
|
||||
md_code('<pre>'),', ',md_code('<p>')],
|
||||
'Multiple HTLM tags'],
|
||||
|
||||
["&andrea", ["&andrea"], 'Parsing of entities'],
|
||||
# no escaping is allowed
|
||||
# ["\\&andrea;", ["&andrea;"]],
|
||||
["l&andrea;", ["l", md_entity('andrea')] ],
|
||||
["&&andrea;", ["&", md_entity('andrea')] ],
|
||||
["&123;;&",[md_entity('123'),';',md_entity('amp')]],
|
||||
|
||||
["a\nThe [syntax page] [s] provides",
|
||||
['a The ', md_link(['syntax page'],'s'), ' provides'], 'Regression'],
|
||||
|
||||
['![a](url "ti"tle")', [md_im_image(['a'],'url','ti"tle')],
|
||||
"Image with quotes"],
|
||||
['![a](url \'ti"tle\')' ],
|
||||
|
||||
['[bar](/url/ "Title with "quotes" inside")',
|
||||
[md_im_link(["bar"],'/url/', 'Title with "quotes" inside')],
|
||||
"Link with quotes"],
|
||||
|
||||
# We dropped this idea
|
||||
# ['$20,000 and $30,000', ['$20,000 and $30,000'], 'Math: spaces'],
|
||||
['$20,000$', [md_inline_math('20,000')]],
|
||||
# ['$ 20,000$', ['$ 20,000$']],
|
||||
# ['$20,000 $ $20,000$', ['$20,000 $ ', md_inline_math('20,000')]],
|
||||
["#{Maruku8}", [Maruku8], "Reading UTF-8"],
|
||||
# ["#{AccIta1}", [AccIta8], "Converting ISO-8859-1 to UTF-8",
|
||||
# {:encoding => 'iso-8859-1'}],
|
||||
|
||||
]
|
||||
|
||||
good_cases = unit_tests_for_attribute_lists + good_cases
|
||||
|
||||
count = 1; last_comment=""; last_expected=:throw
|
||||
good_cases.each do |t|
|
||||
if not t[1]
|
||||
t[1] = last_expected
|
||||
else
|
||||
last_expected = t[1]
|
||||
end
|
||||
if not t[2]
|
||||
t[2] = last_comment + " #{count+=1}"
|
||||
else
|
||||
last_comment = t[2]; count=1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
@verbose = verbose
|
||||
m = Maruku.new
|
||||
m.attributes[:on_error] = :raise
|
||||
Globals[:debug_keep_ials] = true
|
||||
|
||||
num_ok = 0
|
||||
good_cases.each do |input, expected, comment|
|
||||
output = nil
|
||||
begin
|
||||
output = m.parse_span_better(input)
|
||||
#lines = Maruku.split_lines input
|
||||
#output = m.parse_lines_as_span(lines)
|
||||
rescue Exception => e
|
||||
if not expected == :throw
|
||||
ex = e.inspect+ "\n"+ e.backtrace.join("\n")
|
||||
s = comment+describe_difference(input, expected, output)
|
||||
|
||||
print_status(comment,'CRASHED :-(', ex+s)
|
||||
raise e if @break_on_first_error
|
||||
else
|
||||
quiet || print_status(comment,'OK')
|
||||
num_ok += 1
|
||||
end
|
||||
end
|
||||
|
||||
if not expected == :throw
|
||||
if not (expected == output)
|
||||
s = comment+describe_difference(input, expected, output)
|
||||
print_status(comment, 'FAILED', s)
|
||||
break if break_on_first_error
|
||||
else
|
||||
num_ok += 1
|
||||
quiet || print_status(comment, 'OK')
|
||||
end
|
||||
else # I expected a raise
|
||||
if output
|
||||
s = comment+describe_difference(input, expected, output)
|
||||
|
||||
print_status(comment, 'FAILED (no throw)', s)
|
||||
break if break_on_first_error
|
||||
end
|
||||
end
|
||||
end # do
|
||||
if num_ok != good_cases.size
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
PAD=40
|
||||
def print_status(comment, status, verbose_text=nil)
|
||||
if comment.size < PAD
|
||||
comment = comment + (" "*(PAD-comment.size))
|
||||
end
|
||||
puts "- #{comment} #{status}"
|
||||
if @verbose and verbose_text
|
||||
puts verbose_text
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def describe_difference(input, expected, output)
|
||||
"\nInput:\n #{input.inspect}" +
|
||||
"\nExpected:\n #{expected.inspect}" +
|
||||
"\nOutput:\n #{output.inspect}\n"
|
||||
end
|
||||
end end
|
||||
|
||||
class Maruku
|
||||
include MaRuKu::Tests
|
||||
end
|
||||
|
||||
verbose = ARGV.include? 'v'
|
||||
break_on_first = ARGV.include? 'b'
|
||||
quiet = ARGV.include? 'q'
|
||||
ok = Maruku.new.test_span_parser(verbose, break_on_first, quiet)
|
||||
|
||||
exit (ok ? 0 : 1)
|
136
vendor/plugins/maruku/lib/maruku/tests/tests.rb
vendored
136
vendor/plugins/maruku/lib/maruku/tests/tests.rb
vendored
|
@ -1,136 +0,0 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
require 'maruku'
|
||||
|
||||
class Maruku
|
||||
|
||||
|
||||
def Maruku.failed(test, doc, s)
|
||||
raise "Test failed: #{s}\n*****\n#{test}\n*****\n"+
|
||||
"#{doc.inspect}\n*****\n{doc.to_html}"
|
||||
end
|
||||
|
||||
def Maruku.metaTests
|
||||
ref = {:id => 'id1', :class => ['class1','class2'],
|
||||
:style=> 'Style is : important = for all } things'}
|
||||
|
||||
|
||||
tests = MetaTests.split('***')
|
||||
for test in tests
|
||||
#puts "Test: #{test.inspect}"
|
||||
doc = Maruku.new(test)
|
||||
|
||||
doc.children.size == 1 ||
|
||||
failed(test, doc, "children != 1")
|
||||
|
||||
|
||||
h = doc.children[0]
|
||||
|
||||
h.node_type==:header ||
|
||||
failed(test, doc, "child not header")
|
||||
|
||||
# puts doc.inspect
|
||||
# puts doc.to_html
|
||||
end
|
||||
end
|
||||
|
||||
MetaTests = <<EOF
|
||||
|
||||
# Head # {ref1 ref2 ref3}
|
||||
|
||||
{ref1}: id: id1; class: class1
|
||||
{ref2}: class: class2
|
||||
{ref3}: style: "Style is : important = for all } things"
|
||||
|
||||
***
|
||||
|
||||
# Head # {ref1 ref3 ref2}
|
||||
|
||||
{ref1}: id: id1; class: class1
|
||||
{ref2}: class: class2
|
||||
{ref3}: style: "Style is : important = for all } things"
|
||||
|
||||
***
|
||||
|
||||
# Head # {ref1 ref2 ref3}
|
||||
|
||||
{ref1}: id= id1; class=class1
|
||||
{ref2}: class=class2
|
||||
{ref3}: style="Style is : important = for all } things"
|
||||
|
||||
***
|
||||
|
||||
# Head # {ref1 ref2 ref3}
|
||||
|
||||
{ref1}: id=id1 class=class1
|
||||
{ref2}: class=class2
|
||||
{ref3}: style="Style is : important = for all } things"
|
||||
|
||||
***
|
||||
# Head # {ref1 ref2 ref3}
|
||||
|
||||
{ref1}: id:id1 class:class1
|
||||
{ref2}: class : class2
|
||||
{ref3}: style = "Style is : important = for all } things"
|
||||
|
||||
***
|
||||
# Head # {ref1 ref2 ref3}
|
||||
|
||||
{ref1}: id:id1 class:class1
|
||||
{ref2}: class : class2
|
||||
{ref3}: style = "Style is : important = for all } things"
|
||||
|
||||
***
|
||||
|
||||
# Head # {#id1 .class1 ref2 ref3}
|
||||
|
||||
{ref2}: class : class2
|
||||
{ref3}: style = "Style is : important = for all } things"
|
||||
|
||||
***
|
||||
|
||||
# Head # { #id1 .class1 ref2 ref3 }
|
||||
|
||||
{ref2}: class : class2
|
||||
{ref3}: style = "Style is : important = for all } things"
|
||||
|
||||
***
|
||||
|
||||
# Head # { id=id1 class=class1 ref2 ref3 }
|
||||
|
||||
{ref2}: class : class2
|
||||
{ref3}: style = "Style is : important = for all } things"
|
||||
|
||||
***
|
||||
|
||||
# Head # { id:id1 class="class1" class:"class2" style="Style is : important = for all } things"}
|
||||
|
||||
EOF
|
||||
|
||||
end
|
||||
|
||||
if File.basename($0) == 'tests.rb'
|
||||
Maruku.metaTests
|
||||
|
||||
end
|
||||
|
||||
|
377
vendor/plugins/maruku/lib/maruku/toc.rb
vendored
377
vendor/plugins/maruku/lib/maruku/toc.rb
vendored
|
@ -1,199 +1,214 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
module MaRuKu
|
||||
|
||||
class MDDocument
|
||||
# an instance of Section (see below)
|
||||
attr_accessor :toc
|
||||
# A section in the table of contents of a document.
|
||||
class Section
|
||||
# The depth of the section (0 for toplevel).
|
||||
#
|
||||
# Equivalent to `header_element.level`.
|
||||
#
|
||||
# @return [Fixnum]
|
||||
attr_accessor :section_level
|
||||
|
||||
# The nested section number, e.g. `[1, 2, 5]` for Section 1.2.5.
|
||||
#
|
||||
# @return [Array<Fixnum>]
|
||||
attr_accessor :section_number
|
||||
|
||||
# The `:header` node for this section.
|
||||
# The value of `meta[:section]` for the header will be this node.
|
||||
#
|
||||
# @return [MDElement]
|
||||
attr_accessor :header_element
|
||||
|
||||
# The immediate child nodes of this section.
|
||||
#
|
||||
# @todo Why does this never contain Strings?
|
||||
#
|
||||
# @return [Array<MDElement>]
|
||||
attr_accessor :immediate_children
|
||||
|
||||
# The subsections of this section.
|
||||
#
|
||||
# @return [Array<Section>]
|
||||
attr_accessor :section_children
|
||||
|
||||
def initialize
|
||||
@immediate_children = []
|
||||
@section_children = []
|
||||
end
|
||||
|
||||
def inspect(indent = 1)
|
||||
s = ""
|
||||
|
||||
if @header_element
|
||||
s << "\_" * indent <<
|
||||
"(#{@section_level})>\t #{@section_number.join('.')} : " <<
|
||||
@header_element.children_to_s <<
|
||||
" (id: '#{@header_element.attributes[:id]}')\n"
|
||||
else
|
||||
s << "Master\n"
|
||||
end
|
||||
@section_children.each {|c| s << c.inspect(indent+1)}
|
||||
|
||||
s
|
||||
end
|
||||
|
||||
# Assign \{#section\_number section numbers}
|
||||
# to this section and its children.
|
||||
# This also assigns the section number attribute
|
||||
# to the sections' headers.
|
||||
#
|
||||
# This should only be called on the root section.
|
||||
#
|
||||
# @overload def numerate
|
||||
def numerate(a = [])
|
||||
self.section_number = a
|
||||
section_children.each_with_index {|c, i| c.numerate(a + [i + 1])}
|
||||
if h = self.header_element
|
||||
h.attributes[:section_number] = self.section_number
|
||||
end
|
||||
end
|
||||
|
||||
include REXML
|
||||
|
||||
# Returns an HTML representation of the table of contents.
|
||||
#
|
||||
# This should only be called on the root section.
|
||||
def to_html
|
||||
div = Element.new 'div'
|
||||
div.attributes['class'] = 'maruku_toc'
|
||||
div << _to_html
|
||||
div
|
||||
end
|
||||
|
||||
# Returns a LaTeX representation of the table of contents.
|
||||
#
|
||||
# This should only be called on the root section.
|
||||
def to_latex
|
||||
_to_latex + "\n\n"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def _to_html
|
||||
ul = Element.new 'ul'
|
||||
# let's remove the bullets
|
||||
ul.attributes['style'] = 'list-style: none;'
|
||||
@section_children.each do |c|
|
||||
li = Element.new 'li'
|
||||
if span = c.header_element.render_section_number
|
||||
li << span
|
||||
end
|
||||
|
||||
a = c.header_element.wrap_as_element('a')
|
||||
a.delete_attribute 'id'
|
||||
a.attributes['href'] = "##{c.header_element.attributes[:id]}"
|
||||
|
||||
li << a
|
||||
li << c._to_html if c.section_children.size > 0
|
||||
ul << li
|
||||
end
|
||||
ul
|
||||
end
|
||||
|
||||
def _to_latex
|
||||
s = ""
|
||||
@section_children.each do |c|
|
||||
s << "\\noindent"
|
||||
if number = c.header_element.section_number
|
||||
s << number
|
||||
end
|
||||
id = c.header_element.attributes[:id]
|
||||
text = c.header_element.children_to_latex
|
||||
s << "\\hyperlink{#{id}}{#{text}}"
|
||||
s << "\\dotfill \\pageref*{#{id}} \\linebreak\n"
|
||||
s << c._to_latex if c.section_children.size > 0
|
||||
end
|
||||
s
|
||||
end
|
||||
end
|
||||
|
||||
class MDDocument
|
||||
# The table of contents for the document.
|
||||
#
|
||||
# @return [Section]
|
||||
attr_accessor :toc
|
||||
|
||||
def create_toc
|
||||
each_element(:header) {|h| h.attributes[:id] ||= h.generate_id}
|
||||
|
||||
stack = []
|
||||
|
||||
# The root section
|
||||
s = Section.new
|
||||
s.section_level = 0
|
||||
|
||||
stack.push s
|
||||
|
||||
# TODO: Clean up the logic here once we have better tests
|
||||
i = 0
|
||||
while i < @children.size
|
||||
while i < @children.size
|
||||
if @children[i].node_type == :header
|
||||
level = @children[i].level
|
||||
break if level <= stack.last.section_level + 1
|
||||
end
|
||||
|
||||
stack.last.immediate_children.push @children[i]
|
||||
i += 1
|
||||
end
|
||||
|
||||
break if i >= @children.size
|
||||
|
||||
header = @children[i]
|
||||
level = header.level
|
||||
|
||||
if level > stack.last.section_level
|
||||
# this level is inside
|
||||
|
||||
s2 = Section.new
|
||||
s2.section_level = level
|
||||
s2.header_element = header
|
||||
header.instance_variable_set :@section, s2
|
||||
|
||||
stack.last.section_children.push s2
|
||||
stack.push s2
|
||||
|
||||
i += 1
|
||||
elsif level == stack.last.section_level
|
||||
# this level is a sibling
|
||||
stack.pop
|
||||
else
|
||||
# this level is a parent
|
||||
stack.pop
|
||||
end
|
||||
end
|
||||
|
||||
# If there is only one big header, then assume it is the master
|
||||
s = s.section_children.first if s.section_children.size == 1
|
||||
|
||||
# Assign section numbers
|
||||
s.numerate
|
||||
|
||||
s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This represents a section in the TOC.
|
||||
class Section
|
||||
# a Fixnum, is == header_element.level
|
||||
attr_accessor :section_level
|
||||
|
||||
# An array of fixnum, like [1,2,5] for Section 1.2.5
|
||||
attr_accessor :section_number
|
||||
|
||||
# reference to header (header has h.meta[:section] to self)
|
||||
attr_accessor :header_element
|
||||
|
||||
# Array of immediate children of this element
|
||||
attr_accessor :immediate_children
|
||||
|
||||
# Array of Section inside this section
|
||||
attr_accessor :section_children
|
||||
|
||||
def initialize
|
||||
@immediate_children = []
|
||||
@section_children = []
|
||||
end
|
||||
end
|
||||
|
||||
class Section
|
||||
def inspect(indent=1)
|
||||
s = ""
|
||||
if @header_element
|
||||
s += "\_"*indent + "(#{@section_level})>\t #{@section_number.join('.')} : "
|
||||
s += @header_element.children_to_s +
|
||||
" (id: '#{@header_element.attributes[:id]}')\n"
|
||||
else
|
||||
s += "Master\n"
|
||||
end
|
||||
|
||||
@section_children.each do |c|
|
||||
s+=c.inspect(indent+1)
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
# Numerate this section and its children
|
||||
def numerate(a=[])
|
||||
self.section_number = a
|
||||
section_children.each_with_index do |c,i|
|
||||
c.numerate(a.clone.push(i+1))
|
||||
end
|
||||
if h = self.header_element
|
||||
h.attributes[:section_number] = self.section_number
|
||||
end
|
||||
end
|
||||
|
||||
include REXML
|
||||
# Creates an HTML toc.
|
||||
# Call this on the root
|
||||
def to_html
|
||||
div = Element.new 'div'
|
||||
div.attributes['class'] = 'maruku_toc'
|
||||
div << create_toc
|
||||
div
|
||||
end
|
||||
|
||||
def create_toc
|
||||
ul = Element.new 'ul'
|
||||
# let's remove the bullets
|
||||
ul.attributes['style'] = 'list-style: none;'
|
||||
@section_children.each do |c|
|
||||
li = Element.new 'li'
|
||||
if span = c.header_element.render_section_number
|
||||
li << span
|
||||
end
|
||||
a = c.header_element.wrap_as_element('a')
|
||||
a.delete_attribute 'id'
|
||||
a.attributes['href'] = "##{c.header_element.attributes[:id]}"
|
||||
li << a
|
||||
li << c.create_toc if c.section_children.size>0
|
||||
ul << li
|
||||
end
|
||||
ul
|
||||
end
|
||||
|
||||
# Creates a latex toc.
|
||||
# Call this on the root
|
||||
def to_latex
|
||||
to_latex_rec + "\n\n"
|
||||
end
|
||||
|
||||
def to_latex_rec
|
||||
s = ""
|
||||
@section_children.each do |c|
|
||||
s += "\\noindent"
|
||||
number = c.header_element.section_number
|
||||
s += number if number
|
||||
text = c.header_element.children_to_latex
|
||||
id = c.header_element.attributes[:id]
|
||||
s += "\\hyperlink{#{id}}{#{text}}"
|
||||
s += "\\dotfill \\pageref*{#{id}} \\linebreak\n"
|
||||
s += c.to_latex_rec if c.section_children.size>0
|
||||
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class MDDocument
|
||||
|
||||
def create_toc
|
||||
each_element(:header) do |h|
|
||||
h.attributes[:id] ||= h.generate_id
|
||||
end
|
||||
|
||||
stack = []
|
||||
|
||||
# the ancestor section
|
||||
s = Section.new
|
||||
s.section_level = 0
|
||||
|
||||
stack.push s
|
||||
|
||||
i = 0;
|
||||
while i < @children.size
|
||||
while i < @children.size
|
||||
if @children[i].node_type == :header
|
||||
level = @children[i].level
|
||||
break if level <= stack.last.section_level+1
|
||||
end
|
||||
|
||||
stack.last.immediate_children.push @children[i]
|
||||
i += 1
|
||||
end
|
||||
|
||||
break if i>=@children.size
|
||||
|
||||
header = @children[i]
|
||||
level = header.level
|
||||
|
||||
if level > stack.last.section_level
|
||||
# this level is inside
|
||||
|
||||
s2 = Section.new
|
||||
s2.section_level = level
|
||||
s2.header_element = header
|
||||
header.instance_variable_set :@section, s2
|
||||
|
||||
stack.last.section_children.push s2
|
||||
stack.push s2
|
||||
|
||||
i+=1
|
||||
elsif level == stack.last.section_level
|
||||
# this level is a sibling
|
||||
stack.pop
|
||||
else
|
||||
# this level is a parent
|
||||
stack.pop
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# If there is only one big header, then assume
|
||||
# it is the master
|
||||
if s.section_children.size == 1
|
||||
s = s.section_children.first
|
||||
end
|
||||
|
||||
# Assign section numbers
|
||||
s.numerate
|
||||
|
||||
s
|
||||
end
|
||||
end
|
||||
end
|
60
vendor/plugins/maruku/lib/maruku/version.rb
vendored
60
vendor/plugins/maruku/lib/maruku/version.rb
vendored
|
@ -1,40 +1,54 @@
|
|||
#--
|
||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||
#
|
||||
# This file is part of Maruku.
|
||||
#
|
||||
#
|
||||
# Maruku is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
#
|
||||
# Maruku is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Maruku; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#++
|
||||
|
||||
|
||||
module MaRuKu
|
||||
Version = '0.6.0'
|
||||
|
||||
MarukuURL = 'http://maruku.rubyforge.org/'
|
||||
|
||||
# If true, use also PHP Markdown extra syntax
|
||||
#
|
||||
# Note: it is not guaranteed that if it's false
|
||||
# then no special features will be used.
|
||||
#
|
||||
# So please, ignore it for now.
|
||||
def markdown_extra?
|
||||
true
|
||||
end
|
||||
|
||||
def new_meta_data?
|
||||
true
|
||||
end
|
||||
|
||||
# The Maruku version.
|
||||
VERSION = '0.6.0'
|
||||
|
||||
# @deprecated Exists for backwards compatibility. Use {VERSION}
|
||||
# @private
|
||||
Version = VERSION
|
||||
|
||||
# The URL of the Maruku website.
|
||||
MARUKU_URL = 'http://maruku.rubyforge.org/'
|
||||
|
||||
# @deprecated Exists for backwards compatibility. Use {MARUKU_URL}
|
||||
# @private
|
||||
MarukuURL = MARUKU_URL
|
||||
|
||||
# Whether Markdown implements the PHP Markdown extra syntax.
|
||||
#
|
||||
# Note: it is not guaranteed that if this is false,
|
||||
# then no special features will be used.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def markdown_extra?
|
||||
true
|
||||
end
|
||||
|
||||
# Whether Markdown implements the new meta-data proposal.
|
||||
#
|
||||
# Note: it is not guaranteed that if this is false,
|
||||
# then no special features will be used.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def new_meta_data?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue