Skip to content

Commit 9c4f701

Browse files
committed
Add basics for signature template
1 parent 46cfd2e commit 9c4f701

File tree

2 files changed

+413
-99
lines changed

2 files changed

+413
-99
lines changed

templates/helpers.js

Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
var fs = require("fs");
2+
var path = require("path");
3+
var escapeHTML = require("escape-html");
4+
var unescapeHTML = require("unescape-html");
5+
6+
module.exports = function (docMap, options, getCurrent, helpers, OtherHandlebars) {
7+
// create children lookup
8+
var childrenMap = makeChildrenMap(docMap);
9+
10+
var docMapInfo = new DocMapInfo(docMap, getCurrent);
11+
12+
return {
13+
"makeSignature": function (code) {
14+
if (code) {
15+
return escapeHTML(code);
16+
}
17+
18+
var sig = "";
19+
if (this.type === "module") {
20+
sig = "__" + this.name + "__ ";
21+
}
22+
if (this.types) {
23+
return sig + helpers.makeTypes(this.types);
24+
}
25+
26+
if (! /function|constructor/i.test(this.type) && !this.params && !this.returns) {
27+
return sig + helpers.makeType(this);
28+
}
29+
30+
// if it's a constructor add new
31+
if (this.type === "constructor") {
32+
sig += "new ";
33+
}
34+
35+
// get the name part right
36+
var parent = docMap[this.parent];
37+
if (parent) {
38+
if (parent.type == "prototype") {
39+
var parentParent = docMap[parent.parent];
40+
sig += (parentParent.alias || (lastPartOfName(parentParent.name) + ".")).toLowerCase();
41+
42+
} else {
43+
sig += (parent.alias || lastPartOfName(parent.name) + ".");
44+
}
45+
46+
sig += (lastPartOfName(this.name) || "function");
47+
} else {
48+
sig += "function";
49+
}
50+
51+
sig += "(" + helpers.makeParamsString(this.params) + ")";
52+
53+
return sig;
54+
},
55+
"makeParams": function () {
56+
var result = "<b>" + this.name + "</b>";
57+
if (this.types) {
58+
result += " <code>" + helpers.makeTypesString(this.types) + "</code>";
59+
}
60+
return result;
61+
},
62+
makeReturn: function () {
63+
if (this.types) {
64+
return " <code>" + helpers.makeTypesString(this.types) + "</code>";
65+
}
66+
},
67+
makeTypesString: function (types) {
68+
if (types && types.length) {
69+
var txt = "{" + helpers.makeTypes(types);
70+
return txt + "}";
71+
} else {
72+
return '';
73+
}
74+
},
75+
makeTypes: function (types) {
76+
if (types.length) {
77+
// turns [{type: 'Object'}, {type: 'String'}] into '{Object | String}'
78+
return types.map(helpers.makeType).join('|');
79+
} else {
80+
return '';
81+
}
82+
},
83+
makeType: function (t) {
84+
if (t.type === "function") {
85+
var fn = t.params && t.params.length ?
86+
"(" + helpers.makeParamsString(t.params) + ")" : "";
87+
88+
if (t.constructs && t.constructs.types) {
89+
fn = "constructor" + fn;
90+
fn += " => " + helpers.makeTypes(t.constructs.types);
91+
} else {
92+
fn = "function" + fn;
93+
}
94+
95+
return fn;
96+
}
97+
98+
var type = docMap[t.type];
99+
var title = type && type.title || undefined;
100+
var txt = helpers.linkTo(t.type, title);
101+
var params;
102+
103+
if (t.template && t.template.length) {
104+
txt += "&lt;" + t.template.map(function (templateItem) {
105+
return helpers.makeTypes(templateItem.types);
106+
}).join(",") + "&gt;";
107+
}
108+
109+
if (type) {
110+
if (type.type === "function" && (type.params || type.signatures)) {
111+
params = type.params || (type.signatures[0] && type.signatures[0].params) || [];
112+
} else if (type.type === "typedef" && type.types && type.types[0] && type.types[0].type == "function") {
113+
params = type.types[0].params;
114+
}
115+
if (params) {
116+
txt += "(" + helpers.makeParamsString(params) + ")";
117+
}
118+
}
119+
120+
return txt;
121+
},
122+
makeParamsString: function (params) {
123+
if (!params || !params.length) {
124+
return "";
125+
}
126+
127+
return params.map(function (param) {
128+
// try to look up the title
129+
var type = param.types && param.types[0] && param.types[0].type;
130+
return helpers.linkTo(type, param.name) +
131+
(param.variable ? "..." : "");
132+
}).join(", ");
133+
},
134+
};
135+
};
136+
137+
var DocMapInfo = function (docMap, getCurrent) {
138+
this.docMap = docMap;
139+
this.childrenMap = makeChildrenMap(docMap);
140+
this.getCurrent = getCurrent;
141+
};
142+
143+
DocMapInfo.prototype.isCurrent = function (docObject) {
144+
return docObject.name === this.getCurrent().name;
145+
};
146+
147+
DocMapInfo.prototype.hasCurrent = function (docObject) {
148+
var parents = this.getParents(this.getCurrent());
149+
parents.push(this.getCurrent());
150+
151+
var itemMap = {};
152+
153+
parents.forEach(function (docObject) {
154+
itemMap[docObject.name] = true;
155+
});
156+
157+
return itemMap[docObject.name];
158+
};
159+
160+
DocMapInfo.prototype.hasOrIsCurrent = function (docObject) {
161+
return this.isCurrent(docObject) || this.hasCurrent(docObject);
162+
};
163+
164+
DocMapInfo.prototype.getParents = function (docObject, cb) {
165+
var names = {};
166+
167+
// walk up parents until you don't have a parent
168+
var parent = this.docMap[docObject.parent];
169+
var parents = [];
170+
171+
if (!parent) {
172+
return [];
173+
}
174+
175+
// don't allow things that are their own parent
176+
if (parent.parent === docObject.name) {
177+
return parents;
178+
}
179+
180+
while (parent) {
181+
if (cb) {
182+
cb(parent);
183+
}
184+
185+
parents.unshift(parent);
186+
187+
if (names[parent.name]) {
188+
return parents;
189+
}
190+
191+
names[parent.name] = true;
192+
parent = this.docMap[parent.parent];
193+
}
194+
return parents;
195+
};
196+
197+
DocMapInfo.prototype.getTitle = function (docObject) {
198+
return docObject.title || docObject.name;
199+
};
200+
201+
function getShortTitle(name, parent) {
202+
if (parent && (parent.type === "module" || parent.type === "group")) {
203+
var modletName = path.dirname(parent.name);
204+
var moduleName = path.basename(parent.name);
205+
206+
if (name.indexOf(parent.name + "/") === 0) {
207+
name = name.replace(parent.name + "/", "./");
208+
}
209+
// can-util/dom/events/attributes/attributes's parent is can-util/dom/events/events
210+
else if (moduleName && modletName.endsWith(moduleName) && name.indexOf(modletName + "/") === 0) {
211+
name = name.replace(modletName + "/", "./");
212+
}
213+
else {
214+
return;
215+
}
216+
217+
var basename = path.basename(name);
218+
if (name.endsWith("/" + basename + "/" + basename)) {
219+
return path.dirname(name) + "/";
220+
} else {
221+
return name;
222+
}
223+
}
224+
}
225+
226+
DocMapInfo.prototype.getShortTitle = function (docObject) {
227+
if (docObject.type === "module") {
228+
var parents = this.getParents(docObject).reverse();
229+
230+
var parentModule = parents.find(function (docObject) {
231+
return docObject.type === "module";
232+
});
233+
var parentGroup = parents[0] && parents[0].type === "group" && parents[0];
234+
235+
var name = docObject.name,
236+
shortTitle;
237+
238+
if (parentGroup) {
239+
shortTitle = getShortTitle(name, parentGroup);
240+
if (shortTitle) {
241+
return shortTitle;
242+
}
243+
}
244+
245+
if (parentModule) {
246+
shortTitle = getShortTitle(name, parentModule);
247+
if (shortTitle) {
248+
return shortTitle;
249+
}
250+
}
251+
return name;
252+
} else {
253+
return this.getTitle(docObject);
254+
}
255+
};
256+
257+
DocMapInfo.prototype.isGroup = function (docObject) {
258+
return ["group", "static", "prototype"].indexOf(docObject.type) !== -1;
259+
};
260+
261+
DocMapInfo.prototype.getCurrentTree = function () {
262+
// [{docObject, children<>},{docObject}]
263+
var getChildren = this.getChildren.bind(this);
264+
var getNestedDocObject = this.getNestedDocObject.bind(this);
265+
266+
var cur = this.getCurrent();
267+
268+
var curChildren = this.getNestedChildren(cur);
269+
270+
this.getParents(cur, function (docObject) {
271+
curChildren = getChildren(docObject).map(function (docObject) {
272+
if (docObject.name === cur.name) {
273+
return { docObject: docObject, children: curChildren };
274+
} else {
275+
return getNestedDocObject(docObject);
276+
}
277+
});
278+
cur = docObject;
279+
});
280+
281+
if (!curChildren) {
282+
return { children: [] };
283+
} else {
284+
return { children: curChildren };
285+
}
286+
};
287+
288+
DocMapInfo.prototype.getChildren = function (docObject) {
289+
var children = this.childrenMap[docObject.name];
290+
return (children || []).sort(compareDocObjects);
291+
};
292+
293+
DocMapInfo.prototype.getNestedDocObject = function (docObject) {
294+
if (this.isGroup(docObject)) {
295+
return {
296+
docObject: docObject,
297+
children: this.getNestedChildren(docObject)
298+
};
299+
} else {
300+
return { docObject: docObject };
301+
}
302+
};
303+
304+
DocMapInfo.prototype.getNestedChildren = function (docObject) {
305+
return this.getChildren(docObject).map(this.getNestedDocObject.bind(this));
306+
};
307+
308+
var levelMap = ["collection", "modules"];
309+
310+
function makeChildrenMap(docMap) {
311+
var childrenMap = {};
312+
for (var name in docMap) {
313+
var docObject = docMap[name];
314+
var parent = docObject.parent;
315+
if (parent) {
316+
if (!childrenMap[parent]) {
317+
childrenMap[parent] = [];
318+
}
319+
childrenMap[parent].push(docObject);
320+
}
321+
}
322+
return childrenMap;
323+
}
324+
325+
var compareDocObjects = function (child1, child2) {
326+
// put groups at the end
327+
if (/group|prototype|static/i.test(child1.type)) {
328+
if (!/group|prototype|static/i.test(child2.type)) {
329+
return 1;
330+
} else {
331+
if (child1.type === "prototype") {
332+
return -1;
333+
}
334+
if (child2.type === "prototype") {
335+
return 1;
336+
}
337+
if (child1.type === "static") {
338+
return -1;
339+
}
340+
if (child2.type === "static") {
341+
return 1;
342+
}
343+
344+
}
345+
}
346+
347+
if (/prototype|static/i.test(child2.type)) {
348+
return -1;
349+
}
350+
351+
if (typeof child1.order == "number") {
352+
if (typeof child2.order == "number") {
353+
// same order given?
354+
if (child1.order == child2.order) {
355+
// sort by name
356+
if (child1.name < child2.name) {
357+
return -1;
358+
}
359+
return 1;
360+
} else {
361+
return child1.order - child2.order;
362+
}
363+
364+
} else {
365+
return -1;
366+
}
367+
} else {
368+
if (typeof child2.order == "number") {
369+
return 1;
370+
} else {
371+
// alphabetical
372+
if (child1.name < child2.name) {
373+
return -1;
374+
}
375+
return 1;
376+
}
377+
}
378+
};

0 commit comments

Comments
 (0)