Vale off/on comments do not work in mdx around code blocks
Check for existing issues
- [x] Completed
Environment
I am running this on macos with:
docker run --rm -it -v $(pwd)/styles:/styles -v $(pwd):/docs -w /docs jdkato/vale my_file.mdx
And the version:
docker run --rm -it -v $(pwd)/styles:/styles -v $(pwd):/docs -w /docs jdkato/vale -v
vale version v3.11.2
Describe the bug / provide steps to reproduce it
With these delimiters configured:
[*.{md,mdx}]
CommentDelimiters = {/*, */}
And this code (indentation just for github display):
{/* vale off */}
```
thingamajig
```
{/* vale on */}
I will still get a spelling suggestion for thingamajig. I can place <!-- vale off --> on the first line inside the code block and it will disable the suggestion but the comment shows up in the rendered output of the code block.
Vale ignores code blocks by default (you don't need to use comments to do so), so there's something else going on. I'd need to see your full file to understand the issue though.
For context, I work with OP.
We're using vale version 3.11.2
Locally, I'm using vale version 3.11.2 and Vale VSCode v0.20.0.
Our Vale GitHub Action is using a pinned commit: errata-ai/vale-action@dcded780f1ff68e2558e802a165a484a4a3e2fb8 (Jun 6, 2025)
Here's our .vale.ini file:
StylesPath = vale/styles
MinAlertLevel = suggestion
IgnoredScopes = code, img, tt
SkippedScopes = code, figure, pre, script, style
# Vocab = Aembit
[formats]
mdx = md
yml = yaml
[*]
# Ignore code surrounded by plus sign, URLs, parameters defaults, and angle brackets.
TokenIgnores = (<\/?[A-Z].+>), ([^\n]+=[^\n]*), (\+[^\n]+\+), (http[^\n]+\[), (https[^\n]+\[), ([^\n]+@[^\n]+\.[^\n]), (".+?"), ('.+?')
# Ignore SVG markup
TokenIgnores = (\*\*\{\w*\}\*\*)
[*.{md,mdx}]
BasedOnStyles = Aembit, Vale
Vale.Spelling = NO
The .mdx page in question and all other .mdx page act very strangely with regard to how the Vale GitHub Action, CLI, and VS Code extension catch rule violations.
Example page (backslashes to keep GFM from breaking):
---
title: Test page
description: Test page
sidebar:
label: Test page
order: 4
---
import { Steps } from '@astrojs/starlight/components';
owner: Could not determine whether revision 1 is supported, assuming it is.
CT: Could not determine whether revision 2 is supported, assuming it is.
iptables v1.8.9 (legacy): can't initialize iptables table `raw': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
{/* vale off */}
owner: Could not determine whether revision 1 is supported, assuming it is.
CT: Could not determine whether revision 2 is supported, assuming it is.
iptables v1.8.9 (legacy): can't initialize iptables table `raw': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
{/* vale on */}
{/* vale off */}
\```
owner: Could not determine whether revision 1 is supported, assuming it is.
CT: Could not determine whether revision 2 is supported, assuming it is.
iptables v1.8.9 (legacy): can't initialize iptables table `raw': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
\```
{/* vale on */}
{/* vale off */}
\```shell
owner: Could not determine whether revision 1 is supported, assuming it is.
CT: Could not determine whether revision 2 is supported, assuming it is.
iptables v1.8.9 (legacy): can't initialize iptables table `raw': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
\```
{/* vale on */}
{/* vale off */}
\```shell ins="determine"
owner: Could not determine whether revision 1 is supported, assuming it is.
CT: Could not determine whether revision 2 is supported, assuming it is.
iptables v1.8.9 (legacy): can't initialize iptables table `raw': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
\```
{/* vale on */}
{/* vale off */}
\```shell {2,4}
owner: Could not determine whether revision 1 is supported, assuming it is.
CT: Could not determine whether revision 2 is supported, assuming it is.
iptables v1.8.9 (legacy): can't initialize iptables table `raw': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
\```
{/* vale on */}
{/* vale off */}
\```shell {2,4} mark="determine"
owner: Could not determine whether revision 1 is supported, assuming it is.
CT: Could not determine whether revision 2 is supported, assuming it is.
iptables v1.8.9 (legacy): can't initialize iptables table `raw': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
\```
{/* vale on */}
Vale CLI Output:
✖ [31m0 errors[0m, [33m16 warnings[0m and [34m9 suggestions[0m in 1 file.
test-page.mdx:12:8:Aembit.Contractions:Use 'couldn't' instead of 'Could not'.
test-page.mdx:12:47:Aembit.Passive:In general, use active voice instead of passive voice ('is supported').
test-page.mdx:12:70:Aembit.Contractions:Use 'it's' instead of 'it is'.
test-page.mdx:13:5:Aembit.Contractions:Use 'couldn't' instead of 'Could not'.
test-page.mdx:13:44:Aembit.Passive:In general, use active voice instead of passive voice ('is supported').
test-page.mdx:13:67:Aembit.Contractions:Use 'it's' instead of 'it is'.
test-page.mdx:14:1:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:14:44:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:15:42:Aembit.Passive:In general, use active voice instead of passive voice ('be upgraded').
test-page.mdx:19:8:Aembit.Contractions:Use 'couldn't' instead of 'Could not'.
test-page.mdx:19:47:Aembit.Passive:In general, use active voice instead of passive voice ('is supported').
test-page.mdx:19:70:Aembit.Contractions:Use 'it's' instead of 'it is'.
test-page.mdx:20:5:Aembit.Contractions:Use 'couldn't' instead of 'Could not'.
test-page.mdx:20:44:Aembit.Passive:In general, use active voice instead of passive voice ('is supported').
test-page.mdx:20:67:Aembit.Contractions:Use 'it's' instead of 'it is'.
test-page.mdx:21:1:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:21:44:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:22:42:Aembit.Passive:In general, use active voice instead of passive voice ('be upgraded').
test-page.mdx:28:70:Aembit.Contractions:Use 'it's' instead of 'it is'.
test-page.mdx:48:1:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:48:44:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:49:42:Aembit.Passive:In general, use active voice instead of passive voice ('be upgraded').
test-page.mdx:66:1:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:66:44:Aembit.Spelling:Check the spelling of 'iptables'. If the spelling is correct, add it to spelling-exceptions.txt in alphabetical order.
test-page.mdx:67:42:Aembit.Passive:In general, use active voice instead of passive voice ('be upgraded').
@dvaembit @holdenhewett I can guess what's going on:
Using regex in the .vale.ini file to parse HTML-like tags will result in all kinds of things that break, and you start getting the wrong capture groups causing errors to appear in odd places.
I strongly recommend you move to using Vale's recent support for MDX rather than the regular expresion-based support. See the docs, but you'll install the companion mdx2vast command and ensure you have a Vale version that supports MDX conversion. We've moved to this at $dayjob$ now and it's such an improvement.