Maple
⌘K
DOCUMENTATIONv2.0.24

Editor Setup

Maple has no build step and no configuration file, so there is nothing for an editor to read in order to understand your classes. The official Maple CSS extension closes that gap by running the same engine your page runs, so autocomplete, hover help, diagnostics, and color swatches reflect the exact CSS Maple would generate at runtime.

Installation

Search for Maple CSS in the Extensions view, or install it from the command line:

code --install-extension f12io.maple-vscode-extension

Every release is published to both the Visual Studio Marketplace and Open VSX, so editors that cannot reach the Microsoft marketplace, such as Cursor, Windsurf, and Antigravity, install the same extension from their own registry.

Enabling the Extension

The extension stays inactive by default so it never interferes with projects that do not use Maple. There is one exception: an HTML file that loads maple.js or maple.min.js from its <head> activates the extension for that file automatically, which covers the Quick Start setup without any configuration.

For every other project layout, turn it on explicitly for the workspace:

.vscode/settings.json

{
  "maple.enabled": true
}
  

Setting maple.enabled to false is not the same as leaving it unset. An explicit false disables the extension everywhere, including HTML files that would otherwise activate it on their own.

Features

Each feature can be toggled independently, so you can keep the parts that help and drop the ones that do not fit your workflow.

Feature
What It Does
Setting
Autocomplete

Suggests utilities, values, shades, and the custom aliases found in your workspace as you type.

features.autoComplete
Hover Help

Shows the formatted CSS a class generates, so you can verify a utility without opening DevTools.

features.hoverHelp
Color Picker

Renders a live swatch next to any color utility and opens the native VS Code picker on click.

features.colorPicker
Diagnostics

Warns about invalid classes, out-of-range shades, a misplaced ! prefix, alias definitions outside the <html> element, and utilities that conflict with each other.

features.diagnostics
Semantic Highlighting

Colors the parts of a class separately, so media queries, selectors, operators, utilities, and values stay readable in long class strings.

features.highlighting

Custom aliases are discovered by scanning the workspace for --alias- definitions, so an alias you declare on the <html> element of one file is suggested and documented in every other file of the same workspace. See Aliases for the definition syntax.

Settings

All options live under the maple namespace and can be set in the settings UI or directly in settings.json.

Setting
Default
Description
enabled
false

Master switch for the current workspace. Leave it unset to keep the automatic HTML activation.

exclude
node_modules, .git

Glob patterns for files where every feature is turned off.

features.autoComplete
true

Toggles suggestions.

features.hoverHelp
true

Toggles CSS hover tooltips.

features.colorPicker
true

Toggles swatches and the color picker.

features.diagnostics
true

Toggles linting and conflict warnings.

features.highlighting
"on"

Accepts "on", "minimal", or "off". See Highlighting Modes.

format.enabled
false

Enables the built-in class formatter and its command.

format.onSave
false

Formats Maple classes on save. Requires format.enabled.

format.maxClassesPerLine
4

Classes allowed on a single line before wrapping. Set to 1 to force one class per line.

.vscode/settings.json

{
  "maple.enabled": true,
  "maple.exclude": ["**/node_modules/**", "**/.git/**"],
  "maple.features.autoComplete": true,
  "maple.features.hoverHelp": true,
  "maple.features.colorPicker": true,
  "maple.features.diagnostics": true,
  "maple.features.highlighting": "on",
  "maple.format.enabled": true,
  "maple.format.onSave": true,
  "maple.format.maxClassesPerLine": 4
}
  

Highlighting Modes

A Maple class carries more structure than a plain class name, and the three highlighting modes decide how much of that structure is colored.

Mode
Behavior
"on"

Every token gets its own color: media queries, parent, self, and child selectors, operators, separators, utilities, values, aliases, variables, and the important prefix.

"minimal"

Utilities, values, and aliases share a single color, while structural tokens such as media queries, selectors, and operators keep theirs. This keeps the shape of a class visible without turning the line into a rainbow.

"off"

No Maple coloring. Your theme renders class attributes as it normally would.

Formatting Classes

Utility classes grow long, and a single line of thirty utilities is hard to scan. The Maple formatter only adds line breaks. It never reorders, adds, or removes a class, so the class string means exactly the same thing before and after a format pass.

A break is inserted where the property type changes from one class to the next, and again whenever a line reaches maxClassesPerLine. Classes stay in the order you wrote them, so this reads as grouping only where you already placed related utilities together. If a break would strand a single class on its own line, it is folded back into the neighbouring line.


<div
  class="
    c-blue p-2 m-2 fs-50
    o-50 fw-normal
  "
></div>
  

Two layout rules apply on top of the per-line limit:

  • The html element gets one class per line once it goes over the limit. Its classes are alias definitions, which read poorly side by side. At or under the limit it stays on a single line like any other element.

    
    <html
      class="
        --alias-btn=bgc-red-500;p-2
        --alias-card=p-{space,4}
        --alias-underline=brb;brc-{color,body}-90
        --alias-square=px-{space,1.5};ar=1
        --alias-prose=fs-50;lh-1.6
      "
    ></html>
      
  • A blank line is how you group classes yourself. The formatter never moves a class across one, so anything you separate stays separated, pass after pass.

    
    <html
      class="
        --ff-main='Inter',-apple-system,BlinkMacSystemFont,sans-serif
        --ff-mono='JetBrains_Mono',monospace
    
        --color-body=oklch(0.560_0.025_260)
        --color-accent=oklch(0.660_0.25_260)
        --color-calm=oklch(0.660_0.15_235)
        --color-safe=oklch(0.630_0.2_150)
        --color-attention=oklch(0.660_0.25_80)
        --color-critical=oklch(0.660_0.2_20)
    
        @dark:--l-shift=-0.7
    
        --alias-space-none=mt-0
        --alias-space-sm=mt-2
        --alias-space-md=mt-4
        --alias-space-lg=mt-8
      "
    >
    </html>
      

Enabling the Formatter

Set maple.format.enabled to true to register the Maple CSS: Format Classes command, which formats the active document on demand. Add maple.format.onSave if you want the same pass to run every time you save.

The extension does not register itself as a document formatter, so it never competes for the editor.defaultFormatter slot. It formats through the command and through its own save hook, which means it runs in addition to whatever formatter your editor already uses on save.

Prettier Without the Maple Plugin
Plain Prettier squashes class attributes back onto one line. With editor.formatOnSave enabled, both formatters run on the same save and undo each other, which shows up as flickering. Installing the Prettier plugin below resolves this, because Prettier then produces the same layout as the extension and the two agree on the result.

Prettier Plugin

@f12io/prettier-plugin-maple applies the same layout from inside Prettier's own pass. It shares the formatting logic with the extension, so editors, pre-commit hooks, and CI pipelines all produce identical output.

npm install --save-dev prettier @f12io/prettier-plugin-maple
.prettierrc

{
  "plugins": ["@f12io/prettier-plugin-maple"],
  "mapleMaxClassesPerLine": 4
}
  

The plugin wraps the html, vue, angular, babel, babel-ts, and typescript parsers. It formats class attributes in templates, className expressions in JSX including ternaries, the arguments of clsx, classNames, and cva, and any expression you opt in with a /* maple */ comment. Hosts that cannot contain multi-line strings, such as Vue :class and Angular [ngClass], are normalized on a single line instead.

Comment Directives

Directives are comments you place in the code itself. They control the extension where a workspace setting would be too broad, for example a generated file that should be ignored or a string that Maple cannot recognize as a class list on its own.

Directive
Scope
/* maple-disable-file */

Disables the extension for the entire file.

/* maple-disable-line */

Disables the current line. Place it at the end of that line.

/* maple-disable-next-line */

Disables the line that immediately follows.

/* maple-disable */

Disables every feature for the rest of the file, until a matching enable directive.

/* maple-enable */

Re-enables the features after a disable directive.

/* maple */

Opts the following expression in. Every string literal in it, including ternary arms, concatenation parts, template literals, and interpolated strings, is parsed as Maple classes until the statement ends. Objects opt in their keys.


/* maple-disable-next-line */
const legacy = 'p-4 not-a-maple-class';

// Opt in a template literal
const styles = /* maple */ `bgc-red-500 p-4`;

// Opt in both arms of a ternary
const state = /* maple */ isActive ? 'bgc-red-500 p-4' : 'bgc-gray-300 p-2';
  

Supported Languages

Class extraction is language aware, so the extension knows where a class list can appear in each of these file types:

  • HTML: .html
  • React: .jsx, .tsx
  • Vue: .vue
  • Svelte: .svelte
  • Razor: .razor, .cshtml
  • PHP: .php
  • Twig: .twig
  • JavaScript and TypeScript: .js, .ts

In every one of them, the extension reads class and className attributes, plus any expression you opt in with /* maple */. Templates add their own framework syntax on top, and JavaScript and TypeScript files also pick up the arguments of clsx, classNames, and cva calls, which is what makes plain .ts files useful without a template around them.

Virtual Workspaces
Alias discovery scans files on disk, so custom aliases are unavailable in virtual workspaces. Every other feature keeps working on open documents.

Troubleshooting

If a feature stops responding, work through the checks below before filing a report:

  • Confirm the extension is active for the file. Either maple.enabled is true, or the file is HTML and loads Maple from its <head>.
  • Check that the file is not matched by maple.exclude and does not contain a disable directive.
  • Open View → Output → Maple CSS to see the errors the extension logged.

Include that output when filing an issue.

ESC

Start typing to search across the documentation.