From 3eeeb6a3fb4e7d024af0ec6e7932f638589beb21 Mon Sep 17 00:00:00 2001 From: Gaurav Jain Date: Thu, 29 Dec 2016 13:36:39 -0800 Subject: [PATCH] Add support for second-level headings from Markdown docs --- lib/services/menu.service.ts | 36 +++++++++++++++++++++++++++++++++++- lib/utils/md-renderer.ts | 22 ++++++++++++++++------ lib/utils/spec-manager.ts | 1 + 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/lib/services/menu.service.ts b/lib/services/menu.service.ts index a49971a5..56d3eb17 100644 --- a/lib/services/menu.service.ts +++ b/lib/services/menu.service.ts @@ -143,6 +143,12 @@ export class MenuService { while(currentItem) { if (currentItem.id) { selector = `[section="${currentItem.id}"] ` + selector; + // We only need to go up the chain for methods that + // might have multiple tags. For headers/subheaders + // we need to siply early terminate. + if (!currentItem.metadata) { + break; + } } currentItem = currentItem.parent; } @@ -234,12 +240,40 @@ export class MenuService { let id = 'section/' + slugify(header); let item = { name: header, - id: id + id: id, + items: null }; + item.items = this.getMarkdownSubheaders(item); + this.items.push(item); } } + getMarkdownSubheaders(parent: MenuItem):MenuItem[] { + let res = []; + + let schema = this.specMgr.schema; + for (let subheader of (>(schema.info && schema.info['x-redoc-markdown-subheaders'] || []))) { + let parts = subheader.split('/'); + let header = parts[0]; + if (parent.name !== header) { + continue; + } + + let name = parts[1]; + let id = parent.id + '/' + slugify(name); + + let subItem = { + name: name, + id: id, + parent: parent + }; + res.push(subItem); + } + + return res; + } + getMethodsItems(parent: MenuItem, tag:any):MenuItem[] { if (!tag.methods || !tag.methods.length) return null; diff --git a/lib/utils/md-renderer.ts b/lib/utils/md-renderer.ts index 06b5539e..b29417cb 100644 --- a/lib/utils/md-renderer.ts +++ b/lib/utils/md-renderer.ts @@ -22,6 +22,8 @@ const md = new Remarkable({ @Injectable() export class MdRenderer { public firstLevelHeadings: string[] = []; + public secondLevelHeadings: string[] = []; + public currentHeading: string = null; private _origRules:any = {}; private _preProcessors:Function[] = []; @@ -44,19 +46,27 @@ export class MdRenderer { } headingOpenRule(tokens, idx) { - if (tokens[idx].hLevel !== 1 ) { + if (tokens[idx].hLevel > 2 ) { return this._origRules.open(tokens, idx); } else { let content = tokens[idx + 1].content; - this.firstLevelHeadings.push(content); - let contentSlug = slugify(content); - return `` + - ``; + if (tokens[idx].hLevel === 1 ) { + this.firstLevelHeadings.push(content); + this.currentHeading = content; + let contentSlug = slugify(content); + return `` + + ``; + } else if (tokens[idx].hLevel === 2 ) { + this.secondLevelHeadings.push(this.currentHeading + `/` + content); + let contentSlug = slugify(this.currentHeading) + `/` + slugify(content); + return `` + + ``; + } } } headingCloseRule(tokens, idx) { - if (tokens[idx].hLevel !== 1 ) { + if (tokens[idx].hLevel > 2 ) { return this._origRules.close(tokens, idx); } else { return `\n`; diff --git a/lib/utils/spec-manager.ts b/lib/utils/spec-manager.ts index 7a9e3c94..4f63f608 100644 --- a/lib/utils/spec-manager.ts +++ b/lib/utils/spec-manager.ts @@ -72,6 +72,7 @@ export class SpecManager { } this._schema.info['x-redoc-html-description'] = mdRender.renderMd(this._schema.info.description); this._schema.info['x-redoc-markdown-headers'] = mdRender.firstLevelHeadings; + this._schema.info['x-redoc-markdown-subheaders'] = mdRender.secondLevelHeadings; } get schema() {