PostCSS plugin that normalizes CSS @charset declarations by ensuring only a single charset rule exists and is positioned at the top of the document
npx @tessl/cli install tessl/npm-postcss-normalize-charset@6.0.0postcss-normalize-charset is a PostCSS plugin that normalizes CSS @charset declarations by ensuring only a single charset rule exists and is positioned at the top of the document. It prevents issues that can occur when concatenating CSS files with multiple or misplaced charset declarations, and can automatically add UTF-8 charset declarations when non-ASCII characters are detected.
npm install postcss-normalize-charsetconst postcssNormalizeCharset = require("postcss-normalize-charset");Note: This package uses CommonJS exports only. For ES modules, use dynamic import:
const postcssNormalizeCharset = await import("postcss-normalize-charset");
// Use postcssNormalizeCharset.defaultconst postcss = require("postcss");
const postcssNormalizeCharset = require("postcss-normalize-charset");
// Basic usage with default options
const result = await postcss([postcssNormalizeCharset()])
.process('a{content:"©"}', { from: undefined });
console.log(result.css);
// Output: @charset "utf-8";\na{content:"©"}
// Usage with options
const result2 = await postcss([postcssNormalizeCharset({ add: false })])
.process('a{content:"©"}', { from: undefined });
console.log(result2.css);
// Output: a{content:"©"} (no charset added)The main export creates a PostCSS plugin instance with optional configuration.
/**
* Creates a PostCSS plugin that normalizes CSS @charset declarations
* @param {Options} opts - Configuration options for the plugin
* @returns {Plugin} PostCSS plugin instance
*/
function postcssNormalizeCharset(opts?: Options): Plugin;
/**
* PostCSS plugin marker - indicates this function is a PostCSS plugin
* This property is used by PostCSS to identify the function as a plugin
*/
postcssNormalizeCharset.postcss = true;Parameters:
opts (optional): Configuration options objectReturns: PostCSS plugin instance that can be passed to PostCSS
Plugin Behavior:
@charset "utf-8" (unless add: false)The plugin accepts an optional configuration object with the following properties:
add (boolean, optional): Controls whether the plugin automatically adds @charset "utf-8" when non-ASCII characters are detected in CSS that doesn't already have a charset declaration. Defaults to true.const postcss = require("postcss");
const postcssNormalizeCharset = require("postcss-normalize-charset");
// CSS with non-ASCII characters but no charset
const css = 'a{content:"©"}';
const result = await postcss([postcssNormalizeCharset()])
.process(css, { from: undefined });
console.log(result.css);
// Output: @charset "utf-8";\na{content:"©"}const postcss = require("postcss");
const postcssNormalizeCharset = require("postcss-normalize-charset");
// CSS with non-ASCII characters, but prevent charset addition
const css = 'a{content:"©"}';
const result = await postcss([postcssNormalizeCharset({ add: false })])
.process(css, { from: undefined });
console.log(result.css);
// Output: a{content:"©"} (no charset added)const postcss = require("postcss");
const postcssNormalizeCharset = require("postcss-normalize-charset");
// CSS with multiple charset declarations
const css = 'a{content:"©"}@charset "utf-8";@charset "windows-1251";';
const result = await postcss([postcssNormalizeCharset()])
.process(css, { from: undefined });
console.log(result.css);
// Output: @charset "utf-8";\na{content:"©"}const postcss = require("postcss");
const postcssNormalizeCharset = require("postcss-normalize-charset");
// CSS with charset rule in wrong position
const css = 'b{жизнь:калька}@charset "windows-1251";a{content:"©"}';
const result = await postcss([postcssNormalizeCharset()])
.process(css, { from: undefined });
console.log(result.css);
// Output: @charset "windows-1251";b{жизнь:калька}a{content:"©"}const postcss = require("postcss");
const postcssNormalizeCharset = require("postcss-normalize-charset");
// CSS with charset but no non-ASCII characters
const css = 'a{content:"c"}@charset "utf-8";@charset "windows-1251";';
const result = await postcss([postcssNormalizeCharset()])
.process(css, { from: undefined });
console.log(result.css);
// Output: a{content:"c"} (charset rules removed since no non-ASCII chars)/**
* Configuration options for postcss-normalize-charset
*/
interface Options {
/**
* Whether to automatically add @charset "utf-8" when non-ASCII characters are detected
* @default true
*/
add?: boolean;
}
/**
* PostCSS plugin instance interface
*/
interface Plugin {
/** The name identifier for this PostCSS plugin */
postcssPlugin: string;
/** Hook that runs once after all other processing is complete */
OnceExit(css: Root, helpers: { AtRule: AtRuleConstructor }): void;
}
/**
* PostCSS CSS root node representing the entire stylesheet
*/
interface Root {
/** Walk through all nodes in the CSS tree */
walk(callback: (node: Node) => void): void;
/** Add a node to the beginning of the root */
prepend(node: Node): void;
/** The first child node */
first?: Node;
/** The parent node (null for root) */
parent: null;
}
/**
* Base PostCSS node interface
*/
interface Node {
/** The type of node (e.g., 'atrule', 'rule', 'decl') */
type: string;
/** The parent node containing this node */
parent?: Node;
/** Convert the node to a CSS string */
toString(): string;
/** Remove this node from its parent */
remove(): void;
/** Source location information */
source?: {
input: { css: string };
start: { column: number; line: number };
end: { column: number; line: number };
};
}
/**
* PostCSS at-rule node (like @charset, @media, etc.)
*/
interface AtRule extends Node {
/** The at-rule name (without @) */
name: string;
/** The at-rule parameters */
params: string;
}
/**
* PostCSS AtRule constructor for creating @charset rules
*/
interface AtRuleConstructor {
new(props: { name: string; params: string; source?: any }): AtRule;
}