diff --git a/New_Extensibility_Model/Samples/MarkdownLinter/.vsextension/string-resources.json b/New_Extensibility_Model/Samples/MarkdownLinter/.vsextension/string-resources.json
index cb3d4d71..11ca1a99 100644
--- a/New_Extensibility_Model/Samples/MarkdownLinter/.vsextension/string-resources.json
+++ b/New_Extensibility_Model/Samples/MarkdownLinter/.vsextension/string-resources.json
@@ -1,4 +1,8 @@
{
"MarkdownLinter.RunLinterOnCurrentFileCommand.DisplayName": "Run Linter on open file",
- "MarkdownLinter.RunLinterOnSolutionCommand.DisplayName": "Run Linter on solution"
+ "MarkdownLinter.RunLinterOnSolutionCommand.DisplayName": "Run Linter on solution",
+ "MarkdownLinter.Settings.Category.DisplayName": "Markdown Linter",
+ "MarkdownLinter.Settings.Category.Description": "Markdown Linter Settings",
+ "MarkdownLinter.Settings.DisabledRules.DisplayName": "Disabled rules",
+ "MarkdownLinter.Settings.DisabledRules.Description": "List of disabled rules to pass to markdown-cli"
}
\ No newline at end of file
diff --git a/New_Extensibility_Model/Samples/MarkdownLinter/LinterUtilities.cs b/New_Extensibility_Model/Samples/MarkdownLinter/LinterUtilities.cs
index a70d8e39..4ca1c3fd 100644
--- a/New_Extensibility_Model/Samples/MarkdownLinter/LinterUtilities.cs
+++ b/New_Extensibility_Model/Samples/MarkdownLinter/LinterUtilities.cs
@@ -11,6 +11,7 @@ namespace MarkdownLinter;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft;
using Microsoft.VisualStudio.Extensibility.Editor;
@@ -19,27 +20,44 @@ namespace MarkdownLinter;
using Microsoft.VisualStudio.RpcContracts.DiagnosticManagement;
using Microsoft.VisualStudio.Threading;
+#pragma warning disable VSEXTPREVIEW_SETTINGS // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
///
/// Helper class for running linter on a string or file.
///
-internal static class LinterUtilities
+internal class LinterUtilities
{
private static readonly Regex LinterOutputRegex = new(@"(?[^:]+):(?\d*)(:(?\d*))? (?.*)/(?.*)", RegexOptions.Compiled);
+ private readonly Settings.MarkdownLinterCategoryObserver settingsObserver;
+
+ public LinterUtilities(Settings.MarkdownLinterCategoryObserver settingsObserver)
+ {
+ this.settingsObserver = settingsObserver;
+ }
+
///
/// Runs markdown linter on a file uri and returns diagnostic entries.
///
/// File uri to run markdown linter on.
+ /// Cancellation token to monitor.
/// an enumeration of entries for warnings in the markdown file.
- public static async Task> RunLinterOnFileAsync(Uri fileUri)
+ public async Task> RunLinterOnFileAsync(Uri fileUri, CancellationToken cancellationToken)
{
using var linter = new Process();
var lineQueue = new AsyncQueue();
+ var snapshot = await this.settingsObserver.GetSnapshotAsync(cancellationToken);
+ string disabledRules = snapshot.DisabledRules.ValueOrDefault(string.Empty);
+
+ string args = "/c \"npx markdownlint-cli" +
+ (disabledRules.Length > 0 ? $" --disable {disabledRules} --" : string.Empty) +
+ $" \"{fileUri.LocalPath}\"\"";
+
linter.StartInfo = new ProcessStartInfo()
{
- FileName = "node.exe",
- Arguments = $"\"{Environment.ExpandEnvironmentVariables("%APPDATA%\\npm\\node_modules\\markdownlint-cli\\markdownlint.js")}\" \"{fileUri.LocalPath}\"",
+ FileName = "cmd.exe",
+ Arguments = args,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
@@ -76,18 +94,25 @@ public static async Task> RunLinterOnFileAsync(U
/// Runs markdown linter on a given text document and returns diagnostic entries.
///
/// Document to run markdown linter on.
+ /// Cancellation token to monitor.
/// an enumeration of entries for warnings in the markdown file.
- public static async Task> RunLinterOnDocumentAsync(ITextDocumentSnapshot textDocument)
+ public async Task> RunLinterOnDocumentAsync(ITextDocumentSnapshot textDocument, CancellationToken cancellationToken)
{
using var linter = new Process();
var lineQueue = new AsyncQueue();
var content = textDocument.Text.CopyToString();
+ var snapshot = await this.settingsObserver.GetSnapshotAsync(cancellationToken);
+ string disabledRules = snapshot.DisabledRules.ValueOrDefault(string.Empty);
+
+ string args = "/k \"npx markdownlint-cli --stdin" +
+ (disabledRules.Length > 0 ? $" --disable {disabledRules}" : string.Empty) + "\"";
+
linter.StartInfo = new ProcessStartInfo()
{
FileName = "cmd.exe",
- Arguments = $"/k \"{Environment.ExpandEnvironmentVariables("%APPDATA%\\npm\\markdownlint.cmd")}\" -s",
+ Arguments = args,
RedirectStandardError = true,
RedirectStandardInput = true,
UseShellExecute = false,
@@ -125,16 +150,6 @@ public static async Task> RunLinterOnDocumentAsy
return CreateDocumentDiagnosticsForOpenDocument(textDocument, markdownDiagnostics);
}
- ///
- /// Checks if the given path is a valid markdown file.
- ///
- /// Local file path to verify.
- /// true if file is a markdown file, false otherwise.
- public static bool IsValidMarkdownFile(string localPath)
- {
- return localPath is not null && Path.GetExtension(localPath).Equals(".md", StringComparison.OrdinalIgnoreCase);
- }
-
private static IEnumerable CreateDocumentDiagnosticsForOpenDocument(ITextDocumentSnapshot document, IEnumerable diagnostics)
{
foreach (var diagnostic in diagnostics)
diff --git a/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownDiagnosticsService.cs b/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownDiagnosticsService.cs
index 7070eedf..288c89fc 100644
--- a/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownDiagnosticsService.cs
+++ b/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownDiagnosticsService.cs
@@ -7,6 +7,7 @@ namespace MarkdownLinter;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using System.Windows.Media.Animation;
using Microsoft;
using Microsoft.VisualStudio.Extensibility;
using Microsoft.VisualStudio.Extensibility.Documents;
@@ -28,6 +29,7 @@ internal class MarkdownDiagnosticsService : DisposableObject
#pragma warning restore CA2213 // Disposable fields should be disposed
private readonly Dictionary documentCancellationTokens;
private readonly Task initializationTask;
+ private readonly LinterUtilities linterUtilities;
private OutputChannel? outputChannel;
private DiagnosticsReporter? diagnosticsReporter;
@@ -35,10 +37,12 @@ internal class MarkdownDiagnosticsService : DisposableObject
/// Initializes a new instance of the class.
///
/// Extensibility object.
- public MarkdownDiagnosticsService(VisualStudioExtensibility extensibility)
+ /// Service for running the linter on markdown files.
+ public MarkdownDiagnosticsService(VisualStudioExtensibility extensibility, LinterUtilities linterUtilities)
{
this.extensibility = Requires.NotNull(extensibility, nameof(extensibility));
this.documentCancellationTokens = new Dictionary();
+ this.linterUtilities = Requires.NotNull(linterUtilities, nameof(linterUtilities));
this.initializationTask = Task.Run(this.InitializeAsync);
}
@@ -71,7 +75,7 @@ public async Task ProcessFileAsync(Uri documentUri, CancellationToken cancellati
try
{
- var diagnostics = await LinterUtilities.RunLinterOnFileAsync(documentUri);
+ var diagnostics = await this.linterUtilities.RunLinterOnFileAsync(documentUri, cancellationToken);
await this.diagnosticsReporter!.ClearDiagnosticsAsync(documentUri, cancellationToken);
await this.diagnosticsReporter!.ReportDiagnosticsAsync(diagnostics, cancellationToken);
@@ -151,7 +155,7 @@ private async Task ProcessDocumentAsync(ITextDocumentSnapshot documentSnapshot,
try
{
- var diagnostics = await LinterUtilities.RunLinterOnDocumentAsync(documentSnapshot);
+ var diagnostics = await this.linterUtilities.RunLinterOnDocumentAsync(documentSnapshot, cancellationToken);
await this.diagnosticsReporter!.ClearDiagnosticsAsync(documentSnapshot, cancellationToken);
await this.diagnosticsReporter!.ReportDiagnosticsAsync(diagnostics, cancellationToken);
diff --git a/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownLinterExtension.cs b/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownLinterExtension.cs
index 2e741d32..aa15f70c 100644
--- a/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownLinterExtension.cs
+++ b/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownLinterExtension.cs
@@ -38,6 +38,12 @@ protected override void InitializeServices(IServiceCollection serviceCollection)
{
base.InitializeServices(serviceCollection);
+ // Add the settings observer created by MarkdownLinterSettingDefinitions to use in LinterUtilies.
+ serviceCollection.AddSettingsObservers();
+
+ // Add linter utilities as a singleton, it depends on settings observer.
+ serviceCollection.AddSingleton();
+
// As of now, any instance that ingests VisualStudioExtensibility is required to be added as a scoped
// service.
serviceCollection.AddScoped();
diff --git a/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownLinterSettingDefinitions.cs b/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownLinterSettingDefinitions.cs
new file mode 100644
index 00000000..3ceeb782
--- /dev/null
+++ b/New_Extensibility_Model/Samples/MarkdownLinter/MarkdownLinterSettingDefinitions.cs
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace MarkdownLinter;
+
+using Microsoft.VisualStudio.Extensibility;
+using Microsoft.VisualStudio.Extensibility.Settings;
+
+#pragma warning disable VSEXTPREVIEW_SETTINGS // The settings API is currently in preview and marked as experimental
+
+internal static class MarkdownLinterSettingDefinitions
+{
+ [VisualStudioContribution]
+ internal static SettingCategory MarkdownLinterCategory { get; } = new("markdownLinter", "%MarkdownLinter.Settings.Category.DisplayName%")
+ {
+ Description = "%MarkdownLinter.Settings.Category.Description%",
+ GenerateObserverClass = true,
+ };
+
+ [VisualStudioContribution]
+ internal static Setting.String DisabledRules { get; } = new("disabledRules", "%MarkdownLinter.Settings.DisabledRules.DisplayName%", MarkdownLinterCategory, defaultValue: string.Empty)
+ {
+ Description = "%MarkdownLinter.Settings.DisabledRules.Description%",
+ };
+}