mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 23:57:22 +02:00
fix(v2): do not reveal environment file path (#1692)
* fix(v2): do not reveal environment file path * changelog * fix broken markdown linking
This commit is contained in:
parent
84b2270039
commit
a684806a0f
9 changed files with 48 additions and 41 deletions
|
@ -2,7 +2,8 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
- Shorter chunk naming for pages. Instead of absolute path, we use relative path from site directory
|
||||
- Fix broken markdown linking replacement for mdx files
|
||||
- Fix potential security vulnerability because we're exposing the directory structure of the host machine. Instead of absolute path, we use relative path from site directory. Resulting in shorter webpack chunk naming and smaller bundle size.
|
||||
- Use contenthash instead of chunkhash for better long term caching
|
||||
- Allow user to customize generated heading from MDX. Swizzle `@theme/Heading`
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ module.exports = function(context, opts) {
|
|||
// Fetches blog contents and returns metadata for the necessary routes.
|
||||
async loadContent() {
|
||||
const {postsPerPage, include, routeBasePath} = options;
|
||||
const {siteConfig} = context;
|
||||
const {siteConfig, siteDir} = context;
|
||||
const blogDir = contentPath;
|
||||
|
||||
if (!fs.existsSync(blogDir)) {
|
||||
|
@ -65,8 +65,9 @@ module.exports = function(context, opts) {
|
|||
|
||||
await Promise.all(
|
||||
blogFiles.map(async relativeSource => {
|
||||
// Cannot use path.join() as it resolves '../' and removes the '@site'. Let webpack loader resolve it.
|
||||
const source = path.join(blogDir, relativeSource);
|
||||
|
||||
const aliasedSource = `@site/${path.relative(siteDir, source)}`;
|
||||
const blogFileName = path.basename(relativeSource);
|
||||
// Extract, YYYY, MM, DD from the file name.
|
||||
const filePathDateArr = blogFileName.split('-');
|
||||
|
@ -87,7 +88,7 @@ module.exports = function(context, opts) {
|
|||
routeBasePath,
|
||||
frontMatter.id || fileToUrl(blogFileName),
|
||||
]),
|
||||
source,
|
||||
source: aliasedSource,
|
||||
description: frontMatter.description || excerpt,
|
||||
date,
|
||||
tags: frontMatter.tags,
|
||||
|
|
|
@ -17,6 +17,7 @@ describe('loadDocs', () => {
|
|||
url: 'https://docusaurus.io',
|
||||
};
|
||||
const sidebarPath = path.join(siteDir, 'sidebars.json');
|
||||
const pluginPath = 'docs';
|
||||
const plugin = pluginContentDocs(
|
||||
{
|
||||
siteDir,
|
||||
|
@ -28,7 +29,6 @@ describe('loadDocs', () => {
|
|||
},
|
||||
);
|
||||
const {docs: docsMetadata} = await plugin.loadContent();
|
||||
const docsDir = plugin.contentPath;
|
||||
|
||||
expect(docsMetadata.hello).toEqual({
|
||||
category: 'Guides',
|
||||
|
@ -37,7 +37,7 @@ describe('loadDocs', () => {
|
|||
previous: 'foo/baz',
|
||||
previous_title: 'baz',
|
||||
sidebar: 'docs',
|
||||
source: path.join(docsDir, 'hello.md'),
|
||||
source: path.join('@site', pluginPath, 'hello.md'),
|
||||
title: 'Hello, World !',
|
||||
description: `Hi, Endilie here :)`,
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ describe('loadDocs', () => {
|
|||
next_title: 'baz',
|
||||
permalink: '/docs/foo/bar',
|
||||
sidebar: 'docs',
|
||||
source: path.join(docsDir, 'foo', 'bar.md'),
|
||||
source: path.join('@site', pluginPath, 'foo', 'bar.md'),
|
||||
title: 'Bar',
|
||||
description: 'This is custom description',
|
||||
});
|
||||
|
|
|
@ -15,36 +15,28 @@ describe('processMetadata', () => {
|
|||
baseUrl: '/',
|
||||
url: 'https://docusaurus.io',
|
||||
};
|
||||
const docsDir = path.resolve(siteDir, 'docs');
|
||||
const pluginPath = 'docs';
|
||||
const docsDir = path.resolve(siteDir, pluginPath);
|
||||
|
||||
test('normal docs', async () => {
|
||||
const sourceA = path.join('foo', 'bar.md');
|
||||
const sourceB = path.join('hello.md');
|
||||
const dataA = await processMetadata(
|
||||
sourceA,
|
||||
docsDir,
|
||||
{},
|
||||
siteConfig,
|
||||
'docs',
|
||||
);
|
||||
const dataB = await processMetadata(
|
||||
sourceB,
|
||||
docsDir,
|
||||
{},
|
||||
siteConfig,
|
||||
'docs',
|
||||
);
|
||||
|
||||
const [dataA, dataB] = await Promise.all([
|
||||
processMetadata(sourceA, docsDir, {}, siteConfig, pluginPath, siteDir),
|
||||
processMetadata(sourceB, docsDir, {}, siteConfig, pluginPath, siteDir),
|
||||
]);
|
||||
expect(dataA).toEqual({
|
||||
id: 'foo/bar',
|
||||
permalink: '/docs/foo/bar',
|
||||
source: path.join(docsDir, sourceA),
|
||||
source: path.join('@site', pluginPath, sourceA),
|
||||
title: 'Bar',
|
||||
description: 'This is custom description',
|
||||
});
|
||||
expect(dataB).toEqual({
|
||||
id: 'hello',
|
||||
permalink: '/docs/hello',
|
||||
source: path.join(docsDir, sourceB),
|
||||
source: path.join('@site', pluginPath, sourceB),
|
||||
title: 'Hello, World !',
|
||||
description: `Hi, Endilie here :)`,
|
||||
});
|
||||
|
@ -52,11 +44,18 @@ describe('processMetadata', () => {
|
|||
|
||||
test('docs with custom permalink', async () => {
|
||||
const source = path.join('permalink.md');
|
||||
const data = await processMetadata(source, docsDir, {}, siteConfig, 'docs');
|
||||
const data = await processMetadata(
|
||||
source,
|
||||
docsDir,
|
||||
{},
|
||||
siteConfig,
|
||||
pluginPath,
|
||||
siteDir,
|
||||
);
|
||||
expect(data).toEqual({
|
||||
id: 'permalink',
|
||||
permalink: '/docs/endiliey/permalink',
|
||||
source: path.join(docsDir, source),
|
||||
source: path.join('@site', pluginPath, source),
|
||||
title: 'Permalink',
|
||||
description: 'This has a different permalink',
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ module.exports = function(context, opts) {
|
|||
// Fetches blog contents and returns metadata for the contents.
|
||||
async loadContent() {
|
||||
const {include, routeBasePath, sidebarPath} = options;
|
||||
const {siteConfig} = context;
|
||||
const {siteConfig, siteDir} = context;
|
||||
const docsDir = contentPath;
|
||||
|
||||
if (!fs.existsSync(docsDir)) {
|
||||
|
@ -73,6 +73,7 @@ module.exports = function(context, opts) {
|
|||
order,
|
||||
siteConfig,
|
||||
routeBasePath,
|
||||
siteDir,
|
||||
);
|
||||
docs[metadata.id] = metadata;
|
||||
}),
|
||||
|
@ -177,6 +178,7 @@ module.exports = function(context, opts) {
|
|||
loader: path.resolve(__dirname, './markdown/index.js'),
|
||||
options: {
|
||||
siteConfig: context.siteConfig,
|
||||
siteDir: context.siteDir,
|
||||
docsDir: globalContents.docsDir,
|
||||
sourceToPermalink: globalContents.sourceToPermalink,
|
||||
},
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const {getOptions} = require('loader-utils');
|
||||
const {resolve} = require('url');
|
||||
|
||||
|
@ -13,7 +14,7 @@ module.exports = async function(fileString) {
|
|||
const options = Object.assign({}, getOptions(this), {
|
||||
filepath: this.resourcePath,
|
||||
});
|
||||
const {docsDir, sourceToPermalink} = options;
|
||||
const {docsDir, siteDir, sourceToPermalink} = options;
|
||||
|
||||
// Determine the source dir. e.g: /docs, /website/versioned_docs/version-1.0.0
|
||||
let sourceDir;
|
||||
|
@ -37,15 +38,17 @@ module.exports = async function(fileString) {
|
|||
// Replace inline-style links or reference-style links e.g:
|
||||
// This is [Document 1](doc1.md) -> we replace this doc1.md with correct link
|
||||
// [doc1]: doc1.md -> we replace this doc1.md with correct link
|
||||
const mdRegex = /(?:(?:\]\()|(?:\]:\s?))(?!https)([^'")\]\s>]+\.md)/g;
|
||||
const mdRegex = /(?:(?:\]\()|(?:\]:\s?))(?!https)([^'")\]\s>]+\.mdx?)/g;
|
||||
let mdMatch = mdRegex.exec(modifiedLine);
|
||||
while (mdMatch !== null) {
|
||||
// Replace it to correct html link.
|
||||
const mdLink = mdMatch[1];
|
||||
const targetSource = `${sourceDir}/${mdLink}`;
|
||||
const aliasedSource = source =>
|
||||
`@site/${path.relative(siteDir, source)}`;
|
||||
const permalink =
|
||||
sourceToPermalink[resolve(thisSource, mdLink)] ||
|
||||
sourceToPermalink[targetSource];
|
||||
sourceToPermalink[aliasedSource(resolve(thisSource, mdLink))] ||
|
||||
sourceToPermalink[aliasedSource(targetSource)];
|
||||
if (permalink) {
|
||||
modifiedLine = modifiedLine.replace(mdLink, permalink);
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@ const {parse, normalizeUrl} = require('@docusaurus/utils');
|
|||
|
||||
module.exports = async function processMetadata(
|
||||
source,
|
||||
refDir,
|
||||
docsDir,
|
||||
order,
|
||||
siteConfig,
|
||||
docsBasePath,
|
||||
siteDir,
|
||||
) {
|
||||
const filepath = path.resolve(refDir, source);
|
||||
const filepath = path.join(docsDir, source);
|
||||
|
||||
const fileString = await fs.readFile(filepath, 'utf-8');
|
||||
const {frontMatter: metadata = {}, excerpt} = parse(fileString);
|
||||
|
||||
|
@ -24,6 +26,7 @@ module.exports = async function processMetadata(
|
|||
if (!metadata.id) {
|
||||
metadata.id = path.basename(source, path.extname(source));
|
||||
}
|
||||
|
||||
if (metadata.id.includes('/')) {
|
||||
throw new Error('Document id cannot include "/".');
|
||||
}
|
||||
|
@ -45,9 +48,9 @@ module.exports = async function processMetadata(
|
|||
}
|
||||
}
|
||||
|
||||
// The docs absolute file source.
|
||||
// e.g: `/end/docs/hello.md` or `/end/website/versioned_docs/version-1.0.0/hello.md`
|
||||
metadata.source = path.join(refDir, source);
|
||||
// Cannot use path.join() as it resolves '../' and removes the '@site'. Let webpack loader resolve it.
|
||||
const aliasedPath = `@site/${path.relative(siteDir, filepath)}`;
|
||||
metadata.source = aliasedPath;
|
||||
|
||||
// Build the permalink.
|
||||
const {baseUrl} = siteConfig;
|
||||
|
|
|
@ -47,10 +47,8 @@ module.exports = function(context, opts) {
|
|||
|
||||
return pagesFiles.map(relativeSource => {
|
||||
const source = path.join(pagesDir, relativeSource);
|
||||
const aliasedSource = path.join(
|
||||
'@site',
|
||||
path.relative(siteDir, source),
|
||||
);
|
||||
// Cannot use path.join() as it resolves '../' and removes the '@site'. Let webpack loader resolve it.
|
||||
const aliasedSource = `@site/${path.relative(siteDir, source)}`;
|
||||
const pathName = encodePath(fileToPath(relativeSource));
|
||||
// Default Language.
|
||||
return {
|
||||
|
|
|
@ -61,7 +61,7 @@ my-website
|
|||
### Project structure rundown
|
||||
|
||||
- `/blog/` - Contains the blog markdown files. You can delete the directory if you do not want/need a blog. More details can be found in the [blog guide](blog.md).
|
||||
- `/docs/` - Contains the markdown files for the docs. Customize the order of the docs sidebar in `sidebars.js`. More details can be found in the [docs guide](markdown-features).
|
||||
- `/docs/` - Contains the markdown files for the docs. Customize the order of the docs sidebar in `sidebars.js`. More details can be found in the [docs guide](markdown-features.mdx).
|
||||
- `/src/` - Non-documentation files like pages or custom React components. You don't have to strictly put your non-documentation files in here but putting them under a centralized directory makes it easier to specify in case you need to do some sort of linting/processing
|
||||
- `/src/pages` - Any files within this directory will be converted into a website page. More details can be found in the [pages guide](creating-pages.md).
|
||||
- `/static/` - Static directory. Any contents inside here will be copied into the root of the final `build` directory.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue