Normalize URLs with PostCSS
npx @tessl/cli install tessl/npm-postcss-normalize-url@7.0.0PostCSS Normalize URL is a PostCSS plugin that normalizes URLs within CSS stylesheets. It automatically optimizes URL formats for better compression and standardization by removing unnecessary port numbers, converting absolute URLs to more efficient formats, normalizing relative paths, and intelligently managing quotes around URLs.
npm install postcss-normalize-urlconst postcssNormalizeUrl = require("postcss-normalize-url");ES modules:
import postcssNormalizeUrl from "postcss-normalize-url";const postcss = require("postcss");
const postcssNormalizeUrl = require("postcss-normalize-url");
// Use as PostCSS plugin
const result = await postcss([postcssNormalizeUrl()])
.process("h1 { background: url(\"http://site.com:80/image.jpg\") }", {
from: undefined
});
console.log(result.css);
// Output: h1 { background: url(http://site.com/image.jpg) }Creates a PostCSS plugin instance for URL normalization in CSS.
/**
* Creates a PostCSS plugin that normalizes URLs in CSS
* @returns {Plugin} PostCSS plugin object with postcss property
*/
function postcssNormalizeUrl(): Plugin;
// Plugin properties
postcssNormalizeUrl.postcss = true;The plugin processes CSS and performs the following normalizations:
:80 for HTTP, :443 for HTTPS)../)Processes CSS @namespace rules and normalizes URLs within them.
// Plugin automatically handles @namespace rules
// Input: @namespace url("http://example.com:80/ns");
// Output: @namespace url(http://example.com/ns);The plugin specifically processes:
interface Plugin {
postcssPlugin: 'postcss-normalize-url';
OnceExit(css: Root): void;
}
// Plugin creator function with postcss property
interface PluginCreator {
(): Plugin;
postcss: true;
}
// PostCSS types (from postcss package)
interface Root {
walk(callback: (node: Node) => boolean | void): Root;
}
interface Node {
type: string;
}
interface Declaration extends Node {
type: 'decl';
value: string;
}
interface AtRule extends Node {
type: 'atrule';
name: string;
params: string;
}The plugin includes robust error handling:
chrome-extension://) are preserved unchanged/* Input */
h1 { background: url("http://site.com:80/image.jpg") }
/* Output */
h1 { background: url(http://site.com/image.jpg) }/* Input */
h1 { background: url("simple-image.jpg") }
/* Output */
h1 { background: url(simple-image.jpg) }/* Input */
h1 { background: url("path with spaces.jpg") }
/* Output */
h1 { background: url("path with spaces.jpg") }/* Input */
h1 { background: url("./images/../icons/icon.png") }
/* Output */
h1 { background: url(icons/icon.png) }/* Input */
h1 { background: url("css/../font/t.eot") }
/* Output */
h1 { background: url(font/t.eot) }/* Input */
h1 { background: url(" test.png ") }
/* Output */
h1 { background: url(test.png) }/* Input */
h1 { background: url("some really long string \
spanning multiple lines") }
/* Output */
h1 { background: url("some really long string spanning multiple lines") }/* Input */
h1 { background: url("http://website.com/test.svg#icon") }
/* Output - fragment preserved */
h1 { background: url(http://website.com/test.svg#icon) }/* Input */
h1 { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==") }
/* Output - preserved unchanged */
h1 { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==") }