Skip to content

Commit

Permalink
feat: rework plugin to use new core library
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasKruckenberg committed Mar 16, 2021
1 parent b6ac8b3 commit e8e11cf
Showing 1 changed file with 49 additions and 59 deletions.
108 changes: 49 additions & 59 deletions packages/vite/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,114 +1,104 @@
// import * as imagetools from imagetools-core'
import findCacheDir from 'find-cache-dir'
import { basename, extname, join, relative } from 'path'
import type { Plugin, ResolvedConfig } from 'vite'
import { OutputFormat, PluginOptions } from './types'
import { createFilter, dataToEsm } from '@rollup/pluginutils'
import { builtins, parseURL, generateConfigs, generateTransforms, applyTransforms, cache, loadImageFromDisk } from 'imagetools-core'
import { Plugin, ResolvedConfig } from "vite";
import { parseURL, loadImageFromDisk, builtins, resolveConfigs, applyTransforms, generateTransforms, getMetadata } from 'imagetools-core'
import { basename, extname, join } from 'path'
import { createFilter, dataToEsm } from "@rollup/pluginutils";
import { builtinOutputFormats, urlFormat } from './output-formats'
import MagicString from 'magic-string'
import { OutputFormat, PluginOptions } from "./types";
import findCacheDir from "find-cache-dir";

const defaultOptions: PluginOptions = {
include: '**\/*.{heic,heif,avif,jpeg,jpg,png,tiff,webp,gif}?*',
exclude: 'public\/**\/*',
cache: findCacheDir({ name: 'vite-imagetools' }) || false,
cache: findCacheDir({ name: 'imagetools' }) || false,
silent: false
}

export default (userOptions: Partial<PluginOptions> = {}): Plugin => {
export default function imagetools(userOptions: Partial<PluginOptions> = {}): Plugin {
const pluginOptions: PluginOptions = { ...defaultOptions, ...userOptions }

const filter = createFilter(pluginOptions.include, pluginOptions.exclude)

const directives = pluginOptions.extendDirectives
? pluginOptions.extendDirectives(builtins)
const directives = pluginOptions.extendDirectives
? pluginOptions.extendDirectives(builtins)
: builtins

const OutputFormats = pluginOptions.extendOutputFormats
? pluginOptions.extendOutputFormats(builtinOutputFormats)
const outputFormats = pluginOptions.extendOutputFormats
? pluginOptions.extendOutputFormats(builtinOutputFormats)
: builtinOutputFormats

let viteConfig: ResolvedConfig

const generatedImages = new Map()

return {
name: 'imagetools',
enforce: 'pre',
configResolved(cfg) {
viteConfig = cfg
},
async load(id) {
if (!filter(id)) return
if (!filter(id)) return null

const src = new URL(id, 'file://')
const parameters = parseURL(new URL(id, 'file://'))
const parameters = parseURL(src)
const imageConfigs = resolveConfigs(parameters)

const imageConfigs = generateConfigs(parameters)
const img = loadImageFromDisk(src.pathname)

const generatedImages: Record<string, any>[] = []
const outputMetadatas = []

for (const config of imageConfigs) {
const cacheId = cache.generateKey(src, config)

let outputMetadata = undefined
let outputData = undefined

try {
// restore from cache
if (!pluginOptions.cache) throw new Error('no cache configured so break to transformation')

const { data, metadata } = await cache.get(pluginOptions.cache, cacheId)
outputData = data
outputMetadata = metadata
const id = Buffer.from(JSON.stringify(config)).toString('base64')

} catch {
// generateTransforms
const { transforms, metadata, warnings, parametersUsed } = generateTransforms(config, directives)
const { transforms } = generateTransforms(config, directives)
const { image, metadata } = await applyTransforms(transforms, img)

if (!pluginOptions.silent) {
warnings.forEach(message => this.warn(message))
}
generatedImages.set(id, image)

const img = loadImageFromDisk(src.pathname)

// applyTransforms
const { data, info } = await applyTransforms(transforms, img)

outputData = data
outputMetadata = { ...metadata, ...info }

// cache image
if (pluginOptions.cache) {
await cache.put(pluginOptions.cache, cacheId, data, outputMetadata)
}
}

if (viteConfig.command === 'build') {
const fileName = basename(src.pathname, extname(src.pathname)) + `.${outputMetadata.format}`
if (!this.meta.watchMode) {
const fileName = basename(src.pathname, extname(src.pathname)) + `.${metadata.format}`

const fileHandle = this.emitFile({
name: fileName,
source: outputData,
source: await image.toBuffer(),
type: 'asset'
})

outputMetadata.src = `__VITE_IMAGE_ASSET__${fileHandle}__`
} else if (pluginOptions.cache) {
outputMetadata.src = relative(viteConfig.root,join(pluginOptions.cache, cacheId))
metadata.src = `__VITE_IMAGE_ASSET__${fileHandle}__`
} else {
metadata.src = join('/@vite-imagetools', id)
}

generatedImages.push(outputMetadata)
outputMetadatas.push(metadata)
}

let outputFormat: OutputFormat = urlFormat

for (const [key,format] of Object.entries(OutputFormats)) {
if(src.searchParams.has(key)) {
for (const [key, format] of Object.entries(outputFormats)) {
if (src.searchParams.has(key)) {
outputFormat = format
break
}
}

return dataToEsm(outputFormat(generatedImages))
return dataToEsm(outputFormat(outputMetadatas))
},

configureServer(server) {
server.middlewares.use((req, res, next) => {
if (req.url?.startsWith('/@vite-imagetools/')) {
const [, id] = req.url.split('/@vite-imagetools/')

const image = generatedImages.get(id)

res.setHeader('Content-Type', `image/${getMetadata(image, 'format')}`)
res.setHeader('Cache-Control', 'max-age=360000')
return image.clone().pipe(res)
}

next()
})
},

renderChunk(code) {
Expand Down

0 comments on commit e8e11cf

Please sign in to comment.