mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-29 20:13:43 +03:00
feat: experimental temporary support for tags in md
This commit is contained in:
parent
aaaa8999bf
commit
06ef51c08c
|
@ -1,8 +1,8 @@
|
||||||
import * as marked from 'marked';
|
import * as marked from 'marked';
|
||||||
|
|
||||||
import slugify from 'slugify';
|
import slugify from 'slugify';
|
||||||
import { MDComponent } from '../components/Markdown/Markdown';
|
|
||||||
import { highlight, html2Str } from '../utils';
|
import { highlight, html2Str } from '../utils';
|
||||||
|
import { AppStore } from './AppStore';
|
||||||
import { SECTION_ATTR } from './MenuStore';
|
import { SECTION_ATTR } from './MenuStore';
|
||||||
|
|
||||||
const renderer = new marked.Renderer();
|
const renderer = new marked.Renderer();
|
||||||
|
@ -14,9 +14,14 @@ marked.setOptions({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const COMPONENT_REGEXP = '^\\s*<!-- ReDoc-Inject:\\s+?{component}\\s+?-->\\s*$';
|
export const LEGACY_REGEXP = '^\\s*<!-- ReDoc-Inject:\\s+?{component}\\s+?-->\\s*$';
|
||||||
export function buildComponentComment(name: string) {
|
export const MDX_COMPONENT_REGEXP = '^\\s*<{component}\\s*?/>\\s*$';
|
||||||
return `<!-- ReDoc-Inject: <${name}> -->`;
|
export const COMPONENT_REGEXP = '(?:' + LEGACY_REGEXP + '|' + MDX_COMPONENT_REGEXP + ')';
|
||||||
|
|
||||||
|
export interface MDXComponentMeta {
|
||||||
|
component: React.ComponentType;
|
||||||
|
propsSelector: (store?: AppStore) => any;
|
||||||
|
attrs?: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MarkdownHeading {
|
export interface MarkdownHeading {
|
||||||
|
@ -26,6 +31,10 @@ export interface MarkdownHeading {
|
||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildComponentComment(name: string) {
|
||||||
|
return `<!-- ReDoc-Inject: <${name}> -->`;
|
||||||
|
}
|
||||||
|
|
||||||
export class MarkdownRenderer {
|
export class MarkdownRenderer {
|
||||||
headings: MarkdownHeading[] = [];
|
headings: MarkdownHeading[] = [];
|
||||||
currentTopHeading: MarkdownHeading;
|
currentTopHeading: MarkdownHeading;
|
||||||
|
@ -130,20 +139,30 @@ export class MarkdownRenderer {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: rewrite this completelly! Regexp-based 👎
|
||||||
|
// Use marked ecosystem
|
||||||
renderMdWithComponents(
|
renderMdWithComponents(
|
||||||
rawText: string,
|
rawText: string,
|
||||||
components: Dict<MDComponent>,
|
components: Dict<MDXComponentMeta>,
|
||||||
raw: boolean = true,
|
raw: boolean = true,
|
||||||
): Array<string | MDComponent> {
|
): Array<string | MDXComponentMeta> {
|
||||||
const componentDefs: string[] = [];
|
const componentDefs: string[] = [];
|
||||||
const anyCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '(.*?)'), 'gmi');
|
const names = '(?:' + Object.keys(components).join('|') + ')';
|
||||||
|
|
||||||
|
const anyCompRegexp = new RegExp(
|
||||||
|
COMPONENT_REGEXP.replace(/{component}/g, '(<?' + names + '.*?)'),
|
||||||
|
'gmi',
|
||||||
|
);
|
||||||
let match = anyCompRegexp.exec(rawText);
|
let match = anyCompRegexp.exec(rawText);
|
||||||
while (match) {
|
while (match) {
|
||||||
componentDefs.push(match[1]);
|
componentDefs.push(match[1] || match[2]);
|
||||||
match = anyCompRegexp.exec(rawText);
|
match = anyCompRegexp.exec(rawText);
|
||||||
}
|
}
|
||||||
|
|
||||||
const splitCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '.*?'), 'mi');
|
const splitCompRegexp = new RegExp(
|
||||||
|
COMPONENT_REGEXP.replace(/{component}/g, names + '.*?'),
|
||||||
|
'mi',
|
||||||
|
);
|
||||||
const htmlParts = rawText.split(splitCompRegexp);
|
const htmlParts = rawText.split(splitCompRegexp);
|
||||||
const res: any[] = [];
|
const res: any[] = [];
|
||||||
for (let i = 0; i < htmlParts.length; i++) {
|
for (let i = 0; i < htmlParts.length; i++) {
|
||||||
|
@ -171,6 +190,40 @@ function parseComponent(
|
||||||
): {
|
): {
|
||||||
componentName?: string;
|
componentName?: string;
|
||||||
attrs: any;
|
attrs: any;
|
||||||
|
} {
|
||||||
|
if (htmlTag.startsWith('<')) {
|
||||||
|
return legacyParse(htmlTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = /([\w_-]+)(\s+[\w_-]+\s*={[^}]*?})*/.exec(htmlTag);
|
||||||
|
if (match === null || match.length <= 1) {
|
||||||
|
return { componentName: undefined, attrs: {} };
|
||||||
|
}
|
||||||
|
const componentName = match[1];
|
||||||
|
const attrs = {};
|
||||||
|
for (let i = 2; i < match.length; i++) {
|
||||||
|
if (!match[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const [name, value] = match[i]
|
||||||
|
.trim()
|
||||||
|
.split('=')
|
||||||
|
.map(p => p.trim());
|
||||||
|
|
||||||
|
// tslint:disable-next-line
|
||||||
|
attrs[name] = value.startsWith('{') ? eval(value.substr(1, value.length - 2)) : eval(value);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
componentName,
|
||||||
|
attrs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function legacyParse(
|
||||||
|
htmlTag: string,
|
||||||
|
): {
|
||||||
|
componentName?: string;
|
||||||
|
attrs: any;
|
||||||
} {
|
} {
|
||||||
const match = /<([\w_-]+).*?>/.exec(htmlTag);
|
const match = /<([\w_-]+).*?>/.exec(htmlTag);
|
||||||
if (match === null || match.length <= 1) {
|
if (match === null || match.length <= 1) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user