Skip to content

Commit

Permalink
Implement a helper function for rebasing base-url (to be used with cli)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gisonrg committed May 16, 2017
1 parent 4017689 commit 64b2ff6
Show file tree
Hide file tree
Showing 3 changed files with 915 additions and 13 deletions.
121 changes: 120 additions & 1 deletion lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ const utils = require('./utils');
const fs = require('fs');
const path = require('path');
const url = require('url');
const nunjucks = require('nunjucks');

const ATTRIB_INCLUDE_PATH = 'include-path';
const ATTRIB_CWF = 'cwf';
/*
* Utils
*/
function isText(element) {
return element.type === 'text';
return element.type === 'text' || element.type === 'comment';
}

function Parser(options) {
Expand All @@ -36,6 +39,8 @@ Parser.prototype.getDynamicIncludeSrc = function () {

Parser.prototype._preprocess = function (element, context) {
let self = this;
element.attribs = element.attribs || {};
element.attribs[ATTRIB_CWF] = path.resolve(context.cwf);
if (element.name === 'include') {
let isInline = _.hasIn(element.attribs, 'inline');
let isDynamic = _.hasIn(element.attribs, 'dynamic');
Expand All @@ -44,6 +49,7 @@ Parser.prototype._preprocess = function (element, context) {
let includeSrcPath = includeSrc.path;
let filePath = isUrl ? element.attribs.src : path.resolve(path.dirname(context.cwf), includeSrcPath);
element.name = isInline ? 'span' : 'div';
element.attribs[ATTRIB_INCLUDE_PATH] = filePath;

if (isDynamic) {
element.name = 'dynamic-panel';
Expand Down Expand Up @@ -370,4 +376,117 @@ Parser.prototype.renderFile = function (file, cb) {
});
};

Parser.prototype.resolveBaseUrl = function (pageData, config, cb) {
let {baseUrlMap, rootPath} = config;
this.baseUrlMap = baseUrlMap;
this.rootPath = rootPath;
cb = cb || function () {}; // create empty callback
return new Promise((resolve, reject) => {
let handler = new htmlparser.DomHandler((error, dom) => {
if (error) {
reject(error);
cb(error);
return;
}
dom.forEach(d => {
let childrenBase = {};
this._rebaseReference(d, childrenBase);
if (d.attribs && d.attribs[ATTRIB_CWF] && d.attribs[ATTRIB_INCLUDE_PATH]) {
let currentBase = calculateNewBaseUrl(d.attribs[ATTRIB_CWF], this.rootPath, this.baseUrlMap);
let newBase = calculateNewBaseUrl(d.attribs[ATTRIB_CWF], this.rootPath, this.baseUrlMap);
if (currentBase.relative !== newBase.relative) {
let bases = Object.keys(childrenBase);
if (bases.length !== 0) {
// need to rebase
let children = d.children;
if (children) {
cheerio.prototype.options.xmlMode = false;
let rendered = nunjucks.renderString(cheerio.html(children), {baseUrl: `{{baseUrl}}/${newBase.relative}`});
d.children = cheerio.parseHTML(rendered, true);
cheerio.prototype.options.xmlMode = true;
}
}
}
}
});
cheerio.prototype.options.xmlMode = false;
resolve(cheerio.html(dom));
cb(null, cheerio.html(dom));
cheerio.prototype.options.xmlMode = true;
});

let parser = new htmlparser.Parser(handler, {
xmlMode: true,
decodeEntities: true
});

parser.parseComplete(pageData);
});
};

Parser.prototype._rebaseReference = function(node, foundBase) {
if (_.isArray(node)) {
return node.forEach(el => {
return this._rebaseReference(el, foundBase);
});
}

if (isText(node)) {
return node;
} else {
// Rebase children element
let childrenBase = {};
node.children.forEach(el => {
this._rebaseReference(el, childrenBase);
});

// rebase current element
if (node.attribs[ATTRIB_CWF]) {
let path = node.attribs[ATTRIB_CWF];
let newBase = calculateNewBaseUrl(path, this.rootPath, this.baseUrlMap);
if (newBase) {
let {relative, parent} = newBase;
foundBase[parent] = relative;
}

let bases = Object.keys(childrenBase);
if (bases.length !== 0) {
// need to rebase
let newBase = childrenBase[bases[0]];
let children = node.children;
if (children) {
let currentBase = calculateNewBaseUrl(node.attribs[ATTRIB_CWF], this.rootPath, this.baseUrlMap);
if (currentBase) {
if (currentBase.relative !== newBase) {
cheerio.prototype.options.xmlMode = false;
let rendered = nunjucks.renderString(cheerio.html(children), {baseUrl: `{{baseUrl}}/${newBase}`});
node.children = cheerio.parseHTML(rendered, true);
cheerio.prototype.options.xmlMode = true;
}
}
}
}
delete node.attribs[ATTRIB_INCLUDE_PATH];
}
delete node.attribs[ATTRIB_CWF];
}
};

function calculateNewBaseUrl(filePath, root, lookUp) {
function calculate(file, result) {
if (file === root) {
return {relative: path.relative(root, root), parent: root};
}
let parent = path.dirname(file);
if (lookUp[parent] && result.length == 1) {
return {relative: path.relative(parent, result[0]), parent};
} else if (lookUp[parent]) {
return calculate(parent, [parent]);
}
return calculate(parent, result);
}

return calculate(filePath, []);
}

module.exports = Parser;
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
"markdown-it-mark": "^2.0.0",
"markdown-it-table-of-contents": "^0.3.2",
"markdown-it-task-lists": "^1.4.1",
"markdown-it-video": "^0.4.0"
"markdown-it-video": "^0.4.0",
"nunjucks": "^3.0.0",
"path-is-inside": "^1.0.2"
},
"devDependencies": {
"eslint": "^3.16.1",
Expand Down
Loading

0 comments on commit 64b2ff6

Please sign in to comment.