feat: experimental temporary support for tags in md

This commit is contained in:
Roman Hotsiy 2018-06-28 20:12:39 +03:00
parent aaaa8999bf
commit 06ef51c08c
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0

View File

@ -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) {