Extension List

All extensions are listed below.

import {
    BaseKit,
    Blockquote,
    Bold,
    BulletList,
    Clear,
    CodeBlock,
    Color,
    FontFamily,
    FontSize,
    Fullscreen,
    Heading,
    Highlight,
    History,
    HorizontalRule,
    Image,
    Indent,
    Italic,
    Link,
    OrderedList,
    Strike,
    Table,
    TextAlign,
    Underline,
    Video
} from 'olotap';

Creating Your Own Extensions

In the following example, we will explain how to create an emoji extension for your Olotap editor. If you want to see full code example you can reach our demo repo from here.

├── olotap-demo
├── node-modules
├── public
├── src
│   ├── components
│   │   ├── EmojiActionButton.vue
│   ├── extensions
│       │       ├── emoji.js
│   ├── i18n
│   │   ├── locales
│   │   │   ├── en.js
│   │   │   ├── tr.js
│   ├── index.js
│   ├── plugins
│   │   ├── index.js
│   │   ├── vuetify.js

Create an Emoji Extension

First let's create a our emoji.js in your extensions/ folder.

import { Node } from '@tiptap/core';
import EmojiActionButton from '../components/EmojiActionButton.vue';
import { Context } from "olotap";

export const Emoji = Node.create({
  name: 'emoji',
  addOptions() {
    const { state } = Context.useContext(); // olotap store for i18n and others ...
    return {
      ...this.parent?.(),
      button: ({ editor }) => ({
        component: EmojiActionButton,
        componentProps: {
          editor,
          action: (emoji) => {
            if (typeof emoji === 'string') editor.chain().focus().insertContent(emoji).run();
          },
          isActive: () => editor.isActive('emoji') || false,
          icon: 'mdi-emoticon-outline',
          tooltip: state.t('editor.emoji.tooltip')
        }
      })
    };
  }
});

export default Emoji;

Create the EmojiActionButton.vue Component

At the second step you need to create your button component called EmojiActionButton.vue in your components/ folder. This component will open a menu with the help of vuetify v-menu when the emoji button is pressed and allow you to choose one of the available emoji lists.

<template>
  <action-button
    :icon="icon" 
    :tooltip="tooltip" 
    :disabled="disabled"
    :is-active="isActive"
  >
    <v-menu
      v-model="menu"
      :nudge-left="50"
      :nudge-top="42"
      :close-on-content-click="false"
      transition="scale-transition"
      activator="parent"
    >
      <v-list>
        <v-sheet class="d-flex flex-wrap justify-between ma-1" fluid :max-width="230">
          <template v-for="emoji in getEmojiList" :key="emoji">
            <v-btn flat elevation="0" icon density="compact" @click="addEmoji(emoji)">
              {{ emoji }}
            </v-btn>
          </template>
        </v-sheet>
      </v-list>
    </v-menu>
  </action-button>
</template>

<script>
import { ActionButton } from "olotap";

export default {
  components: {
    ActionButton,
  },
  props: {
    editor: {
      type: Object,
      required: true
    },
    icon: {
      type: String,
      default: undefined
    },
    tooltip: {
      type: String,
      default: undefined
    },
    disabled: {
      type: Boolean,
      default: false
    },
    action: {
      type: Function,
      default: undefined
    },
    isActive: {
      type: Function,
      default: undefined
    }
  },
  data() {
    return {
      menu: false,
      emojiList: [
        "😀", "😁", "😂", "🤣", "😃", "😄", "😅", "😆", "😉", "😊",
        "😎", "😍", "😘", "😗", "😙", "😚", "🤗", "🤩", "🤔", "🤨",
        "😐", "😑", "😶", "🙄", "😏", "😣", "😥", "😮", "🤐", "😯",
        "😪", "😫", "🥱", "😴", "😌", "🤤", "😛", "😜", "😝", "🤪"
      ],
    };
  },
  computed: {
    getEmojiList() {
      return this.emojiList;
    }
  },
  methods: {
    addEmoji(emoji) {
      if (this.action) {
        this.action(emoji);
      }
    }
  }
};
</script>

Adding Translations

Go to i18n/locales/en.js and add a translation for the tooltip that will be shown when the emoji button hovers. Below the example we added translation for emoji.tooltip key.

{
  "locale": {
    "en": "English",
    "tr": "Türkçe"
  },
  "editor": {
    "placeholder": "Enter you content here...",
    "video": {
      "tooltip": "Video",
    },
    "emoji": {
      "tooltip": "Emoji"
    }
  }
}

Calling Your Extension

Now let's look at how to include the emoji extension in your application. Import the emoji file and add it to the extension list as follows.

import i18n from "@/i18n";
import "olotap/classic-editor.css";
import { OlotapEditor, defaultBubbleList, Context } from "olotap";
import Emoji from '@/extensions/emoji';

export default {
  name: 'App',
  components: {
    OlotapEditor
  },
  data() {
    return {
      lang: "en",
      model: {
        contentJson: null,
        contentHtml: null
      },
      errorMessages: [],
      markdownTheme: "default",
      editorKey: "editor_",
      extensions: [],
    };
  },
  created() {
    this.model.contentJson = defaultContentJson;
    this.created = false;
    this.createExtensions();
    this.created = true;
  },
  watch: {
    lang(val) {
      i18n.global.locale.value = val;
      this.createExtensions(); // re create extension for new locale
    }
  },
  computed: {
    isFullscreen() {
      return Context.useContext().state.isFullscreen;
    },
    getEditorKey() {
      return "olotap_" + i18n.global.locale.value;
    }
  },
  methods: {
    createExtensions() {
      const {
        BaseKit,
        History,
        Video,
        Table,
        Blockquote,
        HorizontalRule,
        CodeBlock,
        // Fullscreen,
      } = this.$extensions;

      this.extensions = [
        BaseKit.configure({
          placeholder: {
            placeholder: this.$t("editor.placeholder")
          },
          bubble: {
            // default config
            list: {
              image: [ 'float-left', 'float-none', 'float-right', 'divider', 'image-size-small', 'image-size-medium', 'image-size-large', 'divider', 'textAlign', 'divider', 'image', 'image-aspect-ratio', 'remove'],
              text: ['bold', 'italic', 'underline', 'strike', 'divider', 'color', 'highlight', 'textAlign', 'divider', 'link'],
              video: ['video', 'video-size-small', 'video-size-medium', 'video-size-large', 'remove'],
              codeBlock: ['paste-code', 'change-language', 'copy-code', 'remove'],
              horizontalRule: ['remove'],
              blockquote: ['remove'],
            },
            defaultBubbleList: editor => {
              // You can customize the bubble menu here
              const defaultBubble = defaultBubbleList(editor)
              return defaultBubble; // default customize bubble list
            }
          }
        }),
        History.configure({ divider: true  }),
        Video,
        Table.configure({ divider: true }),
        Blockquote,
        HorizontalRule,
        CodeBlock,
        Emoji
        // Fullscreen,
      ];
    },
    onChange(val) {
      // console.error(val)
    },
  }
};

Result

If everything went well, your emoji button should look like this in the editor.

Olotap