Skip to content

Commit d6086b4

Browse files
committed
fix(menu): additional menu entries with children collapsed (first level only)
fix #714
1 parent f94d664 commit d6086b4

File tree

9 files changed

+610
-545
lines changed

9 files changed

+610
-545
lines changed

src/app/application.ts

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { SyntaxKind } from 'ts-simple-ast';
88
const chokidar = require('chokidar');
99
const marked = require('marked');
1010
const traverse = require('traverse');
11+
const crypto = require('crypto');
1112

1213
import { logger } from '../utils/logger';
1314

@@ -37,7 +38,9 @@ import {
3738
findMainSourceFolder
3839
} from '../utils/utils';
3940

41+
import { AdditionalNode } from './interfaces/additional-node.interface';
4042
import { CoverageData } from './interfaces/coverageData.interface';
43+
import { resolve } from 'url';
4144

4245
let cwd = process.cwd();
4346
let startTime = new Date();
@@ -748,12 +751,17 @@ export class Application {
748751
const parsedSummaryData = JSON.parse(summaryData);
749752

750753
let that = this;
754+
let lastLevelOnePage = null;
751755

752756
traverse(parsedSummaryData).forEach(function() {
757+
// tslint:disable-next-line:no-invalid-this
753758
if (this.notRoot && typeof this.node === 'object') {
759+
// tslint:disable-next-line:no-invalid-this
754760
let rawPath = this.path;
755-
let file = this.node.file;
756-
let title = this.node.title;
761+
// tslint:disable-next-line:no-invalid-this
762+
let additionalNode: AdditionalNode = this.node;
763+
let file = additionalNode.file;
764+
let title = additionalNode.title;
757765
let finalPath = Configuration.mainData.includesFolder;
758766

759767
let finalDepth = rawPath.filter(el => {
@@ -763,14 +771,25 @@ export class Application {
763771
if (typeof file !== 'undefined' && typeof title !== 'undefined') {
764772
const url = cleanNameWithoutSpaceAndToLowerCase(title);
765773

774+
/**
775+
* Id created with title + file path hash, seems to be hypothetically unique here
776+
*/
777+
const id = crypto
778+
.createHash('md5')
779+
.update(title + file)
780+
.digest('hex');
781+
782+
// tslint:disable-next-line:no-invalid-this
783+
this.node.id = id;
784+
766785
let lastElementRootTree = null;
767786
finalDepth.forEach(el => {
768787
let elementTree =
769788
lastElementRootTree === null
770789
? parsedSummaryData
771790
: lastElementRootTree;
772791
if (typeof elementTree.children !== 'undefined') {
773-
elementTree = elementTree.children[el];
792+
elementTree = elementTree['children'][el];
774793
} else {
775794
elementTree = elementTree[el];
776795
}
@@ -788,16 +807,30 @@ export class Application {
788807
if (finalDepth.length > 5) {
789808
logger.error('Only 5 levels of depth are supported');
790809
} else {
791-
Configuration.addAdditionalPage({
810+
let _page = {
792811
name: title,
793-
id: title,
812+
id: id,
794813
filename: url,
795814
context: 'additional-page',
796815
path: finalPath,
797816
additionalPage: markdownFile,
798817
depth: finalDepth.length,
818+
childrenLength: additionalNode.children
819+
? additionalNode.children.length
820+
: 0,
821+
children: [],
822+
lastChild: false,
799823
pageType: COMPODOC_DEFAULTS.PAGE_TYPES.INTERNAL
800-
});
824+
};
825+
if (finalDepth.length === 1) {
826+
lastLevelOnePage = _page;
827+
}
828+
if (finalDepth.length > 1) {
829+
// store all child pages of the last root level 1 page inside it
830+
lastLevelOnePage.children.push(_page);
831+
} else {
832+
Configuration.addAdditionalPage(_page);
833+
}
801834
}
802835
}
803836
}
@@ -2504,7 +2537,18 @@ at least one config for the 'info' or 'source' tab in --navTabConfig.`);
25042537
public processAdditionalPages() {
25052538
logger.info('Process additional pages');
25062539
let pages = Configuration.mainData.additionalPages;
2507-
Promise.all(pages.map((page, i) => this.processPage(page)))
2540+
Promise.all(
2541+
pages.map(page => {
2542+
if (page.children.length > 0) {
2543+
return Promise.all([
2544+
this.processPage(page),
2545+
...page.children.map(childPage => this.processPage(childPage))
2546+
]);
2547+
} else {
2548+
return this.processPage(page);
2549+
}
2550+
})
2551+
)
25082552
.then(() => {
25092553
SearchEngine.generateSearchIndexJson(Configuration.mainData.output).then(() => {
25102554
if (Configuration.mainData.assetsFolder !== '') {

src/app/compiler/angular/deps/component-dep.factory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { IDep } from '../dependencies.interfaces';
2-
import { ComponentHelper } from './helpers/component-helper';
31
import { cleanLifecycleHooksFromMethods } from '../../../../utils';
42
import Configuration from '../../../configuration';
3+
import { IDep } from '../dependencies.interfaces';
4+
import { ComponentHelper } from './helpers/component-helper';
55

66
const crypto = require('crypto');
77

src/app/configuration.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as _ from 'lodash';
33
import { COMPODOC_DEFAULTS } from '../utils/defaults';
44

55
import { ConfigurationInterface } from './interfaces/configuration.interface';
6+
import { CoverageData } from './interfaces/coverageData.interface';
67
import { MainDataInterface } from './interfaces/main-data.interface';
78
import { PageInterface } from './interfaces/page.interface';
89

@@ -72,7 +73,7 @@ export class Configuration implements ConfigurationInterface {
7273
routesLength: 0,
7374
angularVersion: '',
7475
exportFormat: COMPODOC_DEFAULTS.exportFormat,
75-
coverageData: {},
76+
coverageData: {} as CoverageData,
7677
customFavicon: '',
7778
customLogo: '',
7879
packageDependencies: [],
@@ -109,6 +110,10 @@ export class Configuration implements ConfigurationInterface {
109110
this._mainData.additionalPages.push(page);
110111
}
111112

113+
public getAdditionalPageById(id): PageInterface {
114+
return this._mainData.additionalPages.find(page => page.id === id);
115+
}
116+
112117
public resetPages() {
113118
this._pages = [];
114119
}

src/app/interfaces/page.interface.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@ export interface PageInterface {
1818
pageType?: string;
1919
component?: any;
2020
markdown?: string;
21+
childrenLength?: number;
22+
children: any[];
23+
lastChild?: boolean;
2124
}

src/resources/js/menu.js

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ document.addEventListener('DOMContentLoaded', function() {
33
mobileMenu = document.getElementById('mobile-menu');
44

55
var localContextInUrl = '';
6-
6+
77
if (COMPODOC_CURRENT_PAGE_CONTEXT !== '') {
88
localContextInUrl = localContextInUrl;
99
switch (COMPODOC_CURRENT_PAGE_CONTEXT) {
1010
case 'additional-page':
11-
localContextInUrl = 'additional-documentation'
11+
localContextInUrl = 'additional-documentation';
1212
break;
1313
case 'class':
14-
localContextInUrl = 'classes'
14+
localContextInUrl = 'classes';
1515
break;
1616
case 'miscellaneous-functions':
1717
case 'miscellaneous-variables':
@@ -24,13 +24,13 @@ document.addEventListener('DOMContentLoaded', function() {
2424
}
2525

2626
function hasClass(el, cls) {
27-
return el.className && new RegExp("(\\s|^)" + cls + "(\\s|$)").test(el.className);
27+
return el.className && new RegExp('(\\s|^)' + cls + '(\\s|$)').test(el.className);
2828
}
2929

3030
var processLink = function(link, url) {
3131
if (url.charAt(0) !== '.') {
3232
var prefix = '';
33-
switch(COMPODOC_CURRENT_PAGE_DEPTH) {
33+
switch (COMPODOC_CURRENT_PAGE_DEPTH) {
3434
case 5:
3535
prefix = '../../../../../';
3636
break;
@@ -52,24 +52,26 @@ document.addEventListener('DOMContentLoaded', function() {
5252
}
5353
link.setAttribute('href', prefix + url);
5454
}
55-
}
55+
};
5656

5757
var processMenuLinks = function(links, dontAddClass) {
5858
for (var i = 0; i < links.length; i++) {
5959
var link = links[i];
6060
var linkHref = link.getAttribute('href');
6161
if (linkHref) {
6262
var linkHrefFile = linkHref.substr(linkHref.lastIndexOf('/') + 1, linkHref.length);
63-
if (linkHrefFile.toLowerCase() === COMPODOC_CURRENT_PAGE_URL.toLowerCase()
64-
&& link.innerHTML.indexOf('Getting started') == -1
65-
&& !dontAddClass
66-
&& linkHref.toLowerCase().indexOf(localContextInUrl.toLowerCase()) !== -1 ) {
63+
if (
64+
linkHrefFile.toLowerCase() === COMPODOC_CURRENT_PAGE_URL.toLowerCase() &&
65+
link.innerHTML.indexOf('Getting started') == -1 &&
66+
!dontAddClass &&
67+
linkHref.toLowerCase().indexOf(localContextInUrl.toLowerCase()) !== -1
68+
) {
6769
link.classList.add('active');
6870
}
6971
processLink(link, linkHref);
7072
}
7173
}
72-
}
74+
};
7375
var chapterLinks = document.querySelectorAll('[data-type="chapter-link"]');
7476
processMenuLinks(chapterLinks);
7577
var entityLinks = document.querySelectorAll('[data-type="entity-link"]');
@@ -84,7 +86,7 @@ document.addEventListener('DOMContentLoaded', function() {
8486
var url = entityLogo.getAttribute('data-src');
8587
if (url.charAt(0) !== '.') {
8688
var prefix = '';
87-
switch(COMPODOC_CURRENT_PAGE_DEPTH) {
89+
switch (COMPODOC_CURRENT_PAGE_DEPTH) {
8890
case 5:
8991
prefix = '../../../../../';
9092
break;
@@ -102,13 +104,13 @@ document.addEventListener('DOMContentLoaded', function() {
102104
break;
103105
case 0:
104106
prefix = './';
105-
break
107+
break;
106108
}
107109
entityLogo.src = prefix + url;
108110
}
109111
}
110112
}
111-
}
113+
};
112114
processLogos(entityLogos);
113115

114116
setTimeout(function() {
@@ -156,7 +158,7 @@ document.addEventListener('DOMContentLoaded', function() {
156158
elementIconChild = parent.getElementsByClassName(faAngleDownClass)[0];
157159
}
158160
if (elementIconChild) {
159-
elementIconChild = $(elementIconChild)
161+
elementIconChild = $(elementIconChild);
160162
if (elementIconChild.hasClass(faAngleUpClass)) {
161163
elementIconChild.addClass(faAngleDownClass);
162164
elementIconChild.removeClass(faAngleUpClass);
@@ -180,7 +182,7 @@ document.addEventListener('DOMContentLoaded', function() {
180182
activeMenuClass,
181183
activeLink;
182184

183-
for (i; i<len; i++) {
185+
for (i; i < len; i++) {
184186
if (getComputedStyle(menus[i]).display != 'none') {
185187
activeMenu = menus[i];
186188
activeMenuClass = activeMenu.getAttribute('class').split(' ')[0];
@@ -202,7 +204,9 @@ document.addEventListener('DOMContentLoaded', function() {
202204
parentChapterMenu = parentUl.parentNode;
203205
if (parentChapterMenu) {
204206
var toggler = parentChapterMenu.querySelector('.menu-toggler'),
205-
elementIconChild = toggler.getElementsByClassName(faAngleUpClass)[0];
207+
elementIconChild = toggler.getElementsByClassName(
208+
faAngleUpClass
209+
)[0];
206210
if (toggler && !elementIconChild) {
207211
toggler.click();
208212
}
@@ -212,24 +216,46 @@ document.addEventListener('DOMContentLoaded', function() {
212216
if (linkContext && linkContext === 'sub-entity') {
213217
// Toggle also the master parent menu
214218
var linkContextId = activeLink.getAttribute('data-context-id');
215-
var toggler = activeMenu.querySelector('.chapter.' + linkContextId + ' a .menu-toggler');
219+
var toggler = activeMenu.querySelector(
220+
'.chapter.' + linkContextId + ' a .menu-toggler'
221+
);
216222
if (toggler) {
217223
toggler.click();
218224
}
225+
if (linkContextId === 'additional') {
226+
var mainToggler = activeMenu.querySelector(
227+
'.chapter.' + linkContextId + ' div.menu-toggler'
228+
);
229+
if (mainToggler) {
230+
mainToggler.click();
231+
}
232+
}
219233
}
220234
} else if (linkType === 'chapter-link') {
235+
var linkContextId = activeLink.getAttribute('data-context-id');
221236
var toggler = activeLink.querySelector('.menu-toggler');
222237
if (toggler) {
223238
toggler.click();
224239
}
240+
if (linkContextId === 'additional') {
241+
var mainToggler = activeMenu.querySelector(
242+
'.chapter.' + linkContextId + ' div.menu-toggler'
243+
);
244+
if (mainToggler) {
245+
mainToggler.click();
246+
}
247+
}
225248
}
226249
setTimeout(function() {
227250
activeMenu.scrollTop = activeLink.offsetTop;
228-
if (activeLink.innerHTML.toLowerCase().indexOf('readme') != -1 || activeLink.innerHTML.toLowerCase().indexOf('overview') != -1) {
251+
if (
252+
activeLink.innerHTML.toLowerCase().indexOf('readme') != -1 ||
253+
activeLink.innerHTML.toLowerCase().indexOf('overview') != -1
254+
) {
229255
activeMenu.scrollTop = 0;
230256
}
231257
}, 300);
232258
}
233259
}
234260
}, 0);
235-
});
261+
});

0 commit comments

Comments
 (0)