Skip to content

Commit 1fcb91d

Browse files
committed
Show single exports of resolved types in nav bar
1 parent a462b45 commit 1fcb91d

File tree

16 files changed

+5955
-98
lines changed

16 files changed

+5955
-98
lines changed

addon/components/docs-header/search-results/component.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ export default Component.extend(EKMixin, {
8080
// Filter out modules that are not in the navigationIndex
8181
.filter(({ document }) => {
8282
if (document.type === 'module') {
83-
let navigableModules = this.get('project.navigationIndex.modules').map(x => x.name);
84-
return navigableModules.includes(document.title);
83+
let navigableModules = this.get('project.navigationIndex').find(section => section.type === 'modules');
84+
let navigableModuleIds = navigableModules ? navigableModules.items.map(item => item.id) : [];
85+
86+
return navigableModuleIds.includes(document.title);
8587
} else {
8688
return true;
8789
}

addon/components/docs-viewer/x-main/component.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default Component.extend({
2525
tagName: 'main',
2626
classNames: [
2727
'docs-px-4', 'md:docs-px-8', 'lg:docs-px-20', 'docs-mx-auto', 'md:docs-mx-0', 'docs-mt-6',
28-
'md:docs-mt-12', 'md:docs-min-w-0'
28+
'md:docs-mt-12', 'md:docs-min-w-0', 'md:docs-flex-1'
2929
],
3030

3131
didInsertElement() {

addon/components/docs-viewer/x-nav/template.hbs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,20 @@
3030
{{yield (hash
3131
section=(component 'docs-viewer/x-section')
3232
item=(component 'docs-viewer/x-nav-item')
33-
subnav=(component 'docs-viewer/x-nav-list' class='ml-4')
33+
subnav=(component 'docs-viewer/x-nav-list' class='docs-ml-4')
3434
)}}
3535

3636
{{!-- Autogenerated API docs --}}
3737
{{#if (gt project.modules.length 0)}}
3838
{{docs-viewer/x-section 'API Reference' style='large'}}
3939

40-
{{#each-in project.navigationIndex as |type items|}}
41-
{{docs-viewer/x-section type}}
40+
{{#each project.navigationIndex as |section|}}
41+
{{docs-viewer/x-section section.type}}
4242

43-
{{#each items as |item|}}
43+
{{#each section.items as |item|}}
4444
{{docs-viewer/x-nav-item (break-on item.name '/') (concat root '.api.item') item.path}}
4545
{{/each}}
46-
{{/each-in}}
46+
{{/each}}
4747
{{/if}}
4848
{{/docs-viewer/x-nav-list}}
4949

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
<li class='docs-mt-8
2-
{{if (eq style 'large') 'docs--mb-4 docs-text-xs'}}
1+
<li class='docs-mt-8
2+
{{if (eq style 'large') 'docs--mb-4 docs-text-xs docs-uppercase' 'docs-capitalize'}}
33
'>
44
{{label}}
55
</li>

lib/broccoli/docs-compiler.js

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const CachingWriter = require('broccoli-caching-writer');
88
const Serializer = require('../serializers/main');
99

1010
const compileMarkdown = require('../utils/compile-markdown');
11+
const NavigationIndexGenerator = require('./docs-compiler/navigation-index-generator');
1112

1213
function compileDescriptions(objects) {
1314
if (!objects) { return; }
@@ -72,81 +73,6 @@ function compileDocDescriptions(modules) {
7273
});
7374
}
7475

75-
const RESOLVED_TYPES = [
76-
'components',
77-
'helpers',
78-
'controllers',
79-
'mixins',
80-
'models',
81-
'services'
82-
];
83-
84-
function generateResolvedTypeNavigationItems(modules, type) {
85-
let items = modules.map(m => {
86-
let segments = m.file.split('/');
87-
segments = segments.slice(segments.indexOf(type) + 1);
88-
89-
if (type.match(segments[segments.length - 1])) {
90-
segments.pop();
91-
}
92-
93-
let path = segments.join('/');
94-
let name;
95-
96-
if (['components', 'helpers'].includes(type)) {
97-
name = `{{${path}}}`;
98-
} else {
99-
let fileName = segments.pop();
100-
name = _.upperFirst(_.camelCase(fileName));
101-
}
102-
103-
return {
104-
path: `${type}/${path}`,
105-
name
106-
};
107-
});
108-
109-
return _.sortBy(items, ['path']);
110-
}
111-
112-
function generateNavigationIndex(modules, klasses) {
113-
let navigationIndex = {};
114-
115-
for (let type of RESOLVED_TYPES) {
116-
let resolvedModules = modules.filter(m => m.file.match(`${type}/`) && !m.file.match('utils/'));
117-
118-
navigationIndex[type] = generateResolvedTypeNavigationItems(resolvedModules, type);
119-
}
120-
121-
navigationIndex.modules = modules
122-
.filter(m => {
123-
return (
124-
!m.file.match(new RegExp(`(${RESOLVED_TYPES.join('|')})/`)) ||
125-
m.file.match('utils/')
126-
);
127-
})
128-
.map(m => {
129-
return {
130-
path: `modules/${m.id}`,
131-
name: m.id
132-
};
133-
});
134-
135-
136-
for (let type in navigationIndex) {
137-
let items = navigationIndex[type];
138-
139-
if (
140-
(Array.isArray(items) && items.length === 0)
141-
|| (!Array.isArray(items) && Object.keys(items).length === 0)
142-
) {
143-
delete navigationIndex[type];
144-
}
145-
}
146-
147-
return navigationIndex;
148-
}
149-
15076
module.exports = class DocsCompiler extends CachingWriter {
15177
constructor(inputNodes, options) {
15278
let defaults = {
@@ -180,7 +106,7 @@ module.exports = class DocsCompiler extends CachingWriter {
180106
id: name,
181107
name: name,
182108
version: projectVersion,
183-
navigationIndex: generateNavigationIndex(modules),
109+
navigationIndex: (new NavigationIndexGenerator).generate(modules),
184110
modules
185111
}
186112

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
const _ = require('lodash');
2+
const RESOLVED_TYPES = [
3+
'components',
4+
'helpers',
5+
'controllers',
6+
'mixins',
7+
'models',
8+
'services',
9+
'classes'
10+
];
11+
12+
module.exports = class NavigationIndexGenerator {
13+
14+
generate(modules) {
15+
// The index is an array - the order is important for the UI
16+
let navIndex = [...RESOLVED_TYPES, 'modules'].map(type => ({
17+
type,
18+
items: []
19+
}));
20+
21+
// Push each module into the right section
22+
modules.forEach(module => {
23+
let moduleType = this._getModuleType(module);
24+
let navItem = this._getNavItemForModule(module, moduleType);
25+
26+
navIndex.find(({ type }) => type === moduleType)
27+
.items
28+
.push(navItem);
29+
});
30+
31+
// Filter out empty sections, and sort non-empty section items by path
32+
return navIndex
33+
.filter(section => section.items.length > 0)
34+
.map(section => {
35+
section.items = _.sortBy(section.items, ['name']);
36+
37+
return section;
38+
});
39+
}
40+
41+
42+
// Private
43+
44+
_getModuleType(module) {
45+
let resolvedType = this._resolvedTypeForModule(module);
46+
47+
if (!resolvedType && this._hasSingleExportOfResolvedType(module)) {
48+
let singleExport = this._exportsForModuleOfResolvedTypes(module)[0];
49+
resolvedType = singleExport.type;
50+
}
51+
52+
return resolvedType || 'modules';
53+
}
54+
55+
_resolvedTypeForModule(module) {
56+
return RESOLVED_TYPES.find(type => {
57+
return module.file.match(`${type}/`) && !module.file.match('utils/');
58+
});
59+
}
60+
61+
_isResolvedType(module) {
62+
return this._resolvedTypeForModule(module);
63+
}
64+
65+
_exportsForModuleOfResolvedTypes(module) {
66+
return [
67+
...module.classes.map(item => ({ type: 'classes', export: item })),
68+
...module.components.map(item => ({ type: 'components', export: item }))
69+
];
70+
}
71+
72+
_exportsForModuleOfNonResolvedTypes(module) {
73+
return [
74+
...module.functions.map(item => ({ type: 'functions', export: item })),
75+
...module.variables.map(item => ({ type: 'variables', export: item })),
76+
];
77+
}
78+
79+
_hasSingleExportOfResolvedType(module) {
80+
return (
81+
this._exportsForModuleOfResolvedTypes(module).length === 1 &&
82+
this._exportsForModuleOfNonResolvedTypes(module).length === 0
83+
);
84+
}
85+
86+
_getNavItemForModule(module, type) {
87+
let navItem;
88+
89+
if (this._isResolvedType(module)) {
90+
navItem = this._getNavItemForModuleOfResolvedType(module, type);
91+
} else if (this._hasSingleExportOfResolvedType(module)) {
92+
navItem = this._getNavItemForModuleWithSingleExport(module, type);
93+
} else {
94+
navItem = this._getNavItemForGenericModule(module, type)
95+
}
96+
97+
return navItem;
98+
}
99+
100+
_getNavItemForModuleOfResolvedType(module, type) {
101+
let segments = module.file.split('/');
102+
segments = segments.slice(segments.indexOf(type) + 1);
103+
104+
if (type.match(segments[segments.length - 1])) {
105+
segments.pop();
106+
}
107+
108+
let path = segments.join('/');
109+
let name;
110+
111+
if (['components', 'helpers'].includes(type)) {
112+
name = `{{${path}}}`;
113+
} else {
114+
let fileName = segments.pop();
115+
name = _.upperFirst(_.camelCase(fileName));
116+
}
117+
118+
return {
119+
id: module[type][0].id,
120+
path: `${type}/${path}`,
121+
name
122+
};
123+
}
124+
125+
_getNavItemForModuleWithSingleExport(module, type) {
126+
let singleExport = module[type][0];
127+
128+
return {
129+
id: singleExport.id,
130+
path: `modules/${singleExport.id}`,
131+
name: singleExport.name
132+
};
133+
}
134+
135+
_getNavItemForGenericModule(module, type) {
136+
return {
137+
id: module.id,
138+
path: `modules/${module.id}`,
139+
name: module.id
140+
};
141+
}
142+
143+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
"broccoli-stew": "^2.0.0",
3939
"ember-cli-autoprefixer": "^0.8.1",
4040
"ember-cli-babel": "^6.16.0",
41-
"ember-cli-clipboard": "^0.9.0",
4241
"ember-cli-htmlbars": "^3.0.0",
4342
"ember-cli-htmlbars-inline-precompile": "^1.0.3",
43+
"ember-cli-clipboard": "^0.10.0",
4444
"ember-cli-sass": "7.1.7",
4545
"ember-cli-string-helpers": "^1.9.0",
4646
"ember-cli-tailwind": "^0.6.2",

0 commit comments

Comments
 (0)