feat(v2): support for adding relative images and handling broken image links (#3069)

* all relative path in image url

* throw error if file doesn't present

* better error

* add @docusaurus/core to deps

* fix test
This commit is contained in:
Anshul Goyal 2020-07-21 18:57:45 +05:30 committed by GitHub
parent 15e73daae7
commit 3155dc30dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 162 additions and 4 deletions

View file

@ -13,6 +13,7 @@ const matter = require('gray-matter');
const stringifyObject = require('stringify-object');
const slug = require('./remark/slug');
const rightToc = require('./remark/rightToc');
const relativePath = require('./remark/transformImage');
const DEFAULT_OPTIONS = {
rehypePlugins: [],
@ -29,6 +30,10 @@ module.exports = async function (fileString) {
remarkPlugins: [
...(reqOptions.beforeDefaultRemarkPlugins || []),
...DEFAULT_OPTIONS.remarkPlugins,
[
relativePath,
{staticDir: reqOptions.staticDir, filePath: this.resourcePath},
],
...(reqOptions.remarkPlugins || []),
],
rehypePlugins: [

View file

@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`transform md images to <img /> 1`] = `
"![img](https://example.com/img.png)
<img src={require(\\"!url-loader!./img.png\\").default} />
<img alt={\\"img\\"} src={require(\\"!url-loader!./img.png\\").default} />
<img alt={\\"img\\"} src={require(\\"!url-loader!./img.png\\").default} title={\\"Title\\"} /> ![img](/img.png)
## Heading
\`\`\`md
![img](./img.png)
\`\`\`
<img alt={\\"img\\"} src={require(\\"!url-loader!./img.png\\").default} />
"
`;

View file

@ -0,0 +1 @@
![img](/img/post.png)

View file

@ -0,0 +1,15 @@
![img](https://example.com/img.png)
![](./img.png)
![img](./img.png)
![img](./img.png 'Title') ![img](/img.png)
## Heading
```md
![img](./img.png)
```
![img](img.png)

View file

@ -0,0 +1,38 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {join} from 'path';
import remark from 'remark';
import mdx from 'remark-mdx';
import vfile from 'to-vfile';
import plugin from '../index';
import slug from '../../slug/index';
const processFixture = async (name, options) => {
const path = join(__dirname, 'fixtures', `${name}.md`);
const file = await vfile.read(path);
const result = await remark()
.use(slug)
.use(mdx)
.use(plugin, {...options, filePath: path})
.process(file);
return result.toString();
};
test('fail if image donot exists', async () => {
expect(
processFixture('fail', {staticDir: join(__dirname, 'fixtures')}),
).rejects.toBeInstanceOf(Error);
});
test('transform md images to <img />', async () => {
const result = await processFixture('img', {
staticDir: join(__dirname, 'fixtures'),
});
expect(result).toMatchSnapshot();
});

View file

@ -0,0 +1,59 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const visit = require('unist-util-visit');
const path = require('path');
const url = require('url');
const fs = require('fs-extra');
const plugin = (options) => {
const transformer = (root) => {
visit(root, 'image', (node) => {
if (!url.parse(node.url).protocol) {
if (!path.isAbsolute(node.url)) {
if (
!fs.existsSync(path.join(path.dirname(options.filePath), node.url))
) {
throw new Error(
`Image ${path.join(
path.dirname(options.filePath),
node.url,
)} used in ${options.filePath} not found.`,
);
}
node.type = 'jsx';
node.value = `<img ${node.alt ? `alt={"${node.alt}"}` : ''} ${
node.url
? `src={require("!url-loader!${
node.url.startsWith('./') ? node.url : `./${node.url}`
}").default}`
: ''
} ${node.title ? `title={"${node.title}"}` : ''} />`;
if (node.url) {
delete node.url;
}
if (node.alt) {
delete node.alt;
}
if (node.title) {
delete node.title;
}
} else if (!fs.existsSync(path.join(options.staticDir, node.url))) {
throw new Error(
`Image ${path.join(options.staticDir, node.url)} used in ${
options.filePath
} not found.`,
);
}
}
});
};
return transformer;
};
module.exports = plugin;