Skip to content

Commit

Permalink
Merge pull request #41 from nextcloud-libraries/feat/customize-assets…
Browse files Browse the repository at this point in the history
…-file-names

feat: add option to customize asset file names
  • Loading branch information
susnux committed Oct 18, 2023
2 parents 63c6365 + b1e4978 commit 67e1a38
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 4 deletions.
42 changes: 39 additions & 3 deletions __tests__/appconfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { build } from 'vite'
// ok as this is just for tests
// eslint-disable-next-line n/no-extraneous-import
import type { RollupOutput, OutputChunk } from 'rollup'
import type { RollupOutput, OutputOptions, OutputChunk } from 'rollup'
import { build, resolveConfig } from 'vite'
import { describe, it, expect } from 'vitest'
import { createAppConfig } from '../lib/appConfig'
import { fileURLToPath } from 'url'
import { resolve } from 'path'
import { LibraryOptions } from '../lib/libConfig'

const __dirname = fileURLToPath(new URL('.', import.meta.url))

Expand All @@ -32,4 +32,40 @@ describe('app config', () => {
expect(code.includes('process.env')).toBe(false)
expect(code).toMatchSnapshot()
})

it('moves CSS assets to css/', async () => {
const resolved = await createConfig('build', 'development')

const output = resolved.build.rollupOptions.output as OutputOptions
expect(typeof output?.assetFileNames).toBe('function')
const assetFileNames = output?.assetFileNames as ((chunkInfo: unknown) => string)
expect(assetFileNames({ name: 'some.css' })).toBe('css/@nextcloud-vite-config-[name].css')
expect(assetFileNames({ name: 'other/file.css' })).toBe('css/@nextcloud-vite-config-[name].css')
})

it('moves image assets to img/', async () => {
const resolved = await createConfig('build', 'development')

const output = resolved.build.rollupOptions.output as OutputOptions
expect(typeof output?.assetFileNames).toBe('function')
const assetFileNames = output?.assetFileNames as ((chunkInfo: unknown) => string)
expect(assetFileNames({ name: 'some.png' })).toBe('img/[name][extname]')
expect(assetFileNames({ name: 'some.svg' })).toBe('img/[name][extname]')
expect(assetFileNames({ name: 'some.jpg' })).toBe('img/[name][extname]')
expect(assetFileNames({ name: 'some.ico' })).toBe('img/[name][extname]')
})

it('allow custom asset names', async () => {
const resolved = await createConfig('build', 'development', { assetFileNames: (({ name }) => name === 'main.css' ? 'css/app-styles.css' : undefined) as never })

const output = resolved.build.rollupOptions.output as OutputOptions
expect(typeof output?.assetFileNames).toBe('function')
const assetFileNames = output?.assetFileNames as ((chunkInfo: unknown) => string)
expect(assetFileNames({ name: 'main.css' })).toBe('css/app-styles.css')
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({
main: 'src/main.js',
}, options)({ command, mode, ssrBuild: false }), command)
})
24 changes: 24 additions & 0 deletions __tests__/libconfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ describe('library config', () => {
// and minify disabled
expect(resolved.build.minify).toBe(false)
})

it('keep name without inlining the CSS assets ', async () => {
const resolved = await createConfig('build', 'development')

expect(resolved.build.rollupOptions.output?.[0].assetFileNames).not.toBe(undefined)
expect(resolved.build.rollupOptions.output?.[0].assetFileNames({ name: 'some.css' })).toBe('[name].css')
expect(resolved.build.rollupOptions.output?.[0].assetFileNames({ name: 'some.nfo' })).toBe('assets/[name]-[hash][extname]')
})

it('move CSS files to asset directory when inlining CSS', async () => {
const resolved = await createConfig('build', 'development', { inlineCSS: true })

expect(resolved.build.rollupOptions.output?.[0].assetFileNames).not.toBe(undefined)
expect(resolved.build.rollupOptions.output?.[0].assetFileNames({ name: 'some.css' })).toBe('assets/[name]-[hash][extname]')
expect(resolved.build.rollupOptions.output?.[0].assetFileNames({ name: 'some.nfo' })).toBe('assets/[name]-[hash][extname]')
})

it('allow custom asset names', async () => {
const resolved = await createConfig('build', 'development', { assetFileNames: (({ name }) => name === 'foo.css' ? 'bar.css' : undefined) as never })

expect(resolved.build.rollupOptions.output?.[0].assetFileNames).not.toBe(undefined)
expect(resolved.build.rollupOptions.output?.[0].assetFileNames({ name: 'foo.css' })).toBe('bar.css')
expect(resolved.build.rollupOptions.output?.[0].assetFileNames({ name: 'baz.css' })).toBe('[name].css')
})
})

const createConfig = async (command: 'build' | 'serve' = 'build', mode: 'development' | 'production' = 'production', options?: LibraryOptions) => await resolveConfig(await createLibConfig({
Expand Down
8 changes: 8 additions & 0 deletions lib/appConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ export const createAppConfig = (entries: { [entryAlias: string]: string }, optio
// global variables for appName and appVersion
intro: `const appName = ${JSON.stringify(appName)}; const appVersion = ${JSON.stringify(appVersion)};`,
assetFileNames: (assetInfo) => {
// Allow to customize the asset file names
if (options.assetFileNames) {
const customName = options.assetFileNames(assetInfo)
if (customName) {
return customName
}
}

const extType = assetInfo.name.split('.').pop()
if (/png|jpe?g|svg|gif|tiff|bmp|ico/i.test(extType)) {
return 'img/[name][extname]'
Expand Down
11 changes: 10 additions & 1 deletion lib/baseConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { readFileSync } from 'node:fs'
import { type CoreJSPluginOptions, corejsPlugin } from 'rollup-plugin-corejs'
import { minify as minifyPlugin } from 'rollup-plugin-esbuild-minify/lib/index.js'
import { nodePolyfills } from 'vite-plugin-node-polyfills'
import { defineConfig, mergeConfig, type UserConfigExport, type UserConfigFn } from 'vite'
import { defineConfig, mergeConfig, type UserConfigExport, type UserConfigFn, type Rollup } from 'vite'
import { RemoveEnsureWatchPlugin } from './plugins/RemoveEnsureWatch.js'

import replace from '@rollup/plugin-replace'
Expand Down Expand Up @@ -49,6 +49,15 @@ export interface BaseOptions {
* @default 'dist/vendor.LICENSE.txt'
*/
thirdPartyLicense?: false | string
/**
* Customize the asset file names.
* Similar to `output.assetFileNames` in rollup config,
* but if returns undefined, then this config defaults is be used.
*
* @example Move CSS styles to `styles/style.css` instead of the default `css/[entrypoint-name].css`:
* (chunkInfo) => chunkInfo.name.endsWith('.css') ? 'styles/style.css' : undefined
*/
assetFileNames?: (chunkInfo: Rollup.PreRenderedAsset) => 'string' | undefined,
/**
* Vite config to override or extend the base config
*/
Expand Down
8 changes: 8 additions & 0 deletions lib/libConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ export const createLibConfig = (entries: { [entryAlias: string]: string }, optio
const userConfig = await Promise.resolve(typeof options.config === 'function' ? options.config(env) : options.config)

const assetFileNames = (assetInfo) => {
// Allow to customize the asset file names
if (options.assetFileNames) {
const customName = options.assetFileNames(assetInfo)
if (customName) {
return customName
}
}

const extType = assetInfo.name.split('.').pop()
if (!options.inlineCSS && /css/i.test(extType)) {
return '[name].css'
Expand Down

0 comments on commit 67e1a38

Please sign in to comment.