diff --git a/lib/services/menu.service.ts b/lib/services/menu.service.ts index ccdd3a2d..7cda8567 100644 --- a/lib/services/menu.service.ts +++ b/lib/services/menu.service.ts @@ -250,7 +250,7 @@ export class MenuService { addMarkdownItems() { let schema = this.specMgr.schema; - let headings = schema.info['x-redoc-markdown-headers'] as StringMap; + let headings:StringMap = schema.info && schema.info['x-redoc-markdown-headers'] || {}; Object.keys(headings).forEach(h => { let heading = headings[h]; let id = 'section/' + heading.id; @@ -413,7 +413,7 @@ export class MenuService { } getItemById(id: string):MenuItem { - return this.flatItems.find(item => item.id === id); + return this.flatItems.find(item => item.id === id || item.id === `section/${id}`); } destroy() { diff --git a/lib/services/search.service.ts b/lib/services/search.service.ts index eaaeb3ae..4bc72c52 100644 --- a/lib/services/search.service.ts +++ b/lib/services/search.service.ts @@ -1,7 +1,8 @@ import { Injectable } from '@angular/core'; import { AppStateService } from './app-state.service'; import { SchemaNormalizer } from './schema-normalizer.service'; -import { JsonPointer, groupBy, SpecManager, StringMap, snapshot } from '../utils/'; +import { JsonPointer, groupBy, SpecManager, StringMap, snapshot, MarkdownHeading } from '../utils/'; +import { methods as swaggerMethods } from '../utils/swagger-defs'; import * as slugify from 'slugify'; import { @@ -44,6 +45,7 @@ export class SearchService { console.time('Indexing'); this.indexPaths(this.spec.schema); this.indexTags(this.spec.schema); + this.indexDescriptionHeadings(this.spec.schema.info['x-redoc-markdown-headers']); console.time('Indexing end'); } @@ -64,6 +66,21 @@ export class SearchService { store[element.pointer] = element; } + indexDescriptionHeadings(headings:StringMap) { + if (!headings) return; + Object.keys(headings).forEach(k => { + let heading = headings[k]; + this.index({ + menuId: heading.id, + title: heading.title, + body: heading.content, + pointer: '/heading/' + heading.id + }); + + this.indexDescriptionHeadings(heading.children); + }); + } + indexTags(swagger:SwaggerSpec) { let tags = swagger.tags; for (let tag of tags) { @@ -84,8 +101,10 @@ export class SearchService { Object.keys(paths).forEach(path => { let opearations = paths[path]; Object.keys(opearations).forEach(verb => { + if (!swaggerMethods.has(verb)) return; const opearation = opearations[verb]; const ptr = JsonPointer.join(basePtr, [path, verb]); + this.indexOperation(opearation, ptr); }); }); diff --git a/lib/utils/md-renderer.ts b/lib/utils/md-renderer.ts index ea16309f..d4c6ab0d 100644 --- a/lib/utils/md-renderer.ts +++ b/lib/utils/md-renderer.ts @@ -63,6 +63,45 @@ export class MdRenderer { return parent.children[id]; } + flattenHeadings(container: StringMap): MarkdownHeading[] { + if (!container) return []; + let res = []; + Object.keys(container).forEach(k => { + let heading = container[k]; + res.push(heading); + res.push(...this.flattenHeadings(heading.children)); + }); + return res; + } + + attachHeadingsContent(rawText:string) { + const buildRegexp = heading => new RegExp( + `` + ); + + const tmpEl = document.createElement('DIV'); + + const html2Str = html => { + tmpEl.innerHTML = html; + return tmpEl.innerText; + }; + + let flatHeadings = this.flattenHeadings(this.headings); + if (flatHeadings.length < 1) return; + let prevHeading = flatHeadings[0]; + + let prevPos = rawText.search(buildRegexp(prevHeading)); + for (let i=1; i < flatHeadings.length; i++) { + let heading = flatHeadings[i]; + let currentPos = rawText.substr(prevPos + 1).search(buildRegexp(heading)) + prevPos + 1; + prevHeading.content = html2Str(rawText.substring(prevPos, currentPos)); + + prevHeading = heading; + prevPos = currentPos; + } + prevHeading.content = html2Str(rawText.substring(prevPos)); + } + headingOpenRule(tokens, idx) { if (tokens[idx].hLevel > 2 ) { return this._origRules.open(tokens, idx); @@ -104,6 +143,8 @@ export class MdRenderer { let res = md.render(text); + this.attachHeadingsContent(res); + if (!this.raw) { this.restoreOrigRules(); }