From 5d1987759078e3eb4d89031ac452550e9af6ecd6 Mon Sep 17 00:00:00 2001 From: Estevao Soares dos Santos Date: Sat, 17 Dec 2016 06:01:15 +0000 Subject: [PATCH] feat(requireSpaceBeforeHeadingText): option to make space between `#` and header text mandatory Credit: @nikz [Nik Wakelin](https://github.com/nikz) Closes #277 --- README.md | 2 ++ dist/showdown.js | Bin 72395 -> 72745 bytes dist/showdown.js.map | Bin 213487 -> 214375 bytes dist/showdown.min.js | Bin 29334 -> 29595 bytes dist/showdown.min.js.map | Bin 32594 -> 32736 bytes src/options.js | 5 +++++ src/showdown.js | 3 ++- src/subParsers/headers.js | 4 +++- .../requireSpaceBeforeHeadingText.html | 2 ++ .../features/requireSpaceBeforeHeadingText.md | 3 +++ test/node/testsuite.features.js | 2 ++ 11 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 test/features/requireSpaceBeforeHeadingText.html create mode 100644 test/features/requireSpaceBeforeHeadingText.md diff --git a/README.md b/README.md index d7730c3..edb19e5 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,8 @@ var defaultOptions = showdown.getDefaultOptions(); wrapped in two

``` + * **requireSpaceBeforeHeadingText**: (boolean) [default false] Makes adding a space between `#` and the header text mandatory (since v1.5.3) + ## Flavors You can also use flavors or presets to set the correct options automatically, so that showdown behaves like popular markdown flavors. diff --git a/dist/showdown.js b/dist/showdown.js index 61b604df1beb05c45eba8003c3464aa8f6c42ae6..2c6fbe172be3a46a154e2931945b168f34e55076 100644 GIT binary patch delta 277 zcmX@Tm1X4)mJJ46lOJ%f$rhy+mSz^E1{WkIr#hvkAckf5BPkeHXEP?C|VkO9=3TBJ|{)U1#T z6ih71FRI+k##O>HnU9xC4zF!ioAdbgY>h8VEK*1;sR%Bq%t=+SRnW*UD9OyvE7rrS zS5v`WK|fAIx!O?2tX4BxA*Li&TSHIV9>Ua8){4o~)=$q>uu_<8cSLz|`TruF Ik7R`b0N9vgF#rGn delta 36 ucmV+<0NekmxCG0!1h6m)v+fE?1hZ@pu(gv^f);tX*%dLwk2%$&A8Wg#$h?p(U=GT-qe~zck5hG)F z(N*uo2O~%*=rX~JbE8lYbi0edx(Ta`6$@rW7eQdhRnXNg9(Z{lp1<9V;qCjw^_~cq zc!3MXBq<0ZCJ`6o@NK{gOI8Q#{6Hd9tvu9Jp4FZp9=5*!L2^NWWR!#68y>2!IM#CM zWb_~h&3k5)Wu@n66i8|i>WUGPg1ONXe<4HY+*y!j?K+`55*{pqju797+J+3!K0IRC zD-rX@B`NNolBB6d!u}{^s9Z_(Wvq4p>n(mFo>g7QxM7>tY}2Uagx7Z+Q1l5vKOABf z13m@SqyT9Xr#BbagQh+qc~yX}hl8zm`kepB3lGsC>ok!OE0gfDdki{XL{@*QPkG_v zSj~(DmR>;6U1(~PnDy4ancBYA(&k!|BNme(Y z3Q=iACCmC#Rtw6SHg_Cv8riNJ4>|VBRKwa=4{o>SS7e3AYGp=UTcYF)aToS_lmq*U zJtRWL=G@LZr~Sco&n!u$)ayQXz!&*@d!61?D(@RxTqa?{+S~X9`}hfun*Rl{Zp2{M KY@hMlYrg@RjoJbL delta 248 zcmVMfS&;bgJ4s)U{e9T zBbWCq0V9_nU;z}Dpn3rmlMpBrmUsaemvG<#29r=i3X@{Etjwv0tf;zMw9M6 zB$r^S0Th>D3;_z4uy6q@w-b2*ng#(emx12_9FuTy3YSn}0ScF3Q2`2*PvZ)gP}Tto ylb~G%lN~J&w-A5F-qvM_MG9HANqTslX0IQop3A3;f4nC7oKohgdPg4PtY)}o8Xi+1xpi%oFZ{ZOC diff --git a/dist/showdown.min.js.map b/dist/showdown.min.js.map index 2c7f5c4e50d13433ebcaf856bc35a1feb126bf5f..2a81f092f8392cbc485571955e219a1d4c2c7dad 100644 GIT binary patch delta 4568 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 delta 4437 zcma)AU2Ggz71ksQSsRo#e~O*NZvIP~NxZw>&3Z*rdhgxY+3{p{JlSm4n`T(d@te~g}B6#2d@lf@tAc3fOE|quyiST#Mxwd7esl?0f z&N=6v-|w7zX8-(O?Subl@9f+$IJx8dzQKpX@9mPmeEyK#;=03_E%4Kc={Ec}^fY7X zF4s+FEDPOY%<6IAh-qR2nOOpVx&f3C*O+cFwiuMh_KqG05GXF!HVzIzyw z+Z8ROuvBzY){XM2d@}O>o{i%cbBm%Xe?R(T(EG;Waji1=!C~LNeML;2F^|cyA-f_G zln>935B{RRr751+${Rd9|K85M#h9MsEEJ2wfqIM;;&R*`k@tdMAL=Lc28T*c4W65P zG(23i^r~R2Aqs<^UaD#@lr6o+nQ^5Rhy28hAf?Fzsfqy0jX~_o(cMDsi-Xmf%UKg!K@1;ZQj8OEsKhS4yOp>)ATcjpAHt$vGAvh;du$Ua`U9GU?atg z%7-^s{S~sb*uIRkY=^#5T{`ZO4ZA}REr;HMD0jd9lQrdu z10ZvlsEeLbMB+#U;CesifATDOR^UmnV%7x!7gJAh z*b~%|-V})}Tm}iF3=#-pd3*lN;k=~>IWw=-;_@SF|6tF;DQ(S9#VKv3%49WO7GVX? zG+^GmQrMcSqN8#JV>SZ`02c}l7=j0j8MBB6D@rOIy^>%enKRMB0wh9ly8kdT7!36c6MccUt)6^;F?wKwJq7Hu9NRJN zmt#wZ)_?(0Zj}&Wmklrkh=(j>v4llYA^^HgY)h7cd5-sxUIjH(o}+>|5%MRM1w|qf zE6~%^2NnPUPm2Q*+H0R7kF(@yc~D>85Ldw1hzc6i#X9wQ3*(3x*vY~!Z+H4xKFDBh zB>c1?i`ju^8=_9Km>J+Lxt2Sx73JHx@iV13<|?kbM77=qoFJRne`bUi9oR1ha;K>*Ar{!W{fjwHj%?6gt-|!p8+3@yoo(;B%15alO_3a!LPODc=4-y`~)Z1>qJzVGH^fzOqI6O6kne&rskj z$D-3X737S)OFoGo8~m&k(EKGFGt672ac);_OoD?=vkV@k^s7dS2T6_KNrh;K?g zMCEMd`1%}AMdba;k}pSk;Ng?X=unTuQWHtJclp&X<_HyYYWU?{bic_<_zn3o;Ql5~ zCNF!-V_5(ay46im7s9m((o5?02q;<*A#E1bWQ}Ff?`tJgA<{*HmS@3KVA-=cc+4sNhn294MO4BD8Csp0NzXBKhaGy`Hz{?QxR?=hn;YSc_~1n*2;=Bg(z zmT>tLZ9(PApur`YX(@`6*##G@J9*q@r&-fRvu;hLsyz5jb)WY76xG3AK|y9Y5Vp7i zG`uguNxZU(JVbWsumv;#xvNMP`rqVXQn>x5pe(^kI*8QF9Yf6oUU0aLJ!rf&JdwbK zOI)j}C1|E;Y6rL7)6it#Otve3*z)%DFd);WsOP%!^X*s9EyE%PZQI~gsv=y&(0zT; zq|m(-r60BxAeLb^ciUq-BGx7Xf7Jd`riFV7%VO35Z&*THsMzA9+U0}O$XL=t;H7~( z9^72pSYfVTARf;8#wJg)&Q)Jn-3=Z2s51)7>ARh=u)0}OFe@Rf%?XZ6-^MnhiiY#s zSjG*5c|keU<&!HjpE`0u^`W|+VdMkwBDfK(Z%KZ6uj{RqXK)f+CuFO8yg{0#n=?2% z7BHJ4%xeThN9Ao9B`m;-jV~XHgJBx6I-MmwCe^{J62*Zdc#n}86JAT;wxWYBv@-1U zNl*oQIHcMtQ^pA>UWMA^@^S)QStM7YyhH-FN_9`(=#S4% z5VE%h)}z2OAhi(~EK#bT4T{E3F=YBP-~f!lb$NIMf!dsNH2Kiria~e2yQ3-XZcQHQz$rMaFs9AavpJ4f=qP36) zMMG>ro`Ju$0HMtjn*}I~DI&U)=qR%rG~S1@^g_bYVfo}MWAcsuL3!@(KDp=K=i+XZ zs#D)M2ai}CfSYlrLaMyHQq>_^^{`}spQzf!g<#6HS(njMLIuQ%t!YIXgU6Gg8MlN=7MKd!r zJZF3Oe*%MdQ<9^1@PJT*gwCY99@Z&M8`5k~zPa|&nLch(_SFV*nBDYHLx!QFOYm|* J1?4C1{tr<`0IvW5 diff --git a/src/options.js b/src/options.js index 6e075a1..f2c4fa6 100644 --- a/src/options.js +++ b/src/options.js @@ -90,6 +90,11 @@ function getDefaultOpts(simple) { defaultValue: false, description: 'Parses simple line breaks as
(GFM Style)', type: 'boolean' + }, + requireSpaceBeforeHeadingText: { + defaultValue: false, + description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)', + type: 'boolean' } }; if (simple === false) { diff --git a/src/showdown.js b/src/showdown.js index ed64ee8..46724c1 100644 --- a/src/showdown.js +++ b/src/showdown.js @@ -20,7 +20,8 @@ var showdown = {}, ghCodeBlocks: true, tasklists: true, disableForced4SpacesIndentedSublists: true, - simpleLineBreaks: true + simpleLineBreaks: true, + requireSpaceBeforeHeadingText: true }, vanilla: getDefaultOpts(true) }; diff --git a/src/subParsers/headers.js b/src/subParsers/headers.js index 5a79493..a6018f5 100644 --- a/src/subParsers/headers.js +++ b/src/subParsers/headers.js @@ -40,7 +40,9 @@ showdown.subParser('headers', function (text, options, globals) { // ... // ###### Header 6 // - text = text.replace(/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm, function (wholeMatch, m1, m2) { + 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 span = showdown.subParser('spanGamut')(m2, options, globals), hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"', hLevel = headerLevelStart - 1 + m1.length, diff --git a/test/features/requireSpaceBeforeHeadingText.html b/test/features/requireSpaceBeforeHeadingText.html new file mode 100644 index 0000000..2610924 --- /dev/null +++ b/test/features/requireSpaceBeforeHeadingText.html @@ -0,0 +1,2 @@ +

header

+

#header

diff --git a/test/features/requireSpaceBeforeHeadingText.md b/test/features/requireSpaceBeforeHeadingText.md new file mode 100644 index 0000000..c7eb76e --- /dev/null +++ b/test/features/requireSpaceBeforeHeadingText.md @@ -0,0 +1,3 @@ +# header + +#header diff --git a/test/node/testsuite.features.js b/test/node/testsuite.features.js index c1a13d6..699a73c 100644 --- a/test/node/testsuite.features.js +++ b/test/node/testsuite.features.js @@ -39,6 +39,8 @@ describe('makeHtml() features testsuite', function () { converter = new showdown.Converter({simpleLineBreaks: true}); } else if (testsuite[i].name === 'excludeTrailingPunctuationFromURLs-option') { converter = new showdown.Converter({simplifiedAutoLink: true, excludeTrailingPunctuationFromURLs: true}); + } else if (testsuite[i].name === 'requireSpaceBeforeHeadingText') { + converter = new showdown.Converter({requireSpaceBeforeHeadingText: true}); } else { converter = new showdown.Converter(); }