Skip to content

Commit

Permalink
Add unicorn plugin (#4666)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Oct 12, 2022
1 parent 4fdf8bd commit 3cb7f13
Show file tree
Hide file tree
Showing 674 changed files with 3,313 additions and 2,526 deletions.
21 changes: 18 additions & 3 deletions .eslintrc.js
Expand Up @@ -10,7 +10,8 @@ module.exports = {
'prettier',
'plugin:prettier/recommended',
'plugin:import/recommended',
'plugin:import/typescript'
'plugin:import/typescript',
'plugin:unicorn/recommended'
],
ignorePatterns: [
'node_modules',
Expand All @@ -26,7 +27,9 @@ module.exports = {
{
files: ['*.js'],
rules: {
'@typescript-eslint/explicit-module-boundary-types': 'off'
'@typescript-eslint/explicit-module-boundary-types': 'off',
'unicorn/no-process-exit': 'off',
'unicorn/prefer-module': 'off'
}
},
{
Expand Down Expand Up @@ -94,6 +97,18 @@ module.exports = {
ignoreMemberSort: false
}
],
'sort-keys': ['error', 'asc', { caseSensitive: false }]
'sort-keys': ['error', 'asc', { caseSensitive: false }],
'unicorn/filename-case': 'off',
'unicorn/no-array-callback-reference': 'off',
'unicorn/no-array-reduce': 'off',
'unicorn/no-await-expression-member': 'off',
'unicorn/no-nested-ternary': 'off',
'unicorn/no-null': 'off',
'unicorn/no-this-assignment': 'off',
'unicorn/no-useless-undefined': 'off',
'unicorn/prefer-code-point': 'off',
'unicorn/prefer-math-trunc': 'off',
'unicorn/prefer-number-properties': 'off',
'unicorn/prefer-top-level-await': 'off'
}
};
4 changes: 2 additions & 2 deletions browser/src/error.ts
@@ -1,4 +1,4 @@
import { errNoFileSystemInBrowser, error } from '../../src/utils/error';
import { error, errorNoFileSystemInBrowser } from '../../src/utils/error';

export const throwNoFileSystem = (method: string) => (): never =>
error(errNoFileSystemInBrowser(method));
error(errorNoFileSystemInBrowser(method));
8 changes: 4 additions & 4 deletions browser/src/path.ts
@@ -1,4 +1,4 @@
const ABSOLUTE_PATH_REGEX = /^(?:\/|(?:[A-Za-z]:)?[\\|/])/;
const ABSOLUTE_PATH_REGEX = /^(?:\/|(?:[A-Za-z]:)?[/\\|])/;
const RELATIVE_PATH_REGEX = /^\.?\.\//;
const ALL_BACKSLASHES_REGEX = /\\/g;
const ANY_SLASH_REGEX = /[/\\]/;
Expand All @@ -24,10 +24,10 @@ export function dirname(path: string): string {
const match = /[/\\][^/\\]*$/.exec(path);
if (!match) return '.';

const dir = path.slice(0, -match[0].length);
const directory = path.slice(0, -match[0].length);

// If `dir` is the empty string, we're at root.
return dir ? dir : '/';
// If `directory` is the empty string, we're at root.
return directory || '/';
}

export function extname(path: string): string {
Expand Down
4 changes: 2 additions & 2 deletions build-plugins/clean-before-write.ts
@@ -1,13 +1,13 @@
import fs from 'fs-extra';
import type { Plugin } from 'rollup';

export default function cleanBeforeWrite(dir: string): Plugin {
export default function cleanBeforeWrite(directory: string): Plugin {
let removePromise: Promise<void> | null = null;
return {
generateBundle(_options, _bundle, isWrite) {
if (isWrite) {
// Only remove before first write, but make all writes wait on the removal
removePromise ||= fs.remove(dir);
removePromise ||= fs.remove(directory);
return removePromise;
}
},
Expand Down
16 changes: 8 additions & 8 deletions build-plugins/generate-license-file.ts
Expand Up @@ -4,12 +4,12 @@ import type { PluginImpl } from 'rollup';
import license, { type Dependency, type Person } from 'rollup-plugin-license';

async function generateLicenseFile(
dir: string,
directory: string,
dependencies: readonly Dependency[]
): Promise<void> {
const coreLicense = await fs.readFile('LICENSE-CORE.md', 'utf8');
const licenses = new Set<string>();
const dependencyLicenseTexts = Array.from(dependencies)
const dependencyLicenseTexts = [...dependencies]
.filter(({ name }) => name !== '@rollup/browser')
.sort(({ name: nameA }, { name: nameB }) => (nameA! > nameB! ? 1 : -1))
.map(({ name, license, licenseText, author, maintainers, contributors, repository }) => {
Expand All @@ -22,13 +22,13 @@ async function generateLicenseFile(
names.add(author.name);
}
// TODO there is an inconsistency in the rollup-plugin-license types
for (const person of contributors.concat(maintainers as unknown as Person[])) {
for (const person of [...contributors, ...(maintainers as unknown as Person[])]) {
if (person?.name) {
names.add(person.name);
}
}
if (names.size > 0) {
text += `By: ${Array.from(names).join(', ')}\n`;
text += `By: ${[...names].join(', ')}\n`;
}
if (repository) {
text += `Repository: ${(typeof repository === 'object' && repository.url) || repository}\n`;
Expand All @@ -54,10 +54,10 @@ async function generateLicenseFile(
coreLicense +
`\n# Licenses of bundled dependencies\n` +
`The published Rollup artifact additionally contains code with the following licenses:\n` +
`${Array.from(licenses).join(', ')}\n\n` +
`${[...licenses].join(', ')}\n\n` +
`# Bundled dependencies:\n` +
dependencyLicenseTexts;
const licenseFile = join(dir, 'LICENSE.md');
const licenseFile = join(directory, 'LICENSE.md');
const existingLicenseText = await fs.readFile(licenseFile, 'utf8');
if (existingLicenseText !== licenseText) {
await fs.writeFile(licenseFile, licenseText);
Expand All @@ -70,7 +70,7 @@ interface LicenseHandler {
writeLicense: PluginImpl;
}

export default function getLicenseHandler(dir: string): LicenseHandler {
export default function getLicenseHandler(directory: string): LicenseHandler {
const licenses = new Map<string, Dependency>();
function addLicenses(dependencies: readonly Dependency[]) {
for (const dependency of dependencies) {
Expand All @@ -85,7 +85,7 @@ export default function getLicenseHandler(dir: string): LicenseHandler {
return {
name: 'write-license',
writeBundle() {
return generateLicenseFile(dir, Array.from(licenses.values()));
return generateLicenseFile(directory, [...licenses.values()]);
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion build-plugins/get-banner.ts
Expand Up @@ -27,5 +27,5 @@ export default async function getBanner(): Promise<string> {
return (getBannerPromise ||= Promise.all([
execPromise('git rev-parse HEAD'),
fs.readFile(new URL('../package.json', import.meta.url), 'utf8')
]).then(([{ stdout }, pkg]) => generateBanner(stdout.trim(), JSON.parse(pkg).version)));
]).then(([{ stdout }, package_]) => generateBanner(stdout.trim(), JSON.parse(package_).version)));
}
1 change: 1 addition & 0 deletions cli/cli.ts
Expand Up @@ -16,6 +16,7 @@ if (command.help || (process.argv.length <= 2 && process.stdin.isTTY)) {
console.log(`rollup v${version}`);
} else {
try {
// eslint-disable-next-line unicorn/prefer-module
require('source-map-support').install();
} catch {
// do nothing
Expand Down
32 changes: 17 additions & 15 deletions cli/logging.ts
Expand Up @@ -4,35 +4,37 @@ import { bold, cyan, dim, red } from '../src/utils/colors';
import relativeId from '../src/utils/relativeId';

// log to stderr to keep `rollup main.js > bundle.js` from breaking
export const stderr = (...args: readonly unknown[]) => process.stderr.write(`${args.join('')}\n`);
export const stderr = (...parameters: readonly unknown[]) =>
process.stderr.write(`${parameters.join('')}\n`);

export function handleError(err: RollupError, recover = false): void {
const name = err.name || err.cause?.name;
export function handleError(error: RollupError, recover = false): void {
const name = error.name || error.cause?.name;
const nameSection = name ? `${name}: ` : '';
const pluginSection = err.plugin ? `(plugin ${err.plugin}) ` : '';
const message = `${pluginSection}${nameSection}${err.message}`;
const pluginSection = error.plugin ? `(plugin ${error.plugin}) ` : '';
const message = `${pluginSection}${nameSection}${error.message}`;

stderr(bold(red(`[!] ${bold(message.toString())}`)));

if (err.url) {
stderr(cyan(err.url));
if (error.url) {
stderr(cyan(error.url));
}

if (err.loc) {
stderr(`${relativeId((err.loc.file || err.id)!)} (${err.loc.line}:${err.loc.column})`);
} else if (err.id) {
stderr(relativeId(err.id));
if (error.loc) {
stderr(`${relativeId((error.loc.file || error.id)!)} (${error.loc.line}:${error.loc.column})`);
} else if (error.id) {
stderr(relativeId(error.id));
}

if (err.frame) {
stderr(dim(err.frame));
if (error.frame) {
stderr(dim(error.frame));
}

if (err.stack) {
stderr(dim(err.stack));
if (error.stack) {
stderr(dim(error.stack));
}

stderr('');

// eslint-disable-next-line unicorn/no-process-exit
if (!recover) process.exit(1);
}
10 changes: 5 additions & 5 deletions cli/run/batchWarnings.ts
Expand Up @@ -51,7 +51,7 @@ export default function batchWarnings(): BatchWarnings {
flush() {
if (count === 0) return;

const codes = Array.from(deferredWarnings.keys()).sort(
const codes = [...deferredWarnings.keys()].sort(
(a, b) => deferredWarnings.get(b)!.length - deferredWarnings.get(a)!.length
);

Expand Down Expand Up @@ -245,8 +245,8 @@ const deferredHandlers: {
}
};

function title(str: string): void {
stderr(bold(yellow(`(!) ${str}`)));
function title(string_: string): void {
stderr(bold(yellow(`(!) ${string_}`)));
}

function info(url: string): void {
Expand All @@ -258,12 +258,12 @@ interface Nested<T> {
key: string;
}

function nest<T extends Record<string, any>>(array: readonly T[], prop: string): Nested<T>[] {
function nest<T extends Record<string, any>>(array: readonly T[], property: string): Nested<T>[] {
const nested: Nested<T>[] = [];
const lookup = new Map<string, Nested<T>>();

for (const item of array) {
const key = item[prop];
const key = item[property];
getOrCreate(lookup, key, () => {
const items = {
items: [],
Expand Down
6 changes: 3 additions & 3 deletions cli/run/build.ts
Expand Up @@ -3,7 +3,7 @@ import ms from 'pretty-ms';
import { rollup } from '../../src/node-entry';
import type { MergedRollupOptions } from '../../src/rollup/types';
import { bold, cyan, green } from '../../src/utils/colors';
import { errOnlyInlineSourcemapsForStdout } from '../../src/utils/error';
import { errorOnlyInlineSourcemapsForStdout } from '../../src/utils/error';
import relativeId from '../../src/utils/relativeId';
import { handleError, stderr } from '../logging';
import type { BatchWarnings } from './batchWarnings';
Expand All @@ -22,7 +22,7 @@ export default async function build(
let inputFiles: string | undefined;
if (typeof inputOptions.input === 'string') {
inputFiles = inputOptions.input;
} else if (inputOptions.input instanceof Array) {
} else if (Array.isArray(inputOptions.input)) {
inputFiles = inputOptions.input.join(', ');
} else if (typeof inputOptions.input === 'object' && inputOptions.input !== null) {
inputFiles = Object.values(inputOptions.input).join(', ');
Expand All @@ -34,7 +34,7 @@ export default async function build(
if (useStdout) {
const output = outputOptions[0];
if (output.sourcemap && output.sourcemap !== 'inline') {
handleError(errOnlyInlineSourcemapsForStdout());
handleError(errorOnlyInlineSourcemapsForStdout());
}
const { output: outputs } = await bundle.generate(output);
for (const file of outputs) {
Expand Down
21 changes: 12 additions & 9 deletions cli/run/commandPlugins.ts
Expand Up @@ -45,21 +45,21 @@ async function loadAndRegisterPlugin(
pluginText: string
): Promise<void> {
let plugin: any = null;
let pluginArg: any = undefined;
let pluginArgument: any = undefined;
if (pluginText[0] === '{') {
// -p "{transform(c,i){...}}"
plugin = new Function('return ' + pluginText);
} else {
const match = pluginText.match(/^([@.:/\\\w|^{}-]+)(=(.*))?$/);
const match = pluginText.match(/^([\w./:@\\^{|}-]+)(=(.*))?$/);
if (match) {
// -p plugin
// -p plugin=arg
pluginText = match[1];
pluginArg = new Function('return ' + match[3])();
pluginArgument = new Function('return ' + match[3])();
} else {
throw new Error(`Invalid --plugin argument format: ${JSON.stringify(pluginText)}`);
}
if (!/^\.|^rollup-plugin-|[@/\\]/.test(pluginText)) {
if (!/^\.|^rollup-plugin-|[/@\\]/.test(pluginText)) {
// Try using plugin prefix variations first if applicable.
// Prefix order is significant - left has higher precedence.
for (const prefix of ['@rollup/plugin-', 'rollup-plugin-']) {
Expand All @@ -76,12 +76,12 @@ async function loadAndRegisterPlugin(
if (pluginText[0] == '.') pluginText = resolve(pluginText);
// Windows absolute paths must be specified as file:// protocol URL
// Note that we do not have coverage for Windows-only code paths
else if (pluginText.match(/^[A-Za-z]:\\/)) {
else if (/^[A-Za-z]:\\/.test(pluginText)) {
pluginText = pathToFileURL(resolve(pluginText)).href;
}
plugin = await requireOrImport(pluginText);
} catch (err: any) {
throw new Error(`Cannot load plugin "${pluginText}": ${err.message}.`);
} catch (error: any) {
throw new Error(`Cannot load plugin "${pluginText}": ${error.message}.`);
}
}
}
Expand All @@ -97,12 +97,14 @@ async function loadAndRegisterPlugin(
)}" for Rollup to recognize it.`
);
}
inputOptions.plugins.push(typeof plugin === 'function' ? plugin.call(plugin, pluginArg) : plugin);
inputOptions.plugins.push(
typeof plugin === 'function' ? plugin.call(plugin, pluginArgument) : plugin
);
}

function getCamelizedPluginBaseName(pluginText: string): string {
return (pluginText.match(/(@rollup\/plugin-|rollup-plugin-)(.+)$/)?.[2] || pluginText)
.split(/[\\/]/)
.split(/[/\\]/)
.slice(-1)[0]
.split('.')[0]
.split('-')
Expand All @@ -112,6 +114,7 @@ function getCamelizedPluginBaseName(pluginText: string): string {

async function requireOrImport(pluginPath: string): Promise<any> {
try {
// eslint-disable-next-line unicorn/prefer-module
return require(pluginPath);
} catch {
return import(pluginPath);
Expand Down
22 changes: 12 additions & 10 deletions cli/run/getConfigPath.ts
@@ -1,7 +1,7 @@
import { promises as fs } from 'node:fs';
import { resolve } from 'node:path';
import { cwd } from 'node:process';
import { errMissingExternalConfig } from '../../src/utils/error';
import { errorMissingExternalConfig } from '../../src/utils/error';
import { handleError } from '../logging';

const DEFAULT_CONFIG_BASE = 'rollup.config';
Expand All @@ -11,28 +11,30 @@ export async function getConfigPath(commandConfig: string | true): Promise<strin
return resolve(await findConfigFileNameInCwd());
}
if (commandConfig.slice(0, 5) === 'node:') {
const pkgName = commandConfig.slice(5);
const packageName = commandConfig.slice(5);
try {
return require.resolve(`rollup-config-${pkgName}`, { paths: [cwd()] });
// eslint-disable-next-line unicorn/prefer-module
return require.resolve(`rollup-config-${packageName}`, { paths: [cwd()] });
} catch {
try {
return require.resolve(pkgName, { paths: [cwd()] });
} catch (err: any) {
if (err.code === 'MODULE_NOT_FOUND') {
handleError(errMissingExternalConfig(commandConfig));
// eslint-disable-next-line unicorn/prefer-module
return require.resolve(packageName, { paths: [cwd()] });
} catch (error: any) {
if (error.code === 'MODULE_NOT_FOUND') {
handleError(errorMissingExternalConfig(commandConfig));
}
throw err;
throw error;
}
}
}
return resolve(commandConfig);
}

async function findConfigFileNameInCwd(): Promise<string> {
const filesInWorkingDir = new Set(await fs.readdir(cwd()));
const filesInWorkingDirectory = new Set(await fs.readdir(cwd()));
for (const extension of ['mjs', 'cjs', 'ts']) {
const fileName = `${DEFAULT_CONFIG_BASE}.${extension}`;
if (filesInWorkingDir.has(fileName)) return fileName;
if (filesInWorkingDirectory.has(fileName)) return fileName;
}
return `${DEFAULT_CONFIG_BASE}.js`;
}

0 comments on commit 3cb7f13

Please sign in to comment.