From 2ac78cebd0aa5da5e0615f5b7c8dcc7e5abaddb5 Mon Sep 17 00:00:00 2001 From: Mikael Lindqvist Date: Wed, 12 Mar 2014 17:23:01 +0100 Subject: [PATCH 1/9] added preprocessor option --- lib/yuidoc.js | 34 +++++++++- scripts/test.sh | 3 +- tests/input/preprocessor/preprocessortest.js | 5 ++ tests/lib/testpreprocessor.js | 9 +++ tests/preprocessor.js | 67 ++++++++++++++++++++ 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 tests/input/preprocessor/preprocessortest.js create mode 100644 tests/lib/testpreprocessor.js create mode 100644 tests/preprocessor.js diff --git a/lib/yuidoc.js b/lib/yuidoc.js index 3d354047..d28cd90e 100755 --- a/lib/yuidoc.js +++ b/lib/yuidoc.js @@ -43,7 +43,8 @@ YUI.add('yuidoc', function (Y) { version: '0.1.0', paths: [], themedir: path.join(__dirname, 'themes', 'default'), - syntaxtype: 'js' + syntaxtype: 'js', + preprocessor: undefined }; /** @@ -245,8 +246,37 @@ YUI.add('yuidoc', function (Y) { } }, + /** + * Applies preprocessors to the data tree. + * @method applyPreprocessors + * @private + */ + applyPreprocessors: function (data) { + if (this.options.preprocessor) { + var preprocessors = [].concat(this.options.preprocessor); + + for (var p in preprocessors) { + var preprocessor=preprocessors[p]; + + // Check if path is absolute, from: + // http://stackoverflow.com/questions/21698906/how-to-check-if-a-path-is-absolute-or-relative + var preprocessorAbsFile; + if (path.resolve(preprocessor)===preprocessor) + preprocessorAbsFile=preprocessor; + + else + preprocessorAbsFile=path.join(process.cwd(),preprocessor); + + var preprocessorModule=require(preprocessorAbsFile); + + preprocessorModule(data); + } + } + }, + /** * Writes the parser JSON data to disk. + * Applies preprocessors, if any. * @method writeJSON * @param {Object} parser The DocParser instance to use * @private @@ -260,6 +290,8 @@ YUI.add('yuidoc', function (Y) { data = parser.data; + this.applyPreprocessors(data); + data.warnings = parser.warnings; if (self.selleck && self.options.selleck && data.files && data.modules) { diff --git a/scripts/test.sh b/scripts/test.sh index 94ffe494..6839f92a 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -19,7 +19,8 @@ wait ./builder.js \ ./options.js \ ./utils.js \ - ./files.js + ./files.js \ + ./preprocessor.js exit $? diff --git a/tests/input/preprocessor/preprocessortest.js b/tests/input/preprocessor/preprocessortest.js new file mode 100644 index 00000000..2444b634 --- /dev/null +++ b/tests/input/preprocessor/preprocessortest.js @@ -0,0 +1,5 @@ +/** + * This class is for testing the preprocessor option. + * @class TestPreprocessor + * @customtag hello + */ \ No newline at end of file diff --git a/tests/lib/testpreprocessor.js b/tests/lib/testpreprocessor.js new file mode 100644 index 00000000..b30cd792 --- /dev/null +++ b/tests/lib/testpreprocessor.js @@ -0,0 +1,9 @@ +module.exports=function(data) { + global.testPreprocessorCallCount++; + + for (className in data.classes) { + classData=data.classes[className]; + + classData.customtagPlusStar=classData.customtag+"*"; + } +} \ No newline at end of file diff --git a/tests/preprocessor.js b/tests/preprocessor.js new file mode 100644 index 00000000..0823ddb3 --- /dev/null +++ b/tests/preprocessor.js @@ -0,0 +1,67 @@ +/*global Y:true */ +var YUITest = require('yuitest'), + Assert = YUITest.Assert, + path = require('path'), + Y = require(path.join(__dirname, '../', 'lib', 'index')); + +//Move to the test dir before running the tests. +process.chdir(__dirname); + +var suite = new YUITest.TestSuite({ + name: 'Preprocessor Test Suite', + setUp: function () { + process.chdir(__dirname); + } +}); + +suite.add(new YUITest.TestCase({ + name: "Preprocessor", + 'test: single preprocessor': function () { + global.testPreprocessorCallCount=0; + + var json = (new Y.YUIDoc({ + quiet: true, + paths: ['input/preprocessor'], + outdir: './out', + preprocessor: 'lib/testpreprocessor.js' + })).run(); + + Assert.areSame(global.testPreprocessorCallCount,1,"the preprocessor was not called"); + }, + 'test: single preprocessor with absolute path': function () { + global.testPreprocessorCallCount=0; + + var json = (new Y.YUIDoc({ + quiet: true, + paths: ['input/preprocessor'], + outdir: './out', + preprocessor: path.join(process.cwd(),'lib/testpreprocessor.js') + })).run(); + + Assert.areSame(global.testPreprocessorCallCount,1,"the preprocessor was not called when an absolute path was used"); + }, + 'test: several preprocessors': function () { + global.testPreprocessorCallCount=0; + + var json = (new Y.YUIDoc({ + quiet: true, + paths: ['input/preprocessor'], + outdir: './out', + preprocessor: ['lib/testpreprocessor.js','./lib/testpreprocessor'] + })).run(); + + Assert.areSame(global.testPreprocessorCallCount,2,"the preprocessor was not called twice"); + }, + 'test: the test preprocessor does its job': function () { + var json = (new Y.YUIDoc({ + quiet: true, + paths: ['input/preprocessor'], + outdir: './out', + preprocessor: 'lib/testpreprocessor.js' + })).run(); + + Assert.areSame(json.classes.TestPreprocessor.customtagPlusStar,"hello*","the preprocessor did not modify the data"); + } +})); + +YUITest.TestRunner.add(suite); From 83d19eabacccb451909d9572650c2da00918fcf8 Mon Sep 17 00:00:00 2001 From: Mikael Lindqvist Date: Wed, 12 Mar 2014 17:25:09 +0100 Subject: [PATCH 2/9] added newlines at end of file --- tests/input/preprocessor/preprocessortest.js | 3 ++- tests/lib/testpreprocessor.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/input/preprocessor/preprocessortest.js b/tests/input/preprocessor/preprocessortest.js index 2444b634..f622cb19 100644 --- a/tests/input/preprocessor/preprocessortest.js +++ b/tests/input/preprocessor/preprocessortest.js @@ -2,4 +2,5 @@ * This class is for testing the preprocessor option. * @class TestPreprocessor * @customtag hello - */ \ No newline at end of file + */ + \ No newline at end of file diff --git a/tests/lib/testpreprocessor.js b/tests/lib/testpreprocessor.js index b30cd792..d3d350f5 100644 --- a/tests/lib/testpreprocessor.js +++ b/tests/lib/testpreprocessor.js @@ -6,4 +6,4 @@ module.exports=function(data) { classData.customtagPlusStar=classData.customtag+"*"; } -} \ No newline at end of file +} From bb2f846a6b9402f5c24f233fb993cf94b93e787d Mon Sep 17 00:00:00 2001 From: Mikael Lindqvist Date: Wed, 12 Mar 2014 17:26:03 +0100 Subject: [PATCH 3/9] newline at end of file, 2nd try --- tests/input/preprocessor/preprocessortest.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/input/preprocessor/preprocessortest.js b/tests/input/preprocessor/preprocessortest.js index f622cb19..314fec3c 100644 --- a/tests/input/preprocessor/preprocessortest.js +++ b/tests/input/preprocessor/preprocessortest.js @@ -3,4 +3,3 @@ * @class TestPreprocessor * @customtag hello */ - \ No newline at end of file From 805df220ccba1e1f36ae0a09517d9ffb2154bee4 Mon Sep 17 00:00:00 2001 From: Mikael Lindqvist Date: Wed, 12 Mar 2014 18:52:03 +0100 Subject: [PATCH 4/9] keep jshint happy and enable preprocessor tests for "npm test" --- lib/yuidoc.js | 19 +++++++++++-------- package.json | 2 +- tests/preprocessor.js | 6 +++++- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/yuidoc.js b/lib/yuidoc.js index d28cd90e..c98432d9 100755 --- a/lib/yuidoc.js +++ b/lib/yuidoc.js @@ -252,23 +252,26 @@ YUI.add('yuidoc', function (Y) { * @private */ applyPreprocessors: function (data) { + var preprocessors, preprocessor, p, + preprocessorAbsFile, preprocessorModule; + if (this.options.preprocessor) { - var preprocessors = [].concat(this.options.preprocessor); + preprocessors = [].concat(this.options.preprocessor); - for (var p in preprocessors) { - var preprocessor=preprocessors[p]; + for (p=0; p Date: Sun, 30 Mar 2014 13:08:05 +0200 Subject: [PATCH 5/9] let the preprocessor(s) see warnings to potentially act on them. --- lib/yuidoc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/yuidoc.js b/lib/yuidoc.js index c98432d9..364ae51c 100755 --- a/lib/yuidoc.js +++ b/lib/yuidoc.js @@ -293,10 +293,10 @@ YUI.add('yuidoc', function (Y) { data = parser.data; - this.applyPreprocessors(data); - data.warnings = parser.warnings; + this.applyPreprocessors(data); + if (self.selleck && self.options.selleck && data.files && data.modules) { Object.keys(self.selleck).forEach(function (file) { Object.keys(data.files).forEach(function (f) { From de5762d1fdbc19f5af48c7f4e19df40752c130cf Mon Sep 17 00:00:00 2001 From: Mikael Lindqvist Date: Sun, 30 Mar 2014 13:25:16 +0200 Subject: [PATCH 6/9] don't define an undefined value --- lib/yuidoc.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/yuidoc.js b/lib/yuidoc.js index 364ae51c..e031f992 100755 --- a/lib/yuidoc.js +++ b/lib/yuidoc.js @@ -43,8 +43,7 @@ YUI.add('yuidoc', function (Y) { version: '0.1.0', paths: [], themedir: path.join(__dirname, 'themes', 'default'), - syntaxtype: 'js', - preprocessor: undefined + syntaxtype: 'js' }; /** From 3d19af818b6cff5e03254a36a2c6807dab4bd668 Mon Sep 17 00:00:00 2001 From: Mikael Lindqvist Date: Sun, 30 Mar 2014 13:45:04 +0200 Subject: [PATCH 7/9] code cleanup and comments added --- lib/yuidoc.js | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/lib/yuidoc.js b/lib/yuidoc.js index e031f992..073c3de9 100755 --- a/lib/yuidoc.js +++ b/lib/yuidoc.js @@ -251,28 +251,21 @@ YUI.add('yuidoc', function (Y) { * @private */ applyPreprocessors: function (data) { - var preprocessors, preprocessor, p, - preprocessorAbsFile, preprocessorModule; + var preprocessors, + preprocessorsRelativeTo; + + // If the preprocessor paths are relative they will be searched for relative + // to the process working directory. This is consistent with how other paths + // are treated by yuidoc, such as the config options 'paths' and 'outdir'. + preprocessorsRelativeTo = process.cwd(); if (this.options.preprocessor) { preprocessors = [].concat(this.options.preprocessor); - for (p=0; p Date: Fri, 18 Apr 2014 12:40:36 +0200 Subject: [PATCH 8/9] * load preprocessors as standard npm modules, in addition to searching relative to config file. * return data when applying preprocessors rather than mutate the data in place. * pass config options to preprocessors. --- lib/yuidoc.js | 39 +++++++++++++------ tests/lib/testpreprocessor.js | 9 ++++- tests/lib/testpreprocessormodule/package.json | 3 ++ .../testpreprocessormodule.js | 3 ++ tests/preprocessor.js | 36 +++++++++++++++-- 5 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 tests/lib/testpreprocessormodule/package.json create mode 100644 tests/lib/testpreprocessormodule/testpreprocessormodule.js diff --git a/lib/yuidoc.js b/lib/yuidoc.js index 073c3de9..80519338 100755 --- a/lib/yuidoc.js +++ b/lib/yuidoc.js @@ -246,27 +246,42 @@ YUI.add('yuidoc', function (Y) { }, /** - * Applies preprocessors to the data tree. - * @method applyPreprocessors + * Applies preprocessors to the data tree. + * This function first clones the data and operates on the clone. + * @method runPreprocessors * @private + * @return {Object} The mutated data */ - applyPreprocessors: function (data) { - var preprocessors, + runPreprocessors: function (data) { + var self = this, + preprocessors, preprocessorsRelativeTo; - // If the preprocessor paths are relative they will be searched for relative - // to the process working directory. This is consistent with how other paths - // are treated by yuidoc, such as the config options 'paths' and 'outdir'. + // We will try to load the preprocessors as npm modules, but we will also + // search for them relative to the process working directory. + // The latter is consistent with how other paths are treated by yuidoc, + // such as the config options 'paths' and 'outdir'. preprocessorsRelativeTo = process.cwd(); - if (this.options.preprocessor) { - preprocessors = [].concat(this.options.preprocessor); + if (self.options.preprocessor) { + data=JSON.parse(JSON.stringify(data)); + + preprocessors = [].concat(self.options.preprocessor); preprocessors.forEach(function (preprocessor) { - var preprocessorModule = require(path.resolve(preprocessorsRelativeTo, preprocessor)); - preprocessorModule(data); + var preprocessorModule; + + try { + preprocessorModule = require(preprocessor); + } catch (e) { + preprocessorModule = require(path.resolve(preprocessorsRelativeTo, preprocessor)); + } + + preprocessorModule(data, self.options); }); } + + return data; }, /** @@ -287,7 +302,7 @@ YUI.add('yuidoc', function (Y) { data.warnings = parser.warnings; - this.applyPreprocessors(data); + data = this.runPreprocessors(data); if (self.selleck && self.options.selleck && data.files && data.modules) { Object.keys(self.selleck).forEach(function (file) { diff --git a/tests/lib/testpreprocessor.js b/tests/lib/testpreprocessor.js index d3d350f5..09bbf011 100644 --- a/tests/lib/testpreprocessor.js +++ b/tests/lib/testpreprocessor.js @@ -1,9 +1,14 @@ -module.exports=function(data) { +module.exports=function(data, options) { + var star="*"; + + if (options.star) + star=options.star; + global.testPreprocessorCallCount++; for (className in data.classes) { classData=data.classes[className]; - classData.customtagPlusStar=classData.customtag+"*"; + classData.customtagPlusStar=classData.customtag+star; } } diff --git a/tests/lib/testpreprocessormodule/package.json b/tests/lib/testpreprocessormodule/package.json new file mode 100644 index 00000000..8ea47800 --- /dev/null +++ b/tests/lib/testpreprocessormodule/package.json @@ -0,0 +1,3 @@ +{ + "main": "./testpreprocessormodule.js" +} \ No newline at end of file diff --git a/tests/lib/testpreprocessormodule/testpreprocessormodule.js b/tests/lib/testpreprocessormodule/testpreprocessormodule.js new file mode 100644 index 00000000..a25528b9 --- /dev/null +++ b/tests/lib/testpreprocessormodule/testpreprocessormodule.js @@ -0,0 +1,3 @@ +module.exports=function(data) { + data.testModuleWasHere=true; +} \ No newline at end of file diff --git a/tests/preprocessor.js b/tests/preprocessor.js index 5cc415ba..ab78ea68 100644 --- a/tests/preprocessor.js +++ b/tests/preprocessor.js @@ -2,6 +2,7 @@ var YUITest = require('yuitest'), Assert = YUITest.Assert, path = require('path'), + fs = require('fs'), Y = require(path.join(__dirname, '../', 'lib', 'index')); //Move to the test dir before running the tests. @@ -36,7 +37,7 @@ suite.add(new YUITest.TestCase({ quiet: true, paths: ['input/preprocessor'], outdir: './out', - preprocessor: path.join(process.cwd(),'lib/testpreprocessor.js') + preprocessor: path.join(process.cwd(),'/lib/testpreprocessor.js') })).run(); Assert.isObject(json); @@ -60,11 +61,40 @@ suite.add(new YUITest.TestCase({ quiet: true, paths: ['input/preprocessor'], outdir: './out', - preprocessor: 'lib/testpreprocessor.js' + preprocessor: 'lib/testpreprocessor.js', + star: "#" })).run(); Assert.isObject(json); - Assert.areSame(json.classes.TestPreprocessor.customtagPlusStar,"hello*","the preprocessor did not modify the data"); + Assert.areSame(json.classes.TestPreprocessor.customtagPlusStar,"hello#","the preprocessor did not modify the data"); + }, + 'test: load preprocessor as a npm module': function () { + // We are testing if it works to load the preprocessor from node_modules, + // so first we need to copy it in place. + if (!fs.existsSync("../node_modules/testpreprocessormodule")) { + fs.mkdirSync("../node_modules/testpreprocessormodule"); + } + + fs.writeFileSync("../node_modules/testpreprocessormodule/package.json", + fs.readFileSync("lib/testpreprocessormodule/package.json")); + + fs.writeFileSync("../node_modules/testpreprocessormodule/testpreprocessormodule.js", + fs.readFileSync("lib/testpreprocessormodule/testpreprocessormodule.js")); + + var json = (new Y.YUIDoc({ + quiet: true, + paths: ['input/preprocessor'], + outdir: './out', + preprocessor: 'testpreprocessormodule' + })).run(); + + Assert.isObject(json); + Assert.isTrue(json.testModuleWasHere,"the preprocesor module was not run"); + + // Clean up things when we are done. + fs.unlinkSync("../node_modules/testpreprocessormodule/package.json"); + fs.unlinkSync("../node_modules/testpreprocessormodule/testpreprocessormodule.js"); + fs.rmdirSync("../node_modules/testpreprocessormodule"); } })); From 64b2acc1b4382297c1f8e657a6f565755ddf8907 Mon Sep 17 00:00:00 2001 From: Mikael Lindqvist Date: Fri, 18 Apr 2014 12:46:24 +0200 Subject: [PATCH 9/9] newlines at end of files --- tests/lib/testpreprocessormodule/package.json | 2 +- tests/lib/testpreprocessormodule/testpreprocessormodule.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/lib/testpreprocessormodule/package.json b/tests/lib/testpreprocessormodule/package.json index 8ea47800..e00fa501 100644 --- a/tests/lib/testpreprocessormodule/package.json +++ b/tests/lib/testpreprocessormodule/package.json @@ -1,3 +1,3 @@ { "main": "./testpreprocessormodule.js" -} \ No newline at end of file +} diff --git a/tests/lib/testpreprocessormodule/testpreprocessormodule.js b/tests/lib/testpreprocessormodule/testpreprocessormodule.js index a25528b9..001e814c 100644 --- a/tests/lib/testpreprocessormodule/testpreprocessormodule.js +++ b/tests/lib/testpreprocessormodule/testpreprocessormodule.js @@ -1,3 +1,3 @@ module.exports=function(data) { data.testModuleWasHere=true; -} \ No newline at end of file +}