Browse files

first commit

  • Loading branch information...
0 parents commit 0a8b823e3083c93158e606277567f41ead009233 @Pita committed May 29, 2011
Showing with 540 additions and 0 deletions.
  1. +3 −0 .npmignore
  2. +13 −0 README.md
  3. +37 −0 exampleDOC/blub/test.md
  4. +44 −0 exampleSRC/blub/test.js
  5. 0 exampleSRC/test
  6. 0 exampleSRC/test2
  7. +87 −0 index.js
  8. +11 −0 package.json
  9. +197 −0 parser.js
  10. +148 −0 writer.js
3 .npmignore
@@ -0,0 +1,3 @@
+exampleSRC
+exampleDOC
+README.md
13 README.md
@@ -0,0 +1,13 @@
+#About
+I created doc.md cause all the jsdoc tools I found were too complex or doesn't do what I wanted. So I decided to create my own jsdoc tool. It creates markdown, this makes it possible to look at the documentation directly in Github.
+
+#Install
+`npm install -g doc.md`
+
+#Usage
+
+doc.md $SRCFOLDER $DESTFOLDER
+
+#LICENSE
+Apache License v2 <http://www.apache.org/licenses/LICENSE-2.0.html>
+
37 exampleDOC/blub/test.md
@@ -0,0 +1,37 @@
+#blub
+`require("./blub/test");`
+
+This is an example module
+
+##Functions
+
+###`test (a, b)`
+This is the first test function
+
+* **a** *(String)* Parameter is text
+* **b** *(Number)* B is a number, its 42
+
+###`test2 (a, b)`
+This is an example module
+
+* **a** *(Number)* a ist 21, the half answer
+* **b** We don't know what b ist
+
+###`test3 (d, k, a)`
+
+* **d**
+* **k**
+* **a**
+
+##Variables
+
+###bla
+bla ist another unimportant variable that we export
+why? cause we can!
+
+###blink
+
+
+###foo *(object)*
+Just a variable
+
44 exampleSRC/blub/test.js
@@ -0,0 +1,44 @@
+/**
+ This is an example module
+*/
+
+/**
+ * This is our second test function
+ * @param b We don't know what b ist
+ * @param a {Number} a ist 21, the half answer
+ * @return {void} nothing
+ * ...
+ */
+exports.test2=function( a, b)
+{
+ console.log("test2");
+}
+
+/**
+ * This is the first test function
+ * @param a {String} Parameter is text
+ * @param b {Number} B is a number, its 42
+ */
+exports.test = function(a,b)
+{
+ console.log("test");
+}
+
+/**
+ * bla ist another unimportant variable that we export
+ * why? cause we can!
+ */
+exports.bla = "content";
+
+/**
+ * Just a variable
+ * @type object
+ */
+exports.foo = {foo: "bar"}
+
+exports.blink = "yeah!";
+
+exports.test3 = function(d ,k , a)
+{
+ console.log("test3");
+}
0 exampleSRC/test
No changes.
0 exampleSRC/test2
No changes.
87 index.js
@@ -0,0 +1,87 @@
+#!/usr/bin/env node
+
+/**
+* 2011 Peter 'Pita' Martischka
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS-IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+var parser = require('./parser');
+var writer = require('./writer');
+var fs = require("fs");
+var path = require("path");
+
+if(process.argv.length != 4)
+{
+ console.error("Usage: doc.md $SRCFOLDER $DESTFOLDER");
+ process.exit(1);
+}
+
+var srcFolder = process.argv[2];
+var destFolder = process.argv[3];
+
+//check src Directory
+var srcValid = false;
+try
+{
+ srcValid = fs.lstatSync(srcFolder).isDirectory();
+} catch(e) {};
+
+if(!srcValid)
+{
+ console.error("'"+srcFolder + "' is no directory!");
+ process.exit(1);
+}
+
+//check dest directory
+var destValid = false;
+try
+{
+ destValid = fs.lstatSync(destFolder).isDirectory();
+} catch(e) {};
+
+if(!destValid)
+{
+ console.error("'"+destFolder + "' is no directory!");
+ process.exit(1);
+}
+
+//start recursive function
+doFolder(srcFolder, ".");
+
+function doFolder(srcFolder, folder)
+{
+ //get the path and files
+ var folderPath = path.normalize(srcFolder + "/" + folder);
+ var files = fs.readdirSync(folderPath);
+
+ //go trough all files in this folder
+ for(var i in files)
+ {
+ var absolutePath = path.normalize(folderPath + "/" + files[i]);
+ var relativePath = path.normalize(folder + "/" + files[i]);
+ var isDirectory = fs.lstatSync(absolutePath).isDirectory();
+
+ //if this is a folder, call function recursively
+ if(isDirectory)
+ {
+ doFolder(srcFolder, relativePath);
+ }
+ //if this is a javascript file, parse it
+ else if(absolutePath.search(/.js$/) != -1)
+ {
+ var parsedObj = parser.parseFile(srcFolder, relativePath);
+ writer.parsedObj2md(destFolder, parsedObj);
+ }
+ }
+}
11 package.json
@@ -0,0 +1,11 @@
+{
+ "name" : "doc.md",
+ "description" : "A simple JSDoc documenation tool that creates markdown for node.js modules",
+ "homepage" : "https://github.com/Pita/doc.md",
+ "keywords" : ["jsdoc", "documenation", "markdown"],
+ "author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com>",
+ "version" : "0.0.1",
+ "bin" : {
+ "doc.md" : "./index.js"
+ }
+}
197 parser.js
@@ -0,0 +1,197 @@
+var fs = require("fs");
+
+/**
+* 2011 Peter 'Pita' Martischka
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS-IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/**
+ * This is the parser, it generates a object out of a javascript file
+ * @param filename, the file you wanna parse
+ */
+exports.parseFile = function(baseFolder, filename)
+{
+ console.error("parse file '" + baseFolder + "/" + filename + "'...");
+
+ var parsedObj = {};
+
+ //get the name of the module
+ var name = filename.substr(filename.lastIndexOf("/")+1);
+ name = filename.substr(0,name.lastIndexOf(".js"));
+ parsedObj.name = name;
+
+ //get the require path
+ var requirePath = "./" + filename.replace(/.js$/,"");
+ parsedObj.path = requirePath;
+
+ //read the file
+ var code = fs.readFileSync(baseFolder + "/" + filename, "utf8");
+
+ //search the comment of the document
+ var docCommentRegExp = /^\s*\/\*\*((.|\n|\r)*?)\*\//m;
+ var match = docCommentRegExp.exec(code);
+ if(match != null)
+ {
+ var docComment = match[1];
+ docComment = docComment.replace(/\n\s*\*\s*/mg, "\n");
+ docComment = trimStr(docComment);
+ parsedObj.comment = docComment;
+ }
+
+ //get all exported functions with a regular expression
+ var functions = [];
+ var functionsRegExp = /exports.([a-zA-Z_$][0-9a-zA-Z_$]*)\s*=\s*function\s*\(([0-9a-zA-Z_$,\s]*)\)*/gm;
+ var match = functionsRegExp.exec(code);
+ while(match != null)
+ {
+ functions.push(match);
+ match = functionsRegExp.exec(code);
+ }
+
+ parsedObj.functions = {};
+
+ //go trough the functions and move all information to the parsedObj
+ for(var i in functions)
+ {
+ //create a entry for the name
+ var functionName = functions[i][1];
+ parsedObj.functions[functionName] = {param: []};
+
+ //get the params
+ var functionParam = functions[i][2].split(",");
+
+ //trim the params and add them to the obj
+ for(var i in functionParam)
+ {
+ var paramName = trimStr(functionParam[i]);
+
+ //parsedObj.functions[functionName].param[paramName] = {};
+ parsedObj.functions[functionName].param.push({name: paramName})
+ }
+ }
+
+ //get all exported variables with a regular expression
+ parsedObj.variables = {};
+ var variableRegExp = /exports.([a-zA-Z_$][0-9a-zA-Z_$]*)\s*=\s*/gm;
+ var match = variableRegExp.exec(code);
+ while(match != null)
+ {
+ var varname = match[1];
+
+ if(!parsedObj.functions[varname])
+ {
+ parsedObj.variables[varname] = {};
+ }
+
+ match = variableRegExp.exec(code);
+ }
+
+ //search all jsdoc blocks in front of a exports variable
+ var jsdocBlocks = {};
+ var blockRegExp = /(\/\*\*(.|\n|\r)*?\*\/)\s*exports\.([a-zA-Z_$][0-9a-zA-Z_$]*)/mg;
+ var match = blockRegExp.exec(code);
+ while(match != null)
+ {
+ jsdocBlocks[match[3]] = match[1];
+ match = blockRegExp.exec(code);
+ }
+
+ //go trough all jsdocblocks
+ for(var i in jsdocBlocks)
+ {
+ //fish all comments out of the jsdoc block
+ var jsdocBlock = jsdocBlocks[i];
+ var type = parsedObj.variables[i] ? "var" : "func";
+ var obj = type == "var" ? parsedObj.variables[i] : parsedObj.functions[i];
+ var commentRegExp = /\/\*\*((.|\n|\r)*?)(@|\*\/)/m;
+ var comment = commentRegExp.exec(jsdocBlock)[1];
+ comment = comment.replace(/\n\s*\*\s*/mg, "\n");
+ comment = trimStr(comment);
+
+ //save the comment
+ obj.comment = comment;
+
+ //search tags in jsdoc block
+ var tagRegExp = /@([a-zA-Z0-9]+)((.|\n|\r)*?)\*\//mg;
+ var jsdocBlockEscapedAt = jsdocBlock.replace(/@/g, "*/@");
+ var match = tagRegExp.exec(jsdocBlockEscapedAt);
+ while(match != null)
+ {
+ var tagType = match[1];
+ var tagText = match[2];
+ tagText = tagText.replace(/\n\s*\*\s*/mg, "\n");
+ tagText = trimStr(tagText);
+
+ //if this is a function param
+ if(tagType == "param" && type == "func")
+ {
+ var paramRegExp = /^([a-zA-Z_$][0-9a-zA-Z_$]*)\s*(\{(.*?)\})?\s*((.|\n|\r)*)/m;
+
+ var match = paramRegExp.exec(tagText);
+
+ var paramName = match[1];
+ var paramType = match[3];
+ var paramComment = match[4];
+
+ var paramNum = -1;
+ for(var i in obj.param)
+ {
+ if(obj.param[i].name == paramName)
+ paramNum = i;
+ }
+
+ if(paramNum == -1)
+ {
+ console.error("WARN: Parameter does not exist in this function! @param " + paramName);
+ }
+ else
+ {
+ obj.param[paramNum].comment = paramComment;
+ obj.param[paramNum].type = paramType;
+ }
+ }
+ //if this is a return tag
+ else if(tagType == "return" && type == "func")
+ {
+ var returnRegExp = /^\s*(\{(.*?)\})?\s*((.|\n|\r)*)/m;
+
+ var match = returnRegExp.exec(tagText);
+
+ var returnType = match[2];
+ var returnComment = match[3];
+
+ obj.return = {type: returnType, comment: returnComment};
+ }
+ else if(tagType == "type" && type == "var")
+ {
+ obj.type = tagText;
+ }
+ else
+ {
+ console.error("WARN: Unknown Tag @"+tagType + ": " + paramComment);
+ }
+
+ match = tagRegExp.exec(jsdocBlockEscapedAt);
+ }
+ }
+
+ console.log("done");
+
+ return parsedObj;
+}
+
+function trimStr(str)
+{
+ return str.replace(/^\s*/, "").replace(/\s*$/,"");
+}
148 writer.js
@@ -0,0 +1,148 @@
+/**
+* 2011 Peter 'Pita' Martischka
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS-IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+var fs = require("fs");
+var path = require("path");
+
+/**
+ * Writes the parsedObject into a markdown file
+ * @param docFolder {String} the destination Folder of the documenation
+ * @param parsedObj {Object} the Parsed Obj
+ */
+exports.parsedObj2md = function(docFolder, parsedObj)
+{
+ var markdownTxt = "";
+
+ //Module name
+ markdownTxt += "#" + parsedObj.name + "\n";
+
+ //Require
+ markdownTxt += "`require(" + JSON.stringify(parsedObj.path) + ");`\n\n";
+
+ //DocumentComment
+ if(parsedObj.comment)
+ markdownTxt += parsedObj.comment + "\n\n";
+
+ //Functions header
+ markdownTxt += "##Functions\n\n";
+
+ //move all functions in an array
+ var funcArray = [];
+ for(var i in parsedObj.functions)
+ {
+ var arrayObj = parsedObj.functions[i];
+ arrayObj.name = i;
+ funcArray.push(arrayObj);
+ }
+
+ //sort that array by function name
+ funcArray.sort(function (a,b)
+ {
+ var sortedArray = [a.name, b.name];
+ sortedArray.sort();
+
+ return sortedArray[0] == a.name ? -1 : 1;
+ });
+
+ //go trough all functions
+ for(var i in funcArray)
+ {
+ //create a array with the names of all parameter
+ var paramArray = [];
+ for(var j in funcArray[i].param)
+ {
+ paramArray.push(funcArray[i].param[j].name);
+ }
+
+ //function header
+ markdownTxt += "###`" + funcArray[i].name + " (" + paramArray.join(", ") + ")`\n";
+
+ //function comment
+ if(funcArray[i].comment)
+ markdownTxt += funcArray[i].comment + "\n";
+
+ markdownTxt += "\n";
+
+ for(var j in funcArray[i].param)
+ {
+ //begining of line and name
+ markdownTxt += "* **" + funcArray[i].param[j].name + "** ";
+
+ if(funcArray[i].param[j].type)
+ markdownTxt += "*(" + funcArray[i].param[j].type + ")* ";
+
+ if(funcArray[i].param[j].comment)
+ markdownTxt += funcArray[i].param[j].comment;
+
+ markdownTxt += "\n";
+ }
+
+ markdownTxt += "\n";
+ }
+
+ //Variables header
+ markdownTxt += "##Variables\n\n";
+
+ //move all variables in an array
+ var varArray = [];
+ for(var i in parsedObj.variables)
+ {
+ var arrayObj = parsedObj.variables[i];
+ arrayObj.name = i;
+ varArray.push(arrayObj);
+ }
+
+ //sort that array by variable name
+ varArray.sort(function (a,b)
+ {
+ var sortedArray = [a.name, b.name];
+ sortedArray.sort();
+
+ return sortedArray[0] == a.name ? -1 : 1;
+ });
+
+ //go trough all variables
+ for(var i in varArray)
+ {
+ markdownTxt += "###" + varArray[i].name + " ";
+
+ if(varArray[i].type)
+ markdownTxt += "*(" + varArray[i].type + ")*";
+
+ markdownTxt += "\n";
+
+ if(varArray[i].comment)
+ markdownTxt += varArray[i].comment;
+
+ markdownTxt += "\n\n";
+ }
+
+ var mdPath = path.normalize(docFolder + "/" + parsedObj.path + ".md");
+ var folder = path.dirname(mdPath);
+
+ //ensure that the folder exists
+ if(!path.existsSync(folder))
+ {
+ fs.mkdirSync(folder, "755");
+ }
+
+ console.log("write file '" + mdPath + "'...");
+
+ //write file
+ fs.writeFileSync(mdPath, markdownTxt, "utf8");
+
+ console.log("done");
+}

0 comments on commit 0a8b823

Please sign in to comment.