Skip to content

Commit 0eaa449

Browse files
authored
Merge pull request MarkBind#189 from rachx/add-log-file
Add logging to file
2 parents be40b75 + 2ed174a commit 0eaa449

File tree

7 files changed

+106
-23
lines changed

7 files changed

+106
-23
lines changed

index.js

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ program
107107
.option('--no-open', 'do not automatically open the site in browser')
108108
.action((root, options) => {
109109
const rootFolder = path.resolve(root || process.cwd());
110+
const logsFolder = path.join(rootFolder, '_markbind/logs');
110111
const outputFolder = path.join(rootFolder, '_site');
111112

112113
const site = new Site(rootFolder, outputFolder);
@@ -167,6 +168,7 @@ program
167168
.then(() => {
168169
const watcher = chokidar.watch(rootFolder, {
169170
ignored: [
171+
logsFolder,
170172
outputFolder,
171173
/(^|[/\\])\../,
172174
x => x.endsWith('___jb_tmp___'), x => x.endsWith('___jb_old___'), // IDE temp files

lib/Page.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,16 @@ Page.prototype.generate = function (builtFiles) {
7878
const markbinder = new MarkBind({
7979
errorHandler: logger.error,
8080
});
81+
const fileConfig = {
82+
baseUrlMap: this.baseUrlMap,
83+
rootPath: this.rootPath,
84+
userDefinedVariablesMap: this.userDefinedVariablesMap,
85+
};
8186
return new Promise((resolve, reject) => {
82-
markbinder.includeFile(this.sourcePath, {
83-
baseUrlMap: this.baseUrlMap,
84-
userDefinedVariablesMap: this.userDefinedVariablesMap,
85-
rootPath: this.rootPath,
86-
})
87-
.then(result => markbinder.resolveBaseUrl(result, {
88-
baseUrlMap: this.baseUrlMap,
89-
rootPath: this.rootPath,
90-
}))
87+
markbinder.includeFile(this.sourcePath, fileConfig)
88+
.then(result => markbinder.resolveBaseUrl(result, fileConfig))
9189
.then(result => fs.outputFileAsync(this.tempPath, result))
92-
.then(() => markbinder.renderFile(this.tempPath, {
93-
baseUrlMap: this.baseUrlMap,
94-
rootPath: this.rootPath,
95-
}))
90+
.then(() => markbinder.renderFile(this.tempPath, fileConfig))
9691
.then((result) => {
9792
this.content = htmlBeautify(result, { indent_size: 2 });
9893

lib/Site.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const SITE_CONFIG_DEFAULT = {
3535
},
3636
],
3737
ignore: [
38+
'_markbind/logs/*',
3839
'_site/*',
3940
'*.json',
4041
'*.md',
@@ -51,6 +52,8 @@ const USER_VARIABLES_DEFAULT = '<span id="example">\n'
5152
+ 'More generally, surround the segment\'s id with double curly braces.\n'
5253
+ '</span>';
5354

55+
const GENERATE_SITE_LOGGING_KEY = 'Generate Site';
56+
5457
function Site(rootPath, outputPath) {
5558
this.rootPath = rootPath;
5659
this.outputPath = outputPath;
@@ -71,6 +74,7 @@ function Site(rootPath, outputPath) {
7174
*/
7275

7376
function rejectHandler(reject, error, removeFolders) {
77+
logger.warn(error);
7478
Promise.all(removeFolders.map(folder => fs.removeAsync(folder)))
7579
.then(() => {
7680
reject(error);
@@ -242,6 +246,7 @@ Site.prototype.collectUserDefinedVariablesMap = function () {
242246

243247
Site.prototype.generate = function (baseUrl) {
244248
// Create the .tmp folder for storing intermediate results.
249+
logger.profile(GENERATE_SITE_LOGGING_KEY);
245250
fs.emptydirSync(this.tempPath);
246251
// Clean the output folder; create it if not exist.
247252
fs.emptydirSync(this.outputPath);
@@ -255,7 +260,8 @@ Site.prototype.generate = function (baseUrl) {
255260
.then(resolve)
256261
.catch((error) => {
257262
rejectHandler(reject, error, [this.tempPath, this.outputPath]);
258-
});
263+
})
264+
.finally(() => logger.profile(GENERATE_SITE_LOGGING_KEY));
259265
});
260266
};
261267

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

278284
Site.prototype._rebuildAffectedSourceFiles = function (filePaths) {
279285
const uniquePaths = _.uniq(filePaths);
286+
logger.verbose(`Rebuild affected paths: ${uniquePaths}`);
280287
return new Promise((resolve, reject) => {
281288
this.regenerateAffectedPages(uniquePaths)
282289
.then(() => fs.removeAsync(this.tempPath))
@@ -366,7 +373,11 @@ Site.prototype.generatePages = function () {
366373
pageTemplate: this.pageTemplate,
367374
}));
368375
this.pageModels.forEach((page) => {
369-
processingFiles.push(page.generate(builtFiles));
376+
processingFiles.push(page.generate(builtFiles)
377+
.catch((err) => {
378+
logger.error(err);
379+
return Promise.reject(new Error(`Error while generating ${page.sourcePath}`));
380+
}));
370381
});
371382
return new Promise((resolve, reject) => {
372383
Promise.all(processingFiles)
@@ -385,7 +396,11 @@ Site.prototype.regenerateAffectedPages = function (filePaths) {
385396
const processingFiles = [];
386397
this.pageModels.forEach((page) => {
387398
if (filePaths.some(filePath => page.includedFiles[filePath])) {
388-
processingFiles.push(page.generate(builtFiles));
399+
processingFiles.push(page.generate(builtFiles)
400+
.catch((err) => {
401+
logger.error(err);
402+
return Promise.reject(new Error(`Error while generating ${page.sourcePath}`));
403+
}));
389404
}
390405
});
391406

lib/markbind/lib/parser.js

+32-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const utils = require('./utils');
2222

2323
const fs = require('fs');
2424
const path = require('path');
25+
const pathIsInside = require('path-is-inside');
2526
const url = require('url');
2627
const nunjucks = require('nunjucks');
2728

@@ -34,7 +35,16 @@ const BOILERPLATE_FOLDER_NAME = '_markbind/boilerplates';
3435
* Utils
3536
*/
3637

38+
/**
39+
* @throws Will throw an error if a non-absolute path or path outside the root is given
40+
*/
3741
function calculateNewBaseUrl(filePath, root, lookUp) {
42+
if (!path.isAbsolute(filePath)) {
43+
throw new Error(`Non-absolute path given to calculateNewBaseUrl: '${filePath}'`);
44+
}
45+
if (!pathIsInside(filePath, root)) {
46+
throw new Error(`Path given '${filePath}' is not in root '${root}'`);
47+
}
3848
function calculate(file, result) {
3949
if (file === root) {
4050
return { relative: path.relative(root, root), parent: root };
@@ -365,7 +375,17 @@ Parser.prototype.includeFile = function (file, config) {
365375
reject(error);
366376
return;
367377
}
368-
const nodes = dom.map(d => this._preprocess(d, context, config));
378+
const nodes = dom.map((d) => {
379+
let processed;
380+
try {
381+
processed = this._preprocess(d, context, config);
382+
} catch (err) {
383+
err.message += `\nError while preprocessing '${file}'`;
384+
this._onError(err);
385+
processed = createErrorNode(d, err);
386+
}
387+
return processed;
388+
});
369389
resolve(cheerio.html(nodes));
370390
});
371391

@@ -416,7 +436,17 @@ Parser.prototype.renderFile = function (file, config) {
416436
reject(error);
417437
return;
418438
}
419-
const nodes = dom.map(d => this._parse(d, context, config));
439+
const nodes = dom.map((d) => {
440+
let parsed;
441+
try {
442+
parsed = this._parse(d, context, config);
443+
} catch (err) {
444+
err.message += `\nError while rendering '${file}'`;
445+
this._onError(err);
446+
parsed = createErrorNode(d, err);
447+
}
448+
return parsed;
449+
});
420450
nodes.forEach((d) => {
421451
this._trimNodes(d);
422452
});

lib/util/logger.js

+42-4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,49 @@
22

33
const chalk = require('chalk');
44
const figlet = require('figlet');
5+
const winston = require('winston');
6+
const DailyRotateFile = require('winston-daily-rotate-file');
7+
8+
winston.configure({
9+
exitOnError: false,
10+
transports: [
11+
new DailyRotateFile({
12+
level: 'debug',
13+
showLevel: true,
14+
handleExceptions: true,
15+
humanReadableUnhandledException: true,
16+
filename: 'markbind-%DATE%.log',
17+
datePattern: 'YYYY-MM-DD',
18+
dirname: '_markbind/logs',
19+
maxFiles: '2d',
20+
}),
21+
],
22+
});
523

624
module.exports = {
7-
info: text => console.log(chalk.cyan('info: ') + text),
8-
warn: text => console.log(chalk.yellow(`warning: ${text}`)),
9-
error: text => console.log(chalk.red(`error: ${text}`)),
10-
log: text => console.log(text),
25+
error: (text) => {
26+
console.log(chalk.red(`error: ${text}`));
27+
winston.error(text);
28+
},
29+
warn: (text) => {
30+
console.log(chalk.yellow(`warning: ${text}`));
31+
winston.warn(text);
32+
},
33+
info: (text) => {
34+
console.log(chalk.cyan('info: ') + text);
35+
winston.info(text);
36+
},
37+
verbose: (text) => {
38+
winston.verbose(text);
39+
},
40+
debug: (text) => {
41+
winston.debug(text);
42+
},
43+
log: (text) => {
44+
console.log(text);
45+
},
1146
logo: () => console.log(chalk.green(figlet.textSync('MarkBind', { horizontalLayout: 'full' }))),
47+
profile: (key) => {
48+
winston.profile(key);
49+
},
1250
};

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@
4444
"markdown-it-video": "^0.4.0",
4545
"nunjucks": "^3.0.0",
4646
"path-is-inside": "^1.0.2",
47-
"walk-sync": "^0.3.1"
47+
"walk-sync": "^0.3.1",
48+
"winston": "^2.4.1",
49+
"winston-daily-rotate-file": "^3.0.1"
4850
},
4951
"repository": {
5052
"type": "git",

test/test_site/site.json

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
}
1212
],
1313
"ignore": [
14+
"_markbind/logs/*",
1415
"_site/*",
1516
"site.json",
1617
"*.md",

0 commit comments

Comments
 (0)