CodeSampleX

Ejemplo

tailwindcss 4.3.3: Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build instead of invoking default export

Muestra verificada para npm tailwindcss 4.3.3: Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous…

sha256:7e8fea6fcad1e429a66c2ec7cabadab555fed65be50225e20dee895a0a8de843

Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido. Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas. MIT-0

Evidencia de ejecución

El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.

Base de evidencia
Contrato firmado aprobado
Recibos de verificación
3
Claves de firma que lo compilaron
3
Entorno declarado node linux x64 node node npm

Entornos de las ejecuciones de verificación

Entorno Contrato Etapas Ejecución
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-16
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5…
2026-09-08

Caso

HOW
Objetivo
Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build instead of invoking default export
Paquetes
Símbolos
  • tailwindcss
  • compile
  • loadStylesheet
  • loadModule
  • build
  • default
Entorno
node
Creado
2026-08-16T07:54:12Z

Contrato

  1. assert default export throws when invoked as PostCSS plugin directing callers to @tailwindcss/postcss
  2. assert compile rejects when @import is used without providing loadStylesheet
  3. assert compile rejects when @plugin is used without providing loadModule
  4. assert compile returns compiler object with sync build method after resolving stylesheets and plugins
  5. assert compiler.build emits CSS rules matching candidate list and resolves @theme variables and @utility rules
  6. assert compiler.build ignores invalid and unreferenced candidates without error

Archivos

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs

Descargar el artefacto de código fuente (tar.gz)

Código fuente

NOTES.md
# Notes: tailwindcss v4 Programmatic API & Default Export Trap

## search_known_solution Response
`search_known_solution` found sample `sha256:52605f9f976b90b774ec86bcad38e5a02628014fd02d62a8b0b8937afdd907fc` ("Generate CSS with tailwind v4, which replaced tailwind.config.js with CSS-first config" demonstrating `@tailwindcss/postcss` integration with PostCSS). This sample addresses the core `tailwindcss` package's programmatic JS compilation API (`compile`, `loadStylesheet`, `loadModule`, `compiler.build`) and its default export trap.

## What a Model Would Have Written Instead
A model expecting Tailwind CSS v3 conventions reaches for `import tailwindcss from 'tailwindcss'` and invokes it as a PostCSS plugin (`tailwindcss(config)`), or attempts programmatic compilation via `await compile(css)` expecting automatic filesystem resolution or a direct CSS string return value.

## How the Wrong Version Fails
Loudly at runtime: calling the default export throws `Error: It looks like you're trying to use 'tailwindcss' directly as a PostCSS plugin...` because PostCSS integration moved to `@tailwindcss/postcss`, and calling `compile()` with `@import` or `@plugin` without custom `loadStylesheet` / `loadModule` callbacks throws `Error: No 'loadStylesheet' function provided to 'compile'` or `Error: No 'loadModule' function provided to 'compile'` as the v4 compiler is decoupled from filesystem I/O.
csx.json
{"case":{"caseId":"case:sha256:ee1aaf2f33c7f0b23b36e6f947131a3b86bddbd20c8d01a03c0116fb25c96b2a","contract":["assert default export throws when invoked as PostCSS plugin directing callers to @tailwindcss/postcss","assert compile rejects when @import is used without providing loadStylesheet","assert compile rejects when @plugin is used without providing loadModule","assert compile returns compiler object with sync build method after resolving stylesheets and plugins","assert compiler.build emits CSS rules matching candidate list and resolves @theme variables and @utility rules","assert compiler.build ignores invalid and unreferenced candidates without error"],"goal":"Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build instead of invoking default export","kind":"HOW","packages":["pkg:npm/tailwindcss@4.3.3"],"schemaVersion":1,"symbols":["tailwindcss","compile","loadStylesheet","loadModule","build","default"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/tailwindcss@4.3.3"],"schemaVersion":1,"symbols":["tailwindcss","compile","loadStylesheet","loadModule","build","default"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-tailwindcss-api",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-tailwindcss-api",
      "version": "1.0.0",
      "license": "MIT-0",
      "dependencies": {
        "tailwindcss": "4.3.3"
      }
    },
    "node_modules/tailwindcss": {
      "version": "4.3.3",
      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
      "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
      "license": "MIT"
    }
  }
}
package.json
{
  "name": "npm-tailwindcss-api",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "license": "MIT-0",
  "dependencies": {
    "tailwindcss": "4.3.3"
  }
}
test/contract.mjs
import { strict as assert } from 'node:assert';
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import tailwindDefault, { compile } from 'tailwindcss';
import plugin from 'tailwindcss/plugin';

// 1. Assert default export throws when invoked as PostCSS plugin
assert.strictEqual(typeof tailwindDefault, 'function', 'default export should be a function');
assert.throws(
  () => {
    tailwindDefault();
  },
  {
    name: 'Error',
    message: /PostCSS plugin has moved to a separate package.*@tailwindcss\/postcss/,
  },
  'calling tailwindcss default export must throw PostCSS plugin deprecation error'
);

// 2. Assert compile throws when @import is present without loadStylesheet
await assert.rejects(
  async () => {
    await compile('@import "tailwindcss";', { base: process.cwd() });
  },
  {
    name: 'Error',
    message: /No `loadStylesheet` function provided to `compile`/,
  },
  'compile must reject with missing loadStylesheet error when @import is used without loader'
);

// 3. Assert compile throws when @plugin is present without loadModule
const tailwindPkgDir = path.dirname(fileURLToPath(import.meta.resolve('tailwindcss/package.json')));
async function mockLoadStylesheet(id, base) {
  if (id === 'tailwindcss' || id === 'tailwindcss/index.css') {
    const cssPath = path.join(tailwindPkgDir, 'index.css');
    const content = await fs.readFile(cssPath, 'utf8');
    return { path: cssPath, base: tailwindPkgDir, content };
  }
  const resolved = path.resolve(base, id);
  const content = await fs.readFile(resolved, 'utf8');
  return { path: resolved, base: path.dirname(resolved), content };
}

await assert.rejects(
  async () => {
    await compile('@import "tailwindcss";\n@plugin "custom-plugin";', {
      base: process.cwd(),
      loadStylesheet: mockLoadStylesheet,
    });
  },
  {
    name: 'Error',
    message: /No `loadModule` function provided to `compile`/,
  },
  'compile must reject with missing loadModule error when @plugin is used without loader'
);

// 4. Set up custom plugin and compile with both loadStylesheet and loadModule
const customPlugin = plugin(function ({ addUtilities }) {
  addUtilities({
    '.skew-15': {
      transform: 'skewY(15deg)',
    },
  });
});

async function mockLoadModule(id, base, resourceHint) {
  if (id === 'custom-plugin') {
    return {
      path: 'virtual:custom-plugin',
      base,
      module: customPlugin,
    };
  }
  throw new Error(`Unknown module: ${id}`);
}

const inputCss = `
@import "tailwindcss";
@plugin "custom-plugin";
@theme {
  --color-accent: #e11d48;
}
@utility btn-primary {
  background-color: var(--color-accent);
  padding: 0.5rem 1rem;
}
`;

const compiler = await compile(inputCss, {
  base: process.cwd(),
  loadStylesheet: mockLoadStylesheet,
  loadModule: mockLoadModule,
});

// Assert shape of returned compiler object
assert.strictEqual(typeof compiler, 'object', 'compile must resolve to compiler object');
assert.strictEqual(typeof compiler.build, 'function', 'compiler must expose a build function');
assert.ok(Array.isArray(compiler.sources), 'compiler must expose sources array');

// 5. Assert compiler.build generates CSS for requested candidates and custom definitions
const candidates = [
  'btn-primary',
  'skew-15',
  'hover:skew-15',
  'text-accent',
  'p-4',
  'opacity-50',
  'nonexistent-helper-class',
];

const outputCss = compiler.build(candidates);
assert.strictEqual(typeof outputCss, 'string', 'build must return a CSS string synchronously');

// Assert custom utility and theme variables are emitted
assert.ok(outputCss.includes('.btn-primary'), 'emits .btn-primary utility class');
assert.ok(outputCss.includes('--color-accent: #e11d48') || outputCss.includes('#e11d48'), 'emits @theme token definition');
assert.ok(outputCss.includes('var(--color-accent)'), 'btn-primary references theme custom property');

// Assert plugin utility and variant are emitted
assert.ok(outputCss.includes('skewY(15deg)'), 'emits skew-15 transform from JS plugin');
assert.ok(outputCss.includes('.hover\\:skew-15:hover'), 'emits hover variant for plugin utility');

// Assert standard utility classes are emitted
assert.ok(outputCss.includes('.text-accent'), 'emits text-accent color utility');
assert.ok(outputCss.includes('.p-4'), 'emits p-4 padding utility');
assert.ok(outputCss.includes('.opacity-50'), 'emits opacity-50 utility');

// 6. Assert unrequested/unscanned utilities and invalid candidates are NOT emitted
assert.ok(!outputCss.includes('nonexistent-helper-class'), 'ignores invalid candidates');
assert.ok(!outputCss.includes('.m-8'), 'does not emit unrequested m-8 utility');
assert.ok(!outputCss.includes('.rotate-45'), 'does not emit unrequested rotate-45 utility');

console.log('CONTRACT PASS: tailwindcss programmatic API behaves as specified');

Seeder de origen

csx-seed