mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-26 18:43:43 +03:00
Refactor markdown headings parsing
This commit is contained in:
parent
1ff87ce665
commit
7fa850b41d
|
@ -8,7 +8,7 @@ import { SpecManager } from '../utils/spec-manager';
|
||||||
import { SchemaHelper } from './schema-helper.service';
|
import { SchemaHelper } from './schema-helper.service';
|
||||||
import { AppStateService } from './app-state.service';
|
import { AppStateService } from './app-state.service';
|
||||||
import { LazyTasksService } from '../shared/components/LazyFor/lazy-for';
|
import { LazyTasksService } from '../shared/components/LazyFor/lazy-for';
|
||||||
import { JsonPointer } from '../utils/JsonPointer';
|
import { JsonPointer, MarkdownHeading, StringMap } from '../utils/';
|
||||||
import * as slugify from 'slugify';
|
import * as slugify from 'slugify';
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,40 +250,35 @@ export class MenuService {
|
||||||
|
|
||||||
addMarkdownItems() {
|
addMarkdownItems() {
|
||||||
let schema = this.specMgr.schema;
|
let schema = this.specMgr.schema;
|
||||||
for (let header of (<Array<string>>(schema.info && schema.info['x-redoc-markdown-headers'] || []))) {
|
let headings = schema.info['x-redoc-markdown-headers'] as StringMap<MarkdownHeading>;
|
||||||
let id = 'section/' + slugify(header);
|
Object.keys(headings).forEach(h => {
|
||||||
|
let heading = headings[h];
|
||||||
|
let id = 'section/' + heading.id;
|
||||||
let item = {
|
let item = {
|
||||||
name: header,
|
name: heading.title,
|
||||||
id: id,
|
id: id,
|
||||||
items: null
|
items: null
|
||||||
};
|
};
|
||||||
item.items = this.getMarkdownSubheaders(item);
|
item.items = this.getMarkdownSubheaders(item, heading);
|
||||||
|
|
||||||
this.items.push(item);
|
this.items.push(item);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getMarkdownSubheaders(parent: MenuItem):MenuItem[] {
|
getMarkdownSubheaders(parent: MenuItem, parentHeading: MarkdownHeading):MenuItem[] {
|
||||||
let res = [];
|
let res = [];
|
||||||
|
|
||||||
let schema = this.specMgr.schema;
|
Object.keys(parentHeading.children || {}).forEach(h => {
|
||||||
for (let subheader of (<Array<string>>(schema.info && schema.info['x-redoc-markdown-subheaders'] || []))) {
|
let heading = parentHeading.children[h];
|
||||||
let parts = subheader.split('/');
|
let id = 'section/' + heading.id;
|
||||||
let header = parts[0];
|
|
||||||
if (parent.name !== header) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = parts[1];
|
|
||||||
let id = parent.id + '/' + slugify(name);
|
|
||||||
|
|
||||||
let subItem = {
|
let subItem = {
|
||||||
name: name,
|
name: heading.title,
|
||||||
id: id,
|
id: id,
|
||||||
parent: parent
|
parent: parent
|
||||||
};
|
};
|
||||||
res.push(subItem);
|
res.push(subItem);
|
||||||
}
|
});
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import * as slugify from 'slugify';
|
import * as slugify from 'slugify';
|
||||||
import * as Remarkable from 'remarkable';
|
import * as Remarkable from 'remarkable';
|
||||||
|
import { StringMap } from './';
|
||||||
|
|
||||||
declare var Prism: any;
|
declare var Prism: any;
|
||||||
const md = new Remarkable({
|
const md = new Remarkable({
|
||||||
|
@ -19,11 +20,17 @@ const md = new Remarkable({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export interface MarkdownHeading {
|
||||||
|
title?: string;
|
||||||
|
id: string;
|
||||||
|
content?: string;
|
||||||
|
children?: StringMap<MarkdownHeading>;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MdRenderer {
|
export class MdRenderer {
|
||||||
public firstLevelHeadings: string[] = [];
|
public headings: StringMap<MarkdownHeading> = {};
|
||||||
public secondLevelHeadings: string[] = [];
|
currentTopHeading: MarkdownHeading;
|
||||||
public currentHeading: string = null;
|
|
||||||
|
|
||||||
private _origRules:any = {};
|
private _origRules:any = {};
|
||||||
private _preProcessors:Function[] = [];
|
private _preProcessors:Function[] = [];
|
||||||
|
@ -45,21 +52,31 @@ export class MdRenderer {
|
||||||
md.renderer.rules.heading_close = this._origRules.close;
|
md.renderer.rules.heading_close = this._origRules.close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveHeading(title: string, parent:MarkdownHeading = {id:null, children: this.headings}) :MarkdownHeading {
|
||||||
|
let id = slugify(title);
|
||||||
|
if (parent && parent.id) id = `${parent.id}/${id}`;
|
||||||
|
parent.children = parent.children || {};
|
||||||
|
parent.children[id] = {
|
||||||
|
title,
|
||||||
|
id
|
||||||
|
};
|
||||||
|
return parent.children[id];
|
||||||
|
}
|
||||||
|
|
||||||
headingOpenRule(tokens, idx) {
|
headingOpenRule(tokens, idx) {
|
||||||
if (tokens[idx].hLevel > 2 ) {
|
if (tokens[idx].hLevel > 2 ) {
|
||||||
return this._origRules.open(tokens, idx);
|
return this._origRules.open(tokens, idx);
|
||||||
} else {
|
} else {
|
||||||
let content = tokens[idx + 1].content;
|
let content = tokens[idx + 1].content;
|
||||||
if (tokens[idx].hLevel === 1 ) {
|
if (tokens[idx].hLevel === 1 ) {
|
||||||
this.firstLevelHeadings.push(content);
|
this.currentTopHeading = this.saveHeading(content);;
|
||||||
this.currentHeading = content;
|
let id = this.currentTopHeading.id;
|
||||||
let contentSlug = slugify(content);
|
return `<h${tokens[idx].hLevel} section="section/${id}">` +
|
||||||
return `<h${tokens[idx].hLevel} section="section/${contentSlug}">` +
|
`<a class="share-link" href="#section/${id}"></a>`;
|
||||||
`<a class="share-link" href="#section/${contentSlug}"></a>`;
|
|
||||||
} else if (tokens[idx].hLevel === 2 ) {
|
} else if (tokens[idx].hLevel === 2 ) {
|
||||||
this.secondLevelHeadings.push(this.currentHeading + `/` + content);
|
let heading = this.saveHeading(content, this.currentTopHeading);
|
||||||
let contentSlug = slugify(this.currentHeading) + `/` + slugify(content);
|
let contentSlug = `${heading.id}`;
|
||||||
return `<h${tokens[idx].hLevel} section="section/${contentSlug}">` +
|
return `<h${tokens[idx].hLevel} section="section/${heading.id}">` +
|
||||||
`<a class="share-link" href="#section/${contentSlug}"></a>`;
|
`<a class="share-link" href="#section/${contentSlug}"></a>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,7 @@ export class SpecManager {
|
||||||
mdRender.addPreprocessor(SecurityDefinitions.insertTagIntoDescription);
|
mdRender.addPreprocessor(SecurityDefinitions.insertTagIntoDescription);
|
||||||
}
|
}
|
||||||
this._schema.info['x-redoc-html-description'] = mdRender.renderMd(this._schema.info.description);
|
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-headers'] = mdRender.headings;
|
||||||
this._schema.info['x-redoc-markdown-subheaders'] = mdRender.secondLevelHeadings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get schema() {
|
get schema() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user