Bläddra i källkod

feat(customizeHeaderId): add option for customizing header ids

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
Marinin Tim 8 år sedan
förälder
incheckning
94c570a9d8

+ 6 - 0
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**
  * **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)
  * **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.
  * **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.

+ 16 - 2
dist/showdown.js

@@ -1,4 +1,4 @@
-;/*! showdown 30-05-2017 */
+;/*! showdown 01-06-2017 */
 (function(){
 (function(){
 /**
 /**
  * Created by Tivie on 13-07-2015.
  * Created by Tivie on 13-07-2015.
@@ -2101,7 +2101,12 @@ showdown.subParser('headers', function (text, options, globals) {
   var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
   var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
 
 
   text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
   text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
-    var span = showdown.subParser('spanGamut')(m2, options, globals),
+    var hText = m2;
+    if (options.customizedHeaderId) {
+      hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
+    }
+
+    var span = showdown.subParser('spanGamut')(hText, options, globals),
         hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
         hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
         hLevel = headerLevelStart - 1 + m1.length,
         hLevel = headerLevelStart - 1 + m1.length,
         header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
         header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
@@ -2111,6 +2116,15 @@ showdown.subParser('headers', function (text, options, globals) {
 
 
   function headerId (m) {
   function headerId (m) {
     var title;
     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.
     // Prefix id to prevent causing inadvertent pre-existing style matches.
     if (showdown.helper.isString(options.prefixHeaderId)) {
     if (showdown.helper.isString(options.prefixHeaderId)) {
       title = options.prefixHeaderId + m;
       title = options.prefixHeaderId + m;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
dist/showdown.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/showdown.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
dist/showdown.min.js.map


+ 15 - 1
src/subParsers/headers.js

@@ -43,7 +43,12 @@ showdown.subParser('headers', function (text, options, globals) {
   var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
   var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
 
 
   text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
   text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
-    var span = showdown.subParser('spanGamut')(m2, options, globals),
+    var hText = m2;
+    if (options.customizedHeaderId) {
+      hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
+    }
+
+    var span = showdown.subParser('spanGamut')(hText, options, globals),
         hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
         hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
         hLevel = headerLevelStart - 1 + m1.length,
         hLevel = headerLevelStart - 1 + m1.length,
         header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
         header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
@@ -53,6 +58,15 @@ showdown.subParser('headers', function (text, options, globals) {
 
 
   function headerId (m) {
   function headerId (m) {
     var title;
     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.
     // Prefix id to prevent causing inadvertent pre-existing style matches.
     if (showdown.helper.isString(options.prefixHeaderId)) {
     if (showdown.helper.isString(options.prefixHeaderId)) {
       title = options.prefixHeaderId + m;
       title = options.prefixHeaderId + m;

+ 4 - 0
test/features/customizedHeaderId-simple.html

@@ -0,0 +1,4 @@
+<h1 id="simple">Просто заголовок</h1>
+<h1 id="headerwithoutcurlybraces">Header without curly braces</h1>
+<h1 id="cool">Headers with multiple braces {braces} {are}</h1>
+<h1 id="withoutspace">Header</h1>

+ 4 - 0
test/features/customizedHeaderId-simple.md

@@ -0,0 +1,4 @@
+# Просто заголовок {simple}
+# Header without curly braces
+# Headers with multiple braces {braces} {are} {cool}
+# Header{withoutspace}

+ 2 - 0
test/node/testsuite.features.js

@@ -76,6 +76,8 @@ describe('makeHtml() features testsuite', function () {
         converter = new showdown.Converter({prefixHeaderId: 'my prefix ', ghCompatibleHeaderId: true});
         converter = new showdown.Converter({prefixHeaderId: 'my prefix ', ghCompatibleHeaderId: true});
       } else if (testsuite[i].name === 'simplifiedAutoLink') {
       } else if (testsuite[i].name === 'simplifiedAutoLink') {
         converter = new showdown.Converter({simplifiedAutoLink: true, strikethrough: true});
         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') {
       } else if (testsuite[i].name === '#378.simplifiedAutoLinks-with-excludeTrailingPunctuationFromURLs') {
         converter = new showdown.Converter({simplifiedAutoLink: true, excludeTrailingPunctuationFromURLs: true});
         converter = new showdown.Converter({simplifiedAutoLink: true, excludeTrailingPunctuationFromURLs: true});
       } else if (testsuite[i].name === '#379.openLinksInNewWindow-breaks-em-markdup') {
       } else if (testsuite[i].name === '#379.openLinksInNewWindow-breaks-em-markdup') {

Vissa filer visades inte eftersom för många filer har ändrats