Add code blocks normalization

This commit is contained in:
Samy Pessé
2016-02-14 15:26:15 +01:00
parent a65f888a77
commit 0e86cdeb4a
2 changed files with 74 additions and 30 deletions
+63 -29
View File
@@ -25,6 +25,9 @@ function HTMLPipeline(htmlString, opts) {
// Output an image
onImage: _.identity,
// Syntax highlighting
onCodeBlock: _.identity,
// Output a svg, if returns null the svg is kept inlined
onOutputSVG: _.constant(null)
});
@@ -39,20 +42,28 @@ function HTMLPipeline(htmlString, opts) {
});
}
// Normalize links
HTMLPipeline.prototype.normalizeLinks = function() {
// Transform a query of elements in the page
HTMLPipeline.prototype._transform = function(query, fn) {
var that = this;
this.$('a').each(function() {
var $a = that.$(this);
var $elements = this.$(query);
return Promise.serie($elements, function(el) {
var $el = that.$(el);
return fn.call(that, $el);
});
};
// Normalize links
HTMLPipeline.prototype.transformLinks = function() {
return this._transform('a', function($a) {
var href = $a.attr('href');
if (!href) return;
if (location.isAnchor(href)) {
// Don't "change" anchor links
} else if (location.isRelative(href)) {
$a.attr('href', that.opts.onRelativeLink(href));
$a.attr('href', this.opts.onRelativeLink(href));
} else {
// External links
$a.attr('target', '_blank');
@@ -61,23 +72,50 @@ HTMLPipeline.prototype.normalizeLinks = function() {
};
// Normalize images
HTMLPipeline.prototype.normalizeImages = function() {
var that = this;
var $imgs = this.$('img');
return Promise.serie($imgs, function(img) {
var $img = that.$(img);
return Promise(that.opts.onImage($img.attr('src')))
HTMLPipeline.prototype.transformImages = function() {
return this._transform('img', function($img) {
return Promise(this.opts.onImage($img.attr('src')))
.then(function(filename) {
$img.attr('src', filename);
});
});
};
// Normalize code blocks
HTMLPipeline.prototype.transformCodeBlocks = function() {
return this._transform('code', function($code) {
// Extract language
var lang = _.chain(
($code.attr('class') || '').split(' ')
)
.map(function(cl) {
// Markdown
if (cl.search('lang-') === 0) return cl.slice('lang-'.length);
// Asciidoc
if (cl.search('language-') === 0) return cl.slice('language-'.length);
return null;
})
.compact()
.first()
.value();
var source = $code.text();
return Promise(this.opts.onCodeBlock(source, lang))
.then(function(blk) {
if (blk.html === false) {
$code.text(blk.body);
} else {
$code.html(blk.body);
}
});
});
};
// Add ID to headings
HTMLPipeline.prototype.addHeadingIDs = function() {
HTMLPipeline.prototype.transformHeadings = function() {
var that = this;
this.$('h1,h2,h3,h4,h5,h6').each(function() {
@@ -90,23 +128,18 @@ HTMLPipeline.prototype.addHeadingIDs = function() {
};
// Outline SVG from the HML
HTMLPipeline.prototype.outlineSVG = function() {
var that = this;
var $svgs = this.$('svg');
return Promise.serie($svgs, function(svg) {
var $svg = that.$(svg);
HTMLPipeline.prototype.transformSvgs = function() {
return this._transform('svg', function($svg) {
var content = [
'<?xml version="1.0" encoding="UTF-8"?>',
renderDOM(that.$, $svg)
renderDOM(this.$, $svg)
].join('\n');
return Promise(that.opts.onOutputSVG(content))
return Promise(this.opts.onOutputSVG(content))
.then(function(filename) {
if (!filename) return;
$svg.replaceWith(that.$('<img>').attr('src', filename));
$svg.replaceWith(this.$('<img>').attr('src', filename));
});
});
};
@@ -116,10 +149,11 @@ HTMLPipeline.prototype.output = function() {
var that = this;
return Promise()
.then(this.normalizeLinks)
.then(this.normalizeImages)
.then(this.addHeadingIDs)
.then(this.outlineSVG)
.then(this.transformLinks)
.then(this.transformImages)
.then(this.transformHeadings)
.then(this.transformCodeBlocks)
.then(this.transformSvgs)
.then(function() {
return renderDOM(that.$);
});
+11 -1
View File
@@ -144,7 +144,17 @@ Page.prototype.parse = function(output) {
var pipelineOpts = {
onRelativeLink: _.partial(output.onRelativeLink, that),
onImage: _.partial(output.onOutputImage, that),
onOutputSVG: _.partial(output.onOutputSVG, that)
onOutputSVG: _.partial(output.onOutputSVG, that),
// Use 'code' template block
onCodeBlock: function(source, lang) {
return output.template.applyBlock('code', {
body: source,
kwargs: {
language: lang
}
});
}
};
var pipeline = new HTMLPipeline(that.content, pipelineOpts);