From 747acd2dfcf614d9cff085e0d9b69e2f93fc52d8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 23 Jun 2020 09:26:05 +0200 Subject: [PATCH] cli: allow svg imports and special .icon.svg import --- packages/cli/asset-types/asset-types.d.ts | 8 ++++ packages/cli/package.json | 4 ++ packages/cli/src/lib/bundler/transforms.ts | 24 ++++++++++- packages/cli/src/lib/packager/config.ts | 8 +++- packages/cli/src/lib/svgrTemplate.ts | 47 ++++++++++++++++++++++ yarn.lock | 22 ++++++++-- 6 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 packages/cli/src/lib/svgrTemplate.ts diff --git a/packages/cli/asset-types/asset-types.d.ts b/packages/cli/asset-types/asset-types.d.ts index d8995fcb37..1763d256f5 100644 --- a/packages/cli/asset-types/asset-types.d.ts +++ b/packages/cli/asset-types/asset-types.d.ts @@ -50,6 +50,14 @@ declare module '*.webp' { export default src; } +declare module '*.icon.svg' { + import { ComponentType } from 'react'; + import { SvgIconProps } from '@material-ui/core'; + + const Icon: ComponentType; + export default Icon; +} + declare module '*.svg' { const src: string; export default src; diff --git a/packages/cli/package.json b/packages/cli/package.json index 96ca8e4a4f..66828e9dec 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -39,6 +39,10 @@ "@rollup/plugin-node-resolve": "^7.1.1", "@spotify/eslint-config": "^7.0.1", "@sucrase/webpack-loader": "^2.0.0", + "@svgr/plugin-jsx": "4.3.x", + "@svgr/plugin-svgo": "4.3.x", + "@svgr/rollup": "4.3.x", + "@svgr/webpack": "4.3.x", "@types/start-server-webpack-plugin": "^2.2.0", "@types/webpack-env": "^1.15.2", "@types/webpack-node-externals": "^1.7.1", diff --git a/packages/cli/src/lib/bundler/transforms.ts b/packages/cli/src/lib/bundler/transforms.ts index 0cd800f2ea..5f881bd53c 100644 --- a/packages/cli/src/lib/bundler/transforms.ts +++ b/packages/cli/src/lib/bundler/transforms.ts @@ -17,6 +17,7 @@ import webpack, { Module, Plugin } from 'webpack'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import { BundlingOptions, BackendBundlingOptions } from './types'; +import { svgrTemplate } from '../svgrTemplate'; type Transforms = { loaders: Module['rules']; @@ -46,7 +47,28 @@ export const transforms = ( }, }, { - test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.frag/, /\.xml/], + test: [/\.icon\.svg$/], + use: [ + { + loader: require.resolve('@sucrase/webpack-loader'), + options: { transforms: ['jsx'] }, + }, + { + loader: require.resolve('@svgr/webpack'), + options: { babel: false, template: svgrTemplate }, + }, + ], + }, + { + test: [ + /\.bmp$/, + /\.gif$/, + /\.jpe?g$/, + /\.png$/, + /\.frag/, + { test: /\.svg/, not: [/\.icon\.svg/] }, + /\.xml/, + ], loader: require.resolve('url-loader'), options: { limit: 10000, diff --git a/packages/cli/src/lib/packager/config.ts b/packages/cli/src/lib/packager/config.ts index 30680ef3b9..5987290604 100644 --- a/packages/cli/src/lib/packager/config.ts +++ b/packages/cli/src/lib/packager/config.ts @@ -23,12 +23,14 @@ import resolve from '@rollup/plugin-node-resolve'; import postcss from 'rollup-plugin-postcss'; import esbuild from 'rollup-plugin-esbuild'; import imageFiles from 'rollup-plugin-image-files'; +import svgr from '@svgr/rollup'; import dts from 'rollup-plugin-dts'; import json from '@rollup/plugin-json'; import { RollupOptions, OutputOptions } from 'rollup'; import { BuildOptions, Output } from './types'; import { paths } from '../paths'; +import { svgrTemplate } from '../svgrTemplate'; export const makeConfigs = async ( options: BuildOptions, @@ -89,8 +91,12 @@ export const makeConfigs = async ( exclude: ['**/*.stories.*', '**/*.test.*'], }), postcss(), - imageFiles(), + imageFiles({ exclude: '**/*.icon.svg' }), json(), + svgr({ + include: '**/*.icon.svg', + template: svgrTemplate, + }), esbuild({ target: 'es2019', }), diff --git a/packages/cli/src/lib/svgrTemplate.ts b/packages/cli/src/lib/svgrTemplate.ts new file mode 100644 index 0000000000..5f7c7f9a4c --- /dev/null +++ b/packages/cli/src/lib/svgrTemplate.ts @@ -0,0 +1,47 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This template, together with loaders in the bundler and packages, allows + * for SVG to be imported directly as MUI SvgIcon components by suffixing + * them with .icon.svg + */ +export function svgrTemplate( + { template }: any, + _opts: any, + { imports, interfaces, componentName, jsx }: any, +) { + const iconName = { + ...componentName, + name: `${componentName.name.replace(/icon$/, '')}Icon`, + }; + + const defaultExport = { + type: 'ExportDefaultDeclaration', + declaration: iconName, + }; + + const typeScriptTemplate = template.smart({ plugins: ['typescript'] }); + return typeScriptTemplate.ast` +${imports} +import SvgIcon from '@material-ui/core/SvgIcon'; + +${interfaces} + +const ${iconName} = props => React.createElement(SvgIcon, props, ${jsx.children}); + +${defaultExport}`; +} diff --git a/yarn.lock b/yarn.lock index fd351efe36..3aa425b46e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3208,7 +3208,7 @@ dependencies: "@babel/types" "^7.4.4" -"@svgr/plugin-jsx@^4.3.3": +"@svgr/plugin-jsx@4.3.x", "@svgr/plugin-jsx@^4.3.3": version "4.3.3" resolved "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-4.3.3.tgz#e2ba913dbdfbe85252a34db101abc7ebd50992fa" integrity sha512-cLOCSpNWQnDB1/v+SUENHH7a0XY09bfuMKdq9+gYvtuwzC2rU4I0wKGFEp1i24holdQdwodCtDQdFtJiTCWc+w== @@ -3218,7 +3218,7 @@ "@svgr/hast-util-to-babel-ast" "^4.3.2" svg-parser "^2.0.0" -"@svgr/plugin-svgo@^4.3.1": +"@svgr/plugin-svgo@4.3.x", "@svgr/plugin-svgo@^4.3.1": version "4.3.1" resolved "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.3.1.tgz#daac0a3d872e3f55935c6588dd370336865e9e32" integrity sha512-PrMtEDUWjX3Ea65JsVCwTIXuSqa3CG9px+DluF1/eo9mlDrgrtFE7NE/DjdhjJgSM9wenlVBzkzneSIUgfUI/w== @@ -3227,7 +3227,21 @@ merge-deep "^3.0.2" svgo "^1.2.2" -"@svgr/webpack@^4.0.3": +"@svgr/rollup@4.3.x": + version "4.3.3" + resolved "https://registry.npmjs.org/@svgr/rollup/-/rollup-4.3.3.tgz#db8bc2746ae0930c14cba2409f417a6ac6aadb38" + integrity sha512-YwgnXN8xPRYFhkfoTUiZktjkjolthaK/lz0okzU09VcBvjx08R7yK1IEwXH3c98sMn8ORdNdiy4Qox78CMjljg== + dependencies: + "@babel/core" "^7.4.5" + "@babel/plugin-transform-react-constant-elements" "^7.0.0" + "@babel/preset-env" "^7.4.5" + "@babel/preset-react" "^7.0.0" + "@svgr/core" "^4.3.3" + "@svgr/plugin-jsx" "^4.3.3" + "@svgr/plugin-svgo" "^4.3.1" + rollup-pluginutils "^2.8.1" + +"@svgr/webpack@4.3.x", "@svgr/webpack@^4.0.3": version "4.3.3" resolved "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.3.3.tgz#13cc2423bf3dff2d494f16b17eb7eacb86895017" integrity sha512-bjnWolZ6KVsHhgyCoYRFmbd26p8XVbulCzSG53BDQqAr+JOAderYK7CuYrB3bDjHJuF6LJ7Wrr42+goLRV9qIg== @@ -16470,7 +16484,7 @@ rollup-pluginutils@2.4.1: estree-walker "^0.6.0" micromatch "^3.1.10" -rollup-pluginutils@2.8.2, rollup-pluginutils@^2.8.2: +rollup-pluginutils@2.8.2, rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: version "2.8.2" resolved "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==