diff --git a/__tests__/appconfig.spec.ts b/__tests__/appconfig.spec.ts index 2261546..a6ad792 100644 --- a/__tests__/appconfig.spec.ts +++ b/__tests__/appconfig.spec.ts @@ -3,15 +3,16 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later */ + // ok as this is just for tests // eslint-disable-next-line n/no-extraneous-import import type { RollupOutput, OutputOptions, OutputChunk } from 'rollup' import { build, resolveConfig } from 'vite' import { describe, it, expect } from 'vitest' -import { createAppConfig } from '../lib/appConfig' +import { AppOptions, createAppConfig } from '../lib/appConfig' import { fileURLToPath } from 'url' import { resolve } from 'path' -import { LibraryOptions } from '../lib/libConfig' +import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' const __dirname = fileURLToPath(new URL('.', import.meta.url)) @@ -65,7 +66,31 @@ describe('app config', () => { expect(assetFileNames({ name: 'foo.css' })).toBe('css/@nextcloud-vite-config-[name].css') }) - const createConfig = async (command: 'build' | 'serve' = 'build', mode: 'development' | 'production' = 'production', options?: LibraryOptions) => await resolveConfig(await createAppConfig({ + describe('inlining css', () => { + const pluginName = cssInjectedByJsPlugin().name + + it('does not inline css by default', async () => { + const resolved = await createConfig() + expect(resolved.plugins.filter(({ name }) => name === pluginName)).toHaveLength(0) + }) + + it('does not inline css when disabled', async () => { + const resolved = await createConfig('build', 'production', { inlineCSS: false }) + expect(resolved.plugins.filter(({ name }) => name === pluginName)).toHaveLength(0) + }) + + it('does inline css when enabled', async () => { + const resolved = await createConfig('build', 'production', { inlineCSS: true }) + expect(resolved.plugins.filter(({ name }) => name === pluginName)).toHaveLength(1) + }) + + it('does inline css when enabled with configuration', async () => { + const resolved = await createConfig('build', 'production', { inlineCSS: { useStrictCSP: true } }) + expect(resolved.plugins.filter(({ name }) => name === pluginName)).toHaveLength(1) + }) + }) + + const createConfig = async (command: 'build' | 'serve' = 'build', mode: 'development' | 'production' = 'production', options?: AppOptions) => await resolveConfig(await createAppConfig({ main: 'src/main.js', }, options)({ command, mode, ssrBuild: false }), command) }) diff --git a/lib/appConfig.ts b/lib/appConfig.ts index b07648d..43ce863 100644 --- a/lib/appConfig.ts +++ b/lib/appConfig.ts @@ -5,6 +5,7 @@ */ import type { UserConfig, UserConfigFn } from 'vite' +import type { PluginConfiguration as VitePluginInjectCSSOptions } from 'vite-plugin-css-injected-by-js/dist/esm/declarations/interface.js' import type { BaseOptions, NodePolyfillsOptions } from './baseConfig.js' import { mergeConfig } from 'vite' @@ -18,7 +19,13 @@ export const appName = process.env.npm_package_name export const appVersion = process.env.npm_package_version export const appNameSanitized = appName.replace(/[/\\]/, '-') -export interface AppOptions extends BaseOptions { +export interface AppOptions extends Omit<BaseOptions, 'inlineCSS'> { + /** + * Inject all styles inside the javascript bundle instead of emitting a .css file + * @default false + */ + inlineCSS?: boolean | VitePluginInjectCSSOptions, + /** * Whether to empty the output directory (`js/`) * @default true @@ -66,7 +73,7 @@ export const createAppConfig = (entries: { [entryAlias: string]: string }, optio } return createBaseConfig({ - ...options, + ...(options as BaseOptions), config: async (env) => { console.info(`Building ${appName} for ${env.mode}`) @@ -76,8 +83,8 @@ export const createAppConfig = (entries: { [entryAlias: string]: string }, optio const plugins = [] // Inject all imported styles into the javascript bundle by creating dynamic styles on the document - if (options?.inlineCSS !== false) { - plugins.push(injectCSSPlugin()) + if (options.inlineCSS) { + plugins.push(injectCSSPlugin(typeof options.inlineCSS === 'object' ? options.inlineCSS : undefined)) } // defaults to true so only not adding if explicitly set to false