diff --git a/scripts/build-plugins/rollup-plugin-build-themes.js b/scripts/build-plugins/rollup-plugin-build-themes.js index 6b8fdae0..b523778b 100644 --- a/scripts/build-plugins/rollup-plugin-build-themes.js +++ b/scripts/build-plugins/rollup-plugin-build-themes.js @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ const path = require('path').posix; +const {optimize} = require('svgo'); async function readCSSSource(location) { const fs = require("fs").promises; - const path = require("path"); const resolvedLocation = path.resolve(__dirname, "../../", `${location}/theme.css`); const data = await fs.readFile(resolvedLocation); return data; @@ -43,6 +43,28 @@ function addThemesToConfig(bundle, manifestLocations, defaultThemes) { } } +/** + * Returns an object where keys are the svg file names and the values + * are the svg code (optimized) + * @param {*} icons Object where keys are css variable names and values are locations of the svg + * @param {*} manifestLocation Location of manifest used for resolving path + */ +async function generateIconSourceMap(icons, manifestLocation) { + const sources = {}; + const fs = require("fs").promises; + for (const icon of Object.values(icons)) { + const [location] = icon.split("?"); + const resolvedLocation = path.resolve(__dirname, "../../", manifestLocation, location); + const iconData = await fs.readFile(resolvedLocation); + const svgString = iconData.toString(); + const result = optimize(svgString); + const optimizedSvgString = result.data; + const fileName = path.basename(resolvedLocation); + sources[fileName] = optimizedSvgString; + } + return sources; +} + /** * Returns a mapping from location (of manifest file) to an array containing all the chunks (of css files) generated from that location. * To understand what chunk means in this context, see https://rollupjs.org/guide/en/#generatebundle. @@ -283,7 +305,7 @@ module.exports = function buildThemes(options) { ]; }, - generateBundle(_, bundle) { + async generateBundle(_, bundle) { const assetMap = getMappingFromFileNameToAssetInfo(bundle); const chunkMap = getMappingFromLocationToChunkArray(bundle); const runtimeThemeChunkMap = getMappingFromLocationToRuntimeChunk(bundle); @@ -304,13 +326,28 @@ module.exports = function buildThemes(options) { const locationRelativeToManifest = path.relative(manifestLocation, locationRelativeToBuildRoot); builtAssets[`${name}-${variant}`] = locationRelativeToManifest; } + // Emit the base svg icons as asset + const nameToAssetHashedLocation = []; + const nameToSource = await generateIconSourceMap(icon, location); + for (const [name, source] of Object.entries(nameToSource)) { + const ref = this.emitFile({ type: "asset", name, source }); + const assetHashedName = this.getFileName(ref); + nameToAssetHashedLocation[name] = assetHashedName; + } + for (const [variable, location] of Object.entries(icon)) { + const [locationWithoutQueryParameters, queryParameters] = location.split("?"); + const name = path.basename(locationWithoutQueryParameters); + const locationRelativeToBuildRoot = nameToAssetHashedLocation[name]; + const locationRelativeToManifest = path.relative(manifestLocation, locationRelativeToBuildRoot); + icon[variable] = `${locationRelativeToManifest}?${queryParameters}`; + } const runtimeThemeChunk = runtimeThemeChunkMap.get(location); const runtimeAssetLocation = path.relative(manifestLocation, assetMap.get(runtimeThemeChunk.fileName).fileName); manifest.source = { "built-assets": builtAssets, "runtime-asset": runtimeAssetLocation, "derived-variables": derivedVariables, - "icon": icon + "icon": icon, }; const name = `theme-${themeKey}.json`; manifestLocations.push(`${manifestLocation}/${name}`);