diff --git a/test/badges.js b/test/badges.js
new file mode 100644
index 0000000..9183031
--- /dev/null
+++ b/test/badges.js
@@ -0,0 +1,23 @@
+/* globals before, describe, it */
+
+var assert = require('assert')
+var marky = require('..')
+var fixtures = require('./fixtures')
+
+describe('badges', function () {
+ var $
+
+ before(function () {
+ $ = marky(fixtures.badges)
+ })
+
+ it('adds a badge class to img tags containing badge images', function () {
+ assert($('img').length)
+ assert.equal($('img').length, $('img.badge').length)
+ })
+
+ it('adds a badge-only class to p tags containing nothing more than a badge', function () {
+ assert.equal($('p:not(.badge-only)').length, 2)
+ assert.equal($('p.badge-only').length, $('p').length - 2)
+ })
+})
diff --git a/test/cdn.js b/test/cdn.js
new file mode 100644
index 0000000..fbd78ac
--- /dev/null
+++ b/test/cdn.js
@@ -0,0 +1,73 @@
+/* globals before, describe, it */
+
+var assert = require('assert')
+var marky = require('..')
+var fixtures = require('./fixtures')
+
+describe('cdn', function () {
+ describe('when serveImagesWithCDN is true', function () {
+ var $
+ var options = {
+ package: {name: 'foo', version: '1.0.0'},
+ serveImagesWithCDN: true
+ }
+
+ before(function () {
+ $ = marky(fixtures.basic, options)
+ })
+
+ it('replaces relative img URLs with npm CDN URLs', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='https://cdn.npm.im/foo@1.0.0/relative.png']").length)
+ })
+
+ it('replaces slashy relative img URLs with npm CDN URLs', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='https://cdn.npm.im/foo@1.0.0/slashy/deep.png']").length)
+ })
+
+ it('leaves protocol relative URLs alone', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='//protocollie.com/woof.png']").length)
+ })
+
+ it('leaves HTTPS URLs alone', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='https://secure.com/good.png']").length)
+ })
+ })
+
+ describe('when serveImagesWithCDN is false (default)', function () {
+ var $
+ var options = {
+ package: {
+ name: 'foo',
+ version: '1.0.0'
+ }
+ }
+
+ before(function () {
+ $ = marky(fixtures.basic, options)
+ })
+
+ it('leaves relative img alone', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='relative.png']").length)
+ })
+
+ it('leaves slashy relative img URLs alone', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='/slashy/deep.png']").length)
+ })
+
+ it('leaves protocol relative URLs alone', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='//protocollie.com/woof.png']").length)
+ })
+
+ it('leaves HTTPS URLs alone', function () {
+ assert(~fixtures.basic.indexOf(''))
+ assert($("img[src='https://secure.com/good.png']").length)
+ })
+ })
+})
diff --git a/test/fixtures.js b/test/fixtures.js
index 6c7c674..86958f2 100644
--- a/test/fixtures.js
+++ b/test/fixtures.js
@@ -1,6 +1,7 @@
var fs = require('fs')
var path = require('path')
var glob = require('glob')
+var pkg = require('../package.json')
var fixtures = {
dependencies: [], // our dependencies and devDependencies
@@ -16,8 +17,8 @@ fs.readdirSync(__dirname + '/fixtures').forEach(function (file) {
})
// Read in dependencies' and devDependencies' readmes
-fixtures.dependencies = Object.keys(require('../package.json').devDependencies)
- .concat(Object.keys(require('../package.json').dependencies))
+fixtures.dependencies = Object.keys(pkg.devDependencies)
+ .concat(Object.keys(pkg.dependencies))
.sort()
fixtures.dependencies.forEach(function (name) {
var modulePath = path.resolve('node_modules', name)
diff --git a/test/github.js b/test/github.js
new file mode 100644
index 0000000..372cb06
--- /dev/null
+++ b/test/github.js
@@ -0,0 +1,6 @@
+/* globals describe */
+
+describe('github', function () {
+ require('./repo-github')
+ require('./repo-other')
+})
diff --git a/test/gravatar.js b/test/gravatar.js
new file mode 100644
index 0000000..6008c70
--- /dev/null
+++ b/test/gravatar.js
@@ -0,0 +1,29 @@
+/* globals before, describe, it */
+
+var assert = require('assert')
+var marky = require('..')
+var fixtures = require('./fixtures')
+
+describe('gravatar', function () {
+ var $
+
+ before(function () {
+ $ = marky(fixtures.gravatar)
+ })
+
+ it('replaces insecure gravatar img src URLs with secure HTTPS URLs', function () {
+ assert(~fixtures.gravatar.indexOf('http://gravatar.com/avatar/123?s=50&d=retro'))
+ assert.equal($('img').length, 3)
+ assert.equal($('img').eq(0).attr('src'), 'https://secure.gravatar.com/avatar/123?s=50&d=retro')
+ })
+
+ it('leaves secure gravatar URLs untouched', function () {
+ assert(~fixtures.gravatar.indexOf('https://secure.gravatar.com/avatar/456?s=50&d=retro'))
+ assert.equal($('img').eq(1).attr('src'), 'https://secure.gravatar.com/avatar/456?s=50&d=retro')
+ })
+
+ it('leaves non-gravtar URLs untouched', function () {
+ assert(~fixtures.gravatar.indexOf('http://not-gravatar.com/foo'))
+ assert.equal($('img').eq(2).attr('src'), 'http://not-gravatar.com/foo')
+ })
+})
diff --git a/test/headings.js b/test/headings.js
new file mode 100644
index 0000000..55ac429
--- /dev/null
+++ b/test/headings.js
@@ -0,0 +1,97 @@
+/* globals before, describe, it */
+
+var assert = require('assert')
+var marky = require('..')
+var fixtures = require('./fixtures')
+
+describe('headings', function () {
+ var $
+
+ before(function () {
+ $ = marky(fixtures.dirty)
+ })
+
+ it('injects hashy anchor tags into headings that have DOM ids', function () {
+ assert(~fixtures.dirty.indexOf('# h1'))
+ assert($("h1 a[href='#h1']").length)
+ })
+
+ it('adds deep-link class to modified headings', function () {
+ assert(~fixtures.dirty.indexOf('# h1'))
+ assert($("h1.deep-link a[href='#h1']").length)
+ })
+
+ it("doesn't inject anchor tags into headings that already contain anchors", function () {
+ assert(~fixtures.dirty.indexOf('### [h3](/already/linky)'))
+ assert($("h3 a[href='/already/linky']").length)
+ })
+
+ it('applies a prefix to generated DOM ids by default', function () {
+ assert(~fixtures.dirty.indexOf('## h2'))
+ assert.equal($('h2#user-content-h2').length, 1)
+ })
+
+ it('allows id prefixes to be disabled with prefixHeadingIds', function () {
+ assert(~fixtures.dirty.indexOf('#### This is a TEST'))
+ $ = marky(fixtures.dirty, {prefixHeadingIds: false})
+ assert.equal($('h4#this-is-a-test').length, 1)
+ })
+
+ it('allows a dash in generated DOM ids just like GitHub', function () {
+ assert(~fixtures.github.indexOf('### heading with a - dash'))
+ $ = marky(fixtures.github)
+ assert.equal($('h3#heading-with-a---dash a').length, 1)
+ })
+
+ it('allows a trailing dash in generated DOM ids just like GitHub', function () {
+ assert(~fixtures.github.indexOf('### heading with a trailing dash -'))
+ $ = marky(fixtures.github)
+ assert.equal($('h3#heading-with-a-trailing-dash-- a').length, 1)
+ })
+
+ it('allows underscores in generated DOM ids like GitHub', function () {
+ assert(~fixtures.github.indexOf('### heading with an _ underscore'))
+ $ = marky(fixtures.github)
+ assert.equal($('h3#heading-with-an-_-underscore a').length, 1)
+ })
+
+ it('filters periods in generated DOM ids like GitHub', function () {
+ assert(~fixtures.github.indexOf('### heading with a period.txt'))
+ $ = marky(fixtures.github)
+ assert.equal($('h3#heading-with-a-periodtxt').length, 1)
+ })
+
+ it('allows two spaces even after filtering like GitHub', function () {
+ assert(~fixtures.github.indexOf('### exchange.bind_headers(exchange, routing [, bindCallback])'))
+ $ = marky(fixtures.github)
+ assert.equal($('h3#exchangebind_headersexchange-routing--bindcallback').length, 1)
+ })
+
+ it('add suffix to duplicate generated DOM ids like GitHub', function () {
+ assert(~fixtures.github.indexOf('### duplicate'))
+ assert(~fixtures.github.indexOf('### duplicate('))
+ assert(~fixtures.github.indexOf('### duplicate)'))
+ $ = marky(fixtures.github)
+ assert.equal($('h3#duplicate a').length, 1)
+ assert.equal($('h3#duplicate-1 a').length, 1)
+ assert.equal($('h3#duplicate-2 a').length, 1)
+ })
+
+ it('encodes innerHTML and removes angle brackets before generating ids', function () {
+ assert(~fixtures.payform.indexOf('## Browser `` Helpers'))
+ $ = marky(fixtures.payform, {prefixHeadingIds: false})
+ assert.equal($('h2#browser-input-helpers a').length, 1)
+ assert.equal($('h2#browser-input-helpers a').html(), 'Browser <input>
Helpers')
+ })
+
+ it('properly handles headings lacking a space between the leading #(s) and heading text', function () {
+ assert(~fixtures.lazyheading.indexOf('#lazy heading'))
+ $ = marky(fixtures.lazyheading, {prefixHeadingIds: false})
+ assert.equal($('h1#lazy-heading-1').length, 1)
+ assert.equal($('h2#lazy-heading-2').length, 1)
+ assert.equal($('h3#lazy-heading-3').length, 1)
+ assert.equal($('h4#lazy-heading-4').length, 1)
+ assert.equal($('h5#lazy-heading-5').length, 1)
+ assert.equal($('h6#lazy-heading-6').length, 1)
+ })
+})
diff --git a/test/index.js b/test/index.js
index 5b6b0c0..bf3828e 100644
--- a/test/index.js
+++ b/test/index.js
@@ -1,696 +1,12 @@
-/* globals before, describe, it */
-
-var assert = require('assert')
-var path = require('path')
-var fixtures = require('./fixtures.js')
-var marky = require('..')
-
-describe('marky-markdown', function () {
- it('is a function', function () {
- assert(marky)
- assert(typeof marky === 'function')
- })
-
- it('accepts a markdown string and returns a cheerio DOM object', function () {
- var $ = marky('hello, world')
- assert($.html)
- assert($._root)
- assert($._options)
- assert(~$.html().indexOf('
hello, world
\n')) - }) - - it('throws an error if first argument is not a string', function () { - assert.throws( - function () { marky(null) }, - /first argument must be a string/ - ) - }) -}) - -describe('markdown processing and syntax highlighting', function () { - var $ - before(function () { - $ = marky(fixtures.basic, {highlightSyntax: true}) - }) - - it('preserves query parameters in URLs when making them into links', function () { - assert(~fixtures.basic.indexOf('watch?v=dQw4w9WgXcQ')) - assert.equal($("a[href*='youtube.com']").attr('href'), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ') - }) - - it('converts github flavored fencing to code blocks', function () { - assert(~fixtures.basic.indexOf('```js')) - assert($('code').length) - }) - - it('adds js class to javascript blocks', function () { - assert(~fixtures.basic.indexOf('```js')) - assert($('code.js').length) - }) - - it('adds sh class to shell blocks', function () { - assert(~fixtures.basic.indexOf('```sh')) - assert($('code.sh').length) - }) - - it('adds coffeescript class to coffee blocks', function () { - assert(~fixtures.basic.indexOf('```coffee')) - assert($('code.coffeescript').length) - }) - - it('adds diff class to diff blocks', function () { - assert(~fixtures.basic.indexOf('```diff')) - assert($('code.diff').length) - }) - - it('adds highlight class to all blocks', function () { - assert.equal($('code').length, $('code.highlight').length) - }) - - it('applies inline syntax highlighting classes to javascript', function () { - assert($('.js.modifier').length) - assert($('.js.function').length) - }) - - it('applies inline syntax highlighting classes to shell', function () { - assert($('.shell.builtin').length) - }) - - it('applies inline syntax highlighting classes to coffeescript', function () { - assert($('.coffee.begin').length) - }) - - it('applies inline syntax highlighting classes to diffs', function () { - assert($('.diff.inserted').length) - assert($('.diff.deleted').length) - }) - - it('does not encode entities within code blocks', function () { - assert(~fixtures.enterprise.indexOf('"name": "@myco/anypackage"')) - var $ = marky(fixtures.enterprise) - assert(!~$.html().indexOf('quot')) - assert(~$.html().indexOf('"')) - }) - - it('linkifies fully-qualified URLs', function () { - assert(~fixtures['maintenance-modules'].indexOf('- https://gist.github.com/sindresorhus/8435329')) - var $ = marky(fixtures['maintenance-modules']) - assert($("a[href='https://gist.github.com/sindresorhus/8435329']").length) - }) - - it('replaces markdown syntax for emoji with unicode for the emoji', function () { - assert(~fixtures.github.indexOf(':sparkles:')) - var $ = marky(fixtures.github) - assert($.html().indexOf('✨')) - }) - - it('does not convert text emoticons to unicode', function () { - assert(~fixtures.github.indexOf(':)')) - var $ = marky(fixtures.github) - assert(~$.html().indexOf(':)')) - }) -}) - -describe('sanitize', function () { - var $ - - before(function () { - $ = marky(fixtures.dirty) - }) - - it('removes script tags', function () { - assert(~fixtures.dirty.indexOf(' [hax](http://hax.com)') - assert.equal(description, 'bad hax') - }) - - it('safely handles inline code blocks', function () { - var description = marky.parsePackageDescription('Browser `` Helpers') - assert.equal(description, 'Browser<input type="text">
Helpers')
- })
-
- it('safely handles script tags in inline code blocks', function () {
- var description = marky.parsePackageDescription('Here comes a ` [hax](http://hax.com)')
+ assert.equal(description, 'bad hax')
+ })
+
+ it('safely handles inline code blocks', function () {
+ var description = marky.parsePackageDescription('Browser `` Helpers')
+ assert.equal(description, 'Browser <input type="text">
Helpers')
+ })
+
+ it('safely handles script tags in inline code blocks', function () {
+ var description = marky.parsePackageDescription('Here comes a `