Skip to content

Commit 63f8427

Browse files
Add lintOutsideWorkspace setting to limit linting to workspace files
Adds an opt-in markdownlint.lintOutsideWorkspace setting (boolean, default true to preserve current behavior). When set to false, Markdown files opened from outside the current workspace are no longer linted, restricting diagnostics to files inside an open workspace folder. Documents not stored on disk (such as untitled documents) are always linted, and explicit actions such as the markdownlint.fixAll command and document formatting continue to work regardless of this setting. Implements #440. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f3a16c2 commit 63f8427

6 files changed

Lines changed: 82 additions & 2 deletions

File tree

.markdownlint.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"### markdownlint.severityForError",
7070
"### markdownlint.severityForWarning",
7171
"### markdownlint.customRules",
72+
"### markdownlint.lintOutsideWorkspace",
7273
"### markdownlint.lintWorkspaceGlobs",
7374
"## Suppress",
7475
"## Snippets",

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Changes
22

3+
* 0.62.0 - Add `lintOutsideWorkspace` setting to limit linting to workspace files
34
* 0.61.0 - Improved rules, add warnings, add `severityForError`/`Warning`
45
* 0.60.0 - Improved rules
56
* 0.59.0 - Add `configFile` setting

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,18 @@ For information about authoring custom rules, see [the `markdownlint` documentat
362362
> In `markdownlint-cli2` configuration files, the `modulePaths` property can be used in conjunction to specify one or more additional paths for resolving module references.
363363
> This can be used to work around the VS Code limitation that globally-installed Node modules are unavailable by setting `modulePaths` to the location of the global module path (typically `/usr/local/lib` on macOS/Linux or `~/AppData/Roaming/npm` on Windows).
364364
365+
### markdownlint.lintOutsideWorkspace
366+
367+
By default, `markdownlint` lints every open Markdown document, including files that are not part of the current workspace. Setting this property to `false` restricts linting to files inside an open workspace folder, so Markdown files opened from elsewhere on the file system are not linted:
368+
369+
```json
370+
{
371+
"markdownlint.lintOutsideWorkspace": false
372+
}
373+
```
374+
375+
> **Note**: Documents that are not stored on disk (such as untitled documents) are always linted. Explicit actions such as the `markdownlint.fixAll` command and document formatting continue to work regardless of this setting.
376+
365377
### markdownlint.lintWorkspaceGlobs
366378

367379
This property specifies the list of globs used when linting a workspace with the `markdownlint.lintWorkspace` command.

extension.mjs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ const sectionConfig = "config";
9595
const sectionConfigFile = "configFile";
9696
const sectionCustomRules = "customRules";
9797
const sectionFocusMode = "focusMode";
98+
const sectionLintOutsideWorkspace = "lintOutsideWorkspace";
9899
const sectionLintWorkspaceGlobs = "lintWorkspaceGlobs";
99100
const sectionRun = "run";
100101
const sectionSeverityForError = "severityForError";
@@ -560,9 +561,21 @@ function lintWorkspaceViaTask () {
560561
});
561562
}
562563

564+
// Returns whether the document's location should be linted (honors lintOutsideWorkspace)
565+
function shouldLintDocumentLocation (document) {
566+
const configuration = vscode.workspace.getConfiguration(extensionDisplayName, document.uri);
567+
if (configuration.get(sectionLintOutsideWorkspace)) {
568+
return true;
569+
}
570+
// Setting is off: only lint files that are inside an open workspace folder
571+
// (non-file documents like untitled or virtual are always allowed)
572+
return (document.uri.scheme !== schemeFile) ||
573+
Boolean(vscode.workspace.getWorkspaceFolder(document.uri));
574+
}
575+
563576
// Lints a Markdown document
564577
function lint (document) {
565-
if (!lintingEnabled || !isMarkdownDocument(document)) {
578+
if (!lintingEnabled || !isMarkdownDocument(document) || !shouldLintDocumentLocation(document)) {
566579
return;
567580
}
568581
const diagnostics = [];
@@ -1015,6 +1028,8 @@ function didChangeWorkspaceFolders (changes) {
10151028
for (const workspaceFolderUri of changes.added.map((folder) => folder.uri)) {
10161029
createFileSystemWatchers(workspaceFolderUri);
10171030
}
1031+
// Re-lint because workspace membership can affect linting (see "lintOutsideWorkspace")
1032+
clearDiagnosticsAndLintVisibleFiles();
10181033
}
10191034

10201035
export function activate (context) {

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "markdownlint",
44
"description": "Markdown linting and style checking for Visual Studio Code",
55
"icon": "images/markdownlint-128.png",
6-
"version": "0.61.2",
6+
"version": "0.62.0",
77
"author": "David Anson (https://dlaa.me/)",
88
"publisher": "DavidAnson",
99
"sponsor": {
@@ -344,6 +344,12 @@
344344
],
345345
"default": false
346346
},
347+
"markdownlint.lintOutsideWorkspace": {
348+
"description": "Whether to lint Markdown files that are open but not part of the current workspace. Set to false to only lint files within the workspace.",
349+
"scope": "resource",
350+
"type": "boolean",
351+
"default": true
352+
},
347353
"markdownlint.lintWorkspaceGlobs": {
348354
"description": "Array of glob expressions to include or ignore when linting a workspace with the \"lintWorkspace\" command.",
349355
"scope": "resource",

test-ui/tests.cjs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
const assert = require("node:assert");
1111
const fs = require("node:fs/promises");
12+
const os = require("node:os");
1213
const path = require("node:path");
1314
const vscode = require("vscode");
1415

@@ -260,6 +261,49 @@ function dynamicWorkspaceSettingsChange () {
260261
});
261262
}
262263

264+
// Verify lintOutsideWorkspace=false stops linting a file outside the workspace
265+
function lintOutsideWorkspaceSetting () {
266+
return testWrapper((resolve, reject, disposables) => {
267+
const configuration = vscode.workspace.getConfiguration("markdownlint");
268+
const outsideName = "/markdownlint-outside.md";
269+
let fileUri = null;
270+
let disabled = false;
271+
let done = false;
272+
disposables.push(
273+
vscode.languages.onDidChangeDiagnostics((diagnosticChangeEvent) => {
274+
callbackWrapper(reject, () => {
275+
if (!fileUri) {
276+
return;
277+
}
278+
const diagnostics = getDiagnostics(diagnosticChangeEvent, outsideName);
279+
const codes = diagnostics.map((diagnostic) => (diagnostic.code && diagnostic.code.value) || diagnostic.code);
280+
if ((codes.length > 0) && !disabled) {
281+
// By default the outside file is linted
282+
assert.ok(codes.includes("MD019"));
283+
disabled = true;
284+
configuration.update("lintOutsideWorkspace", false, vscode.ConfigurationTarget.Workspace)
285+
.then(noop, reject);
286+
} else if ((codes.length === 0) && disabled && !done) {
287+
// With lintOutsideWorkspace=false the outside file is no longer linted
288+
done = true;
289+
configuration.update("lintOutsideWorkspace", undefined, vscode.ConfigurationTarget.Workspace)
290+
.then(() => vscode.commands.executeCommand("workbench.action.closeActiveEditor"))
291+
.then(() => fs.rm(fileUri.fsPath, { "force": true }))
292+
.then(() => resolve(), reject);
293+
}
294+
});
295+
})
296+
);
297+
fs.mkdtemp(path.join(os.tmpdir(), "mdl-"))
298+
.then((directory) => {
299+
fileUri = vscode.Uri.file(path.join(directory, outsideName));
300+
return fs.writeFile(fileUri.fsPath, "# Heading\n");
301+
})
302+
.then(() => vscode.window.showTextDocument(fileUri))
303+
.then(noop, reject);
304+
});
305+
}
306+
263307
// Run lintWorkspace command
264308
function lintWorkspace () {
265309
return testWrapper((resolve, reject, disposables) => {
@@ -286,6 +330,7 @@ if (vscode.workspace.workspaceFolders) {
286330
tests.push(
287331
openEditDiffRevert,
288332
dynamicWorkspaceSettingsChange,
333+
lintOutsideWorkspaceSetting,
289334
// Run this last because its diagnostics persist after test completion
290335
lintWorkspace
291336
);

0 commit comments

Comments
 (0)