Skip to content

Commit 71a7702

Browse files
committed
group-by
1 parent 8e214f4 commit 71a7702

7 files changed

Lines changed: 295 additions & 6 deletions

File tree

lib/jsdoc-parse.js

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
const sortArray = require('sort-array')
33
const transform = require('./transform')
44
const a = require('array-tools')
5+
const t = require('typical')
56

67
/**
78
*
@@ -12,16 +13,18 @@ const a = require('array-tools')
1213

1314
exports.parse = parse
1415
exports.getStats = getStats
16+
exports.groupBy = groupBy
1517

1618
/**
1719
* @param {object[]} - jsdoc output
1820
* @param [options] {object}
1921
* @param [options.private] {boolean} - Include identifier documentation marked as `@private` in the output
2022
* @param [options.html] {boolean} - Enable experimental parsing of .html files.
2123
* @param [options.sort-by=[ 'scope', 'category', 'kind', 'order' ]] {string[]} - Sort by one of more fields, e.g. `--sort-by kind category`. Pass the special value `none` to remove the default sort order.
24+
* @param [options.group-by] {string[]}
2225
*/
2326
function parse (jsdocExplainOutput, options) {
24-
options = options || {}
27+
options = new ParseOptions(options)
2528
let data = transform(jsdocExplainOutput)
2629

2730
data = data.filter(function (doclet) {
@@ -41,6 +44,10 @@ function parse (jsdocExplainOutput, options) {
4144
data = sort(data, [ 'scope', 'category', 'kind', 'order' ])
4245
}
4346

47+
if (options['group-by']) {
48+
data = groupBy(data, options['group-by'])
49+
}
50+
4451
return data
4552
}
4653

@@ -66,15 +73,102 @@ function getStats (jsdocExplainOutput) {
6673
}
6774

6875
function sort (array, sortBy) {
69-
var order = {
70-
kind: [ 'class', 'constructor', 'mixin', 'member', 'namespace',
76+
var customSortOrders = {
77+
kind: [ 'class', 'constructor', 'mixin', 'member', 'namespace', 'enum',
7178
'constant', 'function', 'event', 'typedef', 'external' ],
7279
scope: [ 'global', 'instance', 'static', 'inner' ]
7380
}
7481

7582
if (!sortBy) {
7683
return array
7784
} else {
78-
return sortArray(array, sortBy, order)
85+
return sortArray(array, sortBy, customSortOrders)
86+
}
87+
}
88+
89+
function _addGroup (doclets, groupByFields) {
90+
return doclets.map(doclet => {
91+
doclet._group = groupByFields
92+
.map(field => t.isDefined(doclet[field]) ? doclet[field] : null)
93+
return doclet
94+
})
95+
}
96+
97+
/**
98+
* takes the children of this, groups them, inserts group headings..
99+
*/
100+
function groupBy (doclets, groupByFields) {
101+
var commonSequence = require('common-sequence')
102+
103+
/* don't modify the input array */
104+
groupByFields = groupByFields.slice(0)
105+
106+
/* remove groupByFields that don't have any values */
107+
// console.error(groupByFields)
108+
groupByFields
109+
.forEach(group => {
110+
const docletGroupValues = doclets
111+
.filter(doclet => doclet.kind !== 'constructor')
112+
.map(d => d[group])
113+
let groupValues = a.unique(docletGroupValues)
114+
if (groupValues.length <= 1) groupByFields = a.without(groupByFields, group)
115+
})
116+
// console.error(groupByFields)
117+
doclets = _addGroup(doclets, groupByFields)
118+
119+
var inserts = []
120+
var prevGroup = []
121+
doclets.forEach((doclet, index) => {
122+
if (!deepEqual(doclet._group, prevGroup)) {
123+
var common = commonSequence(doclet._group, prevGroup)
124+
doclet._group.forEach((group, i) => {
125+
if (group !== common[i] && group !== null) {
126+
inserts.push({
127+
index: index,
128+
group: group
129+
})
130+
}
131+
})
132+
}
133+
prevGroup = doclet._group
134+
delete doclet._group
135+
})
136+
137+
/* insert group records */
138+
inserts.reverse().forEach((insert, i) => {
139+
// console.error(i, insert)
140+
doclets.splice(insert.index, 0, { id: insert.group, kind: 'group', parentId: null })
141+
})
142+
143+
/* update parentIds for group members */
144+
let currentGroup = null
145+
doclets.forEach((d, index) => {
146+
d.parentId = currentGroup
147+
if (index === 0) {
148+
currentGroup = d.id
149+
} else {
150+
if (d.kind === 'group') currentGroup = d.id
151+
}
152+
})
153+
154+
return doclets
155+
}
156+
157+
function deepEqual (a, b) {
158+
return JSON.stringify(a) === JSON.stringify(b)
159+
}
160+
161+
/**
162+
* Common jsdoc2md options
163+
*/
164+
class ParseOptions {
165+
constructor (options) {
166+
options = options || {}
167+
168+
this['group-by'] = null
169+
170+
this['sort-by'] = [ 'scope', 'category', 'kind', 'order' ]
171+
172+
Object.assign(this, options)
79173
}
80174
}

lib/transform.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ function transform (data) {
6060
doclet.order = index
6161
})
6262

63-
// return JSON.stringify(json, null, ' ')
6463
return json
6564
}
6665

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
},
2424
"dependencies": {
2525
"array-tools": "^2",
26+
"common-sequence": "^1.0.2",
2627
"core-js": "^2.1.0",
2728
"feature-detect-es6": "^1.2.0",
2829
"object-tools": "^2",
2930
"sort-array": "^0.1.0",
30-
"test-value": "^1.0.1"
31+
"test-value": "^1.0.1",
32+
"typical": "^2.4.2"
3133
},
3234
"devDependencies": {
3335
"babel-preset-es2015": "^6.5.0",

test/expected/deep-class.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[
2+
{
3+
"id": "module:farm"
4+
},
5+
{
6+
"id": "module:farm--Farm",
7+
"parentId": "module:farm"
8+
},
9+
{
10+
"id": "module:farm--Farm()",
11+
"parentId": "module:farm--Farm"
12+
},
13+
{ "id": "instance", "kind": "group", "parentId": "module:farm--Farm" }
14+
{
15+
"id": "module:farm--Farm.Farm#equipment",
16+
"parentId": "instance",
17+
"scope": "instance"
18+
},
19+
{
20+
"id": "module:farm--Farm~Equipment.Equipment#tractor",
21+
"parentId": "module:farm--Farm~Equipment",
22+
"scope": "instance"
23+
},
24+
{
25+
"id": "module:farm--Farm~Tractor.Tractor#engine",
26+
"parentId": "module:farm--Farm~Tractor",
27+
"scope": "instance"
28+
},
29+
{
30+
"id": "module:farm--Farm~Tractor.Tractor#engine.manufacturer",
31+
"parentId": "module:farm--Farm~Tractor.Tractor#engine",
32+
"scope": "static"
33+
},
34+
{
35+
"id": "module:farm--Farm~Tractor.Tractor#engine.size",
36+
"parentId": "module:farm--Farm~Tractor.Tractor#engine",
37+
"scope": "static"
38+
},
39+
{
40+
"id": "module:farm--Farm~Equipment",
41+
"parentId": "module:farm--Farm",
42+
"scope": "inner"
43+
},
44+
{
45+
"id": "module:farm--Farm~Tractor",
46+
"parentId": "module:farm--Farm",
47+
"scope": "inner"
48+
}
49+
]

test/fixture/category.json

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
[
2+
{
3+
"id": "module:category",
4+
"longname": "module:category",
5+
"name": "category",
6+
"kind": "module",
7+
"meta": {
8+
"lineno": 1,
9+
"filename": "0-src.js",
10+
"path": "/Users/lloyd/Documents/jsdoc2md/testbed/build-v2/jsdoc2md/tags/category"
11+
},
12+
"order": 0
13+
},
14+
{
15+
"id": "module:category.one",
16+
"parentId": "module:category",
17+
"longname": "module:category.one",
18+
"name": "one",
19+
"scope": "static",
20+
"kind": "member",
21+
"description": "one",
22+
"memberof": "module:category",
23+
"category": "first",
24+
"meta": {
25+
"lineno": 9,
26+
"filename": "0-src.js",
27+
"path": "/Users/lloyd/Documents/jsdoc2md/testbed/build-v2/jsdoc2md/tags/category"
28+
},
29+
"order": 1
30+
},
31+
{
32+
"id": "module:category.two",
33+
"parentId": "module:category",
34+
"longname": "module:category.two",
35+
"name": "two",
36+
"scope": "static",
37+
"kind": "member",
38+
"description": "two",
39+
"memberof": "module:category",
40+
"category": "first",
41+
"meta": {
42+
"lineno": 14,
43+
"filename": "0-src.js",
44+
"path": "/Users/lloyd/Documents/jsdoc2md/testbed/build-v2/jsdoc2md/tags/category"
45+
},
46+
"order": 2
47+
},
48+
{
49+
"id": "module:category.three",
50+
"parentId": "module:category",
51+
"longname": "module:category.three",
52+
"name": "three",
53+
"scope": "static",
54+
"kind": "member",
55+
"description": "three",
56+
"memberof": "module:category",
57+
"category": "second",
58+
"meta": {
59+
"lineno": 19,
60+
"filename": "0-src.js",
61+
"path": "/Users/lloyd/Documents/jsdoc2md/testbed/build-v2/jsdoc2md/tags/category"
62+
},
63+
"order": 3
64+
},
65+
{
66+
"id": "module:category.four",
67+
"parentId": "module:category",
68+
"longname": "module:category.four",
69+
"name": "four",
70+
"scope": "static",
71+
"kind": "member",
72+
"description": "four",
73+
"memberof": "module:category",
74+
"category": "second",
75+
"meta": {
76+
"lineno": 24,
77+
"filename": "0-src.js",
78+
"path": "/Users/lloyd/Documents/jsdoc2md/testbed/build-v2/jsdoc2md/tags/category"
79+
},
80+
"order": 4
81+
}
82+
]

test/fixture/deep-class.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[
2+
{
3+
"id": "module:farm"
4+
},
5+
{
6+
"id": "module:farm--Farm",
7+
"parentId": "module:farm"
8+
},
9+
{
10+
"id": "module:farm--Farm()",
11+
"parentId": "module:farm--Farm"
12+
},
13+
{
14+
"id": "module:farm--Farm.Farm#equipment",
15+
"parentId": "module:farm--Farm",
16+
"scope": "instance"
17+
},
18+
{
19+
"id": "module:farm--Farm~Equipment.Equipment#tractor",
20+
"parentId": "module:farm--Farm~Equipment",
21+
"scope": "instance"
22+
},
23+
{
24+
"id": "module:farm--Farm~Tractor.Tractor#engine",
25+
"parentId": "module:farm--Farm~Tractor",
26+
"scope": "instance"
27+
},
28+
{
29+
"id": "module:farm--Farm~Tractor.Tractor#engine.manufacturer",
30+
"parentId": "module:farm--Farm~Tractor.Tractor#engine",
31+
"scope": "static"
32+
},
33+
{
34+
"id": "module:farm--Farm~Tractor.Tractor#engine.size",
35+
"parentId": "module:farm--Farm~Tractor.Tractor#engine",
36+
"scope": "static"
37+
},
38+
{
39+
"id": "module:farm--Farm~Equipment",
40+
"parentId": "module:farm--Farm",
41+
"scope": "inner"
42+
},
43+
{
44+
"id": "module:farm--Farm~Tractor",
45+
"parentId": "module:farm--Farm",
46+
"scope": "inner"
47+
}
48+
]

test/group-by.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict'
2+
var test = require('tape')
3+
var jsdocParse = require('../')
4+
5+
test('groupBy', function (t) {
6+
const fixture = require('./fixture/deep-class')
7+
console.log(jsdocParse.groupBy(fixture, [ 'scope', 'category' ]))
8+
t.end()
9+
})
10+
11+
test.only('groupBy2', function (t) {
12+
const fixture = require('./fixture/deep-class')
13+
console.log(jsdocParse.groupBy(fixture, [ 'scope' ]))
14+
t.end()
15+
})

0 commit comments

Comments
 (0)