@docusaurus/mdx-loader 2.0.0-beta.7fe2a9891 → 2.0.0-beta.8

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.
Files changed (43) hide show
  1. package/lib/.tsbuildinfo +1 -0
  2. package/lib/index.d.ts +12 -0
  3. package/lib/index.js +161 -0
  4. package/lib/remark/headings/index.d.ts +9 -0
  5. package/lib/remark/headings/index.js +62 -0
  6. package/lib/remark/toc/index.d.ts +12 -0
  7. package/lib/remark/toc/index.js +67 -0
  8. package/lib/remark/toc/search.d.ts +13 -0
  9. package/lib/remark/toc/search.js +66 -0
  10. package/lib/remark/transformImage/index.d.ts +13 -0
  11. package/lib/remark/transformImage/index.js +80 -0
  12. package/lib/remark/transformLinks/index.d.ts +13 -0
  13. package/lib/remark/transformLinks/index.js +104 -0
  14. package/lib/remark/unwrapMdxCodeBlocks/index.d.ts +9 -0
  15. package/lib/remark/unwrapMdxCodeBlocks/index.js +28 -0
  16. package/lib/remark/utils/index.d.ts +10 -0
  17. package/lib/remark/utils/index.js +39 -0
  18. package/package.json +13 -8
  19. package/src/index.ts +200 -0
  20. package/src/remark/headings/__tests__/{index.test.js → index.test.ts} +0 -2
  21. package/src/remark/headings/{index.js → index.ts} +22 -14
  22. package/src/remark/toc/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +20 -10
  23. package/src/remark/toc/__tests__/{index.test.js → index.test.ts} +29 -15
  24. package/src/remark/toc/__tests__/search.test.ts +182 -0
  25. package/src/remark/toc/{index.js → index.ts} +24 -16
  26. package/src/remark/toc/search.ts +82 -0
  27. package/src/remark/transformImage/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
  28. package/src/remark/transformImage/__tests__/{index.test.js → index.test.ts} +0 -0
  29. package/src/remark/transformImage/{index.js → index.ts} +31 -21
  30. package/src/remark/transformLinks/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +5 -1
  31. package/src/remark/transformLinks/__tests__/fixtures/asset.md +4 -0
  32. package/src/remark/transformLinks/__tests__/{index.test.js → index.test.ts} +0 -0
  33. package/src/remark/transformLinks/{index.js → index.ts} +62 -39
  34. package/src/remark/unwrapMdxCodeBlocks/__tests__/__snapshots__/{index.test.js.snap → index.test.ts.snap} +0 -0
  35. package/src/remark/unwrapMdxCodeBlocks/__tests__/{index.test.js → index.test.ts} +0 -0
  36. package/src/remark/unwrapMdxCodeBlocks/{index.js → index.ts} +11 -9
  37. package/src/remark/utils/index.ts +39 -0
  38. package/src/types.d.ts +40 -0
  39. package/tsconfig.json +4 -3
  40. package/src/index.d.ts +0 -19
  41. package/src/index.js +0 -107
  42. package/src/remark/toc/search.js +0 -73
  43. package/src/remark/utils/index.js +0 -39
@@ -9,24 +9,29 @@ exports[`inline code should be escaped 1`] = `
9
9
  {
10
10
  value: '<code>&lt;Head&gt;Test&lt;/Head&gt;</code>',
11
11
  id: 'headtesthead',
12
- children: []
12
+ children: [],
13
+ level: 3
13
14
  }
14
- ]
15
+ ],
16
+ level: 2
15
17
  },
16
18
  {
17
19
  value: '<code>&lt;div /&gt;</code>',
18
20
  id: 'div-',
19
- children: []
21
+ children: [],
22
+ level: 2
20
23
  },
21
24
  {
22
25
  value: '<code>&lt;div&gt; Test &lt;/div&gt;</code>',
23
26
  id: 'div-test-div',
24
- children: []
27
+ children: [],
28
+ level: 2
25
29
  },
26
30
  {
27
31
  value: '<code>&lt;div&gt;&lt;i&gt;Test&lt;/i&gt;&lt;/div&gt;</code>',
28
32
  id: 'divitestidiv',
29
- children: []
33
+ children: [],
34
+ level: 2
30
35
  }
31
36
  ];
32
37
 
@@ -51,24 +56,29 @@ exports[`non text phrasing content 1`] = `
51
56
  {
52
57
  value: '<strong>Importance</strong>',
53
58
  id: 'importance',
54
- children: []
59
+ children: [],
60
+ level: 3
55
61
  }
56
- ]
62
+ ],
63
+ level: 2
57
64
  },
58
65
  {
59
66
  value: '<del>Strikethrough</del>',
60
67
  id: 'strikethrough',
61
- children: []
68
+ children: [],
69
+ level: 2
62
70
  },
63
71
  {
64
72
  value: '<i>HTML</i>',
65
73
  id: 'html',
66
- children: []
74
+ children: [],
75
+ level: 2
67
76
  },
68
77
  {
69
78
  value: '<code>inline.code()</code>',
70
79
  id: 'inlinecode',
71
- children: []
80
+ children: [],
81
+ level: 2
72
82
  }
73
83
  ];
74
84
 
@@ -12,7 +12,7 @@ import vfile from 'to-vfile';
12
12
  import plugin from '../index';
13
13
  import headings from '../../headings/index';
14
14
 
15
- const processFixture = async (name, options) => {
15
+ const processFixture = async (name, options?) => {
16
16
  const path = join(__dirname, 'fixtures', `${name}.md`);
17
17
  const file = await vfile.read(path);
18
18
  const result = await remark()
@@ -41,7 +41,8 @@ test('text content', async () => {
41
41
  {
42
42
  value: 'Endi',
43
43
  id: 'endi',
44
- children: []
44
+ children: [],
45
+ level: 3
45
46
  },
46
47
  {
47
48
  value: 'Endi',
@@ -50,14 +51,17 @@ test('text content', async () => {
50
51
  {
51
52
  value: 'Yangshun',
52
53
  id: 'yangshun',
53
- children: []
54
+ children: [],
55
+ level: 3
54
56
  }
55
- ]
57
+ ],
58
+ level: 2
56
59
  },
57
60
  {
58
61
  value: 'I ♥ unicode.',
59
62
  id: 'i--unicode',
60
- children: []
63
+ children: [],
64
+ level: 2
61
65
  }
62
66
  ];
63
67
 
@@ -87,7 +91,8 @@ test('should export even with existing name', async () => {
87
91
  {
88
92
  value: 'Thanos',
89
93
  id: 'thanos',
90
- children: []
94
+ children: [],
95
+ level: 2
91
96
  },
92
97
  {
93
98
  value: 'Tony Stark',
@@ -96,9 +101,11 @@ test('should export even with existing name', async () => {
96
101
  {
97
102
  value: 'Avengers',
98
103
  id: 'avengers',
99
- children: []
104
+ children: [],
105
+ level: 3
100
106
  }
101
- ]
107
+ ],
108
+ level: 2
102
109
  }
103
110
  ];
104
111
 
@@ -121,7 +128,8 @@ test('should export with custom name', async () => {
121
128
  {
122
129
  value: 'Endi',
123
130
  id: 'endi',
124
- children: []
131
+ children: [],
132
+ level: 3
125
133
  },
126
134
  {
127
135
  value: 'Endi',
@@ -130,14 +138,17 @@ test('should export with custom name', async () => {
130
138
  {
131
139
  value: 'Yangshun',
132
140
  id: 'yangshun',
133
- children: []
141
+ children: [],
142
+ level: 3
134
143
  }
135
- ]
144
+ ],
145
+ level: 2
136
146
  },
137
147
  {
138
148
  value: 'I ♥ unicode.',
139
149
  id: 'i--unicode',
140
- children: []
150
+ children: [],
151
+ level: 2
141
152
  }
142
153
  ];
143
154
 
@@ -171,7 +182,8 @@ test('should insert below imports', async () => {
171
182
  {
172
183
  value: 'Title',
173
184
  id: 'title',
174
- children: []
185
+ children: [],
186
+ level: 2
175
187
  },
176
188
  {
177
189
  value: 'Test',
@@ -180,9 +192,11 @@ test('should insert below imports', async () => {
180
192
  {
181
193
  value: 'Again',
182
194
  id: 'again',
183
- children: []
195
+ children: [],
196
+ level: 3
184
197
  }
185
- ]
198
+ ],
199
+ level: 2
186
200
  }
187
201
  ];
188
202
 
@@ -0,0 +1,182 @@
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 remark from 'remark';
9
+ import mdx from 'remark-mdx';
10
+ import search from '../search';
11
+ import headings from '../../headings/index';
12
+
13
+ const getHeadings = async (mdText: string) => {
14
+ const node = remark().parse(mdText);
15
+ const result = await remark().use(headings).use(mdx).run(node);
16
+ return search(result);
17
+ };
18
+
19
+ test('should process all heading levels', async () => {
20
+ const md = `
21
+ # Alpha
22
+
23
+ ## Bravo
24
+
25
+ ### Charlie
26
+
27
+ #### Delta
28
+
29
+ ##### Echo
30
+
31
+ ###### Foxtrot
32
+
33
+ `;
34
+
35
+ expect(await getHeadings(md)).toEqual([
36
+ {
37
+ children: [
38
+ {
39
+ children: [
40
+ {
41
+ children: [
42
+ {
43
+ children: [
44
+ {
45
+ children: [],
46
+ id: 'foxtrot',
47
+ level: 6,
48
+ value: 'Foxtrot',
49
+ },
50
+ ],
51
+ id: 'echo',
52
+ level: 5,
53
+ value: 'Echo',
54
+ },
55
+ ],
56
+ id: 'delta',
57
+ level: 4,
58
+ value: 'Delta',
59
+ },
60
+ ],
61
+ id: 'charlie',
62
+ level: 3,
63
+ value: 'Charlie',
64
+ },
65
+ ],
66
+ id: 'bravo',
67
+ level: 2,
68
+ value: 'Bravo',
69
+ },
70
+ ]);
71
+ });
72
+
73
+ test('should process real-world well-formatted md', async () => {
74
+ const md = `
75
+ # title
76
+
77
+ some text
78
+
79
+ ## section 1
80
+
81
+ some text
82
+
83
+ ### subsection 1-1
84
+
85
+ some text
86
+
87
+ #### subsection 1-1-1
88
+
89
+ some text
90
+
91
+ #### subsection 1-1-2
92
+
93
+ some text
94
+
95
+ ### subsection 1-2
96
+
97
+ some text
98
+
99
+ ### subsection 1-3
100
+
101
+ some text
102
+
103
+ ## section 2
104
+
105
+ some text
106
+
107
+ ### subsection 2-1
108
+
109
+ some text
110
+
111
+ ### subsection 2-1
112
+
113
+ some text
114
+
115
+ ## section 3
116
+
117
+ some text
118
+
119
+ ### subsection 3-1
120
+
121
+ some text
122
+
123
+ ### subsection 3-2
124
+
125
+ some text
126
+
127
+ `;
128
+
129
+ expect(await getHeadings(md)).toEqual([
130
+ {
131
+ children: [
132
+ {
133
+ children: [
134
+ {
135
+ children: [],
136
+ id: 'subsection-1-1-1',
137
+ level: 4,
138
+ value: 'subsection 1-1-1',
139
+ },
140
+ {
141
+ children: [],
142
+ id: 'subsection-1-1-2',
143
+ level: 4,
144
+ value: 'subsection 1-1-2',
145
+ },
146
+ ],
147
+ id: 'subsection-1-1',
148
+ level: 3,
149
+ value: 'subsection 1-1',
150
+ },
151
+ {children: [], id: 'subsection-1-2', level: 3, value: 'subsection 1-2'},
152
+ {children: [], id: 'subsection-1-3', level: 3, value: 'subsection 1-3'},
153
+ ],
154
+ id: 'section-1',
155
+ level: 2,
156
+ value: 'section 1',
157
+ },
158
+ {
159
+ children: [
160
+ {children: [], id: 'subsection-2-1', level: 3, value: 'subsection 2-1'},
161
+ {
162
+ children: [],
163
+ id: 'subsection-2-1-1',
164
+ level: 3,
165
+ value: 'subsection 2-1',
166
+ },
167
+ ],
168
+ id: 'section-2',
169
+ level: 2,
170
+ value: 'section 2',
171
+ },
172
+ {
173
+ children: [
174
+ {children: [], id: 'subsection-3-1', level: 3, value: 'subsection 3-1'},
175
+ {children: [], id: 'subsection-3-2', level: 3, value: 'subsection 3-2'},
176
+ ],
177
+ id: 'section-3',
178
+ level: 2,
179
+ value: 'section 3',
180
+ },
181
+ ]);
182
+ });
@@ -5,34 +5,42 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
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');
8
+ import {parse, ParserOptions} from '@babel/parser';
9
+ import type {Identifier} from '@babel/types';
10
+ import traverse from '@babel/traverse';
11
+ import stringifyObject from 'stringify-object';
12
+ import search from './search';
13
+ import type {Plugin, Transformer} from 'unified';
14
+ import type {Node, Parent} from 'unist';
15
+ import type {Literal} from 'mdast';
12
16
 
13
- const parseOptions = {
17
+ const parseOptions: ParserOptions = {
14
18
  plugins: ['jsx'],
15
19
  sourceType: 'module',
16
20
  };
17
- const isImport = (child) => child.type === 'import';
18
- const hasImports = (index) => index > -1;
19
- const isExport = (child) => child.type === 'export';
20
21
 
21
- const isTarget = (child, name) => {
22
+ const isImport = (child: Node): child is Literal => child.type === 'import';
23
+ const hasImports = (index: number) => index > -1;
24
+ const isExport = (child: Node): child is Literal => child.type === 'export';
25
+
26
+ interface PluginOptions {
27
+ name?: string;
28
+ }
29
+
30
+ const isTarget = (child: Literal, name: string) => {
22
31
  let found = false;
23
32
  const ast = parse(child.value, parseOptions);
24
33
  traverse(ast, {
25
34
  VariableDeclarator: (path) => {
26
- if (path.node.id.name === name) {
35
+ if ((path.node.id as Identifier).name === name) {
27
36
  found = true;
28
37
  }
29
38
  },
30
39
  });
31
-
32
40
  return found;
33
41
  };
34
42
 
35
- const getOrCreateExistingTargetIndex = (children, name) => {
43
+ const getOrCreateExistingTargetIndex = (children: Node[], name: string) => {
36
44
  let importsIndex = -1;
37
45
  let targetIndex = -1;
38
46
 
@@ -58,12 +66,12 @@ const getOrCreateExistingTargetIndex = (children, name) => {
58
66
  return targetIndex;
59
67
  };
60
68
 
61
- const plugin = (options = {}) => {
69
+ const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
62
70
  const name = options.name || 'toc';
63
71
 
64
- const transformer = (node) => {
72
+ const transformer: Transformer = (node) => {
65
73
  const headings = search(node);
66
- const {children} = node;
74
+ const {children} = node as Parent<Literal>;
67
75
  const targetIndex = getOrCreateExistingTargetIndex(children, name);
68
76
 
69
77
  if (headings && headings.length) {
@@ -76,4 +84,4 @@ const plugin = (options = {}) => {
76
84
  return transformer;
77
85
  };
78
86
 
79
- module.exports = plugin;
87
+ export default plugin;
@@ -0,0 +1,82 @@
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 toString from 'mdast-util-to-string';
9
+ import visit, {Visitor} from 'unist-util-visit';
10
+ import {toValue} from '../utils';
11
+ import type {TOCItem} from '@docusaurus/types';
12
+ import type {Node} from 'unist';
13
+ import type {Heading} from 'mdast';
14
+
15
+ // Intermediate interface for TOC algorithm
16
+ interface SearchItem {
17
+ node: TOCItem;
18
+ level: number;
19
+ parentIndex: number;
20
+ }
21
+
22
+ /**
23
+ *
24
+ * Generate a TOC AST from the raw Markdown contents
25
+ */
26
+ export default function search(node: Node): TOCItem[] {
27
+ const headings: SearchItem[] = [];
28
+
29
+ const visitor: Visitor<Heading> = (child, _index, parent) => {
30
+ const value = toString(child);
31
+
32
+ // depth:1 headings are titles and not included in the TOC
33
+ if (parent !== node || !value || child.depth < 2) {
34
+ return;
35
+ }
36
+
37
+ headings.push({
38
+ node: {
39
+ value: toValue(child),
40
+ id: child.data!.id as string,
41
+ children: [],
42
+ level: child.depth,
43
+ },
44
+ level: child.depth,
45
+ parentIndex: -1,
46
+ });
47
+ };
48
+
49
+ visit(node, 'heading', visitor);
50
+
51
+ // Keep track of which previous index would be the current heading's direcy parent.
52
+ // Each entry <i> is the last index of the `headings` array at heading level <i>.
53
+ // We will modify these indices as we iterate through all headings.
54
+ // e.g. if an ### H3 was last seen at index 2, then prevIndexForLevel[3] === 2
55
+ // indices 0 and 1 will remain unused.
56
+ const prevIndexForLevel = Array(7).fill(-1);
57
+
58
+ headings.forEach((curr, currIndex) => {
59
+ // take the last seen index for each ancestor level. the highest
60
+ // index will be the direct ancestor of the current heading.
61
+ const ancestorLevelIndexes = prevIndexForLevel.slice(2, curr.level);
62
+ curr.parentIndex = Math.max(...ancestorLevelIndexes);
63
+ // mark that curr.level was last seen at the current index
64
+ prevIndexForLevel[curr.level] = currIndex;
65
+ });
66
+
67
+ const rootNodeIndexes: number[] = [];
68
+
69
+ // For a given parentIndex, add each Node into that parent's `children` array
70
+ headings.forEach((heading, i) => {
71
+ if (heading.parentIndex >= 0) {
72
+ headings[heading.parentIndex].node.children.push(heading.node);
73
+ } else {
74
+ rootNodeIndexes.push(i);
75
+ }
76
+ });
77
+
78
+ const toc = headings
79
+ .filter((_, k) => rootNodeIndexes.includes(k)) // only return root nodes
80
+ .map((heading) => heading.node); // only return Node, no metadata
81
+ return toc;
82
+ }
@@ -5,26 +5,35 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
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 {
8
+ import visit from 'unist-util-visit';
9
+ import path from 'path';
10
+ import url from 'url';
11
+ import fs from 'fs-extra';
12
+ import escapeHtml from 'escape-html';
13
+ import {getFileLoaderUtils} from '@docusaurus/core/lib/webpack/utils';
14
+ import {
15
15
  posixPath,
16
16
  escapePath,
17
17
  toMessageRelativeFilePath,
18
- } = require('@docusaurus/utils');
18
+ } from '@docusaurus/utils';
19
+ import type {Plugin, Transformer} from 'unified';
20
+ import type {Image, Literal} from 'mdast';
19
21
 
20
22
  const {
21
23
  loaders: {inlineMarkdownImageFileLoader},
22
24
  } = getFileLoaderUtils();
23
25
 
24
- const createJSX = (node, pathUrl) => {
26
+ interface PluginOptions {
27
+ filePath: string;
28
+ staticDir: string;
29
+ }
30
+
31
+ const createJSX = (node: Image, pathUrl: string) => {
25
32
  const jsxNode = node;
26
- jsxNode.type = 'jsx';
27
- jsxNode.value = `<img ${node.alt ? `alt={"${escapeHtml(node.alt)}"} ` : ''}${
33
+ (jsxNode as unknown as Literal).type = 'jsx';
34
+ (jsxNode as unknown as Literal).value = `<img ${
35
+ node.alt ? `alt={"${escapeHtml(node.alt)}"} ` : ''
36
+ }${
28
37
  node.url
29
38
  ? `src={require("${inlineMarkdownImageFileLoader}${escapePath(
30
39
  pathUrl,
@@ -33,7 +42,7 @@ const createJSX = (node, pathUrl) => {
33
42
  }${node.title ? ` title="${escapeHtml(node.title)}"` : ''} />`;
34
43
 
35
44
  if (jsxNode.url) {
36
- delete jsxNode.url;
45
+ delete (jsxNode as Partial<Image>).url;
37
46
  }
38
47
  if (jsxNode.alt) {
39
48
  delete jsxNode.alt;
@@ -43,7 +52,7 @@ const createJSX = (node, pathUrl) => {
43
52
  }
44
53
  };
45
54
 
46
- async function ensureImageFileExist(imagePath, sourceFilePath) {
55
+ async function ensureImageFileExist(imagePath: string, sourceFilePath: string) {
47
56
  const imageExists = await fs.pathExists(imagePath);
48
57
  if (!imageExists) {
49
58
  throw new Error(
@@ -54,7 +63,10 @@ async function ensureImageFileExist(imagePath, sourceFilePath) {
54
63
  }
55
64
  }
56
65
 
57
- async function processImageNode(node, {filePath, staticDir}) {
66
+ async function processImageNode(
67
+ node: Image,
68
+ {filePath, staticDir}: PluginOptions,
69
+ ) {
58
70
  if (!node.url) {
59
71
  throw new Error(
60
72
  `Markdown image URL is mandatory in "${toMessageRelativeFilePath(
@@ -71,8 +83,6 @@ async function processImageNode(node, {filePath, staticDir}) {
71
83
  // it's mostly to make next release less risky (2.0.0-alpha.59)
72
84
  if (parsedUrl.protocol === 'pathname:') {
73
85
  node.url = node.url.replace('pathname://', '');
74
- } else {
75
- // noop
76
86
  }
77
87
  }
78
88
  // images without protocol
@@ -92,10 +102,10 @@ async function processImageNode(node, {filePath, staticDir}) {
92
102
  }
93
103
  }
94
104
 
95
- const plugin = (options) => {
96
- const transformer = async (root) => {
97
- const promises = [];
98
- visit(root, 'image', (node) => {
105
+ const plugin: Plugin<[PluginOptions]> = (options) => {
106
+ const transformer: Transformer = async (root) => {
107
+ const promises: Promise<void>[] = [];
108
+ visit(root, 'image', (node: Image) => {
99
109
  promises.push(processImageNode(node, options));
100
110
  });
101
111
  await Promise.all(promises);
@@ -103,4 +113,4 @@ const plugin = (options) => {
103
113
  return transformer;
104
114
  };
105
115
 
106
- module.exports = plugin;
116
+ export default plugin;
@@ -14,7 +14,9 @@ exports[`transformAsset plugin transform md links to <a /> 1`] = `
14
14
 
15
15
  <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}>asset</a>
16
16
 
17
- <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}title=\\"Title\\">asset</a>
17
+ <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default + '#page=2'}>asset with hash</a>
18
+
19
+ <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default} title=\\"Title\\">asset</a>
18
20
 
19
21
  ## Heading
20
22
 
@@ -32,6 +34,8 @@ exports[`transformAsset plugin transform md links to <a /> 1`] = `
32
34
 
33
35
  <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>@site/static/staticAsset.pdf</a>
34
36
 
37
+ <a target=\\"_blank\\" href={require('!file-loader?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default + '#page=2'} title=\\"Title\\">@site/static/staticAsset.pdf</a>
38
+
35
39
  <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 &#39;It is really &quot;AWESOME&quot;&#39;</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
40
 
37
41
  <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>
@@ -4,6 +4,8 @@
4
4
 
5
5
  [asset](./asset.pdf)
6
6
 
7
+ [asset with hash](./asset.pdf#page=2)
8
+
7
9
  [asset](asset.pdf 'Title')
8
10
 
9
11
  ## Heading
@@ -22,6 +24,8 @@
22
24
 
23
25
  [@site/static/staticAsset.pdf](@site/static/staticAsset.pdf)
24
26
 
27
+ [@site/static/staticAsset.pdf](@site/static/staticAsset.pdf#page=2 'Title')
28
+
25
29
  [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
30
 
27
31
  [![Clickable Docusaurus logo](./static/staticAssetImage.png)](/staticAssetImage.png)