diff --git a/CodeMirror6/CodeMirror6Wrapper.razor.cs b/CodeMirror6/CodeMirror6Wrapper.razor.cs
index 6267dd0d..0bc747f6 100644
--- a/CodeMirror6/CodeMirror6Wrapper.razor.cs
+++ b/CodeMirror6/CodeMirror6Wrapper.razor.cs
@@ -111,6 +111,11 @@ public partial class CodeMirror6Wrapper : ComponentBase, IAsyncDisposable
///
[Parameter] public Func>> LintDocument { get; set; } = (_, _) => Task.FromResult(new List());
///
+ /// The CodeMirror setup
+ ///
+ ///
+ [Parameter] public CodeMirrorSetup Setup { get; set; } = new();
+ ///
/// Additional attributes to be applied to the container element
///
///
@@ -214,7 +219,7 @@ public async Task> LintingRequestedFromJS(string code
///
protected override void OnInitialized()
{
- Config = new CodeMirrorConfiguration(
+ Config = new(
Doc,
Placeholder,
Theme?.ToString(),
diff --git a/CodeMirror6/CodeMirrorJsInterop.cs b/CodeMirror6/CodeMirrorJsInterop.cs
index c942a05b..d855a091 100644
--- a/CodeMirror6/CodeMirrorJsInterop.cs
+++ b/CodeMirror6/CodeMirrorJsInterop.cs
@@ -40,7 +40,13 @@ internal async Task ModuleInvokeVoidAsync(string method, params object?[] args)
/// Methods to set JS CodeMirror properties to reflect the values of the blazor wrapper parameters. Internal use only.
///
///
- internal CMSetters PropertySetters => _setters ??= new(_dotnetHelperRef, cm6WrapperComponent.Config, this);
+ internal CMSetters PropertySetters => _setters ??= new(
+ _dotnetHelperRef,
+ cm6WrapperComponent.Config,
+ cm6WrapperComponent.Setup,
+ this
+ );
+
///
/// Methods to invoke JS CodeMirror commands.
///
@@ -64,6 +70,7 @@ public async ValueTask DisposeAsync()
internal class CMSetters(
DotNetObjectReference _dotnetHelperRef,
CodeMirrorConfiguration config,
+ CodeMirrorSetup setup,
CodeMirrorJsInterop cmJsInterop
)
{
@@ -74,7 +81,8 @@ CodeMirrorJsInterop cmJsInterop
public Task InitCodeMirror() => cmJsInterop.ModuleInvokeVoidAsync(
"initCodeMirror",
_dotnetHelperRef,
- config
+ config,
+ setup
);
///
diff --git a/CodeMirror6/Models/CodeMirrorSetup.cs b/CodeMirror6/Models/CodeMirrorSetup.cs
new file mode 100644
index 00000000..b8ea2d23
--- /dev/null
+++ b/CodeMirror6/Models/CodeMirrorSetup.cs
@@ -0,0 +1,107 @@
+using System.Text.Json.Serialization;
+
+namespace CodeMirror6.Models;
+
+///
+/// Stores the configuration of a CodeMirror instance (what plugins to load).
+/// Cannot be changed after the instance is created.
+///
+public readonly record struct CodeMirrorSetup
+{
+ ///
+ /// Default constructor
+ ///
+ public CodeMirrorSetup()
+ {
+ }
+
+ ///
+ /// Whether to show line numbers to the left of the editor.
+ ///
+ [JsonPropertyName("lineNumbers")] public bool LineNumbers { get; init; } = true;
+
+ ///
+ /// Whether to highlight the line gutter when the cursor is on it.
+ ///
+ [JsonPropertyName("highlightActiveLineGutter")] public bool HighlightActiveLineGutter { get; init; } = true;
+
+ ///
+ /// Whether to highlight special characters (whitespace, tabs, newlines).
+ ///
+ [JsonPropertyName("highlightSpecialChars")] public bool HighlightSpecialChars { get; init; } = true;
+
+ ///
+ /// Whether to enable undo/redo.
+ ///
+ [JsonPropertyName("history")] public bool History { get; init; } = true;
+
+ ///
+ /// Whether to enable code folding.
+ ///
+ [JsonPropertyName("foldGutter")] public bool FoldGutter { get; init; } = true;
+
+ ///
+ /// Whether to draw the selection when the editor is focused.
+ ///
+ [JsonPropertyName("drawSelection")] public bool DrawSelection { get; init; } = true;
+
+ ///
+ /// Whether to show a cursor marker when the editor is focused.
+ ///
+ [JsonPropertyName("dropCursor")] public bool DropCursor { get; init; } = true;
+
+ ///
+ /// Whether to allow multiple selections.
+ ///
+ [JsonPropertyName("allowMultipleSelections")] public bool AllowMultipleSelections { get; init; } = true;
+
+ ///
+ /// Whether to indent the current line when a character is typed that might cause the line to be re-indented.
+ ///
+ [JsonPropertyName("indentOnInput")] public bool IndentOnInput { get; init; } = true;
+
+ ///
+ /// Whether to enable syntax highlighting.
+ ///
+ [JsonPropertyName("syntaxHighlighting")] public bool SyntaxHighlighting { get; init; } = true;
+
+ ///
+ /// Whether to highlight matching brackets.
+ ///
+ [JsonPropertyName("bracketMatching")] public bool BracketMatching { get; init; } = true;
+
+ ///
+ /// Whether to automatically close brackets.
+ ///
+ [JsonPropertyName("closeBrackets")] public bool CloseBrackets { get; init; } = true;
+
+ ///
+ /// Whether to enable autocompletion.
+ ///
+ [JsonPropertyName("autocompletion")] public bool Autocompletion { get; init; } = true;
+
+ ///
+ /// Whether to enable rectangular selection.
+ ///
+ [JsonPropertyName("rectangularSelection")] public bool RectangularSelection { get; init; } = true;
+
+ ///
+ /// Whether to enable crosshair selection.
+ ///
+ [JsonPropertyName("crossHairSelection")] public bool CrossHairSelection { get; init; } = true;
+
+ ///
+ /// Whether to highlight the active line.
+ ///
+ [JsonPropertyName("highlightActiveLine")] public bool HighlightActiveLine { get; init; } = true;
+
+ ///
+ /// Whether to highlight selection matches.
+ ///
+ [JsonPropertyName("highlightSelectionMatches")] public bool HighlightSelectionMatches { get; init; } = true;
+
+ ///
+ /// Whether to enable preview images.
+ ///
+ [JsonPropertyName("previewImages")] public bool PreviewImages { get; init; } = true;
+}
diff --git a/CodeMirror6/NodeLib/src/CmSetup.ts b/CodeMirror6/NodeLib/src/CmSetup.ts
new file mode 100644
index 00000000..31735d78
--- /dev/null
+++ b/CodeMirror6/NodeLib/src/CmSetup.ts
@@ -0,0 +1,25 @@
+/**
+ * Stores the configuration of a CodeMirror instance (what plugins to load).
+ * Cannot be changed after the instance is created.
+ */
+export class CmSetup
+{
+ public lineNumbers: boolean
+ public highlightActiveLineGutter: boolean
+ public highlightSpecialChars: boolean
+ public history: boolean
+ public foldGutter: boolean
+ public drawSelection: boolean
+ public dropCursor: boolean
+ public allowMultipleSelections: boolean
+ public indentOnInput: boolean
+ public syntaxHighlighting: boolean
+ public bracketMatching: boolean
+ public closeBrackets: boolean
+ public autocompletion: boolean
+ public rectangularSelection: boolean
+ public crosshairCursor: boolean
+ public highlightActiveLine: boolean
+ public highlightSelectionMatches: boolean
+ public previewImages: boolean
+}
diff --git a/CodeMirror6/NodeLib/src/index.ts b/CodeMirror6/NodeLib/src/index.ts
index 2230ff99..d97c7a35 100644
--- a/CodeMirror6/NodeLib/src/index.ts
+++ b/CodeMirror6/NodeLib/src/index.ts
@@ -8,11 +8,11 @@ import {
indentWithTab, history, historyKeymap, cursorSyntaxLeft, moveLineDown, moveLineUp,
selectSyntaxLeft, selectSyntaxRight, cursorSyntaxRight, selectParentSyntax, indentLess, indentMore,
copyLineUp, copyLineDown, indentSelection, deleteLine, cursorMatchingBracket, toggleComment, toggleBlockComment,
- simplifySelection, insertBlankLine, selectLine, undo, redo, redoSelection, undoSelection
+ simplifySelection, insertBlankLine, selectLine, undo, redo, redoSelection, undoSelection,
} from "@codemirror/commands"
import {
indentUnit, defaultHighlightStyle, syntaxHighlighting, indentOnInput, bracketMatching,
- foldGutter, foldKeymap
+ foldGutter, foldKeymap,
} from "@codemirror/language"
import { autocompletion, completionKeymap, closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete"
import { searchKeymap, highlightSelectionMatches } from "@codemirror/search"
@@ -32,6 +32,7 @@ import {
} from "./CmCommands"
import { images } from "./CmImages"
import { externalLintSource, getExternalLinterConfig } from "./CmLint"
+import { CmSetup } from "./CmSetup"
/**
* Initialize a new CodeMirror instance
@@ -42,7 +43,8 @@ import { externalLintSource, getExternalLinterConfig } from "./CmLint"
export function initCodeMirror(
id: string,
dotnetHelper: any,
- initialConfig: CmConfiguration
+ initialConfig: CmConfiguration,
+ setup: CmSetup
) {
CMInstances[id] = new CmInstance()
CMInstances[id].dotNetHelper = dotnetHelper
@@ -59,28 +61,6 @@ export function initCodeMirror(
CMInstances[id].editableCompartment.of(EditorView.editable.of(initialConfig.editable)),
EditorView.updateListener.of(async (update) => { await updateListenerExtension(dotnetHelper, update) }),
-
- images(),
- linter(async view => await externalLintSource(view, dotnetHelper), getExternalLinterConfig()),
-
- // Basic Setup
- lineNumbers(),
- highlightActiveLineGutter(),
- highlightSpecialChars(),
- history(),
- foldGutter(),
- drawSelection(),
- dropCursor(),
- EditorState.allowMultipleSelections.of(true),
- indentOnInput(),
- syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
- bracketMatching(),
- closeBrackets(),
- autocompletion({}),
- rectangularSelection(),
- crosshairCursor(),
- highlightActiveLine(),
- highlightSelectionMatches(),
keymap.of([
...closeBracketsKeymap,
@@ -121,6 +101,28 @@ export function initCodeMirror(
])
]
+ // Basic Setup
+ if (setup.lineNumbers === true) extensions.push(lineNumbers())
+ if (setup.highlightActiveLineGutter === true) extensions.push(highlightActiveLineGutter())
+ if (setup.highlightSpecialChars === true) extensions.push(highlightSpecialChars())
+ if (setup.history === true) extensions.push(history())
+ if (setup.foldGutter === true) extensions.push(foldGutter())
+ if (setup.drawSelection === true) extensions.push(drawSelection())
+ if (setup.dropCursor === true) extensions.push(dropCursor())
+ if (setup.indentOnInput === true) extensions.push(indentOnInput())
+ if (setup.syntaxHighlighting === true) extensions.push(syntaxHighlighting(defaultHighlightStyle, { fallback: true }))
+ if (setup.bracketMatching === true) extensions.push(bracketMatching())
+ if (setup.closeBrackets === true) extensions.push(closeBrackets())
+ if (setup.autocompletion === true) extensions.push(autocompletion({}))
+ if (setup.rectangularSelection === true) extensions.push(rectangularSelection())
+ if (setup.crosshairCursor === true) extensions.push(crosshairCursor())
+ if (setup.highlightActiveLine === true) extensions.push(highlightActiveLine())
+ if (setup.highlightSelectionMatches === true) extensions.push(highlightSelectionMatches())
+ if (setup.previewImages === true) extensions.push(images())
+
+ extensions.push(linter(async view => await externalLintSource(view, dotnetHelper), getExternalLinterConfig()))
+ if (setup.allowMultipleSelections === true) EditorState.allowMultipleSelections.of(true)
+
CMInstances[id].state = EditorState.create({
doc: initialConfig.doc,
extensions: extensions,
diff --git a/Examples.Common/Example.razor b/Examples.Common/Example.razor
index 1bd51345..295552d7 100644
--- a/Examples.Common/Example.razor
+++ b/Examples.Common/Example.razor
@@ -38,6 +38,7 @@
Language=@Language
AutoFormatMarkdownHeaders=@AutoFormatMarkdownHeaders
LintDocument=@LintDocument
+ Setup=@Setup
style="max-width: 100%; min-height: 40em; "
>
@@ -209,6 +210,12 @@ func main() {{
private ThemeMirrorTheme Theme = ThemeMirrorTheme.OneDark;
private CodeMirrorLanguage Language = CodeMirrorLanguage.Markdown;
private bool AutoFormatMarkdownHeaders = true;
+ private readonly CodeMirrorSetup Setup = new() {
+ HighlightActiveLine = false,
+ LineNumbers = true,
+ HighlightActiveLineGutter = false,
+ HighlightSelectionMatches = false,
+ };
private string ButtonClass(CodeMirrorState state, string docStyleTag) => state.MarkdownStylesAtSelections?.Contains(docStyleTag) == true
? "btn btn-primary"
: "btn";