bem-md-renderer
Advanced tools
Comparing version 0.1.0 to 0.2.0
99
index.js
@@ -37,3 +37,3 @@ var marked = require('marked'), | ||
pedantic: false, | ||
sanitize: false, | ||
sanitize: false, // in many cases md uses html to insert iframe or img on bem.info | ||
renderer: getRenderer() | ||
@@ -55,4 +55,7 @@ }, options), function (err, result) { | ||
function createRenderer() { | ||
renderer = new marked.Renderer(); | ||
var Renderer = marked.Renderer, | ||
baseRenderer = Renderer.prototype; | ||
renderer = new Renderer(); | ||
/** | ||
@@ -80,2 +83,43 @@ * Fix marked issue with cyrillic symbols replacing. | ||
/** | ||
* Replace video`s share service links to iframe video block | ||
* Examples markdown: | ||
* [Youtube 1](https://youtu.be/1GWoMnYldYc) | ||
* [Youtube 2](https://www.youtube.com/watch?v=4jrUgqMlvP0) | ||
* [Yandex](https://video.yandex.ru/iframe/ya-events/clg24o8tu3.7046/) | ||
* [Vimeo 1](https://vimeo.com/53219242/) | ||
* [Vimeo 2](https://player.vimeo.com/video/30838628) | ||
* | ||
* p.s. By default gets base renderer link | ||
* @param {String} href | ||
* @param {String} title | ||
* @param {String} text | ||
*/ | ||
renderer.link = function (href, title, text) { | ||
var result = baseRenderer.link.apply(this, arguments), | ||
services = { | ||
youtube: ['youtu.be', 'youtube.com'], | ||
yandex: [ | ||
'video.yandex.ru', | ||
'static.video.yandex.ru' | ||
], | ||
vimeo: ['vimeo.com', 'player.vimeo.com'] | ||
}; | ||
_.keys(services).forEach(function (service) { | ||
// filter service by match href | ||
var supportService = _.filter(services[service], function (link) { | ||
return href.indexOf(link) > -1; | ||
}); | ||
// href contain link to support video service | ||
if (supportService.length) { | ||
result = getIframe(href, service); | ||
return false; | ||
} | ||
}); | ||
return result; | ||
}; | ||
// Fix(hidden) post scroll, when it contains wide table | ||
@@ -105,12 +149,55 @@ renderer.table = function (header, body) { | ||
/** | ||
* Get service iframe video by passed name | ||
* Required href: | ||
* - youtube: https://youtu.be/1GWoMnYldYc or https://www.youtube.com/watch?v=1GWoMnYldYc | ||
* - yandex: https://video.yandex.ru/iframe/ya-events/clg24o8tu3.7046/ | ||
* - vimeo: https://vimeo.com/30838628 or https://player.vimeo.com/video/30838628 | ||
* @param {String} href - full video href, examples see above | ||
* @param {String} serviceName - name of the service [youtube, yandex, vimeo] | ||
* @returns {String} - iframe video block | ||
*/ | ||
function getIframe(href, serviceName) { | ||
var serviceToUrl = { | ||
youtube: 'www.youtube.com/embed/', | ||
yandex: 'video.yandex.ru/iframe/ya-events/', | ||
vimeo: 'player.vimeo.com/video/' | ||
}, | ||
arr = href.split('/'), | ||
key = arr.pop(), | ||
src; | ||
/** | ||
* Get the second last href arr item for key, | ||
* if href contains slash at the end and our key empty | ||
* For example: https://vimeo.com/53219242/ | ||
*/ | ||
if (!key.length) { | ||
key = arr[arr.length - 1]; | ||
} | ||
/** | ||
* Key contains extra words | ||
* For example: | ||
* Original href = http://www.youtube.com/watch?v=1GWoMnYldYc | ||
* key = watch?v=1GWoMnYldYc - we need remove watch?v= | ||
*/ | ||
if (serviceName === 'youtube' && key.indexOf('watch?v=') > -1) { | ||
key = key.match(/(\d\w).+$/gi)[0]; | ||
} | ||
src = serviceToUrl[serviceName] + key; | ||
return '<iframe src="//' + src + '" width="560" height="315" frameborder="0" allowfullscreen></iframe>'; | ||
} | ||
/** | ||
* Return an instance of custom marked renderer | ||
* Reset usedAnchors variable, | ||
* which need to check duplicate headers in the markdown | ||
* which needed to check duplicate headers in the markdown | ||
* @returns {*} | ||
*/ | ||
function getRenderer() { | ||
if (!renderer) renderer = createRenderer(); | ||
usedAnchors = {}; | ||
usedAnchors = {}; | ||
return renderer; | ||
return renderer || (renderer = createRenderer()); | ||
} | ||
@@ -117,0 +204,0 @@ |
{ | ||
"name": "bem-md-renderer", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "The builder markdown to html with custom renderer, which generates the html headlines like github", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
156
test/test.js
@@ -1,24 +0,108 @@ | ||
var marked = require('marked'), | ||
should = require('should'); | ||
var fs = require('fs'), | ||
path = require('path'), | ||
should = require('should'), | ||
renderer = require('../index.js'), | ||
defaultOptions = { | ||
renderer: renderer.getRenderer(), | ||
gfm: true, | ||
tables: true, | ||
breaks: false, | ||
pedantic: false, | ||
sanitize: false, | ||
smartLists: true, | ||
smartypants: false | ||
}, | ||
md = '# Setting a modifier on a block and reacting to it'; | ||
filePathName = path.join(__dirname, 'test'), | ||
CONTENT = { | ||
HEADING: { | ||
source: '# Setting a modifier on a block and reacting to it', | ||
result: '<h2 id="setting-a-modifier-on-a-block-and-reacting-to-it">' + | ||
'<a href="#setting-a-modifier-on-a-block-and-reacting-to-it" class="anchor">' + | ||
'</a>Setting a modifier on a block and reacting to it</h2>', | ||
idx: 'setting-a-modifier-on-a-block-and-reacting-to-it' | ||
}, | ||
LINK: { | ||
source: '[Link](http://link.com/index "Custom title")', | ||
result: '<a href="http://link.com/index" title="Custom title">Link</a>' | ||
}, | ||
VIDEO: { | ||
source: '[Video](https://youtu.be/1GWoMnYldYc)', | ||
result: '<iframe src="//www.youtube.com/embed/1GWoMnYldYc" width="560" height="315" frameborder="0"' + | ||
' allowfullscreen></iframe>' | ||
}, | ||
DOC: { | ||
source: fs.readFileSync(filePathName + '.md').toString(), | ||
result: fs.readFileSync(filePathName + '.html').toString() | ||
}, | ||
REGEXP: { | ||
// <h1 id="heading-143">heading-143</h1> -> replace `key` to `id` and get value of id attr | ||
attr: 'key=["\']((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)', | ||
// <p><a href="link.com">Link</a></p>/n... -> replace `key` to `a` and get <a href="link.com">Link</a> | ||
tag: '<key.+<\/key>' | ||
} | ||
}; | ||
describe('bem-md-renderer', function () { | ||
it('should render md with custom renderer', function(done) { | ||
var DOC = CONTENT.DOC; | ||
renderer.render(DOC.source, function (err, html) { | ||
if (err) done(err); | ||
html.should.equal(DOC.result); | ||
done(); | ||
}); | ||
}); | ||
describe('#anchors', function () { | ||
var HEADING = CONTENT.HEADING, | ||
SOURCE = HEADING.source; | ||
it('should be correct rendered github-like title id for anchor', function (done) { | ||
renderer.render(SOURCE, function (err, html) { | ||
if (err) done(err); | ||
getAttrValue(html, getRegexp('attr', 'id')).should.equal(HEADING.idx); | ||
done(); | ||
}); | ||
}); | ||
it('should be the same – title id and href anchor in link', function (done) { | ||
renderer.render(SOURCE, function (err, html) { | ||
if (err) done(err); | ||
var anchor = getAttrValue(html, getRegexp('attr', 'href')); | ||
anchor = anchor ? anchor.replace('#', '') : ''; | ||
getAttrValue(html, getRegexp('attr', 'id')).should.equal(anchor); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('#link', function () { | ||
var LINK = CONTENT.LINK, | ||
VIDEO = CONTENT.VIDEO; | ||
it('should render link', function (done) { | ||
renderer.render(LINK.source, function (err, html) { | ||
if (err) done(err); | ||
getCleanedHtml('a', html).should.equal(LINK.result); | ||
done(); | ||
}); | ||
}); | ||
it('should render video iframe', function (done) { | ||
renderer.render(VIDEO.source, function (err, html) { | ||
if (err) done(err); | ||
getCleanedHtml('iframe', html).should.equal(VIDEO.result); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
/** | ||
* Get new regexp to matching value of pass key | ||
* @param {String} type - type regexp match (atts || tag) | ||
* @param {String} key - e.g. html attr like id, class and anothers | ||
* @returns {RegExp} | ||
*/ | ||
function getRegexp (key) { | ||
var reg = 'key=["\']((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)'.replace('key', key); | ||
function getRegexp (type, key) { | ||
var reg = CONTENT.REGEXP[type].replace(/key/g, key); | ||
return new RegExp(reg); | ||
@@ -35,29 +119,21 @@ } | ||
function getAttrValue(html, regexp) { | ||
var result = regexp.exec(html); | ||
return (result && result.length > 1) ? regexp.exec(html)[1] : ''; | ||
var result = html.match(regexp, 'g'); | ||
return (result && result.length > 1) ? result[1] : ''; | ||
} | ||
marked.setOptions(defaultOptions); | ||
/** | ||
* Get cleaned html result by matched tag | ||
* For true compare, we need remove in result html | ||
* tags link `p` and new line symbol | ||
* html: <p><a href="http://link.com/index" title="Custom title">Link</a></p>\n | ||
* result = <a href="http://link.com/index" title="Custom title">Link</a> | ||
* @param {String} tag | ||
* @param {String} html | ||
* @returns {*} | ||
*/ | ||
function getCleanedHtml(tag, html) { | ||
html = html.match(getRegexp('tag', tag), 'g'); | ||
describe('bem-md-renderer', function () { | ||
it('should be correct rendered github-like title id for anchor', function (done) { | ||
marked(md, function (err, html) { | ||
if (err) done(err); | ||
getAttrValue(html, getRegexp('id')).should.equal('setting-a-modifier-on-a-block-and-reacting-to-it'); | ||
done(); | ||
}); | ||
}); | ||
it('should be the same – title id and href anchor in link', function (done) { | ||
marked(md, function (err, html) { | ||
if (err) done(err); | ||
var anchor = getAttrValue(html, getRegexp('href')); | ||
anchor = anchor ? anchor.replace('#', '') : ''; | ||
getAttrValue(html, getRegexp('id')).should.equal(anchor); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
return html.length ? html[0] : ''; | ||
} |
68365
14
404
2