Skip to main content

Configuration

Jess reads config from a styles.config.{ts,js} file, usually at your project root: a file uses every one in its own folder and the folders above it, up to its package root, so a project's config applies to its subfolders. Keep it small at first; grow it only when your build needs it.

// styles.config.js
export default {
options: {}
}

options​

dynamic​

Changes compilation mode so dynamic content is represented as CSS custom properties and patch-friendly output. Reach for this when you need runtime theme switching or app-level style updates.

module​

Overrides whether Jess files compile as modules globally. By default, files named [filename].module.jess or [filename].m.jess are treated as modules and class names are hashed.

Compile settings​

The compile settings (mathMode, unitMode, functionMode, the strict preset, allowCallerScope, processImports, …) are worked out for each file, so a file compiles the same way whichever file imports it. Math written in a file follows that file's settings wherever it ends up: a variable's value, a mixin's body and its guard answer the settings of the file they are written in, not the file that reads or calls them. A file also keeps its own language's built-in functions.

A file's settings come from two places, merged:

  1. Its styles.config files: every one in the file's own folder and the folders above it, merged, the nearest winning setting by setting. A subfolder's config only needs the settings that differ: the rest come from the configs above it. The search stops at the file's package root (the first folder up with a package.json, whose config is included), so one package never reads another's config. An imported file in another folder uses the configs above it, not the entry's. No styles.config is loaded for a file in an installed package (under node_modules).

  2. The settings passed in: to the compiler, to a render, or on the command line. They are merged over the styles.config files setting by setting: a value passed in wins over the same setting in a config file, and the config files supply everything left unset.

    compile and each language.<lang> block merge setting by setting. A single input or output object does too; a list of output (or input) entries replaces the one above it. Any other key (lint, …) is replaced whole by the nearer config.

    new Compiler({ compile: { unitMode: 'preserve' } });
    compiler.render('main.less', { compile: { unitMode: 'preserve' } });

On that merged config, each file's settings are worked out for its language, each step over the one before:

  1. Its language's defaults, or the options its language's plugin was built with (lessPlugin({ unitMode: 'loose' })). A .less file keeps math over units that do not convert as calc() and warns (unitMode: 'preserve'); a .jess file stops with an error (strict). A .jess file imported by a .less file still errors, and a .less file imported by a .jess file still writes calc().

  2. compile settings, which apply to every file, whatever its language.

  3. language.<lang> settings (language.less, language.jess, language.scss), which apply only to files of that language.

    // styles.config.js
    export default {
    compile: { unitMode: 'preserve' },
    language: { jess: { unitMode: 'strict' } }
    }

So a language setting wins over a compile setting wherever each is set: language.less.unitMode: 'loose' in a styles.config applies to .less files even when the render passes compile: { unitMode: 'strict' } or compile: { strict: true }, and .jess files get the render's setting. A deprecated spelling (strictUnits, math, strictMath, leakyScope) counts where it is written: language.less.strictUnits wins over compile.unitMode as language.less.unitMode would, and passed in, it wins over a language.less.unitMode in the config file.

The strict preset is not a mode of its own. It can be set in compile or in language.<lang>, and the more specific one decides: language.less.strict wins over compile.strict for .less files, false included. When on, it fills the modes left unset where it is written, so compile: { strict: true } gives way to any mode a language sets, and language.less.strict: true makes .less strict over a compile.unitMode while language.less.unitMode still wins over it.

compile.plugins​

Add compile-time plugins used by the compiler (for language/runtime extensions). This is separate from bundler plugins such as rollup-plugin-jess.

lint​

Configure jess lint and the @jesscss/lint API.

// styles.config.js
export default {
lint: {
files: ['src/**/*.{css,less,scss,jess}'],
ignoreFiles: ['dist/**'],
reportSyntax: true,
rules: {
'property-no-unknown': 'error',
'length-zero-no-unit': 'warn',
'vendor-prefix': 'warn',
'compatible-vendor-prefixes': 'off',
'unknown-vendor-specific-properties': 'off',
'float': 'off',
'jess/no-suspicious-map-key-access': 'warn',
'jess/unsupported-sass-form': 'warn'
}
}
}

files supplies the default glob set when jess lint is run without positional patterns. ignoreFiles excludes generated or vendored stylesheets.

reportSyntax controls whether parser diagnostics are surfaced through lint. Per-rule values are off, warn, and error; null also disables a rule. Jess uses Stylelint rule names where the rule intent is familiar and Jess-owned namespaces for Jess-only checks. Those rule names are the lint configuration surface; shared diagnostic codes are still emitted in JSON for editor and tool integrations.

Jess lint uses this policy on top of shared diagnostics. Detection itself lives below the lint package, so a diagnostic can be reused by the CLI and the language service instead of being implemented twice.