CodeSampleX

サンプル

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

検証済みサンプル — npm tailwindcss 4.3.3: Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build…

sha256:7e8fea6fcad1e429a66c2ec7cabadab555fed65be50225e20dee895a0a8de843

このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。 合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。 MIT-0

実行証拠

宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。

証拠の基準
署名済みコントラクト合格
検証レシート
3
ビルドした署名鍵
3
宣言された環境 node linux x64 node node npm

検証実行環境

環境 コントラクト ステージ 実行日
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

ケース

HOW
ゴール
Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build instead of invoking default export
パッケージ
シンボル
  • tailwindcss
  • compile
  • loadStylesheet
  • loadModule
  • build
  • default
環境
node
作成日
2026-08-16T07:54:12Z

コントラクト

  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

ファイル

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

ソースアーティファクトをダウンロード (tar.gz)

ソース

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');

オリジンシーダー

csx-seed