From 829a9633235c7280eea86ab525efc6c672767148 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 14 Jul 2026 13:28:45 +0100 Subject: [PATCH] build: adopt isolated declarations --- package.json | 2 +- packages/beasties-webpack-plugin/package.json | 6 +- .../beasties-webpack-plugin/src/index.d.ts | 63 ------------------- packages/beasties-webpack-plugin/src/index.ts | 14 ++--- .../beasties-webpack-plugin/test/helpers.ts | 6 +- .../beasties-webpack-plugin/tsdown.config.mts | 22 ++++++- packages/beasties/src/css.ts | 12 ++-- packages/beasties/src/dom.ts | 4 +- packages/beasties/src/index.ts | 16 ++--- packages/beasties/src/util.ts | 4 +- packages/beasties/tsdown.config.mts | 2 +- .../vite-plugin-beasties/tsdown.config.mts | 2 +- tsconfig.json | 14 ++++- vitest.config.mts | 2 +- 14 files changed, 65 insertions(+), 104 deletions(-) delete mode 100644 packages/beasties-webpack-plugin/src/index.d.ts diff --git a/package.json b/package.json index 18a52f5..007e10e 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "build": "pnpm -r build", "build:main": "pnpm --filter beasties run build", "build:webpack": "pnpm --filter beasties-webpack-plugin run build", - "postinstall": "simple-git-hooks && pnpm -r build", + "postinstall": "simple-git-hooks", "docs": "pnpm -r docs", "lint": "eslint .", "test": "vitest --coverage", diff --git a/packages/beasties-webpack-plugin/package.json b/packages/beasties-webpack-plugin/package.json index 517adf8..55196db 100644 --- a/packages/beasties-webpack-plugin/package.json +++ b/packages/beasties-webpack-plugin/package.json @@ -34,15 +34,13 @@ ], "exports": { ".": { - "types": "./dist/index.d.ts", "import": "./dist/index.mjs", - "require": "./dist/index.cjs", - "default": "./dist/index.mjs" + "require": "./dist/index.cjs" } }, "main": "dist/index.cjs", "module": "dist/index.mjs", - "types": "dist/index.d.ts", + "types": "dist/index.d.cts", "files": [ "dist", "src" diff --git a/packages/beasties-webpack-plugin/src/index.d.ts b/packages/beasties-webpack-plugin/src/index.d.ts deleted file mode 100644 index 384bb4d..0000000 --- a/packages/beasties-webpack-plugin/src/index.d.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { Options } from 'beasties' -import type { Compiler } from 'webpack' -import Beasties from 'beasties' - -/** - * Copyright 2018 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -/** - * Create a Beasties plugin instance with the given options. - * @public - * @param {Options} options Options to control how Beasties inlines CSS. See https://github.com/danielroe/beasties#usage - * @example - * // webpack.config.js - * module.exports = { - * plugins: [ - * new Beasties({ - * // Outputs: - * preload: 'swap', - * - * // Don't inline critical font-face rules, but preload the font URLs: - * preloadFonts: true - * }) - * ] - * } - */ -declare class BeastiesWebpackPlugin extends Beasties { - constructor(options: Options) - /** - * Invoked by Webpack during plugin initialization - */ - apply(compiler: Compiler): void - /** - * Given href, find the corresponding CSS asset - */ - getCssAsset(href: string, style: Node): Promise - /** - * Check if the stylesheet should be inlined - */ - override checkInlineThreshold(link: Node, style: Node, sheet: string): boolean - /** - * Inline the stylesheets from options.additionalStylesheets (assuming it passes `options.filter`) - */ - embedAdditionalStylesheet(document: Document): Promise - /** - * Prune the source CSS files - */ - override pruneSource(style: Node, before: string, sheetInverse: string): boolean -} - -export = BeastiesWebpackPlugin diff --git a/packages/beasties-webpack-plugin/src/index.ts b/packages/beasties-webpack-plugin/src/index.ts index 3fc1208..e6e9d7e 100644 --- a/packages/beasties-webpack-plugin/src/index.ts +++ b/packages/beasties-webpack-plugin/src/index.ts @@ -56,11 +56,11 @@ const DOT_SLASH_RE = /^\.\// * } */ export default class BeastiesWebpackPlugin extends Beasties { - declare compilation: Compilation - declare compiler: Compiler - declare fs: OutputFileSystem - declare logger: Required> - declare options: Options & Required> & { allowRules: Array } + private declare compilation: Compilation + private declare compiler: Compiler + private declare fs: OutputFileSystem + private declare logger: Required> + private declare options: Options & Required> & { allowRules: Array } constructor(options: Options) { super(options) } @@ -68,7 +68,7 @@ export default class BeastiesWebpackPlugin extends Beasties { /** * Invoked by Webpack during plugin initialization */ - apply(compiler: Compiler) { + apply(compiler: Compiler): void { this.compiler = compiler this.logger = Object.assign(compiler.getInfrastructureLogger(PLUGIN_NAME), { silent(_: string): void { }, @@ -237,7 +237,7 @@ export default class BeastiesWebpackPlugin extends Beasties { /** * Inline the stylesheets from options.additionalStylesheets (assuming it passes `options.filter`) */ - async embedAdditionalStylesheet(document: Document) { + async embedAdditionalStylesheet(document: Document): Promise { const styleSheetsIncluded: string[] = []; (this.options.additionalStylesheets || []).forEach((cssFile: string) => { if (styleSheetsIncluded.includes(cssFile)) { diff --git a/packages/beasties-webpack-plugin/test/helpers.ts b/packages/beasties-webpack-plugin/test/helpers.ts index 9f20405..cda368a 100644 --- a/packages/beasties-webpack-plugin/test/helpers.ts +++ b/packages/beasties-webpack-plugin/test/helpers.ts @@ -36,12 +36,12 @@ function parseDom(html: string) { } // returns a promise resolving to the contents of a file -export function readFile(file: string) { +export function readFile(file: string): Promise { return promisify(fs.readFile)(path.resolve(cwd, file), 'utf-8') } // invoke webpack on a given entry module, optionally mutating the default configuration -export function compile(entry: string, configDecorator: (config: webpack.Configuration) => webpack.Configuration | void) { +export function compile(entry: string, configDecorator: (config: webpack.Configuration) => webpack.Configuration | void): Promise { return new Promise((resolve, reject) => { const context = path.dirname(path.resolve(cwd, entry)) entry = path.basename(entry) @@ -82,7 +82,7 @@ export async function compileToHtml( fixture: string, configDecorator: (config: webpack.Configuration) => webpack.Configuration | void, beastiesOptions: Options = {}, -) { +): Promise { const info = await compile(`fixtures/${fixture}/index.js`, (config) => { config = configDecorator(config) || config config.plugins!.push( diff --git a/packages/beasties-webpack-plugin/tsdown.config.mts b/packages/beasties-webpack-plugin/tsdown.config.mts index 8f59011..54054c3 100644 --- a/packages/beasties-webpack-plugin/tsdown.config.mts +++ b/packages/beasties-webpack-plugin/tsdown.config.mts @@ -1,9 +1,25 @@ import { defineConfig } from 'tsdown' +const license = `/** + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */` + export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], - dts: false, + dts: true, deps: { neverBundle: ['webpack'] }, - copy: [{ from: 'src/index.d.ts', to: 'dist' }], -}) + banner: { js: license, dts: license }, +}) as ReturnType diff --git a/packages/beasties/src/css.ts b/packages/beasties/src/css.ts index 0523daf..df22d39 100644 --- a/packages/beasties/src/css.ts +++ b/packages/beasties/src/css.ts @@ -27,7 +27,7 @@ import safeParser from 'postcss-safe-parser' * @see https://github.com/postcss/postcss/ * @private */ -export function parseStylesheet(stylesheet: string, options?: { safeParser?: boolean }) { +export function parseStylesheet(stylesheet: string, options?: { safeParser?: boolean }): Root_ { if (options?.safeParser) { return safeParser(stylesheet) } @@ -47,7 +47,7 @@ interface SerializeStylesheetOptions { * @private * @param ast A Stylesheet to serialize, such as one returned from `parseStylesheet()` */ -export function serializeStylesheet(ast: AnyNode, options: SerializeStylesheetOptions) { +export function serializeStylesheet(ast: AnyNode, options: SerializeStylesheetOptions): string { const cssParts: string[] = [] stringify(ast, (result, node, type) => { @@ -137,7 +137,7 @@ export function markOnly(predicate: SingleIterator): (rule: R * @private * @param rule The Rule to apply marked selectors to (if they exist). */ -export function applyMarkedSelectors(rule: Rule) { +export function applyMarkedSelectors(rule: Rule): void { if (rule.$$markedSelectors) { rule.selectors = rule.$$markedSelectors } @@ -152,7 +152,7 @@ export function applyMarkedSelectors(rule: Rule) { * @param node A Stylesheet or Rule to descend into. * @param iterator Invoked on each node in the tree. Return `false` to remove that node. */ -export function walkStyleRules(node: ChildNode | Root_, iterator: SingleIterator) { +export function walkStyleRules(node: ChildNode | Root_, iterator: SingleIterator): void { if (!('nodes' in node)) { return } @@ -173,7 +173,7 @@ export function walkStyleRules(node: ChildNode | Root_, iterator: SingleIterator * @param node2 A second tree identical to `node` * @param iterator Invoked on each node in the tree. Return `false` to remove that node from the first tree, true to remove it from the second. */ -export function walkStyleRulesWithReverseMirror(node: Rule | Root_, node2: Rule | Root_ | undefined | null, iterator: SingleIterator) { +export function walkStyleRulesWithReverseMirror(node: Rule | Root_, node2: Rule | Root_ | undefined | null, iterator: SingleIterator): void { if (!node2) return walkStyleRules(node, iterator); @@ -245,7 +245,7 @@ function splitFilter(a: T[], b: T[] | undefined, predicate: SplitIterator) } // can be invoked on a style rule to subset its selectors (with reverse mirroring) -function filterSelectors(this: Rule, predicate: SplitIterator) { +function filterSelectors(this: Rule, predicate: SplitIterator): void { if (this._other) { const [a, b] = splitFilter( this.selectors, diff --git a/packages/beasties/src/dom.ts b/packages/beasties/src/dom.ts index 392fe02..df1433a 100644 --- a/packages/beasties/src/dom.ts +++ b/packages/beasties/src/dom.ts @@ -57,7 +57,7 @@ function buildCache(container: Node) { * The DOM implementation is an htmlparser2 DOM enhanced with basic DOM mutation methods. * @param html HTML to parse into a Document instance */ -export function createDocument(html: string) { +export function createDocument(html: string): HTMLDocument { const document = parseDocument(html, { decodeEntities: false }) extendDocument(document) @@ -84,7 +84,7 @@ export function createDocument(html: string) { /** * Serialize a Document to an HTML String */ -export function serializeDocument(document: HTMLDocument) { +export function serializeDocument(document: HTMLDocument): string { return render(document, { decodeEntities: false }) } diff --git a/packages/beasties/src/index.ts b/packages/beasties/src/index.ts index e85bcb8..2760689 100644 --- a/packages/beasties/src/index.ts +++ b/packages/beasties/src/index.ts @@ -113,7 +113,7 @@ export default class Beasties { /** * Apply critical CSS processing to the html */ - async process(html: string) { + async process(html: string): Promise { const start = Date.now() // Parse the generated HTML in a DOM we can mutate @@ -169,7 +169,7 @@ export default class Beasties { /** * Get the style tags that need processing */ - getAffectedStyleTags(document: HTMLDocument) { + getAffectedStyleTags(document: HTMLDocument): Node[] { const styles = [...document.querySelectorAll('style')] // `inline:false` skips processing of inline stylesheets @@ -179,7 +179,7 @@ export default class Beasties { return styles } - mergeStylesheets(document: HTMLDocument) { + mergeStylesheets(document: HTMLDocument): void { const styles = this.getAffectedStyleTags(document) if (styles.length === 0) { this.logger.warn?.( @@ -260,7 +260,7 @@ export default class Beasties { return sheet } - checkInlineThreshold(link: Node, style: Node, sheet: string) { + checkInlineThreshold(link: Node, style: Node, sheet: string): boolean { if (this.options.inlineThreshold && sheet.length < this.options.inlineThreshold) { const href = style.$$name style.$$reduce = false @@ -277,7 +277,7 @@ export default class Beasties { /** * Inline the stylesheets from options.additionalStylesheets (assuming it passes `options.filter`) */ - async embedAdditionalStylesheet(document: HTMLDocument) { + async embedAdditionalStylesheet(document: HTMLDocument): Promise { const styleSheetsIncluded: string[] = [] const sources = await Promise.all( @@ -450,7 +450,7 @@ export default class Beasties { /** * Inline the target stylesheet referred to by a (assuming it passes `options.filter`) */ - async embedLinkedStylesheet(link: ChildNode, document: HTMLDocument) { + async embedLinkedStylesheet(link: ChildNode, document: HTMLDocument): Promise { const sheet = await this.fetchStylesheet(link, document) if (sheet) { this.embedFetchedStylesheet(sheet, document) @@ -460,7 +460,7 @@ export default class Beasties { /** * Prune the source CSS files */ - pruneSource(style: Node, before: string, sheetInverse: string) { + pruneSource(style: Node, before: string, sheetInverse: string): boolean { // if external stylesheet would be below minimum size, just inline everything const minSize = this.options.minimumExternalSize const name = style.$$name @@ -487,7 +487,7 @@ export default class Beasties { /** * Parse the stylesheet within a