mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-20 17:43:24 +00:00
Add code blocks normalization
This commit is contained in:
+63
-29
@@ -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
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user