CtrlK
CommunityDocumentationLog inGet started
Tessl Logo

tessl/npm-tailwindcss--node

Node.js-specific utilities and runtime functionality for Tailwind CSS v4, providing compilation tools, module dependency analysis, source map handling, path normalization, and optimization utilities.

43%

Overall

Evaluation43%

1.16x

Agent success when using this tile

Overview
Eval results
Files

url-processing.mddocs/

URL Processing

CSS URL rewriting functionality for asset path management and relative URL transformation in build processes. Handles url() functions and image-set() properties with comprehensive path resolution and rewriting.

Capabilities

Rewrite URLs Function

Rewrites URLs in CSS for proper relative path handling during build processes.

/**
 * Rewrites URLs in CSS for proper relative path handling
 * Handles url() and image-set() CSS functions with path transformation
 * @param options - Configuration for URL rewriting
 * @returns Promise resolving to CSS with rewritten URLs
 */
function rewriteUrls(options: {
  /** CSS string containing URLs to rewrite */
  css: string;
  /** Base directory of the CSS file being processed */
  base: string;
  /** Root directory for the project (target for relative paths) */
  root: string;
}): Promise<string>;

Usage Examples:

import { rewriteUrls } from "@tailwindcss/node";

// Basic URL rewriting
const css = `
  .hero {
    background-image: url('./images/hero.jpg');
  }
  
  .icon {
    background: url('../assets/icon.svg');
  }
`;

const rewritten = await rewriteUrls({
  css,
  base: '/project/src/styles',      // Directory containing the CSS file
  root: '/project'                  // Project root directory
});

console.log(rewritten);
// Output:
// .hero {
//   background-image: url('./src/styles/images/hero.jpg');
// }
// 
// .icon {
//   background: url('./src/assets/icon.svg');
// }

Image Set Rewriting

Handles CSS image-set() properties with multiple image candidates:

import { rewriteUrls } from "@tailwindcss/node";

const css = `
  .responsive-bg {
    background-image: image-set(
      url('./images/hero-1x.jpg') 1x,
      url('./images/hero-2x.jpg') 2x,
      url('./images/hero-3x.jpg') 3x
    );
  }
`;

const rewritten = await rewriteUrls({
  css,
  base: '/project/src/components',
  root: '/project'
});

console.log(rewritten);
// All URLs in the image-set are rewritten relative to the project root

Build Tool Integration

Common usage in build tools and asset processing:

import { rewriteUrls } from "@tailwindcss/node";
import { compile } from "@tailwindcss/node";
import path from "path";

// Webpack loader example
module.exports = function(source: string) {
  const callback = this.async();
  const resourcePath = this.resourcePath;
  
  const baseDir = path.dirname(resourcePath);
  const rootDir = this.rootContext;
  
  rewriteUrls({
    css: source,
    base: baseDir,
    root: rootDir
  }).then(rewrittenCss => {
    callback(null, rewrittenCss);
  }).catch(callback);
};

// Vite plugin example
export function urlRewritePlugin() {
  return {
    name: 'url-rewrite',
    transform(code: string, id: string) {
      if (id.endsWith('.css')) {
        return rewriteUrls({
          css: code,
          base: path.dirname(id),
          root: process.cwd()
        });
      }
    }
  };
}

Compilation Integration

Use with Tailwind CSS compilation for comprehensive asset handling:

import { compile, rewriteUrls } from "@tailwindcss/node";

async function compileWithUrlRewriting(css: string, options: {
  base: string;
  shouldRewriteUrls?: boolean;
}) {
  // First compile with Tailwind
  const compiler = await compile(css, {
    ...options,
    onDependency: (path) => console.log("Dependency:", path),
    shouldRewriteUrls: true // This enables automatic URL rewriting
  });
  
  const compiled = compiler.build();
  
  // Additional URL rewriting if needed
  if (options.shouldRewriteUrls) {
    return rewriteUrls({
      css: compiled,
      base: options.base,
      root: process.cwd()
    });
  }
  
  return compiled;
}

const result = await compileWithUrlRewriting(`
  @tailwind base;
  
  .custom {
    background: url('./assets/bg.jpg');
  }
`, {
  base: '/project/src/styles',
  shouldRewriteUrls: true
});

URL Processing Behavior

Supported URL Types

The URL rewriter processes these CSS functions:

/* Standard url() functions */
.class1 { background: url('./image.jpg'); }
.class2 { background: url("../assets/icon.svg"); }
.class3 { background: url(./fonts/font.woff2); }

/* Image-set functions */
.responsive {
  background-image: image-set(
    url('./img-1x.jpg') 1x,
    url('./img-2x.jpg') 2x
  );
}

/* Complex image-set with mixed formats */
.modern {
  background-image: image-set(
    url('./image.avif') type('image/avif'),
    url('./image.webp') type('image/webp'),
    url('./image.jpg') type('image/jpeg')
  );
}

Skipped URLs

These URL types are not processed:

/* External URLs */
.external { background: url('https://example.com/image.jpg'); }
.protocol { background: url('//cdn.example.com/icon.svg'); }

/* Data URLs */
.data { background: url('data:image/svg+xml;base64,PHN2Zz48L3N2Zz4='); }

/* Absolute paths */
.absolute { background: url('/static/image.jpg'); }

/* CSS functions */
.gradient { background: linear-gradient(to right, red, blue); }
.element { background: element(#myElement); }

/* Dynamic URLs */
.dynamic { background: url(var(--image-url)); }
.function { background: url(DYNAMIC_URL('./path')); }

Path Resolution Logic

The rewriting process transforms paths as follows:

// Given:
// base: '/project/src/styles'
// root: '/project'  
// CSS: url('./images/hero.jpg')

// Step 1: Resolve relative to base
// '/project/src/styles' + './images/hero.jpg' = '/project/src/styles/images/hero.jpg'

// Step 2: Make relative to root  
// path.relative('/project', '/project/src/styles/images/hero.jpg') = 'src/styles/images/hero.jpg'

// Step 3: Ensure relative path prefix
// 'src/styles/images/hero.jpg' -> './src/styles/images/hero.jpg'

Quote Handling

The rewriter preserves and manages quotes appropriately:

/* Input CSS */
.single { background: url('image.jpg'); }
.double { background: url("image.jpg"); }
.none { background: url(image.jpg); }

/* Output CSS (quotes preserved/added as needed) */
.single { background: url('./path/to/image.jpg'); }
.double { background: url("./path/to/image.jpg"); }
.none { background: url(./path/to/image.jpg); }

/* Special characters require quotes */
.spaces { background: url("./path with spaces/image.jpg"); }
.quotes { background: url("./path/image's.jpg"); }

Advanced Usage

Custom Asset Processing

import { rewriteUrls } from "@tailwindcss/node";

// Process CSS with custom asset handling
async function processWithAssets(css: string, assetMap: Map<string, string>) {
  // First rewrite URLs to normalized paths
  const rewritten = await rewriteUrls({
    css,
    base: './src/styles',
    root: './dist'
  });
  
  // Then replace with hashed asset paths
  let processed = rewritten;
  assetMap.forEach((hashedPath, originalPath) => {
    processed = processed.replace(
      new RegExp(`url\\(['"]?${originalPath}['"]?\\)`, 'g'),
      `url('${hashedPath}')`
    );
  });
  
  return processed;
}

// Usage with asset hashing
const assetMap = new Map([
  ['./assets/hero.jpg', './assets/hero.abc123.jpg'],
  ['./fonts/font.woff2', './fonts/font.def456.woff2']
]);

const processed = await processWithAssets(css, assetMap);

Development vs Production

import { rewriteUrls } from "@tailwindcss/node";

async function processUrls(css: string, isDevelopment: boolean) {
  if (isDevelopment) {
    // Development: rewrite for dev server
    return rewriteUrls({
      css,
      base: './src/styles',
      root: './src'
    });
  } else {
    // Production: rewrite for build output
    return rewriteUrls({
      css, 
      base: './src/styles',
      root: './dist'
    });
  }
}

Performance Optimization

import { rewriteUrls } from "@tailwindcss/node";

// Skip processing if no URLs detected
async function optimizedRewrite(css: string, options: Parameters<typeof rewriteUrls>[0]) {
  // Quick check to avoid unnecessary processing
  if (!css.includes('url(') && !css.includes('image-set(')) {
    return css;
  }
  
  return rewriteUrls(options);
}

// Cache processed results
const processedCache = new Map<string, string>();

async function cachedRewrite(css: string, options: Parameters<typeof rewriteUrls>[0]) {
  const cacheKey = `${css}:${options.base}:${options.root}`;
  
  if (processedCache.has(cacheKey)) {
    return processedCache.get(cacheKey)!;
  }
  
  const result = await rewriteUrls(options);
  processedCache.set(cacheKey, result);
  
  return result;
}

Error Handling

The URL rewriter handles errors gracefully:

import { rewriteUrls } from "@tailwindcss/node";

// Malformed CSS is handled gracefully
const malformedCss = `
  .broken { background: url('unclosed-quote.jpg; }
  .valid { background: url('./valid.jpg'); }
`;

const result = await rewriteUrls({
  css: malformedCss,
  base: './src',
  root: './dist'
});

// Valid URLs are processed, malformed ones are left unchanged
console.log(result);

Browser Compatibility

The rewritten CSS maintains compatibility with all modern browsers and build tools that consume CSS with url() and image-set() functions. The output follows standard CSS specifications and works with:

  • All modern browsers (Chrome, Firefox, Safari, Edge)
  • CSS preprocessors (Sass, Less, Stylus)
  • PostCSS and other CSS processing tools
  • Bundlers (Webpack, Vite, Rollup, esbuild)
tessl i tessl/npm-tailwindcss--node@4.1.0

docs

cache-management.md

compilation.md

index.md

instrumentation.md

module-analysis.md

optimization.md

path-utils.md

source-maps.md

url-processing.md

tile.json