docs(core): fix relative image paths (#5635)

This commit is contained in:
Jack Hsu 2021-05-12 11:04:55 -04:00 committed by GitHub
parent 0bd6deaa65
commit 6db97832e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 87 additions and 13 deletions

View File

@ -1,5 +1,5 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { join, relative } from 'path';
import matter from 'gray-matter';
import { readJsonFile } from '@nrwl/workspace';
import {
@ -29,7 +29,10 @@ export function getDocument(
}
return {
filePath: docPath,
filePath: relative(
version === 'preview' ? previewRootPath : archiveRootPath,
docPath
),
data: file.data,
content: file.content,
excerpt: file.excerpt,

View File

@ -5,7 +5,18 @@ import Content from './content';
describe('Content', () => {
it('should render successfully', () => {
const { baseElement } = render(<Content data="hello" />);
const { baseElement } = render(
<Content
version="1.0.0"
flavor="react"
document={{
content: '',
data: {},
filePath: 'a/b/test.md',
excerpt: '',
}}
/>
);
expect(baseElement).toBeTruthy();
});
});

View File

@ -3,6 +3,7 @@ import ReactMarkdown from 'react-markdown';
import autolinkHeadings from 'rehype-autolink-headings';
import gfm from 'remark-gfm';
import slug from 'rehype-slug';
import { DocumentData } from '@nrwl/nx-dev/data-access-documents';
import { transformLinkPath } from './renderers/transform-link-path';
import { transformImagePath } from './renderers/transform-image-path';
@ -10,7 +11,7 @@ import { renderIframes } from './renderers/render-iframe';
import { CodeBlock } from './code-block';
export interface ContentProps {
data: string;
document: DocumentData;
flavor: string;
version: string;
}
@ -41,12 +42,15 @@ export function Content(props: ContentProps) {
<ReactMarkdown
remarkPlugins={[gfm]}
rehypePlugins={[slug, autolinkHeadings, renderIframes]}
children={props.data}
children={props.document.content}
transformLinkUri={transformLinkPath({
flavor: props.flavor,
version: props.version,
})}
transformImageUri={transformImagePath(props.version)}
transformImageUri={transformImagePath({
version: props.version,
document: props.document,
})}
className="prose max-w-none"
components={components}
/>

View File

@ -48,7 +48,7 @@ export function DocViewer({
className="min-w-0 w-full flex-auto lg:static lg:max-h-full lg:overflow-visible"
>
<Content
data={document.content}
document={document}
flavor={flavor.value}
version={version.path}
/>

View File

@ -0,0 +1,39 @@
import { transformImagePath } from './transform-image-path';
describe('transformImagePath', () => {
it('should transform relative paths', () => {
const opts = {
version: '1.0.0',
document: { content: '', excerpt: '', filePath: 'a/b/test.md', data: {} },
};
const transform = transformImagePath(opts);
expect(transform('./test.png')).toEqual('/documentation/a/b/test.png');
expect(transform('../test.png')).toEqual('/documentation/a/test.png');
expect(transform('../../test.png')).toEqual('/documentation/test.png');
});
it('should transform absolute paths', () => {
const opts = {
version: '1.0.0',
document: { content: '', excerpt: '', filePath: 'a/b/test.md', data: {} },
};
const transform = transformImagePath(opts);
expect(transform('/shared/test.png')).toEqual(
'/documentation/1.0.0/shared/test.png'
);
});
it('should support preview links', () => {
const opts = {
version: 'preview',
document: { content: '', excerpt: '', filePath: 'a/b/test.md', data: {} },
};
const transform = transformImagePath(opts);
expect(transform('/shared/test.png')).toEqual(
'/api/preview-asset?uri=%2Fshared%2Ftest.png&document=a%2Fb%2Ftest.md'
);
});
});

View File

@ -1,12 +1,26 @@
import { uriTransformer } from 'react-markdown';
import { DocumentData } from '@nrwl/nx-dev/data-access-documents';
import { join } from 'path';
export function transformImagePath(version: string): (src: string) => string {
export function transformImagePath({
version,
document,
}: {
version: string;
document: DocumentData;
}): (src: string) => string {
return (src) => {
if (/\.(gif|jpe?g|tiff?|png|webp|bmp)$/i.test(src)) {
if (version === 'preview') {
src = `/api/preview-asset?uri=${encodeURIComponent(src)}`;
src = `/api/preview-asset?uri=${encodeURIComponent(
src
)}&document=${encodeURIComponent(document.filePath)}`;
} else {
src = `/documentation/${version}`.concat(src);
if (src.startsWith('.')) {
src = join('/documentation', document.filePath, '..', src);
} else {
src = `/documentation/${version}`.concat(src);
}
}
}
return uriTransformer(src);

View File

@ -8,12 +8,15 @@ import * as send from 'send';
const previewRootPath = join(appRootPath, 'docs');
export default function (req: NextApiRequest, res: NextApiResponse) {
return new Promise<void>((resolve, reject) => {
if (Array.isArray(req.query.uri)) {
return new Promise<void>((resolve) => {
if (Array.isArray(req.query.uri) || Array.isArray(req.query.document)) {
res.writeHead(422, { 'Content-Type': 'text/plain' });
res.end('Invalid URI');
} else {
const stream = send(req, decodeURIComponent(req.query.uri), {
const uri = decodeURIComponent(req.query.uri);
const document = decodeURIComponent(req.query.document);
const src = uri.startsWith('.') ? join(document, '..', uri) : uri;
const stream = send(req, src, {
// Files outside of the root are forbidden and will result in 404.
root: previewRootPath,
});