소스 검색

feat(simplifiedAutoLink): add support for GFM autolinks

Github Flavored Markdown detects urls and mails embeded in the text without any extra markup or delimiter.
This commit adds this feature to showdown through an option called "simplifiedAutoLink".
Related to #164
Estevão Soares dos Santos 10 년 전
부모
커밋
cff0237299

+ 51 - 9
Gruntfile.js

@@ -95,15 +95,42 @@ module.exports = function (grunt) {
           timeout: 3000,
           ignoreLeaks: false,
           reporter: 'spec'
-        },
-        issues: {
-          src: 'test/node/testsuite.issues.js',
-          options: {
-            globals: ['should'],
-            timeout: 3000,
-            ignoreLeaks: false,
-            reporter: 'spec'
-          }
+        }
+      },
+      issues: {
+        src: 'test/node/testsuite.issues.js',
+        options: {
+          globals: ['should'],
+          timeout: 3000,
+          ignoreLeaks: false,
+          reporter: 'spec'
+        }
+      },
+      standard: {
+        src: 'test/node/testsuite.standard.js',
+        options: {
+          globals: ['should'],
+          timeout: 3000,
+          ignoreLeaks: false,
+          reporter: 'spec'
+        }
+      },
+      features: {
+        src: 'test/node/testsuite.features.js',
+        options: {
+          globals: ['should'],
+          timeout: 3000,
+          ignoreLeaks: false,
+          reporter: 'spec'
+        }
+      },
+      single: {
+        src: 'test/node/**/*.js',
+        options: {
+          globals: ['should'],
+          timeout: 3000,
+          ignoreLeaks: false,
+          reporter: 'spec'
         }
       }
     }
@@ -113,6 +140,21 @@ module.exports = function (grunt) {
 
   require('load-grunt-tasks')(grunt);
 
+  grunt.registerTask('single-test', function (grep) {
+    'use strict';
+    grunt.config.merge({
+      simplemocha: {
+        single: {
+          options: {
+            grep: grep
+          }
+        }
+      }
+    });
+
+    grunt.task.run('simplemocha:node');
+  });
+
   grunt.registerTask('concatenate', ['concat:dist']);
   grunt.registerTask('lint', ['jshint', 'jscs']);
   grunt.registerTask('test', ['lint', 'concat:test', 'simplemocha:node', 'clean']);

+ 20 - 20
dist/showdown.js

@@ -1,4 +1,4 @@
-;/*! showdown 10-07-2015 */
+;/*! showdown 11-07-2015 */
 (function(){
 /**
  * Created by Tivie on 06-01-2015.
@@ -13,7 +13,8 @@ var showdown = {},
       prefixHeaderId:          false,
       noHeaderId:              false,
       headerLevelStart:        1,
-      parseImgDimensions:      false
+      parseImgDimensions:      false,
+      simplifiedAutoLink:      false
     },
     globalOptions = JSON.parse(JSON.stringify(defaultOptions)); //clone default options out of laziness =P
 
@@ -867,33 +868,32 @@ showdown.subParser('anchors', function (text, config, globals) {
 
 });
 
-showdown.subParser('autoLinks', function (text) {
+showdown.subParser('autoLinks', function (text, options) {
   'use strict';
 
-  text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, '<a href=\"$1\">$1</a>');
+  //simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
 
+  var simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi,
+      delimUrlRegex   = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,
+      simpleMailRegex = /\b(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)\b/gi,
+      delimMailRegex  = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
+
+  text = text.replace(delimUrlRegex, '<a href=\"$1\">$1</a>');
+  text = text.replace(delimMailRegex, replaceMail);
+  //simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
   // Email addresses: <address@domain.foo>
 
-  /*
-   text = text.replace(/
-   <
-   (?:mailto:)?
-   (
-   [-.\w]+
-   \@
-   [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
-   )
-   >
-   /gi);
-   */
-  var pattern = /<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
-  text = text.replace(pattern, function (wholeMatch, m1) {
+  if (options.simplifiedAutoLink) {
+    text = text.replace(simpleURLRegex, '<a href=\"$1\">$1</a>');
+    text = text.replace(simpleMailRegex, '<a href=\"$1\">$1</a>');
+  }
+
+  function replaceMail(wholeMatch, m1) {
     var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
     return showdown.subParser('encodeEmailAddress')(unescapedStr);
-  });
+  }
 
   return text;
-
 });
 
 /**

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/showdown.js.map


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/showdown.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
dist/showdown.min.js.map


+ 2 - 1
src/showdown.js

@@ -11,7 +11,8 @@ var showdown = {},
       prefixHeaderId:          false,
       noHeaderId:              false,
       headerLevelStart:        1,
-      parseImgDimensions:      false
+      parseImgDimensions:      false,
+      simplifiedAutoLink:      false
     },
     globalOptions = JSON.parse(JSON.stringify(defaultOptions)); //clone default options out of laziness =P
 

+ 17 - 18
src/subParsers/autoLinks.js

@@ -1,28 +1,27 @@
-showdown.subParser('autoLinks', function (text) {
+showdown.subParser('autoLinks', function (text, options) {
   'use strict';
 
-  text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, '<a href=\"$1\">$1</a>');
+  //simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
 
+  var simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi,
+      delimUrlRegex   = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,
+      simpleMailRegex = /\b(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)\b/gi,
+      delimMailRegex  = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
+
+  text = text.replace(delimUrlRegex, '<a href=\"$1\">$1</a>');
+  text = text.replace(delimMailRegex, replaceMail);
+  //simpleURLRegex  = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
   // Email addresses: <address@domain.foo>
 
-  /*
-   text = text.replace(/
-   <
-   (?:mailto:)?
-   (
-   [-.\w]+
-   \@
-   [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
-   )
-   >
-   /gi);
-   */
-  var pattern = /<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
-  text = text.replace(pattern, function (wholeMatch, m1) {
+  if (options.simplifiedAutoLink) {
+    text = text.replace(simpleURLRegex, '<a href=\"$1\">$1</a>');
+    text = text.replace(simpleMailRegex, '<a href=\"$1\">$1</a>');
+  }
+
+  function replaceMail(wholeMatch, m1) {
     var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
     return showdown.subParser('encodeEmailAddress')(unescapedStr);
-  });
+  }
 
   return text;
-
 });

+ 11 - 0
test/features/#164.1.simple_autolink.html

@@ -0,0 +1,11 @@
+<p>foo.bar</p>
+
+<p>www.foobar</p>
+
+<p><a href="www.foobar.com">www.foobar.com</a></p>
+
+<p><a href="http://foobar.com">http://foobar.com</a></p>
+
+<p><a href="https://www.foobar.com/baz?bazinga=nhecos;">https://www.foobar.com/baz?bazinga=nhecos;</a></p>
+
+<p><a href="http://www.google.com/">http://www.google.com</a></p>

+ 11 - 0
test/features/#164.1.simple_autolink.md

@@ -0,0 +1,11 @@
+foo.bar
+
+www.foobar
+
+www.foobar.com
+
+http://foobar.com
+
+https://www.foobar.com/baz?bazinga=nhecos;
+
+<a href="http://www.google.com/">http://www.google.com</a>

+ 2 - 1
test/node/showdown.js

@@ -22,7 +22,8 @@ describe('showdown.options', function () {
         prefixHeaderId:          false,
         noHeaderId:              false,
         headerLevelStart:        1,
-        parseImgDimensions:      false
+        parseImgDimensions:      false,
+        simplifiedAutoLink:      false
       };
       expect(showdown.getDefaultOptions()).to.be.eql(opts);
     });

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

@@ -14,6 +14,8 @@ describe('makeHtml() features testsuite', function () {
       converter = new showdown.Converter({parseImgDimensions: true});
     } else if (testsuite[i].name === '#69.header_level_start') {
       converter = new showdown.Converter({headerLevelStart: 3});
+    } else if (testsuite[i].name === '#164.1.simple_autolink') {
+      converter = new showdown.Converter({simplifiedAutoLink: true});
     } else {
       converter = new showdown.Converter();
     }

+ 13 - 0
test/single.test.wrapper.js

@@ -0,0 +1,13 @@
+/**
+ * Created by Estevao on 10-07-2015.
+ */
+/*
+var showdown = require('../dist/showdown.js'),
+  bootstrap = require('./bootstrap.js'),
+  assertion = bootstrap.assertion,
+  testsuite = bootstrap.getTestSuite('test/features/');
+
+describe('makeHtml() single test', function () {
+  'use strict';
+});
+*/

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.