From 4f571b1df55828d2454fc799e0e32700774f0bc7 Mon Sep 17 00:00:00 2001 From: Danang Probo Sayekti Date: Sat, 18 Jan 2014 08:44:34 +0700 Subject: [PATCH] Update the core Update the composer, adding PHP Markdown Extra replacing dflydev markdown. --- COPYRIGHT.txt | 6 +- composer.json | 2 +- composer.lock | 57 +- composer.phar | Bin 695869 -> 961537 bytes system/includes/functions.php | 22 +- themes/dan/404-search.html.php | 26 + themes/dan/404.html.php | 19 + themes/dan/css/style.css | 674 +++++ themes/dan/img/facebook.png | Bin 0 -> 2490 bytes themes/dan/img/googleplus.png | Bin 0 -> 2769 bytes themes/dan/img/rss.png | Bin 0 -> 2764 bytes themes/dan/img/share-facebook.png | Bin 0 -> 582 bytes themes/dan/img/share-googleplus.png | Bin 0 -> 836 bytes themes/dan/img/share-twitter.png | Bin 0 -> 668 bytes themes/dan/img/tumblr.png | Bin 0 -> 2640 bytes themes/dan/img/twitter.png | Bin 0 -> 2730 bytes themes/dan/layout.html.php | 69 + themes/dan/main.html.php | 41 + themes/dan/post.html.php | 53 + themes/dan/profile.html.php | 36 + vendor/autoload.php | 4 +- vendor/composer/ClassLoader.php | 196 +- vendor/composer/autoload_classmap.php | 4 +- vendor/composer/autoload_namespaces.php | 8 +- vendor/composer/autoload_psr4.php | 9 + vendor/composer/autoload_real.php | 15 +- vendor/composer/installed.json | 99 +- vendor/dflydev/markdown/.gitignore | 2 - vendor/dflydev/markdown/.travis.yml | 7 - vendor/dflydev/markdown/README.md | 98 - vendor/dflydev/markdown/composer.json | 34 - vendor/dflydev/markdown/phpunit.xml.dist | 28 - .../src/dflydev/markdown/IMarkdownParser.php | 23 - .../src/dflydev/markdown/MarkdownExtraParser.php | 1359 --------- .../src/dflydev/markdown/MarkdownParser.php | 1529 ---------- vendor/dflydev/markdown/tests/bootstrap.php | 12 - .../tests/markdown/MarkdownExtraParserTest.php | 34 - .../dflydev/tests/markdown/MarkdownParserTest.php | 73 - .../LICENSE => michelf/php-markdown/License.md} | 76 +- .../michelf/php-markdown/Michelf/Markdown.inc.php | 10 + vendor/michelf/php-markdown/Michelf/Markdown.php | 3106 ++++++++++++++++++++ .../php-markdown/Michelf/MarkdownExtra.inc.php | 11 + .../michelf/php-markdown/Michelf/MarkdownExtra.php | 38 + .../php-markdown/Michelf/MarkdownInterface.inc.php | 9 + .../php-markdown/Michelf/MarkdownInterface.php | 37 + vendor/michelf/php-markdown/Readme.md | 271 ++ vendor/michelf/php-markdown/Readme.php | 31 + vendor/michelf/php-markdown/composer.json | 31 + 48 files changed, 4765 insertions(+), 3394 deletions(-) create mode 100644 themes/dan/404-search.html.php create mode 100644 themes/dan/404.html.php create mode 100644 themes/dan/css/style.css create mode 100644 themes/dan/img/facebook.png create mode 100644 themes/dan/img/googleplus.png create mode 100644 themes/dan/img/rss.png create mode 100644 themes/dan/img/share-facebook.png create mode 100644 themes/dan/img/share-googleplus.png create mode 100644 themes/dan/img/share-twitter.png create mode 100644 themes/dan/img/tumblr.png create mode 100644 themes/dan/img/twitter.png create mode 100644 themes/dan/layout.html.php create mode 100644 themes/dan/main.html.php create mode 100644 themes/dan/post.html.php create mode 100644 themes/dan/profile.html.php create mode 100644 vendor/composer/autoload_psr4.php delete mode 100644 vendor/dflydev/markdown/.gitignore delete mode 100644 vendor/dflydev/markdown/.travis.yml delete mode 100644 vendor/dflydev/markdown/README.md delete mode 100644 vendor/dflydev/markdown/composer.json delete mode 100644 vendor/dflydev/markdown/phpunit.xml.dist delete mode 100644 vendor/dflydev/markdown/src/dflydev/markdown/IMarkdownParser.php delete mode 100644 vendor/dflydev/markdown/src/dflydev/markdown/MarkdownExtraParser.php delete mode 100644 vendor/dflydev/markdown/src/dflydev/markdown/MarkdownParser.php delete mode 100644 vendor/dflydev/markdown/tests/bootstrap.php delete mode 100644 vendor/dflydev/markdown/tests/dflydev/tests/markdown/MarkdownExtraParserTest.php delete mode 100644 vendor/dflydev/markdown/tests/dflydev/tests/markdown/MarkdownParserTest.php rename vendor/{dflydev/markdown/LICENSE => michelf/php-markdown/License.md} (58%) create mode 100644 vendor/michelf/php-markdown/Michelf/Markdown.inc.php create mode 100644 vendor/michelf/php-markdown/Michelf/Markdown.php create mode 100644 vendor/michelf/php-markdown/Michelf/MarkdownExtra.inc.php create mode 100644 vendor/michelf/php-markdown/Michelf/MarkdownExtra.php create mode 100644 vendor/michelf/php-markdown/Michelf/MarkdownInterface.inc.php create mode 100644 vendor/michelf/php-markdown/Michelf/MarkdownInterface.php create mode 100644 vendor/michelf/php-markdown/Readme.md create mode 100644 vendor/michelf/php-markdown/Readme.php create mode 100644 vendor/michelf/php-markdown/composer.json diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index a48445c..f477c49 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -21,11 +21,9 @@ license, including: Dispatch - Copyright (c) 2014 Jesus A. Domingo Composer - Copyright (c) 2011 Nils Adermann, Jordi Boggiano - - PHP Markdown & Extra - Copyright (c) 2011 Dragonfly Development Inc. - Based on PHP Markdown & Extra - Copyright (c) 2004-2009 Michel Fortin + PHP Markdown & Extra - Copyright (c) 2004-2009 Michel Fortin - Based on Markdown - Copyright (c) 2003-2006 John Gruber + Markdown - Copyright (c) 2003-2006 John Gruber \Suin\RSSWriter - Copyright (c) Suin diff --git a/composer.json b/composer.json index 4a427b9..beedb07 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "require": { - "dflydev/markdown": "v1.0.2", + "michelf/php-markdown": "1.4.*@dev", "suin/php-rss-writer": ">=1.0" } } diff --git a/composer.lock b/composer.lock index 9f8334e..3bf3edf 100644 --- a/composer.lock +++ b/composer.lock @@ -1,59 +1,60 @@ { - "hash": "cec61b54883fb666202e7af8d3393c29", + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + ], + "hash": "f4031afd76d9924ba9ef2f3fe17a97ab", "packages": [ { - "name": "dflydev/markdown", - "version": "v1.0.2", + "name": "michelf/php-markdown", + "version": "dev-lib", "source": { "type": "git", - "url": "https://github.com/dflydev/dflydev-markdown.git", - "reference": "v1.0.2" + "url": "https://github.com/michelf/php-markdown.git", + "reference": "6f952ee180e9bd345f3dd6005aa11e0f5dcbd1b8" }, "dist": { "type": "zip", - "url": "https://github.com/dflydev/dflydev-markdown/zipball/v1.0.2", - "reference": "v1.0.2", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/6f952ee180e9bd345f3dd6005aa11e0f5dcbd1b8", + "reference": "6f952ee180e9bd345f3dd6005aa11e0f5dcbd1b8", "shasum": "" }, "require": { - "php": ">=5.3" + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-lib": "1.4.x-dev" + } + }, "autoload": { "psr-0": { - "dflydev\\markdown": "src" + "Michelf": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "New BSD License" + "BSD-3-Clause" ], "authors": [ - { - "name": "Dragonfly Development Inc.", - "email": "info@dflydev.com", - "homepage": "http://dflydev.com" - }, - { - "name": "Beau Simensen", - "email": "beau@dflydev.com", - "homepage": "http://beausimensen.com" - }, { "name": "Michel Fortin", - "homepage": "http://michelf.com" + "email": "michel.fortin@michelf.ca", + "homepage": "http://michelf.ca/", + "role": "Developer" }, { "name": "John Gruber", - "homepage": "http://daringfireball.net" + "homepage": "http://daringfireball.net/" } ], - "description": "PHP Markdown & Extra", - "homepage": "http://github.com/dflydev/dflydev-markdown", + "description": "PHP Markdown", + "homepage": "http://michelf.ca/projects/php-markdown/", "keywords": [ "markdown" ], - "time": "2012-01-15 19:36:37" + "time": "2013-11-29 21:49:31" }, { "name": "suin/php-rss-writer", @@ -108,9 +109,9 @@ ], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": { + "michelf/php-markdown": 20 + }, "platform": [ ], diff --git a/composer.phar b/composer.phar index 6b6e2a07ceb53d7b7f0dc2fb234da7c7ded40843..c5eb36ca689f3a9795389fa6be2ffa190c1de525 100644 GIT binary patch delta 236233 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¬nkA z^4NPL1<$+a%u0NwD)#1se1xPlZ^*(Je2!Ccn?~u7c<$!t7Rpb*<{DCc5UdMu(vY7p z3=ZU!T}7g=I`--P`B!50fQA4NAL;?NwrK2L@!Jd02B-59R2WRiYI$WsPKOXs$~IM_D&ACH-56yX1Uot;_^MlNdu&D9Liy%ebP84}MgoaWIpVY_ zgVY7v${Sg0c9Lr1-r0vSxgsqw@?^yuu!w}1nmc$<$+fusM^3#EAE~NeZ8xMxOm=%r zr-`ARpR#|ZOg#6i<+VsH&dIL9?IXw-GzE2{)e(p%<%&M4*>yo*wMTO76iShme=ePZ z{f$R=B^0PFPCvm=%qKn1(VnsoW$q?vpjWy`_moift8S=iAEiA^puk9bP@7F6g ziyIot>)3{knF@!*pN@k3#3RV8sUwxl$#sucjZGtoNbZNA!1{6EMTtm}DcDrh2;&Oa zvGl|w(zuAW#&RUjMck$6y^9PW%=?_2qhI?$`NlQAcH-u<(e4^sHKb*NG?}xB-lRC9 z8kkH3CTAk%ikI@4eB1t{w(ttwJ25?<6(5?4)@+bqF>pG8Ca#k8R@95bcT`m$qa-7V zVWh-{3*!Phgu5MZXk3c##NJC0#FMh0R$VwGcE;6L4ox$4N8=Xj%#0G<G4 zgO~1Rdn@WX6-O`ym`0N{Nb>U_^Kwk@R%MPCFfxRJ-=CSs*mDo!c#4H1LEb{SXWfpq?yHQ>SCW;w*ezKFm-gGPiMnI8vgI^ zj(w(4RDQ5*gG&VYiis~U#HTN#Q^*hAeQfmpqet=o$95`XP}^!MnKX7X*S1Inj7F^F zq>6;5&1Smk(64zX(8tF!GL&yGUR$DsNtEvBfj3Rh&*G*5(o)AMpAtWXIWff-TjJ^X z$*BoSZxTQH0K5|e^d@&Jy?=sy&Af1kf%hR01TWC665H!zS1o?)XsqSv_Kx%WZ@504 z8NVTO)BYQ;JI{0bk2pe5FSSB(XghmyL$@NgBdZ#a5RDzaY1oCyy#@H?) z6+|rY4!c*tQH_#Er2w)a+!BS4bewn^XvUN9eBHBQ6hK8N)I(i#Jc%j01Sj?Q z+mhk~QV1Enz%$oN?^|I{Sq!#Zv2@!o;*WHvObTOey+Hq8c?vK zZYbJeIK%O#Q_)iF$&*iBgf0$4)D9rUA)^K6L^^w0CjT;H^nFm>)A(Dxlgo?*Rvhv<973GOF-Vd94R#kH zdun9blNwY}h&ypybv`|I_cHNnv{-*Mq~g#{rn6b_#}K;$_=6xzA_ReixCOUta-{ud zOF*Y0CjhuOqIk1h${vmEpHS&1orKG#b4AT+XfQn4zMP@p_1}mfgDI+~#!^@gQftOR z{tT$n5R+g33Xuc1tFIUlxY7vd!;PdXSg0h^UASTl0~Exf$RIaIH|PGnA|~Jh4g}D^ zDhf5OAYeN?J8~&Kbw#)dwQB(@3VBa9IrRX%gi{x<7&n1(C9EP*cVC{FTgD<2SYvv! z42N;L@K}XefO<-%Q2Czu^yCV3mf-|D>a+hWq{q^er8$2>l~_-f;RKPIx+&~`Eu=l; zIA5E9?YRQIHLwaG2X3T~B(n%??g1fm@I7#0C9oS{h0)Ks8a?@8R{$}ASpucT*pFj} zgj<}M7BpMTsI~WG2~LqHM{qmH-$_^cri*btXh8u=f>SKY!Unx-oNsCthOfpzxr9xx zsY}ra^vMUL{ap?1>D{632Mw&<0#;Oit@?pk7;Pq&zpnv@myvV>s;E8=!z(!p*B(|;yG!z+P=;&q%)#pQ0eBoh?45(vNs zZFa6?E_en{?m&1Diy~uWHhphqHcP=Y#ft>wzu?RZ0lHjb2Bs!+ja9e6d6TirY}SMj zM1YGT>U8e0M#&DRb^ytbtmKm#Yy7$G5};Fvx}MG84Z%#Y9<6|>#7NpbDDF}SvEtz2 zoYE&YZ89V>2_X+27yeGJmbxQ7JGJa>l*FV!#rY3vB-EN414Xa zhW6CA{`xU8r2J^TBbwAviblt)SaOq9)RwsQGER$Hr_Z~T_&*z>13mEV3Vgc;Um8tQ z_fBKJLL3NU&bhS9u`pWV)W4dzQfLdHDV9c;8CR^)v<$)+bbe}FkI!Zp`}hf4ipl$F z(j}3&8cTi>LntKLvNN~`UWA|*<{2EG9(*Hd27XCY4dO%(A-J#siszdvr$Gsl7Qj*x zg~N06=lv`T-*6Y^St!d0bWyY%r|1w9;jqO1uLMF2+@h%HQS%iJCqF|%x8)^}p#c~2 zyLb|pa=rTWHAg>Pp?V5J&*2RmPAZ_rBFbx(lAF$-7K_>kTn-q>A!`Y$eK0*+H=I!%5EMd~H@km2bZPkRY&M)Q?C-;7DXmAnEw`K8bi^PxhdHtT-quo&Y;w3=mF0|5xIZ8VNY2C#qV78rDrT= zt(0<*R51b<81j(jr|cBsyDv=eMdfAfv+`^x+;$IeemVx`=WwmCM9-=|VI)Vq1;CHR zowGC#2|-sTJBA3-Wjo^iF#O1TxbB`ne#3EhDgU(gjOO~{hb068up}C)6w1CLkAEy& zOL(QNntTr{6szZehyE+7haRi~eSKhR?otM)HA~>MQM!D&&)R(t`+(#}w)}DP4Vc>g zTS7?1rQY;2`^I+Nx-j8%t4hYXyG!0k%N0Drp&%4SQ^Zv?FZ?4Mj|Nc~5pGk=PliR8 z7~#q%WN<%IcO-zqNJ_r!=^vHQTZzXSjiZgo;5w-;B#l*uM_6qi()qx`do#mgK$NdWDB0BtiZ@*1(W!xS29e(-GUEZ^Z|uJul*c|&uj z9%=ormMaB5tYHYV6dJ=>4c;6V<^gXv$PX549^E8f26tT5G$^Vg$X9i;hi=YLZr4%( z%a+(MaLYV!<@^|&oj`naQC?0nstUXTK<)D&DMoBU)(eHfYaIlCa&BTW#n%W*;S05D z=T7McVr+q&dq3k43RTY7S0TyIcMWG0cUw`4S-P%M0WNlt13WHw0M zIy}%{G7dCsr-l|-id3?o($8?Pu1Ubb!K-?OV-_)7YMK}DNOCY7>=IDXPQmmp$+D0D zf5`yRCX_&YM~K&jbU|}2WD(%LqcI}8xN%{m8_5NF zt92Q|hD9}OO=Ord6f=jpg<=Mo5wcw<4``Xp0azdgk>ODz3z{YWRMItle~JP&24^#K zb8r$Yg9!>uyB~~&(wiHo>M}~7NwKUhf$(-8lza#S_*{&0>cmJN9(7&v^vEwox}QF* z?F6bw)P#8i?>a1R40Af%PR3JS)NEMmd_GoR^E&NvJL>}xj;Qd35VM2B1SBD7hd{cM z?P1qHc*>k!#;Bl;MH-CgaRdOU-LuX#SOsjgXg|Cd^s z@&R`>ItgV7B&pNmne+2YUC+yh%a5v^VYwIcqBIVEOI*U-mP?^CaKbPlX69lh1#4(& zeY+GM2_y^&<3O4pynuww1F^w$DbJzNQn(~A>?sJ?QYdp%!+2~gUjCror~@H6t$b1r zCph=B2%ScqbPGtl#u(6PdC>ti9+R83xEmfaYcm(Q?Q>?DjTe7Qm`gF4h%^Mi?~=WA zei}{%GthZRaSKoSP*UKUQP4{y3h&TxJ~E4_Q2lE&s965ABNv^7UJ_9*&Ap|fJC;Qc z!Ci`!{%Lo~o90C#@AqFa4;50XlQMkbQ7EtpF9C7!%x4lTmb(ydFOQ)1MB(33uouT_ z^gY)AKum^CVz^A?8s<`CjrG)$dyUm|8W-PZKw1hJ*+L=Mj0IwlVgBb?@AcFVm{oqk zB0HrhJo(VL8M1=xOTM`XD2%P-t?*LvLs$_Q>4reg%iL2%`8t=vte{9NE=SCzM)07D zwc0JCGGvqG`cgE84p9h4Q^}#B`HZ>!1HLGBi%zb)Z&5KclJ^vG(l5G2L^h(ll`d` z6hIAfAcxAJ|FdWbB#pNT+C5npscqyd9=5CsZnu@9qZ2IQ1^;S zBBq+6Yz6dRXL6+T#8Umt*G=rdl>1MO!WGJM$Vl`ihx2O#m87$1vFjvgsm|qgH>bBQ z!|PA>b*DN9`iDo7{VO-fy#xI#D1W^J!`-Q)&^5QMpd9wP1hw0iOo?jPytKN%vA%e23E#-s)Y zyO%mGTZ*9wno^3lt9!+?8bI|HHT&+)xW&xAuI^*Wlf5f3+&tQNT-HcVKL2CB^(v^q zyLwI;SoyY1A=@6KWBB|}k3i3s=a^iec=7AbZ%W7;1|=|)1bSukf7ifC z*qXGD8n~mhA;SF6&j1FxlG`#xXQx{H5HPs{_NM}R`^kZk(nkkL`e}OR4u5y&i4~Lf z?p|$f=Xe`T&a9&4hJf`PD{YkX53<|cH#o9lwwGBxv3E?}aiRwUGMMZPS@w+Af&Gug z_r1TXgteuZrN!;;?>d&dEe(XvltLh&btjA75H0P00D&tv+yFLwM~}5%bMv{si(LQ# z5d*#SMmG;UEB-?*4FH%r(LL1NHLzm#NFLu8385GNQ~Vg83Uj0xi6$R+@vz*}FqQg} zBRvECslMdUiuoV9PxlmMFBN5fb)Oy~!C5JtLvKrISXV56$9np&WH|JlaV2~VZRPf& zOKTRlXi+ImuPo`-Ja)3b6H@11=?21>bOf+;$4K7w_jvEX(JL8PzgOw_z)1LNZlC|> zQBj!B0boVVtYTK56G^vsgbd+9Oo>uW*Sv;XDa!?N78P=S_w)_+c9Sz;#U_7GzfY}S zk^dX8dQWy4U9y~|OrL-8#!$ga!C`SlK-HO=g4x^C-<>za&5nOAS{3xLqp-7k;L6QF zS1CRM*`4fK0f+`5&LoZ%HvV}1Euq(#Dl2$K)H6KXJ+f5Jl;WuyUe?|{|NgUQICUJB zB)FIw7+MzW{0d??)zgJZ-O~yEqgUeP%pRYh52yME^11o)Ixv>fKN6^>b|r}&?!ysH zxBFAzu6(F7TNGp6BAm~pK#BrZ6fD2n^osOv@6!IIrHo;p{_Pz&4w39#$&*J7GT#<& z8TP*hc{(3V6Z~I<@^IPxkXkwCW?%Qni2)o77b!4H??3zCxL&chTS}4!n1Vy?L~5D-Vw!&;-CtpYZ!ifT)15ti zss8TUPIe89(BE=_SONVD5$#;|adAle(O}QuikUluy-TcJ*#8$j-~_CYE-$>&gpKpy zklV9z2VjFkJ*Ti=D01bO9wLf=%69}ZID``wgqE#X9O57jlzRM@iK||4hn>h5Fqg6y z?H$MMC%cEQ)Nz{Ye;$G@(Nj$5NO5XMfy?Jp@W)>lyW$`e?Bvjjc0YVK0um%|0kr_zOH*zab$68Rfm0WIy@{~-KpXk?`iKL8XP{d`J+k}wo) zEJEUK+bREZM@6gDVVC1 zdH9HwcGNo8Zjj$oo#`=pMX=DlH?3~-uYU>&-cYrH<>DMUQF73MwdA+~-}*>T@0B@p z?F9m1`AeOGxy3L446W#m^^ylLBSUoTzB2J2C;Q>bTtd>rWhpHFkD;yTlsvhD@ei2S z%j#)}nGH~GPcc#2#jeYxpM)2(zlsW=C`oz4Wfd@BuQdMc&YtexE3pr6N6K!x;guT6 z;E@^RB3W{5QMnZvU$`>gxyS#=Us5-Tp~qrZZ|^w2|Ay<+neiJkH|@Xi+5;Ww>ko|G zklDBIhMPLB-*^2Di@)+%>|ohawZwD37^_>oH$I0q8Rh>9=NDrS6w~a@qIPrj4Ptn6 zb-Q@S=IR^88=I>Si1v5H_HD^#=9-(P^s66x<4rT^xl1jFVh_b)RI4d6lbyXzG`}Nu zV>PM{(vPus#6BjDAzjY;@rhY#+MG(!DS9f^B6d6$+h1@OZ!-)BnfX_3GV^>{ISbZq zQiyg`xTG0T-@%0XJJ)@qDy=d4qbiJ>M-(>Jos7o8KPW=sb|VJc%DIhr~T) zWxK^yE!FG9t?!Io(-@1-Acp{i4`VT#xiE2mZ)WP^+@&n@{;5wpb!+8kTnI7W>cxBC z8C%s%RpK|t)AUe#GX^o111m#KIt0MTChO^^uZh_6?&=-l|9WSvTQofHtQ8O6TUlSz zgol8$t%oII31i`&iw)wDcUMOvOxV+>BXz5ZT0_=zAB@zAo8J{{t3U-&_Wnpc{kn>) zFRVXPBU0~*t(J|s>Lc%py&_h3m9H27`!m%E@k@`#4p3=_`0V4cYx%EdpNPffr}z`G zUGlH#Cu8;E&L?84>S9e7z>zt0M)B=T$Js+-{aedxYHhmD$ZBWB!%xJvt|kQL%U6H7 zx>0=Z$=E9K$tPml{bjE_5xdd(D&)~^m@xq3R+S4|}&!}#n zZE1gU^ui_8BfQJ{)lHYGkB|K4ll{=WF_Jg97~Wju^6MX z`tP$ebdu;pF*MxZiJTEC8lu*Rm;=-a>e37dQ9ZV$)HK1UTz^3SGPp4DViJyIR=%d* zfL28{5W$1#{!Vng__Zfv2c;msB&utg4MbnR<%H3wsmp@;QTC9y=bhEt>PZ^(;3x&0 zZHbFNfP4|?>jZ)B_CWvtbzH@V);gQTJAS2l*W&0?u~*AzUUa=XcB8m&EVf2G_U_o> zT_n}h7wP5dK`c|m94X#&v&~Iolj&@BZ(OWhh&9Ap=y@Mrf}sUH#lUq~FTC=@NKHdf zy=qO+B4(Z~ukQ#bUtJncXSIsqG(mDaAc6}|KUO1dE~}1;+ujqa6AwRI9<2+Vp`z@W z*w!jqIpQ~qTYjs0TRb~|9<#JL*gJ@Wgf2e6F}k_pq1Z#uq+_+>)4y4*G-m+N_NxNy z5ntFC-6;O)o0S{HkyghMUwwD1VccJb)PG*|9VC#`+4wc_eJ!yz(j=fVZ*5Z*!|;WL z*rxWtBnv^z0L|D@qnI~#V){j=zAj9A%MlW(->9zg>)D3)#4cH!4Kk#I7}Ai#$d2HM zgtpsQ0ktX~ekOJ_z-ES8$E8ob3+qwGbC7|bJcERSq@?Jg!Ekc0hqY~DY;qz&>MD-^ zGGmvf;|Y~_^GDAY&?5udVX>|em)bQkT3qk@101;kpns2+1nFGiULY98lS!p z2k5;}(sNvvXw#V55^+M9Xp7O8?txzDy2W+R#@0t0U;Ado_s9Or;1AyU=0Ci4uHJGSrGCbhjHok3Hy%)TP;Hch)B_I$bn7;lKrQ=Hih4IS#M&<> zCA+%HU0vbomy=vmRx`res6^mTpW64SX>`02$QmyRe5c!$C)AsvA!-Bds}wLs0fB$- zzwc%B3~g6ho3#lHsg8S5{gg>m8qAjjKKBRoQ`e@1sA~mL?aT%%QLT(_2#o(*wX8bX z_AEhF{Ttg!X`g765;*9_qIA_qj8+-WNBPv#C?N3Xn4iDU3wmL}TANWo;M$ETCFm%Q)CuO5+l@Cw^!6?+>3rbN__Ys1xvc@Dkf$x>> zjZ?FPPRa?BW(0nA*-2hTtJj1ugEW$ut~_M+Nnp29EmN%y(+7;|S5;ou0#@Ga^ zu2qLsg$YsD$R4UD`Y0*p*aXfmt?i6h$Hw$7uWpXY@hf%v)8R zoBDWM@=;cqL?zJj%+Z_bbx&h}_oZOv@i4O`!kNNHQQf!ed4S<2gHKLk26*Uv|SbWz%IMtcHhzw?Wqnq|f13iMF3yhYXJ z6{O^uTa>`Mf%HcP0|k0V4sq2~yUXjUYp0T>5CV*T2rSy$YoD>1u%8NFd6~C|@{>7z z0{czf;fai6jI+qwUrDeUjR`y{9~q@a1;wh1yan}wx1W+}(uTkjhZpTyrnFb4n+s21 zcwS}YGR3ZHil_2gpwSV5CE8hEy`u#_o)P`3>Rh#@&SDqAHJdhS5%^2*gLjPWhPa;a z;ne{?vLcz?6Ihk{=rYp%A|Fqs#v~SjrSrnat7|-rNu2NrQC>3fB=APUneJ*OP9oel zTse=+LAD@)GZ)34X(DljZEn(GPb>e7lC6x zeeQjAZwTpFQ40fQ^_IUyuemHBSLf+yq-f^*-}g4xEl7Pbz^I_E3h1F!nyX9T%`XSp z%vy>X6zFFRm>f9Jc$gJ9z<4+j*wc6j3hI3i8}`h4VlEP|o3hUoa0C{ld0#XU)Okw% zXONGM*oVlM-z`~l#AG;&IypGlkeR3euCwVA^wm|OM0IztAxzKU>UHWfq4s%DX832`>;>RFM6%&Orn@>_B}lG(h<@)TlttfiHpGEXU$dd6Gg&{VK{^`PSDcB=FpCy`LgFUvD|q%Ibp;Hg}oY(b`FU+v=y} z<4O{u5t!#OqZpaIv4yu95FMcWVzwaAQF-FHnjYQX;H`PlBaMg8qgyMxJdAz_oDu$R zs(KZs;;b+n_`i`q08cY)x)iPlw0OR2rP*G{x$V#t3FDMsZt4Cp4$$0 zSZtP#jSo^!{o~@}>Ra(0)P1p`#^4uYhZ_$a^ zQy39g{6P1MO-nGq;cbjt=*Ut^y$qBI%%3q{Y3lx*!|47q9Cv>050mue7}Hu%!&^rf z%`;nfQFv1x68O)f=e}1zN{CgSjW+ru@Y!>3kJCB%WFn{961_rhnwyxw;Hw7*HmcWf zl}ZW@>RVq#aR1yC9t3{$;GIJ{yPr%9RwkNDOW^zkhc}^x7NU}_A58LBc7>SSh|t<~ z{cpNrC4~!GvY9V0oN!#WddtobgriXno*WDU#YJ#amfv zsv-hMU;Vv8osk%#&Pwr7Zkh^{zytknUqbR{8c2MWlA!ccjF}Sn!)pf;aK}58dQ*Vt zFred3-A){w7NqPl3kY0X;JZaHSc(PJrW_*BQ}dsy7o189(S#lu z<8TkR4N@{p(Mh29<{_sIwT6Y3cA@%24A`kEO1RlGfu0NQc0(Nw3t@nBo@x0LclWT})jQVN2041xVF*^ds^uJ=of{w~r zvu^^!+QmPMC$Ugkw$v7~R2?BEpiuq-&37sAXBXil?dT3GB72_gK9)*DXj<%-ImQ;K5-P$udYG_?;dDXanRW zMA$4dHw1xC6gNDDb%umQnS&BItL~Piae;cO-Fv4;bgvyZsi}RSx!VX_^w96~%!$UR zTY7~Xn4IYKkaEftn*^RK+;TvjJ(`dsM!nQKL^&O2OoG6O{fEw|VxQj1W>cdOShe>` zg*v9sAZ3b4Y69P(L!L)uGu5Pi!m_?z%6gM42wZmfxkYMZ-!V!6N*}V41bQtz!0U^K z4b+o;m5{CGQV^J2DnvBS@tZ{Ngw``nV_sg4=w6F^Y9iFjtZ!kTDnjJhR9P!|mHQ#i990==gv`>U@E8myc) z%@hJxj_F*ddgTmL^31(UppWkS3==_DGS9@7z^;EQ7}ZFruIk#6ZK8(O zR1gnKzpBz|vSEKQ`zLTmQS2^ttJ6HM{p{?gypd=yJb@#2=X*3%N|$2P*yJiQ9(+sl^{S6y)mVGwTYBGy3?j2x+1U4orKXLXG%i8kA4_q6 zL8oVt0v&!jei$EL+6scXs-hTb+cD1p1ybnVyJrv-Z`Dz8c@uC7F{imUc>voV2( z_kN=_)h_i)z?;8%d3hj>PuYK*iu~6 z40#6rCzqF6?dpYc$Myr|60O!Y#Hv>(WT-0|!XW7h%42)03NMICusO_ITNJ*G1Esq+fdLs)>&Uy=C)>9W9!Pw-AP@?x$3&( z8&_3bd9kyu9KE=9M}{mn;^cO_>g;+Ob=2(KS^w9q-FdOKP2Q(L&PrE-!)? zz^ZVM0Q?c56JpM^b<~Ox#_TB>)_yGp!if`%FVt-CVAZ5qk?M0(Z4fz@71WAZVYED5 zRUTOkZ6;B6x?hf3{P1iwamGTnQ>r5awk@|rZNE5!rD6NG9=@<|9qq3^_^_l#O$dc< zzsdpXg*nGTNaP~6ADJ7;z}m;fjY@JW_0Of!sM9uyn4c3;@KCsnB`@#u3>#LslpsmWDz6;Zz z#HIK8a113ST5V`Y7FD>^=qCcUH+=LKrFx(BXjNXNTbI@nSB}ob9O~*i}JwBrViIXGEpA-d$H+iEL<^rqIxq3WdZ@1m7?j|T(>#7^avZ5(`FS50+iS^~Ru9Ew(uCo?RwK{9atk6=iBHPMc z%2E1twIwCt+-zM^^k3G}3g@_FSstd3px(Lgg*t7&7hE3A32Oakq3Uz{+o|t=Hb@85yW3*u>Ta*3KmmbdYPbLPb1Bnbw$@kaa-gI#(HdJ${uEbNm6ngg2a^SwCXcV&)%CT-F5+w^ z<<8;>&T%dxQ)Fu_bXLW1w!GSrp}zT#H1(hVSUKxH;<NFSyIOKVYWg3DDiqS$SXkH=YP`xn8YXD_mtQAS@K~&*!1$La zKd8RT3)@%TIbm$(rxxO?ltVoKR0B01mi)oSfcGKZ6H-sJtzcejk5Kj2?ksaB&!aYv} zDEGBKAygR)o8M<;u)f0zko-Oy3}I(!PZ*LYIpB*3Y6e$H&f4ni!=dWQ+mWzGrY*2H zk~##V+Dm?LHj3Iu%U1A-VFTcJH;ZgkIM5r*I`8Ac;d}-!%dwLTE_3Ip-S33MhA1jr zTVbW@cnhw3U70m2-D*p=L3bM!rg_?_7bsR&X#4j^LXSi$08$btFYm@pi(G88CR?$m zc$O@hw#`BPjcKHV0` zV0u?7QbYxoib$uaK8riSmT%>IS>Qp)UB`&p)-37^i7zgztS+&GPd~~}+uV=xq`Xn@ zx~eAGZM}N-8{PgFnc#4bn}CrGzj_1dK_hchzH#YTV7+s;L>ZXq#a*C<#F1VOQ_ux?7K#XLFaQkYWUrjT*7zo zy-LM`cLOD>-TttHx}2J%p4l4+udkqfRp)N#qApyPJ2+5YZ&6tgdqr8=e?B)=c%64bj#{gA$EkXDup&*ox|6r*7yQmEht^ z0Thrb!&MfHxz z*Vfk8)VWGv-D)-nX0M}MaK0Pk0Z%+f`E-skwDm*P^=RO^to3eFi(5^SHR5YEJLi89Ue>h z67kcdE|R*UvVgQWv~tt~)Iv}m=M%L)2PuYb9OXfHsX_E75G z;AwxU1x_gR1y~y;NZKwRdJU%)2hmS68XrcFpy0+0Pk(S^qjp&tPG>;dH|bc7ilEz5 zlC#KNSL-aUvqIWf>`iK*Jvm)(fKOkG9de@>4jM)XaVuuiB0LsJPk@@mi~=Xyh@J$U zQRM*0dd-YfYzsZ50;@FP>sT;LXwaBqq>TVC!Hy zP)kU}DZs2`x-8AuQ3h)nhpJ*Hda=n0M4P89{e`hHhgI9bnnH&Mp>ae`dgL&q8!Tp3 z=+chv!|A=jsSb1ie4aulz??LkVRQ=0qc_s%O7M*rtd@3()^@3Fu`Sv&+PF4!3dI}4 z!-}@_i{`V2-9=GSEFx4q!ChYo&T5?H%Wh85^4imO3SLOzg0xpU&_B>HGmKsW69#gD zFk>FwQJbAkhjB2jE7E5|H+m|hHPDe-M0YxvhTLqr3td+RcP&Byq`pE&!qIGchBl-p z{U|FHmssO;BMUz2OIxAcbX>GcPtzQH-GR2^b@I_(1BnEDK%6)6-$^csf+DCCAoHt#N_!jNlKM6XYW=o%PaOUJ<03gnfSyU?;Wvx0upi`T86OxX9T5DbsLgjyzNIz1qcEEFM5 zn^>JZW#g=PVv2JU64cjL=*BYAG+`E<4I3shiIDUG-3xBbq66Xba=I_PG=na^zvn=R znMo(Z)akT;3%YyFqC;7N1H{du``z1FJXyzn;60s@yqZ=DQE}Hn+H~B8WTj*WB2%rq zF5#I5dQOY3qh{lDo0l|eHp&LFq<~B6r@lNd9&#R`(_#3d^utmO3i+zK^z;(g??;D1 z+eEsJZUDl}9z^kW5^-0}p+kn~YN)!_Sv$37c`dSmd#bw-8KRIVpTd&zTDv3JmQq|< zV@r0|6PaPJENO4AE3b56L1kTGEhbK(&7WvZO|-U0-G%!R)*eNw=^K@qOFu+g>dI=X zCtG86zY46|PW!>wdGv}E^XU+X{Yv!Ly3D8JSjawvOm}ku&1Iygq&REJ^OMJw*Ok>5 z$ieOh_V!^ppmA~ZXVG6-Klhoq1dB^*ucD(tMPx&%+& z&Jwdjy+7nHLqMk$BtzGexVNJp^9Y9P3uqw~o3tGI|I481|8`K4rB*)4WzOG`pWHZg zB+@j9SU?B&{~zaUOKGA&+X7tSreAFeAo?Go4YCT+BwR9-{K=rZ!hwbKF5g7!xQgl` zdn~dA9u{mVt!?naB6=Hat;fSn)_f)ayfPSn*tdk{Vae-kM3c^7;Q-LfVCG7?jLLxh z)5Qo_Yo!HQT5Oj$U!tq^y%yNC*Kl2}hT&&Tn$*1K zJe&6%@-QsfkD}lCcY4kJV|O=X>4N9cEmZwHa`~#~=~Q@f10Beac8Jqx1D&x?(TXm! zp~pr#3XqqqSCjjzO#~BJ7z%i0>t3ve%eV1W=kkOK-YOy)#Cv%8XYi( zt+D1PuH;rfFmEo=hRX9F_?c0JNmjnh==-3 z*rHKz`UCX}DkZH@4A5@BPXk3I!;<6lV!0VF=zfCk6H@Ok8*T_9Ea}! zqPvw2(vE#X7wCf32O2)5C20F8^6iqY5+@nL&*jd8F&7Y(tWRlPd-4K(jS7*i#QeeK z(OpM|kGi7V>9)hTpP1BGWb>BBR+-bCYt%$XHL0c(_|$OLUow6Y&QjJ>A;hD@L*`{V znOGBq4T#D`KT+M(?xdah5~f~8j$1sJ6f-UCmQ zbvPg8GddSf6XbNM3}(aO!hE!s=6{aDENKtp4QF_!HH>HS4Rj{hIcq z!1|qNc`B8U*VbO6(yKA6$){W!M^YjEA5%N3nf;CLS>q zA12Q1@U!L2P-F1Gg-k2>(uXNCjGTm<9$AD1TvrVL^%P|%slgZ`1sOCHS& zl@30sOstk1#mwg6omWsttVv{e_@Nb&IW3-v37K4uLcGj5Ne?4TcA`pkS|^v`aSF=f znOJxu9+xd5SoDLh?MP}eQ-WhFZLovMVBtg+>#c1~VsL$fiHEG-OzNL6=f5t! zV>we`)?Kok>C?PuTeLxK8Q=&N`fFL8nI#l4KtiEi2IGJiWv08f6`v>=K80xmPxj_y zt!pN8ifL5x5c38dqS?DMLueQ{gLw$1^Z#o`0nqqbOF-g1eAmdMKzJnNs2JZ|!PM}XFyvZ7iAxCyCCy%M3@L0!e zr#M}bL)IHyfEH88cuJko3`D!mJPQ+Ka)~23SvKDr26LMNV*7Q|Yc`tDFujbK3nxpN z?%-3wbb#DBj3-3yMyXUaj#&b4j%RvsdMEJKcqY)&t;yO-R}WK7R{NESkPC|uhziRsNS)}(syp2LJ`$~4A@ zf<dOi()#pX`}toz&JUARBP?& z$C$+|R6A$^RzA-}Lu;4d312+HEF#{XA@J*RWSg$_h}-QanNkW)SL1A^FJeZ(Tsxbl z&!22HG9#O|U@?R4vch&uf5_^PgN+ufV`NyAjLyZAS7_9Rdzh|T*k0y5!?>o@ z!Tx;vmip5=6l z4zeyG)4%frV-HNWCF!q-cN5bIh#7~@YZ!YArT)zy&;xksHuDNlbJ+m@e>Eo^4%qY~ z6X&frYYMNFz-13U7;=APLhmop`u)VrRN$7tCTmuay+(oWKky`y=D|+T)_AaUDb41| z4vK&al}P+sUkaS|L~Hg~5Da{l_R}hQu%VRk__u6!9S=92B|fKaG7GQt#u#1hKvvKS z`?FJc(;oYrcEH%raqG=mi^8SiA$Gh3cU@uti9WL0hehl=j7E)Pfh0B{*<)*2w+w&G zVLN9v+J8x1F>KpiH=PaIG*7aHm8jRsZMK8$u=aJ_5}A*&0osa(S=5&!t}_1GklE}e zMjQSZJ26xu!Cd`+kh_Qt)8;+TMk#u{3ozd0Ng^rxUwZp>mVwzvSbtbq$9fC40ut1d z;q)79g7%M{Y%7d}#v!){zR8}`Pp-2&VM0vOZZ;W1*kgCIQ3&SjW|I)?*v)o=aXZ-% zIP)lL0cJPr1M7COy`lFWb_G?VeYS@!!ku}U< z=MPPIINx4XZ7o7iQ*l|o15Uon_Jg4J*a)ro2-}Xbw5$$Y1~Q$r$My$ZqJX|A7Ilgi=vdfv(aL!z`$T{66&jijTcxO z%>9IQMCoc0yefYEq8D7N1sSs~ykp4+EUf($ul+3;D!#H^U)DlwA?aBD@I zgOmJ(-KrU7-=U>nkpNK0On>So0eda)U~v{s&P*CB(sfK$yR{o z#(gLu`yvY(Uh>o}oWFYhfDA`1l3z*7j{d8DkSWcc8n+Gc)Bf8D!!`i}_hh*C|6#cM zCT|{HG0xBV2e;gvEvW|?^=wE=%MEGH!yvnH@@zqUvae>q4KE6F16~)rVb3lPah7b$ z#x$I&>N+dI&>9oxPKtBKSR3hHUWGoWapi7|1!0zr?%5<412Iv^h7o52o0jCiZyqv< zUn1d}D3*zNKh;&3yk<5EGSBGuunoFw;l!hCK-Lf!#<<#n}ZQ|E^-p-RbSP6 z8X5G<9 z-DPk&N{X->6aCW;^^Cm6USQT4bl47ij8$OES(b-B1EfG`*ut?|^*J_x*Rnoi&v075 zuh^RubpIL;+DX-P60HB4T?y;+gg_WH505_S*VtGOf@i88n~Q~SyQ8k&e2x7WmP};= zv^D=^-{n~%z`-XD!%sPdT+5#We?w_F>}B*BKk*$~3={5h@mja<+1GH#|H_85+W0@% zz8viR!XiM;F-+mOQH==+?=u`_p^70_;o{&&Z!W-7CwOsneHCW<6~l6c%YfChakN_s zr$VL=8YoMAxW8!!e7OY_Z21}kY+v~>KJ=KGkRHNCz=I*21vdM0na~h|0_a!(7wK76 zKCY}uctB1R=SVQajp*-bTVPGFra6cSpPZ`aZRtVo$@es9=SPa0EqrX(t^m3Oq6=Yh z$e)c6kkmW^o)4Nw_%~zp&`}@>S5_D1-;iXidoV{QlzzOx!PD;TvZ+(pAHt}5iuPn zDvX;186n(AU%lQvvmo^E+@`bf50N4RG|dYaLr+FaHFD8fqDk5XbZxGRR84AJH?z0o z=3bjgcz+*`h~_?UIMN51bYoMvNn?&tP9W#;7r4jG`q$C!nFAvBS954FQ(VEnLca-@ zmYmQ$4H{j}gch@!=kXtC@s|wMM0dod1rZt%XoUB#64u5UvQ}HF4bFygnSGl0wHZs) zrOo*Lmy-qmFs`+h6~1DuV^ z(8k!fCn#9x;O4>z2^}XWa)Jz#mDr(x9$$+VKa_i#f(LErqQ6V?9xPE^;B4UhIU>#6 zkUx%#&`u2FFaV9+@sKyt;tQ$sJ^ZzPBe+l&5?XU^n0%fNRPM1~F{=_*+0dT);X(9L z#oE#8Id=ig91`)(Xko#&bkCAZOw*sx(rJs9NApiu=fo*q{*Gl0X-gg91E8jm}am52h{)0CSe>H#lG$|ZAt{x_LXv-MX28A;RjyT+)DWMK|K8go zrb}->efoBSlbN81rCU!E=bx9Sr0uKbhOlt55FLq$t+^1mJ(&xFZ@-cK;q7{ST6A5G z0`G~O0I9j0Cwx_n^ayx0bu?h!`TI3l5 zJD=v-VlK7-$Cq>C1#`|TzQ*h|EV00Wr!ZAx>yw-U`(%NIJ5O;tzz4Xjrgt2a0k;uq zS8_STrH)}Em3vh0U)%UJ_b?5eN<6(`$s*2I8@GxZj*ow^@xX0DR6kyf>gd+9Ts9`| z<|In-@Zl@iR8QeWFEk7N)^Pp7`y#s6S5xTO{9-eQ$JUd3I1Zk84arrtl{*Z5wsCW{ zi`%$46nT79lV0P#Mwi|eM3~#bRccS{;DFL*@8tdw#@5zXxHQ*C+({Y+dtqRigd4Px zXSjTfFOfvhecy}n>%a4}(P#Ptp5k7i`8#ls;fu6BERPwU$L*X50|rPw@agNk7jc4z zXcnH|Ov81FPk{yDm~Glx=3BwbUc5gfD|n1}Q{?@ra2Zp(U6^rVHQYXh6I@f>_E?fE zhED#mo_rdM(j#8GEc4T7U&EdE7gg4J@+s86tpZpj4${5(EJ*nj58L9Y)lQ9xo*Ng(N+bjHU9bIugRe zOzKee_uBzVY%xX(Nwy{`^jM@UObh0d15lHj+}@&GD+uB(Gz5)7hsc@`{x=$Sg(E$0 z?Z*v&Ih?OBo(4wny^W`df5#n;M>;=kcLcu_vw)-cNI{S1ph`L&#n(fQm9K@MXx<6a zVvskIHX{uxkMdSH8pHcQZYw@gThxkArD5-E%v z8T}Qd>FEQz56kXbIHXtZfbQA7P(MPBgO7qaHXH)Gi~y^h4<(^pbGAmG^+rC3apTxE>HKy$^DMgX zP@H>fBQyEWGPL1Sc`e*x?A=Muih7qD_B_RR)}$4DmH>%wqqb^j!zXJ`uI68){tWZ4 zykaZLix6cqg9c9;d;r@HcNpAUkL%fK9X}ML=lFpT+8KAuwCDH(0(fU)zl(i6_^|q_ z@`?2>Q@&I>YwV@FZ%0SqZhjE#x`8e;%-`T4;VkCM6M?BNIhja=rnT7_u7?3J zILbc=OT0t@2EQS6^O5D^3a8s`?TxvF_-z|B5uBoDG^C#Am%->y`JRw^fj=IJ2}OFs zb@$xdp52FaM{^hLFZ^tk5hK%ti##T~<$R8wzw*!d-a(DkvvUUK<_zsM1nZM*cJ27* z{B9Ns1zglsSNXPZ^(z0HCSBu$=@TzZ@pK zj(G%n?0WNeSSWtaCqmT^NYbM3`B%|?y3HrRncMso_>D)0qWm-89?E{^x5C6bxVz8) z!k>n_zv4j8|HkK#KM@dfhi_**%_UDq@9^Pp#EKpuU1KSC`Dqkn;_V08Rr~r9p`L=i zGld{H-dYe~RA0$QJ#j-2kd=sFgnU})PdQ*+gwS5QP74^^$QRHA(!IsqIH3<5y@{6H zZ?xdgg5R8Am?US=vFrgC-c*f9|ksO!nikr}Yn zLzu+rRkR)!VH*V>k+6q{mk)pZFme>pV~lzNGl#r|UxwA{ z`Q4}yFe5Ftw6+@W#n|%mi9kuQVTu6xOEegEmuamiE-kNh*V*rBQ->F1?rVV>QCQ=N z<6*$9vbu@{zhJ44@F2_&5VmQBzJh=Y{vlc)h=Bq#U&6!qLO%6A3>bMCkD6b+T$P z>0)b%FwGO4h}d%@>qff-6^54zJ)zB2${!NP35Q@PWAOn?nXr3BwXj^PEEm>M5H&$~ z1H#sNc|iXvLDsHJ5a!Xae7xYJ{az*HP%vYn5CPRSLK@h5;mWMJ%m}giK>AVKNXcy) znK&{L2joK;PIZ(6q3=W?g>>-(l&z9I;ly6dO&nG$JOd3?LL^jA6xzeKI>81rCkbId zyM?%ecE#thl|m@WN8eEFp@?M6&7%$}ZdRQrMKK`khTYW8vfQ zAp;U+8_~jeF`}>(+8zt9I;f$BI`E6k>1wL~u zesQg0Fgi_gkCSaN>G|%~`O{kwVPqzkSL2t_s_NV@_^1%4dI zeCi94TrLf!v_AqUb0 zRJ@P8_~{|Ri_2?+!5j#GN63cPT!NpCbZIJmeIP^|u}+^+PO#P+>mnG&z9X~~V)Dks z6ePsJ%kSXUbv)*wc(%$LlkYCDV-rVgE66x3VA|mcp$sk^MloJ@5=X(O6iM$$-#Dv3 z5~4W+DeqH4nEBY|l+c}=ovbjoHCj&YBf^sgJsmnd@e)MUAT;^@6HS9U+VtFj#@fx4 zH_2;oxqiSR*OCeMp_)R~KI0M$ko%|I4z7J5RFY0T$;`uG?rGt{ z|7uDw@|X~zF&_%!SzrfnJ}~W^a0~pONAdc?N0?K;>bx)$9zBNna2cPXM5H(*{N_&u zMJvA`bf7>Sz**$!W00c~95FL&F!6m9rFUGI?0@B=&%nGQ^NxrvM@{2Hp(u11oeinkXcE1Uzrw0y@6m1|S{>}jK;%YiZHf|PN z97gd_Er^o#h$!Bn;p=!2UFjraWXW!e7}{$RZgzAR;lG;N@=18gwCb#f8}Ou6To12V z(3fzs&O;z~YdzGp$2?$DwAcqOhj=RL%t`^QojknI7el5LExwHzBe9~WMaGKg?6}-Y zWMNmF7~g!UoeXbml?dG*rej#$3{--}$6>(-s3CiXiIG}XgqTgiQ6I^o zL8Q2k(k|P@FBnP2cozAhLIzCq$GZ`?(!^-ZH%Z*a-dCbwNs)c=A`viA!` z2TSMY!=|ocEK7`6xY<>V(Beu&nQnG-J@q^KB2vE>CD=MmjDdoim~G$4Dqe(h9)fN+ z#dMfIPCTs@l!-m)f4O4olZ*bLlnP#iOB0ZFj*iE*>eqP1Ui)Lb7-G>PCX1&iz`tRd z-&7Ixw~@&D3FbB80dg)4$Pgj=w;0HUF>k1uCMLGvWvt_X;}mi=$?{q8Gv|jV9=JPA z{1yf*6Fg|#Vi>v$1-!{;hpa7B4-z6zgKysFvjUq?X^JcA92!krx%h#A{$QOUu9X^Z znb*QQGsHwS$OSF?n}%^a}^uFn+L+}mn6d^JmSg#1ZU<46K&kMco2|56Nt zk1>((`Y17!ut6|H&A?l4n@`~>|89iX0hlN;I?hmJraEhij>eXl_c;keI~>}%4|xj} zt{<^co|0?`$Bas%*=@$LJ2nlZkNL-8VR@Y9z3!!)ihy;c4vq@+c{NT@kzkJDFS#GNNAa`(m-s*X(X`({K*M z1CQd-0+*JdAENPF9horskesNkRmJu!ytY!D1n*fXUq~RP<&OEAYgl&&N;I33b9;tcCHiYbB_qatto zL(zrSqBeetA~_~8zY5)CGhp3DWX-f!#EyT0;;VR@3olU{REgRwM&P2}e`MaVSv=h| zS8drAaSjcy$D=#r9|usCJ^ZR@$1jDL-?|~V;$a;ROL)l)@0X!9(=f{X$NzU?#GNOUs`Z0a$xM9%pwiTjhhWov4_BA`X!CM|8>~DF+`E1NFlx9^PQu5z+2p#eay)yi!?0&oI4`=3K=F_ zoZW%;MW`k&gjEZ@JmGsyENoFV`4FncC*KeUz>b~bewesROp}|@1D_LO50Pwpau*(w z-$bq-hktaNY>CXqsHdLv({guw3;=74}+8MiE%9&$VW-!C`5?yYvcgrhQ>1*y!EOW(Sfjle!e2nibfVS_#*Zm zX<;yGDsfBT;kGbTh%^SeepGA~P28cl8=C^lqyxfvrb%zYf3bRX`1mzL`*-qxxbLA_>BhpedHt>zbVS2izsui zIqby$*W?Q{?l$T~Y|%jP8oIwsg~8tAXyNQUCXOJybdb*-Is~t>!pY-e8%f_vWXI_& z-Jb-GG4-i;sgCY&YWhX?Xnqy$resr;HI?Y5O8p5jRp(u8&k6ApO51!&yi0i# z%EjVmw+IeIoNqdf)~DY=v>--*DEd+}G{;Bc&lKdHL9NjF6VcDl@X=0h-h24vma;SA zMjnzci7|nu1(Zv8lzj0^XRCCWcL~kS4VT0$R`dKqJc7}=p==aKK5di_J|04-U`RFx zSpOluW!{F5jzB+n{ zt8a;u8`X3xBS&?u8!!6o9Y=}Uli!MYcze#&(P7%1??nf#<@_j~qT#(>80pSB;UQ}2 zzlh`nE^ z_S^pl>dEJR7bk0Be~72ibQPsO%NBaVnmb}O+_)>YHfH@)lr$W+d*HofZX*-=`Znn` z8h(qQBH)gPv?di z>6$deHPH=e-SAi!86f%0!jFE`TFC&IkchGqzZHTxh)(j^uUZ#=dCvIO7y6r$t^Mk( z`t_d5YW#{yMfn65#@Fhc6I@ukH6|I3Yi%XTg8HYy&`Yj=e6Qul#9Ds!EK$G2S?Qc= zO(}LFS2urUY^s%{xRURWl)K&Nmc&nuOm@~*;ft;|vOTn`{t~9l%UkdhO5S18moPgV zKNzqiMe@@Ihf7~GzT}K&dgL%nScIPdgl~Vv?7c6oQVg`|hEL(qQUHSjf*c~kp)^{G z(I&Q%qA+Iy*GGN!89#VGUXmG-)AH<3RG{`-yu?xJ<<-FeE290W9!e;lohUbm3p_x;V;ON zo@L0qgUE7=kdrM9guMY$h_)kJ3Za1NCB=E^!UexrHW1~R!wQ>^@u3!!se0(ujn)@L zD^dhzYpk3Wgp2$fGvGxzu>?6tQa`=2$7+G{n;`2?5gaq{hT9>;9%}>$(zPd z?5g2X9QhLh86%{LaCxL8K*~soCuNx$7`oZDx(UL6)B@6iyp8mQ;O*lDP zS_fmDQXcGeN(0DKER4xR?p@|YUKv{?rNRsOQWP{4NEWz}kMEQM?90sjFCEsjbwnWrHI}CFmq=)Zm%ihq#PJjAf>}YV{q9C=33DNDW1hM6Y>}_ zNbw6qNC)&fXqZ}IJt=bV%_=Vm+Mg7Cwa=?1jtbKAI)))hiAvJjm0}KT2`Ce#E^zB4 zdd5~xlyaeTGG^pxtGxoCb*+>I7we_5VLJ9irJ;&NyJ zY#b8ES7Z%Wd zm!=@|;2$qoRD@T8ty8hbep97zNSPu9LuS3%t#4B^-KHfpf`)1M8JGL|JXMUXqNZX` zt*1#nJnv}*(KXm$-xTDHyvbN2mYooVF+bC`ItI}pl>-f5a`Er)GCA2l(l1_8L9g?O{PI&l`RN0J%ro1b4N`vVg zFlu<_7wJ4){Z)F9s)NbDNf+7j8Wc9x5AlN+rFW!K*w;Z0K=0jW9b`Yv_jhRnj}m+7 zWyW7XcL=%O0N;|Ry`7cYF_;wr-(sdE1jNdHVLU581a+buriF8I8eVW}FF)=B3m@GCD*hB!Y=c1#GsJjaXeh*18l}(GmaO zoJeL8ywOq4FrI$xC?AY9vXzDo>zOlr7zxXylCYv2TjFvT*Ou2{VhADy&en3^&{`6m zH!&u*NMB6fLVrMB%O3E`iQyNs)!^ibvum;*&2K&*-P>_$hCI-`%z83jZUq6Y<>P29 zhlz4OO!t%I-7x0@1}`!@%Sn>%DbP*u{R}Q;ZKk}k@xx7WSEQ@Y5=#;sp2c`3_HM=w zQ}a!-k(T7!ab&w2ehq@68+vv{t1>HFw&J(pbaw}_lJL@x1DsuDzYwB5i*SJ^kmkA~ zuG0M$sbIzL#=$W!B>7QKS+LOVBD( z4uhDhvM<~`Zt;T;Wx1O=_L?8`6XY1^>mjSe{co^Bpnl7{$@J2vjwUSJ?2j>>8cz1` zZn30fOf;5n-ldOWP+g~63!;<$*=#uhO1jF)KKIcb zEu2}sfbI)NKbht zxifwxRUY!!YY_iGtbssox8Q&9ZI~QDqcdXN2e>)+g~%3|;VF9o8;nbYNi&{yjOY`h zq2jB?FY%UGi_m;0rZpNUP9uTFT|TY~BM#jNOYI4jB_HC5Av~+w?U~lp3`p^mLpu;b zWW4KQO-t4P5iT`eB_Jc=s|>l`U4h?iwUZxuH?XG-egO0TA$q)l9&Bzahr)(Xlt0(~ zWZ4rBtF9^NmnPn>bXXTE;};&%(3+pnR<42N?U4Elz2qQx#z*$`tgj*IpE>#$voImU zSH2Dz6rS%k76^)`$reT(IGK;}%LrfOdS8F6mM0*YPX@{!puA<_U{!#8n^3>f3;F#5 zN&LpLcj0CrjW~39 zW#od`2-zBFED~8u+1!z7xc8yKBKvo2v8;{l^6~`yNKdwuWM^3|S5@;#6p=&~lxqY5%9VD*=zH$kx+YI-Of}I|*4k`v#qm zJ&-^G4-z1H zq~6k}C0cLWa@w1N(c7A+ji%HjZG_R0q&aXH_9YnJ#%X}u`O|1^9M06*;7`#)XGUYk zx_XROMEPkL+Llx-9nb}Dv~*{x_7?k2h10cZS`UjiV6$bu&3kTGDmvLYI3Unio37ym z^tES!_;j{h4>S_9w9z)xBM(?gI(;6i^{2mOKT>|g=qW78Nj=-y|Rd}r;rRd!qBrGYiet|_JS@OqRAEA%2Is6Ywd)c zfU)qqaQ|~kzOXS=jWAb&+NFKXfF?oP&uB4`=ZvSBV?!>u#WN*(*Z>a${wKQ@gnDeT z6&x$<5o|zkrpN(9!;CU*C~Yg#veGaP;8_eKG>eDIJQOi=WGDA8C@BONT0TsR%P>3a z8&0*)BN|TW6v`^fywlJx_B$YHm1xu}3}U1kG!a(cQ!Y-!i35udYYi3n8!@T&QcJ2FP0$i4-j%gu{n)j3@7M02+=F1VQ};u2 zSanQGi}VnBqE*4z|YfkkF1nnERYh zv{2)tW7(fMsq_O_Y7ON^zfoYd^UKPDZ!h>ffOpLtPTaLiV*nI3e0^I{fqJgW#0f!Npl0G zE5?+>x+PIHQBARoPUQJBXUD1o#M*38B>|({rFY9q^X)P=6eHjL?Jm1av*+UYA$0)l zTmiYtwG6_>lTSd{**+SRy7N^L_HU1rAAD!;h>`j9PKu187h>RG{&Kt=KvN^6Gqk?e zx31Wyo5n`SUYa>l>UmX^Or(1w zNR+(C;T?z?43^U(cGIp;DUmWhc3vaQ=P*jQw6U)ta4MDN&qh2t6D?yBu2`VWnZSV zxtfDsKcTrD8CAf$s4AUGXHRIaC{}PdM3(ZBl*Y&3YERhCyZkBm6d0uPh`_?w%6uR; zvb?#u!E=*L26||6gO1I+B5CT6ngC1j@&${xG5MaGNs*wHOLo*8iJ-xIwLtc1t;7-F zwLfaR>G`+80~&tPhWWw%w7El+QpQ=x#>_Z2xP`;m`m=`9TNML2_H~hFh|}8lz;sU% z0rd1B@a5z)5cJs9&&2($J_ByD_>7imH*L&x@(U2x&9?>GJ36n6qVMepv+ryJ^KX3C zJ_SIx2v_|Xf);pY+xi@FF;|qe{wcB8fXDhe8=V-4sQaz{BKv<^MLHrQMTqfIpr{MC zWf?gxkz%v+4uBKF{7sHHqd8XGGb1%>}ngI zv8O;B6;pAh0=J!tMKkM6ip1(*LiVv?PhRUiT{K9hQD%;Kger2y>;4SX`^HfS&fEHk zK$?^%P6qL1C~XT`X3j*)*gv%J<{+%z9`*nE;zdM3@BLDQk-JK?(Op&I1=?I7`bs_;VgpjnLfBI_P8UPClod31 z4BS2)eZ+d{s}2^bU#dk4?d^lQ7n_Z>7v4n>%u$c<_?Q7J(n7ZIal7khmX`7YRxj&47f30~*>q3L z811;(FLs6bs(a*EI!<)hZ~$*Fl36lmMA!8}e;=Ty#KQ8d5Ofol`?N}ckCiU|{~yxsei7Nbb=@F3yp0a1@Z{_ASF4XOZY z9xUQ1d9a97ei|HHc}@ybIqL2> z1XU#*!9iF?tl-A8b;>j77fjjSqL>1i1kR;D-vF8lHd{z=Lxuuc@y>9o!y0DVJl7F9 z3#$n@w&o(6(q#^&f(p!WzL2W^p%$wWzIcska@2596n)-$AcovB1IAPkEZlbo2nTgm z;LrQRMYaPJrsA$?*C0_$d-n2l7a`e~Q8MJ8%yjzy$0VypdIaDGv&rTxt9fSaK%G%s z7zZ=+BbeSZ&0aoZmeXyL$W|^~bbE!EkO;R3)`&otK04^mIBuakE)p}-yK;~76lu#US!*yX{mA*0p?6w^#ZFj9DY9T zl-If7!cvRFU6?ouEj6g6=1Q4o?-EvRoh=-a6w~3$5`BY<4-2=U~0^_9kE#Ya)byD z;4$Y7E0Wd>hN4;$2ZZqDvCuN!h?nUo;=y>C&4bB0BpvE0BQlsUlnoP`8(%=di^bDU zOEXi7r_xM^dA@W}E74Ocn^GUU>b3mAa$836p3L-NoQ%lBC+$TtN9p8jfQ5JJ zP_l1ocSz&R7;&AAPA*26)eGaqESj)HhQm1&5kbics{w(3Tz)!ikLXcj%_5fGP5(^w z3GNf{!M+&gr{haxWH5McTYXzYT`sM!6!~yv++QJFY2CT1Z_~ps>lB-gY!XSt4e2UecW(*pI)rIDPyyzcQYIp$uON{5_}j6i zAb(nt?{$~*(QsChd3>ffVHTTSbZAsGUqmM{FXc}r53|~%WMJ+P?Rv#80>H1zMF9n> zPLpWHwq8A7%qalbE%Xq#+9$E~0z|P1s?S1*2pAooyPml@(#b6%Jb*t@NVCB8dh?hoBO*Qt8aSBDGhy@}`)>g9!HEN>CN#d-+^dePxUA~A|pcHAY$ zf;MC{%g99T#o|URATiX~xmXl9=*L%pr4GXdtO|cZkDgpDN`e{ZG&6%i#LupVQmdd! zJFgOxL|5b0>8nH@%}5dnwDM{Z(O<>qpjGhhn(cFc%FC!~scKqQ)v}ELwq@qA-mBKE zC!R;6Tdx+|ZOO*4YeY_9KX;Dj9H4a$3}!PIw6ToK%82!h8Z1X_>s2P|2qIg-$D1!797?esKjo@KbQ^hKCT~c%%bHrH3CB zH`w`TF2ZQpCME{b_SG<5obC|8xYa~lZKs@P#CQNYL%|Pu5$QjFTC52OR2vAr@f_5i z=ZZlBZ|@RrihCZm0)F(LIu)USk0C@A$eogEo(CVPdJdfnc>#Z#S3$`BWfvB9=t}~z z`_GGH>oCz85?rCNt5`(26q%UTLEo}e1F<6t-P!b_up4V$5c&2EReC5vm=X}nfJn!I z;W%IUtH`C@XT{1;7<1J-#ai)aeGPV$_+r=wI$stEA>BV_(=)$_gyD*HW@T|sh)fnh zjw#mRn<>GVe1Yu+7J+&!)(nB8G+)ZJ$s}xMVa2c%qqcZj@v}JXw47~VMnzkx_U|IY zA2m_!X_3~)s!tWriXhphwpkge$>v>yJ#*5RBIWW{>zdJ?t-$u6lmCfP-TIm4O5(L_ zwpZn6r5P`jz{Sm_N&}R@0yUcF@13t( z=%+U~{dh(+7Im!^s5~$a)}Vd(Wi^uz63*?sX{`^B1#SNBRY(|?wLY9CrApk95e8F} z&+I-lOx|po$2Yz#l7l>ahgL!Qa9B);<&(Hb>q&`M7K5TPH@2>QsWQo%RlVtvCJVa1 zsY;VszBie289CBrvagPsEa@_ar^_d7h%}ay%{F0*;_c?3kS!WAb5jqro|{AM_$AG@ zcoLMmk>LGaGS$j~7l{;?AqNC`rUm!dB1ubzEDTikPV@OGr0Dt_k_mCYJrg2sXPTTt zPi4x1wt41@uX;nsYfcAU=)L7`n%q-9NC&f|o^S!i`ulb4>i2huA}Z|#3n5#%VZ*f> zzy3``+9XbUy*67qxeqL+Z%^!+3UC_6?*kUcz#f65AkTDK^`7AP-q-fw;`pPB6AVN; zj0!NWe_M3=(Wsn&aHHgXQR9b@e$GK*_krZ&-V(ag(yPo5#@-LaE)Pt$|Dj;wD z>43P8Zum^}rN<9r^WJb!jEhvetrCh%1O@Du$%E^a{nOCn@mq0lY%-=V1++=SoEe68v-Uz@Gqc}x#+7;M64~J zc6baFX4h zI==?{#|^bfbYvx@l2<>)Xr1Mo?BOn?)2+j`a7z9G7U1c}#k-WWRwNqZKNASL`Rr>w z#y~M&+oB)Y^CRsllhMY)wmE6ZBALQO(9`&8 zll;t1Jsyx}Ddi8y0~dgg)_KvrQT z!=jk4L?+;P!$yInZ63iax11iVlrUyMO{#157!y3n89csxhl~j|pD#i%hFPYOvqfG5 zm<9uTfOuG5PfxdtAZSale*c!EZy5WD*R`?rVTt4MH@C_ZO}#YZV87ieFEuXShP~Y0 z!d~?mfYZc?W+xX?^`n@wE!!o$PSvaoscC7YL3pMk+vQQ?H zWKp#a2sx=$iwg5ovuXb0m{X|8s+d@eS@#^4s@F;hhD>n$heuiLnAV(%Yfr%5Rv2<1 z?d$=~bzNzo*f2^DGJ!9CdS0FeGR2F4U|g|VzD*xp9~5R@_@YqMY=6ZNC|vILCO^$s z_o{65H(uByZ}Fq{X;`A8&SD|9z6Aw%`&-gwuW4fqgWhCk>S{kN%y7RgR|D?#H5_~o zdSB`hh*4%sn2FEFY!lDabPP*eg(BNSa12@fG^ED~d*ygq@djXF6@nekGXtQb!YTFm zUQpwXC&44wXC;EQA{AFs-;|LFMYL_syjo-72eR2l&y>NB*(r2~;kRGf{AkTmFu0qK z`i0SegECVA2-Dm{X!_+t^-pQqFuf!Y5m|_FSv6cwqNBs~-gfoeNA!Dja#O-dBzLNY zKpf{owI1E4vA$^-*Nbt1k0J|G*5k-=7Y*p5rNMN8GabHbo#v$J6?7_1 zPowwJfL)7U{gjybQ<|Pkm!#`1>j{o~>ADuur4A*nAzf+!t7r7?#d?uHDl#G~^$%^T zZARn-{d3Sqr7n%Pr|WHgG-H75NegG_SwSANA64}YOfKj`ZEhry$$<*HItek-((4z0;a2KDV@_`suHQbPDdHr~f!Qc8$W_OW^ zed*jw-E0%&4D6G613UVnwV-QW1#6&Qhl;V>K;Z4LS{8?C%dPYmbh z($cnh6Bw9E8E`Tw>{`8qj`T+G;)xpFX*lQUcR{ee95Z2S)63W2ib=R}fezf8HvO;W zfqZBcI{(uGeI^q_k&(1aH-c#Nd)Pp~xJo}mae@A!#xGav0BOVe1hmU7fp#P9Mjfb$ z42VNJX9h|7?k0VNV?td`1IGawLvPk!4>hvy)_28I)Na^-+Ba&#IP#R>DX1-+RX4M^B)@P*N&ZagcUI4#Ki=TXqStIrL`$93BZDhVZ)pSu z+3e1U^-WGkFeE2-pw4rz|D7`$LE`Y)%5z5JlhaSV>q&OIGlY|_-{}m3=?h*z6YCmk ztExt|&TAS2^~NmgduLdP`pB;*;)3VK8ufv4ZO(+A>I-ZzoCMzx4NaPB88Wx~HfL`$P;Tz+&IFG6D_igE$!{{~ zi`(&MPa6=*7tF@(HYImBd**ay)J$@GVUfAkSR3Mk`2x_Q*jmR`aZd9#2o69qwQDQcHB= zp7z}BObYdW;d=2u*;Yd{xa)4r;iH=|PaHaS;n_9Xc8_z2FMMsoy`X@oJK@y%%@TxZ wmfhRn)difo?98@={twk%`-tCfe)F5*L&gsIFJ1>KL;wH) diff --git a/system/includes/functions.php b/system/includes/functions.php index db6cd02..c092e06 100644 --- a/system/includes/functions.php +++ b/system/includes/functions.php @@ -3,7 +3,7 @@ // Change this to your timezone date_default_timezone_set('Asia/Jakarta'); -use dflydev\markdown\MarkdownParser; +use \Michelf\MarkdownExtra; use \Suin\RSSWriter\Feed; use \Suin\RSSWriter\Channel; use \Suin\RSSWriter\Item; @@ -100,9 +100,6 @@ function get_posts($posts, $page = 1, $perpage = 0){ // Extract a specific page with results $posts = array_slice($posts, ($page-1) * $perpage, $perpage); - - // Create a new instance of the markdown parser - $md = new MarkdownParser(); foreach($posts as $index => $v){ @@ -140,7 +137,7 @@ function get_posts($posts, $page = 1, $perpage = 0){ $post->tagurl = site_url(). 'tag/' . $arr[1]; // Get the contents and convert it to HTML - $content = $md->transformMarkdown(file_get_contents($filepath)); + $content = MarkdownExtra::defaultTransform(file_get_contents($filepath)); // Extract the title and body $arr = explode('

', $content); @@ -268,9 +265,6 @@ function get_bio($author){ $tmp = array(); - // Create a new instance of the markdown parser - $md = new MarkdownParser(); - foreach($names as $index => $v){ $post = new stdClass; @@ -287,7 +281,7 @@ function get_bio($author){ $post->url = site_url() . 'author/' . $profile; // Get the contents and convert it to HTML - $content = $md->transformMarkdown(file_get_contents($v)); + $content = MarkdownExtra::defaultTransform(file_get_contents($v)); // Extract the title and body $arr = explode('', $content); @@ -320,9 +314,6 @@ function get_static_post($static){ $tmp = array(); - // Create a new instance of the markdown parser - $md = new MarkdownParser(); - foreach($posts as $index => $v){ if(strpos($v, $static.'.md') !== false){ @@ -336,7 +327,7 @@ function get_static_post($static){ $post->url = site_url() . str_replace('.md','',$url); // Get the contents and convert it to HTML - $content = $md->transformMarkdown(file_get_contents($v)); + $content = MarkdownExtra::defaultTransform(file_get_contents($v)); // Extract the title and body $arr = explode('', $content); @@ -356,15 +347,12 @@ function get_keyword($keyword){ $posts = get_post_unsorted(); $tmp = array(); - - // Create a new instance of the markdown parser - $md = new MarkdownParser(); $words = explode(' ', $keyword); foreach($posts as $index => $v){ - $content = $md->transformMarkdown(file_get_contents($v)); + $content = MarkdownExtra::defaultTransform(file_get_contents($v)); foreach ($words as $word) { if(strpos(strtolower(strip_tags($content)), strtolower($word)) !== false){ diff --git a/themes/dan/404-search.html.php b/themes/dan/404-search.html.php new file mode 100644 index 0000000..784ebb4 --- /dev/null +++ b/themes/dan/404-search.html.php @@ -0,0 +1,26 @@ + + + + + + + + Search results not found! - <?php echo config('blog.title') ?> + + + + + +
+

Search results not found!

+
+
+ + +
+ +
+

Please search again, or would you like to try our homepage instead?

+
+ + \ No newline at end of file diff --git a/themes/dan/404.html.php b/themes/dan/404.html.php new file mode 100644 index 0000000..1a1a8ac --- /dev/null +++ b/themes/dan/404.html.php @@ -0,0 +1,19 @@ + + + + + + + + 404 Not Found - <?php echo config('blog.title') ?> + + + + + +
+

This page doesn't exist!

+

Would you like to try our homepage instead?

+
+ + \ No newline at end of file diff --git a/themes/dan/css/style.css b/themes/dan/css/style.css new file mode 100644 index 0000000..1248f71 --- /dev/null +++ b/themes/dan/css/style.css @@ -0,0 +1,674 @@ +/*------------------------- + Simple reset +--------------------------*/ + +*{ + margin:0; + padding:0; +} + + +body { + font-family: Georgia, sans-serif, Arial; + font-size: 16px; + line-height: 1.6; + color: #343A3F; + padding: 0; + margin: 0; + font-weight:500; +} + +/*------------------------- + Heading +--------------------------*/ + +h1, h2, h3, h4, h5, h6 { + font-family: 'Open Sans',sans-serif; + line-height: 1.3; + margin: 0.5em 0; +} + +h1 { + font-size: 28px; +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 18px; +} + +h4 { + font-size: 16px; +} + +h5 { + font-size: 14px; +} + +h6 { + font-size: 12px; +} + +/*------------------------- + Layout +--------------------------*/ + +#outer-wrapper { + margin:0; + padding:0; + float:left; + width: 100%; +} + +#inner-wrapper { + padding: 0 10px; +} + +.container { + padding: 0 20px; +} + +#header-wrapper { + background: #546673; + position:relative; + padding: 1em 0; + float:left; + width: 100%; + color: #ffffff; + font-family: Georgia, sans-serif; + font-style:italic; +} + +#content-wrapper { + float:left; + width: 100%; + padding: 3em 0; +} + +#menu, #header, #content, #footer { + width: 700px; + margin: 0 auto; +} + +#header { + text-align:center; +} + +/*------------------------- + Link +--------------------------*/ + +a, a:visited { + outline:none; + color:#2E9FFF; + text-decoration:none; +} + +a:hover{ + text-decoration:underline; +} + +/*------------------------- + Text element +--------------------------*/ + +blockquote:before { + color: #BBBBBB; + content: "“"; + font-size: 3em; + line-height: 0.1em; + margin-right: 0.2em; + vertical-align: -0.4em; +} + +blockquote:after { + color: #BBBBBB; + content: "”"; + font-size: 3em; + line-height: 0.1em; + vertical-align: -0.45em; +} + +blockquote { + font-style: italic; + margin-left: 1em; +} + +pre { + margin: 1em 0; + overflow: auto; + background: #F1F1FF; +} + +pre code { + color: #333333; + display: block; + font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,serif; + font-size: 14px; + padding: 5px 10px; +} + +.thumbnail { + float: left; + height: 80px; + width: 80px; + margin: 5px 15px 0 0; + overflow: hidden; + display: block; + background-repeat: no-repeat; + background-position: center; + background-size: cover; +} + +ul, ol { + padding-left: 30px; + margin: 1em 0; +} + +ul li, ol li{ + margin: 0.25em 0; +} + +/*------------------------- + Menu +--------------------------*/ + +#menu-wrapper { + font-weight:bold; + font-family: 'Open Sans',sans-serif; + color: #7E909D; + padding: 10px 0; + float:left; + width:100%; +} + +#menu { + font-weight:bold; + font-family: 'Open Sans',sans-serif; + color: #7E909D; +} + +#menu ul { + margin:0; + padding:0; +} + +#menu a { + color: #7E909D; +} + +#menu ul li { + float:left; + margin:0 20px 0 0; + list-style:none; + padding-top:2px; +} + +/*---------------------------- + Search form +-----------------------------*/ + +#search-form { + position:relative; + float:right; +} + +.search-input{ + margin: 0; + padding: 4px 15px; + font-family: Arial, Helvetica, sans-serif; + font-size:14px; + border:1px solid #0076a3; + border-top-left-radius: 5px 5px; + border-bottom-left-radius: 5px 5px; + width: 120px; + color: #888888; +} +.search-button { + margin: 0; + padding: 4px; + font-family: Arial, Helvetica, sans-serif; + font-size:14px; + outline: none; + cursor: pointer; + text-align: center; + text-decoration: none; + color: #ffffff; + border: solid 1px #546673; + border-right:0px; + background: #0095cd; + background: -webkit-gradient(linear, left top, left bottom, from(#2E9FFF), to(#2E9CCC)); + background: -moz-linear-gradient(top, #2E9FFF, #2E9CCC); + border-top-right-radius: 5px 5px; + border-bottom-right-radius: 5px 5px; + width: 60px; +} +.search-button:hover { + text-decoration: none; + background: #007ead; + background: -webkit-gradient(linear, left top, left bottom, from(#0095cc), to(#00678e)); + background: -moz-linear-gradient(top, #0095cc, #00678e); +} +/* Fixes submit button height problem in Firefox */ +.search-button::-moz-focus-inner { + border: 0; +} + +/*------------------------- + Post +--------------------------*/ + +.post { + border-bottom: 1px solid #EBF2F6; + padding: 1em 0; + float: left; + width: 100%; +} + +.inpost .post { + padding-bottom: 0; +} + +p, ul { + margin :1em 0; +} + +.breadcrumb { + font-family: 'Open Sans',sans-serif; + font-size: 14px; + font-weight:normal; +} + +.date { + font-family: 'Open Sans',sans-serif; + font-size: 14px; + color: #A7A7A7; + font-weight:normal; +} + +h1.blog-title { + font-style:normal; +} + +h1.title-post a, h2.title-index a{ + color:#4f4f4f; + text-decoration: none; +} + +h1.title-post a:hover, h2.title-index a:hover { + color: #2E9FFF; +} + +.inpost .post { + padding-top:0; + border: none; +} + +.inpage .border { + padding:0; + margin:0; + border:0; +} + +.inpage .post { + padding-top:0; +} + +.infront .first, .inpost .post, .intag .first, .inarchive .first, .insearch .first { + padding-top:0; +} + +.infront .first h2.title-index { + margin-top:0; +} + +.post-list { + font-size: 14px; +} + +/*------------------------- + Share box +--------------------------*/ + +.share-box { + font-size: 14px; + float:left; +} + +.author-info { + width: 540px; + float:left; +} + +.share { + width:140px; + margin-right: 1em; +} + +.share a { + display: inline-block; + width: 18px; + height: 18px; + margin: 0; + padding: 0 5px; + vertical-align: middle; + -o-transition: all .3s; + -moz-transition: all .3s; + -webkit-transition: all .3s; + -ms-transition: all .3s; + text-indent: -9999em; +} + +.share a.twitter { background: url(../img/share-twitter.png) left top no-repeat; } +.share a.facebook { background: url(../img/share-facebook.png) left top no-repeat; } +.share a.googleplus { background: url(../img/share-googleplus.png) left top no-repeat; } + +.share a:hover { background-position: left -26px; } + +/*------------------------- + Comments +--------------------------*/ + +.comments { + position:relative; + display:block; + font-size:16px; + float:left; + width:100%; +} + +.border { + border-top: 1px solid #DFDFDF; + margin-bottom: 15px; + margin-top: 10px; + padding-bottom: 15px; + width: 100%; + float:left; +} + +.border #disqus_thread { + padding-top: 1.2em; +} + +#disqus_thread { + font-family: Georgia, Times, Cambria, serif; + float:left; + width:100%; +} + +/*------------------------- + Pagination + Postnav +--------------------------*/ + +.postnav{ + width:100%; + float:left; + padding-bottom:1em; + font-family: 'Open Sans',sans-serif; + font-size: 12px; + font-weight:bold; +} + +.postnav a { + background: none repeat scroll 0 0 #E4E7EE; + border-radius: 3px; + color: #555555; + line-height: 1; + padding: 10px 20px; + text-align: center; +} + +.postnav a:hover { + text-decoration:none; + color:#333333; +} + +.postnav .newer { + float:left; +} + +.postnav .older { + float:right; +} + +.pager { + width:100%; + float:left; + padding: 30px 0 1em 0; + font-family: 'Open Sans',sans-serif; + font-size: 12px; + font-weight:bold; +} + +.pager a { + background: none repeat scroll 0 0 #E4E7EE; + border-radius: 3px; + color: #555555; + line-height: 1; + padding: 10px 20px; + text-align: center; +} + +.pager .newer { + float:left; +} + +.pager .older { + float:right; +} + +.pager a:hover { + text-decoration:none; + color:#333333; +} + +/*------------------------- + Footer +--------------------------*/ + +#footer-wrapper { + background: #546673; + position:relative; + padding: 20px 0; + float:left; + width: 100%; + color: #ABB6C5; + font-family: 'Open Sans', sans-serif; +} + +#footer { + font-size: 14px; +} + +#footer a { + color: #CBD2DC; + font-weight:bold; +} + +#footer ul { + margin:0.5em 0; +} + +.footer-column { + padding-bottom: 1.5em; + float:left; + width:100%; +} + +.column { + float: left; + width: 33%; +} + +.social { + float:right; +} + +.social .inner { + padding-left:30px; +} + +.tagcloud ul { + padding:0; + margin:0; +} + +.tagcloud ul li { + float:left; + list-style:none; + margin-right: 10px; +} + +.copyright { + font-size: 12px; + float:left; + width: 100%; + border-top: 1px solid #ABB6C5; + padding-top:1em; +} + +.copyright p { + margin: 0.5em 0; + line-height: 1.2; +} + +/*---------------------------- + The 404 page +-----------------------------*/ + +.message{ + padding:50px 20px 20px 20px; +} + +.message h1{ + font-size:36px; + margin-bottom: 18px; +} + +.message p{ + font-size:13px; +} + +.center{ + text-align:center; +} + +.search-404 { + position:relative; + float:left; + width:100%; + margin-bottom: 1.2em; +} + +#search-form-404 { + float:none; +} + +/*---------------------------- + Media queries +-----------------------------*/ + +@media all and (max-width: 700px) { + + #menu, #header, #content, #footer { + margin: 0 auto; + width: 100%; + } + + #menu-wrapper { + text-align:center; + } + + #menu ul li { + float:none; + display:inline-block; + } + + #search-form { + float:none; + } + + .author-info { + width: 100%; + float:left; + } + + .share { + width:100%; + margin-right: 0; + padding-bottom: 1em; + } + + .column { + float:left; + width:100%; + } + + .postnav .newer { + float:left; + margin-bottom:1em; + } + + .postnav .older { + float:left; + } + + .social .inner { + padding-left:0px; + } + +} + +/*---------------------------- + Video +-----------------------------*/ + +.video-wrapper { + margin-bottom:1em; +} + +@media all and (min-width: 420px) { + + .video-wrapper { + padding-top:315px!important; + position:relative; + width:100%; + max-width:420px!important; + max-height:315px!important; + } + + .video-wrapper iframe, .video-wrapper object, .video-wrapper embed { + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + max-width:420px!important; + max-height:315px!important; + } + +} + +@media all and (max-width: 420px) { + + .video-wrapper { + position: relative; + padding-bottom: 56.25%; + padding-top: 30px; + height: 0; + overflow: hidden; + } + + .video-wrapper iframe, .video-wrapper object, .video-wrapper embed { + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + } + +} + diff --git a/themes/dan/img/facebook.png b/themes/dan/img/facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..f265dd49c2d65af33ba3ad17e8a009ddb91bcf03 GIT binary patch literal 2490 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%0A3IHq5M8pu^VGg4kpA_Jc+vvJ>ae-14wmml8 zvJ>0(oPEQo?c;eWtfw8>#$I?Pzkfk-DCOYW$cT+6M#(pKQUYqwI5ql zhH4-XKRxU6!3j9uxvPvJWAW4#??k8r>xw7!rsHqC|0DUcatQV#@Pb8ZWJm_uM=w&U z@WDL-W~MIA;Iyd3QbQ0I_P%^}{&8bPVbb;p(n>3~p*+S)GY-@8q{KJHK$NHQ`NA;? zC~Q8@KxWpY?DPqgfd!= zS?&nY#qs}&OMH5)vPr~zc^;x{Rm-v4cWF?-^~L@>|`(0xa^ zyv--SmD}%hN0?_S@$PDz`&6Ka;k?}X1nD;Lv#<#NmJ~>JHv6@^Ud$_Zbg(VO`-gI$ zxdGn}Icx6a!5lN^4boB4ZYVJj=TVT=U}t)4(s%5XdzH-4?E7(1{b#F;n0kiJRkoq~ z6a$9PfJ(OOrhOoin!m{%wJXKnroa~7<`gLFp8;0p$u{!2Cnmp+n7vqIDp?W!NQ3uN z*-$NCTa4YB5@RwMN9BkoKYm;TJPF$s>X!Gdclq7kFCoEbM|}!kV0GZVWJP(+3Q&Ga zo?e(fl@a9tGJIwZTyTxLNO(13C-+_iN8qakLw*!_q}(Mfj2_-8Zhs%Xdu!gn-u5OU zC{;#Tuf%;8+`|x{Jbi$&M(CjMb2Sg;WsZ^3v$9O2%Qy&u!j z*5;JYfB#-0^UHbsn`EOo&xbi*&ek5g3=+56$+Y+Ew-!+P*4p?8LZ-R7_T73h*1a>0 zL_7=H=CGF{O{o>yfpPqYJJwt+Ck9A)tV!uHi(LE>u@5?zzZZ?)bx~msvK#(E+npLE z^5J?nmNX28chcZ7m$_%HAgvQjorDGZhLp7W*b4!96b*PpDnAtZ`7I^7JtjO4 zFX3CkOGI^&ZlFrVrB2w4=~4rc9Xf?Gf^OyNo({R7Kr8Fg>99lr8~xIZ<$oBE&N$(MJ&?CRT?`V>erx8Tu&p20vh zPMZabyWYtDyK2Y_;!!U>ZY5E%MC`$$d6DePJV-{0GZ({r542nOU0_8{dum50dS6#{d8T literal 0 HcmV?d00001 diff --git a/themes/dan/img/rss.png b/themes/dan/img/rss.png new file mode 100644 index 0000000000000000000000000000000000000000..48c9ccc4f21adc565261bec7252ac8625cf34d38 GIT binary patch literal 2764 zcmcIm`8U*mAN>?kn2517zGP3fP+22mYeZr!p-HlpB~eI2JyFS$6cRB=8jS45u1JhE zvYS!1v70eu&{*D&@AE%A_niBBz3w^pr+e-XuV^dFi!d$(7X(2tGn6rUf2028VYdD0 zdd4USf)3hQS=gHF%l`*5({c6n^&PFG_V)IIy!@~A^*PzuvC+|v4i3%D%@Y$7z1`il zRnU3l|1dc|zJCw*4-EA60b2+Fz+7M7mn-|erKO?1 z{;`o!U0@ zYI>Y9Ha#&p`Fnig*RR!;6<`YeVXOi@2pB>@f{tKhQI{~prD*kaDl&Q6VwgWc_g**PE$fonYA90cC`f{2S?jSf_KfjR_kNr9O$Q2Yj5=G_?| z0l#{72pKy$Z-G5KaN-BGsle?xsQ&=Id|Ib1fua|HQ~)}Pfu{usKDXCY0TP~od&+>Z z2>h+Ve~=)`dUIh8bP!q9g}_oBU<|?1)E+Jh*q#NNM}Yx1@Yeyu9U$>0czFxlz5srF z1*k&+YqX!z?qeV33>BOg{X6^M|>$2&d5DGFjJSW?kkO{U*Jf&*~vF&w_oz686jJCRbGSa=FoOW}DF5+M^pXB>&j|ya8kr&e5a}zK|EPL8 zD98`|IWzjSuxcsc<^)yxkzUK}X{L>Nj3gxrjcL=Z9DXaMe+|k-$W55bk|p5#k{p5B&3ut zh;j0-sAey3WJZo%TctbAYWP~H_KL)c_TeRZdWp8t+iw+mKR!K$E|5P@`p)Z_VI$=j zyO?`F)g}vOOMQ&7Wooh}n)OYwN?e(%vnH(tuU^CQ;BBx^YQ1$O3Ko*i$Krl_z$l8B zw)AjaC4rbjaX-BvTLa{DrL`-C)m?OeIbjd17U70ly66``Y%eh}m=HDq(kYq)T*`u4~1$ZI*=9NMgj z5$x@v#q%+;iGqAZR&RX0qK6`LZgXQihU4Cu2mI7>zK9HY>2P^ZP!yTg9^XYa&M(Wx z3-ubFN5l=GBtP&My^R<Yj+fO<~B6k=)5! zG@ZDe^2#SeLL!w1P3Zr?f+G5><9*#DL(&AL6MV|G^cvn--8tE#b3o@_^5@otf<`|3 zNC~oLn%g?R?Gf$cUEDgRmqwPYofBm}4sYXsrfyj;J0915C=;LQmXqEs_Dws;Y3s9% z1RK%zJJUH@;iM+w{_Oq8r1I3*7&aHwE2meYh&cwYXHRF_mp|GpVti7e`{HzvtKs1U z9SmjGTgOv&A29vBCO57<59`z4Og|+gZl$jwe-3wtIbxb<7XmC!ogjaa}^-~#p z+%Hm)XnmfMa)wivZj6PFqQ7d^QIt?xKb>*!7govdDqE;vXrradQRy0@kgAFGE|%Gr z&4ZxLv294nn=iR)KQLBLVIsV_tn@QPe?J(=5|0uc`?xu9(@iVB=YWVeDJ~rY3?Q4= zH89Mm*n!h4lhv+#q=zBJJx!`Yg{F5ks8c0tUD$WY+36;5e4FJdjqf6o;;rp&msa{5 zlpEEx!{s`o;fk(nBi0EAulmK=`;^WHYKSr{G(-*LTRyqy#Ht_Uc5zbV@;i&D`h6QO zLJj0MafIWC>#j>wT`SgqgBh>`XHO|5cOA~Q=T)@9SshNqT Kagm`*#D4*i`hFb% literal 0 HcmV?d00001 diff --git a/themes/dan/img/share-facebook.png b/themes/dan/img/share-facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..5541821ec577a47a2cb2b82385a776079fc24cea GIT binary patch literal 582 zcmeAS@N?(olHy`uVBq!ia0vp^LO`s;!3-qh6C`#3sqFziA+A6=EG*1-_C~+Cn}Lkr z{PNJy(D3kZ|9M-13?Klqf#QC1Hb+KALd5;%Yyye^*%1*DKsHcsz``BAvo`q7+2l2C z4NxOc9HeFTCZHCe#-N}epPB1{;(qhC_|M-OxM(L(5TZRgIvS`Ls4Q^tE+E5q_6Gk2 z+X5DB2bu{~5E2sNKYyFw+$})!ffo79+TcB7Ezn6o!`WrCRDe!5E(!7rW-!xVyqNJF zJNsjq1R;ypcY|4->aNJVdGo-1@x8!p>R-MudAjO?&&zn-4Jxzq9reEMDLJZh{*)~P z10%Pmi(`n!`J?A=1~nUquq8MweB-^4>C)MCQRVzM72f}kIVPFx^l?%7-{OfU&DB4j zH>{id&Z=ehm4KCkqUnn-iz#~*Yz?0jy2M(h|MyI#?F(PrlTgX#kiAfpDJ$@IRj~Ht zEiWf<9R6~7YDi*>=24!jZD-ac_XxRNTXmr;?mp+g4NB441>P=sN7i1JUHCkttiq(# zEo9TjD;e(PzBkG|wu!nLKYq2*e_5to+bo|?q5L*{CR`8H@5TJy#_)jQXvpv9j?puo zMXv}v^w7~xg>nDYL^&4i29@*6g+2ZFm1G_~?YCjHE#O;K@KAN_fh7U0`|67r<~iNJ wCY{W1Q{!agzd4V-&DY$KleH)LzmELmdKI;Vst08S|VcmMzZ literal 0 HcmV?d00001 diff --git a/themes/dan/img/share-googleplus.png b/themes/dan/img/share-googleplus.png new file mode 100644 index 0000000000000000000000000000000000000000..fb077cd85fc3c365507bf4d7b1f17bbb013a8af4 GIT binary patch literal 836 zcmeAS@N?(olHy`uVBq!ia0vp^LO`s;!3-qh6C`#pFfhsn_=LCux&HIEhKGlTg@yUf z-sn4LW5E1vq47x&k%)*0pg2$gko23o1t{e=XS4V8HGXq90|kSFgMs1!^S1*P`_0=D zxM(L(J%~ML6Oe=$3uFKRP_O@jZ9qn7Xedw(L>W*okO4FhNP16S3seu$;s<2R-v$(f zSnV@wgU`(Mk&%%=^C30@6@#P}Z1A z)uyvBbl!|!o#&~ZQ{wvVfae#V*rYph7Pp_*x=WSXFA(he^tJo*RP`-M=a1fc?#TOp zwP`=!f=7q-7|OGress~x-Z5==%WRQvnfOA&+(h-1rS#T!Yn2U8#Tlub zxgI;$_K}h6oA@9%4VfQrZn!ZlQ%jWId%@*|N1f^VNoE;Fyv9bC4=gHQe$G(s%c2bb zrgJhTm9`;oJ(nM5-Li&nw#>y(if`Ojx1ByB^UlM^Ps?!jg!Z)oM|Zk3%;VB3ef-B} z0_(+RmijuWtg4=wGCXpzOD8VaQJ5gc^@;V3i$0s&)KzTtPuUM0)_=jQJJ$>t+YFwr KelF{r5}E*meQs6& literal 0 HcmV?d00001 diff --git a/themes/dan/img/share-twitter.png b/themes/dan/img/share-twitter.png new file mode 100644 index 0000000000000000000000000000000000000000..26f102bdd3be46c2411187a93789f6dea5ba5fe0 GIT binary patch literal 668 zcmeAS@N?(olHy`uVBq!ia0vp^LO`s;!3-qh6C`#3sjC4#A+A8$Z_cKOh=}m;@UXBj zAn7}2b4YQGUwJb`1Skjuesed6hKBmi+6a^l4h{ygfr3BDddn3>& zzqwod=WX?yy%DSrqy`9lX0G>}x5awITz2w1qod&WAT zEf6hS@17h1dd#vU$S;^dX8KKzJ~vjzbQOJ}ElZRx7(ZI`uqnGTsHOk@f|Zi-2O{2G z^A_QGr+4V@*_m^zcw}at@-j^rB{qTUaUcvqPm|={?5)D zs^xg_z^=2`+>UO(7Io0`^!0z-g82gc=A1{Kc}nnegdQ_oBXUBebL%WQ-kW`n8Kq+B zyqY%o#;eyeb1dA#rg{0~(x-(blbD1Sx*lCK+ji+UA=dPT{tMmj?f$w#UTtO9RFUtM ze``6Myo6_T1-^Xr#nR?Y*x3!&H~c#oviH%ulGAge1b23P4QsqpaPH>Z*MHWeBpRQa zxG;Y0Q}O=B%g;J`l5c+7tT4a4rq8XjO}E&|j%V|EwL}5MqGQHQ{5z{p|4le!u*mEr z2b-PoJrReq&rZ)uJ{z-GW#ep7js5yog68gLuAHCE7W>IjSmNjYyZO8F1FHk)pI@W> aOnQ5o+1gBn_E2DKFnGH9xvX@%{b%rKKet4ws*wPiX%-F*bhiUnp64{r>&?JMeT^Yin|%gf#E?KKjKS3+fJZeA2* zqG|5DyS>9Nt;Qp!RM|vWnqSbg^SALqsy_5RJvj+RCe`A;wDpc~3dst{-K)cQ^UG?8 zDQf6C1wQhRgV?+KL}#E2F$t+zEp44KX&+`6mQ+pubaa35siHpqeOdRnvCQIz2cA)y z*09Z;eFv}b@VB{*9RvB5&E&(Q<+aW6$r;-x?s}%Sg(VfG6`vLF8B5&JcY7Xc<{DIm zYfsJoP+Z$;{4{KJWBVPt7-VQ2^b)zVcknDM>G0@yeRJE`@{!@g$0x_fQ)A;-d^PaZ z_O6mE{-0eb4i!a^tGj_9tSqbn9JD|N8Wt*QI;I;!_jx!4Md?A}5>j%SDl&@dIw({= z$+4pgon3dHb+GII8r-#RM^I+q|$SEI?;Nz7~Tfuz=CfU6xRU_)4k+pt#%i~$*pHXTLQp$mI0MQ zn9XDS{IA_$@=J!#H%g?%(ixck2JQU@ax^5J#1|@ZF)|cpH986(XiM=pqg%rEnzqOO z0=(KD!^or6Zg17HCDFF3ccn7f0}4NAM^RUvuWtMd!6X(ZQK}r{=;0hrfy|p8W<60d zCeN90aww^xN|IhOhQVZxb@hoB@2fr+Ti}mg#`HfXF}}SA0{Tjhr5S=1YB#WZTaWzs zdpw!GJ!i;X7r$e?>Geo>vmx*2@lQzE=g+(Ss}CeebxgEMcIjtMLzD)t@}%Xwk!qWZ z7L(!uNU2G&P4f{V?%OzDG*RGp=hMeuJs=b{8kE(X{qWkD<$1(i`wC|C(gZyKO6_6h zwK3g9n^c1t`DKE2lE?$!f)ZH-3TxeDQis>PMn?8wD93rEFU_anID-6+lgZBhSb;o&X{VdQDxG+`s8A? z$$jaOt>z@1IF0ev2SGk5oc?tEX+*b@rq+#P z44yi+(+jRNMG{XI4dEM!%)X*kCGWq^62KHpG2DbFqFji*HS#5Jr!XeHg})c_MV&@a z5QgoTY7>$^YRb&`dwWsTa?4pxrV$}oC*)nnjmx$1$ZO{H4!D(tilxrD$oQp7LAfQJ zpl08y5)|iR8_uW&-_vbj;RUr*{%DY?YBooo8z{tMHDmY(7GXn!5dC1)@QdVu21$E< z4M56YHzpe-;^(ta#?JR5FIjZa+Q|son6(S5ZrHwH_tx8*DGOv%(ao}pPnGdz?(k>y zTTs?Aw7HDVXU2U8Yw0(jLSJ)+L5ki=s6^R(>x?}RA@wfSq$2-eV@79gupUYzvG6?HYzZCeDHmb)U>t znZi+*r|on&=y$Gm7Hy-$X~E7dBsh;vp~B15x$XOMM4POD(b?vZx;tlYq4PWAs*arx z_1rLlrW~uNeYasWvRXl_|bdvDA?7bxzlX(egTul;<#}T!Nm9OGjR7 za)7#ZTcB$a0v@xRkR3V8<(1qyN9_*x?QCA+cKV(TtTW#;{pW5+pf>QDKeeixq>FJ8 zNPsL5tGEZ8x^|bN_<91@U9;;a$1$zycy9jAjHm25xdiP1&Pkr{DVN^6^qyiwPJ_&E zW*P>3m6b|pr#YI7@CIcqV;#wan?n>kMn7+cBI8V_c_}!S(}_GuLY$ePT|^Xb7pV-e zI=*<}>?bP6A08HUK}JK_lrh|qouVn420C47v2{nTAyC;#9zZf)Krmnj%;5vOmBWrm zO_gT-RH`n*toS@ed*9ZwX-Nxgt5y!!)6+dvncsX9E25vcsw~5rRv=la4sapo+17*& zpK1eyo!MRqvN37O->~B9ZHYbX3Y(XRr;c6pe)eFs2i-dPn3f%Rnbr~!xmYe^mLn*d z@bO{Q^>Qt0uEYj4rB#A18@Yy%@P1tQ9qR!VnDGT6>dtt}7kMi{-|Pr(p(<+9I2PEK z%0F%Z7fl=7&BbqIIrT-mK8?s`YO)o)lMo}G(ibcF&qW1Dft4YW*Bh&!T&cUWBbAE` z{za>B&vmtcU;7>xb4Z9htH>iMf!pic5n^#Eo`rHb-)LL^;FbI9wmPgTs{X`-E*Bnp zNfn)|@vO6ugHO%BtF+tN<`uCQ9);IFac*_(OSVZ3XQ#F?pWd8*aG!oUM`x* z_BmSR@2t>CZ+~!TAD12lwNClf>JZt!gp^{9AwoW@s+xce8${ZvE&-;qY%X1N|Ney#Lkojyy+33A E1Ih~lwEzGB literal 0 HcmV?d00001 diff --git a/themes/dan/img/twitter.png b/themes/dan/img/twitter.png new file mode 100644 index 0000000000000000000000000000000000000000..7bbb939881eb892f440e518084d3b118a49df2f7 GIT binary patch literal 2730 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 + + + <?php echo isset($title) ? _h($title) : config('blog.title') ?> + + + + + + + + + + + + + +
+ + +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+ +
+ + + \ No newline at end of file diff --git a/themes/dan/main.html.php b/themes/dan/main.html.php new file mode 100644 index 0000000..03a7535 --- /dev/null +++ b/themes/dan/main.html.php @@ -0,0 +1,41 @@ + + + + +
+
+

title ?>

+
- Posted in tag ?> by - Comments
+
+ + body)?> + + body, $p->url)?> +
+
+
+ + +
+ + + + + + +
+ + + + \ No newline at end of file diff --git a/themes/dan/post.html.php b/themes/dan/post.html.php new file mode 100644 index 0000000..7223f09 --- /dev/null +++ b/themes/dan/post.html.php @@ -0,0 +1,53 @@ + +
+
+ + + +

title ?>

+ + + +
+ body; ?> +
+
+ +
+ + +
+ + +
+ + +
+ +
+ + + + + + + +
+ + + + title, $p->url) ?> + + +
\ No newline at end of file diff --git a/themes/dan/profile.html.php b/themes/dan/profile.html.php new file mode 100644 index 0000000..edff022 --- /dev/null +++ b/themes/dan/profile.html.php @@ -0,0 +1,36 @@ + +
+

+
+
+

Posts by this author

+ + +
+ + + + + + +
+ \ No newline at end of file diff --git a/vendor/autoload.php b/vendor/autoload.php index 1abfffe..57fd99c 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -1,7 +1,7 @@ prefixes; + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; } public function getFallbackDirs() { - return $this->fallbackDirs; + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; } public function getClassMap() @@ -75,61 +92,130 @@ class ClassLoader } /** - * Registers a set of classes, merging with any others previously set. + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The classes prefix - * @param array|string $paths The location(s) of the classes - * @param bool $prepend Prepend the location(s) + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories */ public function add($prefix, $paths, $prepend = false) { if (!$prefix) { if ($prepend) { - $this->fallbackDirs = array_merge( + $this->fallbackDirsPsr0 = array_merge( (array) $paths, - $this->fallbackDirs + $this->fallbackDirsPsr0 ); } else { - $this->fallbackDirs = array_merge( - $this->fallbackDirs, + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, (array) $paths ); } return; } - if (!isset($this->prefixes[$prefix])) { - $this->prefixes[$prefix] = (array) $paths; + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; return; } if ($prepend) { - $this->prefixes[$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-0 base directories + * @param bool $prepend Whether to prepend the directories + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( (array) $paths, - $this->prefixes[$prefix] + $this->prefixDirsPsr4[$prefix] ); } else { - $this->prefixes[$prefix] = array_merge( - $this->prefixes[$prefix], + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], (array) $paths ); } } /** - * Registers a set of classes, replacing any others previously set. + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. * - * @param string $prefix The classes prefix - * @param array|string $paths The location(s) of the classes + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories */ public function set($prefix, $paths) { if (!$prefix) { - $this->fallbackDirs = (array) $paths; + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } - return; + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + */ + public function setPsr4($prefix, $paths) { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; } - $this->prefixes[$prefix] = (array) $paths; } /** @@ -175,7 +261,7 @@ class ClassLoader * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True, if loaded + * @return bool|null True if loaded, null otherwise */ public function loadClass($class) { @@ -191,50 +277,78 @@ class ClassLoader * * @param string $class The name of the class * - * @return string|null The path, if found + * @return string|false The path if found, false otherwise */ public function findFile($class) { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 if ('\\' == $class[0]) { $class = substr($class, 1); } + // class map lookup if (isset($this->classMap[$class])) { return $this->classMap[$class]; } + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup if (false !== $pos = strrpos($class, '\\')) { // namespaced class name - $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR; - $className = substr($class, $pos + 1); + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); } else { // PEAR-like class name - $classPath = null; - $className = $class; + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . '.php'; } - $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; - - foreach ($this->prefixes as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { - return $dir . DIRECTORY_SEPARATOR . $classPath; + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } } } } } - foreach ($this->fallbackDirs as $dir) { - if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { - return $dir . DIRECTORY_SEPARATOR . $classPath; + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; } } - if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) { + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { return $file; } + // Remember that this class does not exist. return $this->classMap[$class] = false; } } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 4a9177d..7a91153 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -1,8 +1,8 @@ $vendorDir . '/dflydev/markdown/src', - 'Suin\\RSSWriter' => $vendorDir . '/suin/php-rss-writer/Source', + 'Suin\\RSSWriter' => array($vendorDir . '/suin/php-rss-writer/Source'), + 'Michelf' => array($vendorDir . '/michelf/php-markdown'), ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php new file mode 100644 index 0000000..b265c64 --- /dev/null +++ b/vendor/composer/autoload_psr4.php @@ -0,0 +1,9 @@ + $path) { - $loader->add($namespace, $path); + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); } $classMap = require __DIR__ . '/autoload_classmap.php'; diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 2add93b..ce376d8 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,105 +1,102 @@ [ { - "name": "dflydev/markdown", - "version": "v1.0.2", - "version_normalized": "1.0.2.0", + "name": "suin/php-rss-writer", + "version": "1.2", + "version_normalized": "1.2.0.0", "source": { "type": "git", - "url": "https://github.com/dflydev/dflydev-markdown.git", - "reference": "v1.0.2" + "url": "git://github.com/suin/php-rss-writer.git", + "reference": "1.2" }, "dist": { "type": "zip", - "url": "https://github.com/dflydev/dflydev-markdown/zipball/v1.0.2", - "reference": "v1.0.2", + "url": "https://github.com/suin/php-rss-writer/zipball/1.2", + "reference": "1.2", "shasum": "" }, "require": { - "php": ">=5.3" + "php": ">=5.3.0" }, - "time": "2012-01-15 19:36:37", + "time": "2012-08-23 00:45:18", "type": "library", "installation-source": "dist", "autoload": { "psr-0": { - "dflydev\\markdown": "src" + "Suin\\RSSWriter": "Source" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "New BSD License" + "MIT" ], "authors": [ { - "name": "Dragonfly Development Inc.", - "email": "info@dflydev.com", - "homepage": "http://dflydev.com" - }, - { - "name": "Beau Simensen", - "email": "beau@dflydev.com", - "homepage": "http://beausimensen.com" - }, - { - "name": "Michel Fortin", - "homepage": "http://michelf.com" - }, - { - "name": "John Gruber", - "homepage": "http://daringfireball.net" + "name": "suin", + "email": "suinyeze@gmail.com", + "homepage": "https://www.facebook.com/suinyeze", + "role": "Developer, Renaming Specialist" } ], - "description": "PHP Markdown & Extra", - "homepage": "http://github.com/dflydev/dflydev-markdown", + "description": "Yet another simple RSS writer library for PHP 5.3 or later.", + "homepage": "https://github.com/suin/php-rss-writer", "keywords": [ - "markdown" + "feed", + "generator", + "rss", + "writer" ] }, { - "name": "suin/php-rss-writer", - "version": "1.2", - "version_normalized": "1.2.0.0", + "name": "michelf/php-markdown", + "version": "dev-lib", + "version_normalized": "dev-lib", "source": { "type": "git", - "url": "git://github.com/suin/php-rss-writer.git", - "reference": "1.2" + "url": "https://github.com/michelf/php-markdown.git", + "reference": "6f952ee180e9bd345f3dd6005aa11e0f5dcbd1b8" }, "dist": { "type": "zip", - "url": "https://github.com/suin/php-rss-writer/zipball/1.2", - "reference": "1.2", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/6f952ee180e9bd345f3dd6005aa11e0f5dcbd1b8", + "reference": "6f952ee180e9bd345f3dd6005aa11e0f5dcbd1b8", "shasum": "" }, "require": { "php": ">=5.3.0" }, - "time": "2012-08-23 00:45:18", + "time": "2013-11-29 21:49:31", "type": "library", - "installation-source": "dist", + "extra": { + "branch-alias": { + "dev-lib": "1.4.x-dev" + } + }, + "installation-source": "source", "autoload": { "psr-0": { - "Suin\\RSSWriter": "Source" + "Michelf": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "suin", - "email": "suinyeze@gmail.com", - "homepage": "https://www.facebook.com/suinyeze", - "role": "Developer, Renaming Specialist" + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "http://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "http://daringfireball.net/" } ], - "description": "Yet another simple RSS writer library for PHP 5.3 or later.", - "homepage": "https://github.com/suin/php-rss-writer", + "description": "PHP Markdown", + "homepage": "http://michelf.ca/projects/php-markdown/", "keywords": [ - "feed", - "generator", - "rss", - "writer" + "markdown" ] } ] diff --git a/vendor/dflydev/markdown/.gitignore b/vendor/dflydev/markdown/.gitignore deleted file mode 100644 index 7579f74..0000000 --- a/vendor/dflydev/markdown/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -vendor -composer.lock diff --git a/vendor/dflydev/markdown/.travis.yml b/vendor/dflydev/markdown/.travis.yml deleted file mode 100644 index 7f51331..0000000 --- a/vendor/dflydev/markdown/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: php -php: - - 5.3 - - 5.4 -before_script: - - wget -nc http://getcomposer.org/composer.phar - - php composer.phar update diff --git a/vendor/dflydev/markdown/README.md b/vendor/dflydev/markdown/README.md deleted file mode 100644 index e4feffa..0000000 --- a/vendor/dflydev/markdown/README.md +++ /dev/null @@ -1,98 +0,0 @@ -PHP Markdown & Extra -==================== - -An updated and stripped version of the original [PHP Markdown](http://michelf.com/projects/php-markdown/) -by [Michel Fortin](http://michelf.com/). Works quite well with PSR-0 -autoloaders and is [Composer](http://packagist.org/) friendly. - - -Changes from the official PHP Markdown & Extra ----------------------------------------------- - -The initial pass at updating PHP Markdown & Extra left the core of -the code more or less intact but the changes to the organization -and naming were quite substantial. This effectively makes this package -a hard fork from Markdown 1.0.1n and MarkdownExtra 1.2.4. - -Updated in the following ways: - - * Moved parser classes into their own files - * Using PHP 5.3 namespaces - * Following [PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) standards - * Replaced `@define` configuration variables with class `const` variables - * Integrated with [Travis CI](http://travis-ci.org/) - * Made [Composer](http://packagist.org/) friendly - -Stripped in the following ways: - - * No more embedded plugin code (WordPress, bBlog, etc.) - * No more top level function calls (`Markdown()`, etc.) - -Last synced with: - - * PHP Markdown v1.0.1o - * PHP Markdown Extra v1.2.5 - - -Requirements ------------- - - * PHP 5.3+ - - -Usage ------ - -Simple usage for the standard Markdown ([details](http://michelf.com/projects/php-markdown/)) parser: - - Hello World - $markdownParser->transformMarkdown("#Hello World"); - -Simple usage for the Markdown Extra ([details](http://michelf.com/projects/php-markdown/extra/)) parser: - - Hello World - $markdownParser->transformMarkdown("#Hello World"); - - -License -------- - -This library is licensed under the New BSD License - see the LICENSE file for details. - - -Community ---------- - -If you have questions or want to help out, join us in the -[#dflydev](irc://irc.freenode.net/#dflydev) channel on irc.freenode.net. - - -Not Invented Here ------------------ - -The original [PHP Markdown](http://michelf.com/projects/php-markdown/) was -quite excellent but was not as easy to use as it could be in more modern PHP -applications. Having started to use [Composer](http://packagist.org/) for a -few newer applications that needed to transform Markdown, I decided to strip -and update the original PHP Markdown so that it could be more easily managed -by the likes of Composer. - -All of the initial work done for this library (which I can only assume -was quite substantial after having looked at the code) was done by -[Michel Fortin](http://michelf.com/) during the original port from Perl to -PHP. - -If you do not need to install PHP Markdown by way of Composer or need to -leverage PSR-0 autoloading, I suggest you continue to use the official and -likely more stable and well used original version of -[PHP Markdown](http://michelf.com/projects/php-markdown/) \ No newline at end of file diff --git a/vendor/dflydev/markdown/composer.json b/vendor/dflydev/markdown/composer.json deleted file mode 100644 index 1516899..0000000 --- a/vendor/dflydev/markdown/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "dflydev/markdown", - "type": "library", - "description": "PHP Markdown & Extra", - "homepage": "http://github.com/dflydev/dflydev-markdown", - "keywords": ["markdown"], - "license": "New BSD License", - "authors": [ - { - "name": "Dragonfly Development Inc.", - "email": "info@dflydev.com", - "homepage": "http://dflydev.com" - }, - { - "name": "Beau Simensen", - "email": "beau@dflydev.com", - "homepage": "http://beausimensen.com" - }, - { - "name": "Michel Fortin", - "homepage": "http://michelf.com" - }, - { - "name": "John Gruber", - "homepage": "http://daringfireball.net" - } - ], - "require": { - "php": ">=5.3" - }, - "autoload": { - "psr-0": { "dflydev\\markdown": "src" } - } -} diff --git a/vendor/dflydev/markdown/phpunit.xml.dist b/vendor/dflydev/markdown/phpunit.xml.dist deleted file mode 100644 index 5f092ed..0000000 --- a/vendor/dflydev/markdown/phpunit.xml.dist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - ./tests/dflydev/ - - - - - - ./src/dflydev/ - - ./src/dflydev/*/resources - - - - - diff --git a/vendor/dflydev/markdown/src/dflydev/markdown/IMarkdownParser.php b/vendor/dflydev/markdown/src/dflydev/markdown/IMarkdownParser.php deleted file mode 100644 index 3febb14..0000000 --- a/vendor/dflydev/markdown/src/dflydev/markdown/IMarkdownParser.php +++ /dev/null @@ -1,23 +0,0 @@ -escape_chars .= ':|'; - - # Insert extra document, block, and span transformations. - # Parent constructor will do the sorting. - $this->document_gamut += array( - "doFencedCodeBlocks" => 5, - "stripFootnotes" => 15, - "stripAbbreviations" => 25, - "appendFootnotes" => 50, - ); - $this->block_gamut += array( - "doFencedCodeBlocks" => 5, - "doTables" => 15, - "doDefLists" => 45, - ); - $this->span_gamut += array( - "doFootnotes" => 5, - "doAbbreviations" => 70, - ); - - parent::__construct($configuration); - } - - /** - * (non-PHPdoc) - * @see dflydev\markdown.IMarkdownParser::configureMarkdownParser() - */ - public function configureMarkdownParser($key, $value) - { - switch($key) { - case self::CONFIG_FOOTNOTE_LINK_TITLE: - $this->fn_link_title = $value; - break; - case self::CONFIG_FOOTNOTE_LINK_CLASS: - $this->fn_link_class = $value; - break; - case self::CONFIG_FOOTNOTE_BACKLINK_TITLE: - $this->fn_backlink_title = $value; - break; - case self::CONFIG_FOOTNOTE_BACKLINK_CLASS: - $this->fn_backlink_class = $value; - break; - default: - // Try to handle this in our parent. - parent::configureMarkdownParser($key, $value); - break; - } - // - } - - # Extra variables used during extra transformations. - var $footnotes = array(); - var $footnotes_ordered = array(); - var $abbr_desciptions = array(); - var $abbr_word_re = ''; - - # Give the current footnote number. - var $footnote_counter = 1; - - - function setup() { - # - # Setting up Extra-specific variables. - # - parent::setup(); - - $this->footnotes = array(); - $this->footnotes_ordered = array(); - $this->abbr_desciptions = array(); - $this->abbr_word_re = ''; - $this->footnote_counter = 1; - - foreach ($this->predef_abbr as $abbr_word => $abbr_desc) { - if ($this->abbr_word_re) - $this->abbr_word_re .= '|'; - $this->abbr_word_re .= preg_quote($abbr_word); - $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); - } - } - - function teardown() { - # - # Clearing Extra-specific variables. - # - $this->footnotes = array(); - $this->footnotes_ordered = array(); - $this->abbr_desciptions = array(); - $this->abbr_word_re = ''; - - parent::teardown(); - } - - - ### HTML Block Parser ### - - # Tags that are always treated as block tags: - var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend'; - - # Tags treated as block tags only if the opening tag is alone on it's line: - var $context_block_tags_re = 'script|noscript|math|ins|del'; - - # Tags where markdown="1" default to span mode: - var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; - - # Tags which must not have their contents modified, no matter where - # they appear: - var $clean_tags_re = 'script|math'; - - # Tags that do not need to be closed. - var $auto_close_tags_re = 'hr|img'; - - - function hashHTMLBlocks($text) { - # - # Hashify HTML Blocks and "clean tags". - # - # We only want to do this for block-level HTML tags, such as headers, - # lists, and tables. That's because we still want to wrap

s around - # "paragraphs" that are wrapped in non-block-level tags, such as anchors, - # phrase emphasis, and spans. The list of tags we're looking for is - # hard-coded. - # - # This works by calling _HashHTMLBlocks_InMarkdown, which then calls - # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" - # attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back - # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag. - # These two functions are calling each other. It's recursive! - # - # - # Call the HTML-in-Markdown hasher. - # - list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text); - - return $text; - } - function _hashHTMLBlocks_inMarkdown($text, $indent = 0, - $enclosing_tag_re = '', $span = false) - { - # - # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags. - # - # * $indent is the number of space to be ignored when checking for code - # blocks. This is important because if we don't take the indent into - # account, something like this (which looks right) won't work as expected: - # - #

- #
- # Hello World. <-- Is this a Markdown code block or text? - #
<-- Is this a Markdown code block or a real tag? - #
- # - # If you don't like this, just don't indent the tag on which - # you apply the markdown="1" attribute. - # - # * If $enclosing_tag_re is not empty, stops at the first unmatched closing - # tag with that name. Nested tags supported. - # - # * If $span is true, text inside must treated as span. So any double - # newline will be replaced by a single newline so that it does not create - # paragraphs. - # - # Returns an array of that form: ( processed text , remaining text ) - # - if ($text === '') return array('', ''); - - # Regex to check for the presense of newlines around a block tag. - $newline_before_re = '/(?:^\n?|\n\n)*$/'; - $newline_after_re = - '{ - ^ # Start of text following the tag. - (?>[ ]*)? # Optional comment. - [ ]*\n # Must be followed by newline. - }xs'; - - # Regex to match any tag. - $block_tag_re = - '{ - ( # $2: Capture hole tag. - # Tag name. - '.$this->block_tags_re.' | - '.$this->context_block_tags_re.' | - '.$this->clean_tags_re.' | - (?!\s)'.$enclosing_tag_re.' - ) - (?: - (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name. - (?> - ".*?" | # Double quotes (can contain `>`) - \'.*?\' | # Single quotes (can contain `>`) - .+? # Anything but quotes and `>`. - )*? - )? - > # End of tag. - | - # HTML Comment - | - <\?.*?\?> | <%.*?%> # Processing instruction - | - # CData Block - | - # Code span marker - `+ - '. ( !$span ? ' # If not in span. - | - # Indented code block - (?: ^[ ]*\n | ^ | \n[ ]*\n ) - [ ]{'.($indent+4).'}[^\n]* \n - (?> - (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n - )* - | - # Fenced code block marker - (?> ^ | \n ) - [ ]{0,'.($indent).'}~~~+[ ]*\n - ' : '' ). ' # End (if not is span). - ) - }xs'; - - - $depth = 0; # Current depth inside the tag tree. - $parsed = ""; # Parsed text that will be returned. - - # - # Loop through every tag until we find the closing tag of the parent - # or loop until reaching the end of text if no parent tag specified. - # - do { - # - # Split the text using the first $tag_match pattern found. - # Text before pattern will be first in the array, text after - # pattern will be at the end, and between will be any catches made - # by the pattern. - # - $parts = preg_split($block_tag_re, $text, 2, - PREG_SPLIT_DELIM_CAPTURE); - - # If in Markdown span mode, add a empty-string span-level hash - # after each newline to prevent triggering any block element. - if ($span) { - $void = $this->hashPart("", ':'); - $newline = "$void\n"; - $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; - } - - $parsed .= $parts[0]; # Text before current tag. - - # If end of $text has been reached. Stop loop. - if (count($parts) < 3) { - $text = ""; - break; - } - - $tag = $parts[1]; # Tag to handle. - $text = $parts[2]; # Remaining text after current tag. - $tag_re = preg_quote($tag); # For use in a regular expression. - - # - # Check for: Code span marker - # - if ($tag{0} == "`") { - # Find corresponding end marker. - $tag_re = preg_quote($tag); - if (preg_match('{^(?>.+?|\n(?!\n))*?(?.*\n)+?[ ]{0,'.($indent).'}'.$tag_re.'[ ]*\n}', $text, - $matches)) - { - # End marker found: pass text unchanged until marker. - $parsed .= $tag . $matches[0]; - $text = substr($text, strlen($matches[0])); - } - else { - # No end marker: just skip it. - $parsed .= $tag; - } - } - # - # Check for: Indented code block. - # - else if ($tag{0} == "\n" || $tag{0} == " ") { - # Indented code block: pass it unchanged, will be handled - # later. - $parsed .= $tag; - } - # - # Check for: Opening Block level tag or - # Opening Context Block tag (like ins and del) - # used as a block tag (tag is alone on it's line). - # - else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) || - ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) && - preg_match($newline_before_re, $parsed) && - preg_match($newline_after_re, $text) ) - ) - { - # Need to parse tag and following text using the HTML parser. - list($block_text, $text) = - $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true); - - # Make sure it stays outside of any paragraph by adding newlines. - $parsed .= "\n\n$block_text\n\n"; - } - # - # Check for: Clean tag (like script, math) - # HTML Comments, processing instructions. - # - else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) || - $tag{1} == '!' || $tag{1} == '?') - { - # Need to parse tag and following text using the HTML parser. - # (don't check for markdown attribute) - list($block_text, $text) = - $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false); - - $parsed .= $block_text; - } - # - # Check for: Tag with same name as enclosing tag. - # - else if ($enclosing_tag_re !== '' && - # Same name as enclosing tag. - preg_match('{^= 0); - - return array($parsed, $text); - } - function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) { - # - # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags. - # - # * Calls $hash_method to convert any blocks. - # * Stops when the first opening tag closes. - # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed. - # (it is not inside clean tags) - # - # Returns an array of that form: ( processed text , remaining text ) - # - if ($text === '') return array('', ''); - - # Regex to match `markdown` attribute inside of a tag. - $markdown_attr_re = ' - { - \s* # Eat whitespace before the `markdown` attribute - markdown - \s*=\s* - (?> - (["\']) # $1: quote delimiter - (.*?) # $2: attribute value - \1 # matching delimiter - | - ([^\s>]*) # $3: unquoted attribute value - ) - () # $4: make $3 always defined (avoid warnings) - }xs'; - - # Regex to match any tag. - $tag_re = '{ - ( # $2: Capture hole tag. - - ".*?" | # Double quotes (can contain `>`) - \'.*?\' | # Single quotes (can contain `>`) - .+? # Anything but quotes and `>`. - )*? - )? - > # End of tag. - | - # HTML Comment - | - <\?.*?\?> | <%.*?%> # Processing instruction - | - # CData Block - ) - }xs'; - - $original_text = $text; # Save original text in case of faliure. - - $depth = 0; # Current depth inside the tag tree. - $block_text = ""; # Temporary text holder for current text. - $parsed = ""; # Parsed text that will be returned. - - # - # Get the name of the starting tag. - # (This pattern makes $base_tag_name_re safe without quoting.) - # - if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) - $base_tag_name_re = $matches[1]; - - # - # Loop through every tag until we find the corresponding closing tag. - # - do { - # - # Split the text using the first $tag_match pattern found. - # Text before pattern will be first in the array, text after - # pattern will be at the end, and between will be any catches made - # by the pattern. - # - $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); - - if (count($parts) < 3) { - # - # End of $text reached with unbalenced tag(s). - # In that case, we return original text unchanged and pass the - # first character as filtered to prevent an infinite loop in the - # parent function. - # - return array($original_text{0}, substr($original_text, 1)); - } - - $block_text .= $parts[0]; # Text before current tag. - $tag = $parts[1]; # Tag to handle. - $text = $parts[2]; # Remaining text after current tag. - - # - # Check for: Auto-close tag (like
) - # Comments and Processing Instructions. - # - if (preg_match('{^auto_close_tags_re.')\b}', $tag) || - $tag{1} == '!' || $tag{1} == '?') - { - # Just add the tag to the block as if it was text. - $block_text .= $tag; - } - else { - # - # Increase/decrease nested tag count. Only do so if - # the tag's name match base tag's. - # - if (preg_match('{^mode = $attr_m[2] . $attr_m[3]; - $span_mode = $this->mode == 'span' || $this->mode != 'block' && - preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag); - - # Calculate indent before tag. - if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) { - $strlen = $this->utf8_strlen; - $indent = $strlen($matches[1], 'UTF-8'); - } else { - $indent = 0; - } - - # End preceding block with this tag. - $block_text .= $tag; - $parsed .= $this->$hash_method($block_text); - - # Get enclosing tag name for the ParseMarkdown function. - # (This pattern makes $tag_name_re safe without quoting.) - preg_match('/^<([\w:$]*)\b/', $tag, $matches); - $tag_name_re = $matches[1]; - - # Parse the content using the HTML-in-Markdown parser. - list ($block_text, $text) - = $this->_hashHTMLBlocks_inMarkdown($text, $indent, - $tag_name_re, $span_mode); - - # Outdent markdown text. - if ($indent > 0) { - $block_text = preg_replace("/^[ ]{1,$indent}/m", "", - $block_text); - } - - # Append tag content to parsed text. - if (!$span_mode) $parsed .= "\n\n$block_text\n\n"; - else $parsed .= "$block_text"; - - # Start over a new block. - $block_text = ""; - } - else $block_text .= $tag; - } - - } while ($depth > 0); - - # - # Hash last block text that wasn't processed inside the loop. - # - $parsed .= $this->$hash_method($block_text); - - return array($parsed, $text); - } - - - function hashClean($text) { - # - # Called whenever a tag must be hashed when a function insert a "clean" tag - # in $text, it pass through this function and is automaticaly escaped, - # blocking invalid nested overlap. - # - return $this->hashPart($text, 'C'); - } - - - function doHeaders($text) { - # - # Redefined to add id attribute support. - # - # Setext-style headers: - # Header 1 {#header1} - # ======== - # - # Header 2 {#header2} - # -------- - # - $text = preg_replace_callback( - '{ - (^.+?) # $1: Header text - (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # $2: Id attribute - [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer - }mx', - array(&$this, '_doHeaders_callback_setext'), $text); - - # atx-style headers: - # # Header 1 {#header1} - # ## Header 2 {#header2} - # ## Header 2 with closing hashes ## {#header3} - # ... - # ###### Header 6 {#header2} - # - $text = preg_replace_callback('{ - ^(\#{1,6}) # $1 = string of #\'s - [ ]* - (.+?) # $2 = Header text - [ ]* - \#* # optional closing #\'s (not counted) - (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute - [ ]* - \n+ - }xm', - array(&$this, '_doHeaders_callback_atx'), $text); - - return $text; - } - function _doHeaders_attr($attr) { - if (empty($attr)) return ""; - return " id=\"$attr\""; - } - function _doHeaders_callback_setext($matches) { - if ($matches[3] == '-' && preg_match('{^- }', $matches[1])) - return $matches[0]; - $level = $matches[3]{0} == '=' ? 1 : 2; - $attr = $this->_doHeaders_attr($id =& $matches[2]); - $block = "".$this->runSpanGamut($matches[1]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - function _doHeaders_callback_atx($matches) { - $level = strlen($matches[1]); - $attr = $this->_doHeaders_attr($id =& $matches[3]); - $block = "".$this->runSpanGamut($matches[2]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - - function doTables($text) { - # - # Form HTML tables. - # - $less_than_tab = $this->tab_width - 1; - # - # Find tables with leading pipe. - # - # | Header 1 | Header 2 - # | -------- | -------- - # | Cell 1 | Cell 2 - # | Cell 3 | Cell 4 - # - $text = preg_replace_callback(' - { - ^ # Start of a line - [ ]{0,'.$less_than_tab.'} # Allowed whitespace. - [|] # Optional leading pipe (present) - (.+) \n # $1: Header row (at least one pipe) - - [ ]{0,'.$less_than_tab.'} # Allowed whitespace. - [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline - - ( # $3: Cells - (?> - [ ]* # Allowed whitespace. - [|] .* \n # Row content. - )* - ) - (?=\n|\Z) # Stop at final double newline. - }xm', - array(&$this, '_doTable_leadingPipe_callback'), $text); - - # - # Find tables without leading pipe. - # - # Header 1 | Header 2 - # -------- | -------- - # Cell 1 | Cell 2 - # Cell 3 | Cell 4 - # - $text = preg_replace_callback(' - { - ^ # Start of a line - [ ]{0,'.$less_than_tab.'} # Allowed whitespace. - (\S.*[|].*) \n # $1: Header row (at least one pipe) - - [ ]{0,'.$less_than_tab.'} # Allowed whitespace. - ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline - - ( # $3: Cells - (?> - .* [|] .* \n # Row content - )* - ) - (?=\n|\Z) # Stop at final double newline. - }xm', - array(&$this, '_DoTable_callback'), $text); - - return $text; - } - function _doTable_leadingPipe_callback($matches) { - $head = $matches[1]; - $underline = $matches[2]; - $content = $matches[3]; - - # Remove leading pipe for each row. - $content = preg_replace('/^ *[|]/m', '', $content); - - return $this->_doTable_callback(array($matches[0], $head, $underline, $content)); - } - function _doTable_callback($matches) { - $head = $matches[1]; - $underline = $matches[2]; - $content = $matches[3]; - - # Remove any tailing pipes for each line. - $head = preg_replace('/[|] *$/m', '', $head); - $underline = preg_replace('/[|] *$/m', '', $underline); - $content = preg_replace('/[|] *$/m', '', $content); - - # Reading alignement from header underline. - $separators = preg_split('/ *[|] */', $underline); - foreach ($separators as $n => $s) { - if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"'; - else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"'; - else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"'; - else $attr[$n] = ''; - } - - # Parsing span elements, including code spans, character escapes, - # and inline HTML tags, so that pipes inside those gets ignored. - $head = $this->parseSpan($head); - $headers = preg_split('/ *[|] */', $head); - $col_count = count($headers); - - # Write column headers. - $text = "\n"; - $text .= "\n"; - $text .= "\n"; - foreach ($headers as $n => $header) - $text .= " ".$this->runSpanGamut(trim($header))."\n"; - $text .= "\n"; - $text .= "\n"; - - # Split content by row. - $rows = explode("\n", trim($content, "\n")); - - $text .= "\n"; - foreach ($rows as $row) { - # Parsing span elements, including code spans, character escapes, - # and inline HTML tags, so that pipes inside those gets ignored. - $row = $this->parseSpan($row); - - # Split row by cell. - $row_cells = preg_split('/ *[|] */', $row, $col_count); - $row_cells = array_pad($row_cells, $col_count, ''); - - $text .= "\n"; - foreach ($row_cells as $n => $cell) - $text .= " ".$this->runSpanGamut(trim($cell))."\n"; - $text .= "\n"; - } - $text .= "\n"; - $text .= "
"; - - return $this->hashBlock($text) . "\n"; - } - - - function doDefLists($text) { - # - # Form HTML definition lists. - # - $less_than_tab = $this->tab_width - 1; - - # Re-usable pattern to match any entire dl list: - $whole_list_re = '(?> - ( # $1 = whole list - ( # $2 - [ ]{0,'.$less_than_tab.'} - ((?>.*\S.*\n)+) # $3 = defined term - \n? - [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition - ) - (?s:.+?) - ( # $4 - \z - | - \n{2,} - (?=\S) - (?! # Negative lookahead for another term - [ ]{0,'.$less_than_tab.'} - (?: \S.*\n )+? # defined term - \n? - [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition - ) - (?! # Negative lookahead for another definition - [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition - ) - ) - ) - )'; // mx - - $text = preg_replace_callback('{ - (?>\A\n?|(?<=\n\n)) - '.$whole_list_re.' - }mx', - array(&$this, '_doDefLists_callback'), $text); - - return $text; - } - function _doDefLists_callback($matches) { - # Re-usable patterns to match list item bullets and number markers: - $list = $matches[1]; - - # Turn double returns into triple returns, so that we can make a - # paragraph for the last item in a list, if necessary: - $result = trim($this->processDefListItems($list)); - $result = "
\n" . $result . "\n
"; - return $this->hashBlock($result) . "\n\n"; - } - - - function processDefListItems($list_str) { - # - # Process the contents of a single definition list, splitting it - # into individual term and definition list items. - # - $less_than_tab = $this->tab_width - 1; - - # trim trailing blank lines: - $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); - - # Process definition terms. - $list_str = preg_replace_callback('{ - (?>\A\n?|\n\n+) # leading line - ( # definition terms = $1 - [ ]{0,'.$less_than_tab.'} # leading whitespace - (?![:][ ]|[ ]) # negative lookahead for a definition - # mark (colon) or more whitespace. - (?> \S.* \n)+? # actual term (not whitespace). - ) - (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed - # with a definition mark. - }xm', - array(&$this, '_processDefListItems_callback_dt'), $list_str); - - # Process actual definitions. - $list_str = preg_replace_callback('{ - \n(\n+)? # leading line = $1 - ( # marker space = $2 - [ ]{0,'.$less_than_tab.'} # whitespace before colon - [:][ ]+ # definition mark (colon) - ) - ((?s:.+?)) # definition text = $3 - (?= \n+ # stop at next definition mark, - (?: # next term or end of text - [ ]{0,'.$less_than_tab.'} [:][ ] | -
| \z - ) - ) - }xm', - array(&$this, '_processDefListItems_callback_dd'), $list_str); - - return $list_str; - } - function _processDefListItems_callback_dt($matches) { - $terms = explode("\n", trim($matches[1])); - $text = ''; - foreach ($terms as $term) { - $term = $this->runSpanGamut(trim($term)); - $text .= "\n
" . $term . "
"; - } - return $text . "\n"; - } - function _processDefListItems_callback_dd($matches) { - $leading_line = $matches[1]; - $marker_space = $matches[2]; - $def = $matches[3]; - - if ($leading_line || preg_match('/\n{2,}/', $def)) { - # Replace marker with the appropriate whitespace indentation - $def = str_repeat(' ', strlen($marker_space)) . $def; - $def = $this->runBlockGamut($this->outdent($def . "\n\n")); - $def = "\n". $def ."\n"; - } - else { - $def = rtrim($def); - $def = $this->runSpanGamut($this->outdent($def)); - } - - return "\n
" . $def . "
\n"; - } - - - function doFencedCodeBlocks($text) { - # - # Adding the fenced code block syntax to regular Markdown: - # - # ~~~ - # Code block - # ~~~ - # - $less_than_tab = $this->tab_width; - - $text = preg_replace_callback('{ - (?:\n|\A) - # 1: Opening marker - ( - ~{3,} # Marker: three tilde or more. - ) - [ ]* \n # Whitespace and newline following marker. - - # 2: Content - ( - (?> - (?!\1 [ ]* \n) # Not a closing marker. - .*\n+ - )+ - ) - - # Closing marker. - \1 [ ]* \n - }xm', - array(&$this, '_doFencedCodeBlocks_callback'), $text); - - return $text; - } - function _doFencedCodeBlocks_callback($matches) { - $codeblock = $matches[2]; - $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); - $codeblock = preg_replace_callback('/^\n+/', - array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); - $codeblock = "
$codeblock
"; - return "\n\n".$this->hashBlock($codeblock)."\n\n"; - } - function _doFencedCodeBlocks_newlines($matches) { - return str_repeat("empty_element_suffix", - strlen($matches[0])); - } - - - # - # Redefining emphasis markers so that emphasis by underscore does not - # work in the middle of a word. - # - var $em_relist = array( - '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? tags - # - # Strip leading and trailing lines: - $text = preg_replace('/\A\n+|\n+\z/', '', $text); - - $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); - - # - # Wrap

tags and unhashify HTML blocks - # - foreach ($grafs as $key => $value) { - $value = trim($this->runSpanGamut($value)); - - # Check if this should be enclosed in a paragraph. - # Clean tag hashes & block tag hashes are left alone. - $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); - - if ($is_p) { - $value = "

$value

"; - } - $grafs[$key] = $value; - } - - # Join grafs in one text, then unhash HTML tags. - $text = implode("\n\n", $grafs); - - # Finish by removing any tag hashes still present in $text. - $text = $this->unhash($text); - - return $text; - } - - - ### Footnotes - - function stripFootnotes($text) { - # - # Strips link definitions from text, stores the URLs and titles in - # hash references. - # - $less_than_tab = $this->tab_width - 1; - - # Link defs are in the form: [^id]: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1 - [ ]* - \n? # maybe *one* newline - ( # text = $2 (no blank lines allowed) - (?: - .+ # actual text - | - \n # newlines but - (?!\[\^.+?\]:\s)# negative lookahead for footnote marker. - (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed - # by non-indented content - )* - ) - }xm', - array(&$this, '_stripFootnotes_callback'), - $text); - return $text; - } - function _stripFootnotes_callback($matches) { - $note_id = $this->fn_id_prefix . $matches[1]; - $this->footnotes[$note_id] = $this->outdent($matches[2]); - return ''; # String that will replace the block - } - - - function doFootnotes($text) { - # - # Replace footnote references in $text [^id] with a special text-token - # which will be replaced by the actual footnote marker in appendFootnotes. - # - if (!$this->in_anchor) { - $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text); - } - return $text; - } - - - function appendFootnotes($text) { - # - # Append footnote list to text. - # - $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', - array(&$this, '_appendFootnotes_callback'), $text); - - if (!empty($this->footnotes_ordered)) { - $text .= "\n\n"; - $text .= "
\n"; - $text .= "empty_element_suffix ."\n"; - $text .= "
    \n\n"; - - $attr = " rev=\"footnote\""; - if ($this->fn_backlink_class != "") { - $class = $this->fn_backlink_class; - $class = $this->encodeAttribute($class); - $attr .= " class=\"$class\""; - } - if ($this->fn_backlink_title != "") { - $title = $this->fn_backlink_title; - $title = $this->encodeAttribute($title); - $attr .= " title=\"$title\""; - } - $num = 0; - - while (!empty($this->footnotes_ordered)) { - $footnote = reset($this->footnotes_ordered); - $note_id = key($this->footnotes_ordered); - unset($this->footnotes_ordered[$note_id]); - - $footnote .= "\n"; # Need to append newline before parsing. - $footnote = $this->runBlockGamut("$footnote\n"); - $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', - array(&$this, '_appendFootnotes_callback'), $footnote); - - $attr = str_replace("%%", ++$num, $attr); - $note_id = $this->encodeAttribute($note_id); - - # Add backlink to last paragraph; create new paragraph if needed. - $backlink = ""; - if (preg_match('{

    $}', $footnote)) { - $footnote = substr($footnote, 0, -4) . " $backlink

    "; - } else { - $footnote .= "\n\n

    $backlink

    "; - } - - $text .= "
  1. \n"; - $text .= $footnote . "\n"; - $text .= "
  2. \n\n"; - } - - $text .= "
\n"; - $text .= "
"; - } - return $text; - } - function _appendFootnotes_callback($matches) { - $node_id = $this->fn_id_prefix . $matches[1]; - - # Create footnote marker only if it has a corresponding footnote *and* - # the footnote hasn't been used by another marker. - if (isset($this->footnotes[$node_id])) { - # Transfert footnote content to the ordered list. - $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id]; - unset($this->footnotes[$node_id]); - - $num = $this->footnote_counter++; - $attr = " rel=\"footnote\""; - if ($this->fn_link_class != "") { - $class = $this->fn_link_class; - $class = $this->encodeAttribute($class); - $attr .= " class=\"$class\""; - } - if ($this->fn_link_title != "") { - $title = $this->fn_link_title; - $title = $this->encodeAttribute($title); - $attr .= " title=\"$title\""; - } - - $attr = str_replace("%%", $num, $attr); - $node_id = $this->encodeAttribute($node_id); - - return - "". - "$num". - ""; - } - - return "[^".$matches[1]."]"; - } - - - ### Abbreviations ### - - function stripAbbreviations($text) { - # - # Strips abbreviations from text, stores titles in hash references. - # - $less_than_tab = $this->tab_width - 1; - - # Link defs are in the form: [id]*: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1 - (.*) # text = $2 (no blank lines allowed) - }xm', - array(&$this, '_stripAbbreviations_callback'), - $text); - return $text; - } - function _stripAbbreviations_callback($matches) { - $abbr_word = $matches[1]; - $abbr_desc = $matches[2]; - if ($this->abbr_word_re) - $this->abbr_word_re .= '|'; - $this->abbr_word_re .= preg_quote($abbr_word); - $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); - return ''; # String that will replace the block - } - - - function doAbbreviations($text) { - # - # Find defined abbreviations in text and wrap them in elements. - # - if ($this->abbr_word_re) { - // cannot use the /x modifier because abbr_word_re may - // contain significant spaces: - $text = preg_replace_callback('{'. - '(?abbr_word_re.')'. - '(?![\w\x1A])'. - '}', - array(&$this, '_doAbbreviations_callback'), $text); - } - return $text; - } - function _doAbbreviations_callback($matches) { - $abbr = $matches[0]; - if (isset($this->abbr_desciptions[$abbr])) { - $desc = $this->abbr_desciptions[$abbr]; - if (empty($desc)) { - return $this->hashPart("$abbr"); - } else { - $desc = $this->encodeAttribute($desc); - return $this->hashPart("$abbr"); - } - } else { - return $matches[0]; - } - } - -} - - -/* - -PHP Markdown Extra -================== - -Description ------------ - -This is a PHP port of the original Markdown formatter written in Perl -by John Gruber. This special "Extra" version of PHP Markdown features -further enhancements to the syntax for making additional constructs -such as tables and definition list. - -Markdown is a text-to-HTML filter; it translates an easy-to-read / -easy-to-write structured text format into HTML. Markdown's text format -is most similar to that of plain text email, and supports features such -as headers, *emphasis*, code blocks, blockquotes, and links. - -Markdown's syntax is designed not as a generic markup language, but -specifically to serve as a front-end to (X)HTML. You can use span-level -HTML tags anywhere in a Markdown document, and you can use block level -HTML tags (like
and as well). - -For more information about Markdown's syntax, see: - - - - -Bugs ----- - -To file bug reports please send email to: - - - -Please include with your report: (1) the example input; (2) the output you -expected; (3) the output Markdown actually produced. - - -Version History ---------------- - -See the readme file for detailed release notes for this version. - - -Copyright and License ---------------------- - -PHP Markdown & Extra -Copyright (c) 2004-2009 Michel Fortin - -All rights reserved. - -Based on Markdown -Copyright (c) 2003-2006 John Gruber - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -* Neither the name "Markdown" nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as -is" and any express or implied warranties, including, but not limited -to, the implied warranties of merchantability and fitness for a -particular purpose are disclaimed. In no event shall the copyright owner -or contributors be liable for any direct, indirect, incidental, special, -exemplary, or consequential damages (including, but not limited to, -procurement of substitute goods or services; loss of use, data, or -profits; or business interruption) however caused and on any theory of -liability, whether in contract, strict liability, or tort (including -negligence or otherwise) arising in any way out of the use of this -software, even if advised of the possibility of such damage. - -*/ -?> \ No newline at end of file diff --git a/vendor/dflydev/markdown/src/dflydev/markdown/MarkdownParser.php b/vendor/dflydev/markdown/src/dflydev/markdown/MarkdownParser.php deleted file mode 100644 index 8e82d74..0000000 --- a/vendor/dflydev/markdown/src/dflydev/markdown/MarkdownParser.php +++ /dev/null @@ -1,1529 +0,0 @@ -"; - - /** - * Default tab width for code blocks - * @var integer - */ - const DEFAULT_TAB_WIDTH = 4; - - /** - * Configuration key for changing the empty element suffix - * @var string - */ - const CONFIG_EMPTY_ELEMENT_SUFFIX = 'config.emptyElementSuffix'; - - /** - * Configuration key for changing the tab width for code blocks - * @var string - */ - const CONFIG_TAB_WIDTH = 'config.tabWidth'; - - # Regex to match balanced [brackets]. - # Needed to insert a maximum bracked depth while converting to PHP. - var $nested_brackets_depth = 6; - var $nested_brackets_re; - - var $nested_url_parenthesis_depth = 4; - var $nested_url_parenthesis_re; - - # Table of hash values for escaped characters: - var $escape_chars = '\`*_{}[]()>#+-.!'; - var $escape_chars_re; - - # Change to ">" for HTML output. - var $empty_element_suffix = self::DEFAULT_EMPTY_ELEMENT_SUFFIX; - var $tab_width = self::DEFAULT_TAB_WIDTH; - - # Change to `true` to disallow markup or entities. - var $no_markup = false; - var $no_entities = false; - - # Predefined urls and titles for reference links and images. - var $predef_urls = array(); - var $predef_titles = array(); - - - function __construct(array $configuration = null) - { - # - # Constructor function. Initialize appropriate member variables. - # - $this->_initDetab(); - $this->prepareItalicsAndBold(); - - $this->nested_brackets_re = - str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). - str_repeat('\])*', $this->nested_brackets_depth); - - $this->nested_url_parenthesis_re = - str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). - str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); - - $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; - - # Sort document, block, and span gamut in ascendent priority order. - asort($this->document_gamut); - asort($this->block_gamut); - asort($this->span_gamut); - if ($configuration) { - foreach ($configuration as $key => $value) { - $this->configureMarkdownParser($key, $value); - } - } - } - - /** - * Configure parser - * @param string $key - * @param mixed $value - */ - public function configureMarkdownParser($key, $value) - { - switch($key) { - case self::CONFIG_TAB_WIDTH: - $this->tab_width = $value; - break; - case self::CONFIG_EMPTY_ELEMENT_SUFFIX: - $this->empty_element_suffix = $value; - break; - default: - // TODO: Warning? - break; - } - // - } - - /** - * (non-PHPdoc) - * @see dflydev\markdown.IMarkdownParser::transformMarkdown() - */ - public function transformMarkdown($text) - { - return $this->transform($text); - } - - - # Internal hashes used during transformation. - var $urls = array(); - var $titles = array(); - var $html_hashes = array(); - - # Status flag to avoid invalid nesting. - var $in_anchor = false; - - - function setup() { - # - # Called before the transformation process starts to setup parser - # states. - # - # Clear global hashes. - $this->urls = $this->predef_urls; - $this->titles = $this->predef_titles; - $this->html_hashes = array(); - - $in_anchor = false; - } - - function teardown() { - # - # Called after the transformation process to clear any variable - # which may be taking up memory unnecessarly. - # - $this->urls = array(); - $this->titles = array(); - $this->html_hashes = array(); - } - - - function transform($text) { - # - # Main function. Performs some preprocessing on the input text - # and pass it through the document gamut. - # - $this->setup(); - - # Remove UTF-8 BOM and marker character in input, if present. - $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); - - # Standardize line endings: - # DOS to Unix and Mac to Unix - $text = preg_replace('{\r\n?}', "\n", $text); - - # Make sure $text ends with a couple of newlines: - $text .= "\n\n"; - - # Convert all tabs to spaces. - $text = $this->detab($text); - - # Turn block-level HTML blocks into hash entries - $text = $this->hashHTMLBlocks($text); - - # Strip any lines consisting only of spaces and tabs. - # This makes subsequent regexen easier to write, because we can - # match consecutive blank lines with /\n+/ instead of something - # contorted like /[ ]*\n+/ . - $text = preg_replace('/^[ ]+$/m', '', $text); - - # Run document gamut methods. - foreach ($this->document_gamut as $method => $priority) { - $text = $this->$method($text); - } - - $this->teardown(); - - return $text . "\n"; - } - - var $document_gamut = array( - # Strip link definitions, store in hashes. - "stripLinkDefinitions" => 20, - - "runBasicBlockGamut" => 30, - ); - - - function stripLinkDefinitions($text) { - # - # Strips link definitions from text, stores the URLs and titles in - # hash references. - # - $less_than_tab = $this->tab_width - 1; - - # Link defs are in the form: ^[id]: url "optional title" - $text = preg_replace_callback('{ - ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 - [ ]* - \n? # maybe *one* newline - [ ]* - (?: - <(.+?)> # url = $2 - | - (\S+?) # url = $3 - ) - [ ]* - \n? # maybe one newline - [ ]* - (?: - (?<=\s) # lookbehind for whitespace - ["(] - (.*?) # title = $4 - [")] - [ ]* - )? # title is optional - (?:\n+|\Z) - }xm', - array(&$this, '_stripLinkDefinitions_callback'), - $text); - return $text; - } - function _stripLinkDefinitions_callback($matches) { - $link_id = strtolower($matches[1]); - $url = $matches[2] == '' ? $matches[3] : $matches[2]; - $this->urls[$link_id] = $url; - $this->titles[$link_id] =& $matches[4]; - return ''; # String that will replace the block - } - - - function hashHTMLBlocks($text) { - if ($this->no_markup) return $text; - - $less_than_tab = $this->tab_width - 1; - - # Hashify HTML blocks: - # We only want to do this for block-level HTML tags, such as headers, - # lists, and tables. That's because we still want to wrap

s around - # "paragraphs" that are wrapped in non-block-level tags, such as anchors, - # phrase emphasis, and spans. The list of tags we're looking for is - # hard-coded: - # - # * List "a" is made of tags which can be both inline or block-level. - # These will be treated block-level when the start tag is alone on - # its line, otherwise they're not matched here and will be taken as - # inline later. - # * List "b" is made of tags which are always block-level; - # - $block_tags_a_re = 'ins|del'; - $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. - 'script|noscript|form|fieldset|iframe|math'; - - # Regular expression for the content of a block tag. - $nested_tags_level = 4; - $attr = ' - (?> # optional tag attributes - \s # starts with whitespace - (?> - [^>"/]+ # text outside quotes - | - /+(?!>) # slash not followed by ">" - | - "[^"]*" # text inside double quotes (tolerate ">") - | - \'[^\']*\' # text inside single quotes (tolerate ">") - )* - )? - '; - $content = - str_repeat(' - (?> - [^<]+ # content without tag - | - <\2 # nested opening tag - '.$attr.' # attributes - (?> - /> - | - >', $nested_tags_level). # end of opening tag - '.*?'. # last level nested tag content - str_repeat(' - # closing nested tag - ) - | - <(?!/\2\s*> # other tags with a different name - ) - )*', - $nested_tags_level); - $content2 = str_replace('\2', '\3', $content); - - # First, look for nested blocks, e.g.: - #

- #
- # tags for inner block must be indented. - #
- #
- # - # The outermost tags must start at the left margin for this to match, and - # the inner nested divs must be indented. - # We need to do this before the next, more liberal match, because the next - # match will start at the first `
` and stop at the first `
`. - $text = preg_replace_callback('{(?> - (?> - (?<=\n\n) # Starting after a blank line - | # or - \A\n? # the beginning of the doc - ) - ( # save in $1 - - # Match from `\n` to `\n`, handling nested tags - # in between. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_b_re.')# start tag = $2 - '.$attr.'> # attributes followed by > and \n - '.$content.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special version for tags of group a. - - [ ]{0,'.$less_than_tab.'} - <('.$block_tags_a_re.')# start tag = $3 - '.$attr.'>[ ]*\n # attributes followed by > - '.$content2.' # content, support nesting - # the matching end tag - [ ]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - - | # Special case just for
. It was easier to make a special - # case than to make the other regex more complicated. - - [ ]{0,'.$less_than_tab.'} - <(hr) # start tag = $2 - '.$attr.' # attributes - /?> # the matching end tag - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # Special case for standalone HTML comments: - - [ ]{0,'.$less_than_tab.'} - (?s: - - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - | # PHP and ASP-style processor instructions ( - ) - [ ]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - - ) - )}Sxmi', - array(&$this, '_hashHTMLBlocks_callback'), - $text); - - return $text; - } - function _hashHTMLBlocks_callback($matches) { - $text = $matches[1]; - $key = $this->hashBlock($text); - return "\n\n$key\n\n"; - } - - - function hashPart($text, $boundary = 'X') { - # - # Called whenever a tag must be hashed when a function insert an atomic - # element in the text stream. Passing $text to through this function gives - # a unique text-token which will be reverted back when calling unhash. - # - # The $boundary argument specify what character should be used to surround - # the token. By convension, "B" is used for block elements that needs not - # to be wrapped into paragraph tags at the end, ":" is used for elements - # that are word separators and "X" is used in the general case. - # - # Swap back any tag hash found in $text so we do not have to `unhash` - # multiple times at the end. - $text = $this->unhash($text); - - # Then hash the block. - static $i = 0; - $key = "$boundary\x1A" . ++$i . $boundary; - $this->html_hashes[$key] = $text; - return $key; # String that will replace the tag. - } - - - function hashBlock($text) { - # - # Shortcut function for hashPart with block-level boundaries. - # - return $this->hashPart($text, 'B'); - } - - - var $block_gamut = array( - # - # These are all the transformations that form block-level - # tags like paragraphs, headers, and list items. - # - "doHeaders" => 10, - "doHorizontalRules" => 20, - - "doLists" => 40, - "doCodeBlocks" => 50, - "doBlockQuotes" => 60, - ); - - function runBlockGamut($text) { - # - # Run block gamut tranformations. - # - # We need to escape raw HTML in Markdown source before doing anything - # else. This need to be done for each block, and not only at the - # begining in the Markdown function since hashed blocks can be part of - # list items and could have been indented. Indented blocks would have - # been seen as a code block in a previous pass of hashHTMLBlocks. - $text = $this->hashHTMLBlocks($text); - - return $this->runBasicBlockGamut($text); - } - - function runBasicBlockGamut($text) { - # - # Run block gamut tranformations, without hashing HTML blocks. This is - # useful when HTML blocks are known to be already hashed, like in the first - # whole-document pass. - # - foreach ($this->block_gamut as $method => $priority) { - $text = $this->$method($text); - } - - # Finally form paragraph and restore hashed blocks. - $text = $this->formParagraphs($text); - - return $text; - } - - - function doHorizontalRules($text) { - # Do Horizontal Rules: - return preg_replace( - '{ - ^[ ]{0,3} # Leading space - ([-*_]) # $1: First marker - (?> # Repeated marker group - [ ]{0,2} # Zero, one, or two spaces. - \1 # Marker character - ){2,} # Group repeated at least twice - [ ]* # Tailing spaces - $ # End of line. - }mx', - "\n".$this->hashBlock("empty_element_suffix")."\n", - $text); - } - - - var $span_gamut = array( - # - # These are all the transformations that occur *within* block-level - # tags like paragraphs, headers, and list items. - # - # Process character escapes, code spans, and inline HTML - # in one shot. - "parseSpan" => -30, - - # Process anchor and image tags. Images must come first, - # because ![foo][f] looks like an anchor. - "doImages" => 10, - "doAnchors" => 20, - - # Make links out of things like `` - # Must come after doAnchors, because you can use < and > - # delimiters in inline links like [this](). - "doAutoLinks" => 30, - "encodeAmpsAndAngles" => 40, - - "doItalicsAndBold" => 50, - "doHardBreaks" => 60, - ); - - function runSpanGamut($text) { - # - # Run span gamut tranformations. - # - foreach ($this->span_gamut as $method => $priority) { - $text = $this->$method($text); - } - - return $text; - } - - - function doHardBreaks($text) { - # Do hard breaks: - return preg_replace_callback('/ {2,}\n/', - array(&$this, '_doHardBreaks_callback'), $text); - } - function _doHardBreaks_callback($matches) { - return $this->hashPart("empty_element_suffix\n"); - } - - - function doAnchors($text) { - # - # Turn Markdown link shortcuts into XHTML tags. - # - if ($this->in_anchor) return $text; - $this->in_anchor = true; - - # - # First, handle reference-style links: [link text] [id] - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - ) - }xs', - array(&$this, '_doAnchors_reference_callback'), $text); - - # - # Next, inline-style links: [link text](url "optional title") - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ('.$this->nested_brackets_re.') # link text = $2 - \] - \( # literal paren - [ \n]* - (?: - <(.+?)> # href = $3 - | - ('.$this->nested_url_parenthesis_re.') # href = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # Title = $7 - \6 # matching quote - [ \n]* # ignore any spaces/tabs between closing quote and ) - )? # title is optional - \) - ) - }xs', - array(&$this, '_doAnchors_inline_callback'), $text); - - # - # Last, handle reference-style shortcuts: [link text] - # These must come last in case you've also got [link text][1] - # or [link text](/foo) - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - \[ - ([^\[\]]+) # link text = $2; can\'t contain [ or ] - \] - ) - }xs', - array(&$this, '_doAnchors_reference_callback'), $text); - - $this->in_anchor = false; - return $text; - } - function _doAnchors_reference_callback($matches) { - $whole_match = $matches[1]; - $link_text = $matches[2]; - $link_id =& $matches[3]; - - if ($link_id == "") { - # for shortcut links like [this][] or [this]. - $link_id = $link_text; - } - - # lower-case and turn embedded newlines into spaces - $link_id = strtolower($link_id); - $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); - - if (isset($this->urls[$link_id])) { - $url = $this->urls[$link_id]; - $url = $this->encodeAttribute($url); - - $result = "titles[$link_id] ) ) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - $result = $this->hashPart($result); - } - else { - $result = $whole_match; - } - return $result; - } - function _doAnchors_inline_callback($matches) { - $whole_match = $matches[1]; - $link_text = $this->runSpanGamut($matches[2]); - $url = $matches[3] == '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - $url = $this->encodeAttribute($url); - - $result = "encodeAttribute($title); - $result .= " title=\"$title\""; - } - - $link_text = $this->runSpanGamut($link_text); - $result .= ">$link_text"; - - return $this->hashPart($result); - } - - - function doImages($text) { - # - # Turn Markdown image shortcuts into tags. - # - # - # First, handle reference-style labeled images: ![alt text][id] - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - - ) - }xs', - array(&$this, '_doImages_reference_callback'), $text); - - # - # Next, handle inline images: ![alt text](url "optional title") - # Don't forget: encode * and _ - # - $text = preg_replace_callback('{ - ( # wrap whole match in $1 - !\[ - ('.$this->nested_brackets_re.') # alt text = $2 - \] - \s? # One optional whitespace character - \( # literal paren - [ \n]* - (?: - <(\S*)> # src url = $3 - | - ('.$this->nested_url_parenthesis_re.') # src url = $4 - ) - [ \n]* - ( # $5 - ([\'"]) # quote char = $6 - (.*?) # title = $7 - \6 # matching quote - [ \n]* - )? # title is optional - \) - ) - }xs', - array(&$this, '_doImages_inline_callback'), $text); - - return $text; - } - function _doImages_reference_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $link_id = strtolower($matches[3]); - - if ($link_id == "") { - $link_id = strtolower($alt_text); # for shortcut links like ![this][]. - } - - $alt_text = $this->encodeAttribute($alt_text); - if (isset($this->urls[$link_id])) { - $url = $this->encodeAttribute($this->urls[$link_id]); - $result = "\"$alt_text\"";titles[$link_id])) { - $title = $this->titles[$link_id]; - $title = $this->encodeAttribute($title); - $result .= " title=\"$title\""; - } - $result .= $this->empty_element_suffix; - $result = $this->hashPart($result); - } - else { - # If there's no such link ID, leave intact: - $result = $whole_match; - } - - return $result; - } - function _doImages_inline_callback($matches) { - $whole_match = $matches[1]; - $alt_text = $matches[2]; - $url = $matches[3] == '' ? $matches[4] : $matches[3]; - $title =& $matches[7]; - - $alt_text = $this->encodeAttribute($alt_text); - $url = $this->encodeAttribute($url); - $result = "\"$alt_text\"";encodeAttribute($title); - $result .= " title=\"$title\""; # $title already quoted - } - $result .= $this->empty_element_suffix; - - return $this->hashPart($result); - } - - - function doHeaders($text) { - # Setext-style headers: - # Header 1 - # ======== - # - # Header 2 - # -------- - # - $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', - array(&$this, '_doHeaders_callback_setext'), $text); - - # atx-style headers: - # # Header 1 - # ## Header 2 - # ## Header 2 with closing hashes ## - # ... - # ###### Header 6 - # - $text = preg_replace_callback('{ - ^(\#{1,6}) # $1 = string of #\'s - [ ]* - (.+?) # $2 = Header text - [ ]* - \#* # optional closing #\'s (not counted) - \n+ - }xm', - array(&$this, '_doHeaders_callback_atx'), $text); - - return $text; - } - function _doHeaders_callback_setext($matches) { - # Terrible hack to check we haven't found an empty list item. - if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) - return $matches[0]; - - $level = $matches[2]{0} == '=' ? 1 : 2; - $block = "".$this->runSpanGamut($matches[1]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - function _doHeaders_callback_atx($matches) { - $level = strlen($matches[1]); - $block = "".$this->runSpanGamut($matches[2]).""; - return "\n" . $this->hashBlock($block) . "\n\n"; - } - - - function doLists($text) { - # - # Form HTML ordered (numbered) and unordered (bulleted) lists. - # - $less_than_tab = $this->tab_width - 1; - - # Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; - - $markers_relist = array( - $marker_ul_re => $marker_ol_re, - $marker_ol_re => $marker_ul_re, - ); - - foreach ($markers_relist as $marker_re => $other_marker_re) { - # Re-usable pattern to match any entirel ul or ol list: - $whole_list_re = ' - ( # $1 = whole list - ( # $2 - ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces - ('.$marker_re.') # $4 = first list item marker - [ ]+ - ) - (?s:.+?) - ( # $5 - \z - | - \n{2,} - (?=\S) - (?! # Negative lookahead for another list item marker - [ ]* - '.$marker_re.'[ ]+ - ) - | - (?= # Lookahead for another kind of list - \n - \3 # Must have the same indentation - '.$other_marker_re.'[ ]+ - ) - ) - ) - '; // mx - - # We use a different prefix before nested lists than top-level lists. - # See extended comment in _ProcessListItems(). - - if ($this->list_level) { - $text = preg_replace_callback('{ - ^ - '.$whole_list_re.' - }mx', - array(&$this, '_doLists_callback'), $text); - } - else { - $text = preg_replace_callback('{ - (?:(?<=\n)\n|\A\n?) # Must eat the newline - '.$whole_list_re.' - }mx', - array(&$this, '_doLists_callback'), $text); - } - } - - return $text; - } - function _doLists_callback($matches) { - # Re-usable patterns to match list item bullets and number markers: - $marker_ul_re = '[*+-]'; - $marker_ol_re = '\d+[\.]'; - $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; - - $list = $matches[1]; - $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; - - $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); - - $list .= "\n"; - $result = $this->processListItems($list, $marker_any_re); - - $result = $this->hashBlock("<$list_type>\n" . $result . ""); - return "\n". $result ."\n\n"; - } - - var $list_level = 0; - - function processListItems($list_str, $marker_any_re) { - # - # Process the contents of a single ordered or unordered list, splitting it - # into individual list items. - # - # The $this->list_level global keeps track of when we're inside a list. - # Each time we enter a list, we increment it; when we leave a list, - # we decrement. If it's zero, we're not in a list anymore. - # - # We do this because when we're not inside a list, we want to treat - # something like this: - # - # I recommend upgrading to version - # 8. Oops, now this line is treated - # as a sub-list. - # - # As a single paragraph, despite the fact that the second line starts - # with a digit-period-space sequence. - # - # Whereas when we're inside a list (or sub-list), that line will be - # treated as the start of a sub-list. What a kludge, huh? This is - # an aspect of Markdown's syntax that's hard to parse perfectly - # without resorting to mind-reading. Perhaps the solution is to - # change the syntax rules such that sub-lists must start with a - # starting cardinal number; e.g. "1." or "a.". - - $this->list_level++; - - # trim trailing blank lines: - $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); - - $list_str = preg_replace_callback('{ - (\n)? # leading line = $1 - (^[ ]*) # leading whitespace = $2 - ('.$marker_any_re.' # list marker and space = $3 - (?:[ ]+|(?=\n)) # space only required if item is not empty - ) - ((?s:.*?)) # list item text = $4 - (?:(\n+(?=\n))|\n) # tailing blank line = $5 - (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) - }xm', - array(&$this, '_processListItems_callback'), $list_str); - - $this->list_level--; - return $list_str; - } - function _processListItems_callback($matches) { - $item = $matches[4]; - $leading_line =& $matches[1]; - $leading_space =& $matches[2]; - $marker_space = $matches[3]; - $tailing_blank_line =& $matches[5]; - - if ($leading_line || $tailing_blank_line || - preg_match('/\n{2,}/', $item)) - { - # Replace marker with the appropriate whitespace indentation - $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; - $item = $this->runBlockGamut($this->outdent($item)."\n"); - } - else { - # Recursion for sub-lists: - $item = $this->doLists($this->outdent($item)); - $item = preg_replace('/\n+$/', '', $item); - $item = $this->runSpanGamut($item); - } - - return "
  • " . $item . "
  • \n"; - } - - - function doCodeBlocks($text) { - # - # Process Markdown `
    ` blocks.
    -	#
    -		$text = preg_replace_callback('{
    -				(?:\n\n|\A\n?)
    -				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    -				  (?>
    -					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    -					.*\n+
    -				  )+
    -				)
    -				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    -			}xm',
    -			array(&$this, '_doCodeBlocks_callback'), $text);
    -
    -		return $text;
    -	}
    -	function _doCodeBlocks_callback($matches) {
    -		$codeblock = $matches[1];
    -
    -		$codeblock = $this->outdent($codeblock);
    -		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    -
    -		# trim leading newlines and trailing newlines
    -		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    -
    -		$codeblock = "
    $codeblock\n
    "; - return "\n\n".$this->hashBlock($codeblock)."\n\n"; - } - - - function makeCodeSpan($code) { - # - # Create a code span markup for $code. Called from handleSpanToken. - # - $code = htmlspecialchars(trim($code), ENT_NOQUOTES); - return $this->hashPart("$code"); - } - - - var $em_relist = array( - '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) { - foreach ($this->strong_relist as $strong => $strong_re) { - # Construct list of allowed token expressions. - $token_relist = array(); - if (isset($this->em_strong_relist["$em$strong"])) { - $token_relist[] = $this->em_strong_relist["$em$strong"]; - } - $token_relist[] = $em_re; - $token_relist[] = $strong_re; - - # Construct master expression from list. - $token_re = '{('. implode('|', $token_relist) .')}'; - $this->em_strong_prepared_relist["$em$strong"] = $token_re; - } - } - } - - function doItalicsAndBold($text) { - $token_stack = array(''); - $text_stack = array(''); - $em = ''; - $strong = ''; - $tree_char_em = false; - - while (1) { - # - # Get prepared regular expression for seraching emphasis tokens - # in current context. - # - $token_re = $this->em_strong_prepared_relist["$em$strong"]; - - # - # Each loop iteration search for the next emphasis token. - # Each token is then passed to handleSpanToken. - # - $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); - $text_stack[0] .= $parts[0]; - $token =& $parts[1]; - $text =& $parts[2]; - - if (empty($token)) { - # Reached end of text span: empty stack without emitting. - # any more emphasis. - while ($token_stack[0]) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - } - break; - } - - $token_len = strlen($token); - if ($tree_char_em) { - # Reached closing marker while inside a three-char emphasis. - if ($token_len == 3) { - # Three-char closing marker, close em and strong. - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - $strong = ''; - } else { - # Other closing marker: close one em or strong and - # change current token state to match the other - $token_stack[0] = str_repeat($token{0}, 3-$token_len); - $tag = $token_len == 2 ? "strong" : "em"; - $span = $text_stack[0]; - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] = $this->hashPart($span); - $$tag = ''; # $$tag stands for $em or $strong - } - $tree_char_em = false; - } else if ($token_len == 3) { - if ($em) { - # Reached closing marker for both em and strong. - # Closing strong marker: - for ($i = 0; $i < 2; ++$i) { - $shifted_token = array_shift($token_stack); - $tag = strlen($shifted_token) == 2 ? "strong" : "em"; - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "<$tag>$span"; - $text_stack[0] .= $this->hashPart($span); - $$tag = ''; # $$tag stands for $em or $strong - } - } else { - # Reached opening three-char emphasis marker. Push on token - # stack; will be handled by the special condition above. - $em = $token{0}; - $strong = "$em$em"; - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $tree_char_em = true; - } - } else if ($token_len == 2) { - if ($strong) { - # Unwind any dangling emphasis marker: - if (strlen($token_stack[0]) == 1) { - $text_stack[1] .= array_shift($token_stack); - $text_stack[0] .= array_shift($text_stack); - } - # Closing strong marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $strong = ''; - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $strong = $token; - } - } else { - # Here $token_len == 1 - if ($em) { - if (strlen($token_stack[0]) == 1) { - # Closing emphasis marker: - array_shift($token_stack); - $span = array_shift($text_stack); - $span = $this->runSpanGamut($span); - $span = "$span"; - $text_stack[0] .= $this->hashPart($span); - $em = ''; - } else { - $text_stack[0] .= $token; - } - } else { - array_unshift($token_stack, $token); - array_unshift($text_stack, ''); - $em = $token; - } - } - } - return $text_stack[0]; - } - - - function doBlockQuotes($text) { - $text = preg_replace_callback('/ - ( # Wrap whole match in $1 - (?> - ^[ ]*>[ ]? # ">" at the start of a line - .+\n # rest of the first line - (.+\n)* # subsequent consecutive lines - \n* # blanks - )+ - ) - /xm', - array(&$this, '_doBlockQuotes_callback'), $text); - - return $text; - } - function _doBlockQuotes_callback($matches) { - $bq = $matches[1]; - # trim one level of quoting - trim whitespace-only lines - $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); - $bq = $this->runBlockGamut($bq); # recurse - - $bq = preg_replace('/^/m', " ", $bq); - # These leading spaces cause problem with
     content, 
    -		# so we need to fix that:
    -		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', - array(&$this, '_doBlockQuotes_callback2'), $bq); - - return "\n". $this->hashBlock("
    \n$bq\n
    ")."\n\n"; - } - function _doBlockQuotes_callback2($matches) { - $pre = $matches[1]; - $pre = preg_replace('/^ /m', '', $pre); - return $pre; - } - - - function formParagraphs($text) { - # - # Params: - # $text - string to process with html

    tags - # - # Strip leading and trailing lines: - $text = preg_replace('/\A\n+|\n+\z/', '', $text); - - $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); - - # - # Wrap

    tags and unhashify HTML blocks - # - foreach ($grafs as $key => $value) { - if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { - # Is a paragraph. - $value = $this->runSpanGamut($value); - $value = preg_replace('/^([ ]*)/', "

    ", $value); - $value .= "

    "; - $grafs[$key] = $this->unhash($value); - } - else { - # Is a block. - # Modify elements of @grafs in-place... - $graf = $value; - $block = $this->html_hashes[$graf]; - $graf = $block; -// if (preg_match('{ -// \A -// ( # $1 =
    tag -//
    ]* -// \b -// markdown\s*=\s* ([\'"]) # $2 = attr quote char -// 1 -// \2 -// [^>]* -// > -// ) -// ( # $3 = contents -// .* -// ) -// (
    ) # $4 = closing tag -// \z -// }xs', $block, $matches)) -// { -// list(, $div_open, , $div_content, $div_close) = $matches; -// -// # We can't call Markdown(), because that resets the hash; -// # that initialization code should be pulled into its own sub, though. -// $div_content = $this->hashHTMLBlocks($div_content); -// -// # Run document gamut methods on the content. -// foreach ($this->document_gamut as $method => $priority) { -// $div_content = $this->$method($div_content); -// } -// -// $div_open = preg_replace( -// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); -// -// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; -// } - $grafs[$key] = $graf; - } - } - - return implode("\n\n", $grafs); - } - - - function encodeAttribute($text) { - # - # Encode text for a double-quoted HTML attribute. This function - # is *not* suitable for attributes enclosed in single quotes. - # - $text = $this->encodeAmpsAndAngles($text); - $text = str_replace('"', '"', $text); - return $text; - } - - - function encodeAmpsAndAngles($text) { - # - # Smart processing for ampersands and angle brackets that need to - # be encoded. Valid character entities are left alone unless the - # no-entities mode is set. - # - if ($this->no_entities) { - $text = str_replace('&', '&', $text); - } else { - # Ampersand-encoding based entirely on Nat Irons's Amputator - # MT plugin: - $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', - '&', $text);; - } - # Encode remaining <'s - $text = str_replace('<', '<', $text); - - return $text; - } - - - function doAutoLinks($text) { - $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', - array(&$this, '_doAutoLinks_url_callback'), $text); - - # Email addresses: - $text = preg_replace_callback('{ - < - (?:mailto:)? - ( - (?: - [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ - | - ".*?" - ) - \@ - (?: - [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ - | - \[[\d.a-fA-F:]+\] # IPv4 & IPv6 - ) - ) - > - }xi', - array(&$this, '_doAutoLinks_email_callback'), $text); - - return $text; - } - function _doAutoLinks_url_callback($matches) { - $url = $this->encodeAttribute($matches[1]); - $link = "$url"; - return $this->hashPart($link); - } - function _doAutoLinks_email_callback($matches) { - $address = $matches[1]; - $link = $this->encodeEmailAddress($address); - return $this->hashPart($link); - } - - - function encodeEmailAddress($addr) { - # - # Input: an email address, e.g. "foo@example.com" - # - # Output: the email address as a mailto link, with each character - # of the address encoded as either a decimal or hex entity, in - # the hopes of foiling most address harvesting spam bots. E.g.: - # - #

    foo@exampl - # e.com

    - # - # Based by a filter by Matthew Wickline, posted to BBEdit-Talk. - # With some optimizations by Milian Wolff. - # - $addr = "mailto:" . $addr; - $chars = preg_split('/(? $char) { - $ord = ord($char); - # Ignore non-ascii chars. - if ($ord < 128) { - $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. - # roughly 10% raw, 45% hex, 45% dec - # '@' *must* be encoded. I insist. - if ($r > 90 && $char != '@') /* do nothing */; - else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; - else $chars[$key] = '&#'.$ord.';'; - } - } - - $addr = implode('', $chars); - $text = implode('', array_slice($chars, 7)); # text without `mailto:` - $addr = "$text"; - - return $addr; - } - - - function parseSpan($str) { - # - # Take the string $str and parse it into tokens, hashing embeded HTML, - # escaped characters and handling code spans. - # - $output = ''; - - $span_re = '{ - ( - \\\\'.$this->escape_chars_re.' - | - (?no_markup ? '' : ' - | - # comment - | - <\?.*?\?> | <%.*?%> # processing instruction - | - <[/!$]?[-a-zA-Z0-9:_]+ # regular tags - (?> - \s - (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* - )? - > - ').' - ) - }xs'; - - while (1) { - # - # Each loop iteration seach for either the next tag, the next - # openning code span marker, or the next escaped character. - # Each token is then passed to handleSpanToken. - # - $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); - - # Create token from text preceding tag. - if ($parts[0] != "") { - $output .= $parts[0]; - } - - # Check if we reach the end. - if (isset($parts[1])) { - $output .= $this->handleSpanToken($parts[1], $parts[2]); - $str = $parts[2]; - } - else { - break; - } - } - - return $output; - } - - - function handleSpanToken($token, &$str) { - # - # Handle $token provided by parseSpan by determining its nature and - # returning the corresponding value that should replace it. - # - switch ($token{0}) { - case "\\": - return $this->hashPart("&#". ord($token{1}). ";"); - case "`": - # Search for end marker in remaining text. - if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', - $str, $matches)) - { - $str = $matches[2]; - $codespan = $this->makeCodeSpan($matches[1]); - return $this->hashPart($codespan); - } - return $token; // return as text since no ending marker found. - default: - return $this->hashPart($token); - } - } - - - function outdent($text) { - # - # Remove one level of line-leading tabs or spaces - # - return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); - } - - - # String length function for detab. `_initDetab` will create a function to - # hanlde UTF-8 if the default function does not exist. - var $utf8_strlen = 'mb_strlen'; - - function detab($text) { - # - # Replace tabs with the appropriate amount of space. - # - # For each line we separate the line in blocks delemited by - # tab characters. Then we reconstruct every line by adding the - # appropriate number of space between each blocks. - - $text = preg_replace_callback('/^.*\t.*$/m', - array(&$this, '_detab_callback'), $text); - - return $text; - } - function _detab_callback($matches) { - $line = $matches[0]; - $strlen = $this->utf8_strlen; # strlen function for UTF-8. - - # Split in blocks. - $blocks = explode("\t", $line); - # Add each blocks to the line. - $line = $blocks[0]; - unset($blocks[0]); # Do not add first block twice. - foreach ($blocks as $block) { - # Calculate amount of space, insert spaces, insert block. - $amount = $this->tab_width - - $strlen($line, 'UTF-8') % $this->tab_width; - $line .= str_repeat(" ", $amount) . $block; - } - return $line; - } - function _initDetab() { - # - # Check for the availability of the function in the `utf8_strlen` property - # (initially `mb_strlen`). If the function is not available, create a - # function that will loosely count the number of UTF-8 characters with a - # regular expression. - # - if (function_exists($this->utf8_strlen)) return; - $this->utf8_strlen = create_function('$text', 'return preg_match_all( - "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", - $text, $m);'); - } - - - function unhash($text) { - # - # Swap back in all the tags hashed by _HashHTMLBlocks. - # - return preg_replace_callback('/(.)\x1A[0-9]+\1/', - array(&$this, '_unhash_callback'), $text); - } - function _unhash_callback($matches) { - return $this->html_hashes[$matches[0]]; - } - -} diff --git a/vendor/dflydev/markdown/tests/bootstrap.php b/vendor/dflydev/markdown/tests/bootstrap.php deleted file mode 100644 index 6f8f442..0000000 --- a/vendor/dflydev/markdown/tests/bootstrap.php +++ /dev/null @@ -1,12 +0,0 @@ -add('dflydev\\tests\\markdown', 'tests'); diff --git a/vendor/dflydev/markdown/tests/dflydev/tests/markdown/MarkdownExtraParserTest.php b/vendor/dflydev/markdown/tests/dflydev/tests/markdown/MarkdownExtraParserTest.php deleted file mode 100644 index 70895d5..0000000 --- a/vendor/dflydev/markdown/tests/dflydev/tests/markdown/MarkdownExtraParserTest.php +++ /dev/null @@ -1,34 +0,0 @@ -createParser(); - $html = $markdownParser->transformMarkdown('#Hello World'); - $this->assertEquals("

    Hello World

    \n", $html, 'Simple H1 works'); - } - - /** - * Test tab width for code blocks - */ - public function testTabWidth() - { - $markdownParser = $this->createParser(); - $html = $markdownParser->transformMarkdown(' Hello World'); - $this->assertEquals("
    Hello World\n
    \n", $html, 'Default 4 space tab code block works'); - $this->configureTabWidth($markdownParser, 6); - $html = $markdownParser->transformMarkdown(' Hello World'); - $this->assertEquals("

    Hello World

    \n", $html, 'Default 4 space tab code block not triggered when tab width set to 6'); - $html = $markdownParser->transformMarkdown(' Hello World'); - $this->assertEquals("
    Hello World\n
    \n", $html, 'Setting 6 space tab code block (via method) works'); - $markdownParser = $this->createParser(array($this->configKeyTabWidth => 8)); - $html = $markdownParser->transformMarkdown(' Hello World'); - $this->assertEquals("
    Hello World\n
    \n", $html, 'Setting 8 space tab code block (via constructor) works'); - } - - /** - * Configure a Markdown parser for a specific tab width - * @param \dflydev\markdown\MarkdownParser $markdownParser - * @param integer $width - */ - protected function configureTabWidth(MarkdownParser $markdownParser, $width) - { - $markdownParser->configureMarkdownParser($this->configKeyTabWidth, $width); - } - -} diff --git a/vendor/dflydev/markdown/LICENSE b/vendor/michelf/php-markdown/License.md similarity index 58% rename from vendor/dflydev/markdown/LICENSE rename to vendor/michelf/php-markdown/License.md index bd719dd..027becb 100644 --- a/vendor/dflydev/markdown/LICENSE +++ b/vendor/michelf/php-markdown/License.md @@ -1,40 +1,36 @@ -PHP Markdown & Extra -Copyright (c) 2011, Dragonfly Development Inc -All rights reserved. - -Based on PHP Markdown & Extra -Copyright (c) 2004-2009 Michel Fortin - -All rights reserved. - -Based on Markdown -Copyright (c) 2003-2006 John Gruber - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -* Neither the name "Markdown" nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as -is" and any express or implied warranties, including, but not limited -to, the implied warranties of merchantability and fitness for a -particular purpose are disclaimed. In no event shall the copyright owner -or contributors be liable for any direct, indirect, incidental, special, -exemplary, or consequential damages (including, but not limited to, -procurement of substitute goods or services; loss of use, data, or -profits; or business interruption) however caused and on any theory of -liability, whether in contract, strict liability, or tort (including -negligence or otherwise) arising in any way out of the use of this -software, even if advised of the possibility of such damage. +PHP Markdown Lib +Copyright (c) 2004-2013 Michel Fortin + +All rights reserved. + +Based on Markdown +Copyright (c) 2003-2006 John Gruber + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name "Markdown" nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +This software is provided by the copyright holders and contributors "as +is" and any express or implied warranties, including, but not limited +to, the implied warranties of merchantability and fitness for a +particular purpose are disclaimed. In no event shall the copyright owner +or contributors be liable for any direct, indirect, incidental, special, +exemplary, or consequential damages (including, but not limited to, +procurement of substitute goods or services; loss of use, data, or +profits; or business interruption) however caused and on any theory of +liability, whether in contract, strict liability, or tort (including +negligence or otherwise) arising in any way out of the use of this +software, even if advised of the possibility of such damage. diff --git a/vendor/michelf/php-markdown/Michelf/Markdown.inc.php b/vendor/michelf/php-markdown/Michelf/Markdown.inc.php new file mode 100644 index 0000000..8c28109 --- /dev/null +++ b/vendor/michelf/php-markdown/Michelf/Markdown.inc.php @@ -0,0 +1,10 @@ + +# +# Original Markdown +# Copyright (c) 2004-2006 John Gruber +# +# +namespace Michelf; + + +# +# Markdown Parser Class +# + +class Markdown implements MarkdownInterface { + + ### Version ### + + const MARKDOWNLIB_VERSION = "1.4.0"; + + ### Simple Function Interface ### + + public static function defaultTransform($text) { + # + # Initialize the parser and return the result of its transform method. + # This will work fine for derived classes too. + # + # Take parser class on which this function was called. + $parser_class = \get_called_class(); + + # try to take parser from the static parser list + static $parser_list; + $parser =& $parser_list[$parser_class]; + + # create the parser it not already set + if (!$parser) + $parser = new $parser_class; + + # Transform text using parser. + return $parser->transform($text); + } + + ### Configuration Variables ### + + # Change to ">" for HTML output. + public $empty_element_suffix = " />"; + public $tab_width = 4; + + # Change to `true` to disallow markup or entities. + public $no_markup = false; + public $no_entities = false; + + # Predefined urls and titles for reference links and images. + public $predef_urls = array(); + public $predef_titles = array(); + + + ### Parser Implementation ### + + # Regex to match balanced [brackets]. + # Needed to insert a maximum bracked depth while converting to PHP. + protected $nested_brackets_depth = 6; + protected $nested_brackets_re; + + protected $nested_url_parenthesis_depth = 4; + protected $nested_url_parenthesis_re; + + # Table of hash values for escaped characters: + protected $escape_chars = '\`*_{}[]()>#+-.!'; + protected $escape_chars_re; + + + public function __construct() { + # + # Constructor function. Initialize appropriate member variables. + # + $this->_initDetab(); + $this->prepareItalicsAndBold(); + + $this->nested_brackets_re = + str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). + str_repeat('\])*', $this->nested_brackets_depth); + + $this->nested_url_parenthesis_re = + str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). + str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); + + $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; + + # Sort document, block, and span gamut in ascendent priority order. + asort($this->document_gamut); + asort($this->block_gamut); + asort($this->span_gamut); + } + + + # Internal hashes used during transformation. + protected $urls = array(); + protected $titles = array(); + protected $html_hashes = array(); + + # Status flag to avoid invalid nesting. + protected $in_anchor = false; + + + protected function setup() { + # + # Called before the transformation process starts to setup parser + # states. + # + # Clear global hashes. + $this->urls = $this->predef_urls; + $this->titles = $this->predef_titles; + $this->html_hashes = array(); + + $this->in_anchor = false; + } + + protected function teardown() { + # + # Called after the transformation process to clear any variable + # which may be taking up memory unnecessarly. + # + $this->urls = array(); + $this->titles = array(); + $this->html_hashes = array(); + } + + + public function transform($text) { + # + # Main function. Performs some preprocessing on the input text + # and pass it through the document gamut. + # + $this->setup(); + + # Remove UTF-8 BOM and marker character in input, if present. + $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); + + # Standardize line endings: + # DOS to Unix and Mac to Unix + $text = preg_replace('{\r\n?}', "\n", $text); + + # Make sure $text ends with a couple of newlines: + $text .= "\n\n"; + + # Convert all tabs to spaces. + $text = $this->detab($text); + + # Turn block-level HTML blocks into hash entries + $text = $this->hashHTMLBlocks($text); + + # Strip any lines consisting only of spaces and tabs. + # This makes subsequent regexen easier to write, because we can + # match consecutive blank lines with /\n+/ instead of something + # contorted like /[ ]*\n+/ . + $text = preg_replace('/^[ ]+$/m', '', $text); + + # Run document gamut methods. + foreach ($this->document_gamut as $method => $priority) { + $text = $this->$method($text); + } + + $this->teardown(); + + return $text . "\n"; + } + + protected $document_gamut = array( + # Strip link definitions, store in hashes. + "stripLinkDefinitions" => 20, + + "runBasicBlockGamut" => 30, + ); + + + protected function stripLinkDefinitions($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:\n+|\Z) + }xm', + array(&$this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + protected function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + return ''; # String that will replace the block + } + + + protected function hashHTMLBlocks($text) { + if ($this->no_markup) return $text; + + $less_than_tab = $this->tab_width - 1; + + # Hashify HTML blocks: + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

    s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded: + # + # * List "a" is made of tags which can be both inline or block-level. + # These will be treated block-level when the start tag is alone on + # its line, otherwise they're not matched here and will be taken as + # inline later. + # * List "b" is made of tags which are always block-level; + # + $block_tags_a_re = 'ins|del'; + $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. + 'script|noscript|form|fieldset|iframe|math|svg|'. + 'article|section|nav|aside|hgroup|header|footer|'. + 'figure'; + + # Regular expression for the content of a block tag. + $nested_tags_level = 4; + $attr = ' + (?> # optional tag attributes + \s # starts with whitespace + (?> + [^>"/]+ # text outside quotes + | + /+(?!>) # slash not followed by ">" + | + "[^"]*" # text inside double quotes (tolerate ">") + | + \'[^\']*\' # text inside single quotes (tolerate ">") + )* + )? + '; + $content = + str_repeat(' + (?> + [^<]+ # content without tag + | + <\2 # nested opening tag + '.$attr.' # attributes + (?> + /> + | + >', $nested_tags_level). # end of opening tag + '.*?'. # last level nested tag content + str_repeat(' + # closing nested tag + ) + | + <(?!/\2\s*> # other tags with a different name + ) + )*', + $nested_tags_level); + $content2 = str_replace('\2', '\3', $content); + + # First, look for nested blocks, e.g.: + #

    + #
    + # tags for inner block must be indented. + #
    + #
    + # + # The outermost tags must start at the left margin for this to match, and + # the inner nested divs must be indented. + # We need to do this before the next, more liberal match, because the next + # match will start at the first `
    ` and stop at the first `
    `. + $text = preg_replace_callback('{(?> + (?> + (?<=\n\n) # Starting after a blank line + | # or + \A\n? # the beginning of the doc + ) + ( # save in $1 + + # Match from `\n` to `\n`, handling nested tags + # in between. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_b_re.')# start tag = $2 + '.$attr.'> # attributes followed by > and \n + '.$content.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special version for tags of group a. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_a_re.')# start tag = $3 + '.$attr.'>[ ]*\n # attributes followed by > + '.$content2.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special case just for
    . It was easier to make a special + # case than to make the other regex more complicated. + + [ ]{0,'.$less_than_tab.'} + <(hr) # start tag = $2 + '.$attr.' # attributes + /?> # the matching end tag + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # Special case for standalone HTML comments: + + [ ]{0,'.$less_than_tab.'} + (?s: + + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # PHP and ASP-style processor instructions ( + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + ) + )}Sxmi', + array(&$this, '_hashHTMLBlocks_callback'), + $text); + + return $text; + } + protected function _hashHTMLBlocks_callback($matches) { + $text = $matches[1]; + $key = $this->hashBlock($text); + return "\n\n$key\n\n"; + } + + + protected function hashPart($text, $boundary = 'X') { + # + # Called whenever a tag must be hashed when a function insert an atomic + # element in the text stream. Passing $text to through this function gives + # a unique text-token which will be reverted back when calling unhash. + # + # The $boundary argument specify what character should be used to surround + # the token. By convension, "B" is used for block elements that needs not + # to be wrapped into paragraph tags at the end, ":" is used for elements + # that are word separators and "X" is used in the general case. + # + # Swap back any tag hash found in $text so we do not have to `unhash` + # multiple times at the end. + $text = $this->unhash($text); + + # Then hash the block. + static $i = 0; + $key = "$boundary\x1A" . ++$i . $boundary; + $this->html_hashes[$key] = $text; + return $key; # String that will replace the tag. + } + + + protected function hashBlock($text) { + # + # Shortcut function for hashPart with block-level boundaries. + # + return $this->hashPart($text, 'B'); + } + + + protected $block_gamut = array( + # + # These are all the transformations that form block-level + # tags like paragraphs, headers, and list items. + # + "doHeaders" => 10, + "doHorizontalRules" => 20, + + "doLists" => 40, + "doCodeBlocks" => 50, + "doBlockQuotes" => 60, + ); + + protected function runBlockGamut($text) { + # + # Run block gamut tranformations. + # + # We need to escape raw HTML in Markdown source before doing anything + # else. This need to be done for each block, and not only at the + # begining in the Markdown function since hashed blocks can be part of + # list items and could have been indented. Indented blocks would have + # been seen as a code block in a previous pass of hashHTMLBlocks. + $text = $this->hashHTMLBlocks($text); + + return $this->runBasicBlockGamut($text); + } + + protected function runBasicBlockGamut($text) { + # + # Run block gamut tranformations, without hashing HTML blocks. This is + # useful when HTML blocks are known to be already hashed, like in the first + # whole-document pass. + # + foreach ($this->block_gamut as $method => $priority) { + $text = $this->$method($text); + } + + # Finally form paragraph and restore hashed blocks. + $text = $this->formParagraphs($text); + + return $text; + } + + + protected function doHorizontalRules($text) { + # Do Horizontal Rules: + return preg_replace( + '{ + ^[ ]{0,3} # Leading space + ([-*_]) # $1: First marker + (?> # Repeated marker group + [ ]{0,2} # Zero, one, or two spaces. + \1 # Marker character + ){2,} # Group repeated at least twice + [ ]* # Tailing spaces + $ # End of line. + }mx', + "\n".$this->hashBlock("empty_element_suffix")."\n", + $text); + } + + + protected $span_gamut = array( + # + # These are all the transformations that occur *within* block-level + # tags like paragraphs, headers, and list items. + # + # Process character escapes, code spans, and inline HTML + # in one shot. + "parseSpan" => -30, + + # Process anchor and image tags. Images must come first, + # because ![foo][f] looks like an anchor. + "doImages" => 10, + "doAnchors" => 20, + + # Make links out of things like `` + # Must come after doAnchors, because you can use < and > + # delimiters in inline links like [this](). + "doAutoLinks" => 30, + "encodeAmpsAndAngles" => 40, + + "doItalicsAndBold" => 50, + "doHardBreaks" => 60, + ); + + protected function runSpanGamut($text) { + # + # Run span gamut tranformations. + # + foreach ($this->span_gamut as $method => $priority) { + $text = $this->$method($text); + } + + return $text; + } + + + protected function doHardBreaks($text) { + # Do hard breaks: + return preg_replace_callback('/ {2,}\n/', + array(&$this, '_doHardBreaks_callback'), $text); + } + protected function _doHardBreaks_callback($matches) { + return $this->hashPart("empty_element_suffix\n"); + } + + + protected function doAnchors($text) { + # + # Turn Markdown link shortcuts into XHTML tags. + # + if ($this->in_anchor) return $text; + $this->in_anchor = true; + + # + # First, handle reference-style links: [link text] [id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + # + # Next, inline-style links: [link text](url "optional title") + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + ('.$this->nested_url_parenthesis_re.') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + ) + }xs', + array(&$this, '_doAnchors_inline_callback'), $text); + + # + # Last, handle reference-style shortcuts: [link text] + # These must come last in case you've also got [link text][1] + # or [link text](/foo) + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + protected function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + # for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + # lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } + else { + $result = $whole_match; + } + return $result; + } + protected function _doAnchors_inline_callback($matches) { + $whole_match = $matches[1]; + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $url = $this->encodeAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + + protected function doImages($text) { + # + # Turn Markdown image shortcuts into tags. + # + # + # First, handle reference-style labeled images: ![alt text][id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array(&$this, '_doImages_reference_callback'), $text); + + # + # Next, handle inline images: ![alt text](url "optional title") + # Don't forget: encode * and _ + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + ('.$this->nested_url_parenthesis_re.') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + ) + }xs', + array(&$this, '_doImages_inline_callback'), $text); + + return $text; + } + protected function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id == "") { + $link_id = strtolower($alt_text); # for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } + else { + # If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + protected function _doImages_inline_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; # $title already quoted + } + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + + protected function doHeaders($text) { + # Setext-style headers: + # Header 1 + # ======== + # + # Header 2 + # -------- + # + $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 + # ## Header 2 + # ## Header 2 with closing hashes ## + # ... + # ###### Header 6 + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + protected function _doHeaders_callback_setext($matches) { + # Terrible hack to check we haven't found an empty list item. + if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) + return $matches[0]; + + $level = $matches[2]{0} == '=' ? 1 : 2; + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + protected function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + protected function doLists($text) { + # + # Form HTML ordered (numbered) and unordered (bulleted) lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $markers_relist = array( + $marker_ul_re => $marker_ol_re, + $marker_ol_re => $marker_ul_re, + ); + + foreach ($markers_relist as $marker_re => $other_marker_re) { + # Re-usable pattern to match any entirel ul or ol list: + $whole_list_re = ' + ( # $1 = whole list + ( # $2 + ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces + ('.$marker_re.') # $4 = first list item marker + [ ]+ + ) + (?s:.+?) + ( # $5 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another list item marker + [ ]* + '.$marker_re.'[ ]+ + ) + | + (?= # Lookahead for another kind of list + \n + \3 # Must have the same indentation + '.$other_marker_re.'[ ]+ + ) + ) + ) + '; // mx + + # We use a different prefix before nested lists than top-level lists. + # See extended comment in _ProcessListItems(). + + if ($this->list_level) { + $text = preg_replace_callback('{ + ^ + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + else { + $text = preg_replace_callback('{ + (?:(?<=\n)\n|\A\n?) # Must eat the newline + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + } + + return $text; + } + protected function _doLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $list = $matches[1]; + $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; + + $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); + + $list .= "\n"; + $result = $this->processListItems($list, $marker_any_re); + + $result = $this->hashBlock("<$list_type>\n" . $result . ""); + return "\n". $result ."\n\n"; + } + + protected $list_level = 0; + + protected function processListItems($list_str, $marker_any_re) { + # + # Process the contents of a single ordered or unordered list, splitting it + # into individual list items. + # + # The $this->list_level global keeps track of when we're inside a list. + # Each time we enter a list, we increment it; when we leave a list, + # we decrement. If it's zero, we're not in a list anymore. + # + # We do this because when we're not inside a list, we want to treat + # something like this: + # + # I recommend upgrading to version + # 8. Oops, now this line is treated + # as a sub-list. + # + # As a single paragraph, despite the fact that the second line starts + # with a digit-period-space sequence. + # + # Whereas when we're inside a list (or sub-list), that line will be + # treated as the start of a sub-list. What a kludge, huh? This is + # an aspect of Markdown's syntax that's hard to parse perfectly + # without resorting to mind-reading. Perhaps the solution is to + # change the syntax rules such that sub-lists must start with a + # starting cardinal number; e.g. "1." or "a.". + + $this->list_level++; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + $list_str = preg_replace_callback('{ + (\n)? # leading line = $1 + (^[ ]*) # leading whitespace = $2 + ('.$marker_any_re.' # list marker and space = $3 + (?:[ ]+|(?=\n)) # space only required if item is not empty + ) + ((?s:.*?)) # list item text = $4 + (?:(\n+(?=\n))|\n) # tailing blank line = $5 + (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) + }xm', + array(&$this, '_processListItems_callback'), $list_str); + + $this->list_level--; + return $list_str; + } + protected function _processListItems_callback($matches) { + $item = $matches[4]; + $leading_line =& $matches[1]; + $leading_space =& $matches[2]; + $marker_space = $matches[3]; + $tailing_blank_line =& $matches[5]; + + if ($leading_line || $tailing_blank_line || + preg_match('/\n{2,}/', $item)) + { + # Replace marker with the appropriate whitespace indentation + $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; + $item = $this->runBlockGamut($this->outdent($item)."\n"); + } + else { + # Recursion for sub-lists: + $item = $this->doLists($this->outdent($item)); + $item = preg_replace('/\n+$/', '', $item); + $item = $this->runSpanGamut($item); + } + + return "
  • " . $item . "
  • \n"; + } + + + protected function doCodeBlocks($text) { + # + # Process Markdown `
    ` blocks.
    +	#
    +		$text = preg_replace_callback('{
    +				(?:\n\n|\A\n?)
    +				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    +				  (?>
    +					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    +					.*\n+
    +				  )+
    +				)
    +				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    +			}xm',
    +			array(&$this, '_doCodeBlocks_callback'), $text);
    +
    +		return $text;
    +	}
    +	protected function _doCodeBlocks_callback($matches) {
    +		$codeblock = $matches[1];
    +
    +		$codeblock = $this->outdent($codeblock);
    +		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    +
    +		# trim leading newlines and trailing newlines
    +		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    +
    +		$codeblock = "
    $codeblock\n
    "; + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + + + protected function makeCodeSpan($code) { + # + # Create a code span markup for $code. Called from handleSpanToken. + # + $code = htmlspecialchars(trim($code), ENT_NOQUOTES); + return $this->hashPart("$code"); + } + + + protected $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) { + foreach ($this->strong_relist as $strong => $strong_re) { + # Construct list of allowed token expressions. + $token_relist = array(); + if (isset($this->em_strong_relist["$em$strong"])) { + $token_relist[] = $this->em_strong_relist["$em$strong"]; + } + $token_relist[] = $em_re; + $token_relist[] = $strong_re; + + # Construct master expression from list. + $token_re = '{('. implode('|', $token_relist) .')}'; + $this->em_strong_prepared_relist["$em$strong"] = $token_re; + } + } + } + + protected function doItalicsAndBold($text) { + $token_stack = array(''); + $text_stack = array(''); + $em = ''; + $strong = ''; + $tree_char_em = false; + + while (1) { + # + # Get prepared regular expression for seraching emphasis tokens + # in current context. + # + $token_re = $this->em_strong_prepared_relist["$em$strong"]; + + # + # Each loop iteration search for the next emphasis token. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + $text_stack[0] .= $parts[0]; + $token =& $parts[1]; + $text =& $parts[2]; + + if (empty($token)) { + # Reached end of text span: empty stack without emitting. + # any more emphasis. + while ($token_stack[0]) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + break; + } + + $token_len = strlen($token); + if ($tree_char_em) { + # Reached closing marker while inside a three-char emphasis. + if ($token_len == 3) { + # Three-char closing marker, close em and strong. + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + $strong = ''; + } else { + # Other closing marker: close one em or strong and + # change current token state to match the other + $token_stack[0] = str_repeat($token{0}, 3-$token_len); + $tag = $token_len == 2 ? "strong" : "em"; + $span = $text_stack[0]; + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] = $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + $tree_char_em = false; + } else if ($token_len == 3) { + if ($em) { + # Reached closing marker for both em and strong. + # Closing strong marker: + for ($i = 0; $i < 2; ++$i) { + $shifted_token = array_shift($token_stack); + $tag = strlen($shifted_token) == 2 ? "strong" : "em"; + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] .= $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + } else { + # Reached opening three-char emphasis marker. Push on token + # stack; will be handled by the special condition above. + $em = $token{0}; + $strong = "$em$em"; + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $tree_char_em = true; + } + } else if ($token_len == 2) { + if ($strong) { + # Unwind any dangling emphasis marker: + if (strlen($token_stack[0]) == 1) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + # Closing strong marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $strong = ''; + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $strong = $token; + } + } else { + # Here $token_len == 1 + if ($em) { + if (strlen($token_stack[0]) == 1) { + # Closing emphasis marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + } else { + $text_stack[0] .= $token; + } + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $em = $token; + } + } + } + return $text_stack[0]; + } + + + protected function doBlockQuotes($text) { + $text = preg_replace_callback('/ + ( # Wrap whole match in $1 + (?> + ^[ ]*>[ ]? # ">" at the start of a line + .+\n # rest of the first line + (.+\n)* # subsequent consecutive lines + \n* # blanks + )+ + ) + /xm', + array(&$this, '_doBlockQuotes_callback'), $text); + + return $text; + } + protected function _doBlockQuotes_callback($matches) { + $bq = $matches[1]; + # trim one level of quoting - trim whitespace-only lines + $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); + $bq = $this->runBlockGamut($bq); # recurse + + $bq = preg_replace('/^/m', " ", $bq); + # These leading spaces cause problem with
     content, 
    +		# so we need to fix that:
    +		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', + array(&$this, '_doBlockQuotes_callback2'), $bq); + + return "\n". $this->hashBlock("
    \n$bq\n
    ")."\n\n"; + } + protected function _doBlockQuotes_callback2($matches) { + $pre = $matches[1]; + $pre = preg_replace('/^ /m', '', $pre); + return $pre; + } + + + protected function formParagraphs($text) { + # + # Params: + # $text - string to process with html

    tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

    tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { + # Is a paragraph. + $value = $this->runSpanGamut($value); + $value = preg_replace('/^([ ]*)/', "

    ", $value); + $value .= "

    "; + $grafs[$key] = $this->unhash($value); + } + else { + # Is a block. + # Modify elements of @grafs in-place... + $graf = $value; + $block = $this->html_hashes[$graf]; + $graf = $block; +// if (preg_match('{ +// \A +// ( # $1 =
    tag +//
    ]* +// \b +// markdown\s*=\s* ([\'"]) # $2 = attr quote char +// 1 +// \2 +// [^>]* +// > +// ) +// ( # $3 = contents +// .* +// ) +// (
    ) # $4 = closing tag +// \z +// }xs', $block, $matches)) +// { +// list(, $div_open, , $div_content, $div_close) = $matches; +// +// # We can't call Markdown(), because that resets the hash; +// # that initialization code should be pulled into its own sub, though. +// $div_content = $this->hashHTMLBlocks($div_content); +// +// # Run document gamut methods on the content. +// foreach ($this->document_gamut as $method => $priority) { +// $div_content = $this->$method($div_content); +// } +// +// $div_open = preg_replace( +// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); +// +// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; +// } + $grafs[$key] = $graf; + } + } + + return implode("\n\n", $grafs); + } + + + protected function encodeAttribute($text) { + # + # Encode text for a double-quoted HTML attribute. This function + # is *not* suitable for attributes enclosed in single quotes. + # + $text = $this->encodeAmpsAndAngles($text); + $text = str_replace('"', '"', $text); + return $text; + } + + + protected function encodeAmpsAndAngles($text) { + # + # Smart processing for ampersands and angle brackets that need to + # be encoded. Valid character entities are left alone unless the + # no-entities mode is set. + # + if ($this->no_entities) { + $text = str_replace('&', '&', $text); + } else { + # Ampersand-encoding based entirely on Nat Irons's Amputator + # MT plugin: + $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', + '&', $text); + } + # Encode remaining <'s + $text = str_replace('<', '<', $text); + + return $text; + } + + + protected function doAutoLinks($text) { + $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', + array(&$this, '_doAutoLinks_url_callback'), $text); + + # Email addresses: + $text = preg_replace_callback('{ + < + (?:mailto:)? + ( + (?: + [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ + | + ".*?" + ) + \@ + (?: + [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ + | + \[[\d.a-fA-F:]+\] # IPv4 & IPv6 + ) + ) + > + }xi', + array(&$this, '_doAutoLinks_email_callback'), $text); + $text = preg_replace_callback('{<(tel:([^\'">\s]+))>}i',array(&$this, '_doAutoLinks_tel_callback'), $text); + + return $text; + } + protected function _doAutoLinks_tel_callback($matches) { + $url = $this->encodeAttribute($matches[1]); + $tel = $this->encodeAttribute($matches[2]); + $link = "$tel"; + return $this->hashPart($link); + } + protected function _doAutoLinks_url_callback($matches) { + $url = $this->encodeAttribute($matches[1]); + $link = "$url"; + return $this->hashPart($link); + } + protected function _doAutoLinks_email_callback($matches) { + $address = $matches[1]; + $link = $this->encodeEmailAddress($address); + return $this->hashPart($link); + } + + + protected function encodeEmailAddress($addr) { + # + # Input: an email address, e.g. "foo@example.com" + # + # Output: the email address as a mailto link, with each character + # of the address encoded as either a decimal or hex entity, in + # the hopes of foiling most address harvesting spam bots. E.g.: + # + #

    foo@exampl + # e.com

    + # + # Based by a filter by Matthew Wickline, posted to BBEdit-Talk. + # With some optimizations by Milian Wolff. + # + $addr = "mailto:" . $addr; + $chars = preg_split('/(? $char) { + $ord = ord($char); + # Ignore non-ascii chars. + if ($ord < 128) { + $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. + # roughly 10% raw, 45% hex, 45% dec + # '@' *must* be encoded. I insist. + if ($r > 90 && $char != '@') /* do nothing */; + else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; + else $chars[$key] = '&#'.$ord.';'; + } + } + + $addr = implode('', $chars); + $text = implode('', array_slice($chars, 7)); # text without `mailto:` + $addr = "$text"; + + return $addr; + } + + + protected function parseSpan($str) { + # + # Take the string $str and parse it into tokens, hashing embeded HTML, + # escaped characters and handling code spans. + # + $output = ''; + + $span_re = '{ + ( + \\\\'.$this->escape_chars_re.' + | + (?no_markup ? '' : ' + | + # comment + | + <\?.*?\?> | <%.*?%> # processing instruction + | + <[!$]?[-a-zA-Z0-9:_]+ # regular tags + (?> + \s + (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* + )? + > + | + <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag + | + # closing tag + ').' + ) + }xs'; + + while (1) { + # + # Each loop iteration seach for either the next tag, the next + # openning code span marker, or the next escaped character. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); + + # Create token from text preceding tag. + if ($parts[0] != "") { + $output .= $parts[0]; + } + + # Check if we reach the end. + if (isset($parts[1])) { + $output .= $this->handleSpanToken($parts[1], $parts[2]); + $str = $parts[2]; + } + else { + break; + } + } + + return $output; + } + + + protected function handleSpanToken($token, &$str) { + # + # Handle $token provided by parseSpan by determining its nature and + # returning the corresponding value that should replace it. + # + switch ($token{0}) { + case "\\": + return $this->hashPart("&#". ord($token{1}). ";"); + case "`": + # Search for end marker in remaining text. + if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', + $str, $matches)) + { + $str = $matches[2]; + $codespan = $this->makeCodeSpan($matches[1]); + return $this->hashPart($codespan); + } + return $token; // return as text since no ending marker found. + default: + return $this->hashPart($token); + } + } + + + protected function outdent($text) { + # + # Remove one level of line-leading tabs or spaces + # + return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); + } + + + # String length function for detab. `_initDetab` will create a function to + # hanlde UTF-8 if the default function does not exist. + protected $utf8_strlen = 'mb_strlen'; + + protected function detab($text) { + # + # Replace tabs with the appropriate amount of space. + # + # For each line we separate the line in blocks delemited by + # tab characters. Then we reconstruct every line by adding the + # appropriate number of space between each blocks. + + $text = preg_replace_callback('/^.*\t.*$/m', + array(&$this, '_detab_callback'), $text); + + return $text; + } + protected function _detab_callback($matches) { + $line = $matches[0]; + $strlen = $this->utf8_strlen; # strlen function for UTF-8. + + # Split in blocks. + $blocks = explode("\t", $line); + # Add each blocks to the line. + $line = $blocks[0]; + unset($blocks[0]); # Do not add first block twice. + foreach ($blocks as $block) { + # Calculate amount of space, insert spaces, insert block. + $amount = $this->tab_width - + $strlen($line, 'UTF-8') % $this->tab_width; + $line .= str_repeat(" ", $amount) . $block; + } + return $line; + } + protected function _initDetab() { + # + # Check for the availability of the function in the `utf8_strlen` property + # (initially `mb_strlen`). If the function is not available, create a + # function that will loosely count the number of UTF-8 characters with a + # regular expression. + # + if (function_exists($this->utf8_strlen)) return; + $this->utf8_strlen = create_function('$text', 'return preg_match_all( + "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", + $text, $m);'); + } + + + protected function unhash($text) { + # + # Swap back in all the tags hashed by _HashHTMLBlocks. + # + return preg_replace_callback('/(.)\x1A[0-9]+\1/', + array(&$this, '_unhash_callback'), $text); + } + protected function _unhash_callback($matches) { + return $this->html_hashes[$matches[0]]; + } + +} + + +# +# Temporary Markdown Extra Parser Implementation Class +# +# NOTE: DON'T USE THIS CLASS +# Currently the implementation of of Extra resides here in this temporary class. +# This makes it easier to propagate the changes between the three different +# packaging styles of PHP Markdown. When this issue is resolved, this +# MarkdownExtra_TmpImpl class here will disappear and \Michelf\MarkdownExtra +# will contain the code. So please use \Michelf\MarkdownExtra and ignore this +# one. +# + +abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { + + ### Configuration Variables ### + + # Prefix for footnote ids. + public $fn_id_prefix = ""; + + # Optional title attribute for footnote links and backlinks. + public $fn_link_title = ""; + public $fn_backlink_title = ""; + + # Optional class attribute for footnote links and backlinks. + public $fn_link_class = "footnote-ref"; + public $fn_backlink_class = "footnote-backref"; + + # Class name for table cell alignment (%% replaced left/center/right) + # For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center' + # If empty, the align attribute is used instead of a class name. + public $table_align_class_tmpl = ''; + + # Optional class prefix for fenced code block. + public $code_class_prefix = ""; + # Class attribute for code blocks goes on the `code` tag; + # setting this to true will put attributes on the `pre` tag instead. + public $code_attr_on_pre = false; + + # Predefined abbreviations. + public $predef_abbr = array(); + + + ### Parser Implementation ### + + public function __construct() { + # + # Constructor function. Initialize the parser object. + # + # Add extra escapable characters before parent constructor + # initialize the table. + $this->escape_chars .= ':|'; + + # Insert extra document, block, and span transformations. + # Parent constructor will do the sorting. + $this->document_gamut += array( + "doFencedCodeBlocks" => 5, + "stripFootnotes" => 15, + "stripAbbreviations" => 25, + "appendFootnotes" => 50, + ); + $this->block_gamut += array( + "doFencedCodeBlocks" => 5, + "doTables" => 15, + "doDefLists" => 45, + ); + $this->span_gamut += array( + "doFootnotes" => 5, + "doAbbreviations" => 70, + ); + + parent::__construct(); + } + + + # Extra variables used during extra transformations. + protected $footnotes = array(); + protected $footnotes_ordered = array(); + protected $footnotes_ref_count = array(); + protected $footnotes_numbers = array(); + protected $abbr_desciptions = array(); + protected $abbr_word_re = ''; + + # Give the current footnote number. + protected $footnote_counter = 1; + + + protected function setup() { + # + # Setting up Extra-specific variables. + # + parent::setup(); + + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->footnotes_ref_count = array(); + $this->footnotes_numbers = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + $this->footnote_counter = 1; + + foreach ($this->predef_abbr as $abbr_word => $abbr_desc) { + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + } + } + + protected function teardown() { + # + # Clearing Extra-specific variables. + # + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->footnotes_ref_count = array(); + $this->footnotes_numbers = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + + parent::teardown(); + } + + + ### Extra Attribute Parser ### + + # Expression to use to catch attributes (includes the braces) + protected $id_class_attr_catch_re = '\{((?:[ ]*[#.][-_:a-zA-Z0-9]+){1,})[ ]*\}'; + # Expression to use when parsing in a context when no capture is desired + protected $id_class_attr_nocatch_re = '\{(?:[ ]*[#.][-_:a-zA-Z0-9]+){1,}[ ]*\}'; + + protected function doExtraAttributes($tag_name, $attr) { + # + # Parse attributes caught by the $this->id_class_attr_catch_re expression + # and return the HTML-formatted list of attributes. + # + # Currently supported attributes are .class and #id. + # + if (empty($attr)) return ""; + + # Split on components + preg_match_all('/[#.][-_:a-zA-Z0-9]+/', $attr, $matches); + $elements = $matches[0]; + + # handle classes and ids (only first id taken into account) + $classes = array(); + $id = false; + foreach ($elements as $element) { + if ($element{0} == '.') { + $classes[] = substr($element, 1); + } else if ($element{0} == '#') { + if ($id === false) $id = substr($element, 1); + } + } + + # compose attributes as string + $attr_str = ""; + if (!empty($id)) { + $attr_str .= ' id="'.$id.'"'; + } + if (!empty($classes)) { + $attr_str .= ' class="'.implode(" ", $classes).'"'; + } + return $attr_str; + } + + + protected function stripLinkDefinitions($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr + (?:\n+|\Z) + }xm', + array(&$this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + protected function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]); + return ''; # String that will replace the block + } + + + ### HTML Block Parser ### + + # Tags that are always treated as block tags: + protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption'; + + # Tags treated as block tags only if the opening tag is alone on its line: + protected $context_block_tags_re = 'script|noscript|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; + + # Tags where markdown="1" default to span mode: + protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; + + # Tags which must not have their contents modified, no matter where + # they appear: + protected $clean_tags_re = 'script|math|svg'; + + # Tags that do not need to be closed. + protected $auto_close_tags_re = 'hr|img|param|source|track'; + + + protected function hashHTMLBlocks($text) { + # + # Hashify HTML Blocks and "clean tags". + # + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

    s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded. + # + # This works by calling _HashHTMLBlocks_InMarkdown, which then calls + # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" + # attribute is found within a tag, _HashHTMLBlocks_InHTML calls back + # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag. + # These two functions are calling each other. It's recursive! + # + if ($this->no_markup) return $text; + + # + # Call the HTML-in-Markdown hasher. + # + list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text); + + return $text; + } + protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0, + $enclosing_tag_re = '', $span = false) + { + # + # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags. + # + # * $indent is the number of space to be ignored when checking for code + # blocks. This is important because if we don't take the indent into + # account, something like this (which looks right) won't work as expected: + # + #

    + #
    + # Hello World. <-- Is this a Markdown code block or text? + #
    <-- Is this a Markdown code block or a real tag? + #
    + # + # If you don't like this, just don't indent the tag on which + # you apply the markdown="1" attribute. + # + # * If $enclosing_tag_re is not empty, stops at the first unmatched closing + # tag with that name. Nested tags supported. + # + # * If $span is true, text inside must treated as span. So any double + # newline will be replaced by a single newline so that it does not create + # paragraphs. + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to check for the presense of newlines around a block tag. + $newline_before_re = '/(?:^\n?|\n\n)*$/'; + $newline_after_re = + '{ + ^ # Start of text following the tag. + (?>[ ]*)? # Optional comment. + [ ]*\n # Must be followed by newline. + }xs'; + + # Regex to match any tag. + $block_tag_re = + '{ + ( # $2: Capture whole tag. + # Tag name. + '.$this->block_tags_re.' | + '.$this->context_block_tags_re.' | + '.$this->clean_tags_re.' | + (?!\s)'.$enclosing_tag_re.' + ) + (?: + (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name. + (?> + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + '. ( !$span ? ' # If not in span. + | + # Indented code block + (?: ^[ ]*\n | ^ | \n[ ]*\n ) + [ ]{'.($indent+4).'}[^\n]* \n + (?> + (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n + )* + | + # Fenced code block marker + (?<= ^ | \n ) + [ ]{0,'.($indent+3).'}(?:~{3,}|`{3,}) + [ ]* + (?: + \.?[-_:a-zA-Z0-9]+ # standalone class name + | + '.$this->id_class_attr_nocatch_re.' # extra attributes + )? + [ ]* + (?= \n ) + ' : '' ). ' # End (if not is span). + | + # Code span marker + # Note, this regex needs to go after backtick fenced + # code blocks but it should also be kept outside of the + # "if not in span" condition adding backticks to the parser + `+ + ) + }xs'; + + + $depth = 0; # Current depth inside the tag tree. + $parsed = ""; # Parsed text that will be returned. + + # + # Loop through every tag until we find the closing tag of the parent + # or loop until reaching the end of text if no parent tag specified. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($block_tag_re, $text, 2, + PREG_SPLIT_DELIM_CAPTURE); + + # If in Markdown span mode, add a empty-string span-level hash + # after each newline to prevent triggering any block element. + if ($span) { + $void = $this->hashPart("", ':'); + $newline = "$void\n"; + $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; + } + + $parsed .= $parts[0]; # Text before current tag. + + # If end of $text has been reached. Stop loop. + if (count($parts) < 3) { + $text = ""; + break; + } + + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + $tag_re = preg_quote($tag); # For use in a regular expression. + + # + # Check for: Fenced code block marker. + # Note: need to recheck the whole tag to disambiguate backtick + # fences from code spans + # + if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+|'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) { + # Fenced code block marker: find matching end marker. + $fence_indent = strlen($capture[1]); # use captured indent in re + $fence_re = $capture[2]; # use captured fence in re + if (preg_match('{^(?>.*\n)*?[ ]{'.($fence_indent).'}'.$fence_re.'[ ]*(?:\n|$)}', $text, + $matches)) + { + # End marker found: pass text unchanged until marker. + $parsed .= $tag . $matches[0]; + $text = substr($text, strlen($matches[0])); + } + else { + # No end marker: just skip it. + $parsed .= $tag; + } + } + # + # Check for: Indented code block. + # + else if ($tag{0} == "\n" || $tag{0} == " ") { + # Indented code block: pass it unchanged, will be handled + # later. + $parsed .= $tag; + } + # + # Check for: Code span marker + # Note: need to check this after backtick fenced code blocks + # + else if ($tag{0} == "`") { + # Find corresponding end marker. + $tag_re = preg_quote($tag); + if (preg_match('{^(?>.+?|\n(?!\n))*?(?block_tags_re.')\b}', $tag) || + ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) && + preg_match($newline_before_re, $parsed) && + preg_match($newline_after_re, $text) ) + ) + { + # Need to parse tag and following text using the HTML parser. + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true); + + # Make sure it stays outside of any paragraph by adding newlines. + $parsed .= "\n\n$block_text\n\n"; + } + # + # Check for: Clean tag (like script, math) + # HTML Comments, processing instructions. + # + else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Need to parse tag and following text using the HTML parser. + # (don't check for markdown attribute) + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false); + + $parsed .= $block_text; + } + # + # Check for: Tag with same name as enclosing tag. + # + else if ($enclosing_tag_re !== '' && + # Same name as enclosing tag. + preg_match('{^= 0); + + return array($parsed, $text); + } + protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) { + # + # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags. + # + # * Calls $hash_method to convert any blocks. + # * Stops when the first opening tag closes. + # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed. + # (it is not inside clean tags) + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to match `markdown` attribute inside of a tag. + $markdown_attr_re = ' + { + \s* # Eat whitespace before the `markdown` attribute + markdown + \s*=\s* + (?> + (["\']) # $1: quote delimiter + (.*?) # $2: attribute value + \1 # matching delimiter + | + ([^\s>]*) # $3: unquoted attribute value + ) + () # $4: make $3 always defined (avoid warnings) + }xs'; + + # Regex to match any tag. + $tag_re = '{ + ( # $2: Capture whole tag. + + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + ) + }xs'; + + $original_text = $text; # Save original text in case of faliure. + + $depth = 0; # Current depth inside the tag tree. + $block_text = ""; # Temporary text holder for current text. + $parsed = ""; # Parsed text that will be returned. + + # + # Get the name of the starting tag. + # (This pattern makes $base_tag_name_re safe without quoting.) + # + if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) + $base_tag_name_re = $matches[1]; + + # + # Loop through every tag until we find the corresponding closing tag. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (count($parts) < 3) { + # + # End of $text reached with unbalenced tag(s). + # In that case, we return original text unchanged and pass the + # first character as filtered to prevent an infinite loop in the + # parent function. + # + return array($original_text{0}, substr($original_text, 1)); + } + + $block_text .= $parts[0]; # Text before current tag. + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + + # + # Check for: Auto-close tag (like
    ) + # Comments and Processing Instructions. + # + if (preg_match('{^auto_close_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Just add the tag to the block as if it was text. + $block_text .= $tag; + } + else { + # + # Increase/decrease nested tag count. Only do so if + # the tag's name match base tag's. + # + if (preg_match('{^mode = $attr_m[2] . $attr_m[3]; + $span_mode = $this->mode == 'span' || $this->mode != 'block' && + preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag); + + # Calculate indent before tag. + if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) { + $strlen = $this->utf8_strlen; + $indent = $strlen($matches[1], 'UTF-8'); + } else { + $indent = 0; + } + + # End preceding block with this tag. + $block_text .= $tag; + $parsed .= $this->$hash_method($block_text); + + # Get enclosing tag name for the ParseMarkdown function. + # (This pattern makes $tag_name_re safe without quoting.) + preg_match('/^<([\w:$]*)\b/', $tag, $matches); + $tag_name_re = $matches[1]; + + # Parse the content using the HTML-in-Markdown parser. + list ($block_text, $text) + = $this->_hashHTMLBlocks_inMarkdown($text, $indent, + $tag_name_re, $span_mode); + + # Outdent markdown text. + if ($indent > 0) { + $block_text = preg_replace("/^[ ]{1,$indent}/m", "", + $block_text); + } + + # Append tag content to parsed text. + if (!$span_mode) $parsed .= "\n\n$block_text\n\n"; + else $parsed .= "$block_text"; + + # Start over with a new block. + $block_text = ""; + } + else $block_text .= $tag; + } + + } while ($depth > 0); + + # + # Hash last block text that wasn't processed inside the loop. + # + $parsed .= $this->$hash_method($block_text); + + return array($parsed, $text); + } + + + protected function hashClean($text) { + # + # Called whenever a tag must be hashed when a function inserts a "clean" tag + # in $text, it passes through this function and is automaticaly escaped, + # blocking invalid nested overlap. + # + return $this->hashPart($text, 'C'); + } + + + protected function doAnchors($text) { + # + # Turn Markdown link shortcuts into XHTML tags. + # + if ($this->in_anchor) return $text; + $this->in_anchor = true; + + # + # First, handle reference-style links: [link text] [id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + # + # Next, inline-style links: [link text](url "optional title") + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + ('.$this->nested_url_parenthesis_re.') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + (?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes + ) + }xs', + array(&$this, '_doAnchors_inline_callback'), $text); + + # + # Last, handle reference-style shortcuts: [link text] + # These must come last in case you've also got [link text][1] + # or [link text](/foo) + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + protected function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + # for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + # lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + if (isset($this->ref_attr[$link_id])) + $result .= $this->ref_attr[$link_id]; + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } + else { + $result = $whole_match; + } + return $result; + } + protected function _doAnchors_inline_callback($matches) { + $whole_match = $matches[1]; + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + $attr = $this->doExtraAttributes("a", $dummy =& $matches[8]); + + + $url = $this->encodeAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $attr; + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + + protected function doImages($text) { + # + # Turn Markdown image shortcuts into tags. + # + # + # First, handle reference-style labeled images: ![alt text][id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array(&$this, '_doImages_reference_callback'), $text); + + # + # Next, handle inline images: ![alt text](url "optional title") + # Don't forget: encode * and _ + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + ('.$this->nested_url_parenthesis_re.') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + (?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes + ) + }xs', + array(&$this, '_doImages_inline_callback'), $text); + + return $text; + } + protected function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id == "") { + $link_id = strtolower($alt_text); # for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + if (isset($this->ref_attr[$link_id])) + $result .= $this->ref_attr[$link_id]; + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } + else { + # If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + protected function _doImages_inline_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + $attr = $this->doExtraAttributes("img", $dummy =& $matches[8]); + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; # $title already quoted + } + $result .= $attr; + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + + protected function doHeaders($text) { + # + # Redefined to add id and class attribute support. + # + # Setext-style headers: + # Header 1 {#header1} + # ======== + # + # Header 2 {#header2 .class1 .class2} + # -------- + # + $text = preg_replace_callback( + '{ + (^.+?) # $1: Header text + (?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes + [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer + }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 {#header1} + # ## Header 2 {#header2} + # ## Header 2 with closing hashes ## {#header3.class1.class2} + # ... + # ###### Header 6 {.class2} + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + (?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes + [ ]* + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + protected function _doHeaders_callback_setext($matches) { + if ($matches[3] == '-' && preg_match('{^- }', $matches[1])) + return $matches[0]; + $level = $matches[3]{0} == '=' ? 1 : 2; + $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2]); + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + protected function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + protected function doTables($text) { + # + # Form HTML tables. + # + $less_than_tab = $this->tab_width - 1; + # + # Find tables with leading pipe. + # + # | Header 1 | Header 2 + # | -------- | -------- + # | Cell 1 | Cell 2 + # | Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] # Optional leading pipe (present) + (.+) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + [ ]* # Allowed whitespace. + [|] .* \n # Row content. + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_doTable_leadingPipe_callback'), $text); + + # + # Find tables without leading pipe. + # + # Header 1 | Header 2 + # -------- | -------- + # Cell 1 | Cell 2 + # Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + (\S.*[|].*) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + .* [|] .* \n # Row content + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_DoTable_callback'), $text); + + return $text; + } + protected function _doTable_leadingPipe_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove leading pipe for each row. + $content = preg_replace('/^ *[|]/m', '', $content); + + return $this->_doTable_callback(array($matches[0], $head, $underline, $content)); + } + protected function _doTable_makeAlignAttr($alignname) + { + if (empty($this->table_align_class_tmpl)) + return " align=\"$alignname\""; + + $classname = str_replace('%%', $alignname, $this->table_align_class_tmpl); + return " class=\"$classname\""; + } + protected function _doTable_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove any tailing pipes for each line. + $head = preg_replace('/[|] *$/m', '', $head); + $underline = preg_replace('/[|] *$/m', '', $underline); + $content = preg_replace('/[|] *$/m', '', $content); + + # Reading alignement from header underline. + $separators = preg_split('/ *[|] */', $underline); + foreach ($separators as $n => $s) { + if (preg_match('/^ *-+: *$/', $s)) + $attr[$n] = $this->_doTable_makeAlignAttr('right'); + else if (preg_match('/^ *:-+: *$/', $s)) + $attr[$n] = $this->_doTable_makeAlignAttr('center'); + else if (preg_match('/^ *:-+ *$/', $s)) + $attr[$n] = $this->_doTable_makeAlignAttr('left'); + else + $attr[$n] = ''; + } + + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $head = $this->parseSpan($head); + $headers = preg_split('/ *[|] */', $head); + $col_count = count($headers); + $attr = array_pad($attr, $col_count, ''); + + # Write column headers. + $text = "
    \n"; + $text .= "\n"; + $text .= "\n"; + foreach ($headers as $n => $header) + $text .= " ".$this->runSpanGamut(trim($header))."\n"; + $text .= "\n"; + $text .= "\n"; + + # Split content by row. + $rows = explode("\n", trim($content, "\n")); + + $text .= "\n"; + foreach ($rows as $row) { + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $row = $this->parseSpan($row); + + # Split row by cell. + $row_cells = preg_split('/ *[|] */', $row, $col_count); + $row_cells = array_pad($row_cells, $col_count, ''); + + $text .= "\n"; + foreach ($row_cells as $n => $cell) + $text .= " ".$this->runSpanGamut(trim($cell))."\n"; + $text .= "\n"; + } + $text .= "\n"; + $text .= "
    "; + + return $this->hashBlock($text) . "\n"; + } + + + protected function doDefLists($text) { + # + # Form HTML definition lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable pattern to match any entire dl list: + $whole_list_re = '(?> + ( # $1 = whole list + ( # $2 + [ ]{0,'.$less_than_tab.'} + ((?>.*\S.*\n)+) # $3 = defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?s:.+?) + ( # $4 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another term + [ ]{0,'.$less_than_tab.'} + (?: \S.*\n )+? # defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?! # Negative lookahead for another definition + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + ) + ) + )'; // mx + + $text = preg_replace_callback('{ + (?>\A\n?|(?<=\n\n)) + '.$whole_list_re.' + }mx', + array(&$this, '_doDefLists_callback'), $text); + + return $text; + } + protected function _doDefLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $list = $matches[1]; + + # Turn double returns into triple returns, so that we can make a + # paragraph for the last item in a list, if necessary: + $result = trim($this->processDefListItems($list)); + $result = "
    \n" . $result . "\n
    "; + return $this->hashBlock($result) . "\n\n"; + } + + + protected function processDefListItems($list_str) { + # + # Process the contents of a single definition list, splitting it + # into individual term and definition list items. + # + $less_than_tab = $this->tab_width - 1; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + # Process definition terms. + $list_str = preg_replace_callback('{ + (?>\A\n?|\n\n+) # leading line + ( # definition terms = $1 + [ ]{0,'.$less_than_tab.'} # leading whitespace + (?!\:[ ]|[ ]) # negative lookahead for a definition + # mark (colon) or more whitespace. + (?> \S.* \n)+? # actual term (not whitespace). + ) + (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed + # with a definition mark. + }xm', + array(&$this, '_processDefListItems_callback_dt'), $list_str); + + # Process actual definitions. + $list_str = preg_replace_callback('{ + \n(\n+)? # leading line = $1 + ( # marker space = $2 + [ ]{0,'.$less_than_tab.'} # whitespace before colon + \:[ ]+ # definition mark (colon) + ) + ((?s:.+?)) # definition text = $3 + (?= \n+ # stop at next definition mark, + (?: # next term or end of text + [ ]{0,'.$less_than_tab.'} \:[ ] | +
    | \z + ) + ) + }xm', + array(&$this, '_processDefListItems_callback_dd'), $list_str); + + return $list_str; + } + protected function _processDefListItems_callback_dt($matches) { + $terms = explode("\n", trim($matches[1])); + $text = ''; + foreach ($terms as $term) { + $term = $this->runSpanGamut(trim($term)); + $text .= "\n
    " . $term . "
    "; + } + return $text . "\n"; + } + protected function _processDefListItems_callback_dd($matches) { + $leading_line = $matches[1]; + $marker_space = $matches[2]; + $def = $matches[3]; + + if ($leading_line || preg_match('/\n{2,}/', $def)) { + # Replace marker with the appropriate whitespace indentation + $def = str_repeat(' ', strlen($marker_space)) . $def; + $def = $this->runBlockGamut($this->outdent($def . "\n\n")); + $def = "\n". $def ."\n"; + } + else { + $def = rtrim($def); + $def = $this->runSpanGamut($this->outdent($def)); + } + + return "\n
    " . $def . "
    \n"; + } + + + protected function doFencedCodeBlocks($text) { + # + # Adding the fenced code block syntax to regular Markdown: + # + # ~~~ + # Code block + # ~~~ + # + $less_than_tab = $this->tab_width; + + $text = preg_replace_callback('{ + (?:\n|\A) + # 1: Opening marker + ( + (?:~{3,}|`{3,}) # 3 or more tildes/backticks. + ) + [ ]* + (?: + \.?([-_:a-zA-Z0-9]+) # 2: standalone class name + | + '.$this->id_class_attr_catch_re.' # 3: Extra attributes + )? + [ ]* \n # Whitespace and newline following marker. + + # 4: Content + ( + (?> + (?!\1 [ ]* \n) # Not a closing marker. + .*\n+ + )+ + ) + + # Closing marker. + \1 [ ]* (?= \n ) + }xm', + array(&$this, '_doFencedCodeBlocks_callback'), $text); + + return $text; + } + protected function _doFencedCodeBlocks_callback($matches) { + $classname =& $matches[2]; + $attrs =& $matches[3]; + $codeblock = $matches[4]; + $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + $codeblock = preg_replace_callback('/^\n+/', + array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); + + if ($classname != "") { + if ($classname{0} == '.') + $classname = substr($classname, 1); + $attr_str = ' class="'.$this->code_class_prefix.$classname.'"'; + } else { + $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs); + } + $pre_attr_str = $this->code_attr_on_pre ? $attr_str : ''; + $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str; + $codeblock = "$codeblock
    "; + + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + protected function _doFencedCodeBlocks_newlines($matches) { + return str_repeat("empty_element_suffix", + strlen($matches[0])); + } + + + # + # Redefining emphasis markers so that emphasis by underscore does not + # work in the middle of a word. + # + protected $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

    tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + $value = trim($this->runSpanGamut($value)); + + # Check if this should be enclosed in a paragraph. + # Clean tag hashes & block tag hashes are left alone. + $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); + + if ($is_p) { + $value = "

    $value

    "; + } + $grafs[$key] = $value; + } + + # Join grafs in one text, then unhash HTML tags. + $text = implode("\n\n", $grafs); + + # Finish by removing any tag hashes still present in $text. + $text = $this->unhash($text); + + return $text; + } + + + ### Footnotes + + protected function stripFootnotes($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [^id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1 + [ ]* + \n? # maybe *one* newline + ( # text = $2 (no blank lines allowed) + (?: + .+ # actual text + | + \n # newlines but + (?!\[\^.+?\]:\s)# negative lookahead for footnote marker. + (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed + # by non-indented content + )* + ) + }xm', + array(&$this, '_stripFootnotes_callback'), + $text); + return $text; + } + protected function _stripFootnotes_callback($matches) { + $note_id = $this->fn_id_prefix . $matches[1]; + $this->footnotes[$note_id] = $this->outdent($matches[2]); + return ''; # String that will replace the block + } + + + protected function doFootnotes($text) { + # + # Replace footnote references in $text [^id] with a special text-token + # which will be replaced by the actual footnote marker in appendFootnotes. + # + if (!$this->in_anchor) { + $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text); + } + return $text; + } + + + protected function appendFootnotes($text) { + # + # Append footnote list to text. + # + $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $text); + + if (!empty($this->footnotes_ordered)) { + $text .= "\n\n"; + $text .= "
    \n"; + $text .= "empty_element_suffix ."\n"; + $text .= "
      \n\n"; + + $attr = ""; + if ($this->fn_backlink_class != "") { + $class = $this->fn_backlink_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_backlink_title != "") { + $title = $this->fn_backlink_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + $num = 0; + + while (!empty($this->footnotes_ordered)) { + $footnote = reset($this->footnotes_ordered); + $note_id = key($this->footnotes_ordered); + unset($this->footnotes_ordered[$note_id]); + $ref_count = $this->footnotes_ref_count[$note_id]; + unset($this->footnotes_ref_count[$note_id]); + unset($this->footnotes[$note_id]); + + $footnote .= "\n"; # Need to append newline before parsing. + $footnote = $this->runBlockGamut("$footnote\n"); + $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $footnote); + + $attr = str_replace("%%", ++$num, $attr); + $note_id = $this->encodeAttribute($note_id); + + # Prepare backlink, multiple backlinks if multiple references + $backlink = ""; + for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) { + $backlink .= " "; + } + # Add backlink to last paragraph; create new paragraph if needed. + if (preg_match('{

      $}', $footnote)) { + $footnote = substr($footnote, 0, -4) . " $backlink

      "; + } else { + $footnote .= "\n\n

      $backlink

      "; + } + + $text .= "
    1. \n"; + $text .= $footnote . "\n"; + $text .= "
    2. \n\n"; + } + + $text .= "
    \n"; + $text .= "
    "; + } + return $text; + } + protected function _appendFootnotes_callback($matches) { + $node_id = $this->fn_id_prefix . $matches[1]; + + # Create footnote marker only if it has a corresponding footnote *and* + # the footnote hasn't been used by another marker. + if (isset($this->footnotes[$node_id])) { + $num =& $this->footnotes_numbers[$node_id]; + if (!isset($num)) { + # Transfer footnote content to the ordered list and give it its + # number + $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id]; + $this->footnotes_ref_count[$node_id] = 1; + $num = $this->footnote_counter++; + $ref_count_mark = ''; + } else { + $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1; + } + + $attr = ""; + if ($this->fn_link_class != "") { + $class = $this->fn_link_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_link_title != "") { + $title = $this->fn_link_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + + $attr = str_replace("%%", $num, $attr); + $node_id = $this->encodeAttribute($node_id); + + return + "". + "$num". + ""; + } + + return "[^".$matches[1]."]"; + } + + + ### Abbreviations ### + + protected function stripAbbreviations($text) { + # + # Strips abbreviations from text, stores titles in hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [id]*: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1 + (.*) # text = $2 (no blank lines allowed) + }xm', + array(&$this, '_stripAbbreviations_callback'), + $text); + return $text; + } + protected function _stripAbbreviations_callback($matches) { + $abbr_word = $matches[1]; + $abbr_desc = $matches[2]; + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + return ''; # String that will replace the block + } + + + protected function doAbbreviations($text) { + # + # Find defined abbreviations in text and wrap them in elements. + # + if ($this->abbr_word_re) { + // cannot use the /x modifier because abbr_word_re may + // contain significant spaces: + $text = preg_replace_callback('{'. + '(?abbr_word_re.')'. + '(?![\w\x1A])'. + '}', + array(&$this, '_doAbbreviations_callback'), $text); + } + return $text; + } + protected function _doAbbreviations_callback($matches) { + $abbr = $matches[0]; + if (isset($this->abbr_desciptions[$abbr])) { + $desc = $this->abbr_desciptions[$abbr]; + if (empty($desc)) { + return $this->hashPart("$abbr"); + } else { + $desc = $this->encodeAttribute($desc); + return $this->hashPart("$abbr"); + } + } else { + return $matches[0]; + } + } + +} diff --git a/vendor/michelf/php-markdown/Michelf/MarkdownExtra.inc.php b/vendor/michelf/php-markdown/Michelf/MarkdownExtra.inc.php new file mode 100644 index 0000000..e11b1ef --- /dev/null +++ b/vendor/michelf/php-markdown/Michelf/MarkdownExtra.inc.php @@ -0,0 +1,11 @@ + +# +# Original Markdown +# Copyright (c) 2004-2006 John Gruber +# +# +namespace Michelf; + + +# Just force Michelf/Markdown.php to load. This is needed to load +# the temporary implementation class. See below for details. +\Michelf\Markdown::MARKDOWNLIB_VERSION; + +# +# Markdown Extra Parser Class +# +# Note: Currently the implementation resides in the temporary class +# \Michelf\MarkdownExtra_TmpImpl (in the same file as \Michelf\Markdown). +# This makes it easier to propagate the changes between the three different +# packaging styles of PHP Markdown. Once this issue is resolved, the +# _MarkdownExtra_TmpImpl will disappear and this one will contain the code. +# + +class MarkdownExtra extends \Michelf\_MarkdownExtra_TmpImpl { + + ### Parser Implementation ### + + # Temporarily, the implemenation is in the _MarkdownExtra_TmpImpl class. + # See note above. + +} + diff --git a/vendor/michelf/php-markdown/Michelf/MarkdownInterface.inc.php b/vendor/michelf/php-markdown/Michelf/MarkdownInterface.inc.php new file mode 100644 index 0000000..a023ed4 --- /dev/null +++ b/vendor/michelf/php-markdown/Michelf/MarkdownInterface.inc.php @@ -0,0 +1,9 @@ + +# +# Original Markdown +# Copyright (c) 2004-2006 John Gruber +# +# +namespace Michelf; + + +# +# Markdown Parser Interface +# + +interface MarkdownInterface { + + # + # Initialize the parser and return the result of its transform method. + # This will work fine for derived classes too. + # + public static function defaultTransform($text); + + # + # Main function. Performs some preprocessing on the input text + # and pass it through the document gamut. + # + public function transform($text); + +} + + +?> \ No newline at end of file diff --git a/vendor/michelf/php-markdown/Readme.md b/vendor/michelf/php-markdown/Readme.md new file mode 100644 index 0000000..6430c47 --- /dev/null +++ b/vendor/michelf/php-markdown/Readme.md @@ -0,0 +1,271 @@ +PHP Markdown +============ + +PHP Markdown Lib 1.4.0 - 29 Nov 2013 + +by Michel Fortin + + +based on Markdown by John Gruber + + + +Introduction +------------ + +This is a library package that includes the PHP Markdown parser and its +sibling PHP Markdown Extra with additional features. + +Markdown is a text-to-HTML conversion tool for web writers. Markdown +allows you to write using an easy-to-read, easy-to-write plain text +format, then convert it to structurally valid XHTML (or HTML). + +"Markdown" is actually two things: a plain text markup syntax, and a +software tool, originally written in Perl, that converts the plain text +markup to HTML. PHP Markdown is a port to PHP of the original Markdown +program by John Gruber. + +* [Full documentation of the Markdown syntax]() + - Daring Fireball (John Gruber) +* [Markdown Extra syntax additions]() + - Michel Fortin + + +Requirement +----------- + +This library package requires PHP 5.3 or later. + +Note: The older plugin/library hybrid package for PHP Markdown and +PHP Markdown Extra is still maintained and will work with PHP 4.0.5 and later. + +Before PHP 5.3.7, pcre.backtrack_limit defaults to 100 000, which is too small +in many situations. You might need to set it to higher values. Later PHP +releases defaults to 1 000 000, which is usually fine. + + +Usage +----- + +This library package is meant to be used with class autoloading. For autoloading +to work, your project needs have setup a PSR-0-compatible autoloader. See the +included Readme.php file for a minimal autoloader setup. (If you cannot use +autoloading, see below.) + +With class autoloading in place, putting the 'Michelf' folder in your +include path should be enough for this to work: + + use \Michelf\Markdown; + $my_html = Markdown::defaultTransform($my_text); + +Markdown Extra syntax is also available the same way: + + use \Michelf\MarkdownExtra; + $my_html = MarkdownExtra::defaultTransform($my_text); + +If you wish to use PHP Markdown with another text filter function +built to parse HTML, you should filter the text *after* the `transform` +function call. This is an example with [PHP SmartyPants][psp]: + + use \Michelf\Markdown, \Michelf\SmartyPants; + $my_html = Markdown::defaultTransform($my_text); + $my_html = SmartyPants::defaultTransform($my_html); + +All these examples are using the static `defaultTransform` static function +found inside the parser class. If you want to customize the parser +configuration, you can also instantiate it directly and change some +configuration variables: + + use \Michelf\MarkdownExtra; + $parser = new MarkdownExtra; + $parser->fn_id_prefix = "post22-"; + $my_html = $parser->transform($my_text); + +To learn more, see the full list of [configuration variables]. + + [configuration variables]: http://michelf.ca/projects/php-markdown/configuration/ + + +### Usage without an autoloader + +If you cannot use class autoloading, you can still use `include` or `require` +to access the parser. To load the `\Michelf\Markdown` parser, do it this way: + + require_once 'Michelf/Markdown.inc.php'; + +Or, if you need the `\Michelf\MarkdownExtra` parser: + + require_once 'Michelf/MarkdownExtra.inc.php'; + +While the plain `.php` files depend on autoloading to work correctly, using the +`.inc.php` files instead will eagerly load the dependencies that would be +loaded on demand if you were using autoloading. + + +Public API and Versioning Policy +--------------------------------- + +Version numbers are of the form *major*.*minor*.*patch*. + +The public API of PHP Markdown consist of the two parser classes `Markdown` +and `MarkdownExtra`, their constructors, the `transform` and `defaultTransform` +functions and their configuration variables. The public API is stable for +a given major version number. It might get additions when the minor version +number increments. + +**Protected members are not considered public API.** This is unconventional +and deserves an explanation. Incrementing the major version number every time +the underlying implementation of something changes is going to give +nonessential version numbers for the vast majority of people who just use the +parser. Protected members are meant to create parser subclasses that behave in +different ways. Very few people create parser subclasses. I don't want to +discourage it by making everything private, but at the same time I can't +guarantee any stable hook between versions if you use protected members. + +**Syntax changes** will increment the minor number for new features, and the +patch number for small corrections. A *new feature* is something that needs a +change in the syntax documentation. Note that since PHP Markdown Lib includes +two parsers, a syntax change for either of them will increment the minor +number. Also note that there is nothing perfectly backward-compatible with the +Markdown syntax: all inputs are always valid, so new features always replace +something that was previously legal, although generally nonsensical to do. + + +Bugs +---- + +To file bug reports please send email to: + + +Please include with your report: (1) the example input; (2) the output you +expected; (3) the output PHP Markdown actually produced. + +If you have a problem where Markdown gives you an empty result, first check +that the backtrack limit is not too low by running `php --info | grep pcre`. +See Installation and Requirement above for details. + + +Development and Testing +----------------------- + +Pull requests for fixing bugs are welcome. Proposed new features are +going meticulously reviewed -- taking into account backward compatibility, +potential side effects, and future extensibility -- before deciding on +acceptance or rejection. + +If you make a pull request that includes changes to the parser please add +tests for what is being changed to [MDTest][] and make a pull request there +too. + + [MDTest]: https://github.com/michelf/mdtest/ + + +Version History +--------------- + +PHP Markdown Lib 1.4.0 (29 Nov 2013) + +* Added support for the `tel:` URL scheme in automatic links. + + + + It gets converted to this (note the `tel:` prefix becomes invisible): + + +1-111-111-1111 + +* Added backtick fenced code blocks to MarkdownExtra, originally from + Github-Flavored Markdown. + +* Added an interface called MarkdownInterface implemented by both + the Markdown and MarkdownExtra parsers. You can use the interface if + you want to create a mockup parser object for unit testing. + +* For those of you who cannot use class autoloading, you can now + include `Michelf/Markdown.inc.php` or `Michelf/MarkdownExtra.inc.php` (note + the `.inc.php` extension) to automatically include other files required + by the parser. + + +PHP Markdown Lib 1.3 (11 Apr 2013) + +This is the first release of PHP Markdown Lib. This package requires PHP +version 5.3 or later and is designed to work with PSR-0 autoloading and, +optionally with Composer. Here is a list of the changes since +PHP Markdown Extra 1.2.6: + +* Plugin interface for WordPress and other systems is no longer present in + the Lib package. The classic package is still available if you need it: + + +* Added `public` and `protected` protection attributes, plus a section about + what is "public API" and what isn't in the Readme file. + +* Changed HTML output for footnotes: now instead of adding `rel` and `rev` + attributes, footnotes links have the class name `footnote-ref` and + backlinks `footnote-backref`. + +* Fixed some regular expressions to make PCRE not shout warnings about POSIX + collation classes (dependent on your version of PCRE). + +* Added optional class and id attributes to images and links using the same + syntax as for headers: + + [link](url){#id .class} + ![img](url){#id .class} + + It work too for reference-style links and images. In this case you need + to put those attributes at the reference definition: + + [link][linkref] or [linkref] + ![img][linkref] + + [linkref]: url "optional title" {#id .class} + +* Fixed a PHP notice message triggered when some table column separator + markers are missing on the separator line below column headers. + +* Fixed a small mistake that could cause the parser to retain an invalid + state related to parsing links across multiple runs. This was never + observed (that I know of), but it's still worth fixing. + + +Copyright and License +--------------------- + +PHP Markdown Lib +Copyright (c) 2004-2013 Michel Fortin + +All rights reserved. + +Based on Markdown +Copyright (c) 2003-2005 John Gruber + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + +* Neither the name "Markdown" nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +This software is provided by the copyright holders and contributors "as +is" and any express or implied warranties, including, but not limited +to, the implied warranties of merchantability and fitness for a +particular purpose are disclaimed. In no event shall the copyright owner +or contributors be liable for any direct, indirect, incidental, special, +exemplary, or consequential damages (including, but not limited to, +procurement of substitute goods or services; loss of use, data, or +profits; or business interruption) however caused and on any theory of +liability, whether in contract, strict liability, or tort (including +negligence or otherwise) arising in any way out of the use of this +software, even if advised of the possibility of such damage. diff --git a/vendor/michelf/php-markdown/Readme.php b/vendor/michelf/php-markdown/Readme.php new file mode 100644 index 0000000..d007b11 --- /dev/null +++ b/vendor/michelf/php-markdown/Readme.php @@ -0,0 +1,31 @@ + + + + + PHP Markdown Lib - Readme + + + + + diff --git a/vendor/michelf/php-markdown/composer.json b/vendor/michelf/php-markdown/composer.json new file mode 100644 index 0000000..45abc67 --- /dev/null +++ b/vendor/michelf/php-markdown/composer.json @@ -0,0 +1,31 @@ +{ + "name": "michelf/php-markdown", + "type": "library", + "description": "PHP Markdown", + "homepage": "http://michelf.ca/projects/php-markdown/", + "keywords": ["markdown"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "http://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "http://daringfireball.net/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-0": { "Michelf": "" } + }, + "extra": { + "branch-alias": { + "dev-lib": "1.4.x-dev" + } + } +}