tailwind-a11y 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,7 +34,7 @@ npx tailwind-a11y --help # usage and all options
34
34
  Custom theme colors/spacing are read automatically, so colors and spacing outside
35
35
  Tailwind's defaults resolve too — not just the built-in palette. Both config formats
36
36
  are supported: `theme.extend.colors`/`theme.extend.spacing` in a Tailwind v3
37
- `tailwind.config.js`/`.cjs`, and `--color-*`/`--spacing-*` custom properties in a
37
+ `tailwind.config.js`/`.cjs`/`.mjs`, and `--color-*`/`--spacing-*` custom properties in a
38
38
  Tailwind v4 CSS `@theme { ... }` block (auto-detected from common paths like
39
39
  `app/globals.css`, or passed via `--config`).
40
40
 
@@ -5,7 +5,10 @@ import { defaultPalette } from "./defaultPalette.js";
5
5
  import { spacingScale } from "./spacingScale.js";
6
6
  import { parseColorScale, parseSpacingValue } from "./themeValueParsers.js";
7
7
  import { parseThemeCss } from "./parseThemeCss.js";
8
- const CONFIG_FILENAMES = ["tailwind.config.js", "tailwind.config.cjs"];
8
+ // .mjs appended last (lowest priority) -- the newly-supported format behind
9
+ // the two established ones, same "most established first" ordering
10
+ // CSS_THEME_CANDIDATES below already uses for its own list.
11
+ const CONFIG_FILENAMES = ["tailwind.config.js", "tailwind.config.cjs", "tailwind.config.mjs"];
9
12
  // v1 only looks in the given directory itself -- no ancestor-directory search.
10
13
  // --config (CLI) / settings["tailwind-a11y"].configPath (ESLint) exist as
11
14
  // explicit escape hatches for projects where this isn't enough. `rootDir` must
@@ -42,15 +45,46 @@ export function findTailwindThemeCss(rootDir) {
42
45
  }
43
46
  return null;
44
47
  }
45
- // Loads a Tailwind v3-style tailwind.config.js/.cjs and extracts only
48
+ // Loads a Tailwind v3-style tailwind.config.js/.cjs/.mjs and extracts only
46
49
  // `theme.extend.colors`/`theme.extend.spacing` -- v1 does not read a full
47
- // `theme.colors`/`theme.spacing` replacement, or .mjs/.ts configs (no
48
- // config-transpiling dependency exists in this package). Tailwind v4's
50
+ // `theme.colors`/`theme.spacing` replacement, or .ts configs. Tailwind v4's
49
51
  // CSS-based `@theme` config is a separate format entirely, handled by
50
52
  // loadThemeFromCssFile()/parseThemeCss() below, not by this function.
51
53
  // `configPath` must be an absolute path (require() resolves relative paths
52
54
  // against this module's own location, not the caller's cwd).
53
55
  //
56
+ // .mjs works via plain require() -- verified this session that Node
57
+ // 20.19+/22.13+ can require() an ESM module synchronously, no import(), no
58
+ // async refactor. On an older Node this throws ERR_REQUIRE_ESM, already
59
+ // caught below and treated as "no config found," so this degrades exactly
60
+ // as gracefully as it did before .mjs was supported. Every adapter's actual
61
+ // runtime already clears the threshold: the GitHub Action runs on Node 24
62
+ // (action.yml), eslint-plugin-tailwind-a11y's own engines.node already
63
+ // excludes every version that lacks this, and the CLI's broad >=18 floor
64
+ // just falls back safely on anything older.
65
+ //
66
+ // .ts is a deliberate non-goal, not a "not yet": Node's native TypeScript
67
+ // type-stripping only activates when the *host* process is launched with
68
+ // --experimental-strip-types (verified this session -- a library can't
69
+ // turn this on for the user), so the only way to support .ts transparently
70
+ // would be promoting esbuild from a devDependency to a real runtime
71
+ // dependency of this package purely to transpile config files, a real
72
+ // native-binary weight increase. Also verified this session: a fresh
73
+ // `create-next-app --typescript --tailwind` no longer generates a JS/TS
74
+ // config file at all -- Tailwind v4 projects put theme customization in a
75
+ // CSS `@theme` block instead (see loadThemeFromCssFile() below), so .ts
76
+ // config support would only help a shrinking population of legacy
77
+ // v3-plus-TypeScript projects, not worth the dependency.
78
+ //
79
+ // Known limitation, not fixed: bustRequireCache() below does NOT work for
80
+ // a .mjs config. Node's synchronous require(esm) caches the module in its
81
+ // own internal ESM registry, not (only) in `require.cache` -- deleting the
82
+ // `require.cache` entry doesn't force a reload, confirmed with a real
83
+ // edit-and-reload test this session. CLI and GitHub Action are unaffected
84
+ // (fresh process per run either way); the VS Code extension's live-reload
85
+ // guarantee, which does work correctly for .js/.cjs/.css configs, does NOT
86
+ // extend to .mjs -- editing a .mjs config requires reloading the window.
87
+ //
54
88
  // Node's require() cache is busted before loading -- recursively, for the
55
89
  // config file *and* everything it required (e.g. a config that factors
56
90
  // tokens into a separate `require('./colors.js')`) -- without this, a
@@ -83,7 +117,20 @@ export function loadCustomTheme(configPath) {
83
117
  const cached = require.cache[resolved];
84
118
  if (cached)
85
119
  bustRequireCache(require, cached, new Set());
86
- const config = require(resolved);
120
+ const loaded = require(resolved);
121
+ // Node's require() of an ESM module returns the module namespace object
122
+ // (`{ __esModule: true, default: <the actual export>, ...named exports
123
+ // }`), not the export itself. Gated strictly on the .mjs extension --
124
+ // caught in independent review: a structural check ("does it have a
125
+ // `default` key") instead of this would silently misfire on a genuine
126
+ // CJS config that happens to export its own top-level `default` key
127
+ // (e.g. `module.exports = { default: "unrelated", theme: {...} }`),
128
+ // discarding the real theme with no error. .mjs is the only path that
129
+ // can ever produce this wrapped shape here: a `.js`/`.cjs` require()
130
+ // either returns the CJS export as-is, or -- inside a "type": "module"
131
+ // package -- throws ERR_REQUIRE_ESM before this line is ever reached
132
+ // (already handled by the catch block below, and already tested).
133
+ const config = resolved.endsWith(".mjs") && loaded && typeof loaded === "object" ? loaded.default : loaded;
87
134
  const extend = config?.theme?.extend ?? {};
88
135
  const result = {};
89
136
  if (extend.colors && typeof extend.colors === "object") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-a11y",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Static analysis CLI that catches WCAG accessibility violations — color contrast, touch target size, and focus indicator removal/contrast — in Tailwind CSS class combinations before they ship.",
5
5
  "type": "module",
6
6
  "bin": {