From 94c570a9d816ce8bff57e49a37dae3c1e44638db Mon Sep 17 00:00:00 2001 From: Marinin Tim Date: Thu, 1 Jun 2017 04:35:42 +0300 Subject: [PATCH] feat(customizeHeaderId): add option for customizing header ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s useful for non-Latin texts, where header might be, for example, in Russian, but user wants id to be in English. This feature allows user to set id for header manually, using curly braces: ## Привет, мир {hello-world} Closes #383 --- README.md | 6 ++++++ dist/showdown.js | Bin 89044 -> 89399 bytes dist/showdown.js.map | Bin 258017 -> 259033 bytes dist/showdown.min.js | Bin 37565 -> 37710 bytes dist/showdown.min.js.map | Bin 40017 -> 40207 bytes src/subParsers/headers.js | 16 +++++++++++++++- test/features/customizedHeaderId-simple.html | 4 ++++ test/features/customizedHeaderId-simple.md | 4 ++++ test/node/testsuite.features.js | 2 ++ 9 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test/features/customizedHeaderId-simple.html create mode 100644 test/features/customizedHeaderId-simple.md diff --git a/README.md b/README.md index b6db683..196d78c 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,12 @@ var defaultOptions = showdown.getDefaultOptions(); * **noHeaderId**: (boolean) [default false] Disable the automatic generation of header ids. Setting to true overrides **prefixHeaderId** + * **customizedHeaderId**: (boolean) [default false] Use text in curly braces as header id. + Example: + ``` + ## Sample header {real-id} will use real-id as id + ``` + * **ghCompatibleHeaderId**: (boolean) [default false] Generate header ids compatible with github style (spaces are replaced with dashes and a bunch of non alphanumeric chars are removed) (since v1.5.5) * **prefixHeaderId**: (string/boolean) [default false] Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to `true` will add a generic 'section' prefix. diff --git a/dist/showdown.js b/dist/showdown.js index 089ca1c52c69ef342f83b039161d0d32f1ac225e..56eeec6173996ff117d744c84b04103837ba9db2 100644 GIT binary patch delta 403 zcmb7A%}T>S7(}6$Tnl;QrqY*~4?2p|?$}Q3d^9`NvLdcQ z2!XVD!1Lf+&}+Q}n;_Ur2tC3DH6g1lyMsHoXaL>K>{Lkt_wPvM*zGRj3`wXnXE5>3C2E}HqnNxdV|iFQo>r7}Y{*B6 zjVa0)#R|LyuRRi}wC{6QN5dq2Vd7e|fRTwXJCENsqUfMRt^NEcbFod0;_S^RmXkuI zcbmOF!i&T7eu}lA^H|2-XFgXGmuc?14_6Y{AW0i6yt2B(DyutuU~?%up%*+D1oPa0 zYJtCudFZws&#Gnhny1IG})6PK?F0SmX_!2yZ~mrxo3 z1eeoV0U48UiWHMDq6(An8VZN6$pN>o$pV|Xm&bzxCjxCUmvIUM6PLcQ0}Gcfe*-tS ONQ46j0k=km1CwnCC_MuJ diff --git a/dist/showdown.min.js b/dist/showdown.min.js index cf90cd82b9080f6f783219d9a0cfd4362de501a7..d26f5b615b5ae15014e5b40b6580611659a68e66 100644 GIT binary patch delta 261 zcmdnHlhr3rlvK>-mJ+N8Wb6`C(C6h zspr_H=^ARM>*b{8rI%#r2tjY9s(o7X1KVVPW%CdrYZlcbZZsgpH% zeTI^Hwr!fOp?11nPHJ9yNrq02t&&ZKl6JOsmbQ|el6I!Hl8ruyKlx&sDr3$hPsPpl anYtoOnYEK0T@@zx*Dhh?+H71WEeZg^C?{3` diff --git a/dist/showdown.min.js.map b/dist/showdown.min.js.map index ab04d8686db73c2ae09eeea2431a261c8288aaa2..b9b2e2b805359a938ac4bc4e9c000b67b7fc7c1a 100644 GIT binary patch delta 4796 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' + span + ''; @@ -53,6 +58,15 @@ showdown.subParser('headers', function (text, options, globals) { function headerId (m) { var title; + + // 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]; + } + } + // Prefix id to prevent causing inadvertent pre-existing style matches. if (showdown.helper.isString(options.prefixHeaderId)) { title = options.prefixHeaderId + m; diff --git a/test/features/customizedHeaderId-simple.html b/test/features/customizedHeaderId-simple.html new file mode 100644 index 0000000..5e05d66 --- /dev/null +++ b/test/features/customizedHeaderId-simple.html @@ -0,0 +1,4 @@ +

Просто заголовок

+

Header without curly braces

+

Headers with multiple braces {braces} {are}

+

Header

diff --git a/test/features/customizedHeaderId-simple.md b/test/features/customizedHeaderId-simple.md new file mode 100644 index 0000000..66e531b --- /dev/null +++ b/test/features/customizedHeaderId-simple.md @@ -0,0 +1,4 @@ +# Просто заголовок {simple} +# Header without curly braces +# Headers with multiple braces {braces} {are} {cool} +# Header{withoutspace} diff --git a/test/node/testsuite.features.js b/test/node/testsuite.features.js index 36fbb6c..25907eb 100644 --- a/test/node/testsuite.features.js +++ b/test/node/testsuite.features.js @@ -76,6 +76,8 @@ describe('makeHtml() features testsuite', function () { converter = new showdown.Converter({prefixHeaderId: 'my prefix ', ghCompatibleHeaderId: true}); } else if (testsuite[i].name === 'simplifiedAutoLink') { converter = new showdown.Converter({simplifiedAutoLink: true, strikethrough: true}); + } else if (testsuite[i].name === 'customizedHeaderId-simple') { + converter = new showdown.Converter({customizedHeaderId: true}); } else if (testsuite[i].name === '#378.simplifiedAutoLinks-with-excludeTrailingPunctuationFromURLs') { converter = new showdown.Converter({simplifiedAutoLink: true, excludeTrailingPunctuationFromURLs: true}); } else if (testsuite[i].name === '#379.openLinksInNewWindow-breaks-em-markdup') {