From 9f8c7199eaefff07ab05c259b5cd4869d4d05d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Estev=C3=A3o=20Soares=20dos=20Santos?= Date: Wed, 27 Apr 2022 21:42:24 +0100 Subject: [PATCH] feat(makehtml.events): implements event system refactor for converter.makeHtml (#919) * startrefactoring the event system * refactor: blockquotes, code blocks and links refactored * refactor codeblock to new event system * refactor subparser until ghcode to new events * finish adating ghcodeblock to new event * add headings to new events * add image to event system * add emphasisAndStrong to event system * fix wrong event name in emphasisAndStrong onEnd event * spanGamut and build * showdown.helper.event refactored to showdown.Event * partial * add links * add metadata * add strikethrough and table * build * add underline * add unescapeSpecialChars * small refactoring * remove old tables parser * add lists * add simple event trigger tests * build * fix browserstack * fix browserstack * remove testing for ie11 and bumped firefox min version to 45 * fixes and closes #920 * build --- .eslintrc.json | 7 +- .github/workflows/browserstack.yml | 4 +- Gruntfile.js | 1 + dist/showdown.js | Bin 209090 -> 259365 bytes dist/showdown.js.map | Bin 600068 -> 733208 bytes dist/showdown.min.js | Bin 98369 -> 116084 bytes dist/showdown.min.js.map | Bin 108977 -> 133625 bytes docs/event_system.md | 223 ++++++--- karma.browserstack.js | 15 +- karma.conf.js | 3 +- src/converter.js | 48 +- src/event.js | 225 +++++++++ src/helpers.js | 382 +++++++++++----- src/options.js | 16 +- src/showdown.js | 8 + src/subParsers/makehtml/blockGamut.js | 44 +- src/subParsers/makehtml/blockQuotes.js | 42 -- src/subParsers/makehtml/blockquote.js | 94 ++++ src/subParsers/makehtml/codeBlock.js | 95 ++++ src/subParsers/makehtml/codeBlocks.js | 38 -- src/subParsers/makehtml/codeSpan.js | 101 +++++ src/subParsers/makehtml/codeSpans.js | 48 -- .../makehtml/completeHTMLDocument.js | 35 +- src/subParsers/makehtml/detab.js | 32 +- src/subParsers/makehtml/ellipsis.js | 29 +- src/subParsers/makehtml/emoji.js | 73 ++- src/subParsers/makehtml/emphasisAndStrong.js | 173 +++++++ .../makehtml/encodeAmpsAndAngles.js | 34 +- .../makehtml/encodeBackslashEscapes.js | 49 +- src/subParsers/makehtml/encodeCode.js | 35 +- .../escapeSpecialCharsWithinTagAttributes.js | 38 +- src/subParsers/makehtml/githubCodeBlock.js | 134 ++++++ src/subParsers/makehtml/githubCodeBlocks.js | 50 -- src/subParsers/makehtml/hashBlock.js | 29 +- src/subParsers/makehtml/hashCodeTags.js | 35 +- src/subParsers/makehtml/hashElement.js | 2 +- src/subParsers/makehtml/hashHTMLBlocks.js | 38 +- src/subParsers/makehtml/hashHTMLSpans.js | 59 +-- src/subParsers/makehtml/hashPreCodeTags.js | 35 +- src/subParsers/makehtml/headers.js | 126 ------ src/subParsers/makehtml/heading.js | 171 +++++++ src/subParsers/makehtml/horizontalRule.js | 94 +++- src/subParsers/makehtml/image.js | 188 ++++++++ src/subParsers/makehtml/images.js | 110 ----- src/subParsers/makehtml/italicsAndBold.js | 66 --- src/subParsers/makehtml/link.js | 323 +++++++++++++ src/subParsers/makehtml/links.js | 428 ------------------ src/subParsers/makehtml/list.js | 406 +++++++++++++++++ src/subParsers/makehtml/lists.js | 261 ----------- src/subParsers/makehtml/metadata.js | 91 +++- src/subParsers/makehtml/outdent.js | 17 - src/subParsers/makehtml/paragraphs.js | 7 +- src/subParsers/makehtml/runExtension.js | 2 +- src/subParsers/makehtml/spanGamut.js | 30 +- src/subParsers/makehtml/strikethrough.js | 56 ++- .../makehtml/stripLinkDefinitions.js | 8 +- src/subParsers/makehtml/table.js | 326 +++++++++++++ src/subParsers/makehtml/tables.js | 143 ------ src/subParsers/makehtml/underline.js | 79 +++- .../makehtml/unescapeSpecialChars.js | 19 +- src/subParsers/makehtml/unhashHTMLSpans.js | 46 ++ test/bootstrap.js | 18 +- .../features/customizedHeaderId/simple.html | 1 + .../features/customizedHeaderId/simple.md | 1 + .../cases/features/emojis/special.html | 4 +- .../tables/basic-with-header-ids.html | 8 +- .../makehtml/cases/standard/images.html | 3 +- .../makehtml/cases/standard/images.md | 5 +- .../functional/makehtml/testsuite.features.js | 79 ++-- test/mocks/md-to-trigger-all-events.md | 82 ++++ test/optionswp.js | 2 +- test/unit/showdown.Converter.js | 5 +- test/unit/showdown.events.js | 289 ++++++++++++ test/unit/showdown.js | 1 - 74 files changed, 3946 insertions(+), 1823 deletions(-) create mode 100644 src/event.js delete mode 100644 src/subParsers/makehtml/blockQuotes.js create mode 100644 src/subParsers/makehtml/blockquote.js create mode 100644 src/subParsers/makehtml/codeBlock.js delete mode 100644 src/subParsers/makehtml/codeBlocks.js create mode 100644 src/subParsers/makehtml/codeSpan.js delete mode 100644 src/subParsers/makehtml/codeSpans.js create mode 100644 src/subParsers/makehtml/emphasisAndStrong.js create mode 100644 src/subParsers/makehtml/githubCodeBlock.js delete mode 100644 src/subParsers/makehtml/githubCodeBlocks.js delete mode 100644 src/subParsers/makehtml/headers.js create mode 100644 src/subParsers/makehtml/heading.js create mode 100644 src/subParsers/makehtml/image.js delete mode 100644 src/subParsers/makehtml/images.js delete mode 100644 src/subParsers/makehtml/italicsAndBold.js create mode 100644 src/subParsers/makehtml/link.js delete mode 100644 src/subParsers/makehtml/links.js create mode 100644 src/subParsers/makehtml/list.js delete mode 100644 src/subParsers/makehtml/lists.js delete mode 100644 src/subParsers/makehtml/outdent.js create mode 100644 src/subParsers/makehtml/table.js delete mode 100644 src/subParsers/makehtml/tables.js create mode 100644 src/subParsers/makehtml/unhashHTMLSpans.js create mode 100644 test/functional/makehtml/cases/features/customizedHeaderId/simple.html create mode 100644 test/functional/makehtml/cases/features/customizedHeaderId/simple.md create mode 100644 test/mocks/md-to-trigger-all-events.md create mode 100644 test/unit/showdown.events.js diff --git a/.eslintrc.json b/.eslintrc.json index 5027d33..233efc3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,6 +2,9 @@ "env": { "es6": true }, + "parserOptions": { + "ecmaVersion": "latest" + }, "rules": { "indent": [2, 2, {"SwitchCase": 1, "VariableDeclarator": 2}], "curly": [2, "all"], @@ -10,7 +13,6 @@ "quotes": [2, "single"], "no-multi-str": 2, "no-mixed-spaces-and-tabs": 2, - "no-trailing-spaces": 2, "space-unary-ops": [2, { "nonwords": false, @@ -24,7 +26,6 @@ "eol-last": 2, "space-before-function-paren": [2, "always"], "array-bracket-spacing": [2, "never", {"singleValue": false}], - "space-in-parens": [2, "never"], - "no-multiple-empty-lines": 2 + "space-in-parens": [2, "never"] } } diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml index 91cf84a..6d77e4f 100644 --- a/.github/workflows/browserstack.yml +++ b/.github/workflows/browserstack.yml @@ -21,10 +21,10 @@ jobs: - name: '🚚 Upgrade NPM' run: npm install -g npm - - name: 'âš™ Setup Node.js v17.x' + - name: 'âš™ Setup Node.js v16.x' uses: actions/setup-node@v2 with: - node-version: 17.x + node-version: 16.x cache: 'npm' - name: '📖 Get current package version' diff --git a/Gruntfile.js b/Gruntfile.js index 38c50d4..cf4e1f1 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -33,6 +33,7 @@ module.exports = function (grunt) { 'src/options.js', 'src/showdown.js', 'src/helpers.js', + 'src/event.js', 'src/subParsers/makehtml/*.js', 'src/subParsers/makemarkdown/*.js', 'src/converter.js', diff --git a/dist/showdown.js b/dist/showdown.js index e746ab110b99c3d6cc3a1fb216756f2e66c7363d..49760a1c43b2cf085fe1e502731fbd2f13b9192a 100644 GIT binary patch literal 259365 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 z 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 z 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ÿrJn?$aj( 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 WZ;2aRaLl^KNB2y+yTM)dBdG_s_(wqi delta 57085 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 D;;ef< diff --git a/dist/showdown.min.js b/dist/showdown.min.js index 671f8ca15911ca8a0334eab26938df627f6a2fe5..60898a8bceb10c479faa2dedfd62eedf81475701 100644 GIT binary patch literal 116084 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 Gzx_X&eb1o) delta 29530 zcmcJ232-D=nPxoqeIGiyb#^JGmMT?QRZ<_eyHwTXcDwP>wp(`F*jQ3GsZzEo-K8u! zGu3Tdk_GH83=?3m6Z!E6^b_pvr_ba#jM^-W!$eb>gd-oLKh z?mfMBV4Z2X#_Y5IZSBI=$5ys^CwEP+=&Cw)LAMjO<`x#0$Ieylq@6IWgs$qDvhJL^ zXpP&|dBb)eO4{n+VA7qirwTg$WM+(W`a;Ehqh47s)G^y|7i=rxE>mZQHjd6ToBovP z&s@Px_Km38OhLJzTV|!AE81*fan^iR+x@w#nCpGNwV#i_kFCAa&~(2pwHEU+n#{+b z`PdW2Q~_NF6R?+)Dw_F#Nz4NpML=VhUC@il3EQrU)hQ|6drMn-57vA^ub4Brz7fr! zmpMgQ9vkO>@gf`WUTy2_wo^*NS(r{654wis0MrR3Wu=r{LeWgGx4pB?RD+dgL{Ejj zQO)&kYac#pqUo%8!LSs~9W&1*`^Gb6qXJN7Oy{&~o7Qa7%(xHD8*0NYKHq*MA>YUQ zA?Q{MvbsJ^9SC_+V*9F zj-AFUzH{&CE$*^Waj@Y*qb-?pX2mrK^<*#mGqy2nJlL>@a9&k!bH^>~#dJ*XzK+B` zGd6ak{W{Y*?0v1H^-!!{9O`r`2=W!e#8@2_^EACJouf*uaH2BR2x#7!&ZXYkYOx`f zMNhxz+}CXeD{eH;gI$NrphCQL05sEwj(~atbd#{dvGFSwEaPJ0PGk1OgY!X=rpzj; zs`X)EFLm{8b>nFLo36X|_$_0j6LQPV>A~>x6}{91r9aSpOQ*ZM94u@(Jf&6=$DXr& ztnC`*#gCuB>CBYMx_!JlV;pmnBWg-Hp)3c-hv><8COnXic=mSov@_8~`}R2^3A*N% zO$Rl-lRc?TR79<2y=Qt9zH=Yjuy&5#eX3`0vrn7o@jE?9Hp@4>$Z~AlyRNr&Oa~2{ zMO#6KblUxyf}z=}T~8ZzqD6BP`c%QjAC)?LPw(*B8T#^--VB@d{<*jF5Osx;%&g(w zAgSl6d7|G=!9^+P%(!klhFu5%Ltyb z0beN0<1y^RbdK4!{!mg^i+T<#)eOG(S=PU)EMQJ^c&YCYru$!BWIf(*_iyvE$~M5V zpk(oPPRX!&??cMfz38u&w1OIeb-d+#Bjou$*_QKi!Tw83o&TV8OJF zq;kJAQ=L;(&3mGM{~D~s`?CL;7zxzqxqy;aF>=8 zMa`JjjPc;9b4j8zTBT-~l(M9xY#J=(datW3J4-dM!B|navQU_q8k?yu67VblZmv)P zIWS7V>M^3orHpGhE>7dfl&V^(6i~`6BpuYM=#G0c4X>u@tq<;Ki>$%HzI57BAr#n& za$!!+H5IE1NoHlSVw`hxi;ku@+eHvUY^!1gsIJu$C)5N|7m9mr8q?MI0HPoU}%}poIQeP=0Q_|-l z_8F%M6pH5WJ+>U9sQysP5t*+vn8BsTPPm0}{@566TPXqMD!L1KYFu~A*XxdPw_VX( zRr`OP%-H}{+AVO}Ap?%;jY@g2r?(0f}xFP8Ilqzy!lds+p)u%_*$Zy`&*D zv%ZNrgTq!=6BEEGQ?NS)(9pV{Oqe)-KB8G;)k0M4GoLg{?jp#DsyL>g z@$r)7YM~lZnsL5dWW$o2_1&T=B%K7&0Jrt%+z$m zUw@8u@QkQ$VDVF*9!kyeyS6 zRYwxB2_xfRc_3RrjTnAIG6DV2>PtabRjsCppt14VbK!S635+IjZMX zv<_g{rUBO5Un2=fs#qrvfa$lb0Baoxn|f3|q$19;RIR}S1&{<~CC+N#ltL4bydEcM zB##p%^b6u_BS2@9xKl&`~=y zf#8KbTbL%16ZQdJof`9=$#!F)Th@@=+IO0DdZ$J^g{=hQzcu=ZH+4|0=)u7?3d(h) z`5Q%h0%xO~IajGdOgbjmW92fZ2yFgXi&t&7C--0*6n@z>P4X0@HKtAfGU!Og6$j!1=qdF zYq~+BAQZKF@4ja1$*@8~Cw|yRYAf#BQuH1;Md2dOz3bb2s!KI}Hw6sL*SF=zsM`zA(mX@HMJ9w^2#a29< zcn$?Bzl{(FD%EMdBHE0JX@k9zdKwKHEIxsw6VzA{6T3{kvyNMxKLMp+f%I!(lq0yz zlYTvO7lbEFDSGhd6pR3a2*kSvvv6q^eEtQN;2(XFZCt^8j|YNcgX(59=^N!z8&s-B zm5xhkTFx&Nj6)b;i-H-76`Z>+GXMHwR#3$;Tv;WkVW^8hkEjD28*CR}dVzJHMrHZv zMAJik2&8`fdD|dd@J$vqmBfVVfo&{%PhJ1VK;X|Fzn6_ayZMIu-{n31vhMxhrCxlR z-i4RD@cB0UH|;(CH~Yl9zQ64kpP%)-atGu~gCsy9B#Cloaf>&turZ^uRAY;*6pF$T;TF7C z{;7XcK)-cw$B(Ivf>`{#i*0FRga=i86ONNT7jVEhDz(m;ksVnbx{ zNQwod1v04-==qzw*}4^Ms*)FrCY8fDiitrC#|-n?Sg9iAYFa?UO=$waOKg&FMf4tg zWjo;u|4BDX0I8iuNbRwIYt1>a?SS4NL+W4)geE26Tf27er~h(%UxWw}r}R_PrgDMB@cRYG*9XjsVsUy{)4q`59?Vcs(G)! zmRhf-U{kXA%WbT?)fEbiXp+xTb0xkRTf>o4_A=k~5Nq8FfHwt6j}x7OT8Q|kplxHI z>k05m*+D?*Le-o}jF2a$N&m484f<%l0cufEaz>=9W|L=@CeBPwPN~T^r_?0A+BgUk zXWl%ePI^awwkc7!88DCd!UOCmWPsz3o@aZ!$A8wf%Pr_o`2rZj%0dK&Hlk%m1WGur z>h;BOVH_f4|9uu1;%j4Ydf)nWt7ravTOeTTPkx!T^#!H_W30*H@c#POiIrv)S<(`S zCek?unMBF=-EivoU2hsck+|uu+is;33B?SSk190gIm6WxjjYB_Wt&l*P@H9ze=IYhkv!tyXRMm_;%~c zsxD#iB_&@grGj->Btt>%cTt`IGlMq|iyDHkSvMQml-4;mZ5#UeG2f?~Yu;Dt3OWlE zC(rzK_c{|ch?4h*zdk@`t|5`5ee4QRgm_fMSOrzZ!SC|s{*N$Qi^F!xCrNb71s#ux_@&YQT@mq5BE{w5bRS@N#B16h%_>0<=rvZlT`@#&~~#l4IxC$ zdYep1g}y4eej5x}yZyttg89rD2<>5HCXCmIeCgMnz;bQ@xnE|;7DmroVd9Jp&J z3WLRL4oTYh6W?LIQ&4R}$BO9Pfmce*{PH^@XVYZ)!PwMf6Z-?KyTpd@ zf7-%&ufCF{4kn9z{l$p~@0}u1Nmz+oj3Lh3oxSX=sEfSUD-@_*PBo7H7tcwLo^bTr+6{?u;vHq5NAg&k@w z=4j*398FIxrSSpwUd-`Q3%g!c=x+{C8sxIL;6do!<;2jyAh#U3+uMhn%xw8MB(3X7 zJQozkY$Pf2AGEU0gK?B$;1edLlU_z>OU@)6gi1$%zmX?cz|P1pglRJQy9K6M{IHG}tNe zM>sPe*^opjWFh?ZB}$i|K@#O2l|p;+Ss@h#Vq_oz38}svf~2UfYC_j|@#8n5Ka=a7 zaDKS_9i6PdtvUP>F}bo9d_Jj-)Q5(L_EN{-j&9c0{22VYiw*O4?qef z1R5vr`VtQO22L1_V8*@fim!Ml^Ki;fI8)GJC#Q)@4Ifn%O))7D1FpdMTmQ8}!gD?w zG=q0ZtTI`On@3@36CQa41Q05(3|q2p8V5S6h07uQ7JWYD8Lo2hDqSkac3h zpT3Fh#hH11knQ208x(%psOW~M!l@ya_Mf_KspB=24`}#4IsD~>r=L8^cJOB&Wm`z} zXe!eD;8E6fFn(&{DnN*_E-=>3!$W)%3`$~n{@RNO4IuM#R7L?Xgxj#p98XTpq}1bn z?1B~GmRXPyZ<&Eni1k)z;*l11Go>6?w3;5_$0p1gCB@!R7lBK#oEtLQFsbnN_p%l? z%7@>}dd8gPcyx^H(G@)+P9~I;8$y*66ygXI2ZBJD(dXEHepB)igg2dJo&QdR_imM4 z3nY3}Wp8Rucxn7g6J9cgUS-(AaI(^be#aDsvZ2qwbQ(kRT4FBLe1sr4x9hhjg+c#j z%S~DceWZ4`!fss=!6~X*9L?3g-x;p}%ag_bGR^w<`_e44mI9#Y@y@FdLHyDQ*0mW# zmB_9Q;saNFJKymi*p^eF)ym3P)tkhiH_wpSW+-7I*clFZIA4T%PKK?rk}`=HlZsE0 zhIqzPz!75x#K>j^qRmH+v-XA)xckZ{;1)qVL zug$QVR=`Mt80#uLg90@0Fc4c@fbV6_eAt)?-~rZzSJFk4%r3%kwMeSn@}x67kX0#e z4fMK5e-KgwsbE#$s+ECF@0|Hy(4kt~Q(uG#Zk$ewe`b{R37FNdP>%D0-< z`Qz0E%OxGOh#<<80_n5CyHpBh*HtYF*qw+*L@{y^VJ;T1h64*SFjmkI z+<41>oMj1$j*PJNtTf(<;J&8lY6s|QrbiKnD-9qx4FY?0!dqZ3&_!Ucz~uniG3>nq zXoJu|h-^TcD?jBSH>o}30k@R?l6u*=DOb7U8rGR;%2k92g|i%*?Dt~MSfriE!g@^1 zG*}lL2(A1*hgjzt*zEW}9b$vx%dLmm{!U0|P3#PuhQAa!Cxzy;IfqdFTHUNd@p(1E zW_Z#N(Lpl{BJ?zbjrcqT!H@C{Rz&e~oL^w=E0`T1sg0oGa@a{&RlGxZraZirLRp4w zX(jq5;n)T&p6nN=rxA0Q7BD#rPHZfEV=;h>7er}00zoek6sr>syr?AYL- zBZc`?aws9DE5?Q?dzheS6%~EKttvSPt2C-ygQx=KS5$F=Do~k3pX3}PypG6=G+l*% z%aD*y)P_8gX*%-XNkonDVM5c$P8%78xSL~x9Z5C#KdeKgSiBv7=?H7xoKz>16NyQ8 zs>q+Y$o8!vqu0w9*$MvXBW$;RwOW)fg>5N7+yKKPv|WY!(dJ|)9qE>f4nX}Ru1c!B zbcCJKV1AiUhG2D>IHSOyqE227X(2WNL}rAWE~Y;aO+R1s4VC1M6kmsnlPcLR`A@E8 zr&ns167MP7H#tEroQcV)sT2ZoY5@kSLR)eLI}*~&+6^I^nQ=Vlm6ndWpu$M84b6e~ zG@)Vf{jZ5kjNw6z+Tm+Y60M+^zGqzr|LsP$Ya%;2efI3xdU-wCqYXfD~w(*wRD0+aP+7f2TDXo=Z+&^3XZ97Kj{$49AKe{JV{ej{tY z?n>rdyZ*Xf{$L~P{&!gUFN(Ogz=?U|NKTou|{VCY&1Zh`Yl_%{ARqr z`MC*CYt6CQOJWj;cNi^Efg}m3Kp4R8_8;Oq1nDH;{LPLovh!rv=;~k&Ok4EaEqVs_ zo-=I2Dj5)fgcL!iSXAhc6-*1CtKSaPH9uXh+AadFR&_HdDh3MfH*@K0^6AGXX7t~PaP7;(5 zD7qR(L_bMFyI*$agP;aaXcMFqDLumIDyU`^vY_r6Fq4q5Lmnz7ibwGu8T-L+@LCmo z2Mhxk?G*TH$5}UVrL8xx^vdB{CS-~p!B`T+qNXNcs|OEF3=;!7GwBQw=UT;sP_w8W zEke)2D{zEdsSthf$$S}ndAmH-T|l*jqr4Z z!m1()Xla$C1-X}`Uu65n-Z*%J1PdXt$BIo9o2!eFzJVkZzjo8(i#c^(8Z8PEEuy1y zIn0RFwB%0nmgB5tCE)wn*&3kzUa+bMl^K9aSTmb<1;lS}j`=HfOAL?q6)!bvA0#pkD1&GxoU8#@!YXK>X zT;>MC{~HN+)%aPU-gib4_85_x3O{utyJmwg`0~OVSjRQKLMSvT*yc$^K!U1F$JbNM zQqLX!jT_m?6&oIuXok0f?Syhwc5z`DbO~nDurtcFs%SLJ`ou3-7AO)JIzN5T)WsiA z(Mzq>*egkItv4(ny*}`3*+v}x7*xW473<8@HA4Ph6OWDH03!c{FoJpvLC!b7fsL%M zQd5KfU<`sCG3`Yk8UzbdBmPkj3z*~x2r&3vym&Dq_M?a>BzHcSg)>CY`R{2gF(B5P z&4WPC=}2|2<`AnrkLpPdAB_}fz>Gkr7zx)Q)65_z8HnEPL&^8GX zLUa*k=|ohE7!&tF zAnTgL&9Lgx52)erh z4j;r5rANn*8RCqk({LxyxfT)fh(1HMyTgBaGxQm_!pP7f^QA_#^eByIrmQdvFAL@^ zC4E%&sSpCZD6TsR<4blHrVwOfRnSRL2r)xAGWwEL->#QO@~B8dQhj$>Fy@MZgn@8S zaVf(hfjc`D4JsXM6v!V8Fwtn#sVg5f8Z?ikE{hD-Qo#-g5DY}YiE?8n%FfxaSy6(h zRKnthnZ9c^Jw-=#Mx#BgKdPk~vPJtW(qj<^p!0`MvR+}B_`pfleIPo8!I4ylaVGHq z?LAp63@lALfUh|hl1sktovcH|VAJmKr|)E~YjDy;9D_KGwiruWs5^}maUf2kn?ed< za5h(LoJKbVtFK&-)o?x0K_m(ku1ApJ=9uoE$67S6JCEMdE1M6?xb!%l&ua6{jFn}Q zz178ee&mg8Sa_^$UVbBU*$n^g8(9h$ExfhF_OFGhOO)Tm-+m9%_>N6%+mO%F1PfV& zcL$e}kYy0*sUkQ;9BWI0axw}owltazIip3|DvW5e8CQ4Ci&Ar*!ama4WLfCEt-x2||C2U%q@ZqFCn{0w z4gcgB)>0`^{^$ZF>IVcPdF18?hUOPPo}4&&BlH?_ z_D+t1+7wGc(tNI_=H%%t0dKB=f8&u`WZfJg4u98qwl6scfFtw=9)Pe9bvc-L$xjVL z1iXtJ1#Lbvdn>SB_(juc z$YwhKn9llE=Hyugg;%QLCLtW$n9J@=0yY?eZYC=j2<`|`M(IS7&(7zzLqKX|@sb^y zO3Ci*TbpsEQeeACSip-=Y^FTe*$fT^|4$`E*WFiQ18XV;K^JaY0ZCUD#9W+WH3wow z$6Cr>B8()&`I1@;yEou%6^MfCo&p3xz=&Izqj6OkfMOSu3)p5#7D3dCL(VLbo`J;8 zkl)%XxNxD*6fmSZqDC|&|vm(3xd_%=TT*?&pq7$Wzi8MrKC~yxL0hx%fq$NO;V&sVA??26^vH`Gt z(@G!@TS)EzDT2u2JAfvJQ)%#ip1+%Q^Pit)v!k^wW7!E7oP}tMjP1I%Z@-)EM`(4E zMa9fz$d`(eHfk3~j7%`yZi-ub%3xcO=;Mm;M@!o(0IT0Qf5~L+?OOA7-4H)ebE~lnZjbVpYOquQ%YJTC_?nS&?jRJzXX7;k2l0pEP7>Vj zgBgI-^^H=%R`TT1jUgYG%1tSV+A7DQw&ud`{RhS%S)i|zq-U3le%zJ}XP%gw$}LEi zDss#ysw)=ljMo?g_o$FspR0ezKU87;opHS)n-mF$MLAFY?FzeQSBV4)On(GY0#;He zab=FZp&cVNuc_&!9z?*@DLJT1(km-j5J>bMCV2v*}?5>vNmToSXrX3?v!h>2Q+SH#pdp$lSaAr#1;;trV2 zHT}zUm*EH4?)8M9xC`g{2iR=W7@PU?to70;jaWHxZO!IJcmoCur>qHwP}#07%$9+? zg7P&yK3sQLN7IDA7@3AG?GbhHz%u;tlq-x-v!JAj=TOPd7?r@$EWYA2Hm2~bET+*k zX-X4GQ?wJqF|Q)s8dYkhDC0UlB0*%Eld^GOZ^eqTKiRCiHCw&0p98NZUV0CLh=0#Q~l9q^rGl`man zr^yoY1%!y)!{GFztoOQ%mWQ+l>EgqchoJI9#dabaU?6oS5Iq%H3byn~HS(A9U)it%TT{>mbU`4`;LgV>{l)*v&dO4KQNEw86LI(`=?|jKetQauC*=5JUI{~UW$@{@tDD+Cp zp2>;$8OX4R@RW?)Rgs}1?H&qo-862xnzeFtQP3E&bFybpcj7*Z2^#hrU#6wFOGq}2 zMw7$l8Z_naeT22{6KOy)2|_L-SgTlu3?y5b^S6&ap>?WS*Xg;4WM-}E(x#$$d!%fUjsj!6!ISxn9 zFQOIAD7Xc29?2h=%XnluS*ePNkfp($@#irk+s{fdkgVHh3uSG(0Q)#ZMR7V&6F@?= zwD@9EL+yOwtUoL5A|`n;e;(7nsGds|&Q4sESdQ;B5Y@*AwdeoiKeBBreuL>~RTpv4 zsj{dmQ@3d%7trwq(eVZ9cp4o~TtMGZzhQ)&Up8Hxc}NaNRD~uQ(5FB`Pa1a@9&9A- z#ezU2Ns5UUblfA+FUGnkqjHJD0bnEA4s&SkVOHH54;$m(c$m%K1j8!$(-jUI3Ldqi zlE5kSV#pYq`My7hr8W-enFU;vX+zX8NHK2Aj_-IEYik-`i|L`E3;}y1^%07cU_QTJ zEZ9Q8neina6~!s=>p(!>r3Fi}P9php$h$F;P^XuQg65-7u>rpKF+|{B_dZ12SKr5!-K4*iaKY)!?ckFR6j_%)|0j6) zmdDt-H6|$GF%LrJYaZL6Qc4<5!_&J&>Gl$MfL_KMNE@OS^H@=S&x8~0R2DHBLT*DVcaw>) zMYY(ZyMjr})&WJaY4_x4-~SNXP``b2J$|>mmRDY7Y^O$5-y+=)Cgt+^_p!bM2>nO) zs{)|az_5WjPB$~cqZFH1tI)=y>+9TTMmwJnmv0JK-1P(?sq=@PVEt?9dKUiCC)ffC z+Mi_iaPR#rwSlz8a4}zelI`YC-OoDL!U^i~SD$44{j~Cl2d5NrFe@;+!15T|ak7)k zEw6)IYX~_R-w*?t$1zHPLLK~XI8#PeZ%4plfEW|xk)<3+3ycQxVhtp=h65Ggo*I8Y zI}Yryo@4_pG+{O502S$NGYX_LN@T$KVm0N`d73bb0Hi|<2tsaB4Z8UoE?Sr zdt|JdcQAZa4KEe3CaMt6^jW&#OkBoKh7Bs@J3qwQNvg!21!j6%T-kaWo#VDZhy$4f zOwnm1O@m3(R;9=zaWh<8bEpi4Ri5|q-4Wz2f z72A^y`3vJJqx&wr3DZ9r29pV8^rf)`UCVqL3W!1#NBp9Ls49|ZQ* zH^bY5^6jC5o1dL8Q3Rxm%pw)@lB zie#&3T+Fj`BMO8iMUMN@N7#n2HMXL6eeCTf(ruJnxEV)2%C;ds#lK*tgo}k0pkq#a zF~fSwI@$jpew6jB3EK9_fNj}%O%Kq~!=@elHy>rYai?Z{2tD>X|1{g&Ui%t39Z`jS z!dBE^lxcvU<`S@sb=_i;H3ONJ_!*60%6a)*Q!ltwhfWjh(S}Xe4-t=vNt2S&0@nRo zBJ-O3>5@yb#5(%eQ+pJVtQcIVAWk^#CExrpWR2^*^JDDV4qQuQ8{`qh_5CEo z82rQcv##xeEUy1&*0w|HDNrP!)xq*13I|=G7q~c$jjlTu9!Rp7W0?LN zQC`@%L3v@OhAT$|Cr}Y(0M;-D!~{T*^KXSh4SvHX*f^{3CqBUj@$uzPAhjQT zKsYAMJE^Z`Ewvd@m+D=*8kjZC$`Zs_ROR3LB9##FZ?@P$8nExYl33cVBw2kU;o=Dw?D(a)B@9I>~~~90wJAt ze-<`o`Y{ZU&LsIsVoL@Z$8wW>A)GP}?E*~wqpM!jAo4?WrA~AAFV_V^zNJEW4MP{I8#7qoXDS$_2!+8c?I6-$(*V z!Vep0)(LULyNECD8>b(lc@pg7FaM0q;v@TcTzXIK(M2{*;fA60wNe=cgzN+adnY&_!@h-5EWs0^DiByWat1p3v@9p64uGm zhzM3IxQ`f4W-Bx6U&aettJvTb|982>#lpfEkJL(nV}pf-L{w54u{P=E6r{^1{ZtGf zCJ}Oi1kjK^;=2Rqs=PE7Ik~<(t2+KgyCkg}R?XtWcw?~%{L~lNzAk9tm|S0QgLXm} zfWYq(0e|251@>0#@s=;LH}43p&XgBuBBJq&?A_~aVVB|C{wwRez2-+=6x=N7;Eq*s zH^DMOh-RTRAc{FMoREW_9D*`1MWj^;A%;@v5oa7-(CK=g{BgGuo)uUi>9=)|coCo! zS>mY${GEea=?Vkn;8MrZAca7UEt_R2mGRN%*ih_Qc+G>bwpca)>Yi<}sxrI#J9YiR zIitlY;qF%@{)h-HPWP6yKqL&imoSv`qv%a|$7t3R-_Xwg1_f*U+0$i~TcVcZJn?13 zkp_$1Bb#Bdgg2}my$2wlMs5>)v+zKR<_1UpD_-GU_4CuOvctDQm#l`G=#YYJO-x$c zr8Oi2<@`2ca;9ZTIaqWsg~TcUnF6J$%j%ya2s++n#HW@KNV1t`L8Z4r_I=|rsR-r3H1e3(`b1y*OH2FWi0NaiDjkBX2a5~og zx*1dyIDKuwpV#1*%=qGq;%2j_Uj+A;KZ|&a4kXdTUseFs!ypml4KQ^dMS~!7RKZWk z041?(a8`tuAYLE80^;(6UxQ$4^ZULA^GcOJ^)+^2gF{z#~75PU%t)?yT)_kT5`w#{Y+4h{9mwZ|1W#55aIv; diff --git a/dist/showdown.min.js.map b/dist/showdown.min.js.map index 2d00658cd1ffd2355a1e505e2471bf841b7dc158..64096ec041b7bfd6967047551629fed7fff5815e 100644 GIT binary patch literal 133625 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%0Df7s)JFm%`IaQv|O>x~tRy0s*9gDG~`JaGdq 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 N_2OH5o&BHx`M(!CkN*Gw literal 108977 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 some awesome quote", + blockquote: "some awesome quote" +} +``` + + +## Basic Event + + +## Event Types Events are raised when a subparser is run (or about to be run). Within a subparser, the events always follow a certain order (sequence). For instance, **.before** events always run before **.captureStart**. Each subparser raises several events sequentially: - 1. **.start**: **always runs** except it subparser is disabled +### onStart - Raised when the **subparser has started**, but no capturing or any modification to the text was done. +**`..onStart`**: **always runs** except if the subparser is disabled + +Raised when the **subparser has started**, but no capturing or any modification to the text was done. +**Always runs** (except if the subparser is deactivated through options). - **Always runs** (except if the subparser is deactivated through options). - - ***Properties***: +***Properties***: - | property | type | access | description | - |----------|-----------|------------|--------------------------------------------------------------------| - | input | string | read | The full text that was passed to the subparser | - | output | string | write | The full text with modification that will be passed along the chain| - | regexp | null | | | - | matches | null | | | +| property | type | access | description | +|------------|-----------|------------|--------------------------------------------------------------------| +| input | string | read | The full text that was passed to the subparser | +| output | string | write | The full text with modification that will be passed along the chain| +| regexp | null | | | +| matches | null | | | +| attributes | null | | | + - Usually you would want to use this event if you wish to change the input to the subparser - - 2. **.captureStart**: *might not be run*; +Usually you would want to use this event if you wish to change the input to the subparser. Please note, +however, that the input text is the **complete text** that was fed to the converter. + +### onCapture + +**`..onCapture`**: *might not be run*; - Raised when a regex match is found and a capture was successful. Some normalization and modification - of the regex captured groups might be performed. - - Might not be run if no regex match is found. - - ***Properties***: - - | property | type | access | description | - |----------|-----------|------------|--------------------------------------------------------------------| - | input | string | read | The captured text | - | output | string | write | The text that will be passed to the subparser/other listeners | - | regexp | RegExp | readonly | Regular Expression used to capture groups | - | matches | object | read/write | Matches groups. Changes to this object are reflected in the output | - - Usually you would want to use this event if you wish to modify a certain subparser behavior. - Exs: remove all title attributes from links; change indentation of code blocks; etc... - - 3. **.captureEnd**: *might not be run*; - - Raised after the modifications to the captured text are done but before the replacement is introduced in the document. +Raised when a regex match is found and a capture was successful. Some normalization and modification +of the regex captured groups might be performed. + +Might not be run if no regex match is found. + +***Properties***: + +| property | type | access | description | +|------------|----------|------------|--------------------------------------------------------------------| +| input | string | readonly | The captured text | +| output | string | write | null or well formed HTML (see note) | +| regexp | RegExp | readonly | Regular Expression used to capture groups | +| matches | object | read/write | Matches groups. Changes to this object are reflected in the output | +| attributes | object | read/write | Attributes to add to the HTML output | - Might not be run if no regex match is found. - - ***Properties***: - - | property | type | access | description | - |------------|-----------|------------|--------------------------------------------------------------------------------| - | input | string | read | The captured text | - | output | string | write | The text that will be passed to the subparser/other listeners | - | regexp | RegExp | readonly | Regular Expression used to capture groups | - | matches | object | read/write | Keypairs of matches groups. Changes to this object are reflected in the output | - | attributes | object | read/write | Attributes to add to the HTML output | +Usually you would want to use this event if you wish to modify the subparser behavior, text or modify the HTML output +of the subparser. + +**IMPORTANT NOTE**: Extensions listening to onCapture event should try to AVOID changing the output property. +Instead, they should modify the values of the matches and attributes objects. This is because +the **output property takes precedence over the matches objects** and **prevents showdown to call other subparsers** +inside the captured fragment.This means 3 very important things: + + 1. If something is passed as the output property, any changes to the matches and attributes objects will be ignored. + 2. Changes made by other extensions to the matches or attributes objects will also be ignored + 3. Showdown will not call other subparsers, such as encode code or span gamut in the text fragment, which may lead to + weird results. + +```javascript +// showdown extension 1 that is listening to makehtml.blockquote.onCapture +function extension_1 (showdownEvent) { + // i'm bad and write to output + showdownEvent.output = '

foo
'; // must be an well formed html string + showdownEvent.matches.blockquote = 'some nice quote'; +} + +// showdown extension 1 that is also listening to makehtml.blockquote.onCapture +function extension_2 (showdownEvent) { + // I make blockquotes become bold + let quote = showdownEvent.matches.blockquote; + showdownEvent.matches.blockquote = '' + quote + ''; +} + +// the result will always be
foo
, regardless of the order of extension loading and call +``` + + +### onHash + +**`..onHash`**: *always runs*; - 4. **.beforeHash**: *might not be run*; - - Raised before the output is hashed. +Raised before the output is hashed. **Always runs** (except if the subparser was deactivated through options), +even if no hashing is performed. - Always run (except if the subparser was deactivated through options), even if no hashing is performed. - - ***Properties***: +***Properties***: - | property | type | access | description | - |----------|------------|------------|--------------------------------------------------------------------| - | input | string | read | The captured text | - | output | string | write | The text that will be passed to the subparser/other listeners | - | regexp | null | | | - | matches | null | | | +| property | type | access | description | +|------------|------------|------------|--------------------------------------------------------------------| +| input | string | read | The captured text | +| output | string | write | The text that will be passed to the subparser/other listeners | +| regexp | null | | | +| matches | null | | | +| attributes | null | | | + +Usually you would want to use this event if you wish change the subparser's raw output before it is hashed. + +### onEnd - Usually you would want to use this event if you wish change the subparser output before it is hashed +**`..onEnd`**: *always runs*; - 5. **.end**: *always runs*; - - Raised when the subparser has finished its work and is about to exit. +Raised when the subparser has finished its work and is about to exit. - Always runs (except if the subparser is deactivated through options). +Always runs (except if the subparser is deactivated through options). - ***Properties***: +***Properties***: - | property | type | access | description | - |----------|-----------|------------|--------------------------------------------------------------------| - | input | string | read | The partial/full text with the subparser modifications | - | output | string | write | The text that will be passed to other subparsers | - | regexp | null | | | - | matches | null | | | +| property | type | access | description | +|----------|-----------|------------|--------------------------------------------------------------------| +| input | string | read | The full text with the subparser modifications (contains hashes) | +| output | string | write | The text that will be passed to other subparsers | +| regexp | null | | | +| matches | null | | | - Usually you would want to use this event if you wish change the subparser hashed output +Usually you would want to use this event if you want to run code or perform changes to the text after the subparser was +run and it's output was hashed. Keep in mind that the input is the full text and might contain hashed elements. ### Special Events @@ -147,3 +209,20 @@ These events are always guaranteed to be called, regardless of options or circum As a rule of thumb, ## Events List + + +### blockquote + +#### + + +### metadata + + + +## Common pitfalls + +### Infinite loop + +If you pass the input as output in a `onCapture` event, you might trigger an infinite loop. + diff --git a/karma.browserstack.js b/karma.browserstack.js index 341e42c..7dbe9b6 100644 --- a/karma.browserstack.js +++ b/karma.browserstack.js @@ -18,10 +18,17 @@ module.exports = function (config) { os: 'Windows', os_version: '10' }, - bstack_firefox_windows: { + bstack_firefox_old_windows: { base: 'BrowserStack', browser: 'firefox', - browser_version: '44', + browser_version: '45', + os: 'Windows', + os_version: '10' + }, + bstack_firefox_latest_windows: { + base: 'BrowserStack', + browser: 'firefox', + browser_version: '99', os: 'Windows', os_version: '10' }, @@ -32,6 +39,7 @@ module.exports = function (config) { os: 'Windows', os_version: '10' }, + /* bstack_ie11_windows: { base: 'BrowserStack', browser: 'ie', @@ -39,6 +47,7 @@ module.exports = function (config) { os: 'Windows', os_version: '10' }, + */ bstack_macos_safari: { base: 'BrowserStack', browser: 'safari', @@ -64,7 +73,7 @@ module.exports = function (config) { } }, - browsers: ['bstack_chrome_windows', 'bstack_firefox_windows', 'bstack_ie11_windows', 'bstack_edge_windows', 'bstack_iphoneX', 'bstack_macos_safari', 'bstack_android'], + browsers: ['bstack_chrome_windows', 'bstack_firefox_old_windows', 'bstack_firefox_latest_windows', /*'bstack_ie11_windows',*/ 'bstack_edge_windows', 'bstack_iphoneX', 'bstack_macos_safari', 'bstack_android'], frameworks: ['mocha', 'chai'], reporters: ['dots', 'BrowserStack'], files: [ diff --git a/karma.conf.js b/karma.conf.js index ade836f..a3778f1 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -15,7 +15,8 @@ module.exports = function (config) { { pattern: 'src/options.js'}, // tests { pattern: 'test/unit/showdown*.js' }, - { pattern: 'test/functional/showdown*.js' }, + { pattern: 'test/unit/showdown.events.js' }, + //{ pattern: 'test/functional/makehtml/testsuite.*.js' }, ], reporters: ['progress'], port: 9876, // karma web server port diff --git a/src/converter.js b/src/converter.js index 6e7b29d..cdf2e0d 100644 --- a/src/converter.js +++ b/src/converter.js @@ -11,7 +11,7 @@ showdown.Converter = function (converterOptions) { 'use strict'; - var + let /** * Options used by this converter * @private @@ -64,7 +64,7 @@ showdown.Converter = function (converterOptions) { function _constructor () { converterOptions = converterOptions || {}; - for (var gOpt in globalOptions) { + for (let gOpt in globalOptions) { if (globalOptions.hasOwnProperty(gOpt)) { options[gOpt] = globalOptions[gOpt]; } @@ -72,7 +72,7 @@ showdown.Converter = function (converterOptions) { // Merge options if (typeof converterOptions === 'object') { - for (var opt in converterOptions) { + for (let opt in converterOptions) { if (converterOptions.hasOwnProperty(opt)) { options[opt] = converterOptions[opt]; } @@ -85,6 +85,8 @@ showdown.Converter = function (converterOptions) { if (options.extensions) { showdown.helper.forEach(options.extensions, _parseExtension); } + + options = showdown.helper.validateOptions(options); } /** @@ -205,35 +207,29 @@ showdown.Converter = function (converterOptions) { } function rTrimInputText (text) { - var rsp = text.match(/^\s*/)[0].length, + let rsp = text.match(/^\s*/)[0].length, rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm'); return text.replace(rgx, ''); } /** * - * @param {string} evtName Event name - * @param {string} text Text - * @param {{}} options Converter Options - * @param {{}} globals Converter globals - * @param {{}} [pParams] extra params for event - * @returns showdown.helper.Event - * @private + * @param {showdown.Event} event + * @returns showdown.Event */ - this._dispatch = function dispatch (evtName, text, options, globals, pParams) { - evtName = evtName.toLowerCase(); - var params = pParams || {}; - params.converter = this; - params.text = text; - params.options = options; - params.globals = globals; - var event = new showdown.helper.Event(evtName, text, params); - - if (listeners.hasOwnProperty(evtName)) { - for (var ei = 0; ei < listeners[evtName].length; ++ei) { - var nText = listeners[evtName][ei](event); - if (nText && typeof nText !== 'undefined') { - event.setText(nText); + this.dispatch = function (event) { + if (!(event instanceof showdown.Event)) { + throw new TypeError('dispatch only accepts showdown.Event objects as param, but ' + typeof event + ' given'); + } + event.converter = this; + if (listeners.hasOwnProperty(event.name)) { + for (let i = 0; i < listeners[event.name].length; ++i) { + let listRet = listeners[event.name][i](event); + if (showdown.helper.isString(listRet)) { + event.output = listRet; + event.input = listRet; + } else if (listRet instanceof showdown.Event && listRet.name === event.name) { + event = listRet; } } } @@ -325,7 +321,7 @@ showdown.Converter = function (converterOptions) { // run the sub parsers text = showdown.subParser('makehtml.metadata')(text, options, globals); text = showdown.subParser('makehtml.hashPreCodeTags')(text, options, globals); - text = showdown.subParser('makehtml.githubCodeBlocks')(text, options, globals); + text = showdown.subParser('makehtml.githubCodeBlock')(text, options, globals); text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals); text = showdown.subParser('makehtml.hashCodeTags')(text, options, globals); text = showdown.subParser('makehtml.stripLinkDefinitions')(text, options, globals); diff --git a/src/event.js b/src/event.js new file mode 100644 index 0000000..c319c73 --- /dev/null +++ b/src/event.js @@ -0,0 +1,225 @@ +/** + * Created by Estevao on 31-05-2015. + */ + +showdown.Event = class { + + /** + * Creates a new showdown Event object + * @param {string} name + * @param {string} input + * @param {{}} [params] + * @param {string} params.output + * @param {RegExp} params.regexp + * @param {{}} params.matches + * @param {{}} params.attributes + * @param {{}} params.globals + * @param {{}} params.options + * @param {showdown.Converter} params.converter + */ + constructor (name, input, params) { + params = params || {}; + let {output, regexp, matches, attributes, globals, options, converter} = params; + if (!showdown.helper.isString(name)) { + if (!showdown.helper.isString(name)) { + throw new TypeError('Event.name must be a string but ' + typeof name + ' given'); + } + } + this._name = name.toLowerCase(); + this.input = input; + this.output = output || input; + this.regexp = regexp || null; + this.matches = matches || {}; + this.attributes = attributes || {}; + this._globals = globals || {}; + this._options = showdown.helper.cloneObject(options, true) || {}; + this._converter = converter || undefined; + } + + /** @returns {string} */ + get name () { + return this._name; + } + + /** @returns {string} */ + get input () { + return this._input; + } + + /** @param {string} value */ + set input (value) { + if (!showdown.helper.isString(value)) { + throw new TypeError('Event.input must be a string but ' + typeof value + ' given'); + } + this._input = value; + } + + /** @returns {string} */ + get output () { + return this._output; + } + + /** @param {string|null} value */ + set output (value) { + if (!showdown.helper.isString(value) && value !== null) { + throw new TypeError('Event.output must be a string but ' + typeof value + ' given'); + } + this._output = value; + } + + /** @returns {null|RegExp} */ + get regexp () { + return this._regexp; + } + + /** @param {null|RegExp} value */ + set regexp (value) { + if (!(value instanceof RegExp) && value !== null) { + throw new TypeError('Event.regexp must be a RegExp object (or null) but ' + typeof value + ' given'); + } + this._regexp = value; + } + + /** @returns {{}} */ + get matches () { + return this._matches; + } + + /** @param {{}}value */ + set matches (value) { + if (typeof value !== 'object') { + throw new TypeError('Event.matches must be an object (or null) but ' + typeof value + ' given'); + } + this._matches = {}; + for (let prop in value) { + if (value.hasOwnProperty(prop)) { + let descriptor = {}; + if (/^_(.+)/.test(prop)) { + descriptor = { + enumerable: true, + configurable: false, + writable: false, + value: value[prop] + }; + } else { + descriptor = { + enumerable: true, + configurable: false, + writable: true, + value: value[prop] + }; + } + Object.defineProperty(this._matches, prop, descriptor); + } + } + } + + /** @returns {{}} */ + get attributes () { + return this._attributes; + } + + /** @param {{}} value */ + set attributes (value) { + if (typeof value !== 'object') { + throw new TypeError('Event.attributes must be an object (or null) but ' + typeof value + ' given'); + } + this._attributes = value; + } + + /** @param {showdown.Converter} converter */ + set converter (converter) { + this._converter = converter; + } + + /** @returns {showdown.Converter} */ + get converter () { + return this._converter; + } + + get options () { + return this._options; + } + + get globals () { + return this._globals; + } + // FLUID INTERFACE + + /** + * + * @param {string} value + * @returns {showdown.Event} + */ + setInput (value) { + this.input = value; + return this; + } + + /** + * + * @param {string|null} value + * @returns {showdown.Event} + */ + setOutput (value) { + this.output = value; + return this; + } + + /** + * + * @param {RegExp} value + * @returns {showdown.Event} + */ + setRegexp (value) { + this.regexp = value; + return this; + } + + /** + * + * @param {{}}value + * @returns {showdown.Event} + */ + setMatches (value) { + this.matches = value; + return this; + } + + /** + * + * @param {{}}value + * @returns {showdown.Event} + */ + setAttributes (value) { + this.attributes = value; + return this; + } + + _setOptions (value) { + this._options = value; + return this; + } + + _setGlobals (value) { + this._globals = value; + return this; + } + + _setConverter (value) { + this.converter = value; + return this; + } + + /** + * Legacy: Return the output text + * @returns {string} + */ + getText () { + return this.output; + } + + getMatches () { + return this.matches; + } +}; diff --git a/src/helpers.js b/src/helpers.js index ed33147..14d8d59 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -10,7 +10,7 @@ if (typeof this === 'undefined' && typeof window !== 'undefined') { showdown.helper.document = window.document; } else { if (typeof this.document === 'undefined' && typeof this.window === 'undefined') { - var jsdom = require('jsdom'); + let jsdom = require('jsdom'); this.window = new jsdom.JSDOM('', {}).window; // jshint ignore:line } showdown.helper.document = this.window.document; @@ -19,7 +19,7 @@ if (typeof this === 'undefined' && typeof window !== 'undefined') { /** * Check if var is string * @static - * @param {string} a + * @param {*} a * @returns {boolean} */ showdown.helper.isString = function (a) { @@ -27,6 +27,16 @@ showdown.helper.isString = function (a) { return (typeof a === 'string' || a instanceof String); }; +/** + * Check if var is a number + * @static + * @param {*} a + * @returns {boolean} + */ +showdown.helper.isNumber = function (a) { + return !isNaN(a); +}; + /** * Check if var is a function * @static @@ -35,7 +45,7 @@ showdown.helper.isString = function (a) { */ showdown.helper.isFunction = function (a) { 'use strict'; - var getType = {}; + let getType = {}; return a && getType.toString.call(a) === '[object Function]'; }; @@ -69,6 +79,20 @@ showdown.helper.isUndefined = function (value) { return typeof value === 'undefined'; }; +/** + * Check if value is an object (excluding arrays) + * @param {*} value + * @returns {boolean} + */ +showdown.helper.isObject = function (value) { + 'use strict'; + return ( + typeof value === 'object' && + !Array.isArray(value) && + value !== null + ); +}; + /** * ForEach helper function * Iterates over Arrays and Objects (own properties only) @@ -94,11 +118,11 @@ showdown.helper.forEach = function (obj, callback) { if (typeof obj.forEach === 'function') { obj.forEach(callback); } else if (showdown.helper.isArray(obj)) { - for (var i = 0; i < obj.length; i++) { + for (let i = 0; i < obj.length; i++) { callback(obj[i], i, obj); } } else if (typeof (obj) === 'object') { - for (var prop in obj) { + for (let prop in obj) { if (obj.hasOwnProperty(prop)) { callback(obj[prop], prop, obj); } @@ -109,7 +133,7 @@ showdown.helper.forEach = function (obj, callback) { }; /** - * Standardidize extension name + * Standardize extension name * @static * @param {string} s extension name * @returns {string} @@ -121,7 +145,7 @@ showdown.helper.stdExtName = function (s) { function escapeCharactersCallback (wholeMatch, m1) { 'use strict'; - var charCodeToEscape = m1.charCodeAt(0); + let charCodeToEscape = m1.charCodeAt(0); return '¨E' + charCodeToEscape + 'E'; } @@ -146,21 +170,21 @@ showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash 'use strict'; // First we have to escape the escape characters so that // we can build a character class out of them - var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])'; + let regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])'; if (afterBackslash) { regexString = '\\\\' + regexString; } - var regex = new RegExp(regexString, 'g'); + let regex = new RegExp(regexString, 'g'); text = text.replace(regex, escapeCharactersCallback); return text; }; -var rgxFindMatchPos = function (str, left, right, flags) { +let rgxFindMatchPos = function (str, left, right, flags) { 'use strict'; - var f = flags || '', + let f = flags || '', g = f.indexOf('g') > -1, x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')), l = new RegExp(left, f.replace(/g/g, '')), @@ -178,7 +202,7 @@ var rgxFindMatchPos = function (str, left, right, flags) { } else if (t) { if (!--t) { end = m.index + m[0].length; - var obj = { + let obj = { left: {start: start, end: s}, match: {start: s, end: m.index}, right: {start: m.index, end: end}, @@ -228,10 +252,10 @@ var rgxFindMatchPos = function (str, left, right, flags) { showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) { 'use strict'; - var matchPos = rgxFindMatchPos (str, left, right, flags), + let matchPos = rgxFindMatchPos (str, left, right, flags), results = []; - for (var i = 0; i < matchPos.length; ++i) { + for (let i = 0; i < matchPos.length; ++i) { results.push([ str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), str.slice(matchPos[i].match.start, matchPos[i].match.end), @@ -255,22 +279,22 @@ showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right 'use strict'; if (!showdown.helper.isFunction(replacement)) { - var repStr = replacement; + let repStr = replacement; replacement = function () { return repStr; }; } - var matchPos = rgxFindMatchPos(str, left, right, flags), + let matchPos = rgxFindMatchPos(str, left, right, flags), finalStr = str, lng = matchPos.length; if (lng > 0) { - var bits = []; + let bits = []; if (matchPos[0].wholeMatch.start !== 0) { bits.push(str.slice(0, matchPos[0].wholeMatch.start)); } - for (var i = 0; i < lng; ++i) { + for (let i = 0; i < lng; ++i) { bits.push( replacement( str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end), @@ -309,7 +333,7 @@ showdown.helper.regexIndexOf = function (str, regex, fromIndex) { if (!(regex instanceof RegExp)) { throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp'; } - var indexOf = str.substring(fromIndex || 0).search(regex); + let indexOf = str.substring(fromIndex || 0).search(regex); return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf; }; @@ -338,7 +362,8 @@ showdown.helper.splitAtIndex = function (str, index) { */ /*jshint bitwise: false*/ function xmur3 (str) { - for (var i = 0, h = 1779033703 ^ str.length; i < str.length; i++) { + let h; + for (let i = 0, h = 1779033703 ^ str.length; i < str.length; i++) { h = Math.imul(h ^ str.charCodeAt(i), 3432918353); h = h << 13 | h >>> 19; } @@ -359,7 +384,7 @@ function xmur3 (str) { /*jshint bitwise: false*/ function mulberry32 (a) { return function () { - var t = a += 0x6D2B79F5; + let t = a += 0x6D2B79F5; t = Math.imul(t ^ t >>> 15, t | 1); t ^= t + Math.imul(t ^ t >>> 7, t | 61); return ((t ^ t >>> 14) >>> 0) / 4294967296; @@ -376,7 +401,7 @@ function mulberry32 (a) { */ showdown.helper.encodeEmailAddress = function (mail) { 'use strict'; - var encode = [ + let encode = [ function (ch) { return '&#' + ch.charCodeAt(0) + ';'; }, @@ -389,14 +414,14 @@ showdown.helper.encodeEmailAddress = function (mail) { ]; // RNG seeded with mail, so that we can get determined results for each email. - var rand = mulberry32(xmur3(mail)); + let rand = mulberry32(xmur3(mail)); mail = mail.replace(/./g, function (ch) { if (ch === '@') { // this *must* be encoded. I insist. ch = encode[Math.floor(rand() * 2)](ch); } else { - var r = rand(); + let r = rand(); // roughly 10% raw, 45% hex, 45% dec ch = ( r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch) @@ -440,7 +465,7 @@ showdown.helper.repeat = function (str, count) { throw new RangeError('repeat count must not overflow maximum string size'); } /*jshint bitwise: true*/ - var maxCount = str.length * count; + let maxCount = str.length * count; count = Math.floor(Math.log(count) / Math.log(2)); while (count) { str += str; @@ -504,9 +529,9 @@ showdown.helper._hashHTMLSpan = function (html, globals) { */ showdown.helper.applyBaseUrl = function (baseUrl, url) { // Only prepend if given a base URL and the path is not absolute. - if (baseUrl && !this.isAbsolutePath(url)) { - var urlResolve = require('url').resolve; - url = urlResolve(baseUrl, url); + if (baseUrl && baseUrl !== '' && !showdown.helper.isAbsolutePath(url)) { + let urlResolve = new showdown.helper.URLUtils(url, baseUrl); + url = urlResolve.href; } return url; @@ -523,77 +548,212 @@ showdown.helper.isAbsolutePath = function (path) { return /(^([a-z]+:)?\/\/)|(^#)/i.test(path); }; +showdown.helper.URLUtils = function (url, baseURL) { + const pattern2 = /^([^:\/?#]+:)?(?:\/\/(?:([^:@\/?#]*)(?::([^:@\/?#]*))?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/; + + let m = String(url) + .trim() + .match(pattern2); + if (!m) { + throw new RangeError(); + } + let protocol = m[1] || ''; + let username = m[2] || ''; + let password = m[3] || ''; + let host = m[4] || ''; + let hostname = m[5] || ''; + let port = m[6] || ''; + let pathname = m[7] || ''; + let search = m[8] || ''; + let hash = m[9] || ''; + if (baseURL !== undefined) { + let base = new showdown.helper.URLUtils(baseURL); + let flag = protocol === '' && host === '' && username === ''; + if (flag && pathname === '' && search === '') { + search = base.search; + } + if (flag && pathname.charAt(0) !== '/') { + pathname = (pathname !== '' ? (((base.host !== '' || base.username !== '') && base.pathname === '' ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + pathname) : base.pathname); + } + // dot segments removal + let output = []; + pathname.replace(/^(\.\.?(\/|$))+/, '') + .replace(/\/(\.(\/|$))+/g, '/') + .replace(/\/\.\.$/, '/../') + .replace(/\/?[^\/]*/g, function (p) { + if (p === '/..') { + output.pop(); + } else { + output.push(p); + } + }); + pathname = output.join('').replace(/^\//, pathname.charAt(0) === '/' ? '/' : ''); + if (flag) { + port = base.port; + hostname = base.hostname; + host = base.host; + password = base.password; + username = base.username; + } + if (protocol === '') { + protocol = base.protocol; + } + } + this.origin = protocol + (protocol !== '' || host !== '' ? '//' : '') + host; + this.href = protocol + (protocol !== '' || host !== '' ? '//' : '') + (username !== '' ? username + (password !== '' ? ':' + password : '') + '@' : '') + host + pathname + search + hash; + this.protocol = protocol; + this.username = username; + this.password = password; + this.host = host; + this.hostname = hostname; + this.port = port; + this.pathname = pathname; + this.search = search; + this.hash = hash; +}; + /** - * Showdown's Event Object - * @param {string} name Name of the event - * @param {string} text Text - * @param {{}} params optional. params of the event - * @constructor + * Clones an object . If the second parameter is true, it deep clones the object. + * Note: It should not be used in other contexts than showdown, since this algorithm might fail for + * cyclic references, and dataypes such as Dates, RegExps, Typed Arrays, etc... + * @param {{}} obj Object to clone + * @param {boolean} [deep] [optional] If it should deep clone the object. Default is false */ -showdown.helper.Event = function (name, text, params) { +showdown.helper.cloneObject = function (obj, deep) { + deep = !!deep; + if (obj === null || typeof (obj) !== 'object') { + return obj; + } + + if (obj instanceof Date) { + return new Date(obj); + } + + if (!deep) { + let newObj = {}; + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = obj[key]; + } + } + return newObj; + } + + if (typeof structuredClone === 'function') { + return structuredClone(obj); + } else { + // note: This is not a real deep clone, and might work in weird ways if used in a dif + //this is costly and should be used sparsly + return JSON.parse(JSON.stringify(obj)); + } +}; + +/** + * Populate attributes in output text + * @param {{}} attributes + * @returns {string} + */ +showdown.helper._populateAttributes = function (attributes) { + let text = ''; + if (!attributes || !showdown.helper.isObject(attributes)) { + return text; + } + + for (let attr in attributes) { + if (attributes.hasOwnProperty(attr)) { + let key = attr, + val; + + // since class is a javascript reserved word we use classes + if (attr === 'classes') { + key = 'class'; + } + if (attributes[attr] === null || showdown.helper.isUndefined(attributes[attr])) { + val = null; + } else if (showdown.helper.isArray(attributes[attr])) { + val = attributes[attr].join(' '); + if (val === '') { + val = null; + } + } else if (showdown.helper.isString(attributes[attr])) { + val = attributes[attr]; + } else if (showdown.helper.isNumber(attributes[attr])) { + val = String(attributes[attr]); + } else { + throw new TypeError('Attribute "' + attr + '" must be either an array or string but ' + typeof attributes[attr] + ' given'); + } + // special attributes + switch (attr) { + // these attributes don't expect a value. If they are false, they should be removed. If they are true, + // they should be present but without any value + case 'checked': + case 'disabled': + if (val === true || val === 'true' || val === attr) { + text += ' ' + key; + } + // if falsy, they are just ignored + break; + + // default behavior for all other attributes types + default: + text += (val === null) ? '' : ' ' + key + '="' + val + '"'; + break; + } + } + } + + return text; +}; + +/** + * Remove one level of line-leading tabs or spaces + * @param {string} text + * @returns {string} + */ +showdown.helper.outdent = function (text) { 'use strict'; - - var regexp = params.regexp || null; - var matches = params.matches || {}; - var options = params.options || {}; - var converter = params.converter || null; - var globals = params.globals || {}; - - /** - * Get the name of the event - * @returns {string} - */ - this.getName = function () { - return name; - }; - - this.getEventName = function () { - return name; - }; - - this._stopExecution = false; - - this.parsedText = params.parsedText || null; - - this.getRegexp = function () { - return regexp; - }; - - this.getOptions = function () { - return options; - }; - - this.getConverter = function () { - return converter; - }; - - this.getGlobals = function () { - return globals; - }; - - this.getCapturedText = function () { + if (!showdown.helper.isString(text)) { return text; - }; + } + return text.replace(/^(\t| {1,4})/gm, ''); +}; - this.getText = function () { - return text; - }; +/** + * Validate options + * @param {{}} options + * @returns {{}} + */ +showdown.helper.validateOptions = function (options) { + if (!showdown.helper.isObject(options)) { + throw new TypeError('Options must be an object, but ' + typeof options + ' given'); + } - this.setText = function (newText) { - text = newText; - }; + let defaultOptions = getDefaultOpts(false); - this.getMatches = function () { - return matches; - }; + for (let opt in defaultOptions) { + if (!defaultOptions.hasOwnProperty(opt)) { + continue; + } - this.setMatches = function (newMatches) { - matches = newMatches; - }; + if (!options.hasOwnProperty(opt)) { + options[opt] = defaultOptions[opt].defaultValue; + } - this.preventDefault = function (bool) { - this._stopExecution = !bool; - }; + // TODO: dirty code. think about this we refactoring options + switch (opt) { + case 'prefixHeaderId': + if (typeof options[opt] !== 'boolean' && !showdown.helper.isString(options[opt])) { + throw new TypeError('Option prefixHeaderId must be of type boolean or string but ' + typeof options[opt] + ' given'); + } + break; + default: + if (typeof options[opt] !== defaultOptions[opt].type) { + throw new TypeError('Option ' + opt + ' must be of type ' + defaultOptions[opt].type + ' but ' + typeof options[opt] + ' given'); + } + } + } + //options.headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart); + return options; }; /** @@ -626,7 +786,7 @@ if (!Math.imul) { // automatically handled for our convienence: // 1. 0x003fffff /*opA & 0x000fffff*/ * 0x7fffffff /*opB*/ = 0x1fffff7fc00001 // 0x1fffff7fc00001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/ - var result = (opA & 0x003fffff) * opB; + let result = (opA & 0x003fffff) * opB; // 2. We can remove an integer coersion from the statement above because: // 0x1fffff7fc00001 + 0xffc00000 = 0x1fffffff800001 // 0x1fffffff800001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/ @@ -2432,24 +2592,24 @@ showdown.helper.emojis = { 'zzz': '\ud83d\udca4', /* special emojis :P */ - 'atom': '', - 'basecamp': '', - 'basecampy': '', - 'bowtie': '', - 'electron': '', - 'feelsgood': '', - 'finnadie': '', - 'goberserk': '', - 'godmode': '', - 'hurtrealbad': '', - 'neckbeard': '', - 'octocat': '', - 'rage1': '', - 'rage2': '', - 'rage3': '', - 'rage4': '', - 'shipit': '', - 'suspect': '', - 'trollface': '', - 'showdown': '' + 'atom': 'atom', + 'basecamp': 'basecamp', + 'basecampy': 'basecampy', + 'bowtie': 'bowtie', + 'electron': 'electron', + 'feelsgood': 'feelsgood', + 'finnadie': 'finnadie', + 'goberserk': 'goberserk', + 'godmode': 'godmode', + 'hurtrealbad': 'hurtrealbad', + 'neckbeard': 'neckbeard', + 'octocat': 'octocat', + 'rage1': 'rage1', + 'rage2': 'rage2', + 'rage3': 'rage3', + 'rage4': 'rage4', + 'shipit': 'shipit', + 'suspect': 'suspect', + 'trollface': 'trollface', + 'showdown': 'showdown' }; diff --git a/src/options.js b/src/options.js index 19deb66..fbdc1e0 100644 --- a/src/options.js +++ b/src/options.js @@ -5,7 +5,7 @@ function getDefaultOpts (simple) { 'use strict'; - var defaultOptions = { + let defaultOptions = { omitExtraWLInCodeBlocks: { defaultValue: false, describe: 'Omit the default extra whiteline added to code blocks', @@ -37,9 +37,9 @@ function getDefaultOpts (simple) { type: 'boolean' }, headerLevelStart: { - defaultValue: false, + defaultValue: 1, describe: 'The header blocks level start', - type: 'integer' + type: 'number' }, parseImgDimensions: { defaultValue: false, @@ -172,7 +172,7 @@ function getDefaultOpts (simple) { type: 'boolean' }, relativePathBaseUrl: { - defaultValue: false, + defaultValue: '', describe: 'Prepends a base URL to relative paths', type: 'string' }, @@ -180,8 +180,8 @@ function getDefaultOpts (simple) { if (simple === false) { return JSON.parse(JSON.stringify(defaultOptions)); } - var ret = {}; - for (var opt in defaultOptions) { + let ret = {}; + for (let opt in defaultOptions) { if (defaultOptions.hasOwnProperty(opt)) { ret[opt] = defaultOptions[opt].defaultValue; } @@ -191,9 +191,9 @@ function getDefaultOpts (simple) { function allOptionsOn () { 'use strict'; - var options = getDefaultOpts(true), + let options = getDefaultOpts(true), ret = {}; - for (var opt in options) { + for (let opt in options) { if (options.hasOwnProperty(opt)) { ret[opt] = true; } diff --git a/src/showdown.js b/src/showdown.js index 76a6e68..a361b93 100644 --- a/src/showdown.js +++ b/src/showdown.js @@ -183,6 +183,14 @@ showdown.subParser = function (name, func) { } }; +/** + * + * @returns {{}} + */ +showdown.getSubParserList = function () { + return parsers; +}; + /** * Gets or registers an extension * @static diff --git a/src/subParsers/makehtml/blockGamut.js b/src/subParsers/makehtml/blockGamut.js index 7a9b2b6..2bb38d5 100644 --- a/src/subParsers/makehtml/blockGamut.js +++ b/src/subParsers/makehtml/blockGamut.js @@ -1,23 +1,37 @@ -/** - * These are all the transformations that form block-level - * tags like paragraphs, headers, and list items. - */ +//// +// makehtml/blockGamut.js +// Copyright (c) 2018 ShowdownJS +// +// These are all the transformations that form block-level +// tags like paragraphs, headers, and list items. +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.blockGamut', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.blockGamut.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.blockGamut.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; // we parse blockquotes first so that we can have headings and hrs // inside blockquotes - text = showdown.subParser('makehtml.blockQuotes')(text, options, globals); - text = showdown.subParser('makehtml.headers')(text, options, globals); + text = showdown.subParser('makehtml.blockquote')(text, options, globals); + text = showdown.subParser('makehtml.heading')(text, options, globals); // Do Horizontal Rules: text = showdown.subParser('makehtml.horizontalRule')(text, options, globals); - text = showdown.subParser('makehtml.lists')(text, options, globals); - text = showdown.subParser('makehtml.codeBlocks')(text, options, globals); - text = showdown.subParser('makehtml.tables')(text, options, globals); + text = showdown.subParser('makehtml.list')(text, options, globals); + text = showdown.subParser('makehtml.codeBlock')(text, options, globals); + text = showdown.subParser('makehtml.table')(text, options, globals); // We already ran _HashHTMLBlocks() before, in Markdown(), but that // was to escape raw HTML in the original Markdown source. This time, @@ -26,7 +40,11 @@ showdown.subParser('makehtml.blockGamut', function (text, options, globals) { text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals); text = showdown.subParser('makehtml.paragraphs')(text, options, globals); - text = globals.converter._dispatch('makehtml.blockGamut.after', text, options, globals).getText(); - - return text; + let afterEvent = new showdown.Event('makehtml.blockGamut.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/blockQuotes.js b/src/subParsers/makehtml/blockQuotes.js deleted file mode 100644 index 256f3d7..0000000 --- a/src/subParsers/makehtml/blockQuotes.js +++ /dev/null @@ -1,42 +0,0 @@ -showdown.subParser('makehtml.blockQuotes', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.blockQuotes.before', text, options, globals).getText(); - - // add a couple extra lines after the text and endtext mark - text = text + '\n\n'; - - var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm; - - if (options.splitAdjacentBlockquotes) { - rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm; - } - - text = text.replace(rgx, function (bq) { - // attacklab: hack around Konqueror 3.5.4 bug: - // "----------bug".replace(/^-/g,"") == "bug" - bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting - - // attacklab: clean up hack - bq = bq.replace(/¨0/g, ''); - - bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines - bq = showdown.subParser('makehtml.githubCodeBlocks')(bq, options, globals); - bq = showdown.subParser('makehtml.blockGamut')(bq, options, globals); // recurse - - bq = bq.replace(/(^|\n)/g, '$1 '); - // These leading spaces screw with
 content, so we need to fix that:
-    bq = bq.replace(/(\s*
[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
-      var pre = m1;
-      // attacklab: hack around Konqueror 3.5.4 bug:
-      pre = pre.replace(/^  /mg, '¨0');
-      pre = pre.replace(/¨0/g, '');
-      return pre;
-    });
-
-    return showdown.subParser('makehtml.hashBlock')('
\n' + bq + '\n
', options, globals); - }); - - text = globals.converter._dispatch('makehtml.blockQuotes.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/blockquote.js b/src/subParsers/makehtml/blockquote.js new file mode 100644 index 0000000..4f71133 --- /dev/null +++ b/src/subParsers/makehtml/blockquote.js @@ -0,0 +1,94 @@ +//// +// makehtml/blockquote.js +// Copyright (c) 2018 ShowdownJS +// +// Transforms MD blockquotes into `
` html entities +// +// Markdown uses email-style > characters for blockquoting. +// Markdown allows you to be lazy and only put the > before the first line of a hard-wrapped paragraph but +// it looks best if the text is hard wrapped with a > before every line. +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + +showdown.subParser('makehtml.blockquote', function (text, options, globals) { + 'use strict'; + + let startEvent = new showdown.Event('makehtml.blockquote.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + // add a couple extra lines after the text and endtext mark + text = text + '\n\n'; + + let pattern = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm; + + if (options.splitAdjacentBlockquotes) { + pattern = /^ {0,3}>[\s\S]*?\n\n/gm; + } + + text = text.replace(pattern, function (bq) { + let otp, + attributes = {}, + wholeMatch = bq; + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting + // attacklab: clean up hack + bq = bq.replace(/¨0/g, ''); + bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines + + let captureStartEvent = new showdown.Event('makehtml.blockquote.onCapture', bq); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + blockquote: bq + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + + } else { + bq = captureStartEvent.matches.blockquote; + bq = showdown.subParser('makehtml.githubCodeBlock')(bq, options, globals); + bq = showdown.subParser('makehtml.blockGamut')(bq, options, globals); // recurse + bq = bq.replace(/(^|\n)/g, '$1 '); + // These leading spaces screw with
 content, so we need to fix that:
+      bq = bq.replace(/(\s*
[^\r]+?<\/pre>)/gm, function (wm, m1) {
+        return m1.replace(/^ {2}/mg, '');
+      });
+      attributes = captureStartEvent.attributes;
+      otp = '\n' +  bq + '\n
'; + } + + let beforeHashEvent = new showdown.Event('makehtml.blockquote.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + return showdown.subParser('makehtml.hashBlock')(otp, options, globals); + }); + + let afterEvent = new showdown.Event('makehtml.blockquote.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; +}); diff --git a/src/subParsers/makehtml/codeBlock.js b/src/subParsers/makehtml/codeBlock.js new file mode 100644 index 0000000..c8cc24a --- /dev/null +++ b/src/subParsers/makehtml/codeBlock.js @@ -0,0 +1,95 @@ +//// +// makehtml/codeBlock.js +// Copyright (c) 2022 ShowdownJS +// +// Process Markdown `
` blocks.
+//
+// ***Author:***
+// - Estêvão Soares dos Santos (Tivie) 
+////
+
+
+showdown.subParser('makehtml.codeBlock', function (text, options, globals) {
+  'use strict';
+
+  let startEvent = new showdown.Event('makehtml.codeBlock.onStart', text);
+  startEvent
+    .setOutput(text)
+    ._setGlobals(globals)
+    ._setOptions(options);
+  startEvent = globals.converter.dispatch(startEvent);
+  text = startEvent.output;
+
+  // sentinel workarounds for lack of \A and \Z, safari\khtml bug
+  text += '¨0';
+
+  let pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
+  text = text.replace(pattern, function (wholeMatch, m1, m2) {
+    let codeblock = m1,
+        nextChar = m2,
+        end = '\n',
+        otp,
+        attributes = {
+          pre: {},
+          code: {}
+        };
+
+    let captureStartEvent = new showdown.Event('makehtml.codeBlock.onCapture', codeblock);
+    captureStartEvent
+      .setOutput(null)
+      ._setGlobals(globals)
+      ._setOptions(options)
+      .setRegexp(pattern)
+      .setMatches({
+        _wholeMatch: wholeMatch,
+        codeblock: codeblock
+      })
+      .setAttributes(attributes);
+    captureStartEvent = globals.converter.dispatch(captureStartEvent);
+
+    // if something was passed as output, it takes precedence
+    // and will be used as output
+    if (captureStartEvent.output && captureStartEvent.output !== '') {
+      otp = captureStartEvent.output;
+    } else {
+      codeblock = captureStartEvent.matches.codeblock;
+      codeblock = showdown.helper.outdent(codeblock);
+      codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals);
+      codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals);
+      codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
+      codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
+      attributes = captureStartEvent.attributes;
+
+      otp = '
';
+      if (!showdown.helper.isUndefined(attributes)) {
+        otp = '';
+        otp += '';
+      }
+      if (options.omitExtraWLInCodeBlocks) {
+        end = '';
+      }
+      otp += codeblock + end + '
'; + } + + let beforeHashEvent = new showdown.Event('makehtml.codeBlock.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + return showdown.subParser('makehtml.hashBlock')(otp, options, globals) + nextChar; + }); + + // strip sentinel + text = text.replace(/¨0/, ''); + + let afterEvent = new showdown.Event('makehtml.codeBlock.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; +}); diff --git a/src/subParsers/makehtml/codeBlocks.js b/src/subParsers/makehtml/codeBlocks.js deleted file mode 100644 index ed9da66..0000000 --- a/src/subParsers/makehtml/codeBlocks.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Process Markdown `
` blocks.
- */
-showdown.subParser('makehtml.codeBlocks', function (text, options, globals) {
-  'use strict';
-
-  text = globals.converter._dispatch('makehtml.codeBlocks.before', text, options, globals).getText();
-
-  // sentinel workarounds for lack of \A and \Z, safari\khtml bug
-  text += '¨0';
-
-  var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
-  text = text.replace(pattern, function (wholeMatch, m1, m2) {
-    var codeblock = m1,
-        nextChar = m2,
-        end = '\n';
-
-    codeblock = showdown.subParser('makehtml.outdent')(codeblock, options, globals);
-    codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals);
-    codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals);
-    codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
-    codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
-
-    if (options.omitExtraWLInCodeBlocks) {
-      end = '';
-    }
-
-    codeblock = '
' + codeblock + end + '
'; - - return showdown.subParser('makehtml.hashBlock')(codeblock, options, globals) + nextChar; - }); - - // strip sentinel - text = text.replace(/¨0/, ''); - - text = globals.converter._dispatch('makehtml.codeBlocks.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/codeSpan.js b/src/subParsers/makehtml/codeSpan.js new file mode 100644 index 0000000..1c135a3 --- /dev/null +++ b/src/subParsers/makehtml/codeSpan.js @@ -0,0 +1,101 @@ +//// +// makehtml/codeSpan.js +// Copyright (c) 2018 ShowdownJS +// +// Transforms MD code spans into `` html entities +// +// Backtick quotes are used for spans. +// +// You can use multiple backticks as the delimiters if you want to +// include literal backticks in the code span. So, this input: +// +// Just type ``foo `bar` baz`` at the prompt. +// +// Will translate to: +// +//

Just type foo `bar` baz at the prompt.

+// +// There's no arbitrary limit to the number of backticks you +// can use as delimters. If you need three consecutive backticks +// in your code, use four for delimiters, etc. +// +// You can use spaces to get literal backticks at the edges: +// ... type `` `bar` `` ... +// +// Turns to: +// ... type `bar` ... +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + +showdown.subParser('makehtml.codeSpan', function (text, options, globals) { + 'use strict'; + + let startEvent = new showdown.Event('makehtml.codeSpan.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + + startEvent = globals.converter.dispatch(startEvent); + + text = startEvent.output; + + if (showdown.helper.isUndefined((text))) { + text = ''; + } + + let pattern = /(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm; + + text = text.replace(pattern, function (wholeMatch, m1, m2, c) { + let otp, + attributes = {}; + + c = c.replace(/^([ \t]*)/g, ''); // leading whitespace + c = c.replace(/[ \t]*$/g, ''); // trailing whitespace + + let captureStartEvent = new showdown.Event('makehtml.codeSpan.onCapture', c); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + code: c + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = m1 + captureStartEvent.output; + } else { + c = captureStartEvent.matches.code; + c = showdown.subParser('makehtml.encodeCode')(c, options, globals); + otp = m1 + '' + c + '
'; + } + + let beforeHashEvent = new showdown.Event('makehtml.codeSpan.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + return showdown.subParser('makehtml.hashHTMLSpans')(otp, options, globals); + } + ); + + let afterEvent = new showdown.Event('makehtml.codeSpan.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; +}); diff --git a/src/subParsers/makehtml/codeSpans.js b/src/subParsers/makehtml/codeSpans.js deleted file mode 100644 index e968180..0000000 --- a/src/subParsers/makehtml/codeSpans.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * - * * Backtick quotes are used for spans. - * - * * You can use multiple backticks as the delimiters if you want to - * include literal backticks in the code span. So, this input: - * - * Just type ``foo `bar` baz`` at the prompt. - * - * Will translate to: - * - *

Just type foo `bar` baz at the prompt.

- * - * There's no arbitrary limit to the number of backticks you - * can use as delimters. If you need three consecutive backticks - * in your code, use four for delimiters, etc. - * - * * You can use spaces to get literal backticks at the edges: - * - * ... type `` `bar` `` ... - * - * Turns to: - * - * ... type `bar` ... - */ -showdown.subParser('makehtml.codeSpans', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.codeSpans.before', text, options, globals).getText(); - - if (typeof (text) === 'undefined') { - text = ''; - } - text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, - function (wholeMatch, m1, m2, m3) { - var c = m3; - c = c.replace(/^([ \t]*)/g, ''); // leading whitespace - c = c.replace(/[ \t]*$/g, ''); // trailing whitespace - c = showdown.subParser('makehtml.encodeCode')(c, options, globals); - c = m1 + '' + c + ''; - c = showdown.subParser('makehtml.hashHTMLSpans')(c, options, globals); - return c; - } - ); - - text = globals.converter._dispatch('makehtml.codeSpans.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/completeHTMLDocument.js b/src/subParsers/makehtml/completeHTMLDocument.js index af33976..4f7db4d 100644 --- a/src/subParsers/makehtml/completeHTMLDocument.js +++ b/src/subParsers/makehtml/completeHTMLDocument.js @@ -1,6 +1,14 @@ -/** - * Create a full HTML document from the processed markdown - */ +//// +// makehtml/completeHTMLDocument.js +// Copyright (c) 2018 ShowdownJS +// +// Create a full HTML document from the processed markdown +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.completeHTMLDocument', function (text, options, globals) { 'use strict'; @@ -8,9 +16,15 @@ showdown.subParser('makehtml.completeHTMLDocument', function (text, options, glo return text; } - text = globals.converter._dispatch('makehtml.completeHTMLDocument.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.completeHTMLDocument.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; - var doctype = 'html', + let doctype = 'html', doctypeParsed = '\n', title = '', charset = '\n', @@ -25,7 +39,7 @@ showdown.subParser('makehtml.completeHTMLDocument', function (text, options, glo } } - for (var meta in globals.metadata.parsed) { + for (let meta in globals.metadata.parsed) { if (globals.metadata.parsed.hasOwnProperty(meta)) { switch (meta.toLowerCase()) { case 'doctype': @@ -57,6 +71,11 @@ showdown.subParser('makehtml.completeHTMLDocument', function (text, options, glo text = doctypeParsed + '\n\n' + title + charset + metadata + '\n\n' + text.trim() + '\n\n'; - text = globals.converter._dispatch('makehtml.completeHTMLDocument.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.completeHTMLDocument.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/detab.js b/src/subParsers/makehtml/detab.js index 41e1180..be16e37 100644 --- a/src/subParsers/makehtml/detab.js +++ b/src/subParsers/makehtml/detab.js @@ -1,9 +1,24 @@ -/** - * Convert all tabs to spaces - */ +//// +// makehtml/detab.js +// Copyright (c) 2018 ShowdownJS +// +// Convert all tabs to spaces +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.detab', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.detab.before', text, options, globals).getText(); + + let startEvent = new showdown.Event('makehtml.detab.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; // expand first n-1 tabs text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width @@ -28,6 +43,11 @@ showdown.subParser('makehtml.detab', function (text, options, globals) { text = text.replace(/¨A/g, ' '); // g_tab_width text = text.replace(/¨B/g, ''); - text = globals.converter._dispatch('makehtml.detab.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.detab.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/ellipsis.js b/src/subParsers/makehtml/ellipsis.js index 757fca0..563d0b7 100644 --- a/src/subParsers/makehtml/ellipsis.js +++ b/src/subParsers/makehtml/ellipsis.js @@ -1,3 +1,14 @@ +//// +// makehtml/ellipsis.js +// Copyright (c) 2018 ShowdownJS +// +// transform three dots (...) into ellipsis (…) +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.ellipsis', function (text, options, globals) { 'use strict'; @@ -5,11 +16,21 @@ showdown.subParser('makehtml.ellipsis', function (text, options, globals) { return text; } - text = globals.converter._dispatch('makehtml.ellipsis.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.ellipsis.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; text = text.replace(/\.\.\./g, '…'); - text = globals.converter._dispatch('makehtml.ellipsis.after', text, options, globals).getText(); - - return text; + let afterEvent = new showdown.Event('makehtml.ellipsis.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/emoji.js b/src/subParsers/makehtml/emoji.js index e70d762..7a868a1 100644 --- a/src/subParsers/makehtml/emoji.js +++ b/src/subParsers/makehtml/emoji.js @@ -1,8 +1,15 @@ -/** - * Turn emoji codes into emojis - * - * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis - */ +//// +// makehtml/emoji.js +// Copyright (c) 2018 ShowdownJS +// +// Turn emoji codes into emojis +// List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.emoji', function (text, options, globals) { 'use strict'; @@ -10,18 +17,56 @@ showdown.subParser('makehtml.emoji', function (text, options, globals) { return text; } - text = globals.converter._dispatch('makehtml.emoji.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.emoji.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; - var emojiRgx = /:([\S]+?):/g; + let pattern = /:(\S+?):/g; - text = text.replace(emojiRgx, function (wm, emojiCode) { - if (showdown.helper.emojis.hasOwnProperty(emojiCode)) { - return showdown.helper.emojis[emojiCode]; + text = text.replace(pattern, function (wholeMatch, emojiCode) { + if (!showdown.helper.emojis.hasOwnProperty(emojiCode)) { + return wholeMatch; } - return wm; + let otp = ''; + let captureStartEvent = new showdown.Event('makehtml.emoji.onCapture', emojiCode); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + emojiCode: emojiCode + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + + // if something was passed as output, it takes precedence and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + otp = showdown.helper.emojis[emojiCode]; + } + + let beforeHashEvent = new showdown.Event('makehtml.emoji.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + return beforeHashEvent.output; }); - text = globals.converter._dispatch('makehtml.emoji.after', text, options, globals).getText(); - - return text; + let afterEvent = new showdown.Event('makehtml.emoji.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/emphasisAndStrong.js b/src/subParsers/makehtml/emphasisAndStrong.js new file mode 100644 index 0000000..73ceff5 --- /dev/null +++ b/src/subParsers/makehtml/emphasisAndStrong.js @@ -0,0 +1,173 @@ +//// +// makehtml/emphasisAndStrong.js +// Copyright (c) 2022 ShowdownJS +// +// Transforms MD emphasis and strong into `` and `` html entities +// +// Markdown treats asterisks (*) and underscores (_) as indicators of emphasis. +// Text wrapped with one * or _ will be wrapped with an HTML tag; +// double *’s or _’s will be wrapped with an HTML tag +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + +showdown.subParser('makehtml.emphasisAndStrong', function (text, options, globals) { + 'use strict'; + + let startEvent = new showdown.Event('makehtml.emphasisAndStrong.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + /** + * @param {string} txt + * @param {string} tags + * @param {string} wholeMatch + * @param {RegExp} pattern + * @returns {string} + */ + function parseInside (txt, tags, wholeMatch, pattern) { + let otp = 'ERROR', + attributes, + subEventName; + + switch (tags) { + case '': + attributes = { + em: {} + }; + subEventName = 'emphasis'; + break; + case '': + attributes = { + strong: {} + }; + subEventName = 'strong'; + break; + case '': + attributes = { + em: {}, + strong: {} + }; + subEventName = 'emphasisAndStrong'; + break; + default: + attributes = {}; + subEventName = 'emphasisAndStrong'; + break; + } + + let captureStartEvent = new showdown.Event('makehtml.emphasisAndStrong.' + subEventName + '.onCapture', txt); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + text: txt + }) + .setAttributes(attributes); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + attributes = captureStartEvent.attributes; + if (showdown.helper.isUndefined(attributes.em)) { + attributes.em = {}; + } + if (showdown.helper.isUndefined(attributes.strong)) { + attributes.strong = {}; + } + switch (tags) { + case '': + otp = '' + txt + ''; + break; + case '': + otp = '' + txt + ''; + break; + case '': + otp = '' + + '' + + txt + + '' + + ''; + break; + } + } + + let beforeHashEvent = new showdown.Event('makehtml.emphasisAndStrong.' + subEventName + '.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + return otp; + } + + // it's faster to have 3 separate regexes for each case than have just one + // because of backtracking, in some cases, it could lead to an exponential effect + // called "catastrophic backtrace". Ominous! + const lmwuStrongEmRegex = /\b___(\S[\s\S]*?)___\b/g, + lmwuStrongRegex = /\b__(\S[\s\S]*?)__\b/g, + lmwuEmRegex = /\b_(\S[\s\S]*?)_\b/g, + underscoreStrongEmRegex = /___(\S[\s\S]*?)___/g, + unserscoreStrongRegex = /__(\S[\s\S]*?)__/g, + unserscoreEmRegex = /_([^\s_][\s\S]*?)_/g, + + asteriskStrongEm = /\*\*\*(\S[\s\S]*?)\*\*\*/g, + asteriskStrong = /\*\*(\S[\s\S]*?)\*\*/g, + asteriskEm = /\*([^\s*][\s\S]*?)\*/g; + + + // Parse underscores + if (options.literalMidWordUnderscores) { + text = text.replace(lmwuStrongEmRegex, function (wm, txt) { + return parseInside (txt, '', wm, lmwuStrongEmRegex); + }); + text = text.replace(lmwuStrongRegex, function (wm, txt) { + return parseInside (txt, '', wm, lmwuStrongRegex); + }); + text = text.replace(lmwuEmRegex, function (wm, txt) { + return parseInside (txt, '', wm, lmwuEmRegex); + }); + } else { + text = text.replace(underscoreStrongEmRegex, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', wm, underscoreStrongEmRegex) : wm; + }); + text = text.replace(unserscoreStrongRegex, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', wm, unserscoreStrongRegex) : wm; + }); + text = text.replace(unserscoreEmRegex, function (wm, m) { + // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it) + return (/\S$/.test(m)) ? parseInside (m, '', wm, unserscoreEmRegex) : wm; + }); + } + + // Now parse asterisks + text = text.replace(asteriskStrongEm, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', wm, asteriskStrongEm) : wm; + }); + text = text.replace(asteriskStrong, function (wm, m) { + return (/\S$/.test(m)) ? parseInside (m, '', wm, asteriskStrong) : wm; + }); + text = text.replace(asteriskEm, function (wm, m) { + // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it) + return (/\S$/.test(m)) ? parseInside (m, '', wm, asteriskEm) : wm; + }); + //} + let afterEvent = new showdown.Event('makehtml.emphasisAndStrong.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; +}); diff --git a/src/subParsers/makehtml/encodeAmpsAndAngles.js b/src/subParsers/makehtml/encodeAmpsAndAngles.js index e69322d..f62ae0c 100644 --- a/src/subParsers/makehtml/encodeAmpsAndAngles.js +++ b/src/subParsers/makehtml/encodeAmpsAndAngles.js @@ -1,13 +1,28 @@ -/** - * Smart processing for ampersands and angle brackets that need to be encoded. - */ +//// +// makehtml/encodeAmpsAndAngles.js +// Copyright (c) 2018 ShowdownJS +// +// Smart processing for ampersands and angle brackets that need to be encoded. +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.encodeAmpsAndAngles', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.before', text, options, globals).getText(); + + let startEvent = new showdown.Event('makehtml.encodeAmpsAndAngles.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: // http://bumppo.net/projects/amputator/ - text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&'); + text = text.replace(/&(?!#?[xX]?(?:[\da-fA-F]+|\w+);)/g, '&'); // Encode naked <'s text = text.replace(/<(?![a-z\/?$!])/gi, '<'); @@ -18,6 +33,11 @@ showdown.subParser('makehtml.encodeAmpsAndAngles', function (text, options, glob // Encode > text = text.replace(/>/g, '>'); - text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.encodeAmpsAndAngles.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/encodeBackslashEscapes.js b/src/subParsers/makehtml/encodeBackslashEscapes.js index 12d040b..f6e39ab 100644 --- a/src/subParsers/makehtml/encodeBackslashEscapes.js +++ b/src/subParsers/makehtml/encodeBackslashEscapes.js @@ -1,21 +1,42 @@ -/** - * Returns the string, with after processing the following backslash escape sequences. - * - * attacklab: The polite way to do this is with the new escapeCharacters() function: - * - * text = escapeCharacters(text,"\\",true); - * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); - * - * ...but we're sidestepping its use of the (slow) RegExp constructor - * as an optimization for Firefox. This function gets called a LOT. - */ +//// +// makehtml/encodeBackslashEscapes.js +// Copyright (c) 2018 ShowdownJS +// +// Returns the string, with after processing the following backslash escape sequences. +// +// The polite way to do this is with the new escapeCharacters() function: +// +// text = escapeCharacters(text,"\\",true); +// text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); +// +// ...but we're sidestepping its use of the (slow) RegExp constructor +// as an optimization for Firefox. This function gets called a LOT. +// +// ***Author:*** +// - attacklab +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.encodeBackslashEscapes', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.before', text, options, globals).getText(); + + let startEvent = new showdown.Event('makehtml.encodeBackslashEscapes.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback); text = text.replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g, showdown.helper.escapeCharactersCallback); - text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.encodeBackslashEscapes.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/encodeCode.js b/src/subParsers/makehtml/encodeCode.js index 84afaf7..019e5f4 100644 --- a/src/subParsers/makehtml/encodeCode.js +++ b/src/subParsers/makehtml/encodeCode.js @@ -1,12 +1,26 @@ -/** - * Encode/escape certain characters inside Markdown code runs. - * The point is that in code, these characters are literals, - * and lose their special Markdown meanings. - */ +//// +// makehtml/emoji.js +// Copyright (c) 2018 ShowdownJS +// +// Encode/escape certain characters inside Markdown code runs. +// The point is that in code, these characters are literals, +// and lose their special Markdown meanings. +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.encodeCode', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.encodeCode.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.encodeCode.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; // Encode all ampersands; HTML entities are not // entities within a Markdown code span. @@ -18,6 +32,11 @@ showdown.subParser('makehtml.encodeCode', function (text, options, globals) { // Now, escape characters that are magic in Markdown: .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback); - text = globals.converter._dispatch('makehtml.encodeCode.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.encodeCode.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/escapeSpecialCharsWithinTagAttributes.js b/src/subParsers/makehtml/escapeSpecialCharsWithinTagAttributes.js index 6819588..e2447c4 100644 --- a/src/subParsers/makehtml/escapeSpecialCharsWithinTagAttributes.js +++ b/src/subParsers/makehtml/escapeSpecialCharsWithinTagAttributes.js @@ -1,14 +1,29 @@ -/** - * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they - * don't conflict with their use in Markdown for code, italics and strong. - */ +//// +// makehtml/escapeSpecialCharsWithinTagAttributes.js +// Copyright (c) 2018 ShowdownJS +// +// Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they +// don't conflict with their use in Markdown for code, italics and strong. +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.before', text, options, globals).getText(); + + let startEvent = new showdown.Event('makehtml.escapeSpecialCharsWithinTagAttributes.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; // Build a regex to find HTML tags. - var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi, - comments = /-]|-[^>])(?:[^-]|-[^-])*)--)>/gi; + let tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi, + comments = /-]|-[^>])([^-]|-[^-])*)--)>/gi; text = text.replace(tags, function (wholeMatch) { return wholeMatch @@ -21,6 +36,11 @@ showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes', function (t .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback); }); - text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.escapeSpecialCharsWithinTagAttributes.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/githubCodeBlock.js b/src/subParsers/makehtml/githubCodeBlock.js new file mode 100644 index 0000000..7a98a66 --- /dev/null +++ b/src/subParsers/makehtml/githubCodeBlock.js @@ -0,0 +1,134 @@ +//// +// makehtml/githubCodeBlock.js +// Copyright (c) 2018 ShowdownJS +// +// Handle github codeblocks prior to running HashHTML so that +// HTML contained within the codeblock gets escaped properly +// Example: +// ```ruby +// def hello_world(x) +// puts "Hello, #{x}" +// end +// ``` +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + +showdown.subParser('makehtml.githubCodeBlock', function (text, options, globals) { + 'use strict'; + + // early exit if option is not enabled + if (!options.ghCodeBlocks) { + return text; + } + + let startEvent = new showdown.Event('makehtml.githubCodeBlock.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output + '¨0'; + + let pattern = /(?:^|\n) {0,3}(```+|~~~+) *([^\n\t`~]*)\n([\s\S]*?)\n {0,3}\1/g; + + text = text.replace(pattern, function (wholeMatch, delim, language, codeblock) { + let end = (options.omitExtraWLInCodeBlocks) ? '' : '\n', + otp, + attributes = { + pre: {}, + code: {}, + }; + + let captureStartEvent = new showdown.Event('makehtml.githubCodeBlock.onCapture', codeblock); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _whoteMatch: wholeMatch, + codeblock: codeblock, + infostring: language + }) + .setAttributes(attributes); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + + } else { + + // First parse the github code block + let infostring = captureStartEvent.matches.infostring; + let lang = infostring.trim().split(' ')[0]; + codeblock = captureStartEvent.matches.codeblock; + codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals); + codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals); + codeblock = codeblock + .replace(/^\n+/g, '') // trim leading newlines + .replace(/\n+$/g, ''); // trim trailing whitespace + + attributes = captureStartEvent.attributes; + otp = '
';
+      if (!showdown.helper.isUndefined(attributes)) {
+        otp = '';
+
+        // if the language has spaces followed by some other chars, according to the spec we should just ignore everything
+        // after the first space
+        if (infostring) {
+          if (!attributes.code) {
+            attributes.code = {};
+          }
+          if (!attributes.code.classes) {
+            attributes.code.classes = [];
+          }
+
+          if (attributes.code.classes) {
+            if (showdown.helper.isString(attributes.code.classes)) {
+              attributes.code.classes += ' ' + lang + ' language-' + lang;
+            } else if (showdown.helper.isArray(attributes.code.classes)) {
+              attributes.code.classes.push(lang);
+              attributes.code.classes.push('language-' + lang);
+            }
+          }
+        }
+
+        otp += '';
+      }
+      if (options.omitExtraWLInCodeBlocks) {
+        end = '';
+      }
+      otp += codeblock + end + '
'; + } + + let beforeHashEvent = new showdown.Event('makehtml.githubCodeBlock.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + otp = showdown.subParser('makehtml.hashBlock')(otp, options, globals); + + // Since GHCodeblocks can be false positives, we need to + // store the primitive text and the parsed text in a global var, + // and then return a token + return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: otp}) - 1) + 'G\n\n'; + }); + + // attacklab: strip sentinel + text = text.replace(/¨0/, ''); + + let afterEvent = new showdown.Event('makehtml.githubCodeBlock.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; +}); diff --git a/src/subParsers/makehtml/githubCodeBlocks.js b/src/subParsers/makehtml/githubCodeBlocks.js deleted file mode 100644 index c3a0fa5..0000000 --- a/src/subParsers/makehtml/githubCodeBlocks.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Handle github codeblocks prior to running HashHTML so that - * HTML contained within the codeblock gets escaped properly - * Example: - * ```ruby - * def hello_world(x) - * puts "Hello, #{x}" - * end - * ``` - */ -showdown.subParser('makehtml.githubCodeBlocks', function (text, options, globals) { - 'use strict'; - - // early exit if option is not enabled - if (!options.ghCodeBlocks) { - return text; - } - - text = globals.converter._dispatch('makehtml.githubCodeBlocks.before', text, options, globals).getText(); - - text += '¨0'; - - text = text.replace(/(?:^|\n) {0,3}(```+|~~~+) *([^\n\t`~]*)\n([\s\S]*?)\n {0,3}\1/g, function (wholeMatch, delim, language, codeblock) { - var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n'; - - // if the language has spaces followed by some other chars, according to the spec we should just ignore everything - // after the first space - language = language.trim().split(' ')[0]; - - // First parse the github code block - codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals); - codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals); - codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines - codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace - - codeblock = '
'; - - codeblock = showdown.subParser('makehtml.hashBlock')(codeblock, options, globals); - - // Since GHCodeblocks can be false positives, we need to - // store the primitive text and the parsed text in a global var, - // and then return a token - return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n'; - }); - - // attacklab: strip sentinel - text = text.replace(/¨0/, ''); - - return globals.converter._dispatch('makehtml.githubCodeBlocks.after', text, options, globals).getText(); -}); diff --git a/src/subParsers/makehtml/hashBlock.js b/src/subParsers/makehtml/hashBlock.js index c14948f..29b8034 100644 --- a/src/subParsers/makehtml/hashBlock.js +++ b/src/subParsers/makehtml/hashBlock.js @@ -1,8 +1,31 @@ +//// +// makehtml/hashBlock.js +// Copyright (c) 2018 ShowdownJS +// +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.hashBlock', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.hashBlock.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.hashBlock.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + text = text.replace(/(^\n+|\n+$)/g, ''); text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n'; - text = globals.converter._dispatch('makehtml.hashBlock.after', text, options, globals).getText(); - return text; + + let afterEvent = new showdown.Event('makehtml.hashBlock.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/hashCodeTags.js b/src/subParsers/makehtml/hashCodeTags.js index 6a77042..8ebb326 100644 --- a/src/subParsers/makehtml/hashCodeTags.js +++ b/src/subParsers/makehtml/hashCodeTags.js @@ -1,18 +1,37 @@ -/** - * Hash and escape elements that should not be parsed as markdown - */ +//// +// makehtml/hashCodeTags.js +// Copyright (c) 2018 ShowdownJS +// +// Hash and escape elements that should not be parsed as markdown +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.hashCodeTags', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.hashCodeTags.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.hashCodeTags.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; - var repFunc = function (wholeMatch, match, left, right) { - var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right; + let repFunc = function (wholeMatch, match, left, right) { + let codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right; return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C'; }; // Hash naked text = showdown.helper.replaceRecursiveRegExp(text, repFunc, ']*>', '', 'gim'); - text = globals.converter._dispatch('makehtml.hashCodeTags.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.hashCodeTags.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/hashElement.js b/src/subParsers/makehtml/hashElement.js index 1ed9b02..913ac65 100644 --- a/src/subParsers/makehtml/hashElement.js +++ b/src/subParsers/makehtml/hashElement.js @@ -2,7 +2,7 @@ showdown.subParser('makehtml.hashElement', function (text, options, globals) { 'use strict'; return function (wholeMatch, m1) { - var blockText = m1; + let blockText = m1; // Undo double lines blockText = blockText.replace(/\n\n/g, '\n'); diff --git a/src/subParsers/makehtml/hashHTMLBlocks.js b/src/subParsers/makehtml/hashHTMLBlocks.js index 039ec29..98339fb 100644 --- a/src/subParsers/makehtml/hashHTMLBlocks.js +++ b/src/subParsers/makehtml/hashHTMLBlocks.js @@ -1,8 +1,25 @@ +//// +// makehtml/hashHTMLBlocks.js +// Copyright (c) 2018 ShowdownJS +// +// Hash HTML blocks +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.hashHTMLBlocks.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.hashHTMLBlocks.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; - var blockTags = [ + let blockTags = [ 'pre', 'div', 'h1', @@ -40,7 +57,7 @@ showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) 'p' ], repFunc = function (wholeMatch, match, left, right) { - var txt = wholeMatch; + let txt = wholeMatch; // check if this html element is marked as markdown // if so, it's contents should be parsed as markdown if (left.search(/\bmarkdown\b/) !== -1) { @@ -57,9 +74,9 @@ showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) } // hash HTML Blocks - for (var i = 0; i < blockTags.length; ++i) { + for (let i = 0; i < blockTags.length; ++i) { - var opTagPos, + let opTagPos, rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'), patLeft = '<' + blockTags[i] + '\\b[^>]*>', patRight = ''; @@ -70,7 +87,7 @@ showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) //2. Split the text in that position - var subTexts = showdown.helper.splitAtIndex(text, opTagPos), + let subTexts = showdown.helper.splitAtIndex(text, opTagPos), //3. Match recursively newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im'); @@ -94,6 +111,11 @@ showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) text = text.replace(/\n\n( {0,3}<([?%])[^\r]*?\2>[ \t]*(?=\n{2,}))/g, showdown.subParser('makehtml.hashElement')(text, options, globals)); - text = globals.converter._dispatch('makehtml.hashHTMLBlocks.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.hashHTMLBlocks.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/hashHTMLSpans.js b/src/subParsers/makehtml/hashHTMLSpans.js index 304b2cc..0c06dde 100644 --- a/src/subParsers/makehtml/hashHTMLSpans.js +++ b/src/subParsers/makehtml/hashHTMLSpans.js @@ -1,9 +1,23 @@ -/** - * Hash span elements that should not be parsed as markdown - */ +//// +// makehtml/hashHTMLSpans.js +// Copyright (c) 2018 ShowdownJS +// +// Hash span elements that should not be parsed as markdown +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + showdown.subParser('makehtml.hashHTMLSpans', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.hashHTMLSpans.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.hashHTMLSpans.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; // Hash Self Closing tags text = text.replace(/<[^>]+?\/>/gi, function (wm) { @@ -25,34 +39,11 @@ showdown.subParser('makehtml.hashHTMLSpans', function (text, options, globals) { return showdown.helper._hashHTMLSpan(wm, globals); }); - text = globals.converter._dispatch('makehtml.hashHTMLSpans.after', text, options, globals).getText(); - return text; -}); - -/** - * Unhash HTML spans - */ -showdown.subParser('makehtml.unhashHTMLSpans', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.unhashHTMLSpans.before', text, options, globals).getText(); - - for (var i = 0; i < globals.gHtmlSpans.length; ++i) { - var repText = globals.gHtmlSpans[i], - // limiter to prevent infinite loop (assume 10 as limit for recurse) - limit = 0; - - while (/¨C(\d+)C/.test(repText)) { - var num = RegExp.$1; - repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]); - if (limit === 10) { - console.error('maximum nesting of 10 spans reached!!!'); - break; - } - ++limit; - } - text = text.replace('¨C' + i + 'C', repText); - } - - text = globals.converter._dispatch('makehtml.unhashHTMLSpans.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.hashHTMLSpans.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/hashPreCodeTags.js b/src/subParsers/makehtml/hashPreCodeTags.js index e989ea9..f7189a8 100644 --- a/src/subParsers/makehtml/hashPreCodeTags.js +++ b/src/subParsers/makehtml/hashPreCodeTags.js @@ -1,19 +1,38 @@ -/** - * Hash and escape
' + codeblock + end + '
 elements that should not be parsed as markdown
- */
+////
+// makehtml/githubCodeBlock.js
+// Copyright (c) 2018 ShowdownJS
+//
+// Hash and escape 
 elements that should not be parsed as markdown
+//
+// ***Author:***
+// - Estêvão Soares dos Santos (Tivie) 
+////
+
+
 showdown.subParser('makehtml.hashPreCodeTags', function (text, options, globals) {
   'use strict';
-  text = globals.converter._dispatch('makehtml.hashPreCodeTags.before', text, options, globals).getText();
+  let startEvent = new showdown.Event('makehtml.hashPreCodeTags.onStart', text);
+  startEvent
+    .setOutput(text)
+    ._setGlobals(globals)
+    ._setOptions(options);
+  startEvent = globals.converter.dispatch(startEvent);
+  text = startEvent.output;
 
-  var repFunc = function (wholeMatch, match, left, right) {
+  let repFunc = function (wholeMatch, match, left, right) {
     // encode html entities
-    var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right;
+    let codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right;
     return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
   };
 
   // Hash 

   text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}]*>\\s*]*>', '^ {0,3}\\s*
', 'gim'); - text = globals.converter._dispatch('makehtml.hashPreCodeTags.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.hashPreCodeTags.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/headers.js b/src/subParsers/makehtml/headers.js deleted file mode 100644 index c343ef9..0000000 --- a/src/subParsers/makehtml/headers.js +++ /dev/null @@ -1,126 +0,0 @@ -showdown.subParser('makehtml.headers', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.headers.before', text, options, globals).getText(); - - var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart), - - // Set text-style headers: - // Header 1 - // ======== - // - // Header 2 - // -------- - // - setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm, - setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm; - - text = text.replace(setextRegexH1, function (wholeMatch, m1) { - - var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals), - hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', - hLevel = headerLevelStart, - hashBlock = '' + spanGamut + ''; - return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals); - }); - - text = text.replace(setextRegexH2, function (matchFound, m1) { - var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals), - hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"', - hLevel = headerLevelStart + 1, - hashBlock = '' + spanGamut + ''; - return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals); - }); - - // atx-style headers: - // # Header 1 - // ## Header 2 - // ## Header 2 with closing hashes ## - // ... - // ###### Header 6 - // - var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm; - - text = text.replace(atxStyle, function (wholeMatch, m1, m2) { - var hText = m2; - if (options.customizedHeaderId) { - hText = m2.replace(/\s?{([^{]+?)}\s*$/, ''); - } - - var span = showdown.subParser('makehtml.spanGamut')(hText, options, globals), - hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"', - hLevel = headerLevelStart - 1 + m1.length, - header = '' + span + ''; - - return showdown.subParser('makehtml.hashBlock')(header, options, globals); - }); - - function headerId (m) { - var title, - prefix; - - // It is separate from other options to allow combining prefix and customized - if (options.customizedHeaderId) { - var match = m.match(/{([^{]+?)}\s*$/); - if (match && match[1]) { - m = match[1]; - } - } - - title = m; - - // Prefix id to prevent causing inadvertent pre-existing style matches. - if (showdown.helper.isString(options.prefixHeaderId)) { - prefix = options.prefixHeaderId; - } else if (options.prefixHeaderId === true) { - prefix = 'section-'; - } else { - prefix = ''; - } - - if (!options.rawPrefixHeaderId) { - title = prefix + title; - } - - if (options.ghCompatibleHeaderId) { - title = title - .replace(/ /g, '-') - // replace previously escaped chars (&, ¨ and $) - .replace(/&/g, '') - .replace(/¨T/g, '') - .replace(/¨D/g, '') - // replace rest of the chars (&~$ are repeated as they might have been escaped) - // borrowed from github's redcarpet (some they should produce similar results) - .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '') - .toLowerCase(); - } else if (options.rawHeaderId) { - title = title - .replace(/ /g, '-') - // replace previously escaped chars (&, ¨ and $) - .replace(/&/g, '&') - .replace(/¨T/g, '¨') - .replace(/¨D/g, '$') - // replace " and ' - .replace(/["']/g, '-') - .toLowerCase(); - } else { - title = title - .replace(/[^\w]/g, '') - .toLowerCase(); - } - - if (options.rawPrefixHeaderId) { - title = prefix + title; - } - - if (globals.hashLinkCounts[title]) { - title = title + '-' + (globals.hashLinkCounts[title]++); - } else { - globals.hashLinkCounts[title] = 1; - } - return title; - } - - text = globals.converter._dispatch('makehtml.headers.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/heading.js b/src/subParsers/makehtml/heading.js new file mode 100644 index 0000000..9ca040e --- /dev/null +++ b/src/subParsers/makehtml/heading.js @@ -0,0 +1,171 @@ +//// +// makehtml/blockquote.js +// Copyright (c) 2018 ShowdownJS +// +// Transforms MD headings into `` html entities +// +// Setext-style headers: +// Header 1 +// ======== +// +// Header 2 +// -------- +// +// atx-style headers: +// # Header 1 +// ## Header 2 +// ## Header 2 with closing hashes ## +// ... +// ###### Header 6 +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + +showdown.subParser('makehtml.heading', function (text, options, globals) { + 'use strict'; + + function parseHeader (pattern, wholeMatch, headingText, headingLevel, headingId) { + let captureStartEvent = new showdown.Event('makehtml.heading.onCapture', headingText), + otp; + + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + heading: headingText + }) + .setAttributes({ + id: headingId + }); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + + } else { + headingText = captureStartEvent.matches.heading; + let spanGamut = showdown.subParser('makehtml.spanGamut')(headingText, options, globals), + attributes = captureStartEvent.attributes; + otp = '' + spanGamut + ''; + } + + let beforeHashEvent = new showdown.Event('makehtml.heading.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + + return showdown.subParser('makehtml.hashBlock')(otp, options, globals); + } + + let startEvent = new showdown.Event('makehtml.heading.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + let setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm, + setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm, + atxRegex = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm; + + text = text.replace(setextRegexH1, function (wholeMatch, headingText) { + let id = (options.noHeaderId) ? null : showdown.subParser('makehtml.heading.id')(headingText, options, globals); + return parseHeader(setextRegexH1, wholeMatch, headingText, options.headerLevelStart, id); + }); + + text = text.replace(setextRegexH2, function (wholeMatch, headingText) { + let id = (options.noHeaderId) ? null : showdown.subParser('makehtml.heading.id')(headingText, options, globals); + return parseHeader(setextRegexH2, wholeMatch, headingText, options.headerLevelStart + 1, id); + }); + + text = text.replace(atxRegex, function (wholeMatch, m1, m2) { + let headingLevel = options.headerLevelStart - 1 + m1.length, + headingText = (options.customizedHeaderId) ? m2.replace(/\s?{([^{]+?)}\s*$/, '') : m2, + id = (options.noHeaderId) ? null : showdown.subParser('makehtml.heading.id')(m2, options, globals); + return parseHeader(setextRegexH2, wholeMatch, headingText, headingLevel, id); + }); + + + let afterEvent = new showdown.Event('makehtml.heading.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; +}); + +showdown.subParser('makehtml.heading.id', function (m, options, globals) { + let title, + prefix; + + // It is separate from other options to allow combining prefix and customized + if (options.customizedHeaderId) { + let match = m.match(/{([^{]+?)}\s*$/); + if (match && match[1]) { + m = match[1]; + } + } + + title = m; + + // Prefix id to prevent causing inadvertent pre-existing style matches. + if (showdown.helper.isString(options.prefixHeaderId)) { + prefix = options.prefixHeaderId; + } else if (options.prefixHeaderId === true) { + prefix = 'section-'; + } else { + prefix = ''; + } + + if (!options.rawPrefixHeaderId) { + title = prefix + title; + } + + if (options.ghCompatibleHeaderId) { + title = title + .replace(/ /g, '-') + // replace previously escaped chars (&, ¨ and $) + .replace(/&/g, '') + .replace(/¨T/g, '') + .replace(/¨D/g, '') + // replace rest of the chars (&~$ are repeated as they might have been escaped) + // borrowed from github's redcarpet (so they should produce similar results) + .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '') + .toLowerCase(); + } else if (options.rawHeaderId) { + title = title + .replace(/ /g, '-') + // replace previously escaped chars (&, ¨ and $) + .replace(/&/g, '&') + .replace(/¨T/g, '¨') + .replace(/¨D/g, '$') + // replace " and ' + .replace(/["']/g, '-') + .toLowerCase(); + } else { + title = title + .replace(/[^\w]/g, '') + .toLowerCase(); + } + + if (options.rawPrefixHeaderId) { + title = prefix + title; + } + + if (globals.hashLinkCounts[title]) { + title = title + '-' + (globals.hashLinkCounts[title]++); + } else { + globals.hashLinkCounts[title] = 1; + } + return title; +}); diff --git a/src/subParsers/makehtml/horizontalRule.js b/src/subParsers/makehtml/horizontalRule.js index 2a1f814..0c03087 100644 --- a/src/subParsers/makehtml/horizontalRule.js +++ b/src/subParsers/makehtml/horizontalRule.js @@ -1,18 +1,86 @@ -/** - * Turn Markdown horizontal rule shortcuts into
tags. - * - * Any 3 or more unindented consecutive hyphens, asterisks or underscores with or without a space beetween them - * in a single line is considered a horizontal rule - */ +//// +// makehtml/blockquote.js +// Copyright (c) 2018 ShowdownJS +// +// Turn Markdown horizontal rule shortcuts into
tags. +// +// Any 3 or more unindented consecutive hyphens, asterisks or underscores with or without a space beetween them +// in a single line is considered a horizontal rule +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// showdown.subParser('makehtml.horizontalRule', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.horizontalRule.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.horizontalRule.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; - var key = showdown.subParser('makehtml.hashBlock')('
', options, globals); - text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key); - text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key); - text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key); - text = globals.converter._dispatch('makehtml.horizontalRule.after', text, options, globals).getText(); - return text; + const rgx1 = /^ {0,2}( ?-){3,}[ \t]*$/gm; + text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, function (wholeMatch) { + return parse(rgx1, wholeMatch); + }); + + const rgx2 = /^ {0,2}( ?\*){3,}[ \t]*$/gm; + text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, function (wholeMatch) { + return parse(rgx2, wholeMatch); + }); + + const rgx3 = /^ {0,2}( ?\*){3,}[ \t]*$/gm; + text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, function (wholeMatch) { + return parse(rgx3, wholeMatch); + }); + + let afterEvent = new showdown.Event('makehtml.horizontalRule.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; + + /** + * + * @param {RegExp} pattern + * @param {string} wholeMatch + * @returns {string} + */ + function parse (pattern, wholeMatch) { + let otp; + let captureStartEvent = new showdown.Event('makehtml.horizontalRule.onCapture', wholeMatch); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _whoteMatch: wholeMatch + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + otp = ''; + } + + let beforeHashEvent = new showdown.Event('makehtml.horizontalRule.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + otp = showdown.subParser('makehtml.hashBlock')(otp, options, globals); + return otp; + } + }); diff --git a/src/subParsers/makehtml/image.js b/src/subParsers/makehtml/image.js new file mode 100644 index 0000000..b596cd0 --- /dev/null +++ b/src/subParsers/makehtml/image.js @@ -0,0 +1,188 @@ +//// +// makehtml/blockquote.js +// Copyright (c) 2018 ShowdownJS +// +// Turn Markdown image into tags. +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + +showdown.subParser('makehtml.image', function (text, options, globals) { + 'use strict'; + + let startEvent = new showdown.Event('makehtml.image.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + let inlineRegExp = /!\[([^\]]*?)][ \t]*\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\5)?[ \t]?\)/g, + crazyRegExp = /!\[([^\]]*?)][ \t]*\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\5)?[ \t]?\)/g, + base64RegExp = /!\[([^\]]*?)][ \t]*\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, + referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]/g, + refShortcutRegExp = /!\[([^\[\]]+)]/g; + + // First, handle reference-style labeled images: ![alt text][id] + text = text.replace(referenceRegExp, function (wholeMatch, altText, linkId) { + return writeImageTag ('reference', referenceRegExp, wholeMatch, altText, null, linkId); + }); + + // Next, handle inline images: ![alt text](url =x "optional title") + // base64 encoded images + text = text.replace(base64RegExp, function (wholeMatch, altText, url, width, height, m5, title) { + url = url.replace(/\s/g, ''); + return writeImageTag ('inline', base64RegExp, wholeMatch, altText, url, null, width, height, title); + }); + + // cases with crazy urls like ./image/cat1).png + text = text.replace(crazyRegExp, function (wholeMatch, altText, url, width, height, m5, title) { + url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); + return writeImageTag ('inline', crazyRegExp, wholeMatch, altText, url, null, width, height, title); + }); + + // normal cases + text = text.replace(inlineRegExp, function (wholeMatch, altText, url, width, height, m5, title) { + url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); + return writeImageTag ('inline', inlineRegExp, wholeMatch, altText, url, null, width, height, title); + }); + + // handle reference-style shortcuts: ![img text] + text = text.replace(refShortcutRegExp, function (wholeMatch, altText) { + return writeImageTag ('reference', refShortcutRegExp, wholeMatch, altText); + }); + + let afterEvent = new showdown.Event('makehtml.image.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; + + + + /** + * @param {string} subEvtName + * @param {RegExp} pattern + * @param {string} wholeMatch + * @param {string} altText + * @param {string|null} [url] + * @param {string|null} [linkId] + * @param {string|null} [width] + * @param {string|null} [height] + * @param {string|null} [title] + * @returns {string} + */ + function writeImageTag (subEvtName, pattern, wholeMatch, altText, url, linkId, width, height, title) { + + let gUrls = globals.gUrls, + gTitles = globals.gTitles, + gDims = globals.gDimensions, + matches = { + _wholeMatch: wholeMatch, + _altText: altText, + _linkId: linkId, + _url: url, + _width: width, + _height: height, + _title: title + }, + otp, + attributes = {}; + + linkId = (linkId) ? linkId.toLowerCase() : null; + + if (!title) { + title = null; + } + // Special case for explicit empty url + if (wholeMatch.search(/\(? ?(['"].*['"])?\)$/m) > -1) { + url = ''; + + } else if (showdown.helper.isUndefined(url) || url === '' || url === null) { + if (linkId === '' || linkId === null) { + // lower-case and turn embedded newlines into spaces + linkId = altText.toLowerCase().replace(/ ?\n/g, ' '); + } + url = '#' + linkId; + + if (!showdown.helper.isUndefined(gUrls[linkId])) { + url = gUrls[linkId]; + if (!showdown.helper.isUndefined(gTitles[linkId])) { + title = gTitles[linkId]; + } + if (!showdown.helper.isUndefined(gDims[linkId])) { + width = gDims[linkId].width; + height = gDims[linkId].height; + } + } else { + return wholeMatch; + } + } + + altText = altText + .replace(/"/g, '"') + //altText = showdown.helper.escapeCharacters(altText, '*_', false); + .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + //url = showdown.helper.escapeCharacters(url, '*_', false); + url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + + if (title && showdown.helper.isString(title)) { + title = title + .replace(/"/g, '"') + .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + } + + if (width) { + width = (width === '*') ? 'auto' : width; + } else { + width = null; + } + + if (height) { + height = (height === '*') ? 'auto' : height; + } else { + height = null; + } + + let captureStartEvent = new showdown.Event('makehtml.image.' + subEvtName + '.onCapture', wholeMatch); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches(matches) + .setAttributes({ + src: url, + alt: altText, + title: title, + width: width, + height: height + }); + + captureStartEvent = globals.converter.dispatch(captureStartEvent); + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + attributes = captureStartEvent.attributes; + otp = ''; + } + + let beforeHashEvent = new showdown.Event('makehtml.image.' + subEvtName + '.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + + return otp; + } + +}); diff --git a/src/subParsers/makehtml/images.js b/src/subParsers/makehtml/images.js deleted file mode 100644 index e7fbbc1..0000000 --- a/src/subParsers/makehtml/images.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Turn Markdown image shortcuts into tags. - */ -showdown.subParser('makehtml.images', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.images.before', text, options, globals).getText(); - - var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, - crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g, - base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g, - referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g, - refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g; - - function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) { - url = url.replace(/\s/g, ''); - return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title); - } - - function writeImageTagBaseUrl (wholeMatch, altText, linkId, url, width, height, m5, title) { - url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); - - return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title); - } - - function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) { - - var gUrls = globals.gUrls, - gTitles = globals.gTitles, - gDims = globals.gDimensions; - - linkId = linkId.toLowerCase(); - - if (!title) { - title = ''; - } - // Special case for explicit empty url - if (wholeMatch.search(/\(? ?(['"].*['"])?\)$/m) > -1) { - url = ''; - - } else if (url === '' || url === null) { - if (linkId === '' || linkId === null) { - // lower-case and turn embedded newlines into spaces - linkId = altText.toLowerCase().replace(/ ?\n/g, ' '); - } - url = '#' + linkId; - - if (!showdown.helper.isUndefined(gUrls[linkId])) { - url = gUrls[linkId]; - if (!showdown.helper.isUndefined(gTitles[linkId])) { - title = gTitles[linkId]; - } - if (!showdown.helper.isUndefined(gDims[linkId])) { - width = gDims[linkId].width; - height = gDims[linkId].height; - } - } else { - return wholeMatch; - } - } - - altText = altText - .replace(/"/g, '"') - //altText = showdown.helper.escapeCharacters(altText, '*_', false); - .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - //url = showdown.helper.escapeCharacters(url, '*_', false); - url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - var result = '' + altText + 'x "optional title") - - // base64 encoded images - text = text.replace(base64RegExp, writeImageTagBase64); - - // cases with crazy urls like ./image/cat1).png - text = text.replace(crazyRegExp, writeImageTagBaseUrl); - - // normal cases - text = text.replace(inlineRegExp, writeImageTagBaseUrl); - - // handle reference-style shortcuts: ![img text] - text = text.replace(refShortcutRegExp, writeImageTag); - - text = globals.converter._dispatch('makehtml.images.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/italicsAndBold.js b/src/subParsers/makehtml/italicsAndBold.js deleted file mode 100644 index 07862be..0000000 --- a/src/subParsers/makehtml/italicsAndBold.js +++ /dev/null @@ -1,66 +0,0 @@ -showdown.subParser('makehtml.italicsAndBold', function (text, options, globals) { - 'use strict'; - - text = globals.converter._dispatch('makehtml.italicsAndBold.before', text, options, globals).getText(); - - // it's faster to have 3 separate regexes for each case than have just one - // because of backtracing, in some cases, it could lead to an exponential effect - // called "catastrophic backtrace". Ominous! - - function parseInside (txt, left, right) { - return left + txt + right; - } - - // Parse underscores - if (options.literalMidWordUnderscores) { - text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { - return parseInside (txt, '', ''); - }); - text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { - return parseInside (txt, '', ''); - }); - text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) { - return parseInside (txt, '', ''); - }); - } else { - text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) { - // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it) - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - } - - // Now parse asterisks - /* - if (options.literalMidWordAsterisks) { - text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]+?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) { - return parseInside (txt, lead + '', ''); - }); - text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]+?)\*\*\B(?!\*)/g, function (wm, lead, txt) { - return parseInside (txt, lead + '', ''); - }); - text = text.replace(/([^*]|^)\B\*(\S[\s\S]+?)\*\B(?!\*)/g, function (wm, lead, txt) { - return parseInside (txt, lead + '', ''); - }); - } else { - */ - text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) { - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) { - // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it) - return (/\S$/.test(m)) ? parseInside (m, '', '') : wm; - }); - //} - - text = globals.converter._dispatch('makehtml.italicsAndBold.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/link.js b/src/subParsers/makehtml/link.js new file mode 100644 index 0000000..ff3e550 --- /dev/null +++ b/src/subParsers/makehtml/link.js @@ -0,0 +1,323 @@ +//// +// makehtml/links.js +// Copyright (c) 2018 ShowdownJS +// +// Transforms MD links into `
` html anchors +// +// A link contains link text (the visible text), a link destination (the URI that is the link destination), and +// optionally a link title. There are two basic kinds of links in Markdown. +// In inline links the destination and title are given immediately after the link text. +// In reference links the destination and title are defined elsewhere in the document. +// +// ***Author:*** +// - Estevão Soares dos Santos (Tivie) +//// + +showdown.subParser('makehtml.link', function (text, options, globals) { + + // + // Parser starts here + // + let startEvent = new showdown.Event('makehtml.link.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + // 1. Handle reference-style links: [link text] [id] + let referenceRegex = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]/g; + text = text.replace(referenceRegex, function (wholeMatch, text, linkId) { + // bail if we find 2 newlines somewhere + if (/\n\n/.test(wholeMatch)) { + return wholeMatch; + } + return writeAnchorTag ('reference', referenceRegex, wholeMatch, text, linkId); + }); + + // 2. Handle inline-style links: [link text](url "optional title") + // 2.1. Look for empty cases: []() and [empty]() and []("title") + let inlineEmptyRegex = /\[(.*?)]\(? ?(["'](.*)["'])?\)/g; + text = text.replace(inlineEmptyRegex, function (wholeMatch, text, m1, title) { + return writeAnchorTag ('inline', inlineEmptyRegex, wholeMatch, text, null, null, title, true); + }); + + // 2.2. Look for cases with crazy urls like ./image/cat1).png + // the url mus be enclosed in <> + let inlineCrazyRegex = /\[((?:\[[^\]]*]|[^\[\]])*)]\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\4))?[ \t]?\)/g; + text = text.replace(inlineCrazyRegex, function (wholeMatch, text, url, m1, m2, title) { + return writeAnchorTag ('inline', inlineCrazyRegex, wholeMatch, text, null, url, title); + }); + + // 2.3. inline links with no title or titles wrapped in ' or ": + // [text](url.com) || [text]() || [text](url.com "title") || [text]( "title") + let inlineNormalRegex1 = /\[([\S ]*?)]\s?\( *?\s*(?:(['"])(.*?)\3)? *\)/g; + text = text.replace(inlineNormalRegex1, function (wholeMatch, text, url, m1, title) { + return writeAnchorTag ('inline', inlineNormalRegex1, wholeMatch, text, null, url, title); + }); + + // 2.4. inline links with titles wrapped in (): [foo](bar.com (title)) + let inlineNormalRegex2 = /\[([\S ]*?)]\s?\( *?\s+\((.*?)\) *\)/g; + text = text.replace(inlineNormalRegex2, function (wholeMatch, text, url, title) { + return writeAnchorTag ('inline', inlineNormalRegex2, wholeMatch, text, null, url, title); + }); + + + // 3. Handle reference-style shortcuts: [link text] + // These must come last in case there's a [link text][1] or [link text](/foo) + let referenceShortcutRegex = /\[([^\[\]]+)]/g; + text = text.replace(referenceShortcutRegex, function (wholeMatch, text) { + return writeAnchorTag ('reference', referenceShortcutRegex, wholeMatch, text); + }); + + // 4. Handle angle brackets links -> `` + // Must come after links, because you can use < and > delimiters in inline links like [this](). + + // 4.1. Handle links first + let angleBracketsLinksRegex = /<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi; + text = text.replace(angleBracketsLinksRegex, function (wholeMatch, url, urlStart) { + let text = url; + url = (urlStart === 'www.') ? 'http://' + url : url; + return writeAnchorTag ('angleBrackets', angleBracketsLinksRegex, wholeMatch, text, null, url); + }); + + // 4.2. Then mail adresses + let angleBracketsMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z\d]+(\.[-a-z\d]+)*\.[a-z]+)>/gi; + text = text.replace(angleBracketsMailRegex, function (wholeMatch, mail) { + const m = parseMail(mail); + return writeAnchorTag ('angleBrackets', angleBracketsMailRegex, wholeMatch, m.mail, null, m.url); + }); + + // 5. Handle GithubMentions (if option is enabled) + if (options.ghMentions) { + let ghMentionsRegex = /(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi; + text = text.replace(ghMentionsRegex, function (wholeMatch, st, escape, mentions, username) { + // bail if the mentions was escaped + if (escape === '\\') { + return st + mentions; + } + // check if options.ghMentionsLink is a string + // TODO Validation should be done at initialization not at runtime + if (!showdown.helper.isString(options.ghMentionsLink)) { + throw new Error('ghMentionsLink option must be a string'); + } + let url = options.ghMentionsLink.replace(/\{u}/g, username); + return st + writeAnchorTag ('reference', ghMentionsRegex, wholeMatch, mentions, null, url); + }); + } + + // 6 and 7 have to come here to prevent naked links to catch html + // 6. Handle tags + text = text.replace(/]*>[\s\S]*<\/a>/g, function (wholeMatch) { + return showdown.helper._hashHTMLSpan(wholeMatch, globals); + }); + + // 7. Handle tags + text = text.replace(/]*\/?>/g, function (wholeMatch) { + return showdown.helper._hashHTMLSpan(wholeMatch, globals); + }); + + // 8. Handle naked links (if option is enabled) + if (options.simplifiedAutoLink) { + // 8.1. Check for naked URLs + // we also include leading markdown magic chars [_*~] for cases like __https://www.google.com/foobar__ + let nakedUrlRegex = /([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi; + text = text.replace(nakedUrlRegex, function (wholeMatch, leadingMDChars, url, urlPrefix) { + // we now will start traversing the url from the front to back, looking for punctuation chars [_*~,;:.!?\)\]] + const len = url.length; + let suffix = ''; + + for (let i = len - 1; i >= 0; --i) { + let char = url.charAt(i); + if (/[_*~,;:.!?]/.test(char)) { + // it's a punctuation char so we remove it from the url + url = url.slice(0, -1); + // and prepend it to the suffix + suffix = char + suffix; + } else if (/[)\]]/.test(char)) { + // it's a parenthesis so we need to check for "balance" (kinda) + let opPar, clPar; + if (/\)/.test(char)) { + // it's a curved parenthesis + opPar = url.match(/\(/g) || []; + clPar = url.match(/\)/g); + } else { + // it's a squared parenthesis + opPar = url.match(/\[/g) || []; + clPar = url.match(/]/g); + } + if (opPar.length < clPar.length) { + // there are more closing Parenthesis than opening so chop it!!!!! + url = url.slice(0, -1); + // and prepend it to the suffix + suffix = char + suffix; + } else { + // it's (kinda) balanced so our work is done + break; + } + } else { + // it's not a punctuation or a parenthesis so our work is done + break; + } + } + + // we copy the treated url to the text variable + let txt = url; + // finally, if it's a www shortcut, we prepend http + url = (urlPrefix === 'www.') ? 'http://' + url : url; + + // url part is done so let's take care of text now + // we need to escape the text (because of links such as www.example.com/foo__bar__baz) + txt = txt.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + + // and return the link tag, with the leadingMDChars and suffix. The leadingMDChars are added at the end too because + // we consumed those characters in the regexp + return leadingMDChars + + writeAnchorTag ('autoLink', nakedUrlRegex, wholeMatch, txt, null, url) + + suffix + + leadingMDChars; + }); + + // 8.2. Now check for naked mail + let nakedMailRegex = /(^|\s)(?:mailto:)?([A-Za-z\d!#$%&'*+-/=?^_`{|}~.]+@[-a-z\d]+(\.[-a-z\d]+)*\.[a-z]+)(?=$|\s)/gmi; + text = text.replace(nakedMailRegex, function (wholeMatch, leadingChar, mail) { + const m = parseMail(mail); + return leadingChar + writeAnchorTag ('autoLink', nakedMailRegex, wholeMatch, m.mail, null, m.url); + }); + } + + let afterEvent = new showdown.Event('makehtml.link.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; + + + + /** + * + * @param {string} subEvtName + * @param {RegExp} pattern + * @param {string} wholeMatch + * @param {string} text + * @param {string|null} [linkId] + * @param {string|null} [url] + * @param {string|null} [title] + * @param {boolean} [emptyCase] + * @returns {string} + */ + function writeAnchorTag (subEvtName, pattern, wholeMatch, text, linkId, url, title, emptyCase) { + + let matches = { + _wholeMatch: wholeMatch, + _linkId: linkId, + _url: url, + _title: title, + text: text + }, + otp, + attributes = {}; + + title = title || null; + url = url || null; + linkId = (linkId) ? linkId.toLowerCase() : null; + emptyCase = !!emptyCase; + + if (emptyCase) { + url = ''; + } else if (!url) { + if (!linkId) { + // lower-case and turn embedded newlines into spaces + linkId = text.toLowerCase().replace(/ ?\n/g, ' '); + } + url = '#' + linkId; + + if (!showdown.helper.isUndefined(globals.gUrls[linkId])) { + url = globals.gUrls[linkId]; + if (!showdown.helper.isUndefined(globals.gTitles[linkId])) { + title = globals.gTitles[linkId]; + } + } else { + return wholeMatch; + } + } + + url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); + url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + attributes.href = url; + + if (title && showdown.helper.isString(title)) { + title = title + .replace(/"/g, '"') + .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); + attributes.title = title; + } + + // optionLinksInNewWindow only applies + // to external links. Hash links (#) open in same page + if (options.openLinksInNewWindow && !/^#/.test(url)) { + attributes.rel = 'noopener noreferrer'; + attributes.target = '¨E95Eblank'; // escaped _ + + } + + let captureStartEvent = new showdown.Event('makehtml.link.' + subEvtName + '.onCapture', wholeMatch); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches(matches) + .setAttributes(attributes); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + attributes = captureStartEvent.attributes; + text = captureStartEvent.matches.text || ''; + // Text can be a markdown element, so we run through the appropriate parsers + text = showdown.subParser('makehtml.codeSpan')(text, options, globals); + text = showdown.subParser('makehtml.emoji')(text, options, globals); + text = showdown.subParser('makehtml.underline')(text, options, globals); + text = showdown.subParser('makehtml.emphasisAndStrong')(text, options, globals); + text = showdown.subParser('makehtml.strikethrough')(text, options, globals); + text = showdown.subParser('makehtml.ellipsis')(text, options, globals); + text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals); + otp = '' + text + ''; + } + + let beforeHashEvent = new showdown.Event('makehtml.link.' + subEvtName + '.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + return showdown.subParser('makehtml.hashHTMLSpans')(otp, options, globals); + } + + /** + * @param {string} mail + * @returns {{mail: string, url: string}} + */ + function parseMail (mail) { + let url = 'mailto:'; + mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals); + if (options.encodeEmails) { + url = showdown.helper.encodeEmailAddress(url + mail); + mail = showdown.helper.encodeEmailAddress(mail); + } else { + url = url + mail; + } + return { + mail: mail, + url: url + }; + } +}); diff --git a/src/subParsers/makehtml/links.js b/src/subParsers/makehtml/links.js deleted file mode 100644 index cac80da..0000000 --- a/src/subParsers/makehtml/links.js +++ /dev/null @@ -1,428 +0,0 @@ -//// -// makehtml/links.js -// Copyright (c) 2018 ShowdownJS -// -// Transforms MD links into `` html anchors -// -// A link contains link text (the visible text), a link destination (the URI that is the link destination), and -// optionally a link title. There are two basic kinds of links in Markdown. -// In inline links the destination and title are given immediately after the link text. -// In reference links the destination and title are defined elsewhere in the document. -// -// ***Author:*** -// - Estevão Soares dos Santos (Tivie) -//// - -(function () { - /** - * Helper function: Wrapper function to pass as second replace parameter - * - * @param {RegExp} rgx - * @param {string} evtRootName - * @param {{}} options - * @param {{}} globals - * @returns {Function} - */ - function replaceAnchorTagReference (rgx, evtRootName, options, globals, emptyCase) { - emptyCase = !!emptyCase; - return function (wholeMatch, text, id, url, m5, m6, title) { - // bail we we find 2 newlines somewhere - if (/\n\n/.test(wholeMatch)) { - return wholeMatch; - } - - var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals); - return writeAnchorTag(evt, options, globals, emptyCase); - }; - } - - function replaceAnchorTagBaseUrl (rgx, evtRootName, options, globals, emptyCase) { - return function (wholeMatch, text, id, url, m5, m6, title) { - url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url); - - var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals); - return writeAnchorTag(evt, options, globals, emptyCase); - }; - } - - /** - * TODO Normalize this - * Helper function: Create a capture event - * @param {RegExp} rgx - * @param {String} evtName Event name - * @param {String} wholeMatch - * @param {String} text - * @param {String} id - * @param {String} url - * @param {String} title - * @param {{}} options - * @param {{}} globals - * @returns {showdown.helper.Event|*} - */ - function createEvent (rgx, evtName, wholeMatch, text, id, url, title, options, globals) { - return globals.converter._dispatch(evtName, wholeMatch, options, globals, { - regexp: rgx, - matches: { - wholeMatch: wholeMatch, - text: text, - id: id, - url: url, - title: title - } - }); - } - - /** - * Helper Function: Normalize and write an anchor tag based on passed parameters - * @param evt - * @param options - * @param globals - * @param {boolean} emptyCase - * @returns {string} - */ - function writeAnchorTag (evt, options, globals, emptyCase) { - - var wholeMatch = evt.getMatches().wholeMatch; - var text = evt.getMatches().text; - var id = evt.getMatches().id; - var url = evt.getMatches().url; - var title = evt.getMatches().title; - var target = ''; - - if (!title) { - title = ''; - } - id = (id) ? id.toLowerCase() : ''; - - if (emptyCase) { - url = ''; - } else if (!url) { - if (!id) { - // lower-case and turn embedded newlines into spaces - id = text.toLowerCase().replace(/ ?\n/g, ' '); - } - url = '#' + id; - - if (!showdown.helper.isUndefined(globals.gUrls[id])) { - url = globals.gUrls[id]; - if (!showdown.helper.isUndefined(globals.gTitles[id])) { - title = globals.gTitles[id]; - } - } else { - return wholeMatch; - } - } - //url = showdown.helper.escapeCharacters(url, '*_:~', false); // replaced line to improve performance - url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - - if (title !== '' && title !== null) { - title = title.replace(/"/g, '"'); - //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance - title = title.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - title = ' title="' + title + '"'; - } - - // optionLinksInNewWindow only applies - // to external links. Hash links (#) open in same page - if (options.openLinksInNewWindow && !/^#/.test(url)) { - // escaped _ - target = ' rel="noopener noreferrer" target="¨E95Eblank"'; - } - - // Text can be a markdown element, so we run through the appropriate parsers - text = showdown.subParser('makehtml.codeSpans')(text, options, globals); - text = showdown.subParser('makehtml.emoji')(text, options, globals); - text = showdown.subParser('makehtml.underline')(text, options, globals); - text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals); - text = showdown.subParser('makehtml.strikethrough')(text, options, globals); - text = showdown.subParser('makehtml.ellipsis')(text, options, globals); - text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals); - - //evt = createEvent(rgx, evtRootName + '.captureEnd', wholeMatch, text, id, url, title, options, globals); - - var result = '' + text + ''; - - //evt = createEvent(rgx, evtRootName + '.beforeHash', wholeMatch, text, id, url, title, options, globals); - - result = showdown.subParser('makehtml.hashHTMLSpans')(result, options, globals); - - return result; - } - - var evtRootName = 'makehtml.links'; - - /** - * Turn Markdown link shortcuts into XHTML tags. - */ - showdown.subParser('makehtml.links', function (text, options, globals) { - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 1. Handle reference-style links: [link text] [id] - text = showdown.subParser('makehtml.links.reference')(text, options, globals); - - // 2. Handle inline-style links: [link text](url "optional title") - text = showdown.subParser('makehtml.links.inline')(text, options, globals); - - // 3. Handle reference-style shortcuts: [link text] - // These must come last in case there's a [link text][1] or [link text](/foo) - text = showdown.subParser('makehtml.links.referenceShortcut')(text, options, globals); - - // 4. Handle angle brackets links -> `` - // Must come after links, because you can use < and > delimiters in inline links like [this](). - text = showdown.subParser('makehtml.links.angleBrackets')(text, options, globals); - - // 5. Handle GithubMentions (if option is enabled) - text = showdown.subParser('makehtml.links.ghMentions')(text, options, globals); - - // 6. Handle tags and img tags - text = text.replace(/]*>[\s\S]*<\/a>/g, function (wholeMatch) { - return showdown.helper._hashHTMLSpan(wholeMatch, globals); - }); - - text = text.replace(/]*\/?>/g, function (wholeMatch) { - return showdown.helper._hashHTMLSpan(wholeMatch, globals); - }); - - // 7. Handle naked links (if option is enabled) - text = showdown.subParser('makehtml.links.naked')(text, options, globals); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.inline', function (text, options, globals) { - var evtRootName = evtRootName + '.inline'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 1. Look for empty cases: []() and [empty]() and []("title") - var rgxEmpty = /\[(.*?)]()()()()\(? ?(?:["'](.*)["'])?\)/g; - text = text.replace(rgxEmpty, replaceAnchorTagBaseUrl(rgxEmpty, evtRootName, options, globals, true)); - - // 2. Look for cases with crazy urls like ./image/cat1).png - var rgxCrazy = /\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g; - text = text.replace(rgxCrazy, replaceAnchorTagBaseUrl(rgxCrazy, evtRootName, options, globals)); - - // 3. inline links with no title or titles wrapped in ' or ": - // [text](url.com) || [text]() || [text](url.com "title") || [text]( "title") - //var rgx2 = /\[[ ]*[\s]?[ ]*([^\n\[\]]*?)[ ]*[\s]?[ ]*] ?()\(?(?:[ ]*[\n]?[ ]*()(['"])(.*?)\5)?[ ]*[\s]?[ ]*\)/; // this regex is too slow!!! - var rgx2 = /\[([\S ]*?)]\s?()\( *?\s*(?:()(['"])(.*?)\5)? *\)/g; - text = text.replace(rgx2, replaceAnchorTagBaseUrl(rgx2, evtRootName, options, globals)); - - // 4. inline links with titles wrapped in (): [foo](bar.com (title)) - var rgx3 = /\[([\S ]*?)]\s?()\( *?\s+()()\((.*?)\) *\)/g; - text = text.replace(rgx3, replaceAnchorTagBaseUrl(rgx3, evtRootName, options, globals)); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.reference', function (text, options, globals) { - var evtRootName = evtRootName + '.reference'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - var rgx = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g; - text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals)); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.referenceShortcut', function (text, options, globals) { - var evtRootName = evtRootName + '.referenceShortcut'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - var rgx = /\[([^\[\]]+)]()()()()()/g; - text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals)); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.ghMentions', function (text, options, globals) { - var evtRootName = evtRootName + 'ghMentions'; - - if (!options.ghMentions) { - return text; - } - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - var rgx = /(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi; - - text = text.replace(rgx, function (wholeMatch, st, escape, mentions, username) { - // bail if the mentions was escaped - if (escape === '\\') { - return st + mentions; - } - - // check if options.ghMentionsLink is a string - // TODO Validation should be done at initialization not at runtime - if (!showdown.helper.isString(options.ghMentionsLink)) { - throw new Error('ghMentionsLink option must be a string'); - } - var url = options.ghMentionsLink.replace(/{u}/g, username); - var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, mentions, null, url, null, options, globals); - // captureEnd Event is triggered inside writeAnchorTag function - return st + writeAnchorTag(evt, options, globals); - }); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - - return text; - }); - - /** - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.angleBrackets', function (text, options, globals) { - var evtRootName = 'makehtml.links.angleBrackets'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 1. Parse links first - var urlRgx = /<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi; - text = text.replace(urlRgx, function (wholeMatch, url, urlStart) { - var text = url; - url = (urlStart === 'www.') ? 'http://' + url : url; - var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals); - return writeAnchorTag(evt, options, globals); - }); - - // 2. Then Mail Addresses - var mailRgx = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi; - text = text.replace(mailRgx, function (wholeMatch, mail) { - var url = 'mailto:'; - mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals); - if (options.encodeEmails) { - url = showdown.helper.encodeEmailAddress(url + mail); - mail = showdown.helper.encodeEmailAddress(mail); - } else { - url = url + mail; - } - var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals); - return writeAnchorTag(evt, options, globals); - }); - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - return text; - }); - - /** - * TODO MAKE THIS WORK (IT'S NOT ACTIVATED) - * TODO WRITE THIS DOCUMENTATION - */ - showdown.subParser('makehtml.links.naked', function (text, options, globals) { - if (!options.simplifiedAutoLink) { - return text; - } - - var evtRootName = 'makehtml.links.naked'; - - text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText(); - - // 2. Now we check for - // we also include leading markdown magic chars [_*~] for cases like __https://www.google.com/foobar__ - var urlRgx = /([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi; - text = text.replace(urlRgx, function (wholeMatch, leadingMDChars, url, urlPrefix) { - - // we now will start traversing the url from the front to back, looking for punctuation chars [_*~,;:.!?\)\]] - var len = url.length; - var suffix = ''; - for (var i = len - 1; i >= 0; --i) { - var char = url.charAt(i); - - if (/[_*~,;:.!?]/.test(char)) { - // it's a punctuation char - // we remove it from the url - url = url.slice(0, -1); - // and prepend it to the suffix - suffix = char + suffix; - } else if (/\)/.test(char)) { - var opPar = url.match(/\(/g) || []; - var clPar = url.match(/\)/g); - - // it's a curved parenthesis so we need to check for "balance" (kinda) - if (opPar.length < clPar.length) { - // there are more closing Parenthesis than opening so chop it!!!!! - url = url.slice(0, -1); - // and prepend it to the suffix - suffix = char + suffix; - } else { - // it's (kinda) balanced so our work is done - break; - } - } else if (/]/.test(char)) { - var opPar2 = url.match(/\[/g) || []; - var clPar2 = url.match(/\]/g); - // it's a squared parenthesis so we need to check for "balance" (kinda) - if (opPar2.length < clPar2.length) { - // there are more closing Parenthesis than opening so chop it!!!!! - url = url.slice(0, -1); - // and prepend it to the suffix - suffix = char + suffix; - } else { - // it's (kinda) balanced so our work is done - break; - } - } else { - // it's not a punctuation or a parenthesis so our work is done - break; - } - } - - // we copy the treated url to the text variable - var text = url; - // finally, if it's a www shortcut, we prepend http - url = (urlPrefix === 'www.') ? 'http://' + url : url; - - // url part is done so let's take care of text now - // we need to escape the text (because of links such as www.example.com/foo__bar__baz) - text = text.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback); - - // finally we dispatch the event - var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals); - - // and return the link tag, with the leadingMDChars and suffix. The leadingMDChars are added at the end too because - // we consumed those characters in the regexp - return leadingMDChars + writeAnchorTag(evt, options, globals) + suffix + leadingMDChars; - }); - - // 2. Then mails - var mailRgx = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi; - text = text.replace(mailRgx, function (wholeMatch, leadingChar, mail) { - var url = 'mailto:'; - mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals); - if (options.encodeEmails) { - url = showdown.helper.encodeEmailAddress(url + mail); - mail = showdown.helper.encodeEmailAddress(mail); - } else { - url = url + mail; - } - var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals); - return leadingChar + writeAnchorTag(evt, options, globals); - }); - - - text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText(); - return text; - }); -})(); diff --git a/src/subParsers/makehtml/list.js b/src/subParsers/makehtml/list.js new file mode 100644 index 0000000..6f11cb2 --- /dev/null +++ b/src/subParsers/makehtml/list.js @@ -0,0 +1,406 @@ +//// +// makehtml/list.js +// Copyright (c) 2022 ShowdownJS +// +// Transforms MD lists into `
    ` or `
      ` html list +// +// Markdown supports ordered (numbered) and unordered (bulleted) lists. +// Unordered lists use asterisks, pluses, and hyphens - interchangably - as list markers +// Ordered lists use numbers followed by periods. +// +// ***Author:*** +// - Estevão Soares dos Santos (Tivie) +//// + + +showdown.subParser('makehtml.list', function (text, options, globals) { + 'use strict'; + + // Start of list parsing + const subListRgx = /^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + const mainListRgx = /(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + const listTypeRgx = /[*+-]/g; + + let startEvent = new showdown.Event('makehtml.list.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + // add sentinel to hack around khtml/safari bug: + // http://bugs.webkit.org/show_bug.cgi?id=11231 + text += '¨0'; + + if (globals.gListLevel) { + text = text.replace(subListRgx, function (wholeMatch, list, m2) { + return parseConsecutiveLists(subListRgx, list, (m2.search(listTypeRgx) > -1) ? 'ul' : 'ol', true); + }); + } else { + text = text.replace(mainListRgx, function (wholeMatch, m1, list, m3) { + return parseConsecutiveLists(mainListRgx, list, (m3.search(listTypeRgx) > -1) ? 'ul' : 'ol', false); + }); + } + + // strip sentinel + text = text.replace(/¨0/, ''); + + let afterEvent = new showdown.Event('makehtml.list.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; + + + /** + * + * @param {RegExp} pattern + * @param {string} item + * @param {boolean} checked + * @returns {string} + */ + function processTaskListItem (pattern, item, checked) { + + const checkboxRgx = /^[ \t]*\[([xX ])]/m; + item = item.replace(checkboxRgx, function (wm, checkedRaw) { + + let attributes = { + type: 'checkbox', + disabled: true, + style: 'margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;', + checked: !!checked + }; + let captureStartEvent = new showdown.Event('makehtml.list.taskListItem.checkbox.onCapture', item); + + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: item, + _tasklistButton: wm, + _taksListButtonChecked: checkedRaw + }) + .setAttributes(attributes); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + let otp; + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + attributes = captureStartEvent.attributes; + otp = ''; + } + + let beforeHashEvent = new showdown.Event('makehtml.list.taskListItem.checkbox.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + return otp; + }); + + return item; + } + + /** + * Process the contents of a single ordered or unordered list, splitting it + * into individual list items. + * @param {string} listStr + * @param {boolean} trimTrailing + * @returns {string} + */ + function processListItems (listStr, trimTrailing) { + // The $g_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.". + globals.gListLevel++; + + // trim trailing blank lines: + listStr = listStr.replace(/\n{2,}$/, '\n'); + + // attacklab: add sentinel to emulate \z + listStr += '¨0'; + + let rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[([xX ])])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm, + isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr)); + + // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation, + // which is a syntax breaking change + // activating this option reverts to old behavior + // This will be removed in version 2.0 + if (options.disableForced4SpacesIndentedSublists) { + rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[([xX ])])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm; + } + + listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checkedRaw) { + let item = showdown.helper.outdent(m4), + attributes = {}, + checked = (checkedRaw && checkedRaw.trim() !== ''), + eventName = 'makehtml.list.listItem', + captureStartEvent, + matches = { + _wholeMatch: wholeMatch, + listItem: item, + }; + + + // Support for github tasklists + if (taskbtn && options.tasklists) { + // it's a github tasklist and tasklists are enabled + + // Style used for tasklist bullets + attributes.classes = ['task-list-item']; + attributes.style = 'list-style-type: none;'; + if (options.moreStyling && checked) { + attributes.classes.push('task-list-item-complete'); + } + eventName = 'makehtml.list.taskListItem'; + matches._taskListButton = taskbtn; + matches._taskListButtonChecked = checkedRaw; + } + + + captureStartEvent = new showdown.Event(eventName + '.onCapture', item); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(rgx) + .setMatches(matches) + .setAttributes(attributes); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + item = captureStartEvent.output; + } else { + + attributes = captureStartEvent.attributes; + item = captureStartEvent.matches.listItem; + + // even if user there's no tasklist, it's fine because the tasklist handler will bail without raising the event + if (options.tasklists) { + item = processTaskListItem(rgx, item, checked); + } + + // ISSUE #312 + // This input: - - - a + // causes trouble to the parser, since it interprets it as: + //
      • a
      + // instead of: + //
      • - - a
      + // So, to prevent it, we will put a marker (¨A)in the beginning of the line + // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser + item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) { + return '¨A' + wm2; + }); + + // SPECIAL CASE: a heading followed by a paragraph of text that is not separated by a double newline + // or/nor indented. ex: + // + // - # foo + // bar is great + // + // While this does now follow the spec per se, not allowing for this might cause confusion since + // header blocks don't need double-newlines after + if (/^#+.+\n.+/.test(item)) { + item = item.replace(/^(#+.+)$/m, '$1\n'); + } + + // m1 - Leading line or + // Has a double return (multi paragraph) + if (m1 || (item.search(/\n{2,}/) > -1)) { + item = showdown.subParser('makehtml.githubCodeBlock')(item, options, globals); + item = showdown.subParser('makehtml.blockquote')(item, options, globals); + item = showdown.subParser('makehtml.heading')(item, options, globals); + item = showdown.subParser('makehtml.list')(item, options, globals); + item = showdown.subParser('makehtml.codeBlock')(item, options, globals); + item = showdown.subParser('makehtml.table')(item, options, globals); + item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals); + //item = showdown.subParser('makehtml.paragraphs')(item, options, globals); + + // TODO: This is a copy of the paragraph parser + // This is a provisory fix for issue #494 + // For a permanent fix we need to rewrite the paragraph parser, passing the unhashify logic outside + // so that we can call the paragraph parser without accidently unashifying previously parsed blocks + + // Strip leading and trailing lines: + item = item.replace(/^\n+/g, ''); + item = item.replace(/\n+$/g, ''); + + let grafs = item.split(/\n{2,}/g), + grafsOut = [], + end = grafs.length; // Wrap

      tags + + for (let i = 0; i < end; i++) { + let str = grafs[i]; + // if this is an HTML marker, copy it + if (str.search(/¨([KG])(\d+)\1/g) >= 0) { + grafsOut.push(str); + + // test for presence of characters to prevent empty lines being parsed + // as paragraphs (resulting in undesired extra empty paragraphs) + } else if (str.search(/\S/) >= 0) { + str = showdown.subParser('makehtml.spanGamut')(str, options, globals); + str = str.replace(/^([ \t]*)/g, '

      '); + str += '

      '; + grafsOut.push(str); + } + } + item = grafsOut.join('\n'); + // Strip leading and trailing lines: + item = item.replace(/^\n+/g, ''); + item = item.replace(/\n+$/g, ''); + + } else { + + // Recursion for sub-lists: + item = showdown.subParser('makehtml.list')(item, options, globals); + item = item.replace(/\n$/, ''); // chomp(item) + item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals); + + // Colapse double linebreaks + item = item.replace(/\n\n+/g, '\n\n'); + + if (isParagraphed) { + item = showdown.subParser('makehtml.paragraphs')(item, options, globals); + } else { + item = showdown.subParser('makehtml.spanGamut')(item, options, globals); + } + } + + // now we need to remove the marker (¨A) + item = item.replace('¨A', ''); + // we can finally wrap the line in list item tags + + item = '' + item + '\n'; + + } + + let beforeHashEvent = new showdown.Event(eventName + '.onHash', item); + beforeHashEvent + .setOutput(item) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + return beforeHashEvent.output; + }); + + // attacklab: strip sentinel + listStr = listStr.replace(/¨0/g, ''); + + globals.gListLevel--; + + if (trimTrailing) { + listStr = listStr.replace(/\s+$/, ''); + } + + return listStr; + } + + /** + * + * @param {string} list + * @param {string} listType + * @returns {string|null} + */ + function styleStartNumber (list, listType) { + // check if ol and starts by a number different than 1 + if (listType === 'ol') { + let res = list.match(/^ *(\d+)\./); + if (res && res[1] !== '1') { + return res[1]; + } + } + return null; + } + + /** + * Check and parse consecutive lists (better fix for issue #142) + * @param {RegExp} pattern + * @param {string} list + * @param {string} listType + * @param {boolean} trimTrailing + * @returns {string} + */ + function parseConsecutiveLists (pattern, list, listType, trimTrailing) { + let otp = ''; + let captureStartEvent = new showdown.Event('makehtml.list.onCapture', list); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: list, + list: list + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + let attributes = captureStartEvent.attributes; + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + + // check if we caught 2 or more consecutive lists by mistake + // we use the counterRgx, meaning if listType is UL we look for OL and vice versa + const olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm; + const ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm; + let counterRxg = (listType === 'ul') ? olRgx : ulRgx; + + let attrs = showdown.helper.cloneObject(attributes); + if (list.search(counterRxg) !== -1) { + + (function parseCL (txt) { + let pos = txt.search(counterRxg); + attrs.start = styleStartNumber(list, listType); + + if (pos !== -1) { + // slice + otp += '\n\n<' + listType + showdown.helper._populateAttributes(attrs) + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '\n'; + + // invert counterType and listType + listType = (listType === 'ul') ? 'ol' : 'ul'; + counterRxg = (listType === 'ul') ? olRgx : ulRgx; + + //recurse + parseCL(txt.slice(pos), attrs); + } else { + otp += '\n\n<' + listType + showdown.helper._populateAttributes(attrs) + '>\n' + processListItems(txt, !!trimTrailing) + '\n'; + } + })(list, attributes); + + } else { + attrs.start = styleStartNumber(list, listType); + otp = '\n\n<' + listType + showdown.helper._populateAttributes(attrs) + '>\n' + processListItems(list, !!trimTrailing) + '\n'; + } + } + return otp; + } +}); diff --git a/src/subParsers/makehtml/lists.js b/src/subParsers/makehtml/lists.js deleted file mode 100644 index 9d34889..0000000 --- a/src/subParsers/makehtml/lists.js +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Form HTML ordered (numbered) and unordered (bulleted) lists. - */ -showdown.subParser('makehtml.lists', function (text, options, globals) { - 'use strict'; - - /** - * Process the contents of a single ordered or unordered list, splitting it - * into individual list items. - * @param {string} listStr - * @param {boolean} trimTrailing - * @returns {string} - */ - function processListItems (listStr, trimTrailing) { - // The $g_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.". - globals.gListLevel++; - - // trim trailing blank lines: - listStr = listStr.replace(/\n{2,}$/, '\n'); - - // attacklab: add sentinel to emulate \z - listStr += '¨0'; - - var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[([xX ])])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm, - isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr)); - - // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation, - // which is a syntax breaking change - // activating this option reverts to old behavior - // This will be removed in version 2.0 - if (options.disableForced4SpacesIndentedSublists) { - rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[([xX ])])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm; - } - - listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) { - checked = (checked && checked.trim() !== ''); - - var item = showdown.subParser('makehtml.outdent')(m4, options, globals), - bulletStyle = ''; - - // Support for github tasklists - if (taskbtn && options.tasklists) { - - // Style used for tasklist bullets - bulletStyle = ' class="task-list-item'; - if (options.moreStyling) {bulletStyle += checked ? ' task-list-item-complete' : '';} - bulletStyle += '" style="list-style-type: none;"'; - - item = item.replace(/^[ \t]*\[([xX ])?]/m, function () { - var otp = '
    1. a
- // instead of: - //
  • - - a
- // So, to prevent it, we will put a marker (¨A)in the beginning of the line - // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser - item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) { - return '¨A' + wm2; - }); - - // SPECIAL CASE: a heading followed by a paragraph of text that is not separated by a double newline - // or/nor indented. ex: - // - // - # foo - // bar is great - // - // While this does now follow the spec per se, not allowing for this might cause confusion since - // header blocks don't need double-newlines after - if (/^#+.+\n.+/.test(item)) { - item = item.replace(/^(#+.+)$/m, '$1\n'); - } - - // m1 - Leading line or - // Has a double return (multi paragraph) - if (m1 || (item.search(/\n{2,}/) > -1)) { - item = showdown.subParser('makehtml.githubCodeBlocks')(item, options, globals); - item = showdown.subParser('makehtml.blockQuotes')(item, options, globals); - item = showdown.subParser('makehtml.headers')(item, options, globals); - item = showdown.subParser('makehtml.lists')(item, options, globals); - item = showdown.subParser('makehtml.codeBlocks')(item, options, globals); - item = showdown.subParser('makehtml.tables')(item, options, globals); - item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals); - //item = showdown.subParser('makehtml.paragraphs')(item, options, globals); - - // TODO: This is a copy of the paragraph parser - // This is a provisory fix for issue #494 - // For a permanente fix we need to rewrite the paragraph parser, passing the unhashify logic outside - // so that we can call the paragraph parser without accidently unashifying previously parsed blocks - - // Strip leading and trailing lines: - item = item.replace(/^\n+/g, ''); - item = item.replace(/\n+$/g, ''); - - var grafs = item.split(/\n{2,}/g), - grafsOut = [], - end = grafs.length; // Wrap

tags - - for (var i = 0; i < end; i++) { - var str = grafs[i]; - // if this is an HTML marker, copy it - if (str.search(/¨([KG])(\d+)\1/g) >= 0) { - grafsOut.push(str); - - // test for presence of characters to prevent empty lines being parsed - // as paragraphs (resulting in undesired extra empty paragraphs) - } else if (str.search(/\S/) >= 0) { - str = showdown.subParser('makehtml.spanGamut')(str, options, globals); - str = str.replace(/^([ \t]*)/g, '

'); - str += '

'; - grafsOut.push(str); - } - } - item = grafsOut.join('\n'); - // Strip leading and trailing lines: - item = item.replace(/^\n+/g, ''); - item = item.replace(/\n+$/g, ''); - - } else { - - // Recursion for sub-lists: - item = showdown.subParser('makehtml.lists')(item, options, globals); - item = item.replace(/\n$/, ''); // chomp(item) - item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals); - - // Colapse double linebreaks - item = item.replace(/\n\n+/g, '\n\n'); - - if (isParagraphed) { - item = showdown.subParser('makehtml.paragraphs')(item, options, globals); - } else { - item = showdown.subParser('makehtml.spanGamut')(item, options, globals); - } - } - - // now we need to remove the marker (¨A) - item = item.replace('¨A', ''); - // we can finally wrap the line in list item tags - item = '' + item + '\n'; - - return item; - }); - - // attacklab: strip sentinel - listStr = listStr.replace(/¨0/g, ''); - - globals.gListLevel--; - - if (trimTrailing) { - listStr = listStr.replace(/\s+$/, ''); - } - - return listStr; - } - - function styleStartNumber (list, listType) { - // check if ol and starts by a number different than 1 - if (listType === 'ol') { - var res = list.match(/^ *(\d+)\./); - if (res && res[1] !== '1') { - return ' start="' + res[1] + '"'; - } - } - return ''; - } - - /** - * Check and parse consecutive lists (better fix for issue #142) - * @param {string} list - * @param {string} listType - * @param {boolean} trimTrailing - * @returns {string} - */ - function parseConsecutiveLists (list, listType, trimTrailing) { - // check if we caught 2 or more consecutive lists by mistake - // we use the counterRgx, meaning if listType is UL we look for OL and vice versa - var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm, - ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm, - counterRxg = (listType === 'ul') ? olRgx : ulRgx, - result = ''; - - if (list.search(counterRxg) !== -1) { - (function parseCL (txt) { - var pos = txt.search(counterRxg), - style = styleStartNumber(list, listType); - if (pos !== -1) { - // slice - result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '\n'; - - // invert counterType and listType - listType = (listType === 'ul') ? 'ol' : 'ul'; - counterRxg = (listType === 'ul') ? olRgx : ulRgx; - - //recurse - parseCL(txt.slice(pos)); - } else { - result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '\n'; - } - })(list); - } else { - var style = styleStartNumber(list, listType); - result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '\n'; - } - - return result; - } - - // Start of list parsing - var subListRgx = /^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; - var mainListRgx = /(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; - - text = globals.converter._dispatch('lists.before', text, options, globals).getText(); - // add sentinel to hack around khtml/safari bug: - // http://bugs.webkit.org/show_bug.cgi?id=11231 - text += '¨0'; - - if (globals.gListLevel) { - text = text.replace(subListRgx, function (wholeMatch, list, m2) { - var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; - return parseConsecutiveLists(list, listType, true); - }); - } else { - text = text.replace(mainListRgx, function (wholeMatch, m1, list, m3) { - var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol'; - return parseConsecutiveLists(list, listType, false); - }); - } - - // strip sentinel - text = text.replace(/¨0/, ''); - text = globals.converter._dispatch('makehtml.lists.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/metadata.js b/src/subParsers/makehtml/metadata.js index c665287..8b15176 100644 --- a/src/subParsers/makehtml/metadata.js +++ b/src/subParsers/makehtml/metadata.js @@ -8,11 +8,50 @@ showdown.subParser('makehtml.metadata', function (text, options, globals) { return text; } - text = globals.converter._dispatch('makehtml.metadata.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.metadata.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + /** + * @param {RegExp} pattern + * @param {string} wholeMatch + * @param {string} format + * @param {string} content + * @returns {string} + */ + function parseMetadataContents (pattern, wholeMatch, format, content) { + let otp; + let captureStartEvent = new showdown.Event('makehtml.metadata.onCapture', content); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + format: format, + content: content + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + + format = captureStartEvent.matches.format; + content = captureStartEvent.matches.content; + + // if something was passed as output, it will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + otp = '¨M'; + } - function parseMetadataContents (content) { // raw is raw so it's not changed in any way globals.metadata.raw = content; + globals.metadata.format = format; // escape chars forbidden in html attributes // double quotes @@ -20,35 +59,47 @@ showdown.subParser('makehtml.metadata', function (text, options, globals) { // ampersand first .replace(/&/g, '&') // double quotes - .replace(/"/g, '"'); - + .replace(/"/g, '"') // Restore dollar signs and tremas - content = content .replace(/¨D/g, '$$') - .replace(/¨T/g, '¨'); + .replace(/¨T/g, '¨') + // replace multiple spaces + .replace(/\n {4}/g, ' '); - content = content.replace(/\n {4}/g, ' '); content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) { globals.metadata.parsed[key] = value; return ''; }); + let beforeHashEvent = new showdown.Event('makehtml.metadata.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + if (!otp) { + otp = '¨M'; + } + return otp; } - text = text.replace(/^\s*«««+\s*(\S*?)\n([\s\S]+?)\n»»»+\s*\n/, function (wholematch, format, content) { - parseMetadataContents(content); - return '¨M'; + // 1. Metadata with «««»»» delimiters + const rgx1 = /^\s*«««+\s*(\S*?)\n([\s\S]+?)\n»»»+\s*\n/; + text = text.replace(rgx1, function (wholeMatch, format, content) { + return parseMetadataContents(rgx1, wholeMatch, format, content); }); - text = text.replace(/^\s*---+\s*(\S*?)\n([\s\S]+?)\n---+\s*\n/, function (wholematch, format, content) { - if (format) { - globals.metadata.format = format; - } - parseMetadataContents(content); - return '¨M'; + // 2. Metadata with YAML delimiters + const rgx2 = /^\s*---+\s*(\S*?)\n([\s\S]+?)\n---+\s*\n/; + text = text.replace(rgx2, function (wholeMatch, format, content) { + return parseMetadataContents(rgx1, wholeMatch, format, content); }); - text = text.replace(/¨M/g, ''); - - text = globals.converter._dispatch('makehtml.metadata.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.metadata.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/outdent.js b/src/subParsers/makehtml/outdent.js deleted file mode 100644 index 67f4106..0000000 --- a/src/subParsers/makehtml/outdent.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Remove one level of line-leading tabs or spaces - */ -showdown.subParser('makehtml.outdent', function (text, options, globals) { - 'use strict'; - text = globals.converter._dispatch('makehtml.outdent.before', text, options, globals).getText(); - - // attacklab: hack around Konqueror 3.5.4 bug: - // "----------bug".replace(/^-/g,"") == "bug" - text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width - - // attacklab: clean up hack - text = text.replace(/¨0/g, ''); - - text = globals.converter._dispatch('makehtml.outdent.after', text, options, globals).getText(); - return text; -}); diff --git a/src/subParsers/makehtml/paragraphs.js b/src/subParsers/makehtml/paragraphs.js index 81acdf3..1792ff8 100644 --- a/src/subParsers/makehtml/paragraphs.js +++ b/src/subParsers/makehtml/paragraphs.js @@ -4,7 +4,6 @@ showdown.subParser('makehtml.paragraphs', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.paragraphs.before', text, options, globals).getText(); // Strip leading and trailing lines: text = text.replace(/^\n+/g, ''); text = text.replace(/\n+$/g, ''); @@ -37,7 +36,7 @@ showdown.subParser('makehtml.paragraphs', function (text, options, globals) { codeFlag = false; // if this is a marker for an html block... // use RegExp.test instead of string.search because of QML bug - while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) { + while (/¨([KG])(\d+)\1/.test(grafsOutIt)) { var delim = RegExp.$1, num = RegExp.$2; @@ -54,7 +53,7 @@ showdown.subParser('makehtml.paragraphs', function (text, options, globals) { } blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs - grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText); + grafsOutIt = grafsOutIt.replace(/(\n\n)?¨([KG])\d+\2(\n\n)?/, blockText); // Check if grafsOutIt is a pre->code if (/^]*>\s*]*>/.test(grafsOutIt)) { codeFlag = true; @@ -66,5 +65,5 @@ showdown.subParser('makehtml.paragraphs', function (text, options, globals) { // Strip leading and trailing lines: text = text.replace(/^\n+/g, ''); text = text.replace(/\n+$/g, ''); - return globals.converter._dispatch('makehtml.paragraphs.after', text, options, globals).getText(); + return text; }); diff --git a/src/subParsers/makehtml/runExtension.js b/src/subParsers/makehtml/runExtension.js index cf5b411..c23ee5e 100644 --- a/src/subParsers/makehtml/runExtension.js +++ b/src/subParsers/makehtml/runExtension.js @@ -9,7 +9,7 @@ showdown.subParser('makehtml.runExtension', function (ext, text, options, global } else if (ext.regex) { // TODO remove this when old extension loading mechanism is deprecated - var re = ext.regex; + let re = ext.regex; if (!(re instanceof RegExp)) { re = new RegExp(re, 'g'); } diff --git a/src/subParsers/makehtml/spanGamut.js b/src/subParsers/makehtml/spanGamut.js index 2f2205b..794a115 100644 --- a/src/subParsers/makehtml/spanGamut.js +++ b/src/subParsers/makehtml/spanGamut.js @@ -5,25 +5,26 @@ showdown.subParser('makehtml.spanGamut', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.span.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.spanGamut.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; - text = showdown.subParser('makehtml.codeSpans')(text, options, globals); + text = showdown.subParser('makehtml.codeSpan')(text, options, globals); text = showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes')(text, options, globals); text = showdown.subParser('makehtml.encodeBackslashEscapes')(text, options, globals); // Process link and image tags. Images must come first, // because ![foo][f] looks like a link. - text = showdown.subParser('makehtml.images')(text, options, globals); + text = showdown.subParser('makehtml.image')(text, options, globals); + text = showdown.subParser('makehtml.link')(text, options, globals); - text = globals.converter._dispatch('smakehtml.links.before', text, options, globals).getText(); - text = showdown.subParser('makehtml.links')(text, options, globals); - text = globals.converter._dispatch('smakehtml.links.after', text, options, globals).getText(); - - //text = showdown.subParser('makehtml.autoLinks')(text, options, globals); - //text = showdown.subParser('makehtml.simplifiedAutoLinks')(text, options, globals); text = showdown.subParser('makehtml.emoji')(text, options, globals); text = showdown.subParser('makehtml.underline')(text, options, globals); - text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals); + text = showdown.subParser('makehtml.emphasisAndStrong')(text, options, globals); text = showdown.subParser('makehtml.strikethrough')(text, options, globals); text = showdown.subParser('makehtml.ellipsis')(text, options, globals); @@ -45,6 +46,11 @@ showdown.subParser('makehtml.spanGamut', function (text, options, globals) { text = text.replace(/ +\n/g, '
\n'); } - text = globals.converter._dispatch('makehtml.spanGamut.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.spanGamut.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/strikethrough.js b/src/subParsers/makehtml/strikethrough.js index ca8f630..ff77503 100644 --- a/src/subParsers/makehtml/strikethrough.js +++ b/src/subParsers/makehtml/strikethrough.js @@ -1,11 +1,55 @@ showdown.subParser('makehtml.strikethrough', function (text, options, globals) { 'use strict'; - - if (options.strikethrough) { - text = globals.converter._dispatch('makehtml.strikethrough.before', text, options, globals).getText(); - text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return '' + txt + ''; }); - text = globals.converter._dispatch('makehtml.strikethrough.after', text, options, globals).getText(); + if (!options.strikethrough) { + return text; } - return text; + let startEvent = new showdown.Event('makehtml.strikethrough.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + const strikethroughRegex = /~{2}([\s\S]+?)~{2}/g; + text = text.replace(strikethroughRegex, function (wholeMatch, txt) { + + let otp; + let captureStartEvent = new showdown.Event('makehtml.strikethrough.onCapture', txt); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(strikethroughRegex) + .setMatches({ + _wholeMatch: wholeMatch, + strikethrough: txt + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + otp = '' + txt + ''; + } + + let beforeHashEvent = new showdown.Event('makehtml.strikethrough.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + return beforeHashEvent.output; + }); + + let afterEvent = new showdown.Event('makehtml.strikethrough.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/stripLinkDefinitions.js b/src/subParsers/makehtml/stripLinkDefinitions.js index 894c8d9..092989f 100644 --- a/src/subParsers/makehtml/stripLinkDefinitions.js +++ b/src/subParsers/makehtml/stripLinkDefinitions.js @@ -6,13 +6,13 @@ showdown.subParser('makehtml.stripLinkDefinitions', function (text, options, globals) { 'use strict'; - var regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm, - base64Regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm; + const regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm, + base64Regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm; // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug text += '¨0'; - var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) { + let replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) { // if there aren't two instances of linkId it must not be a reference link so back out linkId = linkId.toLowerCase(); @@ -35,7 +35,7 @@ showdown.subParser('makehtml.stripLinkDefinitions', function (text, options, glo } else { if (title) { - globals.gTitles[linkId] = title.replace(/"|'/g, '"'); + globals.gTitles[linkId] = title.replace(/["']/g, '"'); } if (options.parseImgDimensions && width && height) { globals.gDimensions[linkId] = { diff --git a/src/subParsers/makehtml/table.js b/src/subParsers/makehtml/table.js new file mode 100644 index 0000000..87fdb41 --- /dev/null +++ b/src/subParsers/makehtml/table.js @@ -0,0 +1,326 @@ +showdown.subParser('makehtml.table', function (text, options, globals) { + 'use strict'; + + if (!options.tables) { + return text; + } + + // find escaped pipe characters + text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback); + + // + // parser starts here + // + let startEvent = new showdown.Event('makehtml.table.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + // parse multi column tables + const tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*[-=]{2,}[\s\S]+?(?:\n\n|¨0)/gm; + text = text.replace(tableRgx, function (wholeMatch) { + return parse(tableRgx, wholeMatch); + }); + + const singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm; + text = text.replace(singeColTblRgx, function (wholeMatch) { + return parse(singeColTblRgx, wholeMatch); + }); + + let afterEvent = new showdown.Event('makehtml.table.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; + + + + + /** + * + * @param {RegExp} pattern + * @param {string} wholeMatch + * @returns {string} + */ + function parse (pattern, wholeMatch) { + let tab = preParse(wholeMatch); + + // if parseTable returns null then it's a malformed table so we return what we caught + if (!tab) { + return wholeMatch; + } + + // only now we consider it to be a markdown table and start doing stuff + let headers = tab.rawHeaders; + let styles = tab.rawStyles; + let cells = tab.rawCells; + + let otp; + let captureStartEvent = new showdown.Event('makehtml.table.onCapture', wholeMatch); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + table: wholeMatch + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + if (captureStartEvent.output && captureStartEvent.output !== '') { + // user provided an otp, so we use it + otp = captureStartEvent.output; + } else { + // user changed matches.table, so we need to generate headers, styles, and cells again + if (captureStartEvent.matches.table !== wholeMatch) { + tab = preParse(captureStartEvent.matches.table); + // user passed a malformed table, so we bail + if (!tab) { + return wholeMatch; + } + headers = tab.rawHeaders; + styles = tab.rawStyles; + cells = tab.rawCells; + } + let parsedTab = parseTable (headers, styles, cells); + let attributes = captureStartEvent.attributes; + otp = buildTableOtp(parsedTab.headers, parsedTab.cells, attributes); + } + + let beforeHashEvent = new showdown.Event('makehtml.table.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + otp = beforeHashEvent.output; + return otp; + } + + /** + * + * @param {string[]} headers + * @param {string[]} cells + * @param {{}} attributes + * @returns {string} + */ + function buildTableOtp (headers, cells, attributes) { + let otp; + const colCount = headers.length, + rowCount = cells.length; + + otp = '\n\n\n'; + for (let i = 0; i < colCount; ++i) { + otp += headers[i]; + } + otp += '\n\n\n'; + + for (let i = 0; i < rowCount; ++i) { + otp += '\n'; + for (let ii = 0; ii < colCount; ++ii) { + otp += cells[i][ii]; + } + otp += '\n'; + } + otp += '\n\n'; + return otp; + } + + /** + * @param {string} rawTable + * @returns {{rawHeaders: string[], rawStyles: string[], rawCells: *[]}|null} + */ + function preParse (rawTable) { + let tableLines = rawTable.split('\n'); + + for (let i = 0; i < tableLines.length; ++i) { + // strip wrong first and last column if wrapped tables are used + if (/^ {0,3}\|/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, ''); + } + if (/\|[ \t]*$/.test(tableLines[i])) { + tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, ''); + } + // parse code spans first, but we only support one line code spans + tableLines[i] = showdown.subParser('makehtml.codeSpan')(tableLines[i], options, globals); + } + + let rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}), + rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}), + rawCells = []; + + tableLines.shift(); + tableLines.shift(); + + for (let i = 0; i < tableLines.length; ++i) { + if (tableLines[i].trim() === '') { + continue; + } + rawCells.push( + tableLines[i] + .split('|') + .map(function (s) { + return s.trim(); + }) + ); + } + + if (rawHeaders.length < rawStyles.length) { + return null; + } + + return { + rawHeaders: rawHeaders, + rawStyles: rawStyles, + rawCells: rawCells + }; + } + + /** + * + * @param {string[]} rawHeaders + * @param {string[]} rawStyles + * @param {string[]} rawCells + * @returns {{headers: *, cells: *}} + */ + function parseTable (rawHeaders, rawStyles, rawCells) { + const headers = [], + cells = [], + styles = [], + colCount = rawHeaders.length, + rowCount = rawCells.length; + + for (let i = 0; i < colCount; ++i) { + styles.push(parseStyle(rawStyles[i])); + } + + for (let i = 0; i < colCount; ++i) { + let header = rawHeaders[i]; + let captureStartEvent = new showdown.Event('makehtml.table.header.onCapture', rawHeaders[i]); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(null) + .setMatches({ + _wholeMatch: rawHeaders[i], + header: rawHeaders[i] + }) + .setAttributes(styles[i]); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + if (captureStartEvent.output && captureStartEvent.output !== '') { + // user provided an otp, so we use it + header = captureStartEvent.output; + } else { + header = parseHeader(captureStartEvent.matches.header, styles[i]); + } + let beforeHashEvent = new showdown.Event('makehtml.table.header.onHash', header); + beforeHashEvent + .setOutput(header) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + header = beforeHashEvent.output; + + headers.push(header); + } + + for (let i = 0; i < rowCount; ++i) { + let row = []; + for (let ii = 0; ii < colCount; ++ii) { + let cell = (!showdown.helper.isUndefined(rawCells[i][ii])) ? rawCells[i][ii] : '', + attributes = (!showdown.helper.isUndefined(styles[ii])) ? styles[ii] : {}; + + // since we're reusing attributes, we might need to remove the id that we previously set for headers + if (attributes.id) { + attributes.classes = [attributes.id] + '_col'; + delete attributes.id; + } + + + let captureStartEvent = new showdown.Event('makehtml.table.cell.onCapture', cell); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(null) + .setMatches({ + _wholeMatch: cell, + cell: cell + }) + .setAttributes(attributes); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + if (captureStartEvent.output && captureStartEvent.output !== '') { + // user provided an otp, so we use it + cell = captureStartEvent.output; + } else { + attributes = captureStartEvent.attributes; + cell = parseCell(captureStartEvent.matches.cell, attributes); + } + let beforeHashEvent = new showdown.Event('makehtml.table.cell.onHash', cell); + beforeHashEvent + .setOutput(cell) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + cell = beforeHashEvent.output; + + row.push(cell); + } + cells.push(row); + } + + return {headers: headers, cells: cells}; + } + + /** + * @param {string} sLine + * @returns {{}|{style: string}} + */ + function parseStyle (sLine) { + if (/^:[ \t]*-+$/.test(sLine)) { + return { style: 'text-align:left;' }; + } else if (/^-+[ \t]*:[ \t]*$/.test(sLine)) { + return { style: 'text-align:right;' }; + } else if (/^:[ \t]*-+[ \t]*:$/.test(sLine)) { + return { style: 'text-align:center;' }; + } else { + return {}; + } + } + + /** + * + * @param {string} headerText + * @param {{id: string}} attributes + * @returns {string} + */ + function parseHeader (headerText, attributes) { + headerText = headerText.trim(); + headerText = showdown.subParser('makehtml.spanGamut')(headerText, options, globals); + + // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility + // TODO think about this option!!! and remove backwards compatibility + if (options.tablesHeaderId || options.tableHeaderId) { + attributes.id = headerText.replace(/ /g, '_').toLowerCase(); + } + return '' + headerText + '\n'; + } + + /** + * + * @param {string} cellText + * @param {{}} attributes + * @returns {string} + */ + function parseCell (cellText, attributes) { + cellText = showdown.subParser('makehtml.spanGamut')(cellText, options, globals); + return '' + cellText + '\n'; + } +}); diff --git a/src/subParsers/makehtml/tables.js b/src/subParsers/makehtml/tables.js deleted file mode 100644 index a1331a9..0000000 --- a/src/subParsers/makehtml/tables.js +++ /dev/null @@ -1,143 +0,0 @@ -showdown.subParser('makehtml.tables', function (text, options, globals) { - 'use strict'; - - if (!options.tables) { - return text; - } - - var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*[-=]{2,}[\s\S]+?(?:\n\n|¨0)/gm, - //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm; - singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*[-=]{2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm; - - function parseStyles (sLine) { - if (/^:[ \t]*--*$/.test(sLine)) { - return ' style="text-align:left;"'; - } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) { - return ' style="text-align:right;"'; - } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) { - return ' style="text-align:center;"'; - } else { - return ''; - } - } - - function parseHeaders (header, style) { - var id = ''; - header = header.trim(); - // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility - if (options.tablesHeaderId || options.tableHeaderId) { - id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"'; - } - header = showdown.subParser('makehtml.spanGamut')(header, options, globals); - - return '' + header + '\n'; - } - - function parseCells (cell, style) { - var subText = showdown.subParser('makehtml.spanGamut')(cell, options, globals); - return '' + subText + '\n'; - } - - function buildTable (headers, cells) { - var tb = '\n\n\n', - tblLgn = headers.length; - - for (var i = 0; i < tblLgn; ++i) { - tb += headers[i]; - } - tb += '\n\n\n'; - - for (i = 0; i < cells.length; ++i) { - tb += '\n'; - for (var ii = 0; ii < tblLgn; ++ii) { - tb += cells[i][ii]; - } - tb += '\n'; - } - tb += '\n
\n'; - return tb; - } - - function parseTable (rawTable) { - var i, tableLines = rawTable.split('\n'); - - for (i = 0; i < tableLines.length; ++i) { - // strip wrong first and last column if wrapped tables are used - if (/^ {0,3}\|/.test(tableLines[i])) { - tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, ''); - } - if (/\|[ \t]*$/.test(tableLines[i])) { - tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, ''); - } - // parse code spans first, but we only support one line code spans - - tableLines[i] = showdown.subParser('makehtml.codeSpans')(tableLines[i], options, globals); - } - - var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}), - rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}), - rawCells = [], - headers = [], - styles = [], - cells = []; - - tableLines.shift(); - tableLines.shift(); - - for (i = 0; i < tableLines.length; ++i) { - if (tableLines[i].trim() === '') { - continue; - } - rawCells.push( - tableLines[i] - .split('|') - .map(function (s) { - return s.trim(); - }) - ); - } - - if (rawHeaders.length < rawStyles.length) { - return rawTable; - } - - for (i = 0; i < rawStyles.length; ++i) { - styles.push(parseStyles(rawStyles[i])); - } - - for (i = 0; i < rawHeaders.length; ++i) { - if (showdown.helper.isUndefined(styles[i])) { - styles[i] = ''; - } - headers.push(parseHeaders(rawHeaders[i], styles[i])); - } - - for (i = 0; i < rawCells.length; ++i) { - var row = []; - for (var ii = 0; ii < headers.length; ++ii) { - if (showdown.helper.isUndefined(rawCells[i][ii])) { - - } - row.push(parseCells(rawCells[i][ii], styles[ii])); - } - cells.push(row); - } - - return buildTable(headers, cells); - } - - text = globals.converter._dispatch('makehtml.tables.before', text, options, globals).getText(); - - // find escaped pipe characters - text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback); - - // parse multi column tables - text = text.replace(tableRgx, parseTable); - - // parse one column tables - text = text.replace(singeColTblRgx, parseTable); - - text = globals.converter._dispatch('makehtml.tables.after', text, options, globals).getText(); - - return text; -}); diff --git a/src/subParsers/makehtml/underline.js b/src/subParsers/makehtml/underline.js index a3d4414..d223474 100644 --- a/src/subParsers/makehtml/underline.js +++ b/src/subParsers/makehtml/underline.js @@ -5,28 +5,85 @@ showdown.subParser('makehtml.underline', function (text, options, globals) { return text; } - text = globals.converter._dispatch('makehtml.underline.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.underline.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; if (options.literalMidWordUnderscores) { - text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) { - return '' + txt + ''; + + const rgx1 = /\b___(\S[\s\S]*?)___\b/g; + text = text.replace(rgx1, function (wm, txt) { + return parse(rgx1, wm, txt); }); - text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) { - return '' + txt + ''; + + const rgx2 = /\b__(\S[\s\S]*?)__\b/g; + text = text.replace(rgx2, function (wm, txt) { + return parse(rgx2, wm, txt); }); } else { - text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) { - return (/\S$/.test(m)) ? '' + m + '' : wm; + + const rgx3 = /___(\S[\s\S]*?)___/g; + text = text.replace(rgx3, function (wm, txt) { + if (!(/\S$/.test(txt))) { + return wm; + } + return parse(rgx3, wm, txt); }); - text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) { - return (/\S$/.test(m)) ? '' + m + '' : wm; + + const rgx4 = /__(\S[\s\S]*?)__/g; + text = text.replace(rgx4, function (wm, txt) { + if (!(/\S$/.test(txt))) { + return wm; + } + return parse(rgx4, wm, txt); }); } // escape remaining underscores to prevent them being parsed by italic and bold text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback); - text = globals.converter._dispatch('makehtml.underline.after', text, options, globals).getText(); + let afterEvent = new showdown.Event('makehtml.underline.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; + + + function parse (pattern, wholeMatch, txt) { + let otp; + let captureStartEvent = new showdown.Event('makehtml.underline.onCapture', txt); + captureStartEvent + .setOutput(null) + ._setGlobals(globals) + ._setOptions(options) + .setRegexp(pattern) + .setMatches({ + _wholeMatch: wholeMatch, + strikethrough: txt + }) + .setAttributes({}); + captureStartEvent = globals.converter.dispatch(captureStartEvent); + // if something was passed as output, it takes precedence + // and will be used as output + if (captureStartEvent.output && captureStartEvent.output !== '') { + otp = captureStartEvent.output; + } else { + otp = '' + txt + ''; + } + let beforeHashEvent = new showdown.Event('makehtml.underline.onHash', otp); + beforeHashEvent + .setOutput(otp) + ._setGlobals(globals) + ._setOptions(options); + beforeHashEvent = globals.converter.dispatch(beforeHashEvent); + return beforeHashEvent.output; + } + - return text; }); diff --git a/src/subParsers/makehtml/unescapeSpecialChars.js b/src/subParsers/makehtml/unescapeSpecialChars.js index b96144e..3ce0193 100644 --- a/src/subParsers/makehtml/unescapeSpecialChars.js +++ b/src/subParsers/makehtml/unescapeSpecialChars.js @@ -3,13 +3,24 @@ */ showdown.subParser('makehtml.unescapeSpecialChars', function (text, options, globals) { 'use strict'; - text = globals.converter._dispatch('makehtml.unescapeSpecialChars.before', text, options, globals).getText(); + let startEvent = new showdown.Event('makehtml.unescapeSpecialChars.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) { - var charCodeToReplace = parseInt(m1); + let charCodeToReplace = parseInt(m1); return String.fromCharCode(charCodeToReplace); }); - text = globals.converter._dispatch('makehtml.unescapeSpecialChars.after', text, options, globals).getText(); - return text; + let afterEvent = new showdown.Event('makehtml.unescapeSpecialChars.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; }); diff --git a/src/subParsers/makehtml/unhashHTMLSpans.js b/src/subParsers/makehtml/unhashHTMLSpans.js new file mode 100644 index 0000000..3b61a88 --- /dev/null +++ b/src/subParsers/makehtml/unhashHTMLSpans.js @@ -0,0 +1,46 @@ +//// +// makehtml/unhashHTMLSpans.js +// Copyright (c) 2018 ShowdownJS +// +// Unhash HTML spans +// +// ***Author:*** +// - Estêvão Soares dos Santos (Tivie) +//// + + +showdown.subParser('makehtml.unhashHTMLSpans', function (text, options, globals) { + 'use strict'; + let startEvent = new showdown.Event('makehtml.unhashHTMLSpans.onStart', text); + startEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + startEvent = globals.converter.dispatch(startEvent); + text = startEvent.output; + + for (let i = 0; i < globals.gHtmlSpans.length; ++i) { + let repText = globals.gHtmlSpans[i], + // limiter to prevent infinite loop (assume 20 as limit for recurse) + limit = 0; + + while (/¨C(\d+)C/.test(repText)) { + let num = repText.match(/¨C(\d+)C/)[1]; + repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]); + if (limit === 10) { + console.error('maximum nesting of 20 spans reached!!!'); + break; + } + ++limit; + } + text = text.replace('¨C' + i + 'C', repText); + } + + let afterEvent = new showdown.Event('makehtml.unhashHTMLSpans.onEnd', text); + afterEvent + .setOutput(text) + ._setGlobals(globals) + ._setOptions(options); + afterEvent = globals.converter.dispatch(afterEvent); + return afterEvent.output; +}); diff --git a/test/bootstrap.js b/test/bootstrap.js index 5c2ec14..6cc713c 100644 --- a/test/bootstrap.js +++ b/test/bootstrap.js @@ -1,6 +1,22 @@ //.webstorm.bootstrap.js -var chai = require('chai'); +const chai = require('chai'); +const fs = require('fs'); global.chai = chai; global.expect = chai.expect; global.showdown = require('../.build/showdown.js'); global.getDefaultOpts = require('./optionswp.js').getDefaultOpts; + +// mock XMLHttpRequest for browser and node test +function XMLHttpRequest () { + this.responseText = null; + this.status = null; + + this.open = function (mode, file) { + //mode is ignored, it's always sync + this.responseText = fs.readFileSync(file); + this.status = 200; + return this; + }; +} + +global.XMLHttpRequest = XMLHttpRequest; diff --git a/test/functional/makehtml/cases/features/customizedHeaderId/simple.html b/test/functional/makehtml/cases/features/customizedHeaderId/simple.html new file mode 100644 index 0000000..8599cb6 --- /dev/null +++ b/test/functional/makehtml/cases/features/customizedHeaderId/simple.html @@ -0,0 +1 @@ +

some header

diff --git a/test/functional/makehtml/cases/features/customizedHeaderId/simple.md b/test/functional/makehtml/cases/features/customizedHeaderId/simple.md new file mode 100644 index 0000000..15c59e0 --- /dev/null +++ b/test/functional/makehtml/cases/features/customizedHeaderId/simple.md @@ -0,0 +1 @@ +# some header {some-id} diff --git a/test/functional/makehtml/cases/features/emojis/special.html b/test/functional/makehtml/cases/features/emojis/special.html index 8068ec6..69611ac 100644 --- a/test/functional/makehtml/cases/features/emojis/special.html +++ b/test/functional/makehtml/cases/features/emojis/special.html @@ -1,2 +1,2 @@ -

this is showdown's emoji

-

and this is github's emoji

+

this is showdown's emoji showdown

+

and this is github's emoji octocat

diff --git a/test/functional/makehtml/cases/features/tables/basic-with-header-ids.html b/test/functional/makehtml/cases/features/tables/basic-with-header-ids.html index 3843ed3..8ce92a5 100644 --- a/test/functional/makehtml/cases/features/tables/basic-with-header-ids.html +++ b/test/functional/makehtml/cases/features/tables/basic-with-header-ids.html @@ -7,12 +7,12 @@ - Row 1 Cell 1 - Row 1 Cell 2 + Row 1 Cell 1 + Row 1 Cell 2 - Row 2 Cell 1 - Row 2 Cell 2 + Row 2 Cell 1 + Row 2 Cell 2 diff --git a/test/functional/makehtml/cases/standard/images.html b/test/functional/makehtml/cases/standard/images.html index f28e0b9..a16ba90 100644 --- a/test/functional/makehtml/cases/standard/images.html +++ b/test/functional/makehtml/cases/standard/images.html @@ -1,6 +1,7 @@

Alt text

Alt text

Alt text

-

My Image

+

some alt text

+

My Image

![leave me alone]

![leave me alone][]

diff --git a/test/functional/makehtml/cases/standard/images.md b/test/functional/makehtml/cases/standard/images.md index 2cd5930..bc9dbb6 100644 --- a/test/functional/makehtml/cases/standard/images.md +++ b/test/functional/makehtml/cases/standard/images.md @@ -4,6 +4,8 @@ ![Alt text][id] +![some alt text][1] + ![My Image] ![leave me alone] @@ -11,4 +13,5 @@ ![leave me alone][] [id]: url/to/image.jpg "Optional title attribute" - [My Image]: url/to/image2.jpg "Optional title attribute" + [1]: url/to/image2.jpg + [My Image]: url/to/image3.jpg "Optional title attribute" diff --git a/test/functional/makehtml/testsuite.features.js b/test/functional/makehtml/testsuite.features.js index 2ef6c38..5e8b18a 100644 --- a/test/functional/makehtml/testsuite.features.js +++ b/test/functional/makehtml/testsuite.features.js @@ -1,7 +1,7 @@ /** * Created by Estevao on 08-06-2015. */ -var bootstrap = require('./makehtml.bootstrap.js'), +const bootstrap = require('./makehtml.bootstrap.js'), showdown = bootstrap.showdown, assertion = bootstrap.assertion, testsuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/'), @@ -20,6 +20,7 @@ var bootstrap = require('./makehtml.bootstrap.js'), metadataSuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/metadata/'), splitAdjacentBlockquotesSuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/splitAdjacentBlockquotes/'), moreStyling = bootstrap.getTestSuite('test/functional/makehtml/cases/features/moreStyling/'), + customizedHeaderId = bootstrap.getTestSuite('test/functional/makehtml/cases/features/customizedHeaderId/'), http = require('http'), https = require('https'), expect = require('chai').expect; @@ -28,8 +29,8 @@ describe('makeHtml() features testsuite', function () { 'use strict'; describe('issues', function () { - for (var i = 0; i < testsuite.length; ++i) { - var converter; + for (let i = 0; i < testsuite.length; ++i) { + let converter; if (testsuite[i].name === '#143.support-image-dimensions') { converter = new showdown.Converter({parseImgDimensions: true}); } else if (testsuite[i].name === '#69.header-level-start') { @@ -113,9 +114,9 @@ describe('makeHtml() features testsuite', function () { /** test Table Syntax Support **/ describe('table support', function () { - var converter, + let converter, suite = tableSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { if (suite[i].name === 'basic-with-header-ids') { converter = new showdown.Converter({tables: true, tablesHeaderId: true}); } else if (suite[i].name === '#179.parse-md-in-table-ths') { @@ -129,9 +130,9 @@ describe('makeHtml() features testsuite', function () { /** test simplifiedAutoLink Support **/ describe('simplifiedAutoLink support in', function () { - var converter, + let converter, suite = simplifiedAutoLinkSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { if (suite[i].name === 'emphasis-and-strikethrough') { converter = new showdown.Converter({simplifiedAutoLink: true, strikethrough: true}); } else if (suite[i].name === 'disallow-underscores') { @@ -147,9 +148,9 @@ describe('makeHtml() features testsuite', function () { /** test openLinksInNewWindow support **/ describe('openLinksInNewWindow support in', function () { - var converter, + let converter, suite = openLinksInNewWindowSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { if (suite[i].name === 'simplifiedAutoLink') { converter = new showdown.Converter({openLinksInNewWindow: true, simplifiedAutoLink: true}); } else { @@ -161,9 +162,9 @@ describe('makeHtml() features testsuite', function () { /** test disableForced4SpacesIndentedSublists support **/ describe('disableForced4SpacesIndentedSublists support in', function () { - var converter, + let converter, suite = disableForced4SpacesIndentedSublistsSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({disableForced4SpacesIndentedSublists: true}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); } @@ -171,9 +172,9 @@ describe('makeHtml() features testsuite', function () { /** test rawHeaderId support **/ describe('rawHeaderId support', function () { - var converter, + let converter, suite = rawHeaderIdSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { if (suite[i].name === 'with-prefixHeaderId') { converter = new showdown.Converter({rawHeaderId: true, prefixHeaderId: '/prefix/'}); } else { @@ -185,9 +186,9 @@ describe('makeHtml() features testsuite', function () { /** test rawPrefixHeaderId support **/ describe('rawPrefixHeaderId support', function () { - var converter, + let converter, suite = rawPrefixHeaderIdSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({rawPrefixHeaderId: true, prefixHeaderId: '/prefix/'}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); } @@ -195,7 +196,7 @@ describe('makeHtml() features testsuite', function () { /** test emojis support **/ describe('emojis support', function () { - var converter, + let converter, suite = emojisSuite, imgSrcRegexp = /]+src=("https?:\/\/[^"]+"|'https?:\/\/[^']+')/g; @@ -221,7 +222,7 @@ describe('makeHtml() features testsuite', function () { }; } - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { if (suite[i].name === 'simplifiedautolinks') { converter = new showdown.Converter({emoji: true, simplifiedAutoLink: true}); } else { @@ -230,7 +231,7 @@ describe('makeHtml() features testsuite', function () { it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); - var imgUrl = imgSrcRegexp.exec(suite[i].expected); + let imgUrl = imgSrcRegexp.exec(suite[i].expected); if (imgUrl) { it('should use a working emoji URL', testImageUrlExists(imgUrl[1])); } @@ -239,9 +240,9 @@ describe('makeHtml() features testsuite', function () { /** test underline support **/ describe('underline support', function () { - var converter, + let converter, suite = underlineSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { if (suite[i].name === 'simplifiedautolinks') { converter = new showdown.Converter({underline: true, simplifiedAutoLink: true}); } else { @@ -253,9 +254,9 @@ describe('makeHtml() features testsuite', function () { /** test ellipsis option **/ describe('ellipsis option', function () { - var converter, + let converter, suite = ellipsisSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({ellipsis: false}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); } @@ -263,9 +264,9 @@ describe('makeHtml() features testsuite', function () { /** test literalMidWordUnderscores option **/ describe('literalMidWordUnderscores option', function () { - var converter, + let converter, suite = literalMidWordUnderscoresSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({literalMidWordUnderscores: true}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); } @@ -274,9 +275,9 @@ describe('makeHtml() features testsuite', function () { /** test literalMidWordAsterisks option **/ /* describe('literalMidWordAsterisks option', function () { - var converter, + let converter, suite = literalMidWordAsterisksSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({literalMidWordAsterisks: true}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); } @@ -285,9 +286,9 @@ describe('makeHtml() features testsuite', function () { /** test completeHTMLDocument option **/ describe('completeHTMLDocument option', function () { - var converter, + let converter, suite = completeHTMLOutputSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({completeHTMLDocument: true}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); @@ -296,10 +297,10 @@ describe('makeHtml() features testsuite', function () { /** test metadata option **/ describe('metadata option', function () { - var converter, + let converter, suite = metadataSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { if (suite[i].name === 'embeded-in-output' || suite[i].name === 'embeded-two-consecutive-metadata-blocks' || suite[i].name === 'embeded-two-consecutive-metadata-blocks-different-symbols') { @@ -315,10 +316,10 @@ describe('makeHtml() features testsuite', function () { /** test metadata option **/ describe('splitAdjacentBlockquotes option', function () { - var converter, + let converter, suite = splitAdjacentBlockquotesSuite; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({splitAdjacentBlockquotes: true}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); } @@ -326,13 +327,23 @@ describe('makeHtml() features testsuite', function () { /** test moreStyling option **/ describe('moreStyling option', function () { - var converter, + let converter, suite = moreStyling; - for (var i = 0; i < suite.length; ++i) { + for (let i = 0; i < suite.length; ++i) { converter = new showdown.Converter({moreStyling: true, tasklists: true}); it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); } }); + describe('customizedHeaderId option', function () { + let converter, + suite = customizedHeaderId; + + for (let i = 0; i < suite.length; ++i) { + converter = new showdown.Converter({customizedHeaderId: true}); + it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter)); + } + }); + }); diff --git a/test/mocks/md-to-trigger-all-events.md b/test/mocks/md-to-trigger-all-events.md new file mode 100644 index 0000000..3bb1178 --- /dev/null +++ b/test/mocks/md-to-trigger-all-events.md @@ -0,0 +1,82 @@ +# ATX h1 + +## ATX h2 + +### ATX h3 + +#### ATX h4 + +##### ATX h5 + +###### ATX h6 + +setext h1 +---------- + +setext h2 +========== + +some paragraph + +*italic* + +**bold** + +***bold and italic*** + +__underline__ + +___superunderline___ + +~~strikethrough~~ + +[link](foo.com) + +|[img](foo.com/img.jpg) + +some `code line` + +--- + +some http://autolink.com autolink + +> blockquote + +other paragraph + + code + block + +```javascript +gh codeblock +``` + +@mentions + +- ul 1 +- ul 2 +- ul 3 + +other paragraph + +1. ol 1 +2. ol 2 +3. ol 3 + +foo + +- [ ] task item 1 +- [X] task item 2 + +| foo | bar | +|-----|-----| +| 1 | 2 | + +paragraph + +| foo | bar | +|-----|-----| + +
a div
+ + diff --git a/test/optionswp.js b/test/optionswp.js index dd20264..3c0d392 100644 --- a/test/optionswp.js +++ b/test/optionswp.js @@ -1,5 +1,5 @@ /* jshint ignore:start */ -var fs = require('fs'), +let fs = require('fs'), filedata; filedata = fs.readFileSync('src/options.js', 'utf8'); eval(filedata); diff --git a/test/unit/showdown.Converter.js b/test/unit/showdown.Converter.js index 7ff6b8d..9b138e4 100644 --- a/test/unit/showdown.Converter.js +++ b/test/unit/showdown.Converter.js @@ -1,7 +1,6 @@ /** * Created by Estevao on 31-05-2015. */ -//let showdown = require('../../.build/showdown.js') || require('showdown'); chai.should(); @@ -159,8 +158,8 @@ describe('showdown.Converter', function () { it('should listen to ' + name, function () { let converter = new showdown.Converter(); converter.listen(name, function (event) { - let evtName = event.getName(); - let text = event.getCapturedText(); + let evtName = event.name; + let text = event.input; evtName.should.equal(name.toLowerCase()); text.should.match(/^[\s\S]*foo[\s\S]*$/); return text; diff --git a/test/unit/showdown.events.js b/test/unit/showdown.events.js new file mode 100644 index 0000000..a8a7446 --- /dev/null +++ b/test/unit/showdown.events.js @@ -0,0 +1,289 @@ +/** + * Created by Tivie on 04/03/2022. + */ + +// in node, if bootstrap is pre-loaded, there's a mock of XMLHttpRequest which +// internally just calls fs.readFileSync + +describe('showdown.Event', function () { + 'use strict'; + //const subparserList = showdown.getSubParserList(); + + const testSpec = { + makehtml: { + doesNotExist: [ + { event: 'onStart', text: 'foo', result: false }, + { event: 'onEnd', text: 'foo', result: false }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: 'foo', result: false } + ], + blockquote: [ + { event: 'onStart', text: '> foo', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '> foo', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '> foo', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '> foo', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + codeBlock: [ + { event: 'onStart', text: ' foo\n bar', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: ' foo\n bar', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: ' foo\n bar', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: ' foo\n bar', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + codeSpan: [ + { event: 'onStart', text: '`foo`', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '`foo`', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '`foo`', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '`foo`', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + emoji: [ + { event: 'onStart', text: ':smile:', result: true }, + { event: 'onStart', text: 'smile', result: true }, + { event: 'onEnd', text: ':smile:', result: true }, + { event: 'onEnd', text: 'smile', result: true }, + { event: 'onCapture', text: ':smile:', result: true }, + { event: 'onCapture', text: ':blablablablabla:', result: false }, // this emoji does not exist + { event: 'onCapture', text: 'smile', result: false }, + { event: 'onHash', text: ':smile:', result: true }, + { event: 'onHash', text: ':blablablablabla:', result: false }, // this emoji does not exist + { event: 'onHash', text: 'smile', result: false } + ], + emphasisAndStrong: [ + { event: 'onStart', text: '*foo*', result: true }, + { event: 'onStart', text: '**foo**', result: true }, + { event: 'onStart', text: '***foo***', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '*foo*', result: true }, + { event: 'onEnd', text: '**foo**', result: true }, + { event: 'onEnd', text: '***foo***', result: true }, + { event: 'onEnd', text: 'foo', result: true } + ], + 'emphasisAndStrong.emphasis': [ + { event: 'onCapture', text: '*foo*', result: true }, + { event: 'onCapture', text: '**foo**', result: false }, + { event: 'onCapture', text: '***foo***', result: false }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '*foo*', result: true }, + { event: 'onHash', text: '**foo**', result: false }, + { event: 'onHash', text: '***foo***', result: false }, + { event: 'onHash', text: 'foo', result: false } + ], + 'emphasisAndStrong.strong': [ + { event: 'onCapture', text: '*foo*', result: false }, + { event: 'onCapture', text: '**foo**', result: true }, + { event: 'onCapture', text: '***foo***', result: false }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '*foo*', result: false }, + { event: 'onHash', text: '**foo**', result: true }, + { event: 'onHash', text: '***foo***', result: false }, + { event: 'onHash', text: 'foo', result: false } + ], + 'emphasisAndStrong.emphasisAndStrong': [ + { event: 'onCapture', text: '*foo*', result: false }, + { event: 'onCapture', text: '**foo**', result: false }, + { event: 'onCapture', text: '***foo***', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '*foo*', result: false }, + { event: 'onHash', text: '**foo**', result: false }, + { event: 'onHash', text: '***foo***', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + githubCodeBlock: [ + { event: 'onStart', text: '```\nfoo\n```', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '```\nfoo\n```', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '```\nfoo\n```', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '```\nfoo\n```', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + heading: [ + { event: 'onStart', text: '# foo', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '# foo', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '# foo', result: true }, + { event: 'onCapture', text: 'foo\n---', result: true }, + { event: 'onCapture', text: 'foo\n===', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '# foo', result: true }, + { event: 'onHash', text: 'foo\n---', result: true }, + { event: 'onHash', text: 'foo\n===', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + horizontalRule: [ + { event: 'onStart', text: '---', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '---', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '---', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '---', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + image: [ + { event: 'onStart', text: '![foo](bar.jpg)', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '![foo](bar.jpg)', result: true }, + { event: 'onEnd', text: 'foo', result: true } + ], + 'image.inline': [ + { event: 'onCapture', text: '![foo](bar.jpg)', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '![foo](bar.jpg)', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + 'image.reference': [ + { event: 'onCapture', text: '![foo][1]\n\n[1]: bar.jpg', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '![foo][1]\n\n[1]: bar.jpg', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + link: [ + { event: 'onStart', text: '[foo](bar.jpg)', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '[foo](bar.jpg)', result: true }, + { event: 'onEnd', text: 'foo', result: true } + ], + 'link.inline': [ + { event: 'onCapture', text: '[foo](bar.jpg)', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '[foo](bar.jpg)', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + 'link.reference': [ + { event: 'onCapture', text: '[foo][1]\n\n[1]: bar.jpg', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '[foo][1]\n\n[1]: bar.jpg', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + list: [ + { event: 'onStart', text: '1. foo\n2.bar\n', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '1. foo\n2.bar\n', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '1. foo\n2.bar\n', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + //{ event: 'onHash', text: '1. foo\n2.bar\n', result: true }, + //{ event: 'onHash', text: 'foo', result: false } + ], + 'list.listItem': [ + { event: 'onCapture', text: '1. foo\n2.bar\n', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '1. foo\n2.bar\n', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + 'list.taskListItem': [ + { event: 'onCapture', text: '1. [X] foo\n2. [x] bar\n', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '1. [X] foo\n2. [x] bar\n', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + 'list.taskListItem.checkbox': [ + { event: 'onCapture', text: '1. [X] foo\n2. [x] bar\n', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '1. [X] foo\n2. [x] bar\n', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + metadata: [ + { event: 'onStart', text: '«««yaml\nfoo: bar\n»»»\n', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '«««yaml\nfoo: bar\n»»»\n', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '«««yaml\nfoo: bar\n»»»\n', result: true }, + { event: 'onCapture', text: '---yaml\nfoo: bar\n---\n', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '«««yaml\nfoo: bar\n»»»\n', result: true }, + { event: 'onHash', text: '---yaml\nfoo: bar\n---\n', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + strikethrough: [ + { event: 'onStart', text: '~~foo~~', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '~~foo~~', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '~~foo~~', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '~~foo~~', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + table: [ + { event: 'onStart', text: '|foo|bar|\n|---|---|\n|1|2|', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '|foo|bar|\n|---|---|\n|1|2|', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '|foo|bar|\n|---|---|\n|1|2|', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '|foo|bar|\n|---|---|\n|1|2|', result: true }, + { event: 'onHash', text: 'foo', result: false } + ], + underline: [ + { event: 'onStart', text: '__foo__', result: true }, + { event: 'onStart', text: 'foo', result: true }, + { event: 'onEnd', text: '__foo__', result: true }, + { event: 'onEnd', text: 'foo', result: true }, + { event: 'onCapture', text: '__foo__', result: true }, + { event: 'onCapture', text: 'foo', result: false }, + { event: 'onHash', text: '__foo__', result: true }, + { event: 'onHash', text: 'foo', result: false } + ] + } + }; + + describe('event triggering', function () { + + let converter; + + before(function () { + converter = new showdown.Converter({ + strikethrough: true, + tables: true, + ghCodeBlocks: true, + tasklists: true, + ghMentions: true, + emoji: true, + underline: true, + ellipsis: true, + metadata: true + }); + }); + + describe('makehtml', function () { + /* jshint -W083*/ + for (let parser in testSpec.makehtml) { + + describe(parser, function () { + for (let ts in testSpec.makehtml[parser]) { + let event = 'makehtml.' + parser + '.' + testSpec.makehtml[parser][ts].event; + let md = testSpec.makehtml[parser][ts].text; + let title = (testSpec.makehtml[parser][ts].result) ? 'should ' : 'should NOT '; + title += 'trigger "' + event + ' event"'; + let expected = testSpec.makehtml[parser][ts].result; + let actual = false; + + it(title, function () { + converter.listen(event, function () { + actual = true; + }); + converter.makeHtml(md); + expected.should.equal(actual); + }); + } + }); + } + /* jshint +W083*/ + }); + }); +}); diff --git a/test/unit/showdown.js b/test/unit/showdown.js index d96e9fc..97645a6 100644 --- a/test/unit/showdown.js +++ b/test/unit/showdown.js @@ -1,7 +1,6 @@ /** * Created by Tivie on 27/01/2017. */ -//let showdown = require('../../.build/showdown.js') || require('showdown'); describe('showdown.options', function () { 'use strict';