Maruku Cleanup Branch
Use Nathan Weizenbaum's "cleanup" branch of Maruku. There were a few evident problems with his branch, so please report any anomalies you see.
This commit is contained in:
parent
dead710e69
commit
06ae79322a
|
@ -955,7 +955,7 @@ class WikiControllerTest < ActionController::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_recursive_include
|
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)
|
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
|
||||||
|
|
||||||
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
|
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>
|
77
vendor/plugins/maruku/lib/maruku.rb
vendored
77
vendor/plugins/maruku/lib/maruku.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,63 +15,54 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# 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'
|
require 'rexml/document'
|
||||||
|
|
||||||
# :include:MaRuKu.txt
|
|
||||||
module MaRuKu
|
module MaRuKu
|
||||||
|
module In
|
||||||
|
module Markdown
|
||||||
|
module SpanLevelParser; end
|
||||||
|
module BlockLevelParser; end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module In
|
module Out
|
||||||
module Markdown
|
module Markdown; end
|
||||||
module SpanLevelParser; end
|
module HTML; end
|
||||||
module BlockLevelParser; end
|
module Latex; end
|
||||||
end
|
end
|
||||||
# more to come?
|
|
||||||
end
|
|
||||||
|
|
||||||
module Out
|
module Strings; end
|
||||||
# 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 Helpers; end
|
||||||
module Strings; end
|
|
||||||
|
|
||||||
module Helpers; end
|
module Errors; end
|
||||||
|
|
||||||
module Errors; end
|
class MDElement
|
||||||
|
include REXML
|
||||||
class MDElement
|
include MaRuKu
|
||||||
include REXML
|
include Out::Markdown
|
||||||
include MaRuKu
|
include Out::HTML
|
||||||
include Out::Markdown
|
include Out::Latex
|
||||||
include Out::HTML
|
include Strings
|
||||||
include Out::Latex
|
include Helpers
|
||||||
include Strings
|
include Errors
|
||||||
include Helpers
|
end
|
||||||
include Errors
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class MDDocument < MDElement
|
class MDDocument < MDElement
|
||||||
include In::Markdown
|
include In::Markdown
|
||||||
include In::Markdown::SpanLevelParser
|
include In::Markdown::SpanLevelParser
|
||||||
include In::Markdown::BlockLevelParser
|
include In::Markdown::BlockLevelParser
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is the public interface
|
|
||||||
class Maruku < MaRuKu::MDDocument; end
|
class Maruku < MaRuKu::MDDocument; end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
require 'rexml/document'
|
|
||||||
|
|
||||||
# Structures definition
|
# Structures definition
|
||||||
require 'maruku/structures'
|
require 'maruku/structures'
|
||||||
require 'maruku/structures_inspect'
|
require 'maruku/structures_inspect'
|
||||||
|
@ -106,7 +96,7 @@ require 'maruku/attributes'
|
||||||
|
|
||||||
require 'maruku/structures_iterators'
|
require 'maruku/structures_iterators'
|
||||||
|
|
||||||
require 'maruku/errors_management'
|
require 'maruku/errors'
|
||||||
|
|
||||||
# Code for creating a table of contents
|
# Code for creating a table of contents
|
||||||
require 'maruku/toc'
|
require 'maruku/toc'
|
||||||
|
@ -140,4 +130,3 @@ require 'maruku/output/to_s'
|
||||||
|
|
||||||
# class Maruku is the global interface
|
# class Maruku is the global interface
|
||||||
require 'maruku/maruku'
|
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
|
|
273
vendor/plugins/maruku/lib/maruku/attributes.rb
vendored
273
vendor/plugins/maruku/lib/maruku/attributes.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,160 +15,124 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#++
|
|
||||||
|
|
||||||
|
|
||||||
class String
|
module MaRuKu
|
||||||
def quote_if_needed
|
# This represents a list of attributes specified in the Markdown document
|
||||||
if /[\s\'\"]/.match self
|
# that apply to a Markdown-generated tag.
|
||||||
inspect
|
# What was `{#id .class key="val" ref}` in the Markdown
|
||||||
else
|
# is parsed into `[[:id, 'id'], [:class, 'id'], ['key', 'val'], [:ref, 'ref']]`.
|
||||||
self
|
class AttributeList < Array
|
||||||
end
|
def to_s
|
||||||
end
|
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
|
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
|
|
||||||
|
|
69
vendor/plugins/maruku/lib/maruku/defaults.rb
vendored
69
vendor/plugins/maruku/lib/maruku/defaults.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,56 +15,50 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#++
|
|
||||||
|
|
||||||
|
|
||||||
module MaRuKu
|
module MaRuKu
|
||||||
|
|
||||||
Globals = {
|
Globals = {
|
||||||
:unsafe_features => false,
|
:unsafe_features => false,
|
||||||
:on_error => :warning,
|
:on_error => :warning,
|
||||||
|
|
||||||
|
:use_numbered_headers => false,
|
||||||
|
|
||||||
:use_numbered_headers => false,
|
:maruku_signature => false,
|
||||||
|
:code_background_color => '#fef',
|
||||||
|
:code_show_spaces => false,
|
||||||
|
|
||||||
:maruku_signature => false,
|
:filter_html => 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_mathml => true, # also set :html_math_engine
|
:html_math_output_png => false,
|
||||||
:html_math_engine => 'itex2mml', #ritex, itex2mml, none
|
:html_png_engine => 'none',
|
||||||
|
:html_png_dir => 'pngs',
|
||||||
|
:html_png_url => 'pngs/',
|
||||||
|
:html_png_resolution => 200,
|
||||||
|
|
||||||
:html_math_output_png => false,
|
:html_use_syntax => true,
|
||||||
: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
|
||||||
|
|
||||||
:latex_use_listings => false,
|
:debug_keep_ials => false,
|
||||||
:latex_cjk => false,
|
:doc_prefix => ''
|
||||||
:latex_cache_file => "blahtex_cache.pstore", # cache file for blahtex filter
|
}
|
||||||
|
|
||||||
:debug_keep_ials => false,
|
class MDElement
|
||||||
:doc_prefix => ''
|
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)
|
||||||
|
|
||||||
class MDElement
|
$stderr.puts "Bug: no default for #{sym.inspect}"
|
||||||
def get_setting(sym)
|
nil
|
||||||
if self.attributes.has_key?(sym) then
|
end
|
||||||
return self.attributes[sym]
|
end
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
201
vendor/plugins/maruku/lib/maruku/ext/div.rb
vendored
201
vendor/plugins/maruku/lib/maruku/ext/div.rb
vendored
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
#+-----------------------------------{.warning}------
|
#+-----------------------------------{.warning}------
|
||||||
#| this is the last warning!
|
#| this is the last warning!
|
||||||
#|
|
#|
|
||||||
|
@ -10,123 +8,114 @@
|
||||||
#| +--------------------------------------------------
|
#| +--------------------------------------------------
|
||||||
#+---------------------------------------------------
|
#+---------------------------------------------------
|
||||||
|
|
||||||
#OpenDiv = /^[ ]{0,3}\+\-\-+\s*(.*)$/
|
# TODO: Scope these properly
|
||||||
#CloseDiv = /^[ ]{0,3}\=\-\-+\s*(.*)$/
|
|
||||||
OpenDiv = /^[ ]{0,3}\+\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/
|
OpenDiv = /^[ ]{0,3}\+\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/
|
||||||
CloseDiv = /^[ ]{0,3}\=\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/
|
CloseDiv = /^[ ]{0,3}\=\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/
|
||||||
StartPipe = /^[ ]{0,3}\|(.*)$/ # $1 is rest of line
|
StartPipe = /^[ ]{0,3}\|(.*)$/ # $1 is rest of line
|
||||||
DecorativeClosing = OpenDiv
|
DecorativeClosing = OpenDiv
|
||||||
|
|
||||||
MaRuKu::In::Markdown::register_block_extension(
|
MaRuKu::In::Markdown.register_block_extension(
|
||||||
:regexp => OpenDiv,
|
:regexp => OpenDiv,
|
||||||
:handler => lambda { |doc, src, context|
|
:handler => lambda do |doc, src, context|
|
||||||
# return false if not doc.is_math_enabled?
|
first = src.shift_line
|
||||||
first = src.shift_line
|
ial_at_beginning = first[OpenDiv, 1]
|
||||||
first =~ OpenDiv
|
ial_at_end = nil
|
||||||
ial_at_beginning = $1
|
|
||||||
ial_at_end = nil
|
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
# if second line starts with "|"
|
# if second line starts with "|"
|
||||||
if src.cur_line =~ StartPipe
|
if src.cur_line =~ StartPipe
|
||||||
# then we read until no more "|"
|
# then we read until no more "|"
|
||||||
while src.cur_line && (src.cur_line =~ StartPipe)
|
while src.cur_line && src.cur_line =~ StartPipe
|
||||||
content = $1
|
lines.push $1
|
||||||
lines.push content
|
src.shift_line
|
||||||
src.shift_line
|
end
|
||||||
end
|
if src.cur_line =~ DecorativeClosing
|
||||||
if src.cur_line =~ DecorativeClosing
|
ial_at_end = $1
|
||||||
ial_at_end = $1
|
src.shift_line
|
||||||
src.shift_line
|
end
|
||||||
end
|
else
|
||||||
else
|
# else we read until CloseDiv
|
||||||
# else we read until CloseDiv
|
divs_open = 1
|
||||||
divs_open = 1
|
while src.cur_line && divs_open > 0
|
||||||
while src.cur_line && (divs_open>0)
|
if src.cur_line =~ CloseDiv
|
||||||
if src.cur_line =~ CloseDiv
|
divs_open -= 1
|
||||||
divs_open -= 1
|
if divs_open == 0
|
||||||
if divs_open == 0
|
ial_at_end = $1
|
||||||
ial_at_end = $1
|
src.shift_line
|
||||||
src.shift_line
|
break
|
||||||
break
|
else
|
||||||
else
|
lines.push src.shift_line
|
||||||
lines.push src.shift_line
|
end
|
||||||
end
|
else
|
||||||
else
|
if src.cur_line =~ OpenDiv
|
||||||
if src.cur_line =~ OpenDiv
|
divs_open += 1
|
||||||
divs_open += 1
|
end
|
||||||
end
|
lines.push src.shift_line
|
||||||
lines.push src.shift_line
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if divs_open > 0
|
if divs_open > 0
|
||||||
e = "At end of input, I still have #{divs_open} DIVs open."
|
doc.maruku_error("At end of input, I still have #{divs_open} DIVs open.",
|
||||||
doc.maruku_error(e, src, context)
|
src, context)
|
||||||
return true
|
next true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ial_at_beginning = nil unless
|
ial_at_beginning = nil unless ial_at_beginning && ial_at_beginning.size > 0
|
||||||
(ial_at_beginning&&ial_at_beginning.size > 0)
|
ial_at_end = nil unless ial_at_end && ial_at_end.size > 0
|
||||||
ial_at_end = nil unless (ial_at_end && ial_at_end.size > 0)
|
|
||||||
|
|
||||||
if ial_at_beginning && ial_at_end
|
if ial_at_beginning && ial_at_end
|
||||||
e = "Found two conflicting IALs: #{ial_at_beginning.inspect} and #{ial_at_end.inspect}"
|
doc.maruku_error("Found two conflicting IALs: #{ial_at_beginning.inspect} and #{ial_at_end.inspect}",
|
||||||
doc.maruku_error(e, src, context)
|
src, context)
|
||||||
end
|
end
|
||||||
|
|
||||||
al_string = ial_at_beginning || ial_at_end
|
al_string = ial_at_beginning || ial_at_end
|
||||||
al = nil
|
al = nil
|
||||||
|
|
||||||
if al_string =~ /^\{(.*)\}\s*$/
|
if al_string =~ /^\{(.*)\}\s*$/
|
||||||
inside = $1
|
al = al_string && doc.read_attribute_list(
|
||||||
cs = MaRuKu::In::Markdown::SpanLevelParser::CharSource
|
MaRuKu::In::Markdown::SpanLevelParser::CharSource.new($1),
|
||||||
al = al_string &&
|
nil, [nil])
|
||||||
doc.read_attribute_list(cs.new(inside), its_context=nil, break_on=[nil])
|
end
|
||||||
end
|
|
||||||
|
|
||||||
src = MaRuKu::In::Markdown::BlockLevelParser::LineSource.new(lines)
|
context.push(
|
||||||
children = doc.parse_blocks(src)
|
doc.md_div(
|
||||||
|
doc.parse_blocks(
|
||||||
|
MaRuKu::In::Markdown::BlockLevelParser::LineSource.new(lines)),
|
||||||
|
al))
|
||||||
|
true
|
||||||
|
end)
|
||||||
|
|
||||||
context.push doc.md_div(children, al)
|
module MaRuKu
|
||||||
true
|
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
|
||||||
|
|
||||||
module MaRuKu; class MDElement
|
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
|
||||||
|
|
||||||
def md_div(children, al=nil)
|
module Out
|
||||||
type = label = num = nil
|
module HTML
|
||||||
doc.refid2ref ||= {}
|
def to_html_div
|
||||||
if al
|
add_ws wrap_as_element('div')
|
||||||
al.each do |k, v|
|
end
|
||||||
case k
|
end
|
||||||
when :class
|
end
|
||||||
type = $1 if v =~ /^num_(\w*)/
|
end
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
module MaRuKu; 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/elements'
|
||||||
require 'maruku/ext/math/parsing'
|
require 'maruku/ext/math/parsing'
|
||||||
require 'maruku/ext/math/to_latex'
|
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/itex2mml'
|
||||||
require 'maruku/ext/math/mathml_engines/blahtex'
|
require 'maruku/ext/math/mathml_engines/blahtex'
|
||||||
|
|
||||||
|
|
||||||
=begin maruku_doc
|
=begin maruku_doc
|
||||||
Attribute: math_enabled
|
Attribute: math_enabled
|
||||||
Scope: global, document
|
Scope: global, document
|
||||||
|
@ -37,5 +34,4 @@ Array containing any of `'\\['`, `'\\begin{equation}'`, `'$$'`.
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
|
|
||||||
MaRuKu::Globals[:math_numbered] = []
|
MaRuKu::Globals[:math_numbered] = []
|
||||||
|
|
|
@ -1,27 +1,21 @@
|
||||||
module MaRuKu; class MDElement
|
module MaRuKu
|
||||||
|
class MDElement
|
||||||
|
def md_inline_math(math)
|
||||||
|
self.md_el(:inline_math, [], :math => math)
|
||||||
|
end
|
||||||
|
|
||||||
def md_inline_math(math)
|
def md_equation(math, label, numerate)
|
||||||
self.md_el(:inline_math, [], meta={:math=>math})
|
reglabel = /\\label\{(\w+)\}/
|
||||||
end
|
math = math.gsub(reglabel, '') if label = math[reglabel, 1]
|
||||||
|
num = nil
|
||||||
def md_equation(math, label, numerate)
|
if (label || numerate) && @doc # take number
|
||||||
reglabel= /\\label\{(\w+)\}/
|
@doc.eqid2eq ||= {}
|
||||||
if math =~ reglabel
|
num = @doc.eqid2eq.size + 1
|
||||||
label = $1
|
label = "eq#{num}" if not label # TODO do id for document
|
||||||
math.gsub!(reglabel,'')
|
end
|
||||||
end
|
e = self.md_el(:equation, [], :math => math, :label => label, :num => num)
|
||||||
# puts "Found label = #{label} math #{math.inspect} "
|
@doc.eqid2eq[label] = e if label && @doc # take number
|
||||||
num = nil
|
e
|
||||||
if (label || numerate) && @doc #take number
|
end
|
||||||
@doc.eqid2eq ||= {}
|
end
|
||||||
num = @doc.eqid2eq.size + 1
|
end
|
||||||
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
|
|
||||||
|
|
|
@ -1,107 +1,93 @@
|
||||||
|
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'digest/md5'
|
require 'digest/md5'
|
||||||
require 'pstore'
|
require 'pstore'
|
||||||
|
|
||||||
module MaRuKu; module Out; module HTML
|
module MaRuKu
|
||||||
|
module Out
|
||||||
|
module HTML
|
||||||
|
PNG = Struct.new(:src, :depth, :height)
|
||||||
|
|
||||||
PNG = Struct.new(:src,:depth,:height)
|
def convert_to_png_blahtex(kind, tex)
|
||||||
|
FileUtils.mkdir_p get_setting(:html_png_dir)
|
||||||
|
|
||||||
def convert_to_png_blahtex(kind, tex)
|
# first, we check whether this image has already been processed
|
||||||
begin
|
md5sum = Digest::MD5.hexdigest(tex + " params: ")
|
||||||
FileUtils::mkdir_p get_setting(:html_png_dir)
|
result_file = File.join(get_setting(:html_png_dir), md5sum + ".txt")
|
||||||
|
|
||||||
# first, we check whether this image has already been processed
|
if not File.exists?(result_file)
|
||||||
md5sum = Digest::MD5.hexdigest(tex+" params: ")
|
Tempfile.open('maruku_blahtex') do |tmp_in|
|
||||||
result_file = File.join(get_setting(:html_png_dir), md5sum+".txt")
|
tmp_in.write tex
|
||||||
|
tmp_in.close
|
||||||
|
|
||||||
if not File.exists?(result_file)
|
# It's important taht we don't replace *all* newlines,
|
||||||
tmp_in = Tempfile.new('maruku_blahtex')
|
# because newlines in arguments get escaped as "'\n'".
|
||||||
f = tmp_in.open
|
system <<COMMAND.gsub("\n ", " ")
|
||||||
f.write tex
|
blahtex --png --use-preview-package
|
||||||
f.close
|
--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
|
||||||
|
|
||||||
resolution = get_setting(:html_png_resolution)
|
result = File.read(result_file)
|
||||||
|
if result.nil? || result.empty?
|
||||||
|
maruku_error "Blahtex error: empty output"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
options = "--png --use-preview-package --shell-dvipng 'dvipng -D #{resolution}' "
|
doc = Document.new(result, :respect_whitespace => :all)
|
||||||
options += "--displaymath " if kind == :equation
|
png = doc.root.elements[1]
|
||||||
options += ("--temp-directory '%s' " % get_setting(:html_png_dir))
|
if png.name != 'png'
|
||||||
options += ("--png-directory '%s'" % get_setting(:html_png_dir))
|
maruku_error "Blahtex error: \n#{doc}"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
cmd = "blahtex #{options} < #{tmp_in.path} > #{result_file}"
|
raise "No depth element in:\n #{doc}" unless depth = png.elements['depth']
|
||||||
#$stderr.puts "$ #{cmd}"
|
raise "No height element in:\n #{doc}" unless height = png.elements['height']
|
||||||
system cmd
|
raise "No md5 element in:\n #{doc}" unless md5 = png.elements['md5']
|
||||||
tmp_in.delete
|
|
||||||
end
|
|
||||||
|
|
||||||
result = File.read(result_file)
|
depth = depth.text.to_f
|
||||||
if result.nil? || result.empty?
|
height = height.text.to_f # TODO: check != 0
|
||||||
raise "Blahtex error: empty output"
|
md5 = md5.text
|
||||||
|
|
||||||
|
PNG.new("#{get_setting(:html_png_url)}#{md5}.png", depth, height)
|
||||||
|
rescue Exception => e
|
||||||
|
maruku_error "Error: #{e}"
|
||||||
end
|
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
|
def convert_to_mathml_blahtex(kind, tex)
|
||||||
height = height.text.to_f # XXX check != 0
|
@@BlahtexCache ||= PStore.new(get_setting(:latex_cache_file))
|
||||||
md5 = md5.text
|
|
||||||
|
|
||||||
dir_url = get_setting(:html_png_url)
|
@@BlahtexCache.transaction do
|
||||||
return PNG.new("#{dir_url}#{md5}.png", depth, height)
|
if @@BlahtexCache[tex].nil?
|
||||||
rescue Exception => e
|
Tempfile.open('maruku_blahtex') do |tmp_in|
|
||||||
maruku_error "Error: #{e}"
|
tmp_in.write tex
|
||||||
end
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
def convert_to_mathml_blahtex(kind, tex)
|
blahtex = @@BlahtexCache[tex]
|
||||||
@@BlahtexCache = PStore.new(get_setting(:latex_cache_file))
|
doc = Document.new(blahtex, :respect_whitespace => :all)
|
||||||
|
unless mathml = doc.root.elements['mathml']
|
||||||
|
maruku_error "Blahtex error: \n#{doc}"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
return mathml
|
||||||
@@BlahtexCache.transaction do
|
end
|
||||||
if @@BlahtexCache[tex].nil?
|
rescue Exception => e
|
||||||
tmp_in = Tempfile.new('maruku_blahtex')
|
maruku_error "Error: #{e}"
|
||||||
f = tmp_in.open
|
end
|
||||||
f.write tex
|
end
|
||||||
f.close
|
end
|
||||||
tmp_out = Tempfile.new('maruku_blahtex')
|
end
|
||||||
|
|
||||||
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
|
|
||||||
|
|
|
@ -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)
|
return Document.new(mathml.to_utf8, :respect_whitespace => :all).root
|
||||||
begin
|
rescue LoadError => e
|
||||||
if not $itex2mml_parser
|
# TODO: Properly scope this global
|
||||||
require 'stringsupport'
|
maruku_error "Could not load package 'itex2mml'.\nPlease install it." unless $already_warned_itex2mml
|
||||||
require 'itextomml'
|
$already_warned_itex2mml = true
|
||||||
$itex2mml_parser = Itex2MML::Parser.new
|
nil
|
||||||
end
|
rescue REXML::ParseException => e
|
||||||
|
maruku_error "Invalid MathML TeX: \n#{tex.gsub(/^/, 'tex>')}\n\n #{e.inspect}"
|
||||||
itex_method = {:equation=>:block_filter,:inline=>:inline_filter}
|
nil
|
||||||
|
rescue
|
||||||
mathml = $itex2mml_parser.send(itex_method[kind], tex).to_utf8
|
maruku_error "Could not produce MathML TeX: \n#{tex}\n\n #{e.inspect}"
|
||||||
doc = Document.new(mathml, {:respect_whitespace =>:all}).root
|
nil
|
||||||
return doc
|
end
|
||||||
rescue LoadError => e
|
end
|
||||||
maruku_error "Could not load package 'itex2mml'.\n"+ "Please install it." unless $already_warned_itex2mml
|
end
|
||||||
$already_warned_itex2mml = true
|
end
|
||||||
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
|
|
||||||
|
|
200
vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb
vendored
200
vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb
vendored
|
@ -1,119 +1,111 @@
|
||||||
module MaRuKu
|
module MaRuKu
|
||||||
|
class MDDocument
|
||||||
|
# A hash of equation ids to equation elements
|
||||||
|
#
|
||||||
|
# @return [String => MDElement]
|
||||||
|
attr_accessor :eqid2eq
|
||||||
|
|
||||||
class MDDocument
|
def is_math_enabled?
|
||||||
# Hash equation id (String) to equation element (MDElement)
|
get_setting :math_enabled
|
||||||
attr_accessor :eqid2eq
|
end
|
||||||
|
end
|
||||||
def is_math_enabled?
|
|
||||||
get_setting :math_enabled
|
|
||||||
end
|
|
||||||
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
|
MaRuKu::In::Markdown.register_span_extension(
|
||||||
RegInlineMath = /\${1}((?:[^\$]|\\\$)+)\$/
|
:chars => ?$,
|
||||||
|
:regexp => RegInlineMath,
|
||||||
MaRuKu::In::Markdown::register_span_extension(
|
:handler => lambda do |doc, src, con|
|
||||||
:chars => ?$,
|
next false unless doc.is_math_enabled?
|
||||||
:regexp => RegInlineMath,
|
next false unless m = src.read_regexp(RegInlineMath)
|
||||||
:handler => lambda { |doc, src, con|
|
math = m.captures.compact.first
|
||||||
return false if not doc.is_math_enabled?
|
con.push doc.md_inline_math(math)
|
||||||
|
true
|
||||||
if m = src.read_regexp(RegInlineMath)
|
end)
|
||||||
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}')
|
MathOpen1 = Regexp.escape('\\begin{equation}')
|
||||||
MathClose1 = Regexp.escape('\\end{equation}')
|
MathClose1 = Regexp.escape('\\end{equation}')
|
||||||
MathOpen2 = Regexp.escape('\\[')
|
MathOpen2 = Regexp.escape('\\[')
|
||||||
MathClose2 = Regexp.escape('\\]')
|
MathClose2 = Regexp.escape('\\]')
|
||||||
MathOpen3 = Regexp.escape('$$')
|
MathOpen3 = Regexp.escape('$$')
|
||||||
MathClose3 = Regexp.escape('$$')
|
MathClose3 = Regexp.escape('$$')
|
||||||
|
|
||||||
EqLabel = /(?:\((\w+)\))/
|
EqLabel = /(?:\((\w+)\))/
|
||||||
EquationOpen = /#{MathOpen1}|#{MathOpen2}|#{MathOpen3}/
|
EquationOpen = /#{MathOpen1}|#{MathOpen2}|#{MathOpen3}/
|
||||||
EquationClose = /#{MathClose1}|#{MathClose2}|#{MathClose3}/
|
EquationClose = /#{MathClose1}|#{MathClose2}|#{MathClose3}/
|
||||||
|
|
||||||
# $1 is opening, $2 is tex
|
# $1 is opening, $2 is tex
|
||||||
EquationStart = /^[ ]{0,3}(#{EquationOpen})(.*)$/
|
EquationStart = /^[ ]{0,3}(#{EquationOpen})(.*)$/
|
||||||
# $1 is tex, $2 is closing, $3 is tex
|
# $1 is tex, $2 is closing, $3 is tex
|
||||||
EquationEnd = /^(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
EquationEnd = /^(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
||||||
# $1 is opening, $2 is tex, $3 is closing, $4 is label
|
# $1 is opening, $2 is tex, $3 is closing, $4 is label
|
||||||
OneLineEquation = /^[ ]{0,3}(#{EquationOpen})(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
OneLineEquation = /^[ ]{0,3}(#{EquationOpen})(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/
|
||||||
|
|
||||||
MaRuKu::In::Markdown::register_block_extension(
|
MaRuKu::In::Markdown.register_block_extension(
|
||||||
:regexp => EquationStart,
|
:regexp => EquationStart,
|
||||||
:handler => lambda { |doc, src, con|
|
:handler => lambda do |doc, src, con|
|
||||||
return false if not doc.is_math_enabled?
|
next false unless doc.is_math_enabled?
|
||||||
first = src.shift_line
|
first = src.shift_line
|
||||||
if first =~ OneLineEquation
|
if first =~ OneLineEquation
|
||||||
opening, tex, closing, label = $1, $2, $3, $4
|
opening, tex, closing, label = $1, $2, $3, $4
|
||||||
numerate = doc.get_setting(:math_numbered).include?(opening)
|
numerate = doc.get_setting(:math_numbered).include?(opening)
|
||||||
con.push doc.md_equation(tex, label, numerate)
|
con.push doc.md_equation(tex, label, numerate)
|
||||||
else
|
next true
|
||||||
first =~ EquationStart
|
end
|
||||||
opening, tex = $1, $2
|
|
||||||
|
|
||||||
numerate = doc.get_setting(:math_numbered).include?(opening)
|
opening, tex = first.scan(EquationStart).first
|
||||||
label = nil
|
numerate = doc.get_setting(:math_numbered).include?(opening)
|
||||||
while true
|
label = nil
|
||||||
if not src.cur_line
|
loop do
|
||||||
doc.maruku_error("Stream finished while reading equation\n\n"+
|
unless src.cur_line
|
||||||
doc.add_tabs(tex,1,'$> '), src, con)
|
doc.maruku_error(
|
||||||
break
|
"Stream finished while reading equation\n\n" + tex.gsub(/^/, '$> '),
|
||||||
end
|
src, con)
|
||||||
line = src.shift_line
|
break
|
||||||
if line =~ EquationEnd
|
end
|
||||||
tex_line, closing = $1, $2
|
|
||||||
label = $3 if $3
|
line = src.shift_line
|
||||||
tex += tex_line + "\n"
|
if line =~ EquationEnd
|
||||||
break
|
tex_line, closing = $1, $2
|
||||||
else
|
label = $3 if $3
|
||||||
tex += line + "\n"
|
tex << tex_line << "\n"
|
||||||
end
|
break
|
||||||
end
|
end
|
||||||
con.push doc.md_equation(tex, label, numerate)
|
|
||||||
end
|
tex << line << "\n"
|
||||||
true
|
end
|
||||||
})
|
con.push doc.md_equation(tex, label, numerate)
|
||||||
|
true
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
# This adds support for \eqref
|
# This adds support for \eqref
|
||||||
RegEqrefLatex = /\\eqref\{(\w+)\}/
|
RegEqrefLatex = /\\eqref\{(\w+)\}/
|
||||||
RegEqPar = /\(eq:(\w+)\)/
|
RegEqPar = /\(eq:(\w+)\)/
|
||||||
RegEqref = Regexp::union(RegEqrefLatex, RegEqPar)
|
RegEqref = Regexp.union(RegEqrefLatex, RegEqPar)
|
||||||
|
|
||||||
MaRuKu::In::Markdown::register_span_extension(
|
MaRuKu::In::Markdown.register_span_extension(
|
||||||
:chars => [?\\, ?(],
|
:chars => [?\\, ?(],
|
||||||
:regexp => RegEqref,
|
:regexp => RegEqref,
|
||||||
:handler => lambda { |doc, src, con|
|
:handler => lambda do |doc, src, con|
|
||||||
return false if not doc.is_math_enabled?
|
return false unless doc.is_math_enabled?
|
||||||
eqid = src.read_regexp(RegEqref).captures.compact.first
|
eqid = src.read_regexp(RegEqref).captures.compact.first
|
||||||
r = doc.md_el(:eqref, [], meta={:eqid=>eqid})
|
con.push doc.md_el(:eqref, [], :eqid => eqid)
|
||||||
con.push r
|
true
|
||||||
true
|
end)
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# This adds support for \ref
|
# This adds support for \ref
|
||||||
RegRef = /\\ref\{(\w*)\}/
|
RegRef = /\\ref\{(\w*)\}/
|
||||||
MaRuKu::In::Markdown::register_span_extension(
|
MaRuKu::In::Markdown.register_span_extension(
|
||||||
:chars => [?\\, ?(],
|
:chars => [?\\, ?(],
|
||||||
:regexp => RegRef,
|
:regexp => RegRef,
|
||||||
:handler => lambda { |doc, src, con|
|
:handler => lambda do |doc, src, con|
|
||||||
return false if not doc.is_math_enabled?
|
return false unless doc.is_math_enabled?
|
||||||
refid = src.read_regexp(RegRef).captures.compact.first
|
refid = src.read_regexp(RegRef).captures.compact.first
|
||||||
r = doc.md_el(:divref, [], meta={:refid=>refid})
|
con.push doc.md_el(:divref, [], :refid => refid)
|
||||||
con.push r
|
true
|
||||||
true
|
end)
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
277
vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb
vendored
277
vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
=begin maruku_doc
|
=begin maruku_doc
|
||||||
Extension: math
|
Extension: math
|
||||||
Attribute: html_math_engine
|
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:
|
If you want to use your custom engine `foo`, then set:
|
||||||
|
|
||||||
HTML math engine: foo
|
HTML math engine: foo
|
||||||
{:lang=markdown}
|
{:lang=markdown}
|
||||||
|
|
||||||
and then implement two functions:
|
and then implement two functions:
|
||||||
|
|
||||||
def convert_to_mathml_foo(kind, tex)
|
def convert_to_mathml_foo(kind, tex)
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
=end
|
=end
|
||||||
|
|
||||||
=begin maruku_doc
|
=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.
|
Same thing as `html_math_engine`, only for PNG output.
|
||||||
|
|
||||||
def convert_to_png_foo(kind, tex)
|
def convert_to_png_foo(kind, tex)
|
||||||
# same thing
|
# same thing
|
||||||
...
|
...
|
||||||
end
|
end
|
||||||
{:lang=ruby}
|
{:lang=ruby}
|
||||||
|
|
||||||
=end
|
=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
|
||||||
|
|
||||||
|
# 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
|
puts "A method called #{method} should be defined."
|
||||||
def render_mathml(kind, tex)
|
return nil
|
||||||
engine = get_setting(:html_math_engine)
|
end
|
||||||
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
|
|
||||||
|
|
||||||
# Creates an xml Mathml document of self.math
|
def pixels_per_ex
|
||||||
def render_png(kind, tex)
|
$pixels_per_ex ||= render_png(:inline, "x").height
|
||||||
engine = get_setting(:html_png_engine)
|
end
|
||||||
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
|
def adjust_png(png, use_depth)
|
||||||
if not $pixels_per_ex
|
src = png.src
|
||||||
x = render_png(:inline, "x")
|
|
||||||
$pixels_per_ex = x.height # + x.depth
|
|
||||||
end
|
|
||||||
$pixels_per_ex
|
|
||||||
end
|
|
||||||
|
|
||||||
def adjust_png(png, use_depth)
|
height_in_px = png.height
|
||||||
src = png.src
|
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;"
|
||||||
|
|
||||||
height_in_px = png.height
|
img = Element.new 'img'
|
||||||
depth_in_px = png.depth
|
img.attributes['src'] = src
|
||||||
height_in_ex = height_in_px / pixels_per_ex
|
img.attributes['style'] = style
|
||||||
depth_in_ex = depth_in_px / pixels_per_ex
|
img.attributes['alt'] = "$#{self.math.strip}$"
|
||||||
total_height_in_ex = height_in_ex + depth_in_ex
|
img
|
||||||
style = ""
|
end
|
||||||
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
|
def to_html_inline_math
|
||||||
mathml = get_setting(:html_math_output_mathml) && render_mathml(:inline, self.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)
|
png = get_setting(:html_math_output_png) && render_png(:inline, self.math)
|
||||||
|
|
||||||
span = create_html_element 'span'
|
span = create_html_element 'span'
|
||||||
add_class_to(span, 'maruku-inline')
|
add_class_to(span, 'maruku-inline')
|
||||||
|
|
||||||
if mathml
|
if mathml
|
||||||
add_class_to(mathml, 'maruku-mathml')
|
add_class_to(mathml, 'maruku-mathml')
|
||||||
return mathml
|
return mathml
|
||||||
end
|
end
|
||||||
|
|
||||||
if png
|
if png
|
||||||
img = adjust_png(png, use_depth=true)
|
img = adjust_png(png, true)
|
||||||
add_class_to(img, 'maruku-png')
|
add_class_to(img, 'maruku-png')
|
||||||
span << img
|
span << img
|
||||||
end
|
end
|
||||||
span
|
|
||||||
|
|
||||||
end
|
span
|
||||||
|
end
|
||||||
|
|
||||||
def to_html_equation
|
def to_html_equation
|
||||||
mathml = get_setting(:html_math_output_mathml) && render_mathml(:equation, self.math)
|
mathml = get_setting(:html_math_output_mathml) && render_mathml(:equation, self.math)
|
||||||
png = get_setting(:html_math_output_png) && render_png(:equation, self.math)
|
png = get_setting(:html_math_output_png) && render_png(:equation, self.math)
|
||||||
|
|
||||||
div = create_html_element 'div'
|
div = create_html_element 'div'
|
||||||
add_class_to(div, 'maruku-equation')
|
add_class_to(div, 'maruku-equation')
|
||||||
if mathml
|
if mathml
|
||||||
if self.label # then numerate
|
if self.label # then numerate
|
||||||
span = Element.new 'span'
|
span = Element.new 'span'
|
||||||
span.attributes['class'] = 'maruku-eq-number'
|
span.attributes['class'] = 'maruku-eq-number'
|
||||||
num = self.num
|
span << Text.new("(#{self.num})")
|
||||||
span << Text.new("(#{num})")
|
div << span
|
||||||
div << span
|
div.attributes['id'] = "eq:#{self.label}"
|
||||||
div.attributes['id'] = "eq:#{self.label}"
|
end
|
||||||
end
|
add_class_to(mathml, 'maruku-mathml')
|
||||||
add_class_to(mathml, 'maruku-mathml')
|
div << mathml
|
||||||
div << mathml
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if png
|
if png
|
||||||
img = adjust_png(png, use_depth=false)
|
img = adjust_png(png, false)
|
||||||
add_class_to(img, 'maruku-png')
|
add_class_to(img, 'maruku-png')
|
||||||
div << img
|
div << img
|
||||||
if self.label # then numerate
|
if self.label # then numerate
|
||||||
span = Element.new 'span'
|
span = Element.new 'span'
|
||||||
span.attributes['class'] = 'maruku-eq-number'
|
span.attributes['class'] = 'maruku-eq-number'
|
||||||
num = self.num
|
span << Text.new("(#{self.num})")
|
||||||
span << Text.new("(#{num})")
|
div << span
|
||||||
div << span
|
div.attributes['id'] = "eq:#{self.label}"
|
||||||
div.attributes['id'] = "eq:#{self.label}"
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
source_span = Element.new 'span'
|
source_span = Element.new 'span'
|
||||||
add_class_to(source_span, 'maruku-eq-tex')
|
add_class_to(source_span, 'maruku-eq-tex')
|
||||||
code = convert_to_mathml_none(:equation, self.math.strip)
|
code = convert_to_mathml_none(:equation, self.math.strip)
|
||||||
code.attributes['style'] = 'display: none'
|
code.attributes['style'] = 'display: none'
|
||||||
source_span << code
|
source_span << code
|
||||||
div << source_span
|
div << source_span
|
||||||
|
|
||||||
div
|
div
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_html_eqref
|
def to_html_eqref
|
||||||
if eq = self.doc.eqid2eq[self.eqid]
|
unless eq = self.doc.eqid2eq[self.eqid]
|
||||||
num = eq.num
|
maruku_error "Cannot find equation #{self.eqid.inspect}"
|
||||||
a = Element.new 'a'
|
return Text.new("(eq:#{self.eqid})")
|
||||||
a.attributes['class'] = 'maruku-eqref'
|
end
|
||||||
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 to_html_divref
|
a = Element.new 'a'
|
||||||
ref= nil
|
a.attributes['class'] = 'maruku-eqref'
|
||||||
self.doc.refid2ref.each_value { |h|
|
a.attributes['href'] = "#eq:#{self.eqid}"
|
||||||
ref = h[self.refid] if h.has_key?(self.refid)
|
a << Text.new("(#{eq.num})")
|
||||||
}
|
a
|
||||||
if ref
|
end
|
||||||
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
|
|
||||||
|
|
||||||
|
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'
|
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
|
def to_latex_equation
|
||||||
"$#{self.math.strip}$".fix_latex
|
if self.label
|
||||||
end
|
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
|
def to_latex_eqref
|
||||||
if self.label
|
"\\eqref{#{self.eqid}}"
|
||||||
l = "\\label{#{self.label}}"
|
end
|
||||||
"\\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
|
def to_latex_divref
|
||||||
"\\eqref{#{self.eqid}}"
|
"\\ref{#{self.refid}}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_latex_divref
|
private
|
||||||
"\\ref{#{self.refid}}"
|
|
||||||
end
|
|
||||||
|
|
||||||
end end end
|
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
|
||||||
|
|
372
vendor/plugins/maruku/lib/maruku/helpers.rb
vendored
372
vendor/plugins/maruku/lib/maruku/helpers.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,245 +15,200 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# 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 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
|
e = MDElement.new(node_type, children, meta, al)
|
||||||
def md_el(node_type, children=[], meta={}, al=nil)
|
e.doc = @doc
|
||||||
if (e=children.first).kind_of?(MDElement) and
|
e
|
||||||
e.node_type == :ial then
|
end
|
||||||
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
|
|
||||||
|
|
||||||
def md_header(level, children, al=nil)
|
def md_header(level, children, al = nil)
|
||||||
md_el(:header, children, {:level => level}, al)
|
md_el(:header, children, {:level => level}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Inline code
|
# Inline code
|
||||||
def md_code(code, al=nil)
|
def md_code(code, al = nil)
|
||||||
md_el(:inline_code, [], {:raw_code => code}, al)
|
md_el(:inline_code, [], {:raw_code => code}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Code block
|
# Code block
|
||||||
def md_codeblock(source, al=nil)
|
def md_codeblock(source, al = nil)
|
||||||
md_el(:code, [], {:raw_code => source}, al)
|
md_el(:code, [], {:raw_code => source}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_quote(children, al=nil)
|
def md_quote(children, al = nil)
|
||||||
md_el(:quote, children, {}, al)
|
md_el(:quote, children, {}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_li(children, want_my_par, al=nil)
|
def md_li(children, want_my_par, al = nil)
|
||||||
md_el(:li, children, {:want_my_paragraph=>want_my_par}, al)
|
md_el(:li, children, {:want_my_paragraph => want_my_par}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_footnote(footnote_id, children, al=nil)
|
def md_footnote(footnote_id, children, al = nil)
|
||||||
md_el(:footnote, children, {:footnote_id=>footnote_id}, al)
|
md_el(:footnote, children, {:footnote_id => footnote_id}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_abbr_def(abbr, text, al=nil)
|
def md_abbr_def(abbr, text, al = nil)
|
||||||
md_el(:abbr_def, [], {:abbr=>abbr, :text=>text}, al)
|
md_el(:abbr_def, [], {:abbr => abbr, :text => text}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_abbr(abbr, title)
|
def md_abbr(abbr, title)
|
||||||
md_el(:abbr, [abbr], {:title=>title})
|
md_el(:abbr, [abbr], :title => title)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_html(raw_html, al=nil)
|
def md_html(raw_html, al = nil)
|
||||||
e = md_el(:raw_html, [], {:raw_html=>raw_html})
|
e = md_el(:raw_html, [], :raw_html => raw_html)
|
||||||
begin
|
begin
|
||||||
# remove newlines and whitespace at begin
|
e.instance_variable_set("@parsed_html",
|
||||||
# end end of string, or else REXML gets confused
|
REXML::Document.new("<marukuwrap>#{raw_html.strip}</marukuwrap>"))
|
||||||
raw_html = raw_html.gsub(/\A\s*</,'<').
|
rescue REXML::ParseException => ex
|
||||||
gsub(/>[\s\n]*\Z/,'>')
|
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
|
||||||
|
|
||||||
raw_html = "<marukuwrap>#{raw_html}</marukuwrap>"
|
def md_link(children, ref_id, al = nil)
|
||||||
e.instance_variable_set :@parsed_html,
|
md_el(:link, children, {:ref_id => ref_id.downcase}, al)
|
||||||
REXML::Document.new(raw_html)
|
end
|
||||||
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)
|
def md_im_link(children, url, title = nil, al = nil)
|
||||||
md_el(:link, children, {:ref_id=>ref_id.downcase}, al)
|
md_el(:im_link, children, {:url => url, :title => title}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_im_link(children, url, title=nil, al=nil)
|
def md_image(children, ref_id, al = nil)
|
||||||
md_el(:im_link, children, {:url=>url,:title=>title}, al)
|
md_el(:image, children, {:ref_id => ref_id}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_image(children, ref_id, al=nil)
|
def md_im_image(children, url, title = nil, al = nil)
|
||||||
md_el(:image, children, {:ref_id=>ref_id}, al)
|
md_el(:im_image, children, {:url => url, :title => title}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_im_image(children, url, title=nil, al=nil)
|
def md_em(children, al = nil)
|
||||||
md_el(:im_image, children, {:url=>url,:title=>title},al)
|
md_el(:emphasis, [children].flatten, {}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_em(children, al=nil)
|
def md_br
|
||||||
md_el(:emphasis, [children].flatten, {}, al)
|
md_el(:linebreak, [], {}, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_br()
|
def md_hrule
|
||||||
md_el(:linebreak, [], {}, nil)
|
md_el(:hrule, [], {}, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_hrule()
|
def md_strong(children, al = nil)
|
||||||
md_el(:hrule, [], {}, nil)
|
md_el(:strong, [children].flatten, {}, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_strong(children, al=nil)
|
def md_emstrong(children, al = nil)
|
||||||
md_el(:strong, [children].flatten, {}, al)
|
md_strong(md_em(children), al)
|
||||||
end
|
end
|
||||||
|
|
||||||
def md_emstrong(children, al=nil)
|
# A URL to be linkified (e.g. `<http://www.example.com/>`).
|
||||||
md_strong(md_em(children), al)
|
def md_url(url, al = nil)
|
||||||
end
|
md_el(:immediate_link, [], {:url => url}, al)
|
||||||
|
end
|
||||||
|
|
||||||
# <http://www.example.com/>
|
# An email to be linkified
|
||||||
def md_url(url, al=nil)
|
# (e.g. `<andrea@rubyforge.org>` or `<mailto:andrea@rubyforge.org>`).
|
||||||
md_el(:immediate_link, [], {:url=>url}, al)
|
def md_email(email, al = nil)
|
||||||
end
|
md_el(:email_address, [], {:email => email}, al)
|
||||||
|
end
|
||||||
|
|
||||||
# <andrea@rubyforge.org>
|
def md_entity(entity_name, al = nil)
|
||||||
# <mailto:andrea@rubyforge.org>
|
md_el(:entity, [], {:entity_name => entity_name}, al)
|
||||||
def md_email(email, al=nil)
|
end
|
||||||
md_el(:email_address, [], {:email=>email}, al)
|
|
||||||
end
|
|
||||||
|
|
||||||
def md_entity(entity_name, al=nil)
|
# Markdown extra
|
||||||
md_el(:entity, [], {:entity_name=>entity_name}, al)
|
def md_foot_ref(ref_id, al = nil)
|
||||||
end
|
md_el(:footnote_reference, [], {:footnote_id => ref_id}, al)
|
||||||
|
end
|
||||||
|
|
||||||
# Markdown extra
|
def md_par(children, al = nil)
|
||||||
def md_foot_ref(ref_id, al=nil)
|
md_el(:paragraph, children, meta = {}, al)
|
||||||
md_el(:footnote_reference, [], {:footnote_id=>ref_id}, al)
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def md_par(children, al=nil)
|
# A definition of a reference (e.g. `[1]: http://url [properties]`).
|
||||||
md_el(:paragraph, children, meta={}, al)
|
def md_ref_def(ref_id, url, title = nil, meta = {}, al = nil)
|
||||||
end
|
meta[:url] = url
|
||||||
|
meta[:ref_id] = ref_id
|
||||||
|
meta[:title] = title if title
|
||||||
|
md_el(:ref_definition, [], meta, al)
|
||||||
|
end
|
||||||
|
|
||||||
# [1]: http://url [properties]
|
# inline attribute list
|
||||||
def md_ref_def(ref_id, url, title=nil, meta={}, al=nil)
|
def md_ial(al)
|
||||||
meta[:url] = url
|
al = Maruku::AttributeList.new(al) unless al.is_a?(Maruku::AttributeList)
|
||||||
meta[:ref_id] = ref_id
|
md_el(:ial, [], :ial => al)
|
||||||
meta[:title] = title if title
|
end
|
||||||
md_el(:ref_definition, [], meta, al)
|
|
||||||
end
|
|
||||||
|
|
||||||
# inline attribute list
|
# Attribute list definition
|
||||||
def md_ial(al)
|
def md_ald(id, al)
|
||||||
al = Maruku::AttributeList.new(al) if
|
md_el(:ald, [], :ald_id => id, :ald => al)
|
||||||
not al.kind_of?Maruku::AttributeList
|
end
|
||||||
md_el(:ial, [], {:ial=>al})
|
|
||||||
end
|
|
||||||
|
|
||||||
# Attribute list definition
|
# A server directive (e.g. `<?target code... ?>`)
|
||||||
def md_ald(id, al)
|
def md_xml_instr(target, code)
|
||||||
md_el(:ald, [], {:ald_id=>id,:ald=>al})
|
md_el(:xml_instr, [], :target => target, :code => code)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Server directive <?target code... ?>
|
class MDElement
|
||||||
def md_xml_instr(target, code)
|
INSPECT2_FORMS = {
|
||||||
md_el(:xml_instr, [], {:target=>target, :code=>code})
|
:paragraph => ["par", :children],
|
||||||
end
|
: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
|
||||||
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
|
def consume_whitespace
|
||||||
while c = cur_char
|
while c = cur_char
|
||||||
if (c == ?\s || c == ?\t)
|
if (c == ?\s || c == ?\t)
|
||||||
# puts "ignoring #{c}"
|
# puts "ignoring #{c}"
|
||||||
ignore_char
|
ignore_char
|
||||||
else
|
else
|
||||||
|
@ -191,7 +191,7 @@ def describe_pos(buffer, buffer_index)
|
||||||
pre + "+--- Byte #{buffer_index}\n"+
|
pre + "+--- Byte #{buffer_index}\n"+
|
||||||
|
|
||||||
"Shown bytes [#{index_start} to #{size}] of #{buffer.size}:\n"+
|
"Shown bytes [#{index_start} to #{size}] of #{buffer.size}:\n"+
|
||||||
add_tabs(buffer,1,">")
|
buffer.gsub(/^/, ">")
|
||||||
|
|
||||||
# "CharSource: At character #{@buffer_index} of block "+
|
# "CharSource: At character #{@buffer_index} of block "+
|
||||||
# " beginning with:\n #{@buffer[0,50].inspect} ...\n"+
|
# " 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"+
|
"match=#{@m.to_s.inspect}\n"+
|
||||||
"Tag stack = #{@tag_stack.inspect} \n"+
|
"Tag stack = #{@tag_stack.inspect} \n"+
|
||||||
"Before:\n"+
|
"Before:\n"+
|
||||||
add_tabs(@already,1,'|')+"\n"+
|
@already.gsub(/^/, '|')+"\n"+
|
||||||
"After:\n"+
|
"After:\n"+
|
||||||
add_tabs(@rest,1,'|')+"\n"
|
@rest.gsub(/^/, '|')+"\n"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ class LineSource
|
||||||
|
|
||||||
# if @parent
|
# if @parent
|
||||||
# s << "Parent context is: \n"
|
# s << "Parent context is: \n"
|
||||||
# s << add_tabs(@parent.describe,1,'|')
|
# s << @parent.describe.gsub(/^/, '|')
|
||||||
# end
|
# end
|
||||||
s
|
s
|
||||||
end
|
end
|
||||||
|
|
|
@ -198,8 +198,8 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
ial = $2
|
ial = $2
|
||||||
al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil])
|
al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil])
|
||||||
end
|
end
|
||||||
level = num_leading_hashes(line)
|
level = line[/^#+/].size
|
||||||
text = parse_lines_as_span [strip_hashes(line)]
|
text = parse_lines_as_span [line.gsub(/\A#+|#+\Z/, '')]
|
||||||
return md_header(level, text, al)
|
return md_header(level, text, al)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
if not code =~ (/\?>\s*$/)
|
if not code =~ (/\?>\s*$/)
|
||||||
garbage = (/\?>(.*)$/.match(code))[1]
|
garbage = (/\?>(.*)$/.match(code))[1]
|
||||||
maruku_error "Trailing garbage on last line: #{garbage.inspect}:\n"+
|
maruku_error "Trailing garbage on last line: #{garbage.inspect}:\n"+
|
||||||
add_tabs(code, 1, '|'), src
|
code.gsub(/^/, '|'), src
|
||||||
end
|
end
|
||||||
code.gsub!(/\?>\s*$/, '')
|
code.gsub!(/\?>\s*$/, '')
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
end
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
ex = e.inspect + e.backtrace.join("\n")
|
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
|
end
|
||||||
if not (h.rest =~ /^\s*$/)
|
if not (h.rest =~ /^\s*$/)
|
||||||
maruku_error "Could you please format this better?\n"+
|
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
|
lines << src.shift_line
|
||||||
end
|
end
|
||||||
# dbg_describe_ary(lines, 'PAR')
|
|
||||||
children = parse_lines_as_span(lines, src)
|
children = parse_lines_as_span(lines, src)
|
||||||
|
|
||||||
return md_par(children)
|
return md_par(children)
|
||||||
|
@ -296,7 +295,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
stripped = first[indentation, first.size-1]
|
stripped = first[indentation, first.size-1]
|
||||||
lines.unshift stripped
|
lines.unshift stripped
|
||||||
|
|
||||||
# dbg_describe_ary(lines, 'LIST ITEM ')
|
|
||||||
|
|
||||||
src2 = LineSource.new(lines, src, parent_offset)
|
src2 = LineSource.new(lines, src, parent_offset)
|
||||||
children = parse_blocks(src2)
|
children = parse_blocks(src2)
|
||||||
|
@ -347,7 +345,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
# add first line
|
# add first line
|
||||||
if text && text.strip != "" then lines.unshift text end
|
if text && text.strip != "" then lines.unshift text end
|
||||||
|
|
||||||
# dbg_describe_ary(lines, 'FOOTNOTE')
|
|
||||||
src2 = LineSource.new(lines, src, parent_offset)
|
src2 = LineSource.new(lines, src, parent_offset)
|
||||||
children = parse_blocks(src2)
|
children = parse_blocks(src2)
|
||||||
|
|
||||||
|
@ -405,7 +402,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
want_my_paragraph = saw_anything_after ||
|
want_my_paragraph = saw_anything_after ||
|
||||||
(saw_empty && (src.cur_line && (src.cur_line.md_type == item_type)))
|
(saw_empty && (src.cur_line && (src.cur_line.md_type == item_type)))
|
||||||
|
|
||||||
# dbg_describe_ary(lines, 'LI')
|
|
||||||
# create a new context
|
# create a new context
|
||||||
|
|
||||||
while lines.last && (lines.last.md_type == :empty)
|
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
|
while src.cur_line && src.cur_line.md_type == :quote
|
||||||
lines << unquote(src.shift_line)
|
lines << unquote(src.shift_line)
|
||||||
end
|
end
|
||||||
# dbg_describe_ary(lines, 'QUOTE')
|
|
||||||
|
|
||||||
src2 = LineSource.new(lines, src, parent_offset)
|
src2 = LineSource.new(lines, src, parent_offset)
|
||||||
children = parse_blocks(src2)
|
children = parse_blocks(src2)
|
||||||
|
@ -451,7 +446,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
|
|
||||||
source = lines.join("\n")
|
source = lines.join("\n")
|
||||||
|
|
||||||
# dbg_describe_ary(lines, 'CODE')
|
|
||||||
|
|
||||||
return md_codeblock(source)
|
return md_codeblock(source)
|
||||||
end
|
end
|
||||||
|
@ -568,7 +562,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
while src.cur_line && src.cur_line.md_type == :text
|
while src.cur_line && src.cur_line.md_type == :text
|
||||||
terms << md_el(:definition_term, parse_lines_as_span([src.shift_line]))
|
terms << md_el(:definition_term, parse_lines_as_span([src.shift_line]))
|
||||||
end
|
end
|
||||||
# dbg_describe_ary(terms, 'DT')
|
|
||||||
|
|
||||||
want_my_paragraph = false
|
want_my_paragraph = false
|
||||||
|
|
||||||
|
@ -599,7 +592,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
||||||
|
|
||||||
lines.unshift first
|
lines.unshift first
|
||||||
|
|
||||||
# dbg_describe_ary(lines, 'DD')
|
|
||||||
src2 = LineSource.new(lines, src, parent_offset)
|
src2 = LineSource.new(lines, src, parent_offset)
|
||||||
children = parse_blocks(src2)
|
children = parse_blocks(src2)
|
||||||
definitions << md_el(:definition_data, children)
|
definitions << md_el(:definition_data, children)
|
||||||
|
|
|
@ -141,19 +141,19 @@ Disabled by default because of security concerns.
|
||||||
return object.instance_eval(code)
|
return object.instance_eval(code)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
maruku_error "Exception while executing this:\n"+
|
maruku_error "Exception while executing this:\n"+
|
||||||
add_tabs(code, 1, ">")+
|
code.gsub(/^/, ">")+
|
||||||
"\nThe error was:\n"+
|
"\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
|
rescue RuntimeError => e
|
||||||
maruku_error "2: Exception while executing this:\n"+
|
maruku_error "2: Exception while executing this:\n"+
|
||||||
add_tabs(code, 1, ">")+
|
code.gsub(/^/, ">")+
|
||||||
"\nThe error was:\n"+
|
"\nThe error was:\n"+
|
||||||
add_tabs(e.inspect, 1, "|")
|
e.inspect.gsub(/^/, "|")
|
||||||
rescue SyntaxError => e
|
rescue SyntaxError => e
|
||||||
maruku_error "2: Exception while executing this:\n"+
|
maruku_error "2: Exception while executing this:\n"+
|
||||||
add_tabs(code, 1, ">")+
|
code.gsub(/^/, ">")+
|
||||||
"\nThe error was:\n"+
|
"\nThe error was:\n"+
|
||||||
add_tabs(e.inspect, 1, "|")
|
e.inspect.gsub(/^/, "|")
|
||||||
end
|
end
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -500,7 +500,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
|
||||||
# end
|
# end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
maruku_error "Bad html: \n" +
|
maruku_error "Bad html: \n" +
|
||||||
add_tabs(e.inspect+e.backtrace.join("\n"),1,'>'),
|
(e.inspect+e.backtrace.join("\n")).gsub(/^/, '>'),
|
||||||
src,con
|
src,con
|
||||||
maruku_recover "I will try to continue after bad HTML.", src, con
|
maruku_recover "I will try to continue after bad HTML.", src, con
|
||||||
con.push_char src.shift_char
|
con.push_char src.shift_char
|
||||||
|
@ -733,7 +733,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
|
||||||
def describe
|
def describe
|
||||||
lines = @elements.map{|x| x.inspect}.join("\n")
|
lines = @elements.map{|x| x.inspect}.join("\n")
|
||||||
s = "Elements read in span: \n" +
|
s = "Elements read in span: \n" +
|
||||||
add_tabs(lines,1, ' -')+"\n"
|
lines.gsub(/^/, ' -')+"\n"
|
||||||
|
|
||||||
if @cur_string.size > 0
|
if @cur_string.size > 0
|
||||||
s += "Current string: \n #{@cur_string.inspect}\n"
|
s += "Current string: \n #{@cur_string.inspect}\n"
|
||||||
|
|
22
vendor/plugins/maruku/lib/maruku/maruku.rb
vendored
22
vendor/plugins/maruku/lib/maruku/maruku.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,18 +15,17 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#++
|
|
||||||
|
|
||||||
|
|
||||||
# The Maruku class is the public interface
|
# The public interface for Maruku.
|
||||||
#
|
#
|
||||||
|
# @example Render a document fragment
|
||||||
class Maruku
|
# Maruku.new("## Header ##").to_html
|
||||||
def initialize(s=nil, meta={})
|
# # => "<h2 id='header'>header</h2>"
|
||||||
super(nil)
|
class Maruku < MaRuKu::MDDocument
|
||||||
self.attributes.merge! meta
|
def initialize(s = nil, meta = {})
|
||||||
if s
|
super(nil)
|
||||||
parse_doc(s)
|
self.attributes.merge! meta
|
||||||
end
|
parse_doc(s) if s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -828,7 +828,7 @@ If true, raw HTML is discarded from the output.
|
||||||
else # invalid
|
else # invalid
|
||||||
# Creates red box with offending HTML
|
# Creates red box with offending HTML
|
||||||
tell_user "Wrapping bad html in a PRE with class 'markdown-html-error'\n"+
|
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 = Element.new('pre')
|
||||||
pre.attributes['style'] = 'border: solid 3px red; background-color: pink'
|
pre.attributes['style'] = 'border: solid 3px red; background-color: pink'
|
||||||
pre.attributes['class'] = 'markdown-html-error'
|
pre.attributes['class'] = 'markdown-html-error'
|
||||||
|
|
|
@ -55,10 +55,10 @@ module MaRuKu; module Out; module Latex
|
||||||
end
|
end
|
||||||
|
|
||||||
class LatexEntity
|
class LatexEntity
|
||||||
safe_attr_accessor :html_num, Fixnum
|
attr_accessor :html_num
|
||||||
safe_attr_accessor :html_entity, String
|
attr_accessor :html_entity
|
||||||
safe_attr_accessor :latex_string, String
|
attr_accessor :latex_string
|
||||||
safe_attr_accessor :latex_packages, Array
|
attr_accessor :latex_packages
|
||||||
end
|
end
|
||||||
|
|
||||||
def Latex.need_entity_table
|
def Latex.need_entity_table
|
||||||
|
@ -69,7 +69,7 @@ module MaRuKu; module Out; module Latex
|
||||||
def Latex.init_entity_table
|
def Latex.init_entity_table
|
||||||
# $stderr.write "Creating entity table.."
|
# $stderr.write "Creating entity table.."
|
||||||
# $stderr.flush
|
# $stderr.flush
|
||||||
doc = Document.new XML_TABLE
|
doc = Document.new(File.read(File.dirname(__FILE__) + "/../../../data/entities.xml"))
|
||||||
doc.elements.each("//char") do |c|
|
doc.elements.each("//char") do |c|
|
||||||
num = c.attributes['num'].to_i
|
num = c.attributes['num'].to_i
|
||||||
name = c.attributes['name']
|
name = c.attributes['name']
|
||||||
|
@ -97,271 +97,5 @@ module MaRuKu; module Out; module Latex
|
||||||
|
|
||||||
ENTITY_TABLE = {}
|
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
|
end end end
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ module MaRuKu; module Out; module Markdown
|
||||||
|
|
||||||
def to_md_li_span(context)
|
def to_md_li_span(context)
|
||||||
len = (context[:line_length] || DefaultLineLength) - 2
|
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[0] = ?*
|
||||||
s + "\n"
|
s + "\n"
|
||||||
end
|
end
|
||||||
|
@ -60,7 +60,7 @@ module MaRuKu; module Out; module Markdown
|
||||||
len = (context[:line_length] || DefaultLineLength) - 2
|
len = (context[:line_length] || DefaultLineLength) - 2
|
||||||
md = ""
|
md = ""
|
||||||
self.children.each_with_index do |li, i|
|
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]
|
s[0,4] = "#{i+1}. "[0,4]
|
||||||
# puts w.inspect
|
# puts w.inspect
|
||||||
md += s
|
md += s
|
||||||
|
|
282
vendor/plugins/maruku/lib/maruku/string_utils.rb
vendored
282
vendor/plugins/maruku/lib/maruku/string_utils.rb
vendored
|
@ -18,150 +18,176 @@
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#++
|
#++
|
||||||
|
|
||||||
|
require 'strscan'
|
||||||
|
|
||||||
# Boring stuff with strings.
|
module MaRuKu
|
||||||
module MaRuKu; module Strings
|
# Utility functions for dealing with strings.
|
||||||
|
module Strings
|
||||||
|
TAB_SIZE = 4
|
||||||
|
|
||||||
def add_tabs(s,n=1,char="\t")
|
# Split a string into multiple lines,
|
||||||
s.split("\n").map{|x| char*n+x }.join("\n")
|
# on line feeds and/or carriage returns.
|
||||||
end
|
#
|
||||||
|
# @param s [String]
|
||||||
|
# @return [String]
|
||||||
|
def split_lines(s)
|
||||||
|
s.split(/\r\n|\r|\n/)
|
||||||
|
end
|
||||||
|
|
||||||
TabSize = 4;
|
# 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)
|
||||||
|
|
||||||
def split_lines(s)
|
while scanner.scan(/(\w[\w\s\-]+): +(.*)\n/)
|
||||||
s.gsub("\r","").split("\n")
|
k, v = normalize_key_and_value(scanner[1], scanner[2])
|
||||||
end
|
headers[k.to_sym] = v
|
||||||
|
end
|
||||||
|
|
||||||
# This parses email headers. Returns an hash.
|
headers[:data] = scanner.rest
|
||||||
#
|
headers
|
||||||
# +hash['data']+ is the message.
|
end
|
||||||
#
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Keys are downcased, space becomes underscore, converted to symbols.
|
# Returns the number of leading spaces,
|
||||||
def normalize_key_and_value(k,v)
|
# considering that a tab counts as {TAB_SIZE} spaces.
|
||||||
v = v ? v.strip : true # no value defaults to true
|
#
|
||||||
k = k.strip
|
# @param s [String]
|
||||||
|
# @return [Fixnum]
|
||||||
|
def number_of_leading_spaces(s)
|
||||||
|
spaces = s.scan(/^\s*/).first
|
||||||
|
spaces.count(" ") + spaces.count("\t") * TAB_SIZE
|
||||||
|
end
|
||||||
|
|
||||||
# check synonyms
|
# This returns the position of the first non-list character
|
||||||
v = true if ['yes','true'].include?(v.to_s.downcase)
|
# in a list item.
|
||||||
v = false if ['no','false'].include?(v.to_s.downcase)
|
#
|
||||||
|
# @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
|
||||||
|
|
||||||
k = k.downcase.gsub(' ','_')
|
# Replace spaces with underscores and remove non-word characters.
|
||||||
return k, v
|
#
|
||||||
end
|
# @param s [String]
|
||||||
|
# @return [String]
|
||||||
|
def sanitize_ref_id(s)
|
||||||
|
s.strip.downcase.gsub(' ', '_').gsub(/[^\w]/, '')
|
||||||
|
end
|
||||||
|
|
||||||
# Returns the number of leading spaces, considering that
|
# Remove line-initial `>` characters for a quotation.
|
||||||
# a tab counts as `TabSize` spaces.
|
#
|
||||||
def number_of_leading_spaces(s)
|
# @param s [String]
|
||||||
s[/^[ \t]*/].gsub("\t", ' '*TabSize).length
|
# @return [String]
|
||||||
end
|
def unquote(s)
|
||||||
|
s.gsub(/^>\s?/, '')
|
||||||
|
end
|
||||||
|
|
||||||
# This returns the position of the first real char in a list item
|
# Removes indentation from the beginning of `s`,
|
||||||
#
|
# up to at most `n` spaces.
|
||||||
# For example:
|
# Tabs are counted as {TAB_SIZE} spaces.
|
||||||
# '*Hello' # => 1
|
#
|
||||||
# '* Hello' # => 2
|
# @param s [String]
|
||||||
# ' * Hello' # => 3
|
# @param n [Fixnum]
|
||||||
# ' * Hello' # => 5
|
# @return [String]
|
||||||
# '1.Hello' # => 2
|
def strip_indent(s, n)
|
||||||
# ' 1. Hello' # => 5
|
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
|
||||||
|
|
||||||
def spaces_before_first_char(s)
|
# Escapes a string so that it can be safely used in a Bourne shell command line.
|
||||||
case s.md_type
|
#
|
||||||
when :ulist
|
# Note that a resulted string should be used unquoted
|
||||||
# whitespace, followed by ('*'|'+'|'-') followed by
|
# and is not intended for use in double quotes nor in single quotes.
|
||||||
# more whitespace, followed by an optional IAL, followed
|
#
|
||||||
# by yet more whitespace
|
# This is a copy of the Shellwords.shellescape function in Ruby 1.8.7.
|
||||||
h=s[/^\s*(\*|\+|\-)\s*(\{.*?\})?\s*/]
|
# It's included for Ruby 1.8.6 compatibility.
|
||||||
when :olist
|
#
|
||||||
# whitespace, followed by a number, followed by a period,
|
# @param str [String]
|
||||||
# more whitespace, an optional IAL, and more whitespace
|
# @return [String]
|
||||||
h=s[/^\s*\d+\.\s*(\{.*?\})?\s*/]
|
def shellescape(str)
|
||||||
else
|
# An empty argument will be skipped, so return empty quotes.
|
||||||
tell_user "BUG (my bad): '#{s}' is not a list"
|
return "''" if str.empty?
|
||||||
h=''
|
|
||||||
end
|
|
||||||
ial = h[/\{.*\}/]
|
|
||||||
return [h.length, ial]
|
|
||||||
end
|
|
||||||
|
|
||||||
# Counts the number of leading '#' in the string
|
str = str.dup
|
||||||
def num_leading_hashes(s)
|
|
||||||
h = s[/^#*/]
|
|
||||||
h ? h.length : 0
|
|
||||||
end
|
|
||||||
|
|
||||||
# Strips initial and final hashes
|
# Process as a single byte sequence because not all shell
|
||||||
def strip_hashes(s)
|
# implementations are multibyte aware.
|
||||||
s.sub(/^#*(.*?)(#|\s)*$/, '\1').strip
|
str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")
|
||||||
end
|
|
||||||
|
|
||||||
# change space to "_" and remove any non-word character
|
# A LF cannot be escaped with a backslash because a backslash + LF
|
||||||
def sanitize_ref_id(x)
|
# combo is regarded as line continuation and simply ignored.
|
||||||
x.downcase.gsub(' ','_').gsub(/[^\w]/,'')
|
str.gsub!(/\n/, "'\n'")
|
||||||
end
|
|
||||||
|
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
# removes initial quote
|
private
|
||||||
def unquote(s)
|
|
||||||
s.gsub(/^>\s?/,'')
|
|
||||||
end
|
|
||||||
|
|
||||||
# toglie al massimo n caratteri
|
# Normalize the key/value pairs for email headers.
|
||||||
def strip_indent(s, n)
|
# Keys are downcased and converted to symbols;
|
||||||
i = 0
|
# spaces become underscores.
|
||||||
while i < s.size && n>0
|
#
|
||||||
c = s[i,1]
|
# Values of `"yes"`, `"true"`, `"no"`, and `"false"`
|
||||||
if c == ' '
|
# are converted to appropriate booleans.
|
||||||
n-=1;
|
#
|
||||||
elsif c == "\t"
|
# @param k [String]
|
||||||
n-=TabSize;
|
# @param v [String]
|
||||||
else
|
# @return [Array(String, String or Boolean)]
|
||||||
break
|
def normalize_key_and_value(k, v)
|
||||||
end
|
k = k.strip.downcase.gsub(/\s+/, '_')
|
||||||
i+=1
|
v = v.strip
|
||||||
end
|
|
||||||
s[i, s.size]
|
|
||||||
end
|
|
||||||
|
|
||||||
def dbg_describe_ary(a, prefix='')
|
|
||||||
i = 0
|
|
||||||
a.each do |l|
|
|
||||||
puts "#{prefix} (#{i+=1})# #{l.inspect}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def force_linebreak?(l)
|
|
||||||
l =~ / $/
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
# 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
|
end
|
||||||
|
|
245
vendor/plugins/maruku/lib/maruku/structures.rb
vendored
245
vendor/plugins/maruku/lib/maruku/structures.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,155 +15,129 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# 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
|
module MaRuKu
|
||||||
|
# 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
|
||||||
|
|
||||||
# I did not want to have a class for each possible element.
|
# The child nodes of this element.
|
||||||
# Instead I opted to have only the class "MDElement"
|
#
|
||||||
# that represents eveything in the document (paragraphs, headers, etc).
|
# @return [Array<String or MDElement>]
|
||||||
#
|
attr_accessor :children
|
||||||
# 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
|
# An attribute list. May not be nil.
|
||||||
safe_attr_accessor :children, Array
|
#
|
||||||
|
# @return [AttributeList]
|
||||||
|
attr_accessor :al
|
||||||
|
|
||||||
# An attribute list, may not be nil
|
# The processed attributes.
|
||||||
safe_attr_accessor :al, Array #Maruku::AttributeList
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
# These are the processed attributes
|
# The root element of the document
|
||||||
safe_attr_accessor :attributes, Hash
|
# to which this element belongs.
|
||||||
|
#
|
||||||
|
# @return [Maruku]
|
||||||
|
attr_accessor :doc
|
||||||
|
|
||||||
# Reference of the document (which is of class Maruku)
|
def initialize(node_type = :unset, children = [], meta = {}, al = nil)
|
||||||
attr_accessor :doc
|
self.children = children
|
||||||
|
self.node_type = node_type
|
||||||
|
self.attributes = {}
|
||||||
|
|
||||||
def initialize(node_type=:unset, children=[], meta={},
|
meta.each do |symbol, value|
|
||||||
al=MaRuKu::AttributeList.new )
|
self.instance_eval <<RUBY
|
||||||
super();
|
def #{symbol}; @#{symbol}; end
|
||||||
self.children = children
|
def #{symbol}=(val); @#{symbol} = val; end
|
||||||
self.node_type = node_type
|
RUBY
|
||||||
|
self.send "#{symbol}=", value
|
||||||
|
end
|
||||||
|
|
||||||
@attributes = {}
|
self.al = al || AttributeList.new
|
||||||
|
self.meta_priv = meta
|
||||||
|
end
|
||||||
|
|
||||||
meta.each do |symbol, value|
|
# @private
|
||||||
self.instance_eval "
|
attr_accessor :meta_priv
|
||||||
def #{symbol}; @#{symbol}; end
|
|
||||||
def #{symbol}=(val); @#{symbol}=val; end"
|
|
||||||
self.send "#{symbol}=", value
|
|
||||||
end
|
|
||||||
|
|
||||||
self.al = al || AttributeList.new
|
def ==(o)
|
||||||
|
o.is_a?(MDElement) &&
|
||||||
|
self.node_type == o.node_type &&
|
||||||
|
self.meta_priv == o.meta_priv &&
|
||||||
|
self.children == o.children
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self.meta_priv = meta
|
# This represents the whole document and holds global data.
|
||||||
end
|
class MDDocument
|
||||||
|
# @return [{String => {:url => String, :title => String}}]
|
||||||
|
attr_accessor :refs
|
||||||
|
|
||||||
attr_accessor :meta_priv
|
# @return [{String => MDElement}]
|
||||||
|
attr_accessor :footnotes
|
||||||
|
|
||||||
def ==(o)
|
# @return [{String => String}]
|
||||||
ok = o.kind_of?(MDElement) &&
|
attr_accessor :abbreviations
|
||||||
(self.node_type == o.node_type) &&
|
|
||||||
(self.meta_priv == o.meta_priv) &&
|
|
||||||
(self.children == o.children)
|
|
||||||
|
|
||||||
if not ok
|
# Attribute definition lists.
|
||||||
# puts "This:\n"+self.inspect+"\nis different from\n"+o.inspect+"\n\n"
|
#
|
||||||
end
|
# @return [{String => AttributeList}]
|
||||||
ok
|
attr_accessor :ald
|
||||||
end
|
|
||||||
|
# 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
|
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,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,72 +15,37 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# 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
|
module MaRuKu
|
||||||
class MDElement
|
class MDElement
|
||||||
def inspect(compact=true)
|
def inspect(compact=true)
|
||||||
if compact
|
if compact
|
||||||
i2 = inspect2
|
i2 = inspect2
|
||||||
return i2 if i2
|
return i2 if i2
|
||||||
end
|
end
|
||||||
|
|
||||||
"md_el(:%s,%s,%s,%s)" %
|
# Make sure the attributes are lexically ordered
|
||||||
[
|
meta_ordered = "{" + @meta_priv.keys.
|
||||||
self.node_type,
|
map {|x| x.to_s}.sort.map {|x| x.to_sym}.
|
||||||
children_inspect(compact),
|
map {|k| k.inspect + "=>" + @meta_priv[k].inspect}.
|
||||||
@meta_priv.inspect_ordered,
|
join(',') + "}"
|
||||||
self.al.inspect
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
def children_inspect(compact=true)
|
"md_el(%s,%s,%s,%s)" % [
|
||||||
s = @children.inspect_more(compact,', ')
|
self.node_type.inspect,
|
||||||
if @children.empty?
|
children_inspect(compact),
|
||||||
"[]"
|
meta_ordered,
|
||||||
elsif s.size < 70
|
self.al.inspect
|
||||||
s
|
]
|
||||||
else
|
end
|
||||||
"[\n"+
|
|
||||||
add_tabs(@children.inspect_more(compact,",\n",false))+
|
|
||||||
"\n]"
|
|
||||||
end
|
|
||||||
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
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,46 +15,34 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#++
|
|
||||||
|
|
||||||
|
|
||||||
module MaRuKu
|
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
|
# Iterates through each String child node of this element,
|
||||||
|
# replacing it with the result of the block.
|
||||||
# Yields to each element of specified node_type
|
# This includes deeply-nested child nodes.
|
||||||
# All elements if e_node_type is nil.
|
#
|
||||||
def each_element(e_node_type=nil, &block)
|
# This destructively modifies this node and its children.
|
||||||
@children.each do |c|
|
#
|
||||||
if c.kind_of? MDElement
|
# @todo Make this non-destructive
|
||||||
if (not e_node_type) || (e_node_type == c.node_type)
|
def replace_each_string(&block)
|
||||||
block.call c
|
@children.map! do |c|
|
||||||
end
|
next yield c unless c.is_a?(MDElement)
|
||||||
c.each_element(e_node_type, &block)
|
c.replace_each_string(&block)
|
||||||
end
|
c
|
||||||
end
|
end.flatten!
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
369
vendor/plugins/maruku/lib/maruku/toc.rb
vendored
369
vendor/plugins/maruku/lib/maruku/toc.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,184 +15,200 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#++
|
|
||||||
|
|
||||||
|
|
||||||
module MaRuKu
|
module MaRuKu
|
||||||
|
# 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
|
||||||
|
|
||||||
class MDDocument
|
# The nested section number, e.g. `[1, 2, 5]` for Section 1.2.5.
|
||||||
# an instance of Section (see below)
|
#
|
||||||
attr_accessor :toc
|
# @return [Array<Fixnum>]
|
||||||
end
|
attr_accessor :section_number
|
||||||
|
|
||||||
# This represents a section in the TOC.
|
# The `:header` node for this section.
|
||||||
class Section
|
# The value of `meta[:section]` for the header will be this node.
|
||||||
# a Fixnum, is == header_element.level
|
#
|
||||||
attr_accessor :section_level
|
# @return [MDElement]
|
||||||
|
attr_accessor :header_element
|
||||||
# An array of fixnum, like [1,2,5] for Section 1.2.5
|
|
||||||
attr_accessor :section_number
|
# The immediate child nodes of this section.
|
||||||
|
#
|
||||||
# reference to header (header has h.meta[:section] to self)
|
# @todo Why does this never contain Strings?
|
||||||
attr_accessor :header_element
|
#
|
||||||
|
# @return [Array<MDElement>]
|
||||||
# Array of immediate children of this element
|
attr_accessor :immediate_children
|
||||||
attr_accessor :immediate_children
|
|
||||||
|
# The subsections of this section.
|
||||||
# Array of Section inside this section
|
#
|
||||||
attr_accessor :section_children
|
# @return [Array<Section>]
|
||||||
|
attr_accessor :section_children
|
||||||
def initialize
|
|
||||||
@immediate_children = []
|
def initialize
|
||||||
@section_children = []
|
@immediate_children = []
|
||||||
end
|
@section_children = []
|
||||||
end
|
end
|
||||||
|
|
||||||
class Section
|
def inspect(indent = 1)
|
||||||
def inspect(indent=1)
|
s = ""
|
||||||
s = ""
|
|
||||||
if @header_element
|
if @header_element
|
||||||
s += "\_"*indent + "(#{@section_level})>\t #{@section_number.join('.')} : "
|
s << "\_" * indent <<
|
||||||
s += @header_element.children_to_s +
|
"(#{@section_level})>\t #{@section_number.join('.')} : " <<
|
||||||
" (id: '#{@header_element.attributes[:id]}')\n"
|
@header_element.children_to_s <<
|
||||||
else
|
" (id: '#{@header_element.attributes[:id]}')\n"
|
||||||
s += "Master\n"
|
else
|
||||||
end
|
s << "Master\n"
|
||||||
|
end
|
||||||
@section_children.each do |c|
|
@section_children.each {|c| s << c.inspect(indent+1)}
|
||||||
s+=c.inspect(indent+1)
|
|
||||||
end
|
s
|
||||||
s
|
end
|
||||||
end
|
|
||||||
|
# Assign \{#section\_number section numbers}
|
||||||
# Numerate this section and its children
|
# to this section and its children.
|
||||||
def numerate(a=[])
|
# This also assigns the section number attribute
|
||||||
self.section_number = a
|
# to the sections' headers.
|
||||||
section_children.each_with_index do |c,i|
|
#
|
||||||
c.numerate(a.clone.push(i+1))
|
# This should only be called on the root section.
|
||||||
end
|
#
|
||||||
if h = self.header_element
|
# @overload def numerate
|
||||||
h.attributes[:section_number] = self.section_number
|
def numerate(a = [])
|
||||||
end
|
self.section_number = a
|
||||||
end
|
section_children.each_with_index {|c, i| c.numerate(a + [i + 1])}
|
||||||
|
if h = self.header_element
|
||||||
include REXML
|
h.attributes[:section_number] = self.section_number
|
||||||
# Creates an HTML toc.
|
end
|
||||||
# Call this on the root
|
end
|
||||||
def to_html
|
|
||||||
div = Element.new 'div'
|
include REXML
|
||||||
div.attributes['class'] = 'maruku_toc'
|
|
||||||
div << create_toc
|
# Returns an HTML representation of the table of contents.
|
||||||
div
|
#
|
||||||
end
|
# This should only be called on the root section.
|
||||||
|
def to_html
|
||||||
def create_toc
|
div = Element.new 'div'
|
||||||
ul = Element.new 'ul'
|
div.attributes['class'] = 'maruku_toc'
|
||||||
# let's remove the bullets
|
div << _to_html
|
||||||
ul.attributes['style'] = 'list-style: none;'
|
div
|
||||||
@section_children.each do |c|
|
end
|
||||||
li = Element.new 'li'
|
|
||||||
if span = c.header_element.render_section_number
|
# Returns a LaTeX representation of the table of contents.
|
||||||
li << span
|
#
|
||||||
end
|
# This should only be called on the root section.
|
||||||
a = c.header_element.wrap_as_element('a')
|
def to_latex
|
||||||
a.delete_attribute 'id'
|
_to_latex + "\n\n"
|
||||||
a.attributes['href'] = "##{c.header_element.attributes[:id]}"
|
end
|
||||||
li << a
|
|
||||||
li << c.create_toc if c.section_children.size>0
|
protected
|
||||||
ul << li
|
|
||||||
end
|
def _to_html
|
||||||
ul
|
ul = Element.new 'ul'
|
||||||
end
|
# let's remove the bullets
|
||||||
|
ul.attributes['style'] = 'list-style: none;'
|
||||||
# Creates a latex toc.
|
@section_children.each do |c|
|
||||||
# Call this on the root
|
li = Element.new 'li'
|
||||||
def to_latex
|
if span = c.header_element.render_section_number
|
||||||
to_latex_rec + "\n\n"
|
li << span
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_latex_rec
|
a = c.header_element.wrap_as_element('a')
|
||||||
s = ""
|
a.delete_attribute 'id'
|
||||||
@section_children.each do |c|
|
a.attributes['href'] = "##{c.header_element.attributes[:id]}"
|
||||||
s += "\\noindent"
|
|
||||||
number = c.header_element.section_number
|
li << a
|
||||||
s += number if number
|
li << c._to_html if c.section_children.size > 0
|
||||||
text = c.header_element.children_to_latex
|
ul << li
|
||||||
id = c.header_element.attributes[:id]
|
end
|
||||||
s += "\\hyperlink{#{id}}{#{text}}"
|
ul
|
||||||
s += "\\dotfill \\pageref*{#{id}} \\linebreak\n"
|
end
|
||||||
s += c.to_latex_rec if c.section_children.size>0
|
|
||||||
|
def _to_latex
|
||||||
end
|
s = ""
|
||||||
s
|
@section_children.each do |c|
|
||||||
end
|
s << "\\noindent"
|
||||||
|
if number = c.header_element.section_number
|
||||||
end
|
s << number
|
||||||
|
end
|
||||||
class MDDocument
|
id = c.header_element.attributes[:id]
|
||||||
|
text = c.header_element.children_to_latex
|
||||||
def create_toc
|
s << "\\hyperlink{#{id}}{#{text}}"
|
||||||
each_element(:header) do |h|
|
s << "\\dotfill \\pageref*{#{id}} \\linebreak\n"
|
||||||
h.attributes[:id] ||= h.generate_id
|
s << c._to_latex if c.section_children.size > 0
|
||||||
end
|
end
|
||||||
|
s
|
||||||
stack = []
|
end
|
||||||
|
end
|
||||||
# the ancestor section
|
|
||||||
s = Section.new
|
class MDDocument
|
||||||
s.section_level = 0
|
# The table of contents for the document.
|
||||||
|
#
|
||||||
stack.push s
|
# @return [Section]
|
||||||
|
attr_accessor :toc
|
||||||
i = 0;
|
|
||||||
while i < @children.size
|
def create_toc
|
||||||
while i < @children.size
|
each_element(:header) {|h| h.attributes[:id] ||= h.generate_id}
|
||||||
if @children[i].node_type == :header
|
|
||||||
level = @children[i].level
|
stack = []
|
||||||
break if level <= stack.last.section_level+1
|
|
||||||
end
|
# The root section
|
||||||
|
s = Section.new
|
||||||
stack.last.immediate_children.push @children[i]
|
s.section_level = 0
|
||||||
i += 1
|
|
||||||
end
|
stack.push s
|
||||||
|
|
||||||
break if i>=@children.size
|
# TODO: Clean up the logic here once we have better tests
|
||||||
|
i = 0
|
||||||
header = @children[i]
|
while i < @children.size
|
||||||
level = header.level
|
while i < @children.size
|
||||||
|
if @children[i].node_type == :header
|
||||||
if level > stack.last.section_level
|
level = @children[i].level
|
||||||
# this level is inside
|
break if level <= stack.last.section_level + 1
|
||||||
|
end
|
||||||
s2 = Section.new
|
|
||||||
s2.section_level = level
|
stack.last.immediate_children.push @children[i]
|
||||||
s2.header_element = header
|
i += 1
|
||||||
header.instance_variable_set :@section, s2
|
end
|
||||||
|
|
||||||
stack.last.section_children.push s2
|
break if i >= @children.size
|
||||||
stack.push s2
|
|
||||||
|
header = @children[i]
|
||||||
i+=1
|
level = header.level
|
||||||
elsif level == stack.last.section_level
|
|
||||||
# this level is a sibling
|
if level > stack.last.section_level
|
||||||
stack.pop
|
# this level is inside
|
||||||
else
|
|
||||||
# this level is a parent
|
s2 = Section.new
|
||||||
stack.pop
|
s2.section_level = level
|
||||||
end
|
s2.header_element = header
|
||||||
|
header.instance_variable_set :@section, s2
|
||||||
end
|
|
||||||
|
stack.last.section_children.push s2
|
||||||
# If there is only one big header, then assume
|
stack.push s2
|
||||||
# it is the master
|
|
||||||
if s.section_children.size == 1
|
i += 1
|
||||||
s = s.section_children.first
|
elsif level == stack.last.section_level
|
||||||
end
|
# this level is a sibling
|
||||||
|
stack.pop
|
||||||
# Assign section numbers
|
else
|
||||||
s.numerate
|
# this level is a parent
|
||||||
|
stack.pop
|
||||||
s
|
end
|
||||||
end
|
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
|
end
|
46
vendor/plugins/maruku/lib/maruku/version.rb
vendored
46
vendor/plugins/maruku/lib/maruku/version.rb
vendored
|
@ -1,4 +1,3 @@
|
||||||
#--
|
|
||||||
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
# Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
|
||||||
#
|
#
|
||||||
# This file is part of Maruku.
|
# This file is part of Maruku.
|
||||||
|
@ -16,25 +15,40 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Maruku; if not, write to the Free Software
|
# along with Maruku; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#++
|
|
||||||
|
|
||||||
module MaRuKu
|
module MaRuKu
|
||||||
Version = '0.6.0'
|
# The Maruku version.
|
||||||
|
VERSION = '0.6.0'
|
||||||
|
|
||||||
MarukuURL = 'http://maruku.rubyforge.org/'
|
# @deprecated Exists for backwards compatibility. Use {VERSION}
|
||||||
|
# @private
|
||||||
|
Version = VERSION
|
||||||
|
|
||||||
# If true, use also PHP Markdown extra syntax
|
# The URL of the Maruku website.
|
||||||
#
|
MARUKU_URL = 'http://maruku.rubyforge.org/'
|
||||||
# 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?
|
# @deprecated Exists for backwards compatibility. Use {MARUKU_URL}
|
||||||
true
|
# @private
|
||||||
end
|
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
|
end
|
||||||
|
|
Loading…
Reference in a new issue