[Parameter] public bool HighlightWhitespace { get; set; }
///
+ /// Whether the editor is visible
+ ///
+ ///
+ [Parameter] public bool Visible { get; set; }
+ ///
/// Additional attributes to be applied to the container element
///
///
@@ -183,6 +188,7 @@ public partial class CodeMirror6WrapperInternal : ComponentBase, IAsyncDisposabl
: AllowVerticalResize ? "vertical"
: AllowHorizontalResize ? "horizontal"
: "none";
+ private string VisibleClass => Visible ? string.Empty : " d-none ";
///
/// JavaScript interop instance
diff --git a/CodeMirror6/NodeLib/src/CmColumns.ts b/CodeMirror6/NodeLib/src/CmColumns.ts
index 2b571a05..1a6ad8e5 100644
--- a/CodeMirror6/NodeLib/src/CmColumns.ts
+++ b/CodeMirror6/NodeLib/src/CmColumns.ts
@@ -1,6 +1,7 @@
import { Decoration, ViewPlugin, EditorView, KeyBinding } from "@codemirror/view";
import { Extension, RangeSetBuilder, Transaction } from "@codemirror/state";
import { buildWidget } from "./lib/codemirror-kit";
+import { Diagnostic } from "@codemirror/lint";
function createColumnReplaceDecoration(content: string, from: number) {
@@ -49,6 +50,11 @@ function getRelativeColumnOffset(text: string, separator: string, position: numb
} else if (char === '\\') {
escapeNext = true
offset++
+ } else if (char === '\n' && previous) {
+ previousColumnOffset = offset
+ offset++
+ } else if (char === '\n' && i >= position) {
+ return offset
} else if (char === separator && !inQuotes && previous) {
previousColumnOffset = offset
offset++
@@ -133,6 +139,35 @@ export const getColumnStylingKeymap = (separator: string): KeyBinding[] => [
}},
]
+export function getSeparator(languageName: string) {
+ if (languageName === "CSV") return ','
+ if (languageName === "TSV") return '\t'
+ return null
+}
+
+export async function columnLintSource(view: EditorView, separator: string): Promise {
+ try {
+ const code = view.state.doc.toString()
+ const data = parseCSV(code, separator)
+ const nbCols = data[0].length
+ const errors: Diagnostic[] = []
+ for (let i = 1; i < data.length; i++) {
+ if (data[i].length !== nbCols && data[i].length !== 1) {
+ const message = `Expected ${nbCols} columns, found ${data[i].length}`
+ const from = view.state.doc.line(i + 1).from
+ const to = view.state.doc.line(i + 1).to
+ errors.push({ from, to, message, severity: 'error' })
+ }
+ }
+ if (errors.length > 0)
+ console.log('Linter found:', errors)
+ return errors
+ } catch (error) {
+ console.error('Linter error:', error)
+ return
+ }
+}
+
function moveCursor(view: EditorView, inc: number) {
console.log("moveCursors")
const { state } = view
diff --git a/CodeMirror6/NodeLib/src/CmLint.ts b/CodeMirror6/NodeLib/src/CmLint.ts
index 9c5d9454..6fa94631 100644
--- a/CodeMirror6/NodeLib/src/CmLint.ts
+++ b/CodeMirror6/NodeLib/src/CmLint.ts
@@ -9,7 +9,8 @@ export async function externalLintSource(view: EditorView, dotnetHelper: DotNet.
try {
const code = view.state.doc.toString()
const errors: Diagnostic[] = await dotnetHelper.invokeMethodAsync("LintingRequestedFromJS", code)
- console.log('Linter found:', errors)
+ if (errors.length > 0)
+ console.log('Linter found:', errors)
return errors
} catch (error) {
console.error('Linter error:', error)
diff --git a/CodeMirror6/NodeLib/src/index.ts b/CodeMirror6/NodeLib/src/index.ts
index a8a82c89..c57e67b2 100644
--- a/CodeMirror6/NodeLib/src/index.ts
+++ b/CodeMirror6/NodeLib/src/index.ts
@@ -58,7 +58,7 @@ import { DotNet } from "@microsoft/dotnet-js-interop"
import { markdownTableExtension } from "./CmMarkdownTable"
import { dynamicDiagramsExtension } from "./CmDiagrams"
import { hideMarksExtension } from "./CmHideMarkdownMarks"
-import { getColumnStylingKeymap, columnStylingPlugin } from "./CmColumns"
+import { getColumnStylingKeymap, columnStylingPlugin, columnLintSource, getSeparator } from "./CmColumns"
/**
* Initialize a new CodeMirror instance
@@ -99,13 +99,17 @@ export async function initCodeMirror(
CMInstances[id].emojiReplacerCompartment.of(replaceEmojiExtension(initialConfig.replaceEmojiCodes)),
lastOperationWasUndo,
indentationMarkers(),
- CMInstances[id].lineWrappingCompartment.of(initialConfig.lineWrapping ? EditorView.lineWrapping : []),
+ CMInstances[id].lineWrappingCompartment.of(initialConfig.lineWrapping && initialConfig.languageName !== "CSV" && initialConfig.languageName !== "TSV" ? EditorView.lineWrapping : []),
CMInstances[id].unifiedMergeViewCompartment.of(initialConfig.mergeViewConfiguration ? unifiedMergeView(initialConfig.mergeViewConfiguration) : []),
CMInstances[id].highlightTrailingWhitespaceCompartment.of(initialConfig.highlightTrailingWhitespace ? highlightTrailingWhitespace() : []),
CMInstances[id].highlightWhitespaceCompartment.of(initialConfig.highlightWhitespace ? highlightWhitespace() : []),
CMInstances[id].columnsStylingCompartment.of(
initialConfig.languageName === "CSV" || initialConfig.languageName === "TSV"
- ? [columnStylingPlugin(initialConfig.languageName === "CSV" ? ',' : '\t'), keymap.of(getColumnStylingKeymap(initialConfig.languageName === "CSV" ? ',' : '\t'))]
+ ? [
+ columnStylingPlugin(getSeparator(initialConfig.languageName)),
+ keymap.of(getColumnStylingKeymap(getSeparator(initialConfig.languageName))),
+ linter(async view => columnLintSource(view, getSeparator(initialConfig.languageName))),
+ ]
: []
),
@@ -304,6 +308,7 @@ export async function setLanguage(id: string, languageName: string, fileNameOrEx
const customKeyMap = getLanguageKeyMaps(languageName, fileNameOrExtension)
if (languageName !== "CSV" && languageName !== "TSV")
customKeyMap.push(indentWithTab)
+ const separator = getSeparator(languageName)
CMInstances[id].view.dispatch({
effects: [
@@ -313,7 +318,11 @@ export async function setLanguage(id: string, languageName: string, fileNameOrEx
CMInstances[id].markdownStylingCompartment.reconfigure(autoFormatMarkdownExtensions(id, languageName === 'Markdown')),
CMInstances[id].columnsStylingCompartment.reconfigure(
languageName === "CSV" || languageName === "TSV"
- ? [columnStylingPlugin(languageName === "CSV" ? ',' : '\t'), keymap.of(getColumnStylingKeymap(languageName === "CSV" ? ',' : '\t'))]
+ ? [
+ columnStylingPlugin(separator),
+ keymap.of(getColumnStylingKeymap(separator)),
+ linter(async view => columnLintSource(view, separator)),
+ ]
: []
),
]
diff --git a/Examples.BlazorServer/Examples.BlazorServer.csproj b/Examples.BlazorServer/Examples.BlazorServer.csproj
index d91094cd..2d69aa5a 100644
--- a/Examples.BlazorServer/Examples.BlazorServer.csproj
+++ b/Examples.BlazorServer/Examples.BlazorServer.csproj
@@ -4,7 +4,7 @@
enable
false
enable
- 0.3.1
+ 0.3.2
diff --git a/Examples.BlazorServerInteractive/Examples.BlazorServerInteractive.csproj b/Examples.BlazorServerInteractive/Examples.BlazorServerInteractive.csproj
index 88b0667f..3a0b5eac 100644
--- a/Examples.BlazorServerInteractive/Examples.BlazorServerInteractive.csproj
+++ b/Examples.BlazorServerInteractive/Examples.BlazorServerInteractive.csproj
@@ -4,7 +4,7 @@
enable
enable
false
- 0.3.1
+ 0.3.2
diff --git a/Examples.BlazorWasm/Examples.BlazorWasm.csproj b/Examples.BlazorWasm/Examples.BlazorWasm.csproj
index 75357825..c6c863cf 100644
--- a/Examples.BlazorWasm/Examples.BlazorWasm.csproj
+++ b/Examples.BlazorWasm/Examples.BlazorWasm.csproj
@@ -4,7 +4,7 @@
enable
enable
false
- 0.3.1
+ 0.3.2
diff --git a/Examples.Common/Examples.Common.csproj b/Examples.Common/Examples.Common.csproj
index 218498f0..10364307 100644
--- a/Examples.Common/Examples.Common.csproj
+++ b/Examples.Common/Examples.Common.csproj
@@ -5,7 +5,7 @@
enable
enable
false
- 0.3.1
+ 0.3.2
diff --git a/NEW_CHANGELOG.md b/NEW_CHANGELOG.md
index 349f9f37..05361261 100644
--- a/NEW_CHANGELOG.md
+++ b/NEW_CHANGELOG.md
@@ -1,7 +1,16 @@
+### ⚡️ Improve performance
+
+- Add "Visible" property to allow hiding the editor without destroying it
+
+### ✨ Introduce new features
+
+- Add linting that checks csv column count relative to first line
+- Disable initial setting of line wrapping in csv mode
+
### 🐛 Fix a bug
-- Fix shift-tab in csv not working on last cell
+- Fix tabulating csv columns skipped the last / first ones
-### 🥅 Catch errors
+### 📝 Add or update documentation
-- Silence errors when DOM elements are no longer available in Diagrams (SVG) and file upload (main div)
+- Update README
diff --git a/README.md b/README.md
index d2ace8b2..c801fc9c 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ Visit the [live demo](https://gaelj.github.io/BlazorCodeMirror6/) to see the com
- [x] support C# language
- [x] update doc in dotnet either on text changes or on blur
- [x] diff viewer
+- [x] CSV mode: add column paddings for alignment, navigate columns with tab / shift-tab
- [ ] search & replace toolbar button
- [ ] toolbar with toolbar button template
- [ ] support read-only paragraphs
@@ -47,7 +48,6 @@ Visit the [live demo](https://gaelj.github.io/BlazorCodeMirror6/) to see the com
- [ ] automatic translation
- [ ] deleting a file link deletes the file from the server
- [ ] button (visible when editor is hovered), to copy raw editor content to clipboard
-- [ ] CSV mode
### Markdown specific