diff --git a/src/app/components/fragments/markdown-toolbar/markdown-toolbar.component.ts b/src/app/components/fragments/markdown-toolbar/markdown-toolbar.component.ts
index 316f6b778d11027087b9df04454617072226f37b..9f46ef0fe4fc5f88f28f40250544579de787d9db 100644
--- a/src/app/components/fragments/markdown-toolbar/markdown-toolbar.component.ts
+++ b/src/app/components/fragments/markdown-toolbar/markdown-toolbar.component.ts
@@ -1,6 +1,7 @@
 import { Component, Input } from '@angular/core';
 import { MarkdownHelpDialogComponent } from '../../dialogs/markdown-help-dialog/markdown-help-dialog.component';
 import { MatDialog } from '@angular/material';
+import { Data, GenericDataDialogComponent } from '../../dialogs/generic-data-dialog/generic-data-dialog.component';
 
 @Component({
   selector: 'app-markdown-toolbar',
@@ -9,7 +10,7 @@ import { MatDialog } from '@angular/material';
 })
 /**
  * Component offering markdown action buttons for a textarea.
- * Associated via input attribute containing the textare's HTML id.
+ * Associated via input attribute containing the textarea's HTML id.
  */
 export class MarkdownToolbarComponent {
   /**
@@ -26,15 +27,15 @@ export class MarkdownToolbarComponent {
    * @type {Button[]}
    */
   buttons: Button[] = [
-    new Button('bold', 'Bold', 'format_bold', '**'),
-    new Button('italic', 'Italic', 'format_italic', '*'),
-    new Button('title', 'Title', 'title', '## ', ''),
-    new Button('link', 'Link', 'insert_link', '[', '](https://...)'),
-    new Button('ul', 'Unordered list', 'format_list_bulleted', '* ', ''),
-    new Button('ol', 'Ordered list', 'format_list_numbered', '1. ', ''),
-    new Button('code', 'Code', 'code', '`'),
-    new Button('quote', 'Quote', 'format_quote', '> ', ''),
-    new Button('image', 'Image', 'insert_photo', '![', '](https://...)'),
+    new Button('bold', 'Bold', 'format_bold', '**{{TEXT}}**'),
+    new Button('italic', 'Italic', 'format_italic', '*{{TEXT}}*'),
+    new Button('title', 'Title', 'title', '## {{TEXT}}'),
+    new Button('link', 'Link', 'insert_link', '[{{TEXT}}]({{URL}})'),
+    new Button('ul', 'Unordered list', 'format_list_bulleted', '* {{TEXT}}'),
+    new Button('ol', 'Ordered list', 'format_list_numbered', '1. {{TEXT}}'),
+    new Button('code', 'Code', 'code', '`{{TEXT}}`'),
+    new Button('quote', 'Quote', 'format_quote', '> {{TEXT}}'),
+    new Button('image', 'Image', 'insert_photo', '![{{TEXT}}}]({{URL}})'),
     new Button('help', 'Help', 'help', '')
   ];
 
@@ -57,32 +58,76 @@ export class MarkdownToolbarComponent {
       return;
     }
 
+    // Init formatted string with button's format string, placeholders will be replaced later on
+    let formattedString = button.format;
+    // Get offset for cursor position (set the cursor to the beginning of the surrounded text)
+    const cursorPosition = formattedString.indexOf('{{TEXT}}');
+
     // Handle different buttons here
     switch (button.id) {
       case 'help':
         // Open help dialog and prevent default action
         this.dialog.open(MarkdownHelpDialogComponent);
         break;
+      case 'link':
+      case 'image':
+        // Open a configuration dialog
+        const dialogRef = this.dialog.open(GenericDataDialogComponent, {
+          data: [
+            new Data('TEXT', 'Text', this.getSelectedText()),
+            new Data('URL', 'URL')
+          ]
+        });
+        // Wait for dialog to get closed..
+        dialogRef.afterClosed().subscribe(result => {
+          // Cancel if there is no data (dialog got closed without submitting)
+          if (result === undefined) {
+            return;
+          }
+          // Loop data entries..
+          result.forEach(data => {
+            // Replace placeholder with data provided by the user
+            formattedString = formattedString.replace(`{{${data.id}}}`, data.value);
+          });
+          // Insert the formatted string and update the cursor position
+          this.insertTextAtSelection(formattedString, cursorPosition);
+        });
+        break;
       default:
-        // Insert the text associated to the button
-        this.insertTag(button.textBefore, button.textAfter);
+        // Replace text placeholder with the selected text (keep surrounding tags empty if there was no selection)
+        formattedString = formattedString.replace('{{TEXT}}', this.getSelectedText());
+        // Insert the text associated to the button and update the cursor position
+        this.insertTextAtSelection(formattedString, cursorPosition);
     }
   }
 
-  private insertTag(before: string, after: string) {
+  /**
+   * Get the selected text of the textarea
+   * @returns {string}
+   */
+  private getSelectedText() {
+    return this.textarea.value.slice(this.textarea.selectionStart, this.textarea.selectionEnd);
+  }
+
+  /**
+   * Insert the passed string at the cursor position (replaces selected text if there is any) and update the cursor's position to start
+   * of the inserted text respecting the passed selection offset
+   * @param {string} formattedString
+   * @param {number} selectionOffset
+   */
+  private insertTextAtSelection(text: string, selectionOffset: number) {
     // Get the textarea's text selection positions (no selection when selectionStart == selectionEnd)
     const selectionStart = this.textarea.selectionStart;
     const selectionEnd = this.textarea.selectionEnd;
     // Get textarea's value
-    const text = this.textarea.value;
+    const value = this.textarea.value;
 
     // Insert the action's text at the cursor's position
-    this.textarea.value = [text.slice(0, selectionStart), before, text.slice(selectionStart, selectionEnd),
-      after, text.slice(selectionEnd)].join('');
+    this.textarea.value = [value.slice(0, selectionStart), text, value.slice(selectionEnd)].join('');
     // Focus the textarea
     this.textarea.focus();
     // Calculate the new cursor position (based on the action's text length and the previous cursor position)
-    const cursorPosition = selectionStart + before.length;
+    const cursorPosition = selectionStart + selectionOffset;
     // Set the cursor to the calculated position
     this.textarea.setSelectionRange(cursorPosition, cursorPosition);
   }
@@ -118,34 +163,23 @@ class Button {
    */
   icon: string;
   /**
-   * Text that gets placed in front of the text selection
+   * Format string
+   * TODO:
    */
-  textBefore: string;
-  /**
-   * Text that gets placed behind the text selection
-   */
-  textAfter: string;
+  format: string;
 
   /**
-   * Constructor for creating an instance of {@link Button}, if {@link textAfter} doesn't get passed,
-   * it will be initialized with the value of {@link textBefore}
+   * Constructor for creating an instance of {@link Button}
    *
    * @param {string} id
    * @param {string} label
    * @param {string} icon
-   * @param {string} textBefore
-   * @param {string=} textAfter optional - if not passed will be initialized with the value of {@link textBefore}
+   * @param {string} format
    */
-  constructor(id: string, label: string, icon: string, textBefore: string, textAfter?: string) {
+  constructor(id: string, label: string, icon: string, format: string) {
     this.id = id;
     this.label = label;
     this.icon = icon;
-    this.textBefore = textBefore;
-    // If textAfter is not set, define it with textBefore's value as markdown tags mostly get closed the way they are opened
-    if (textAfter !== undefined) {
-      this.textAfter = textAfter;
-    } else {
-      this.textAfter = textBefore;
-    }
+    this.format = format;
   }
 }