From 84bf0f86f8cf90276c96e971d82e184c107100f0 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Fri, 6 Oct 2023 16:07:11 +0200
Subject: [PATCH 1/3] basic actions
---
.../input-markdown.element.ts | 368 +++++++++++++++++-
1 file changed, 361 insertions(+), 7 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
index e9202df63b..0753b304d6 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
@@ -1,4 +1,6 @@
-import { UmbCodeEditorElement, loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
+import { KeyCode, KeyMod } from 'monaco-editor';
+import { UmbMediaPickerContext } from '../../../media/media/components/input-media/input-media.context.js';
+import { UmbCodeEditorController, UmbCodeEditorElement, loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
import { css, html, customElement, query, property } from '@umbraco-cms/backoffice/external/lit';
import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
@@ -12,18 +14,20 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@customElement('umb-input-markdown')
export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
protected getFormElement() {
- return undefined;
+ return this._codeEditor;
}
@property({ type: Boolean })
preview?: boolean;
#isCodeEditorReady = new UmbBooleanState(false);
- isCodeEditorReady = this.#isCodeEditorReady.asObservable();
+ #editor?: UmbCodeEditorController;
@query('umb-code-editor')
_codeEditor?: UmbCodeEditorElement;
+ #mediaPicker = new UmbMediaPickerContext(this);
+
constructor() {
super();
this.#loadCodeEditor();
@@ -32,20 +36,356 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
async #loadCodeEditor() {
try {
await loadCodeEditor();
- this._codeEditor?.editor?.updateOptions({
+ this.#isCodeEditorReady.next(true);
+
+ this.#editor = this._codeEditor?.editor;
+
+ this.#editor?.updateOptions({
lineNumbers: false,
minimap: false,
folding: false,
});
- this.#isCodeEditorReady.next(true);
+ this.#loadActions();
} catch (error) {
console.error(error);
}
}
+ async #loadActions() {
+ // Going to base the keybindings of a Markdown Shortcut plugin https://marketplace.visualstudio.com/items?itemName=robole.markdown-shortcuts#shortcuts
+ // TODO: Find a way to have "double" keybindings (ctrl+m+ctrl+c for `code`, rather than simple ctrl+c as its taken by OS to copy things)
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Heading H1',
+ id: 'h1',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.Digit1],
+ run: () => this._insertAtCurrentLine('#'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Heading H2',
+ id: 'h2',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.Digit2],
+ run: () => this._insertAtCurrentLine('##'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Heading H3',
+ id: 'h3',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.Digit3],
+ run: () => this._insertAtCurrentLine('###'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Heading H4',
+ id: 'h4',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.Digit4],
+ run: () => this._insertAtCurrentLine('####'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Heading H5',
+ id: 'h5',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.Digit5],
+ run: () => this._insertAtCurrentLine('#####'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Heading H6',
+ id: 'h6',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.Digit6],
+ run: () => this._insertAtCurrentLine('######'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Bold Text',
+ id: 'b',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.KeyB],
+ run: () => this._insertBetweenSelection('**', '**', 'Your Bold Text'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Italic Text',
+ id: 'i',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.KeyI],
+ run: () => this._insertBetweenSelection('*', '*', 'Your Italic Text'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Quote',
+ id: 'q',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.KeyQ],
+ run: () => this._insertAtCurrentLine('> '),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Ordered List',
+ id: 'ol',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.KeyO],
+ run: () => this._insertAtCurrentLine('1. '),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Unordered List',
+ id: 'ul',
+ keybindings: [KeyMod.CtrlCmd | KeyCode.KeyU],
+ run: () => this._insertAtCurrentLine('- '),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Code',
+ id: 'code',
+ //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC],
+ run: () => this._insertBetweenSelection('`', '`', 'Code'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Fenced Code',
+ id: 'fenced-code',
+ //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyF],
+ run: () => this._insertBetweenSelection('```', '```', 'Code'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Line',
+ id: 'line',
+ //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC],
+ run: () => this._insertAtCurrentLine('---\n'),
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Link',
+ id: 'link',
+ //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC],
+ run: () => this._insertBetweenSelection('[', '](https://example.com)', 'title'),
+ // TODO: Open in modal
+ });
+ this.#editor?.monacoEditor?.addAction({
+ label: 'Add Image',
+ id: 'image',
+ //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC],
+ run: () => this._insertBetweenSelection('', 'alt text'),
+ // TODO: Open in modal
+ });
+ }
+
+ private _focusEditor(): void {
+ // If we press one of the action buttons manually (which is outside the editor), we need to focus the editor again.
+ this.#editor?.monacoEditor?.focus();
+ }
+
+ private _insertBetweenSelection(startValue: string, endValue: string, placeholder?: string) {
+ this._focusEditor();
+ const selection = this.#editor?.getSelections()[0];
+ if (!selection) return;
+
+ const selectedValue = this.#editor?.getValueInRange({
+ startLineNumber: selection.startLineNumber,
+ endLineNumber: selection.endLineNumber,
+ startColumn: selection.startColumn - startValue.length,
+ endColumn: selection.endColumn + endValue.length,
+ });
+ if (selectedValue?.startsWith(startValue) && selectedValue.endsWith(endValue)) {
+ //Cancel previous insert
+ this.#editor?.select({ ...selection, startColumn: selection.startColumn + startValue.length });
+ this.#editor?.monacoEditor?.executeEdits('', [
+ {
+ range: {
+ startColumn: selection.startColumn - startValue.length,
+ startLineNumber: selection.startLineNumber,
+ endColumn: selection.startColumn,
+ endLineNumber: selection.startLineNumber,
+ },
+ text: '',
+ },
+ {
+ range: {
+ startColumn: selection.endColumn + startValue.length,
+ startLineNumber: selection.startLineNumber,
+ endColumn: selection.endColumn,
+ endLineNumber: selection.startLineNumber,
+ },
+ text: '',
+ },
+ ]);
+ } else {
+ // Insert
+ this.#editor?.insertAtPosition(startValue, {
+ lineNumber: selection.startLineNumber,
+ column: selection.startColumn,
+ });
+ this.#editor?.insertAtPosition(endValue, {
+ lineNumber: selection.endLineNumber,
+ column: selection.endColumn + startValue.length,
+ });
+ }
+
+ // if no text were selected when action fired
+ if (selection.startColumn === selection.endColumn && selection.startLineNumber === selection.endLineNumber) {
+ if (placeholder) {
+ this.#editor?.insertAtPosition(placeholder, {
+ lineNumber: selection.startLineNumber,
+ column: selection.startColumn + startValue.length,
+ });
+ }
+ this.#editor?.select({
+ startLineNumber: selection.startLineNumber,
+ endLineNumber: selection.endLineNumber,
+ startColumn: selection.startColumn + startValue.length,
+ endColumn: selection.startColumn + startValue.length + (placeholder?.length ?? 0),
+ });
+ }
+ }
+
+ private _insertAtCurrentLine(value: string) {
+ this._focusEditor();
+ const selection = this.#editor?.getSelections()[0];
+ if (!selection) return;
+
+ const previousLineValue = this.#editor?.getValueInRange({
+ ...selection,
+ startLineNumber: selection.startLineNumber - 1,
+ });
+ const lineValue = this.#editor?.getValueInRange({ ...selection, startColumn: 1 });
+
+ // Regex: check if the line starts with a positive number followed by dot and a space
+ if (lineValue?.startsWith(value) || lineValue?.match(/^[1-9]\d*\.\s.*/)) {
+ // Cancel previous insert
+ this.#editor?.monacoEditor?.executeEdits('', [
+ {
+ range: {
+ startColumn: 1,
+ startLineNumber: selection.startLineNumber,
+ endColumn: 1 + value.length,
+ endLineNumber: selection.startLineNumber,
+ },
+ text: '',
+ },
+ ]);
+ } else if (value.match(/^[1-9]\d*\.\s.*/) && previousLineValue?.match(/^[1-9]\d*\.\s.*/)) {
+ // Check if the PREVIOUS line starts with a positive number followed by dot and a space. If yes, get that number.
+ const previousNumber = parseInt(previousLineValue, 10);
+ this.#editor?.insertAtPosition(`${previousNumber + 1}. `, {
+ lineNumber: selection.startLineNumber,
+ column: 1,
+ });
+ } else {
+ // Insert
+ this.#editor?.insertAtPosition(value, {
+ lineNumber: selection.startLineNumber,
+ column: 1,
+ });
+ }
+ }
+
+ private _renderBasicActions() {
+ return html`
+ this.#editor?.monacoEditor?.getAction('h1')?.run()}>
+ H
+
+ this.#editor?.monacoEditor?.getAction('b')?.run()}>
+ B
+
+ this.#editor?.monacoEditor?.getAction('i')?.run()}>
+ I
+
+
+
+ this.#editor?.monacoEditor?.getAction('q')?.run()}>
+
+
+ this.#editor?.monacoEditor?.getAction('ol')?.run()}>
+
+
+ this.#editor?.monacoEditor?.getAction('ul')?.run()}>
+
+
+
+
+ this.#editor?.monacoEditor?.getAction('fenced-code')?.run()}>
+
+
+ this.#editor?.monacoEditor?.getAction('line')?.run()}>
+
+
+ this.#editor?.monacoEditor?.getAction('link')?.run()}>
+
+
+ this.#editor?.monacoEditor?.getAction('image')?.run()}>
+
+
+
+
+ {
+ this._focusEditor();
+ this.#editor?.monacoEditor?.trigger('', 'editor.action.quickCommand', '');
+ }}>
+ F1
+
+
`;
+ }
+
+ onKeyPress(e: KeyboardEvent) {
+ if (e.key !== 'Enter' && e.key !== 'Tab') return;
+
+ const selection = this.#editor?.getSelections()[0];
+ if (!selection) return;
+
+ const lineValue = this.#editor?.getValueInRange({ ...selection, startColumn: 1 });
+ if (!lineValue) return;
+
+ if (e.key === 'Enter') {
+ if (lineValue.startsWith('- ') && lineValue.length > 3) {
+ requestAnimationFrame(() => this.#editor?.insert('- '));
+ } else if (lineValue.match(/^[1-9]\d*\.\s.*/) && lineValue.length) {
+ const previousNumber = parseInt(lineValue, 10);
+ requestAnimationFrame(() => this.#editor?.insert(`${previousNumber + 1}. `));
+ }
+ }
+ }
+
render() {
- return html`
-
+ return html` ${this._renderBasicActions()}
+
${this.renderPreview()}`;
}
@@ -63,6 +403,16 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
#actions {
background-color: var(--uui-color-background-alt);
display: flex;
+ gap: var(--uui-size-6);
+ }
+
+ #actions div {
+ display: flex;
+ gap: var(--uui-size-1);
+ }
+
+ #actions div:last-child {
+ margin-left: auto;
}
umb-code-editor {
@@ -70,6 +420,10 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
border-radius: var(--uui-border-radius);
border: 1px solid var(--uui-color-divider-emphasis);
}
+
+ uui-button {
+ width: 50px;
+ }
`,
];
}
From d921a14087920c82f150260fbd905e128d190f16 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Mon, 9 Oct 2023 13:59:31 +0200
Subject: [PATCH 2/3] link and media inserts
---
.../input-markdown.element.ts | 183 ++++++++++++++++--
.../link-picker/link-picker-modal.element.ts | 2 +
2 files changed, 166 insertions(+), 19 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
index 0753b304d6..98b97bf5f6 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
@@ -1,10 +1,15 @@
import { KeyCode, KeyMod } from 'monaco-editor';
-import { UmbMediaPickerContext } from '../../../media/media/components/input-media/input-media.context.js';
import { UmbCodeEditorController, UmbCodeEditorElement, loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
-import { css, html, customElement, query, property } from '@umbraco-cms/backoffice/external/lit';
+import { css, html, customElement, query, property, state } from '@umbraco-cms/backoffice/external/lit';
import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
+import {
+ UMB_LINK_PICKER_MODAL,
+ UMB_MEDIA_TREE_PICKER_MODAL,
+ UMB_MODAL_MANAGER_CONTEXT_TOKEN,
+ UmbModalManagerContext,
+} from '@umbraco-cms/backoffice/modal';
/**
* @element umb-input-markdown
@@ -26,11 +31,17 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
@query('umb-code-editor')
_codeEditor?: UmbCodeEditorElement;
- #mediaPicker = new UmbMediaPickerContext(this);
+ private _modalContext?: UmbModalManagerContext;
+
+ @state()
+ tabSize = 4;
constructor() {
super();
this.#loadCodeEditor();
+ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
+ this._modalContext = instance;
+ });
}
async #loadCodeEditor() {
@@ -45,6 +56,7 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
minimap: false,
folding: false,
});
+ this.tabSize = this.#editor?.monacoModel?.getOptions().tabSize ?? 4;
this.#loadActions();
} catch (error) {
console.error(error);
@@ -52,8 +64,8 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
}
async #loadActions() {
- // Going to base the keybindings of a Markdown Shortcut plugin https://marketplace.visualstudio.com/items?itemName=robole.markdown-shortcuts#shortcuts
// TODO: Find a way to have "double" keybindings (ctrl+m+ctrl+c for `code`, rather than simple ctrl+c as its taken by OS to copy things)
+ // Going with the keybindings of a Markdown Shortcut plugin https://marketplace.visualstudio.com/items?itemName=robole.markdown-shortcuts#shortcuts or perhaps there are keybindings that would make more sense.
this.#editor?.monacoEditor?.addAction({
label: 'Add Heading H1',
id: 'h1',
@@ -106,7 +118,7 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
label: 'Add Quote',
id: 'q',
keybindings: [KeyMod.CtrlCmd | KeyCode.KeyQ],
- run: () => this._insertAtCurrentLine('> '),
+ run: () => this._insertQuote(),
});
this.#editor?.monacoEditor?.addAction({
label: 'Add Ordered List',
@@ -136,20 +148,20 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
label: 'Add Line',
id: 'line',
//keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC],
- run: () => this._insertAtCurrentLine('---\n'),
+ run: () => this._insertLine(),
});
this.#editor?.monacoEditor?.addAction({
label: 'Add Link',
id: 'link',
//keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC],
- run: () => this._insertBetweenSelection('[', '](https://example.com)', 'title'),
+ run: () => this._insertLink(),
// TODO: Open in modal
});
this.#editor?.monacoEditor?.addAction({
label: 'Add Image',
id: 'image',
//keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC],
- run: () => this._insertBetweenSelection('', 'alt text'),
+ run: () => this._insertMedia(),
// TODO: Open in modal
});
}
@@ -159,6 +171,100 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
this.#editor?.monacoEditor?.focus();
}
+ private _insertLink() {
+ const selection = this.#editor?.getSelections()[0];
+ if (!selection) return;
+
+ const selectedValue = this.#editor?.getValueInRange(selection);
+
+ this._focusEditor(); // Focus before opening modal
+ const modalContext = this._modalContext?.open(UMB_LINK_PICKER_MODAL, {
+ index: null,
+ link: { name: selectedValue },
+ config: {},
+ });
+
+ modalContext
+ ?.onSubmit()
+ .then((data) => {
+ const name = this.localize.term('general_name');
+ const url = this.localize.term('general_url');
+
+ this.#editor?.monacoEditor?.executeEdits('', [
+ { range: selection, text: `[${data.link.name || name}](${data.link.url || url})` },
+ ]);
+
+ if (!data.link.name) {
+ this.#editor?.select({
+ startColumn: selection.startColumn + 1,
+ endColumn: selection.startColumn + 1 + name.length,
+ endLineNumber: selection.startLineNumber,
+ startLineNumber: selection.startLineNumber,
+ });
+ } else if (!data.link.url) {
+ this.#editor?.select({
+ startColumn: selection.startColumn + 3 + data.link.name.length,
+ endColumn: selection.startColumn + 3 + data.link.name.length + url.length,
+ endLineNumber: selection.startLineNumber,
+ startLineNumber: selection.startLineNumber,
+ });
+ }
+ })
+ .catch(() => undefined)
+ .finally(() => this._focusEditor());
+ }
+
+ private _insertMedia() {
+ const selection = this.#editor?.getSelections()[0];
+ if (!selection) return;
+
+ const alt = this.#editor?.getValueInRange(selection);
+
+ this._focusEditor(); // Focus before opening modal
+ const modalContext = this._modalContext?.open(UMB_MEDIA_TREE_PICKER_MODAL, {});
+
+ modalContext
+ ?.onSubmit()
+ .then((data) => {
+ const imgUrl = data.selection[0];
+ this.#editor?.monacoEditor?.executeEdits('', [
+ //TODO: media url
+ { range: selection, text: `[${alt || 'alt text'}](TODO: id-${imgUrl || this.localize.term('general_url')})` },
+ ]);
+
+ if (!alt?.length) {
+ this.#editor?.select({
+ startColumn: selection.startColumn + 1,
+ endColumn: selection.startColumn + 9,
+ endLineNumber: selection.startLineNumber,
+ startLineNumber: selection.startLineNumber,
+ });
+ }
+ })
+ .catch(() => undefined)
+ .finally(() => this._focusEditor());
+ }
+
+ private _insertLine() {
+ const selection = this.#editor?.getSelections()[0];
+ if (!selection) return;
+
+ const endColumn = this.#editor?.monacoModel?.getLineMaxColumn(selection.endLineNumber) ?? 1;
+
+ if (endColumn === 1) {
+ this.#editor?.insertAtPosition('---\n', {
+ lineNumber: selection.endLineNumber,
+ column: 1,
+ });
+ } else {
+ this.#editor?.insertAtPosition('\n---\n', {
+ lineNumber: selection.endLineNumber,
+ column: endColumn,
+ });
+ }
+ this._focusEditor();
+ }
+
private _insertBetweenSelection(startValue: string, endValue: string, placeholder?: string) {
this._focusEditor();
const selection = this.#editor?.getSelections()[0];
@@ -170,7 +276,12 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
startColumn: selection.startColumn - startValue.length,
endColumn: selection.endColumn + endValue.length,
});
- if (selectedValue?.startsWith(startValue) && selectedValue.endsWith(endValue)) {
+
+ if (
+ selectedValue?.startsWith(startValue) &&
+ selectedValue.endsWith(endValue) &&
+ selectedValue.length > startValue.length + endValue.length
+ ) {
//Cancel previous insert
this.#editor?.select({ ...selection, startColumn: selection.startColumn + startValue.length });
this.#editor?.monacoEditor?.executeEdits('', [
@@ -203,6 +314,13 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
lineNumber: selection.endLineNumber,
column: selection.endColumn + startValue.length,
});
+
+ this.#editor?.select({
+ startLineNumber: selection.startLineNumber,
+ endLineNumber: selection.endLineNumber,
+ startColumn: selection.startColumn + startValue.length,
+ endColumn: selection.endColumn + startValue.length,
+ });
}
// if no text were selected when action fired
@@ -213,6 +331,7 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
column: selection.startColumn + startValue.length,
});
}
+
this.#editor?.select({
startLineNumber: selection.startLineNumber,
endLineNumber: selection.endLineNumber,
@@ -263,6 +382,28 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
}
}
+ private _insertQuote() {
+ const selection = this.#editor?.getSelections()[0];
+ if (!selection) return;
+
+ let index = selection.startLineNumber;
+ for (index; index <= selection.endLineNumber; index++) {
+ const line = this.#editor?.getValueInRange({
+ startLineNumber: index,
+ endLineNumber: index,
+ startColumn: 1,
+ endColumn: 3,
+ });
+ if (!line?.startsWith('> ')) {
+ this.#editor?.insertAtPosition('> ', {
+ lineNumber: index,
+ column: 1,
+ });
+ }
+ }
+ this._focusEditor();
+ }
+
private _renderBasicActions() {
return html`
3) {
- requestAnimationFrame(() => this.#editor?.insert('- '));
- } else if (lineValue.match(/^[1-9]\d*\.\s.*/) && lineValue.length) {
- const previousNumber = parseInt(lineValue, 10);
- requestAnimationFrame(() => this.#editor?.insert(`${previousNumber + 1}. `));
- }
+ if (lineValue.startsWith('- ') && lineValue.length > 2) {
+ requestAnimationFrame(() => this.#editor?.insert('- '));
+ } else if (lineValue.match(/^[1-9]\d*\.\s.*/) && lineValue.length > 3) {
+ const previousNumber = parseInt(lineValue, 10);
+ requestAnimationFrame(() => this.#editor?.insert(`${previousNumber + 1}. `));
}
}
render() {
+ //TODO: Why is the theme dark in Backoffice, but light in Storybook?
return html` ${this._renderBasicActions()}
-
+
${this.renderPreview()}`;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts
index aece02e1a1..df38f1f184 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts
@@ -153,6 +153,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElementLink to page
this._handleSelectionChange(event, 'document')}
.selection=${[this._selectedKey ?? '']}
@@ -163,6 +164,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElementLink to media
this._handleSelectionChange(event, 'media')}
.selection=${[this._selectedKey ?? '']}
From d89cd3ecd4f1a58ed6248f3735f491b4a6c360d0 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Mon, 9 Oct 2023 14:17:57 +0200
Subject: [PATCH 3/3] remove tabsize
---
.../input-markdown-editor/input-markdown.element.ts | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
index 98b97bf5f6..23d31e1088 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts
@@ -33,9 +33,6 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
private _modalContext?: UmbModalManagerContext;
- @state()
- tabSize = 4;
-
constructor() {
super();
this.#loadCodeEditor();
@@ -56,7 +53,6 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) {
minimap: false,
folding: false,
});
- this.tabSize = this.#editor?.monacoModel?.getOptions().tabSize ?? 4;
this.#loadActions();
} catch (error) {
console.error(error);