Upgrade 0.2 to 0.3

  • Change cssxjs in your package.json to ^0.3
  • Change eslint-plugin-cssxjs and any directly installed @cssxjs/* packages to ^0.3
  • If you lint Pug templates, use eslint@^9 and the new flat eslint.config.mjs config
  • Run your package manager install command after the version bump

Pug TypeScript and Embedded Styles

CSSX 0.3 uses the new react-pug transform.

This migration guide focuses on moving Pug components to the new preferred style and updating ESLint.

Quick Migration Checklist

  1. Upgrade cssxjs and CSSX-related packages to ^0.3.
  2. Keep cssxjs/babel in your Babel presets.
  3. Move local styles in Pug components from separate styl or css template strings into a terminal style block inside the pug template.
  4. Use style(lang='styl') for Stylus and style for plain CSS.
  5. Remove TypeScript workarounds around Pug templates; TS expressions are now supported directly in TSX files.
  6. Replace tsc --noEmit with npx cssxjs check for Pug-aware project type checks.
  7. Replace the old CSSX ESLint preset with eslint-plugin-cssxjs.
  8. Use ESLint v9 flat config. Do not upgrade to ESLint v10 for this setup.

Embedded Style Blocks

Old

Pug structure and styles were usually split between pug and a separate styl template:

import { pug, styl } from 'cssxjs'
import { View, Text } from 'react-native'

function Card({ title, children }) {
  return pug`
    View.card
      Text.title= title
      View.content
        = children
  `

  styl`
    .card
      padding 16px
      border-radius 8px
      background white
    .title
      font-size 18px
  `
}

New

Put local styles at the end of the pug template:

import { pug } from 'cssxjs'
import { View, Text } from 'react-native'

function Card({ title, children }) {
  return pug`
    View.card
      Text.title= title
      View.content
        = children

    style(lang='styl')
      .card
        padding 16px
        border-radius 8px
        background white
      .title
        font-size 18px
  `
}

Result: the component structure and its local styles stay in one Pug block. CSSX moves the style block into a local styl template during the Babel transform.

For plain CSS:

return pug`
  View.card
    Text.title CSS styles

  style
    .card {
      padding: 16px;
      border-radius: 8px;
      background: white;
    }
`

Behavior:

  • The embedded style block must be the last top-level node in the pug template.
  • style defaults to CSS.
  • style(lang='styl') uses Stylus.
  • Standalone styl and css template literals still work for JSX components and shared module-level styles.

TypeScript in Pug

Pug templates in .tsx files now support TypeScript expressions. If you previously extracted typed expressions out of Pug only to satisfy the old transform or editor tooling, you can usually move them back into the template.

Use npx cssxjs check for Pug-aware type checks:

npx cssxjs check

Do not rely on tsc --noEmit alone for Pug components. TypeScript treats the content of pug`...` as template string text, so it does not parse or type-check Pug expressions by itself.

See TypeScript Support for the full guide and command options.

ESLint Migration (Breaking)

Old

Projects commonly used the old CSSX ESLint preset or eslint-config-cssxjs through legacy ESLint config:

// .eslintrc.js
module.exports = {
  extends: ['cssxjs']
}

New

Use ESLint v9 and eslint-plugin-cssxjs with flat config:

npm install -D eslint@^9 eslint-plugin-cssxjs
# or
yarn add -D eslint@^9 eslint-plugin-cssxjs
# or
pnpm add -D eslint@^9 eslint-plugin-cssxjs
// eslint.config.mjs
import { defineConfig } from 'eslint/config'
import cssxjs from 'eslint-plugin-cssxjs'

export default defineConfig([
  {
    files: ['**/*.{js,jsx,ts,tsx}'],
    plugins: {
      cssxjs
    },
    processor: 'cssxjs/react-pug'
  }
])

Important:

  • Use ESLint v9 for CSSX 0.3 Pug linting.
  • Do not use ESLint v10 for this setup.
  • The plugin processor maps JavaScript and TypeScript diagnostics from inside pug templates back to the original Pug source.

ESLint with neostandard

If your project uses neostandard, compose the CSSX processor after the base config:

// eslint.config.mjs
import { defineConfig } from 'eslint/config'
import neostandard, { resolveIgnoresFromGitignore } from 'neostandard'
import cssxjs from 'eslint-plugin-cssxjs'

export default defineConfig([
  ...neostandard({
    ignores: resolveIgnoresFromGitignore(),
    ts: true
  }),
  {
    plugins: {
      cssxjs
    },
    processor: 'cssxjs/react-pug'
  }
])

VS Code

Install vscode-react-pug-tsx for TypeScript-aware Pug editing and embedded style highlighting.

For Stylus highlighting inside style(lang='styl'), also install a Stylus language extension.

Validation

After migrating:

npx eslint .

Then run your app build or bundler so Babel processes the new embedded style blocks.