Skip to content

Commit

Permalink
feat(nxdev): add markdown display features (#5601)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcabanes committed May 8, 2021
1 parent 5b63507 commit da8285b
Show file tree
Hide file tree
Showing 9 changed files with 558 additions and 12 deletions.
5 changes: 2 additions & 3 deletions nx-dev/data-access-documents/src/lib/documents.api.ts
@@ -1,7 +1,7 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import matter from 'gray-matter';
import * as marked from 'marked';
import { readJsonFile } from '@nrwl/workspace';
import {
archiveRootPath,
extractTitle,
Expand All @@ -12,7 +12,6 @@ import {
DocumentData,
DocumentMetadata,
} from './documents.models';
import { readJsonFile } from '@nrwl/workspace';

export function getDocument(
version: string,
Expand All @@ -32,7 +31,7 @@ export function getDocument(
return {
filePath: docPath,
data: file.data,
content: marked.parse(file.content),
content: file.content,
excerpt: file.excerpt,
};
}
Expand Down
49 changes: 47 additions & 2 deletions nx-dev/feature-doc-viewer/src/lib/content.tsx
@@ -1,15 +1,60 @@
import React from 'react';
import ReactMarkdown from 'react-markdown';
import gfm from 'remark-gfm';
import autolinkHeadings from 'rehype-autolink-headings';
import slug from 'rehype-slug';
import highlight from 'rehype-highlight/light';
import { transformLinkPath } from './renderers/transform-link-path';
import { transformImagePath } from './renderers/transform-image-path';
import { renderIframes } from './renderers/render-iframe';

export interface ContentProps {
data: string;
flavor: string;
version: string;
}

export function Content(props: ContentProps) {
return (
<div className="min-w-0 flex-auto px-4 sm:px-6 xl:px-8 pt-10 pb-24 lg:pb-16">
<div
<ReactMarkdown
remarkPlugins={[gfm]}
rehypePlugins={[
slug,
autolinkHeadings,
renderIframes,
[
highlight,
{
languages: {
bash: require('highlight.js/lib/languages/bash'),
console: require('highlight.js/lib/languages/markdown'), // TODO: clean from documentation's markdown
css: require('highlight.js/lib/languages/css'),
handlebars: require('highlight.js/lib/languages/handlebars'),
groovy: require('highlight.js/lib/languages/groovy'),
html: require('highlight.js/lib/languages/xml'),
javascript: require('highlight.js/lib/languages/javascript'),
json: require('highlight.js/lib/languages/json'),
jsonc: require('highlight.js/lib/languages/json'), // TODO: clean from documentation's markdown
text: require('highlight.js/lib/languages/markdown'),
txt: require('highlight.js/lib/languages/markdown'), // TODO: clean from documentation's markdown
typescript: require('highlight.js/lib/languages/typescript'),
typescriptx: require('highlight.js/lib/languages/typescript'), // TODO: clean from documentation's markdown
tsx: require('highlight.js/lib/languages/typescript'), // TODO: clean from documentation's markdown
shell: require('highlight.js/lib/languages/shell'),
yaml: require('highlight.js/lib/languages/yaml'),
},
plainText: ['treeview'],
},
],
]}
children={props.data}
transformLinkUri={transformLinkPath({
flavor: props.flavor,
version: props.version,
})}
transformImageUri={transformImagePath(props.version)}
className="prose max-w-none"
dangerouslySetInnerHTML={{ __html: props.data }}
/>
</div>
);
Expand Down
6 changes: 5 additions & 1 deletion nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx
Expand Up @@ -49,7 +49,11 @@ export function DocViewer({
className="min-w-0 w-full flex-auto lg:static lg:max-h-full lg:overflow-visible"
>
<div className="w-full flex">
<Content data={document.content} />
<Content
data={document.content}
flavor={flavor.value}
version={version.id}
/>
<div className="hidden xl:text-sm xl:block flex-none w-64 pl-8 mr-8">
<div className="flex flex-col justify-between overflow-y-auto sticky max-h-(screen-18) pt-10 pb-6 top-18">
<Toc />
Expand Down
21 changes: 21 additions & 0 deletions nx-dev/feature-doc-viewer/src/lib/renderers/render-iframe.ts
@@ -0,0 +1,21 @@
export function renderIframes(): (tree: any) => void {
return (tree): void => {
const iframeList = tree.children.filter(
(child) => child.type === 'raw' && child.value.includes('<iframe')
);
iframeList.forEach((item) => {
item.type = 'element';
item.tagName = 'iframe';
item.children = [];
item.properties = {};
let match;
const regex = new RegExp(
'[\\s\\r\\t\\n]*([a-z0-9\\-_]+)[\\s\\r\\t\\n]*=[\\s\\r\\t\\n]*([\'"])((?:\\\\\\2|(?!\\2).)*)\\2',
'ig'
);
while ((match = regex.exec(item.value))) {
item.properties[match[1]] = match[3];
}
});
};
}
@@ -0,0 +1,10 @@
import { uriTransformer } from 'react-markdown';

export function transformImagePath(version: string): (src: string) => string {
return (src) => {
if (/\.(gif|jpe?g|tiff?|png|webp|bmp)$/i.test(src)) {
src = `/${version}`.concat(src); // TODO: copy imgs into public folder, by version id
}
return uriTransformer(src);
};
}
18 changes: 18 additions & 0 deletions nx-dev/feature-doc-viewer/src/lib/renderers/transform-link-path.ts
@@ -0,0 +1,18 @@
import { uriTransformer } from 'react-markdown';

export function transformLinkPath(options: {
flavor: string;
version: string;
}): (href) => string {
return (href) =>
uriTransformer(
href
? href
.replace(
'%7B%7Bframework%7D%7D',
`${options.version}/${options.flavor}`
)
.replace('%7B%7Bversion%7D%7D', options.version)
: href
);
}
10 changes: 10 additions & 0 deletions nx-dev/nx-dev/styles/main.css
Expand Up @@ -2,6 +2,7 @@

/*! purgecss start ignore */
@import 'nx-dev/feature-search/src/lib/algolia-search.global.css';
@import 'highlight.js/styles/github-gist.css';
/*! purgecss end ignore */

@tailwind components;
Expand All @@ -11,3 +12,12 @@ svg {
shape-rendering: crispEdges;
text-rendering: optimizeLegibility;
}

/*
Code embed
*/
.prose pre {
background: inherit !important;
color: inherit !important;
border: 1px solid #e1e4e8;
}
8 changes: 6 additions & 2 deletions package.json
Expand Up @@ -258,12 +258,16 @@
"document-register-element": "^1.13.1",
"gray-matter": "^4.0.2",
"kill-port": "^1.6.1",
"marked": "^2.0.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-markdown": "^6.0.2",
"rehype-autolink-headings": "^5.0.1",
"rehype-highlight": "^4.1.0",
"rehype-slug": "^4.0.1",
"remark-gfm": "^1.0.0",
"weak-napi": "^2.0.2"
},
"resolutions": {
"ng-packagr/rxjs": "6.6.3"
}
}
}

0 comments on commit da8285b

Please sign in to comment.