mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-02 03:37:48 +02:00
feat(mdx-loader): read image dimensions when processing Markdown (#6339)
This commit is contained in:
parent
6f892e20b0
commit
e5801e49f6
8 changed files with 32 additions and 10 deletions
|
@ -96,7 +96,7 @@
|
||||||
"eslint-plugin-react-hooks": "^4.3.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"husky": "^7.0.4",
|
"husky": "^7.0.4",
|
||||||
"image-size": "^1.0.0",
|
"image-size": "^1.0.1",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"lerna": "^4.0.0",
|
"lerna": "^4.0.0",
|
||||||
"lerna-changelog": "^1.0.1",
|
"lerna-changelog": "^1.0.1",
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
|
"image-size": "^1.0.1",
|
||||||
"mdast-util-to-string": "^2.0.0",
|
"mdast-util-to-string": "^2.0.0",
|
||||||
"remark-emoji": "^2.1.0",
|
"remark-emoji": "^2.1.0",
|
||||||
"stringify-object": "^3.3.0",
|
"stringify-object": "^3.3.0",
|
||||||
|
|
|
@ -17,8 +17,11 @@ import path from 'path';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import escapeHtml from 'escape-html';
|
import escapeHtml from 'escape-html';
|
||||||
|
import sizeOf from 'image-size';
|
||||||
|
import {promisify} from 'util';
|
||||||
import type {Plugin, Transformer} from 'unified';
|
import type {Plugin, Transformer} from 'unified';
|
||||||
import type {Image, Literal} from 'mdast';
|
import type {Image, Literal} from 'mdast';
|
||||||
|
import logger from '@docusaurus/logger';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loaders: {inlineMarkdownImageFileLoader},
|
loaders: {inlineMarkdownImageFileLoader},
|
||||||
|
@ -30,7 +33,11 @@ interface PluginOptions {
|
||||||
siteDir: string;
|
siteDir: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toImageRequireNode(node: Image, imagePath: string, filePath: string) {
|
async function toImageRequireNode(
|
||||||
|
node: Image,
|
||||||
|
imagePath: string,
|
||||||
|
filePath: string,
|
||||||
|
) {
|
||||||
const jsxNode = node as Literal & Partial<Image>;
|
const jsxNode = node as Literal & Partial<Image>;
|
||||||
let relativeImagePath = posixPath(
|
let relativeImagePath = posixPath(
|
||||||
path.relative(path.dirname(filePath), imagePath),
|
path.relative(path.dirname(filePath), imagePath),
|
||||||
|
@ -46,13 +53,27 @@ function toImageRequireNode(node: Image, imagePath: string, filePath: string) {
|
||||||
escapePath(relativeImagePath) + search
|
escapePath(relativeImagePath) + search
|
||||||
}").default${hash ? ` + '${hash}'` : ''}`;
|
}").default${hash ? ` + '${hash}'` : ''}`;
|
||||||
const title = node.title ? ` title="${escapeHtml(node.title)}"` : '';
|
const title = node.title ? ` title="${escapeHtml(node.title)}"` : '';
|
||||||
|
let width = '';
|
||||||
|
let height = '';
|
||||||
|
try {
|
||||||
|
const size = (await promisify(sizeOf)(imagePath))!;
|
||||||
|
if (size.width) {
|
||||||
|
width = ` width="${size.width}"`;
|
||||||
|
}
|
||||||
|
if (size.height) {
|
||||||
|
height = ` height="${size.height}"`;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.error`The image at path=${imagePath} can't be read correctly. Please ensure it's a valid image.
|
||||||
|
${(e as Error).message}`;
|
||||||
|
}
|
||||||
|
|
||||||
Object.keys(jsxNode).forEach(
|
Object.keys(jsxNode).forEach(
|
||||||
(key) => delete jsxNode[key as keyof typeof jsxNode],
|
(key) => delete jsxNode[key as keyof typeof jsxNode],
|
||||||
);
|
);
|
||||||
|
|
||||||
(jsxNode as Literal).type = 'jsx';
|
(jsxNode as Literal).type = 'jsx';
|
||||||
jsxNode.value = `<img ${alt}src={${src}}${title} />`;
|
jsxNode.value = `<img ${alt}src={${src}}${title}${width}${height} />`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensureImageFileExist(imagePath: string, sourceFilePath: string) {
|
async function ensureImageFileExist(imagePath: string, sourceFilePath: string) {
|
||||||
|
@ -124,7 +145,7 @@ async function processImageNode(node: Image, options: PluginOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const imagePath = await getImageAbsolutePath(parsedUrl.pathname, options);
|
const imagePath = await getImageAbsolutePath(parsedUrl.pathname, options);
|
||||||
toImageRequireNode(node, imagePath, options.filePath);
|
await toImageRequireNode(node, imagePath, options.filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
const plugin: Plugin<[PluginOptions]> = (options) => {
|
const plugin: Plugin<[PluginOptions]> = (options) => {
|
||||||
|
|
|
@ -44,7 +44,7 @@ exports[`transformAsset plugin transform md links to <a /> 1`] = `
|
||||||
|
|
||||||
<a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>Just staticAsset.pdf</a>, and <a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?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('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>coded <code>staticAsset 3.pdf</code></a>
|
<a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>Just staticAsset.pdf</a>, and <a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?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('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./static/staticAsset.pdf').default}>coded <code>staticAsset 3.pdf</code></a>
|
||||||
|
|
||||||
<a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./static/staticAssetImage.png').default}><img alt={\\"Clickable Docusaurus logo\\"} src={require(\\"![CWD]/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=[CWD]/node_modules/file-loader/dist/cjs.js!./static/staticAssetImage.png\\").default} /></a>
|
<a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./static/staticAssetImage.png').default}><img alt={\\"Clickable Docusaurus logo\\"} src={require(\\"![CWD]/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[hash].[ext]&fallback=[CWD]/node_modules/file-loader/dist/cjs.js!./static/staticAssetImage.png\\").default} width=\\"200\\" height=\\"200\\" /></a>
|
||||||
|
|
||||||
<a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}><span style={{color: \\"red\\"}}>Stylized link to asset file</span></a>
|
<a target=\\"_blank\\" href={require('![CWD]/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[hash].[ext]!./asset.pdf').default}><span style={{color: \\"red\\"}}>Stylized link to asset file</span></a>
|
||||||
"
|
"
|
||||||
|
|
|
@ -9,3 +9,7 @@ ul.contains-task-list {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
|
@ -181,6 +181,3 @@ html[data-theme='dark'] img[src$='#gh-light-mode-only'] {
|
||||||
.test-marker-site-custom-css-unique-rule {
|
.test-marker-site-custom-css-unique-rule {
|
||||||
content: 'site-custom-css-unique-rule';
|
content: 'site-custom-css-unique-rule';
|
||||||
}
|
}
|
||||||
.test-marker-site-custom-css-shared-rule {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ const EXPECTED_CSS_MARKERS = [
|
||||||
'.DocSearch-Hit-content-wrapper',
|
'.DocSearch-Hit-content-wrapper',
|
||||||
'.navbar__title',
|
'.navbar__title',
|
||||||
'--ifm-color-scheme:light',
|
'--ifm-color-scheme:light',
|
||||||
'.test-marker-site-custom-css-shared-rule',
|
|
||||||
'.col[class*=col--]',
|
'.col[class*=col--]',
|
||||||
'.padding-vert--xl',
|
'.padding-vert--xl',
|
||||||
'.footer__link-item',
|
'.footer__link-item',
|
||||||
|
|
|
@ -10194,7 +10194,7 @@ image-q@^1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/image-q/-/image-q-1.1.1.tgz#fc84099664460b90ca862d9300b6bfbbbfbf8056"
|
resolved "https://registry.yarnpkg.com/image-q/-/image-q-1.1.1.tgz#fc84099664460b90ca862d9300b6bfbbbfbf8056"
|
||||||
integrity sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=
|
integrity sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=
|
||||||
|
|
||||||
image-size@^1.0.0:
|
image-size@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.1.tgz#86d6cfc2b1d19eab5d2b368d4b9194d9e48541c5"
|
resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.1.tgz#86d6cfc2b1d19eab5d2b368d4b9194d9e48541c5"
|
||||||
integrity sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==
|
integrity sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==
|
||||||
|
|
Loading…
Add table
Reference in a new issue