diff --git a/app/src/components/v-menu/v-menu.vue b/app/src/components/v-menu/v-menu.vue
index 09c49bde33..dd3e80b8b8 100644
--- a/app/src/components/v-menu/v-menu.vue
+++ b/app/src/components/v-menu/v-menu.vue
@@ -36,7 +36,15 @@
>
@@ -124,8 +132,7 @@ export default defineComponent({
watch(isActive, (newActive) => {
if (newActive === true) {
- reference.value =
- ((activator.value as HTMLElement)?.childNodes[0] as HTMLElement) || virtualReference.value;
+ reference.value = ((activator.value as HTMLElement)?.childNodes[0] as HTMLElement) || virtualReference.value;
Vue.nextTick(() => {
popper.value = document.getElementById(id.value);
diff --git a/app/src/interfaces/markdown/composables/use-edit.ts b/app/src/interfaces/markdown/composables/use-edit.ts
index b67b263c46..04368a0777 100644
--- a/app/src/interfaces/markdown/composables/use-edit.ts
+++ b/app/src/interfaces/markdown/composables/use-edit.ts
@@ -11,27 +11,33 @@ type Alteration =
| 'heading'
| 'blockquote'
| 'code'
- | 'link';
+ | 'link'
+ | 'table';
type AlterationFunctions = Record<
Alteration,
(
selections: string,
- cursors: { cursorHead: Position; cursorFrom: Position; cursorTo: Position }
+ cursors: { cursorHead: Position; cursorFrom: Position; cursorTo: Position },
+ options?: Record
) => { newSelection: string; newCursor: Position; highlight?: { from: Position; to: Position } }
>;
export function useEdit(codemirror: Ref) {
const alterations: AlterationFunctions = {
- heading(selection, { cursorTo }) {
+ heading(selection, { cursorTo }, options) {
+ const level = options?.level || 3;
+
let newSelection = selection;
let newCursor = cursorTo;
- if (selection.startsWith('# ')) {
- newSelection = selection.substring(2);
+ const prefix = '#'.repeat(level) + ' ';
+
+ if (selection.startsWith(prefix)) {
+ newSelection = selection.substring(prefix.length);
} else {
- newSelection = `# ${selection}`;
- newCursor.ch = newCursor.ch + 2;
+ newSelection = `${prefix}${selection}`;
+ newCursor.ch = newCursor.ch + prefix.length;
}
return { newSelection, newCursor };
@@ -195,11 +201,28 @@ export function useEdit(codemirror: Ref) {
return { newSelection, newCursor, highlight };
},
+ table(selection, cursors, options) {
+ if (!options) return { newSelection: selection, newCursor: cursors.cursorFrom };
+
+ let table: string = '';
+
+ // Headers
+ const headers = [];
+ for (let i = 0; i < options.columns; i++) headers.push('Header');
+ table += `| ${headers.join(' | ')} |`;
+ table += `\n| ${headers.map(() => '------').join(' | ')} |`;
+
+ for (let i = 0; i < options.rows; i++) {
+ table += `\n| ${headers.map(() => 'Cell').join(' | ')} |`;
+ }
+
+ return { newSelection: table, newCursor: cursors.cursorFrom };
+ },
};
return { edit };
- function edit(type: Alteration) {
+ function edit(type: Alteration, options?: Record) {
if (codemirror.value) {
const cursor = codemirror.value.getCursor('head');
const cursorFrom = codemirror.value.getCursor('from');
@@ -210,11 +233,15 @@ export function useEdit(codemirror: Ref) {
const selection = codemirror.value.getSelection();
- const { newSelection, newCursor, highlight } = alterations[type](selection || word, {
- cursorFrom: cloneDeep(selection ? cursorFrom : wordRange.anchor),
- cursorTo: cloneDeep(selection ? cursorTo : wordRange.head),
- cursorHead: cursor,
- });
+ const { newSelection, newCursor, highlight } = alterations[type](
+ selection || word,
+ {
+ cursorFrom: cloneDeep(selection ? cursorFrom : wordRange.anchor),
+ cursorTo: cloneDeep(selection ? cursorTo : wordRange.head),
+ cursorHead: cursor,
+ },
+ options
+ );
if (word && !selection) {
codemirror.value.replaceRange(newSelection, wordRange.anchor, wordRange.head);
diff --git a/app/src/interfaces/markdown/markdown.vue b/app/src/interfaces/markdown/markdown.vue
index 76f20a2a17..02dc6cfa4b 100644
--- a/app/src/interfaces/markdown/markdown.vue
+++ b/app/src/interfaces/markdown/markdown.vue
@@ -1,15 +1,77 @@