@docusaurus/mdx-loader 2.0.0-beta.15a2b59f9 → 2.0.0-beta.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +24 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +178 -0
- package/lib/index.js.map +1 -0
- package/lib/remark/headings/index.d.ts +9 -0
- package/lib/remark/headings/index.d.ts.map +1 -0
- package/lib/remark/headings/index.js +60 -0
- package/lib/remark/headings/index.js.map +1 -0
- package/lib/remark/toc/index.d.ts +13 -0
- package/lib/remark/toc/index.d.ts.map +1 -0
- package/lib/remark/toc/index.js +81 -0
- package/lib/remark/toc/index.js.map +1 -0
- package/lib/remark/transformImage/index.d.ts +14 -0
- package/lib/remark/transformImage/index.d.ts.map +1 -0
- package/lib/remark/transformImage/index.js +109 -0
- package/lib/remark/transformImage/index.js.map +1 -0
- package/lib/remark/transformLinks/index.d.ts +14 -0
- package/lib/remark/transformLinks/index.d.ts.map +1 -0
- package/lib/remark/transformLinks/index.js +100 -0
- package/lib/remark/transformLinks/index.js.map +1 -0
- package/lib/remark/unwrapMdxCodeBlocks/index.d.ts +9 -0
- package/lib/remark/unwrapMdxCodeBlocks/index.d.ts.map +1 -0
- package/lib/remark/unwrapMdxCodeBlocks/index.js +29 -0
- package/lib/remark/unwrapMdxCodeBlocks/index.js.map +1 -0
- package/lib/remark/utils/index.d.ts +11 -0
- package/lib/remark/utils/index.d.ts.map +1 -0
- package/lib/remark/utils/index.js +38 -0
- package/lib/remark/utils/index.js.map +1 -0
- package/package.json +19 -16
- package/src/deps.d.ts +30 -0
- package/src/index.ts +225 -0
- package/src/{index.d.ts → mdx-loader.d.ts} +7 -8
- package/src/remark/headings/{index.js → index.ts} +22 -23
- package/src/remark/toc/index.ts +102 -0
- package/src/remark/transformImage/index.ts +167 -0
- package/src/remark/transformLinks/index.ts +150 -0
- package/src/remark/unwrapMdxCodeBlocks/{index.js → index.ts} +14 -15
- package/src/remark/utils/index.ts +37 -0
- package/src/index.js +0 -107
- package/src/remark/headings/__tests__/index.test.js +0 -315
- package/src/remark/toc/__tests__/__snapshots__/index.test.js.snap +0 -85
- package/src/remark/toc/__tests__/fixtures/empty-headings.md +0 -5
- package/src/remark/toc/__tests__/fixtures/inline-code.md +0 -9
- package/src/remark/toc/__tests__/fixtures/insert-below-imports.md +0 -11
- package/src/remark/toc/__tests__/fixtures/just-content.md +0 -15
- package/src/remark/toc/__tests__/fixtures/name-exist.md +0 -7
- package/src/remark/toc/__tests__/fixtures/non-text-content.md +0 -9
- package/src/remark/toc/__tests__/index.test.js +0 -212
- package/src/remark/toc/index.js +0 -79
- package/src/remark/toc/search.js +0 -73
- package/src/remark/transformImage/__tests__/__snapshots__/index.test.js.snap +0 -31
- package/src/remark/transformImage/__tests__/fixtures/fail.md +0 -1
- package/src/remark/transformImage/__tests__/fixtures/img.md +0 -17
- package/src/remark/transformImage/__tests__/fixtures/img.png +0 -0
- package/src/remark/transformImage/__tests__/fixtures/noUrl.md +0 -1
- package/src/remark/transformImage/__tests__/fixtures/pathname.md +0 -1
- package/src/remark/transformImage/__tests__/index.test.js +0 -59
- package/src/remark/transformImage/index.js +0 -106
- package/src/remark/transformLinks/__tests__/__snapshots__/index.test.js.snap +0 -41
- package/src/remark/transformLinks/__tests__/fixtures/asset.md +0 -29
- package/src/remark/transformLinks/__tests__/fixtures/asset.pdf +0 -0
- package/src/remark/transformLinks/__tests__/fixtures/noUrl.md +0 -1
- package/src/remark/transformLinks/__tests__/fixtures/pathname.md +0 -1
- package/src/remark/transformLinks/__tests__/fixtures/static/staticAsset.pdf +0 -0
- package/src/remark/transformLinks/__tests__/fixtures/static/staticAssetImage.png +0 -0
- package/src/remark/transformLinks/__tests__/index.test.js +0 -44
- package/src/remark/transformLinks/index.js +0 -143
- package/src/remark/unwrapMdxCodeBlocks/__tests__/__snapshots__/index.test.js.snap +0 -819
- package/src/remark/unwrapMdxCodeBlocks/__tests__/fixtures/has-mdx-code-blocks.mdx +0 -95
- package/src/remark/unwrapMdxCodeBlocks/__tests__/index.test.js +0 -38
- package/src/remark/utils/index.js +0 -39
- package/tsconfig.json +0 -9
package/src/remark/toc/index.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const {parse} = require('@babel/parser');
|
|
9
|
-
const traverse = require('@babel/traverse').default;
|
|
10
|
-
const stringifyObject = require('stringify-object');
|
|
11
|
-
const search = require('./search');
|
|
12
|
-
|
|
13
|
-
const parseOptions = {
|
|
14
|
-
plugins: ['jsx'],
|
|
15
|
-
sourceType: 'module',
|
|
16
|
-
};
|
|
17
|
-
const isImport = (child) => child.type === 'import';
|
|
18
|
-
const hasImports = (index) => index > -1;
|
|
19
|
-
const isExport = (child) => child.type === 'export';
|
|
20
|
-
|
|
21
|
-
const isTarget = (child, name) => {
|
|
22
|
-
let found = false;
|
|
23
|
-
const ast = parse(child.value, parseOptions);
|
|
24
|
-
traverse(ast, {
|
|
25
|
-
VariableDeclarator: (path) => {
|
|
26
|
-
if (path.node.id.name === name) {
|
|
27
|
-
found = true;
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
return found;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const getOrCreateExistingTargetIndex = (children, name) => {
|
|
36
|
-
let importsIndex = -1;
|
|
37
|
-
let targetIndex = -1;
|
|
38
|
-
|
|
39
|
-
children.forEach((child, index) => {
|
|
40
|
-
if (isImport(child)) {
|
|
41
|
-
importsIndex = index;
|
|
42
|
-
} else if (isExport(child) && isTarget(child, name)) {
|
|
43
|
-
targetIndex = index;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
if (targetIndex === -1) {
|
|
48
|
-
const target = {
|
|
49
|
-
default: false,
|
|
50
|
-
type: 'export',
|
|
51
|
-
value: `export const ${name} = [];`,
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
targetIndex = hasImports(importsIndex) ? importsIndex + 1 : 0;
|
|
55
|
-
children.splice(targetIndex, 0, target);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return targetIndex;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const plugin = (options = {}) => {
|
|
62
|
-
const name = options.name || 'toc';
|
|
63
|
-
|
|
64
|
-
const transformer = (node) => {
|
|
65
|
-
const headings = search(node);
|
|
66
|
-
const {children} = node;
|
|
67
|
-
const targetIndex = getOrCreateExistingTargetIndex(children, name);
|
|
68
|
-
|
|
69
|
-
if (headings && headings.length) {
|
|
70
|
-
children[targetIndex].value = `export const ${name} = ${stringifyObject(
|
|
71
|
-
headings,
|
|
72
|
-
)};`;
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
return transformer;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
module.exports = plugin;
|
package/src/remark/toc/search.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// @ts-check
|
|
9
|
-
|
|
10
|
-
const toString = require('mdast-util-to-string');
|
|
11
|
-
const visit = require('unist-util-visit');
|
|
12
|
-
// Destructuring require tslib
|
|
13
|
-
// eslint-disable-next-line prefer-destructuring
|
|
14
|
-
const toValue = require('../utils').toValue;
|
|
15
|
-
|
|
16
|
-
/** @typedef {import('@docusaurus/types').TOCItem} TOC */
|
|
17
|
-
/** @typedef {import('unist').Node} Node */
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @typedef {Object} StringValuedNode
|
|
21
|
-
* @property {string} type
|
|
22
|
-
* @property {string} value
|
|
23
|
-
* @property {number} depth
|
|
24
|
-
* @property {Object} data
|
|
25
|
-
* @property {StringValuedNode[]} children
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
// Visit all headings. We `slug` all headings (to account for
|
|
29
|
-
// duplicates), but only take h2 and h3 headings.
|
|
30
|
-
/**
|
|
31
|
-
* @param {StringValuedNode} node
|
|
32
|
-
* @returns {TOC[]}
|
|
33
|
-
*/
|
|
34
|
-
function search(node) {
|
|
35
|
-
/** @type {TOC[]} */
|
|
36
|
-
const headings = [];
|
|
37
|
-
let current = -1;
|
|
38
|
-
let currentDepth = 0;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {StringValuedNode} child
|
|
42
|
-
* @param {number} index
|
|
43
|
-
* @param {Node | undefined} parent
|
|
44
|
-
* @returns {void}
|
|
45
|
-
*/
|
|
46
|
-
const onHeading = (child, index, parent) => {
|
|
47
|
-
const value = toString(child);
|
|
48
|
-
|
|
49
|
-
if (parent !== node || !value || child.depth > 3 || child.depth < 2) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const entry = {
|
|
54
|
-
value: toValue(child),
|
|
55
|
-
id: child.data.id,
|
|
56
|
-
children: [],
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
if (!headings.length || currentDepth >= child.depth) {
|
|
60
|
-
headings.push(entry);
|
|
61
|
-
current += 1;
|
|
62
|
-
currentDepth = child.depth;
|
|
63
|
-
} else {
|
|
64
|
-
headings[current].children.push(entry);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
visit(node, 'heading', onHeading);
|
|
69
|
-
|
|
70
|
-
return headings;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
module.exports = search;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`transformImage plugin fail if image does not exist 1`] = `"Image packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img/doesNotExist.png used in packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/fail.md not found."`;
|
|
4
|
-
|
|
5
|
-
exports[`transformImage plugin fail if image url is absent 1`] = `"Markdown image URL is mandatory in \\"packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/noUrl.md\\" file"`;
|
|
6
|
-
|
|
7
|
-
exports[`transformImage plugin pathname protocol 1`] = `
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
`;
|
|
11
|
-
|
|
12
|
-
exports[`transformImage plugin transform md images to <img /> 1`] = `
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
<img src={require(\\"!url-loader?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=file-loader!./img.png\\").default} />
|
|
16
|
-
|
|
17
|
-
<img alt={\\"img\\"} src={require(\\"!url-loader?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=file-loader!./img.png\\").default} />
|
|
18
|
-
|
|
19
|
-
<img alt={\\"img\\"} src={require(\\"!url-loader?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=file-loader!./img.png\\").default} title=\\"Title\\" /> <img alt={\\"img\\"} src={require(\\"!url-loader?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=file-loader!packages/docusaurus-mdx-loader/src/remark/transformImage/__tests__/fixtures/img.png\\").default} />
|
|
20
|
-
|
|
21
|
-
<img alt={\\"img with "quotes"\\"} src={require(\\"!url-loader?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=file-loader!./img.png\\").default} title=\\"'Quoted' title\\" />
|
|
22
|
-
|
|
23
|
-
## Heading
|
|
24
|
-
|
|
25
|
-
\`\`\`md
|
|
26
|
-

|
|
27
|
-
\`\`\`
|
|
28
|
-
|
|
29
|
-
<img alt={\\"img\\"} src={require(\\"!url-loader?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=file-loader!./img.png\\").default} />
|
|
30
|
-
"
|
|
31
|
-
`;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-

|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-

|
|
4
|
-
|
|
5
|
-

|
|
6
|
-
|
|
7
|
-
 
|
|
8
|
-
|
|
9
|
-

|
|
10
|
-
|
|
11
|
-
## Heading
|
|
12
|
-
|
|
13
|
-
```md
|
|
14
|
-

|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-

|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
![img]()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-

|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {join, relative} from 'path';
|
|
9
|
-
import remark from 'remark';
|
|
10
|
-
import mdx from 'remark-mdx';
|
|
11
|
-
import vfile from 'to-vfile';
|
|
12
|
-
import plugin from '../index';
|
|
13
|
-
import headings from '../../headings/index';
|
|
14
|
-
|
|
15
|
-
const processFixture = async (name, options) => {
|
|
16
|
-
const path = join(__dirname, 'fixtures', `${name}.md`);
|
|
17
|
-
const file = await vfile.read(path);
|
|
18
|
-
const result = await remark()
|
|
19
|
-
.use(headings)
|
|
20
|
-
.use(mdx)
|
|
21
|
-
.use(plugin, {...options, filePath: path})
|
|
22
|
-
.process(file);
|
|
23
|
-
|
|
24
|
-
return result.toString();
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
// avoid hardcoding absolute
|
|
28
|
-
const staticDir = `./${relative(process.cwd(), join(__dirname, 'fixtures'))}`;
|
|
29
|
-
|
|
30
|
-
describe('transformImage plugin', () => {
|
|
31
|
-
test('fail if image does not exist', async () => {
|
|
32
|
-
await expect(
|
|
33
|
-
processFixture('fail', {
|
|
34
|
-
staticDir,
|
|
35
|
-
}),
|
|
36
|
-
).rejects.toThrowErrorMatchingSnapshot();
|
|
37
|
-
});
|
|
38
|
-
test('fail if image url is absent', async () => {
|
|
39
|
-
await expect(
|
|
40
|
-
processFixture('noUrl', {
|
|
41
|
-
staticDir,
|
|
42
|
-
}),
|
|
43
|
-
).rejects.toThrowErrorMatchingSnapshot();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('transform md images to <img />', async () => {
|
|
47
|
-
const result = await processFixture('img', {
|
|
48
|
-
staticDir,
|
|
49
|
-
});
|
|
50
|
-
expect(result).toMatchSnapshot();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('pathname protocol', async () => {
|
|
54
|
-
const result = await processFixture('pathname', {
|
|
55
|
-
staticDir,
|
|
56
|
-
});
|
|
57
|
-
expect(result).toMatchSnapshot();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const visit = require('unist-util-visit');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const url = require('url');
|
|
11
|
-
const fs = require('fs-extra');
|
|
12
|
-
const escapeHtml = require('escape-html');
|
|
13
|
-
const {getFileLoaderUtils} = require('@docusaurus/core/lib/webpack/utils');
|
|
14
|
-
const {
|
|
15
|
-
posixPath,
|
|
16
|
-
escapePath,
|
|
17
|
-
toMessageRelativeFilePath,
|
|
18
|
-
} = require('@docusaurus/utils');
|
|
19
|
-
|
|
20
|
-
const {
|
|
21
|
-
loaders: {inlineMarkdownImageFileLoader},
|
|
22
|
-
} = getFileLoaderUtils();
|
|
23
|
-
|
|
24
|
-
const createJSX = (node, pathUrl) => {
|
|
25
|
-
const jsxNode = node;
|
|
26
|
-
jsxNode.type = 'jsx';
|
|
27
|
-
jsxNode.value = `<img ${node.alt ? `alt={"${escapeHtml(node.alt)}"} ` : ''}${
|
|
28
|
-
node.url
|
|
29
|
-
? `src={require("${inlineMarkdownImageFileLoader}${escapePath(
|
|
30
|
-
pathUrl,
|
|
31
|
-
)}").default}`
|
|
32
|
-
: ''
|
|
33
|
-
}${node.title ? ` title="${escapeHtml(node.title)}"` : ''} />`;
|
|
34
|
-
|
|
35
|
-
if (jsxNode.url) {
|
|
36
|
-
delete jsxNode.url;
|
|
37
|
-
}
|
|
38
|
-
if (jsxNode.alt) {
|
|
39
|
-
delete jsxNode.alt;
|
|
40
|
-
}
|
|
41
|
-
if (jsxNode.title) {
|
|
42
|
-
delete jsxNode.title;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
async function ensureImageFileExist(imagePath, sourceFilePath) {
|
|
47
|
-
const imageExists = await fs.pathExists(imagePath);
|
|
48
|
-
if (!imageExists) {
|
|
49
|
-
throw new Error(
|
|
50
|
-
`Image ${toMessageRelativeFilePath(
|
|
51
|
-
imagePath,
|
|
52
|
-
)} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`,
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async function processImageNode(node, {filePath, staticDir}) {
|
|
58
|
-
if (!node.url) {
|
|
59
|
-
throw new Error(
|
|
60
|
-
`Markdown image URL is mandatory in "${toMessageRelativeFilePath(
|
|
61
|
-
filePath,
|
|
62
|
-
)}" file`,
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const parsedUrl = url.parse(node.url);
|
|
67
|
-
if (parsedUrl.protocol) {
|
|
68
|
-
// pathname:// is an escape hatch,
|
|
69
|
-
// in case user does not want his images to be converted to require calls going through webpack loader
|
|
70
|
-
// we don't have to document this for now,
|
|
71
|
-
// it's mostly to make next release less risky (2.0.0-alpha.59)
|
|
72
|
-
if (parsedUrl.protocol === 'pathname:') {
|
|
73
|
-
node.url = node.url.replace('pathname://', '');
|
|
74
|
-
} else {
|
|
75
|
-
// noop
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
// images without protocol
|
|
79
|
-
else if (path.isAbsolute(node.url)) {
|
|
80
|
-
// absolute paths are expected to exist in the static folder
|
|
81
|
-
const expectedImagePath = path.join(staticDir, node.url);
|
|
82
|
-
await ensureImageFileExist(expectedImagePath, filePath);
|
|
83
|
-
createJSX(node, posixPath(expectedImagePath));
|
|
84
|
-
}
|
|
85
|
-
// We try to convert image urls without protocol to images with require calls
|
|
86
|
-
// going through webpack ensures that image assets exist at build time
|
|
87
|
-
else {
|
|
88
|
-
// relative paths are resolved against the source file's folder
|
|
89
|
-
const expectedImagePath = path.join(path.dirname(filePath), node.url);
|
|
90
|
-
await ensureImageFileExist(expectedImagePath, filePath);
|
|
91
|
-
createJSX(node, node.url.startsWith('./') ? node.url : `./${node.url}`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const plugin = (options) => {
|
|
96
|
-
const transformer = async (root) => {
|
|
97
|
-
const promises = [];
|
|
98
|
-
visit(root, 'image', (node) => {
|
|
99
|
-
promises.push(processImageNode(node, options));
|
|
100
|
-
});
|
|
101
|
-
await Promise.all(promises);
|
|
102
|
-
};
|
|
103
|
-
return transformer;
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
module.exports = plugin;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`transformAsset plugin fail if asset url is absent 1`] = `"Markdown link URL is mandatory in \\"packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/fixtures/noUrl.md\\" file (title: asset, line: 1)."`;
|
|
4
|
-
|
|
5
|
-
exports[`transformAsset plugin pathname protocol 1`] = `
|
|
6
|
-
"[asset](pathname:///asset/unchecked.pdf)
|
|
7
|
-
"
|
|
8
|
-
`;
|
|
9
|
-
|
|
10
|
-
exports[`transformAsset plugin transform md links to <a /> 1`] = `
|
|
11
|
-
"[asset](https://example.com/asset.pdf)
|
|
12
|
-
|
|
13
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}></a>
|
|
14
|
-
|
|
15
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}>asset</a>
|
|
16
|
-
|
|
17
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}title=\\"Title\\">asset</a>
|
|
18
|
-
|
|
19
|
-
## Heading
|
|
20
|
-
|
|
21
|
-
\`\`\`md
|
|
22
|
-
[asset](./asset.pdf)
|
|
23
|
-
\`\`\`
|
|
24
|
-
|
|
25
|
-
[assets](!file-loader!./asset.pdf)
|
|
26
|
-
|
|
27
|
-
[assets](/github/!file-loader!/assets.pdf)
|
|
28
|
-
|
|
29
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}>asset</a>
|
|
30
|
-
|
|
31
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>staticAsset.pdf</a>
|
|
32
|
-
|
|
33
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>@site/static/staticAsset.pdf</a>
|
|
34
|
-
|
|
35
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>Just staticAsset.pdf</a>, and <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}><strong>awesome</strong> staticAsset 2.pdf 'It is really "AWESOME"'</a>, but also <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>coded <code>staticAsset 3.pdf</code></a>
|
|
36
|
-
|
|
37
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAssetImage.png').default}><img alt={\\"Clickable Docusaurus logo\\"} src={require(\\"!url-loader?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=file-loader!./static/staticAssetImage.png\\").default} /></a>
|
|
38
|
-
|
|
39
|
-
<a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}><span style={{color: \\"red\\"}}>Stylized link to asset file</span></a>
|
|
40
|
-
"
|
|
41
|
-
`;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
[asset](https://example.com/asset.pdf)
|
|
2
|
-
|
|
3
|
-
[](./asset.pdf)
|
|
4
|
-
|
|
5
|
-
[asset](./asset.pdf)
|
|
6
|
-
|
|
7
|
-
[asset](asset.pdf 'Title')
|
|
8
|
-
|
|
9
|
-
## Heading
|
|
10
|
-
|
|
11
|
-
```md
|
|
12
|
-
[asset](./asset.pdf)
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
[assets](!file-loader!./asset.pdf)
|
|
16
|
-
|
|
17
|
-
[assets](/github/!file-loader!/assets.pdf)
|
|
18
|
-
|
|
19
|
-
[asset](asset.pdf)
|
|
20
|
-
|
|
21
|
-
[staticAsset.pdf](/staticAsset.pdf)
|
|
22
|
-
|
|
23
|
-
[@site/static/staticAsset.pdf](@site/static/staticAsset.pdf)
|
|
24
|
-
|
|
25
|
-
[Just staticAsset.pdf](/staticAsset.pdf), and [**awesome** staticAsset 2.pdf 'It is really "AWESOME"'](/staticAsset.pdf), but also [coded `staticAsset 3.pdf`](/staticAsset.pdf)
|
|
26
|
-
|
|
27
|
-
[](/staticAssetImage.png)
|
|
28
|
-
|
|
29
|
-
[<span style={{color: "red"}}>Stylized link to asset file</span>](./asset.pdf)
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[asset]()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[asset](pathname:///asset/unchecked.pdf)
|
|
File without changes
|
|
Binary file
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {join} from 'path';
|
|
9
|
-
import remark from 'remark';
|
|
10
|
-
import mdx from 'remark-mdx';
|
|
11
|
-
import vfile from 'to-vfile';
|
|
12
|
-
import plugin from '..';
|
|
13
|
-
import transformImage from '../../transformImage';
|
|
14
|
-
|
|
15
|
-
const processFixture = async (name, options) => {
|
|
16
|
-
const path = join(__dirname, 'fixtures', `${name}.md`);
|
|
17
|
-
const staticDir = join(__dirname, 'fixtures', 'static');
|
|
18
|
-
const file = await vfile.read(path);
|
|
19
|
-
const result = await remark()
|
|
20
|
-
.use(mdx)
|
|
21
|
-
.use(transformImage, {...options, filePath: path, staticDir})
|
|
22
|
-
.use(plugin, {...options, filePath: path, staticDir})
|
|
23
|
-
.process(file);
|
|
24
|
-
|
|
25
|
-
return result.toString();
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
describe('transformAsset plugin', () => {
|
|
29
|
-
test('fail if asset url is absent', async () => {
|
|
30
|
-
await expect(
|
|
31
|
-
processFixture('noUrl'),
|
|
32
|
-
).rejects.toThrowErrorMatchingSnapshot();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('transform md links to <a />', async () => {
|
|
36
|
-
const result = await processFixture('asset');
|
|
37
|
-
expect(result).toMatchSnapshot();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('pathname protocol', async () => {
|
|
41
|
-
const result = await processFixture('pathname');
|
|
42
|
-
expect(result).toMatchSnapshot();
|
|
43
|
-
});
|
|
44
|
-
});
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
toMessageRelativeFilePath,
|
|
10
|
-
posixPath,
|
|
11
|
-
escapePath,
|
|
12
|
-
} = require('@docusaurus/utils');
|
|
13
|
-
|
|
14
|
-
const visit = require('unist-util-visit');
|
|
15
|
-
const path = require('path');
|
|
16
|
-
const url = require('url');
|
|
17
|
-
const fs = require('fs-extra');
|
|
18
|
-
const escapeHtml = require('escape-html');
|
|
19
|
-
const {toValue} = require('../utils');
|
|
20
|
-
const {getFileLoaderUtils} = require('@docusaurus/core/lib/webpack/utils');
|
|
21
|
-
|
|
22
|
-
const {
|
|
23
|
-
loaders: {inlineMarkdownLinkFileLoader},
|
|
24
|
-
} = getFileLoaderUtils();
|
|
25
|
-
|
|
26
|
-
async function ensureAssetFileExist(fileSystemAssetPath, sourceFilePath) {
|
|
27
|
-
const assetExists = await fs.pathExists(fileSystemAssetPath);
|
|
28
|
-
if (!assetExists) {
|
|
29
|
-
throw new Error(
|
|
30
|
-
`Asset ${toMessageRelativeFilePath(
|
|
31
|
-
fileSystemAssetPath,
|
|
32
|
-
)} used in ${toMessageRelativeFilePath(sourceFilePath)} not found.`,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// transform the link node to a jsx link with a require() call
|
|
38
|
-
function toAssetRequireNode({node, filePath, requireAssetPath}) {
|
|
39
|
-
/* eslint-disable no-param-reassign */
|
|
40
|
-
|
|
41
|
-
let relativeRequireAssetPath = posixPath(
|
|
42
|
-
path.relative(path.dirname(filePath), requireAssetPath),
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
// nodejs does not like require("assets/file.pdf")
|
|
46
|
-
relativeRequireAssetPath = relativeRequireAssetPath.startsWith('.')
|
|
47
|
-
? relativeRequireAssetPath
|
|
48
|
-
: `./${relativeRequireAssetPath}`;
|
|
49
|
-
|
|
50
|
-
const href = `require('${inlineMarkdownLinkFileLoader}${escapePath(
|
|
51
|
-
relativeRequireAssetPath,
|
|
52
|
-
)}').default`;
|
|
53
|
-
const children = (node.children || []).map((n) => toValue(n)).join('');
|
|
54
|
-
const title = node.title ? `title="${escapeHtml(node.title)}"` : '';
|
|
55
|
-
|
|
56
|
-
node.type = 'jsx';
|
|
57
|
-
node.value = `<a target="_blank" href={${href}}${title}>${children}</a>`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// If the link looks like an asset link, we'll link to the asset,
|
|
61
|
-
// and use a require("assetUrl") (using webpack url-loader/file-loader)
|
|
62
|
-
// instead of navigating to such link
|
|
63
|
-
async function convertToAssetLinkIfNeeded({node, staticDir, filePath}) {
|
|
64
|
-
const assetPath = node.url;
|
|
65
|
-
|
|
66
|
-
const hasSiteAlias = assetPath.startsWith('@site/');
|
|
67
|
-
const hasAssetLikeExtension =
|
|
68
|
-
path.extname(assetPath) && !assetPath.match(/#|.md|.mdx|.html/);
|
|
69
|
-
|
|
70
|
-
const looksLikeAssetLink = hasSiteAlias || hasAssetLikeExtension;
|
|
71
|
-
|
|
72
|
-
if (!looksLikeAssetLink) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function toAssetLinkNode(requireAssetPath) {
|
|
77
|
-
toAssetRequireNode({
|
|
78
|
-
node,
|
|
79
|
-
filePath,
|
|
80
|
-
requireAssetPath,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (assetPath.startsWith('@site/')) {
|
|
85
|
-
const siteDir = path.join(staticDir, '..');
|
|
86
|
-
const fileSystemAssetPath = path.join(
|
|
87
|
-
siteDir,
|
|
88
|
-
assetPath.replace('@site/', ''),
|
|
89
|
-
);
|
|
90
|
-
await ensureAssetFileExist(fileSystemAssetPath, filePath);
|
|
91
|
-
toAssetLinkNode(fileSystemAssetPath);
|
|
92
|
-
} else if (path.isAbsolute(assetPath)) {
|
|
93
|
-
const fileSystemAssetPath = path.join(staticDir, assetPath);
|
|
94
|
-
if (await fs.pathExists(fileSystemAssetPath)) {
|
|
95
|
-
toAssetLinkNode(fileSystemAssetPath);
|
|
96
|
-
}
|
|
97
|
-
} else {
|
|
98
|
-
const fileSystemAssetPath = path.join(path.dirname(filePath), assetPath);
|
|
99
|
-
if (await fs.pathExists(fileSystemAssetPath)) {
|
|
100
|
-
toAssetLinkNode(fileSystemAssetPath);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function processLinkNode({node, _index, _parent, filePath, staticDir}) {
|
|
106
|
-
if (!node.url) {
|
|
107
|
-
// try to improve error feedback
|
|
108
|
-
// see https://github.com/facebook/docusaurus/issues/3309#issuecomment-690371675
|
|
109
|
-
const title =
|
|
110
|
-
node.title || (node.children[0] && node.children[0].value) || '?';
|
|
111
|
-
const line =
|
|
112
|
-
(node.position && node.position.start && node.position.start.line) || '?';
|
|
113
|
-
throw new Error(
|
|
114
|
-
`Markdown link URL is mandatory in "${toMessageRelativeFilePath(
|
|
115
|
-
filePath,
|
|
116
|
-
)}" file (title: ${title}, line: ${line}).`,
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const parsedUrl = url.parse(node.url);
|
|
121
|
-
if (parsedUrl.protocol) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
await convertToAssetLinkIfNeeded({
|
|
126
|
-
node,
|
|
127
|
-
staticDir,
|
|
128
|
-
filePath,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const plugin = (options) => {
|
|
133
|
-
const transformer = async (root) => {
|
|
134
|
-
const promises = [];
|
|
135
|
-
visit(root, 'link', (node, index, parent) => {
|
|
136
|
-
promises.push(processLinkNode({node, index, parent, ...options}));
|
|
137
|
-
});
|
|
138
|
-
await Promise.all(promises);
|
|
139
|
-
};
|
|
140
|
-
return transformer;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
module.exports = plugin;
|