Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ program
.option('--no-open', 'do not automatically open the site in browser')
.action((root, options) => {
const rootFolder = path.resolve(root || process.cwd());
const logsFolder = path.join(rootFolder, '_markbind/logs');
const outputFolder = path.join(rootFolder, '_site');

const site = new Site(rootFolder, outputFolder);
Expand Down Expand Up @@ -167,6 +168,7 @@ program
.then(() => {
const watcher = chokidar.watch(rootFolder, {
ignored: [
logsFolder,
outputFolder,
/(^|[/\\])\../,
x => x.endsWith('___jb_tmp___'), x => x.endsWith('___jb_old___'), // IDE temp files
Expand Down
21 changes: 8 additions & 13 deletions lib/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,16 @@ Page.prototype.generate = function (builtFiles) {
const markbinder = new MarkBind({
errorHandler: logger.error,
});
const fileConfig = {
baseUrlMap: this.baseUrlMap,
rootPath: this.rootPath,
userDefinedVariablesMap: this.userDefinedVariablesMap,
};
return new Promise((resolve, reject) => {
markbinder.includeFile(this.sourcePath, {
baseUrlMap: this.baseUrlMap,
userDefinedVariablesMap: this.userDefinedVariablesMap,
rootPath: this.rootPath,
})
.then(result => markbinder.resolveBaseUrl(result, {
baseUrlMap: this.baseUrlMap,
rootPath: this.rootPath,
}))
markbinder.includeFile(this.sourcePath, fileConfig)
.then(result => markbinder.resolveBaseUrl(result, fileConfig))
.then(result => fs.outputFileAsync(this.tempPath, result))
.then(() => markbinder.renderFile(this.tempPath, {
baseUrlMap: this.baseUrlMap,
rootPath: this.rootPath,
}))
.then(() => markbinder.renderFile(this.tempPath, fileConfig))
.then((result) => {
this.content = htmlBeautify(result, { indent_size: 2 });

Expand Down
21 changes: 18 additions & 3 deletions lib/Site.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const SITE_CONFIG_DEFAULT = {
},
],
ignore: [
'_markbind/logs/*',
'_site/*',
'*.json',
'*.md',
Expand All @@ -51,6 +52,8 @@ const USER_VARIABLES_DEFAULT = '<span id="example">\n'
+ 'More generally, surround the segment\'s id with double curly braces.\n'
+ '</span>';

const GENERATE_SITE_LOGGING_KEY = 'Generate Site';

function Site(rootPath, outputPath) {
this.rootPath = rootPath;
this.outputPath = outputPath;
Expand All @@ -71,6 +74,7 @@ function Site(rootPath, outputPath) {
*/

function rejectHandler(reject, error, removeFolders) {
logger.warn(error);
Promise.all(removeFolders.map(folder => fs.removeAsync(folder)))
.then(() => {
reject(error);
Expand Down Expand Up @@ -242,6 +246,7 @@ Site.prototype.collectUserDefinedVariablesMap = function () {

Site.prototype.generate = function (baseUrl) {
// Create the .tmp folder for storing intermediate results.
logger.profile(GENERATE_SITE_LOGGING_KEY);
fs.emptydirSync(this.tempPath);
// Clean the output folder; create it if not exist.
fs.emptydirSync(this.outputPath);
Expand All @@ -255,7 +260,8 @@ Site.prototype.generate = function (baseUrl) {
.then(resolve)
.catch((error) => {
rejectHandler(reject, error, [this.tempPath, this.outputPath]);
});
})
.finally(() => logger.profile(GENERATE_SITE_LOGGING_KEY));
});
};

Expand All @@ -277,6 +283,7 @@ Site.prototype.buildSourceFiles = function () {

Site.prototype._rebuildAffectedSourceFiles = function (filePaths) {
const uniquePaths = _.uniq(filePaths);
logger.verbose(`Rebuild affected paths: ${uniquePaths}`);
return new Promise((resolve, reject) => {
this.regenerateAffectedPages(uniquePaths)
.then(() => fs.removeAsync(this.tempPath))
Expand Down Expand Up @@ -366,7 +373,11 @@ Site.prototype.generatePages = function () {
pageTemplate: this.pageTemplate,
}));
this.pageModels.forEach((page) => {
processingFiles.push(page.generate(builtFiles));
processingFiles.push(page.generate(builtFiles)
.catch((err) => {
logger.error(err);
return Promise.reject(new Error(`Error while generating ${page.sourcePath}`));
}));
});
return new Promise((resolve, reject) => {
Promise.all(processingFiles)
Expand All @@ -385,7 +396,11 @@ Site.prototype.regenerateAffectedPages = function (filePaths) {
const processingFiles = [];
this.pageModels.forEach((page) => {
if (filePaths.some(filePath => page.includedFiles[filePath])) {
processingFiles.push(page.generate(builtFiles));
processingFiles.push(page.generate(builtFiles)
.catch((err) => {
logger.error(err);
return Promise.reject(new Error(`Error while generating ${page.sourcePath}`));
}));
}
});

Expand Down
34 changes: 32 additions & 2 deletions lib/markbind/lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const utils = require('./utils');

const fs = require('fs');
const path = require('path');
const pathIsInside = require('path-is-inside');
const url = require('url');
const nunjucks = require('nunjucks');

Expand All @@ -34,7 +35,16 @@ const BOILERPLATE_FOLDER_NAME = '_markbind/boilerplates';
* Utils
*/

/**
* @throws Will throw an error if a non-absolute path or path outside the root is given
*/
function calculateNewBaseUrl(filePath, root, lookUp) {
if (!path.isAbsolute(filePath)) {
throw new Error(`Non-absolute path given to calculateNewBaseUrl: '${filePath}'`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check if throw prints the stack trace?
Then we can just have "Non-absolute path given: '${filePath}'".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't print the stack trace

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm okay.

}
if (!pathIsInside(filePath, root)) {
throw new Error(`Path given '${filePath}' is not in root '${root}'`);
}
function calculate(file, result) {
if (file === root) {
return { relative: path.relative(root, root), parent: root };
Expand Down Expand Up @@ -365,7 +375,17 @@ Parser.prototype.includeFile = function (file, config) {
reject(error);
return;
}
const nodes = dom.map(d => this._preprocess(d, context, config));
const nodes = dom.map((d) => {
let processed;
try {
processed = this._preprocess(d, context, config);
} catch (err) {
err.message += `\nError while preprocessing '${file}'`;
this._onError(err);
processed = createErrorNode(d, err);
}
return processed;
});
resolve(cheerio.html(nodes));
});

Expand Down Expand Up @@ -416,7 +436,17 @@ Parser.prototype.renderFile = function (file, config) {
reject(error);
return;
}
const nodes = dom.map(d => this._parse(d, context, config));
const nodes = dom.map((d) => {
let parsed;
try {
parsed = this._parse(d, context, config);
} catch (err) {
err.message += `\nError while rendering '${file}'`;
this._onError(err);
parsed = createErrorNode(d, err);
}
return parsed;
});
nodes.forEach((d) => {
this._trimNodes(d);
});
Expand Down
46 changes: 42 additions & 4 deletions lib/util/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,49 @@

const chalk = require('chalk');
const figlet = require('figlet');
const winston = require('winston');
const DailyRotateFile = require('winston-daily-rotate-file');

winston.configure({
exitOnError: false,
transports: [
new DailyRotateFile({
level: 'debug',
showLevel: true,
handleExceptions: true,
humanReadableUnhandledException: true,
filename: 'markbind-%DATE%.log',
datePattern: 'YYYY-MM-DD',
dirname: '_markbind/logs',
maxFiles: '2d',
}),
],
});

module.exports = {
info: text => console.log(chalk.cyan('info: ') + text),
warn: text => console.log(chalk.yellow(`warning: ${text}`)),
error: text => console.log(chalk.red(`error: ${text}`)),
log: text => console.log(text),
error: (text) => {
console.log(chalk.red(`error: ${text}`));
winston.error(text);
},
warn: (text) => {
console.log(chalk.yellow(`warning: ${text}`));
winston.warn(text);
},
info: (text) => {
console.log(chalk.cyan('info: ') + text);
winston.info(text);
},
verbose: (text) => {
winston.verbose(text);
},
debug: (text) => {
winston.debug(text);
},
log: (text) => {
console.log(text);
},
logo: () => console.log(chalk.green(figlet.textSync('MarkBind', { horizontalLayout: 'full' }))),
profile: (key) => {
winston.profile(key);
},
};
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
"markdown-it-video": "^0.4.0",
"nunjucks": "^3.0.0",
"path-is-inside": "^1.0.2",
"walk-sync": "^0.3.1"
"walk-sync": "^0.3.1",
"winston": "^2.4.1",
"winston-daily-rotate-file": "^3.0.1"
},
"repository": {
"type": "git",
Expand Down
1 change: 1 addition & 0 deletions test/test_site/site.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
}
],
"ignore": [
"_markbind/logs/*",
"_site/*",
"site.json",
"*.md",
Expand Down