Skip to content

Commit

Permalink
✨ Implement configuration of which plugins are enabled at startup
Browse files Browse the repository at this point in the history
  • Loading branch information
gaelj committed Dec 23, 2023
1 parent c559008 commit 213acdc
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 28 deletions.
7 changes: 6 additions & 1 deletion CodeMirror6/CodeMirror6Wrapper.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ public partial class CodeMirror6Wrapper : ComponentBase, IAsyncDisposable
/// <value></value>
[Parameter] public Func<string, CancellationToken, Task<List<CodeMirrorDiagnostic>>> LintDocument { get; set; } = (_, _) => Task.FromResult(new List<CodeMirrorDiagnostic>());
/// <summary>
/// The CodeMirror setup
/// </summary>
/// <value></value>
[Parameter] public CodeMirrorSetup Setup { get; set; } = new();
/// <summary>
/// Additional attributes to be applied to the container element
/// </summary>
/// <value></value>
Expand Down Expand Up @@ -214,7 +219,7 @@ public async Task<List<CodeMirrorDiagnostic>> LintingRequestedFromJS(string code
/// </summary>
protected override void OnInitialized()
{
Config = new CodeMirrorConfiguration(
Config = new(
Doc,
Placeholder,
Theme?.ToString(),
Expand Down
12 changes: 10 additions & 2 deletions CodeMirror6/CodeMirrorJsInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
/// <returns></returns>
internal CMSetters PropertySetters => _setters ??= new(_dotnetHelperRef, cm6WrapperComponent.Config, this);
internal CMSetters PropertySetters => _setters ??= new(
_dotnetHelperRef,
cm6WrapperComponent.Config,
cm6WrapperComponent.Setup,
this
);

/// <summary>
/// Methods to invoke JS CodeMirror commands.
/// </summary>
Expand All @@ -64,6 +70,7 @@ public async ValueTask DisposeAsync()
internal class CMSetters(
DotNetObjectReference<CodeMirror6Wrapper> _dotnetHelperRef,
CodeMirrorConfiguration config,
CodeMirrorSetup setup,
CodeMirrorJsInterop cmJsInterop
)
{
Expand All @@ -74,7 +81,8 @@ CodeMirrorJsInterop cmJsInterop
public Task InitCodeMirror() => cmJsInterop.ModuleInvokeVoidAsync(
"initCodeMirror",
_dotnetHelperRef,
config
config,
setup
);

/// <summary>
Expand Down
107 changes: 107 additions & 0 deletions CodeMirror6/Models/CodeMirrorSetup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System.Text.Json.Serialization;

namespace CodeMirror6.Models;

/// <summary>
/// Stores the configuration of a CodeMirror instance (what plugins to load).
/// Cannot be changed after the instance is created.
/// </summary>
public readonly record struct CodeMirrorSetup
{
/// <summary>
/// Default constructor
/// </summary>
public CodeMirrorSetup()
{
}

/// <summary>
/// Whether to show line numbers to the left of the editor.
/// </summary>
[JsonPropertyName("lineNumbers")] public bool LineNumbers { get; init; } = true;

/// <summary>
/// Whether to highlight the line gutter when the cursor is on it.
/// </summary>
[JsonPropertyName("highlightActiveLineGutter")] public bool HighlightActiveLineGutter { get; init; } = true;

/// <summary>
/// Whether to highlight special characters (whitespace, tabs, newlines).
/// </summary>
[JsonPropertyName("highlightSpecialChars")] public bool HighlightSpecialChars { get; init; } = true;

/// <summary>
/// Whether to enable undo/redo.
/// </summary>
[JsonPropertyName("history")] public bool History { get; init; } = true;

/// <summary>
/// Whether to enable code folding.
/// </summary>
[JsonPropertyName("foldGutter")] public bool FoldGutter { get; init; } = true;

/// <summary>
/// Whether to draw the selection when the editor is focused.
/// </summary>
[JsonPropertyName("drawSelection")] public bool DrawSelection { get; init; } = true;

/// <summary>
/// Whether to show a cursor marker when the editor is focused.
/// </summary>
[JsonPropertyName("dropCursor")] public bool DropCursor { get; init; } = true;

/// <summary>
/// Whether to allow multiple selections.
/// </summary>
[JsonPropertyName("allowMultipleSelections")] public bool AllowMultipleSelections { get; init; } = true;

/// <summary>
/// Whether to indent the current line when a character is typed that might cause the line to be re-indented.
/// </summary>
[JsonPropertyName("indentOnInput")] public bool IndentOnInput { get; init; } = true;

/// <summary>
/// Whether to enable syntax highlighting.
/// </summary>
[JsonPropertyName("syntaxHighlighting")] public bool SyntaxHighlighting { get; init; } = true;

/// <summary>
/// Whether to highlight matching brackets.
/// </summary>
[JsonPropertyName("bracketMatching")] public bool BracketMatching { get; init; } = true;

/// <summary>
/// Whether to automatically close brackets.
/// </summary>
[JsonPropertyName("closeBrackets")] public bool CloseBrackets { get; init; } = true;

/// <summary>
/// Whether to enable autocompletion.
/// </summary>
[JsonPropertyName("autocompletion")] public bool Autocompletion { get; init; } = true;

/// <summary>
/// Whether to enable rectangular selection.
/// </summary>
[JsonPropertyName("rectangularSelection")] public bool RectangularSelection { get; init; } = true;

/// <summary>
/// Whether to enable crosshair selection.
/// </summary>
[JsonPropertyName("crossHairSelection")] public bool CrossHairSelection { get; init; } = true;

/// <summary>
/// Whether to highlight the active line.
/// </summary>
[JsonPropertyName("highlightActiveLine")] public bool HighlightActiveLine { get; init; } = true;

/// <summary>
/// Whether to highlight selection matches.
/// </summary>
[JsonPropertyName("highlightSelectionMatches")] public bool HighlightSelectionMatches { get; init; } = true;

/// <summary>
/// Whether to enable preview images.
/// </summary>
[JsonPropertyName("previewImages")] public bool PreviewImages { get; init; } = true;
}
25 changes: 25 additions & 0 deletions CodeMirror6/NodeLib/src/CmSetup.ts
Original file line number Diff line number Diff line change
@@ -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
}
52 changes: 27 additions & 25 deletions CodeMirror6/NodeLib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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,

Expand Down Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions Examples.Common/Example.razor
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
Language=@Language
AutoFormatMarkdownHeaders=@AutoFormatMarkdownHeaders
LintDocument=@LintDocument
Setup=@Setup
style="max-width: 100%; min-height: 40em; "
>
<ContentBefore Context="c">
Expand Down Expand Up @@ -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";
Expand Down

0 comments on commit 213acdc

Please sign in to comment.