Skip to content

Commit 0aecf7e

Browse files
committed
process js
1 parent f9720b3 commit 0aecf7e

32 files changed

+1269
-222
lines changed

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
language: node_js
2+
node_js: node
3+
before_install:
4+
- "export DISPLAY=:99.0"
5+
- "sh -e /etc/init.d/xvfb start"

bit-docs.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var tags = require("./tags/tags");
2+
var processJavaScript = require("./process/javascript");
3+
module.exports = function(bitDocs){
4+
// register your tags
5+
bitDocs.register("tags", tags);
6+
bitDocs.register("process", processJavaScript);
7+
8+
var dependencies = {},
9+
pack = require("./package.json");
10+
dependencies[pack.name] = pack.version;
11+
12+
bitDocs.register("html", {
13+
dependencies: dependencies,
14+
templates: __dirname+"/templates"
15+
});
16+
17+
});

lib/updateNameAndParentWithScope.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var slashOrDot = /[\.\/]/;
2+
var getParent = require("bit-docs-process-tags/get-parent");
3+
4+
module.exports = function(docObject, scope, docMap){
5+
if(scope && docMap && scope !== docObject && !slashOrDot.test( docObject.name ) ) {
6+
7+
var parentAndName = getParent.andName({
8+
parents: "*",
9+
useName: ["constructor","static","prototype","add","module"],
10+
scope: scope,
11+
docMap: docMap,
12+
name: docObject.name
13+
});
14+
if(!docObject.parent) {
15+
docObject.parent = parentAndName.parent;
16+
}
17+
18+
docObject.name = parentAndName.name;
19+
}
20+
};

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,13 @@
1919
"bugs": {
2020
"url": "https://github.com/bit-docs/bit-docs-js/issues"
2121
},
22-
"homepage": "https://github.com/bit-docs/bit-docs-js#readme"
22+
"homepage": "https://github.com/bit-docs/bit-docs-js#readme",
23+
"dependencies": {
24+
"bit-docs-process-tags": "^0.0.3",
25+
"bit-docs-type-annotate": "^0.0.1",
26+
"lodash": "^4.13.1"
27+
},
28+
"devDependencies": {
29+
"mocha": ">= 1.18.0"
30+
}
2331
}

process/clean_indent.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
var spaceReg = /\S/g;
2+
3+
module.exports = function cleanIndent(lines) {
4+
// first calculate the amount of space to remove
5+
// and get lines starting with text content
6+
var removeSpace = Infinity,
7+
match, contentLines = [],
8+
hasContent = false,
9+
line, l;
10+
11+
spaceReg.lastIndex = 0;
12+
// for each line
13+
for (l = 0; l < lines.length; l++) {
14+
line = lines[l];
15+
// test if it has something other than a space
16+
match = spaceReg.exec(line);
17+
// if it does, and it's less than our current maximum
18+
if (match && line && spaceReg.lastIndex < removeSpace) {
19+
// update our current maximum
20+
removeSpace = spaceReg.lastIndex;
21+
// mark as starting to have content
22+
hasContent = true;
23+
}
24+
// if we have content now, add to contentLines
25+
if (hasContent) {
26+
contentLines.push(line);
27+
}
28+
// update the regexp position
29+
spaceReg.lastIndex = 0;
30+
}
31+
// remove from the position before the last char
32+
removeSpace = removeSpace - 1;
33+
34+
// go through content lines and remove the removeSpace
35+
if (isFinite(removeSpace) && removeSpace !== 0) {
36+
for (l = 0; l < contentLines.length; l++) {
37+
contentLines[l] = contentLines[l].substr(removeSpace);
38+
}
39+
}
40+
return contentLines;
41+
};

process/code.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
var _ = require("lodash");
2+
/**
3+
* @function documentjs.process.code
4+
* @parent documentjs.process.methods
5+
*
6+
* Process a code hint into properties on a `docObject`.
7+
*
8+
* @signature `documentjs.process.code(options, callback)`
9+
*
10+
* Using the `options.code`, and `options.tags`, processes the code
11+
* into properties on a docObject. The `callback` is called with the new docObject.
12+
*
13+
* @param {documentjs.process.processOptions} options An options object that contains
14+
* the code to process.
15+
*
16+
* @param {function(documentjs.process.docObject,documentjs.process.docObject)} callback(newDoc,newScope)
17+
*
18+
* A function that is called back with a docObject created from the code and the scope
19+
* `docObject`. If
20+
* no docObject is created, `newDoc` will be null.
21+
*
22+
* @body
23+
*
24+
* ## Use
25+
*
26+
* documentjs.process.code(
27+
* {code: "foo: function(){"},
28+
* function(newDoc){
29+
* newDoc.type //-> "function"
30+
* }
31+
* )
32+
*/
33+
module.exports = function(options, callback){
34+
var tag = guessTag(options.tags, options.code, options.docObject && options.docObject.type, options.scope),
35+
docObject;
36+
if(tag){
37+
docObject = tag.code(options.code, options.scope, options.docMap);
38+
}
39+
if(docObject && options.docObject) {
40+
_.defaults(docObject, options.docObject);
41+
}
42+
callback(docObject, docObject && tag.codeScope ? docObject : options.scope);
43+
};
44+
45+
var guessTag = function( tags, code, firstGuess, scope ) {
46+
var matches = function(tag, code){
47+
if ( tags[tag] &&
48+
tags[tag].codeMatch &&
49+
(typeof tags[tag].codeMatch == 'function' ?
50+
tags[tag].codeMatch(code) :
51+
tags[tag].codeMatch.test(code) ) ) {
52+
return tags[tag];
53+
}
54+
},
55+
res;
56+
57+
58+
if(firstGuess && (res = matches(firstGuess,code))){
59+
return res
60+
}
61+
// if the scope is static or prototype, favor function
62+
if(scope && /static|prototype/.test(scope.type) && (res = matches('function',code)) ){
63+
return res;
64+
}
65+
66+
for ( var type in tags ) {
67+
if( res = matches(type,code)) {
68+
return tags[type];
69+
}
70+
}
71+
72+
return null;
73+
};

process/code_and_comment.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
var processCode = require("./code"),
2+
processTags = require("bit-docs-process-tags");
3+
4+
var typeCheckReg = /^\s*@(\w+)/;
5+
/**
6+
* @function documentjs.process.codeAndComment
7+
* @parent documentjs.process.methods
8+
*
9+
* @signature `documentjs.process.codeAndComment(options, callback)`
10+
*
11+
* Processes a code suggestion and then a comment and produces a docObject.
12+
*
13+
* @param {documentjs.process.processOptions} options An options object that contains
14+
* the code and comment to process.
15+
*
16+
* @param {function(documentjs.process.docObject,documentjs.process.docObject)} callback(newDoc,newScope)
17+
*
18+
* A function that is called back with a docObject created from the code and the scope
19+
* `docObject`. If
20+
* no docObject is created, `newDoc` will be null.
21+
*
22+
* @option newDoc the new documentation object
23+
* @option newScope the new scope
24+
*/
25+
module.exports = function(options, callback){
26+
var self = this,
27+
comment = options.comment;
28+
29+
var firstLine = (typeof comment == 'string' ? comment : comment[0]) || "",
30+
check = firstLine.match(typeCheckReg);
31+
32+
if(check){
33+
if(!options.docObject){
34+
options.docObject = {};
35+
}
36+
options.docObject.type = check[1].toLowerCase();
37+
}
38+
39+
if(options.code){
40+
processCode(options, function(newDoc, newScope){
41+
processTags({
42+
comment: options.comment,
43+
scope: newScope || options.scope,
44+
docMap: options.docMap,
45+
docObject: newDoc || options.docObject || {},
46+
tags: options.tags || {}
47+
}, function(newDoc, newScope){
48+
callback(newDoc, newScope);
49+
});
50+
51+
52+
});
53+
} else {
54+
processTags({
55+
comment: options.comment,
56+
scope: options.scope,
57+
docMap: options.docMap,
58+
docObject: {},
59+
tags: options.tags || {}
60+
}, function(newDoc, newScope){
61+
callback(newDoc, newScope);
62+
});
63+
}
64+
};

process/code_test.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
var processCode = require("./code"),
2+
propertyTag = require("./test_property_tag"),
3+
assert = require("assert");
4+
5+
describe("code", function(){
6+
7+
it("basics",function(){
8+
var tags = {
9+
constructor: {
10+
codeMatch: /some constructor/,
11+
code: function(code, scope, objects){
12+
return {
13+
type: "constructor",
14+
name: "Bar"
15+
};
16+
},
17+
codeScope: true
18+
},
19+
property: propertyTag
20+
};
21+
var docMap = {Foo: {name: "Foo",type: "constructor"}};
22+
processCode({
23+
code: "some constructor",
24+
docMap: docMap,
25+
scope: docMap.Foo,
26+
tags: tags
27+
}, function(constructorDoc, constructorScope){
28+
assert.equal(constructorDoc, constructorScope, "scope is the constructor");
29+
30+
processCode({
31+
code: "prop = 'something'",
32+
scope: constructorScope,
33+
docMap: docMap,
34+
tags: tags
35+
}, function(propDoc, propScope){
36+
assert.equal(propScope, constructorScope, "prop doesn't change scope");
37+
assert.equal(propDoc.name,"Bar.prop");
38+
assert.equal(propDoc.parent,"Bar");
39+
40+
});
41+
42+
});
43+
});
44+
45+
});

process/get_comments.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
2+
var multiLineCommentReg = /(?:\/\*\*((?:[^*]|(?:\*+[^*\/]))*)\*+\/)/g;
3+
4+
var commentReg = /\r?\n(?:\s*\*+)?/g;
5+
6+
var nextCodeLineReg = /[^\w\{\(\["'\$]*([^\r\n]*)/g,
7+
startsWithComment = /^\s*\/\*/;
8+
9+
var cleanIndent = require("./clean_indent");
10+
11+
module.exports = function getComments(source) {
12+
var start = new Date;
13+
//var source = source.replace('\r\n','\n')
14+
var comments = [],
15+
match,
16+
getLine = lineNumber(source),
17+
nextCodeLineMatch,
18+
nextCodeLine,
19+
code;
20+
21+
multiLineCommentReg.lastIndex = 0;
22+
23+
24+
while (match = multiLineCommentReg.exec(source)) {
25+
26+
27+
var origComment = match[1],
28+
lines = cleanIndent( origComment.replace(commentReg, '\n').split("\n") ),
29+
lastIndex = multiLineCommentReg.lastIndex;
30+
31+
nextCodeLineReg.lastIndex = lastIndex;
32+
nextCodeLineMatch = nextCodeLineReg.exec(source);;
33+
34+
if(nextCodeLineMatch) {
35+
36+
if(startsWithComment.test( nextCodeLineMatch[0] ) ) {
37+
code = '';
38+
} else {
39+
code = nextCodeLineMatch[1];
40+
}
41+
} else {
42+
code = '';
43+
}
44+
var docObject = {
45+
comment: lines,
46+
code: code,
47+
line: getLine(lastIndex - match[0].length)
48+
};
49+
if(code) {
50+
docObject.codeLine = getLine(nextCodeLineReg.lastIndex);
51+
}
52+
comments.push(docObject);
53+
}
54+
return comments;
55+
};
56+
57+
58+
function lineNumber(source) {
59+
60+
var curLine = 0,
61+
curIndex, lines, len;
62+
63+
64+
return function (index) {
65+
if (!lines) {
66+
lines = source.split('\n');
67+
curIndex = lines[0].length + 1;
68+
len = lines.length;
69+
}
70+
// if we haven't already, split the
71+
if (index < curIndex) {
72+
return curLine;
73+
}
74+
curLine++;
75+
while (curLine < len && (curIndex += lines[curLine].length + 1) <= index) {
76+
curLine++;
77+
}
78+
return curLine;
79+
};
80+
81+
};

process/get_comments_test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
var getComments = require("./get_comments");
3+
var assert = require("assert");
4+
var fs = require("fs");
5+
var path = require("path");
6+
7+
describe("getComments", function(){
8+
9+
it("able to get a comment directly after another comment (#62)", function(done){
10+
fs.readFile(path.join(__dirname,"test","comment_after_comment.js"), function(err, data){
11+
if(err) {
12+
return done(err);
13+
}
14+
var result = getComments(""+data);
15+
assert.deepEqual([
16+
{ comment: ["a",""], code: "", line: 0},
17+
{ comment: ["b",""], code: "", line: 3},
18+
{ comment: ["c "], code: "", line: 6},
19+
{ comment: ["d",""], code: 'foo = "bar";', line: 8, codeLine: 11},
20+
{ comment: ["e",""], code: '', line: 12}
21+
], result);
22+
done();
23+
});
24+
25+
});
26+
27+
});

0 commit comments

Comments
 (0)