grind-assets
Version:
Asset management for Grind
132 lines (106 loc) • 3.12 kB
JavaScript
import './Stage'
import '../../Errors/makeSyntaxError'
import '../../Support/optional'
const rollup = optional('rollup', '>=1.0.0')
const rollupBabel = optional('@rollup/plugin-babel', '>=5.1.0')
export class RollupStage extends Stage {
static configName = 'rollup'
plugins = []
options = null
output = null
constructor(app, sourceMaps, { enabled = false, output = {}, plugins = {}, ...options } = {}) {
super(app, sourceMaps)
this.options = options
this.output = output
this.enabled = enabled
if (plugins['@rollup/plugin-babel'].isNil) {
plugins['@rollup/plugin-babel'] = true
}
for (const [plugin, config] of Object.entries(plugins)) {
if (config === false) {
continue
}
if (plugin === '@rollup/plugin-babel') {
if (!config.isNil && typeof config.root === 'string') {
config.root = this.app.paths.base(config.root)
}
this.plugins.push([rollupBabel, config])
} else if (plugin[0] === '~') {
const name = `Rollup${plugin[1].toUpperCase()}${plugin.substring(2)}Plugin`
this.plugins.push([
require(`../../Rollup/${name}`)[name],
{
grind: app,
req: true,
...(!config.isNil && typeof config === 'object' ? config : {}),
},
])
} else {
if (plugin === '@rollup/plugin-replace' && config['process.env.NODE_ENV'].isNil) {
config['process.env.NODE_ENV'] = JSON.stringify(
process.env.ROLLUP_ENV || process.env.BABEL_ENV || process.env.NODE_ENV,
)
}
this.plugins.push([optional(plugin), config])
}
}
}
async compile(pathname, stream = null, req = null) {
rollup.assert()
if (this.handleBabel) {
rollupBabel.assert()
}
if (!stream.isNil) {
throw new Error('Preprocessed stream not supported')
}
const plugins = []
for (const [plugin, config] of this.plugins) {
if (plugin.name === '@rollup/plugin-babel' && !this.handleBabel) {
continue
}
plugin.assert()
if (!plugin.pkg) {
continue
}
if (!config.isNil && typeof config === 'object') {
if (config.req === true) {
config.req = req
}
}
plugins.push(plugin.pkg(config || {}))
}
try {
const bundle = await rollup.pkg.rollup({
...this.options,
input: pathname,
plugins,
})
const { output } = await bundle.generate({
format: 'cjs',
sourcemap: this.sourceMaps === 'auto',
...this.output,
})
if (!Array.isArray(output) || output.length !== 1 || output[0].isEntry !== true) {
throw new Error('Unsupported file')
}
const [{ map, code }] = output
const inlineMap = !map.isNil ? `\n//# sourceMappingURL=${map.toUrl()}\n` : null
return `${code}${inlineMap || ''}`
} catch (err) {
if (!(err instanceof SyntaxError)) {
throw err
}
let message = err.message
message = err.message.split(/\n/)[0]
message = message.substring(message.indexOf(':') + 1).trim()
const loc = err.loc || {}
throw await makeSyntaxError(this.app, {
message,
fileName: err.id || loc.file || loc.fileName || pathname,
lineNumber: loc.line,
columnNumber: loc.column,
causedBy: err,
})
}
}
}