diff --git a/src/Template.js b/src/Template.js index f26ab44ff..9429d4a45 100644 --- a/src/Template.js +++ b/src/Template.js @@ -28,6 +28,7 @@ class Template extends TemplateContent { this.outputDir = false; } + this.linters = []; this.transforms = []; this.plugins = {}; this.templateData = templateData; @@ -326,13 +327,23 @@ class Template extends TemplateContent { } } + addLinter(callback) { + this.linters.push(callback); + } + + async runLinters(str, inputPath, outputPath) { + this.linters.forEach(function(linter) { + linter.call(this, str, inputPath, outputPath); + }); + } + addTransform(callback) { this.transforms.push(callback); } - async runTransforms(str, outputPath) { + async runTransforms(str, outputPath, inputPath) { this.transforms.forEach(function(transform) { - str = transform.call(this, str, outputPath); + str = transform.call(this, str, outputPath, inputPath); }); return str; @@ -389,10 +400,11 @@ class Template extends TemplateContent { async getRenderedTemplates(data) { let pages = await this.getTemplates(data); for (let page of pages) { - page.templateContent = await page.template._getContent( - page.outputPath, - page.data - ); + let content = await page.template._getContent(page.outputPath, page.data); + + await this.runLinters(content, page.inputPath, page.outputPath); + + page.templateContent = content; } return pages; } @@ -451,6 +463,9 @@ class Template extends TemplateContent { for (let transform of this.transforms) { tmpl.addTransform(transform); } + for (let linter of this.linters) { + tmpl.addLinter(linter); + } tmpl.setIsVerbose(this.isVerbose); tmpl.setDryRun(this.isDryRun); diff --git a/src/TemplateWriter.js b/src/TemplateWriter.js index 89e37d790..0f2843153 100644 --- a/src/TemplateWriter.js +++ b/src/TemplateWriter.js @@ -83,10 +83,17 @@ TemplateWriter.prototype._createTemplate = function(path) { * return pretty(str, { ocd: true }); * } */ - for (let filterName in this.config.filters) { - let filter = this.config.filters[filterName]; - if (typeof filter === "function") { - tmpl.addTransform(filter); + for (let transformName in this.config.filters) { + let transform = this.config.filters[transformName]; + if (typeof transform === "function") { + tmpl.addTransform(transform); + } + } + + for (let linterName in this.config.linters) { + let linter = this.config.linters[linterName]; + if (typeof linter === "function") { + tmpl.addLinter(linter); } } diff --git a/src/UserConfig.js b/src/UserConfig.js index f2bffb03f..27bbed6b1 100644 --- a/src/UserConfig.js +++ b/src/UserConfig.js @@ -37,6 +37,7 @@ class UserConfig { this.libraryOverrides = {}; this.layoutAliases = {}; + this.linters = {}; // now named `transforms` in API this.filters = {}; this.activeNamespace = ""; @@ -201,6 +202,12 @@ class UserConfig { this.filters[name] = callback; } + addLinter(name, callback) { + name = this.getNamespacedName(name); + + this.linters[name] = callback; + } + addLayoutAlias(from, to) { this.layoutAliases[from] = to; } @@ -409,7 +416,9 @@ class UserConfig { getMergingConfigObject() { return { templateFormats: this.templateFormats, + // now called transforms filters: this.filters, + linters: this.linters, layoutAliases: this.layoutAliases, passthroughCopies: this.passthroughCopies, liquidOptions: this.liquidOptions, diff --git a/test/TemplateTest.js b/test/TemplateTest.js index ee1bcc474..e01101334 100644 --- a/test/TemplateTest.js +++ b/test/TemplateTest.js @@ -1094,3 +1094,23 @@ test("Test a transform with pages", async t => { let rendered = await tmpl.getRenderedTemplates(data); t.is(rendered[0].templateContent, "OVERRIDE BY A TRANSFORM"); }); + +test("Test a linter", async t => { + let tmpl = new Template( + "./test/stubs/transform-pages/template.njk", + "./test/stubs/", + "./test/stubs/_site" + ); + + tmpl.addLinter(function(str) { + throw new Error("this is a lint rule"); + }); + + let data = await tmpl.getData(); + try { + await tmpl.getRenderedTemplates(data); + t.fail("Should have errored"); + } catch (e) { + t.pass("Threw an error:" + e); + } +});