Skip to content

Commit fd47f1d

Browse files
committed
some tests working
0 parents  commit fd47f1d

File tree

5 files changed

+402
-0
lines changed

5 files changed

+402
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

.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"

package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "bit-docs-process-tags",
3+
"version": "0.0.1",
4+
"description": "Processes @tags",
5+
"main": "process-tags.js",
6+
"scripts": {
7+
"test": "mocha test.js --reporter spec"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/bit-docs/bit-docs-process-tags.git"
12+
},
13+
"keywords": [
14+
"bit-docs",
15+
"donejs"
16+
],
17+
"author": "Bitovi",
18+
"license": "MIT",
19+
"bugs": {
20+
"url": "https://github.com/bit-docs/bit-docs-process-tags/issues"
21+
},
22+
"homepage": "https://github.com/bit-docs/bit-docs-process-tags#readme",
23+
"dependencies": {
24+
"lodash": "^4.13.1"
25+
},
26+
"devDependencies": {
27+
"mocha": ">= 1.18.0"
28+
}
29+
}

process-tags.js

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
var _ = require("lodash");
2+
3+
var doubleAt = /@@/g,
4+
matchTag = /^\s*@(\w+)/,
5+
matchSpace = /^\s*/;
6+
/**
7+
* @function documentjs.process.comment
8+
* @parent documentjs.process.methods
9+
*
10+
* @signature `documentjs.process.comment(options, callback)`
11+
*
12+
* Processes a comment and produces a docObject.
13+
*
14+
* @param {documentjs.process.processOptions} options An options object that contains
15+
* the code and comment to process.
16+
*
17+
* @param {function(documentjs.process.docObject,documentjs.process.docObject)} callback(newDoc,newScope)
18+
*
19+
* A function that is called back with a docObject created from the code and the scope
20+
* `docObject`. If
21+
* no docObject is created, `newDoc` will be null.
22+
*
23+
* @body
24+
*
25+
* ## Processing rules
26+
*
27+
* The processing rules can be found in the [documentjs.Tag Tag interface].
28+
*/
29+
module.exports = function(options, addDocObjectToDocMap){
30+
31+
var docObject = options.docObject || {},
32+
comment = options.content || options.comment,
33+
docMap = options.docMap,
34+
scope = options.scope,
35+
tags = options.tags || defaultTags;
36+
37+
38+
var i = 0,
39+
lines = typeof comment == 'string' ? comment.split("\n") : comment,
40+
len = lines.length,
41+
// a stack of the tagData and tag
42+
typeDataStack = [],
43+
tagName,
44+
curTag,
45+
// the docData that a th
46+
curTagData,
47+
48+
indentation,
49+
indentationStack = [];
50+
51+
var state = {
52+
defaultWriteProp: undefined,
53+
docObject: docObject,
54+
scope: scope,
55+
docMap: docMap
56+
};
57+
58+
_.defaults(docObject,{
59+
body: "",
60+
description: ""
61+
});
62+
63+
// for each line
64+
for ( var l = 0; l < len; l++ ) {
65+
66+
// see if it starts with something that looks like a @tag
67+
var line = lines[l],
68+
match = line.match(matchTag);
69+
70+
//console.log(">",line, indentationStack.map(function(foo){ return foo.tag.name }) );
71+
72+
// if we have a tag
73+
if ( match ) {
74+
75+
// get the tag object
76+
tagName = match[1].toLowerCase();
77+
curTag = tags[tagName];
78+
79+
indentation = line.match( matchSpace )[0];
80+
81+
// get the current data
82+
curTagData = getFromStack(indentationStack, indentation, state.docObject, curTag && curTag.keepStack);
83+
84+
// if we don't have a tag object
85+
if (!curTag ) {
86+
// do default behavior
87+
tags._default.add.call(state.docObject, line, curTagData, state.scope, docMap, state.defaultWriteProp, options );
88+
continue;
89+
}
90+
91+
// call the tag types add method
92+
try{
93+
curTagData = curTag.add.call(state.docObject, line, curTagData, state.scope, docMap, state.defaultWriteProp, options );
94+
} catch(e){
95+
console.log("ERROR:");
96+
console.log(" tag -", tagName);
97+
console.log(" line-",line);
98+
throw e;
99+
}
100+
101+
if(Array.isArray(curTagData) && typeof curTagData[0] === "string") {
102+
103+
handleCtrl(curTagData, state, indentationStack, addDocObjectToDocMap);
104+
105+
} else if ( curTagData ) {
106+
107+
indentationStack.push({
108+
tag: curTag,
109+
tagData: curTagData,
110+
indentation: indentation
111+
});
112+
113+
} // if no curTag data, it's a single line tag, keep things where they are
114+
115+
}
116+
else {
117+
// we have a normal line
118+
//clean up @@abc becomes @abc
119+
line = line.replace(doubleAt, "@");
120+
121+
var last = _.last(indentationStack);
122+
123+
// if we a lastTag (we are on a multi-line tag)
124+
if ( last && last.tag ) {
125+
// we should probably clean up the line
126+
line = line.replace(last.indentation,"");
127+
128+
last.tag.addMore.call(state.docObject, line, last.tagData, state.scope, docMap);
129+
} else {
130+
// write to the default place
131+
writeToDefault(state, state.docObject, line);
132+
}
133+
}
134+
}
135+
136+
// call end on any tags still left
137+
getFromStack(indentationStack, "", state.docObject);
138+
addDocObjectToDocMap(state.docObject, state.scope);
139+
};
140+
141+
// pop off the stack until indentation matches
142+
var getFromStack = function(indentationStack, indentation, docObject, keepStack ){
143+
if(!keepStack) {
144+
while(indentationStack.length && _.last(indentationStack).indentation >= indentation) {
145+
var top = indentationStack.pop();
146+
if(top.tag && top.tag.end) {
147+
top.tag.end.call(docObject, top.tagData);
148+
}
149+
}
150+
}
151+
return indentationStack.length ? _.last(indentationStack).tagData : docObject;
152+
};
153+
154+
var writeToDefault = function(state, docObject, line) {
155+
if(state.defaultWriteProp){
156+
docObject[state.defaultWriteProp] += line + "\n";
157+
} else {
158+
// if we don't have two newlines, keep adding to description
159+
if( docObject.body ){
160+
docObject.body += line + "\n";
161+
} else if(!docObject.description){
162+
docObject.description += line + "\n";
163+
} else if(!line || /^[\s]/.test( line ) ){
164+
state.defaultWriteProp = "body";
165+
docObject[state.defaultWriteProp] += line + "\n";
166+
} else {
167+
docObject.description += line + "\n";
168+
}
169+
}
170+
};
171+
172+
var handleCtrl = function(curTagData, state, stack, addDocObjectToDocMap){
173+
// depending on curTagData, we do different things:
174+
// if we get ['push',{DATA}], this means we are an
175+
// 'inline' tag, meaning we are going to add
176+
// content to whatever tag we are currently in
177+
// @codestart and @codeend are the best examples of this
178+
var command = curTagData[0];
179+
180+
if ( command == 'push' ) { //
181+
// sets as the current object to add to
182+
stack.push({
183+
tag: lastTag,
184+
tagData: lastTagData,
185+
indentation: ""
186+
});
187+
// set ourselves as the current lastTag and the 2nd
188+
// item in the array as curTagData
189+
curData = curTagData[1];
190+
lastTag = curTag;
191+
}
192+
// if we get ['pop', text],
193+
// add text to the previous parent tag
194+
else if ( command == 'pop' || command == 'poppop' ) {
195+
// get the last tag
196+
var last = stack.pop();
197+
if ( command === 'poppop' ) {
198+
last = stack.pop();
199+
}
200+
// as long as we had a previous tag
201+
if ( last && last.tag ) {
202+
//call the previous tag's addMore
203+
last.tag.addMore.call(state.docObject, curTagData[1], last.tagData);
204+
} else {
205+
// otherwise, add to the default place to write to
206+
state.docObject[state.defaultWriteProp || "body"] += "\n" + curTagData[1]
207+
}
208+
} else if ( command == 'scope') {
209+
// allow the total replacement of docObject for @add
210+
if(curTagData[2]) {
211+
state.docObject = curTagData[2];
212+
}
213+
214+
// might need to change the head of the scope
215+
// curData =
216+
state.scope = curTagData[1];
217+
218+
} else if ( command == 'default' ) {
219+
// if we get ['default',PROPNAME]
220+
// we change default write to prop name
221+
// this will make it so if we aren't in a tag, all default
222+
// lines to to the defaultWriteProp
223+
// this is used by @constructor
224+
state.defaultWriteProp = curTagData[1];
225+
stack.splice(0, stack.length);
226+
} else if( command == 'add') {
227+
// we are adding something docMap
228+
addDocObjectToDocMap(curTagData[1]);
229+
}
230+
};

0 commit comments

Comments
 (0)