diff --git a/.eslintrc.js b/.eslintrc.js index edfbf50d97eb..50453b0ada69 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -380,7 +380,14 @@ module.exports = { // We don't provide any escape hatches for this rule. Rest siblings and // function placeholder params are always ignored, and any other unused // locals must be justified with a disable comment. - '@typescript-eslint/no-unused-vars': [ERROR, {ignoreRestSiblings: true}], + '@typescript-eslint/no-unused-vars': [ + ERROR, + { + ignoreRestSiblings: true, + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], '@typescript-eslint/prefer-optional-chain': ERROR, '@docusaurus/no-html-links': ERROR, '@docusaurus/prefer-docusaurus-heading': ERROR, diff --git a/packages/docusaurus-plugin-svgr/.npmignore b/packages/docusaurus-plugin-svgr/.npmignore new file mode 100644 index 000000000000..03c9ae1e1b54 --- /dev/null +++ b/packages/docusaurus-plugin-svgr/.npmignore @@ -0,0 +1,3 @@ +.tsbuildinfo* +tsconfig* +__tests__ diff --git a/packages/docusaurus-plugin-svgr/README.md b/packages/docusaurus-plugin-svgr/README.md new file mode 100644 index 000000000000..27b865208d4d --- /dev/null +++ b/packages/docusaurus-plugin-svgr/README.md @@ -0,0 +1,7 @@ +# `@docusaurus/plugin-svgr` + +[SVGR](https://react-svgr.com/) plugin for Docusaurus. + +## Usage + +See [plugin-svgr documentation](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-svgr). diff --git a/packages/docusaurus-plugin-svgr/package.json b/packages/docusaurus-plugin-svgr/package.json new file mode 100644 index 000000000000..aea47b5a2095 --- /dev/null +++ b/packages/docusaurus-plugin-svgr/package.json @@ -0,0 +1,37 @@ +{ + "name": "@docusaurus/plugin-svgr", + "version": "3.6.1", + "description": "SVGR plugin for Docusaurus.", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "build": "tsc --build", + "watch": "tsc --build --watch" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/facebook/docusaurus.git", + "directory": "packages/docusaurus-plugin-svgr" + }, + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.6.1", + "@docusaurus/types": "3.6.1", + "@docusaurus/utils": "3.6.1", + "@docusaurus/utils-validation": "3.6.1", + "@svgr/core": "8.1.0", + "@svgr/webpack": "^8.1.0", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "engines": { + "node": ">=18.0" + } +} diff --git a/packages/docusaurus-plugin-svgr/src/__tests__/options.test.ts b/packages/docusaurus-plugin-svgr/src/__tests__/options.test.ts new file mode 100644 index 000000000000..63edff7dd217 --- /dev/null +++ b/packages/docusaurus-plugin-svgr/src/__tests__/options.test.ts @@ -0,0 +1,100 @@ +/** + * 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 {normalizePluginOptions} from '@docusaurus/utils-validation'; +import { + validateOptions, + type PluginOptions, + type Options, + DEFAULT_OPTIONS, +} from '../options'; +import type {Validate} from '@docusaurus/types'; + +function validate(options?: Options) { + return validateOptions({ + validate: normalizePluginOptions as Validate< + Options | undefined, + PluginOptions + >, + options, + }); +} + +function result(options?: Options) { + return { + id: 'default', + ...DEFAULT_OPTIONS, + ...options, + }; +} + +describe('validateOptions', () => { + it('accepts undefined', () => { + expect(validate(undefined)).toEqual(result(DEFAULT_OPTIONS)); + }); + + it('accepts empty object', () => { + expect(validate({})).toEqual(result(DEFAULT_OPTIONS)); + }); + + it('accepts defaults', () => { + expect(validate(DEFAULT_OPTIONS)).toEqual(result(DEFAULT_OPTIONS)); + }); + + it('rejects null', () => { + expect( + // @ts-expect-error: TS should error + () => validate(null), + ).toThrowErrorMatchingInlineSnapshot(`""value" must be of type object"`); + }); + + it('rejects number', () => { + expect( + // @ts-expect-error: TS should error + () => validate(42), + ).toThrowErrorMatchingInlineSnapshot(`""value" must be of type object"`); + }); + + describe('svgrConfig', () => { + it('accepts undefined', () => { + expect(validate({svgrConfig: undefined})).toEqual( + result(DEFAULT_OPTIONS), + ); + }); + + it('accepts empty', () => { + expect(validate({svgrConfig: {}})).toEqual(result(DEFAULT_OPTIONS)); + }); + + it('accepts any record', () => { + expect(validate({svgrConfig: {any: 'value', evenNumbers: 42}})).toEqual( + result({ + ...DEFAULT_OPTIONS, + svgrConfig: { + any: 'value', + evenNumbers: 42, + }, + }), + ); + }); + + it('accepts default', () => { + expect(validate({svgrConfig: DEFAULT_OPTIONS.svgrConfig})).toEqual( + result(DEFAULT_OPTIONS), + ); + }); + + it('rejects number values', () => { + expect(() => + // @ts-expect-error: invalid type + validate({svgrConfig: 42}), + ).toThrowErrorMatchingInlineSnapshot( + `""svgrConfig" must be of type object"`, + ); + }); + }); +}); diff --git a/packages/docusaurus-plugin-svgr/src/index.ts b/packages/docusaurus-plugin-svgr/src/index.ts new file mode 100644 index 000000000000..ab92a1ee1507 --- /dev/null +++ b/packages/docusaurus-plugin-svgr/src/index.ts @@ -0,0 +1,30 @@ +/** + * 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 {createLoader} from './svgrLoader'; +import type {LoadContext, Plugin} from '@docusaurus/types'; +import type {PluginOptions, Options} from './options'; + +export default function pluginSVGR( + _context: LoadContext, + options: PluginOptions, +): Plugin { + return { + name: 'docusaurus-plugin-svgr', + configureWebpack: (config, isServer) => { + return { + module: { + rules: [createLoader({isServer, svgrConfig: options.svgrConfig})], + }, + }; + }, + }; +} + +export {validateOptions} from './options'; + +export type {PluginOptions, Options}; diff --git a/packages/docusaurus-plugin-svgr/src/options.ts b/packages/docusaurus-plugin-svgr/src/options.ts new file mode 100644 index 000000000000..c4cd5c9f37e8 --- /dev/null +++ b/packages/docusaurus-plugin-svgr/src/options.ts @@ -0,0 +1,41 @@ +/** + * 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 {Joi} from '@docusaurus/utils-validation'; +import type {OptionValidationContext} from '@docusaurus/types'; + +// TODO unfortunately there's a SVGR TS error when skipLibCheck=false +// related to prettier, see https://github.com/gregberge/svgr/issues/904 +// import type {Config as SVGRConfig} from '@svgr/core'; +// export type {SVGRConfig}; +export type SVGRConfig = any; +export type SVGOConfig = NonNullable; + +export type PluginOptions = { + svgrConfig: SVGRConfig; +}; + +export type Options = { + svgrConfig?: Partial; +}; + +export const DEFAULT_OPTIONS: Partial = { + svgrConfig: {}, +}; + +const pluginOptionsSchema = Joi.object({ + svgrConfig: Joi.object() + .pattern(Joi.string(), Joi.any()) + .optional() + .default(DEFAULT_OPTIONS.svgrConfig), +}).default(DEFAULT_OPTIONS); + +export function validateOptions({ + validate, + options, +}: OptionValidationContext): PluginOptions { + return validate(pluginOptionsSchema, options); +} diff --git a/packages/docusaurus-plugin-svgr/src/svgrLoader.ts b/packages/docusaurus-plugin-svgr/src/svgrLoader.ts new file mode 100644 index 000000000000..3744b9decca1 --- /dev/null +++ b/packages/docusaurus-plugin-svgr/src/svgrLoader.ts @@ -0,0 +1,69 @@ +/** + * 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 {getFileLoaderUtils} from '@docusaurus/utils'; + +import type {SVGRConfig, SVGOConfig} from './options'; +import type {RuleSetRule} from 'webpack'; + +// TODO Docusaurus v4: change these defaults? +// see https://github.com/facebook/docusaurus/issues/8297 +// see https://github.com/facebook/docusaurus/pull/10205 +// see https://github.com/facebook/docusaurus/pull/10211 +const DefaultSVGOConfig: SVGOConfig = { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeTitle: false, + removeViewBox: false, + }, + }, + }, + ], +}; + +const DefaultSVGRConfig: SVGRConfig = { + prettier: false, + svgo: true, + svgoConfig: DefaultSVGOConfig, + titleProp: true, +}; + +type Params = {isServer: boolean; svgrConfig: SVGRConfig}; + +function createSVGRLoader(params: Params): RuleSetRule { + const options: SVGRConfig = { + ...DefaultSVGRConfig, + ...params.svgrConfig, + }; + return { + loader: require.resolve('@svgr/webpack'), + options, + }; +} + +export function createLoader(params: Params): RuleSetRule { + const utils = getFileLoaderUtils(params.isServer); + return { + test: /\.svg$/i, + oneOf: [ + { + use: [createSVGRLoader(params)], + // We don't want to use SVGR loader for non-React source code + // ie we don't want to use SVGR for CSS files... + issuer: { + and: [/\.(?:tsx?|jsx?|mdx?)$/i], + }, + }, + { + use: [utils.loaders.url({folder: 'images'})], + }, + ], + }; +} diff --git a/packages/docusaurus-plugin-svgr/src/types.d.ts b/packages/docusaurus-plugin-svgr/src/types.d.ts new file mode 100644 index 000000000000..6f6f99f12793 --- /dev/null +++ b/packages/docusaurus-plugin-svgr/src/types.d.ts @@ -0,0 +1,8 @@ +/** + * 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. + */ + +/// diff --git a/packages/docusaurus-plugin-svgr/tsconfig.json b/packages/docusaurus-plugin-svgr/tsconfig.json new file mode 100644 index 000000000000..343f87c70bdc --- /dev/null +++ b/packages/docusaurus-plugin-svgr/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "noEmit": false + }, + "include": ["src"], + "exclude": ["**/__tests__/**"] +} diff --git a/packages/docusaurus-preset-classic/package.json b/packages/docusaurus-preset-classic/package.json index 3b627aefed34..8b0cfa0c4d29 100644 --- a/packages/docusaurus-preset-classic/package.json +++ b/packages/docusaurus-preset-classic/package.json @@ -27,6 +27,7 @@ "@docusaurus/plugin-google-gtag": "3.6.1", "@docusaurus/plugin-google-tag-manager": "3.6.1", "@docusaurus/plugin-sitemap": "3.6.1", + "@docusaurus/plugin-svgr": "3.6.1", "@docusaurus/theme-classic": "3.6.1", "@docusaurus/theme-common": "3.6.1", "@docusaurus/theme-search-algolia": "3.6.1", diff --git a/packages/docusaurus-preset-classic/src/index.ts b/packages/docusaurus-preset-classic/src/index.ts index 45ae988bc507..eac8c461b306 100644 --- a/packages/docusaurus-preset-classic/src/index.ts +++ b/packages/docusaurus-preset-classic/src/index.ts @@ -37,6 +37,7 @@ export default function preset( blog, pages, sitemap, + svgr, theme, googleAnalytics, gtag, @@ -92,6 +93,9 @@ export default function preset( if (sitemap !== false && (isProd || debug)) { plugins.push(makePluginConfig('@docusaurus/plugin-sitemap', sitemap)); } + if (svgr !== false) { + plugins.push(makePluginConfig('@docusaurus/plugin-svgr', svgr)); + } if (Object.keys(rest).length > 0) { throw new Error( `Unrecognized keys ${Object.keys(rest).join( diff --git a/packages/docusaurus-preset-classic/src/options.ts b/packages/docusaurus-preset-classic/src/options.ts index a8fdb68125f2..98c4087ac696 100644 --- a/packages/docusaurus-preset-classic/src/options.ts +++ b/packages/docusaurus-preset-classic/src/options.ts @@ -9,6 +9,7 @@ import type {Options as DocsPluginOptions} from '@docusaurus/plugin-content-docs import type {Options as BlogPluginOptions} from '@docusaurus/plugin-content-blog'; import type {Options as PagesPluginOptions} from '@docusaurus/plugin-content-pages'; import type {Options as SitemapPluginOptions} from '@docusaurus/plugin-sitemap'; +import type {Options as SVGRPluginOptions} from '@docusaurus/plugin-svgr'; import type {Options as GAPluginOptions} from '@docusaurus/plugin-google-analytics'; import type {Options as GtagPluginOptions} from '@docusaurus/plugin-google-gtag'; import type {Options as GTMPluginOptions} from '@docusaurus/plugin-google-tag-manager'; @@ -31,6 +32,8 @@ export type Options = { pages?: false | PagesPluginOptions; /** Options for `@docusaurus/plugin-sitemap`. Use `false` to disable. */ sitemap?: false | SitemapPluginOptions; + /** Options for `@docusaurus/plugin-svgr`. Use `false` to disable. */ + svgr?: false | SVGRPluginOptions; /** Options for `@docusaurus/theme-classic`. */ theme?: ThemeOptions; /** diff --git a/packages/docusaurus-types/src/plugin.d.ts b/packages/docusaurus-types/src/plugin.d.ts index fae721dcd0cb..51cecbf64783 100644 --- a/packages/docusaurus-types/src/plugin.d.ts +++ b/packages/docusaurus-types/src/plugin.d.ts @@ -108,6 +108,12 @@ export type HtmlTagObject = { export type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[]; +export type ConfigureWebpackResult = WebpackConfiguration & { + mergeStrategy?: { + [key: string]: CustomizeRuleString; + }; +}; + export type Plugin = { name: string; loadContent?: () => Promise | Content; @@ -134,11 +140,7 @@ export type Plugin = { isServer: boolean, configureWebpackUtils: ConfigureWebpackUtils, content: Content, - ) => WebpackConfiguration & { - mergeStrategy?: { - [key: string]: CustomizeRuleString; - }; - }; + ) => ConfigureWebpackResult; configurePostCss?: (options: PostCssOptions) => PostCssOptions; getThemePath?: () => string; getTypeScriptThemePath?: () => string; diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 4e2b66ba87a9..08f7eef4caed 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -21,7 +21,6 @@ "@docusaurus/logger": "3.6.1", "@docusaurus/types": "3.6.1", "@docusaurus/utils-common": "3.6.1", - "@svgr/webpack": "^8.1.0", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-utils/src/__tests__/webpackUtils.test.ts b/packages/docusaurus-utils/src/__tests__/webpackUtils.test.ts deleted file mode 100644 index 3d2c70f68924..000000000000 --- a/packages/docusaurus-utils/src/__tests__/webpackUtils.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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 {getFileLoaderUtils} from '../webpackUtils'; - -describe('getFileLoaderUtils()', () => { - it('plugin svgo/removeViewBox and removeTitle should be disabled', () => { - const {oneOf} = getFileLoaderUtils().rules.svg(); - expect(oneOf![0]!.use).toContainEqual( - expect.objectContaining({ - loader: require.resolve('@svgr/webpack'), - options: expect.objectContaining({ - svgoConfig: { - plugins: [ - { - name: 'preset-default', - params: { - overrides: { - removeTitle: false, - removeViewBox: false, - }, - }, - }, - ], - }, - }), - }), - ); - }); -}); diff --git a/packages/docusaurus-utils/src/webpackUtils.ts b/packages/docusaurus-utils/src/webpackUtils.ts index 8c005a8a5c4b..dc3dd2b1181a 100644 --- a/packages/docusaurus-utils/src/webpackUtils.ts +++ b/packages/docusaurus-utils/src/webpackUtils.ts @@ -45,7 +45,6 @@ type FileLoaderUtils = { images: () => RuleSetRule; fonts: () => RuleSetRule; media: () => RuleSetRule; - svg: () => RuleSetRule; otherAssets: () => RuleSetRule; }; }; @@ -134,45 +133,6 @@ function createFileLoaderUtils({ test: /\.(?:mp4|avi|mov|mkv|mpg|mpeg|vob|wmv|m4v|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/i, }), - svg: () => ({ - test: /\.svg$/i, - oneOf: [ - { - use: [ - { - loader: require.resolve('@svgr/webpack'), - options: { - prettier: false, - svgo: true, - svgoConfig: { - plugins: [ - { - name: 'preset-default', - params: { - overrides: { - removeTitle: false, - removeViewBox: false, - }, - }, - }, - ], - }, - titleProp: true, - }, - }, - ], - // We don't want to use SVGR loader for non-React source code - // ie we don't want to use SVGR for CSS files... - issuer: { - and: [/\.(?:tsx?|jsx?|mdx?)$/i], - }, - }, - { - use: [loaders.url({folder: 'images'})], - }, - ], - }), - otherAssets: () => ({ use: [loaders.file({folder: 'files'})], test: /\.(?:pdf|docx?|xlsx?|zip|rar)$/i, diff --git a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap index 8f321b063446..88a08cdf5997 100644 --- a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap +++ b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap @@ -52,54 +52,3 @@ exports[`base webpack config creates webpack aliases 1`] = ` "react-dom": "../../../../../../../node_modules/react-dom", } `; - -exports[`base webpack config uses svg rule 1`] = ` -{ - "oneOf": [ - { - "issuer": { - "and": [ - /\\\\\\.\\(\\?:tsx\\?\\|jsx\\?\\|mdx\\?\\)\\$/i, - ], - }, - "use": [ - { - "loader": "/node_modules/@svgr/webpack/dist/index.js", - "options": { - "prettier": false, - "svgo": true, - "svgoConfig": { - "plugins": [ - { - "name": "preset-default", - "params": { - "overrides": { - "removeTitle": false, - "removeViewBox": false, - }, - }, - }, - ], - }, - "titleProp": true, - }, - }, - ], - }, - { - "use": [ - { - "loader": "/node_modules/url-loader/dist/cjs.js", - "options": { - "emitFile": true, - "fallback": "/node_modules/file-loader/dist/cjs.js", - "limit": 10000, - "name": "assets/images/[name]-[contenthash].[ext]", - }, - }, - ], - }, - ], - "test": /\\\\\\.svg\\$/i, -} -`; diff --git a/packages/docusaurus/src/webpack/__tests__/base.test.ts b/packages/docusaurus/src/webpack/__tests__/base.test.ts index b4c29b514e17..676e509fe4b9 100644 --- a/packages/docusaurus/src/webpack/__tests__/base.test.ts +++ b/packages/docusaurus/src/webpack/__tests__/base.test.ts @@ -132,20 +132,4 @@ describe('base webpack config', () => { ); expect(relativeAliases).toMatchSnapshot(); }); - - it('uses svg rule', async () => { - const config = await createBaseConfig({ - props, - isServer: false, - minify: false, - faster: DEFAULT_FASTER_CONFIG, - configureWebpackUtils: await createTestConfigureWebpackUtils(), - }); - - const svgRule = (config.module?.rules ?? []).find((rule) => { - return rule && (rule as any).test.toString().includes('.svg'); - }); - expect(svgRule).toBeDefined(); - expect(svgRule).toMatchSnapshot(); - }); }); diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index 31ea6b85d5c1..5ae2a215e533 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -245,7 +245,6 @@ export async function createBaseConfig({ fileLoaderUtils.rules.images(), fileLoaderUtils.rules.fonts(), fileLoaderUtils.rules.media(), - fileLoaderUtils.rules.svg(), fileLoaderUtils.rules.otherAssets(), { test: /\.[jt]sx?$/i, diff --git a/website/_dogfooding/_pages tests/index.mdx b/website/_dogfooding/_pages tests/index.mdx index 4f7c2889bff1..d862394e29c4 100644 --- a/website/_dogfooding/_pages tests/index.mdx +++ b/website/_dogfooding/_pages tests/index.mdx @@ -26,6 +26,7 @@ import Readme from "../README.mdx" ### Other tests - [React 18](/tests/pages/react-18) +- [SVG](/tests/pages/svg) - [Crash test](/tests/pages/crashTest) - [Code block tests](/tests/pages/code-block-tests) - [Link tests](/tests/pages/link-tests) diff --git a/website/_dogfooding/_pages tests/svg/index.mdx b/website/_dogfooding/_pages tests/svg/index.mdx new file mode 100644 index 000000000000..494bc5e21d10 --- /dev/null +++ b/website/_dogfooding/_pages tests/svg/index.mdx @@ -0,0 +1,11 @@ +import Integrations from './integrations.svg'; +import OpenSource from './open-source.svg'; +import Mascot from './mascot.svg'; + +# Many inline SVGs + +Have a bunch of SVGs, they're written to intentionally override each others styled when inlined on the same page. + + + + diff --git a/website/_dogfooding/_pages tests/svg/integrations.svg b/website/_dogfooding/_pages tests/svg/integrations.svg new file mode 100644 index 000000000000..659c5d146bfa --- /dev/null +++ b/website/_dogfooding/_pages tests/svg/integrations.svg @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/_dogfooding/_pages tests/svg/mascot.svg b/website/_dogfooding/_pages tests/svg/mascot.svg new file mode 100644 index 000000000000..b3c8bbe6e758 --- /dev/null +++ b/website/_dogfooding/_pages tests/svg/mascot.svg @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/_dogfooding/_pages tests/svg/open-source.svg b/website/_dogfooding/_pages tests/svg/open-source.svg new file mode 100644 index 000000000000..08311e31c091 --- /dev/null +++ b/website/_dogfooding/_pages tests/svg/open-source.svg @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/docs/api/plugins/overview.mdx b/website/docs/api/plugins/overview.mdx index 651517d4ee83..23eb70892996 100644 --- a/website/docs/api/plugins/overview.mdx +++ b/website/docs/api/plugins/overview.mdx @@ -23,8 +23,11 @@ These plugins will add a useful behavior to your Docusaurus site. - [@docusaurus/plugin-debug](./plugin-debug.mdx) - [@docusaurus/plugin-sitemap](./plugin-sitemap.mdx) +- [@docusaurus/plugin-svgr](./plugin-svgr.mdx) +- [@docusaurus/plugin-rsdoctor](./plugin-rsdoctor.mdx) - [@docusaurus/plugin-pwa](./plugin-pwa.mdx) - [@docusaurus/plugin-client-redirects](./plugin-client-redirects.mdx) - [@docusaurus/plugin-ideal-image](./plugin-ideal-image.mdx) - [@docusaurus/plugin-google-analytics](./plugin-google-analytics.mdx) - [@docusaurus/plugin-google-gtag](./plugin-google-gtag.mdx) +- [@docusaurus/plugin-google-tag-manager](./plugin-google-tag-manager.mdx) diff --git a/website/docs/api/plugins/plugin-svgr.mdx b/website/docs/api/plugins/plugin-svgr.mdx new file mode 100644 index 000000000000..bd5bef1eab90 --- /dev/null +++ b/website/docs/api/plugins/plugin-svgr.mdx @@ -0,0 +1,55 @@ +--- +sidebar_position: 7 +slug: /api/plugins/@docusaurus/plugin-svgr +--- + +# 📦 plugin-svgr + +import APITable from '@site/src/components/APITable'; + +An [SVGR](https://react-svgr.com/) plugin to transform SVG files into React components automatically at build time. + +## Installation {#installation} + +```bash npm2yarn +npm install --save @docusaurus/plugin-svgr +``` + +:::tip + +If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency. + +You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic). + +::: + +## Configuration {#configuration} + +Accepted fields: + +```mdx-code-block + +``` + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `svgrConfig` | `object` | `{}` | The [SVGR config options](https://react-svgr.com/docs/options/), forwarded as is | + +```mdx-code-block + +``` + +### Example configuration {#ex-config} + +You can configure this plugin through plugin options. + +```js config-tabs +// Preset Options: svgr +// Plugin Options: @docusaurus/plugin-svgr + +const config = { + svgrConfig: { + /* SVGR config */ + }, +}; +``` diff --git a/website/docs/using-plugins.mdx b/website/docs/using-plugins.mdx index 92d86097d717..a9d7f043243b 100644 --- a/website/docs/using-plugins.mdx +++ b/website/docs/using-plugins.mdx @@ -148,6 +148,7 @@ The classic preset is shipped by default to new Docusaurus websites created with - [`@docusaurus/plugin-google-tag-manager`](./api/plugins/plugin-google-tag-manager.mdx) - [`@docusaurus/plugin-google-analytics`](./api/plugins/plugin-google-analytics.mdx) (**deprecated**) - [`@docusaurus/plugin-sitemap`](./api/plugins/plugin-sitemap.mdx) +- [`@docusaurus/plugin-svgr`](./api/plugins/plugin-svgr.mdx) The classic preset will relay each option entry to the respective plugin/theme. @@ -171,6 +172,8 @@ export default { pages: {}, // Will be passed to @docusaurus/plugin-sitemap (false to disable) sitemap: {}, + // Will be passed to @docusaurus/plugin-svgr (false to disable) + svgr: {}, // Will be passed to @docusaurus/plugin-google-gtag (only enabled when explicitly specified) gtag: {}, // Will be passed to @docusaurus/plugin-google-tag-manager (only enabled when explicitly specified) diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index b52e5c859a7a..852a0b4e3c83 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -547,6 +547,11 @@ export default async function createConfigAsync() { priority: null, changefreq: null, }, + svgr: { + svgrConfig: { + svgoConfig: undefined, // Use .svgo.config.js + }, + }, } satisfies Preset.Options, ], ], diff --git a/website/svgo.config.js b/website/svgo.config.js new file mode 100644 index 000000000000..be70fc07fc59 --- /dev/null +++ b/website/svgo.config.js @@ -0,0 +1,29 @@ +/** + * 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 path = require('path'); + +module.exports = { + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + removeTitle: false, + removeViewBox: false, + }, + }, + }, + { + name: 'prefixIds', + params: { + delim: '', + prefix: (_, info) => path.parse(info.path).name, + }, + }, + ], +};