Skip to content
Snippets Groups Projects
Commit 4573c1c7 authored by Marcus Eibrink-Lunzenauer's avatar Marcus Eibrink-Lunzenauer
Browse files

StEP00368: Update des CKEditors auf v5

Closes #1083, #1226, #1154, and #1088

Merge request !641
parent b6e68ead
Branches
No related tags found
No related merge requests found
Showing
with 21256 additions and 11942 deletions
......@@ -22,7 +22,7 @@
"no-await-in-loop": "error",
"no-promise-executor-return": "error",
"require-atomic-updates": "error",
"max-nested-callbacks": ["error", 3],
"max-nested-callbacks": ["error", 4],
"no-return-await": "error",
"prefer-promise-reject-errors": "error"
}
......
......@@ -120,4 +120,333 @@ class WysiwygController extends AuthenticatedController
}
$this->render_json($response); // send HTTP response to client
}
/**
* Store or retrieve settings.
*
* Settings are further subdivided into groups. For example: global,
* seminar- and user-specific settings (see below).
*
* HTTP GET
* returns a JSON object with current settings.
*
* HTTP PUT
* expects a JSON object with settings to store and returns
* updated settings as a JSON object. Some settings are read-only,
* others can only be set if the user has the necessary access level.
*
* Currently only the following basic features are supported:
*
* HTTP GET wysiwyg/settings/global
* Always returns:
* {
* "upload": {
* "permission": "autor",
* "folder": {
* "name": "Wysiwyg Uploads",
* "description": "Vom WYSIWYG Editor hochgeladene Dateien."
* }
* }
* }
* }
*
* HTTP GET wysiwyg/settings/users/current
* Always returns following setting for the authenticated user:
* {
* "disabled": false | true
* }
*
* HTTP PUT wysiwyg/settings/users/current
* Allows only to reset or set the disabled state with:
* {
* "disabled": false | true
* }
*
* Below is a specification of possible future extensions to this
* interface, that are based on current feature requests by users
* (mainly people from ELMO, ELAN and ECULT).
*
* wysiwyg/settings/global
* Common settings for all WYSIWYG editors throughout Stud.IP.
* wysiwyg/settings/seminars
* Settings of all seminars.
* Listed seminars depend on access level:
* root => full access to all seminars
* dozent, tutor of a seminar => full access to those seminars
* others => read-access to seminars they are a member of
* wysiwyg/settings/seminars/ID
* Settings of the seminar with the given ID.
* Access permissions: see above.
* wysiwyg/settings/seminars/ID/users
* Seminar's settings for all its users.
* Access permissions: see above.
* wysiwyg/settings/seminars/ID/users/ID
* Seminar's settings for a specific user in that seminar.
* Access permissions: see above.
* wysiwyg/settings/users
* Settings of all users.
* Listed users depend on access level:
* root => full access to all users
* not root => full access to own settings only
* wysiwyg/settings/users/ID
* Settings of the user with the given ID.
* Access permissions: see above.
* wysiwyg/settings/users/ID/seminars
* User's settings for all seminars the user is a member of.
* Access permissions: see above.
* wysiwyg/settings/users/ID/seminars/ID
* User's settings for the seminar with the given ID.
* Access permissions: see above.
*
* The difference of seminar's settings for a user and user's settings
* for a seminar:
*
* A seminar's teacher may want to set the upload directory for each user
* to a separate one, which should not be overwritable by a user, in
* order to make sure that users cannot see other users uploads (there
* are other ways to do this, but it's just an example).
*
* A user might want to have a specific upload directory in order to
* collaborate better with other users in the same seminar (e.g. when
* students form a study group).
*
* For example the ELMO module needs such settings.
*
* JSON scheme for access to wysiwyg/settings:
* {
* "global": { "SETTING": ..., ... },
* "seminars": {
* "ID": {
* "users": { "ID": {...}, ... },
* "SETTING": ...,
* ...
* },
* "ID": {...},
* ...
* },
* "users": {
* "ID": {
* "seminars": { "ID": {...}, ... },
* "SETTING": ...,
* ...
* },
* "ID": {...},
* ...
* }
* }
*
* When accessing a sub-resource that resource's branch of the JSON scheme
* will be returned.
*/
public function settings_action()
{
try {
if (!Request::isGet() && !Request::isPut()) {
throw new WysiwygHttpExceptionMethodNotAllowed(
_('Nur die HTTP-Methoden GET und PUT sind erlaubt.')
);
}
$arguments = func_get_args();
$settingsGroup = array_shift($arguments);
if (Request::isPut()) {
$this->setSettings($settingsGroup, $arguments);
}
$this->render_json($this->objectToArray(
$this->getSettings($settingsGroup, $arguments)
));
} catch (WysiwygHttpException $e) {
$this->set_status($e->getCode());
$this->set_content_type('text/plain; charset=utf-8');
$this->render_text($e->getMessage());
}
}
public function a11yhelp_action()
{
// nothing to do
PageLayout::setTitle(_('Hilfe zur Bedienung des Editors'));
}
/**
* Set WYSIWYG settings for a specific group.
*
* Dummy implementation: Currently only accepts setting the
* disabled flag for wysiwyg/settings/users/current.
*
* The HTTP request's body must contain a JSON document of the form:
* {
* "disabled": true | false
* }
*
* If the JSON contains other additional values they will be ignored.
*
* @param string $group Must be set to 'users'.
* @param array $arguments Must contain exactly one entry: 'current'.
*/
private function setSettings($group, $arguments) {
$user = array_shift($arguments);
if ($group !== 'users' || $user !== 'current') {
throw new WysiwygHttpExceptionForbidden(
_('Zugriff verweigert')
);
}
$subgroup = array_shift($arguments);
if (($subgroup !== null && $subgroup !== '') || count($arguments) > 0) {
throw new WysiwygHttpExceptionNotFound(
_('Die Benutzereinstellungen enthalten keine Untergruppen.')
);
}
$data = json_decode(file_get_contents('php://input'));
if (isset($data->disabled)) {
$config = $GLOBALS['user']->cfg;
//$config->WYSIWYG_DISABLED = (boolean)$data->disabled;
$config->store(
'WYSIWYG_DISABLED',
(boolean)$data->disabled
);
} else {
throw new WysiwygHttpExceptionBadRequest(
_('Die Anfrage enthält ungültige Werte.')
);
}
// all unknown parameters are ignored
}
/**
* Return WYSIWYG settings for a specific group.
*
* @param $group string The requested settings group: 'user', 'seminar',
* 'global' or 'all'. If the group is set to 'all' then all levels will be
* returned. If the group is unknown an error will be thrown.
*
* @return object Settings for the requested group.
*/
private function getSettings($group, $arguments)
{
switch ($group) {
case null: return $this->getAllSettings();
case 'global': return $this->getGlobalSettings($arguments);
case 'users': return $this->getUserSettings($arguments);
}
throw new WysiwygHttpExceptionNotFound(
_('Die angeforderte Gruppe von Einstellungen existiert nicht.')
);
}
/**
* Return all WYSIWYG settings.
*
* Returns an object with properties named after settings groups,
* containing the respective group's settings. For example:
*
* {
* "global": {...}
* "seminars": {...},
* "users": {...},
* }
*
* @return object All settings.
*/
private function getAllSettings()
{
$settings = new stdClass;
$settings->global = $this->getGlobalSettings();
$settings->users = $this->getUserSettings();
return $settings;
}
/**
* Return global WYSIWYG settings.
*
* @return object Global settings.
*/
private function getGlobalSettings($arguments = [])
{
$subgroup = array_shift($arguments);
if (($subgroup !== null && $subgroup !== '') || count($arguments) > 0) {
throw new WysiwygHttpExceptionNotFound(_('Die globalen Einstellungen enthalten keine Untergruppen.'));
}
$settings = new stdClass;
$settings->disabled = !\Config::get()->WYSIWYG;
$settings->upload = new stdClass;
$settings->upload->permission = self::UPLOAD_PERMISSION;
$settings->upload->folder = new stdClass;
$settings->upload->folder->name = self::FOLDER_NAME;
$settings->upload->folder->description = self::FOLDER_DESCRIPTION;
return $settings;
}
/**
* Return current user's WYSIWYG settings.
*
* @return object User's settings.
*/
private function getUserSettings($arguments = [])
{
// NOTE simulate a list of users containing only the current
// user until this is implemented correctly
$settings = new stdClass;
$settings->current = $this->getCurrentUserSettings();
$userId = array_shift($arguments);
if ($userId === null || $userId === '' && count($arguments) === 0) {
return $settings;
}
if ($userId === 'current') {
$subgroup = array_shift($arguments);
if (($subgroup !== null && $subgroup !== '') || count($arguments) > 0) {
throw new WysiwygHttpExceptionNotFound(
_('Die Benutzereinstellungen enthalten keine Untergruppen.')
);
}
return $settings->current;
}
throw new WysiwygHttpExceptionForbidden(
_('Zugriff verweigert.')
);
}
/**
* Return current user's WYSIWYG settings.
*
* @return object User's settings.
*/
public function getCurrentUserSettings()
{
$config = $GLOBALS['user']->cfg;
$settings = new stdClass;
$settings->disabled = (boolean)$config->WYSIWYG_DISABLED;
return $settings;
}
/**
* Recursively convert objects to associative arrays.
*
* Workaround for broken StudipController::render_json.
*
* If the data is neither object nor array then it will be
* returned unchanged.
*
* @param mixed $data Data to convert.
*
* @return mixed Converted data.
*/
private function objectToArray($data)
{
if (gettype($data) === 'object') {
$data = (array)$data;
}
if (gettype($data) === 'array') {
foreach ($data as $key => $value) {
$data[$key] = $this->objectToArray($value);
}
}
return $data;
}
}
<h3><?= _('Editorwerkzeugleiste') ?></h3>
<p>
<?= _(
'Zum Zugriff auf die Elemente der Werkzeugleiste des Editors drücken Sie Alt+F10. Gehen Sie zum nächsten oder vorherigen Element mit der rechten oder linken Pfeiltaste. Drücken Sie die Leertaste oder Eingabetaste, um ein Element in der Werkzeugleiste zu aktivieren.'
) ?>
</p>
<h3><?= _('Editor-Kontextmenü (Rechtsklickmenü)') ?></h3>
<p>
<?= _(
'Drücken Sie Umschalt+F10 / Umschalt+Strg+F10 oder die Anwendungstaste um das Kontextmenü zu öffnen. Man kann die Pfeiltasten zur Navigation durch das Menü benutzen. Mit der Leertaste oder der Enter-Taste kann man den Menüpunkt aufrufen. Das Kontextmenü kann mit der Escape-Taste geschlossen werden.'
) ?></p>
<h3><?= _('Befehle') ?></h3>
<ul>
<li><?= _('Rückgängig-Befehl: Drücken Sie Strg+Z') ?></li>
<li><?= _('Wiederherstellen-Befehl: Drücken Sie Strg+Y') ?></li>
<li><?= _('Fettschrift-Befehl: Drücken Sie Strg+B') ?></li>
<li><?= _('Kursiv-Befehl: Drücken Sie Strg+I') ?></li>
<li><?= _('Unterstreichen-Befehl: Drücken Sie Strg+U') ?></li>
<li><?= _('Link-Befehl: Drücken Sie Strg+K') ?></li>
<li><?= _('Eingabehilfen: Drücken Sie Alt+0 zum Aufrufen dieses Dialoges') ?></li>
</ul>
......@@ -63,7 +63,7 @@ $lang_attr = str_replace('_', '-', $_SESSION['_language']);
<?= PageLayout::getHeadElements() ?>
<script>
window.STUDIP.editor_enabled = <?= json_encode((bool) Studip\Markup::editorEnabled()) ?> && CKEDITOR.env.isCompatible;
window.STUDIP.editor_enabled = <?= json_encode((bool) Studip\Markup::editorEnabled()) ?>;
</script>
</head>
......
This diff is collapsed.
......@@ -27,6 +27,32 @@
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"@babel/register": "^7.12.1",
"@ckeditor/ckeditor5-alignment": "32.0.0",
"@ckeditor/ckeditor5-autoformat": "32.0.0",
"@ckeditor/ckeditor5-basic-styles": "32.0.0",
"@ckeditor/ckeditor5-build-classic": "32.0.0",
"@ckeditor/ckeditor5-build-decoupled-document": "32.0.0",
"@ckeditor/ckeditor5-build-inline": "32.0.0",
"@ckeditor/ckeditor5-code-block": "32.0.0",
"@ckeditor/ckeditor5-dev-utils": "^28.1.1",
"@ckeditor/ckeditor5-dev-webpack-plugin": "^28.1.1",
"@ckeditor/ckeditor5-essentials": "32.0.0",
"@ckeditor/ckeditor5-find-and-replace": "32.0.0",
"@ckeditor/ckeditor5-font": "32.0.0",
"@ckeditor/ckeditor5-horizontal-line": "32.0.0",
"@ckeditor/ckeditor5-html-support": "32.0.0",
"@ckeditor/ckeditor5-indent": "32.0.0",
"ckeditor5-math": "32.0.0",
"@ckeditor/ckeditor5-paragraph": "32.0.0",
"@ckeditor/ckeditor5-remove-format": "32.0.0",
"@ckeditor/ckeditor5-select-all": "32.0.0",
"@ckeditor/ckeditor5-source-editing": "32.0.0",
"@ckeditor/ckeditor5-special-characters": "32.0.0",
"@ckeditor/ckeditor5-table": "32.0.0",
"@ckeditor/ckeditor5-theme-lark": "32.0.0",
"@ckeditor/ckeditor5-typing": "32.0.0",
"@ckeditor/ckeditor5-upload": "32.0.0",
"@ckeditor/ckeditor5-vue2": "^1.0.5",
"@elan-ev/reststate-vuex": "~1.0.5",
"@fullcalendar/core": "^4.3.1",
"@fullcalendar/daygrid": "^4.3.0",
......@@ -79,6 +105,7 @@
"postcss-less": "^6.0.0",
"postcss-loader": "4.1.0",
"postcss-scss": "^4.0.4",
"raw-loader": "^4.0.2",
"sanitize-html": "^2.7.0",
"sass": "^1.29.0",
"sass-loader": "^10.1.0",
......@@ -104,9 +131,9 @@
"vue-typer": "^1.2.0",
"vuedraggable": "^2.24.3",
"vuex": "^3.6.2",
"webpack": "5.61",
"webpack-cli": "^4.7.0",
"webpack-dev-server": "4.4.0",
"webpack": "^5.70.0",
"webpack-cli": "4.2.0",
"webpack-dev-server": "3.11.0",
"webpack-merge": "5.4.0"
},
"babel": {
......
This diff is collapsed.
......@@ -14,14 +14,14 @@ $(document).on('click', '#wiki button[name="submit-and-edit"]', function(event)
data = {},
form_data,
i,
id,
wysiwyg_editor = false;
if (STUDIP.editor_enabled) {
id = $('textarea[name="body"]', form).attr('id');
wysiwyg_editor = CKEDITOR.instances[id];
wysiwyg_editor.setData(STUDIP.wysiwyg.markAsHtml(wysiwyg_editor.getData()));
wysiwyg_editor.updateElement();
const textarea = $('textarea[name="body"]', form).get(0);
if (textarea) {
wysiwyg_editor = STUDIP.wysiwyg.getEditor(textarea);
wysiwyg_editor.sourceElement.value = STUDIP.wysiwyg.markAsHtml(wysiwyg_editor.getData());
}
}
form_data = form.serializeArray();
......
......@@ -13,49 +13,7 @@ STUDIP.domReady(() => {
// hidden, the editor does not function properly; therefore attach to
// visible textareas only
function replaceVisibleTextareas() {
$('textarea.wysiwyg').each(function() {
var editor = CKEDITOR.dom.element.get(this).getEditor();
if (!editor && $(this).is(':visible')) {
STUDIP.wysiwyg.replace(this);
} else if (editor && editor.container && $(editor.container.$).is(':hidden')) {
editor.destroy(true);
}
});
}
// customize existing dialog windows
CKEDITOR.on('dialogDefinition', function(ev) {
var dialogName = ev.data.name,
dialogDefinition = ev.data.definition;
if (dialogName == 'table') {
var infoTab = dialogDefinition.getContents('info');
infoTab.get('txtBorder')['default'] = '';
infoTab.get('txtWidth')['default'] = '';
infoTab.get('txtCellSpace')['default'] = '';
infoTab.get('txtCellPad')['default'] = '';
var advancedTab = dialogDefinition.getContents('advanced');
advancedTab.get('advCSSClasses')['default'] = 'content';
}
});
});
// Hotfix for Dialogs
$.widget( "ui.dialog", $.ui.dialog, {
// jQuery UI v1.11+ fix to accommodate CKEditor (and other iframed content) inside a dialog
// @see http://bugs.jqueryui.com/ticket/9087
// @see http://dev.ckeditor.com/ticket/10269
_allowInteraction: function( event ) {
return this._super( event ) ||
// addresses general interaction issues with iframes inside a dialog
event.target.ownerDocument !== this.document[ 0 ] ||
// addresses interaction issues with CKEditor's dialog windows and iframe-based dropdowns in IE
!!$( event.target ).closest( ".cke_dialog, .cke_dialog_background_cover, .cke" ).length;
const textareas = document.querySelectorAll('textarea.wysiwyg');
textareas.forEach(STUDIP.wysiwyg.replace);
}
});
......@@ -74,6 +74,15 @@ STUDIP.loadChunk = (function () {
);
break;
case 'wysiwyg':
promise = import(
/* webpackChunkName: "vue.js" */
'./chunks/wysiwyg'
).then(({default: ClassicEditor}) => {
return ClassicEditor;
});
break;
default:
promise = Promise.reject(new Error(`Unknown chunk: ${chunk}`));
}
......
......@@ -8,6 +8,7 @@ import PortalVue from 'portal-vue';
import BaseComponents from '../../../vue/base-components.js';
import BaseDirectives from "../../../vue/base-directives.js";
import StudipStore from "../../../vue/store/StudipStore.js";
import CKEditor from '@ckeditor/ckeditor5-vue2';
// Setup gettext
Vue.use(GetTextPlugin, getVueConfig());
......@@ -42,6 +43,7 @@ Vue.mixin({
},
});
Vue.use(CKEditor);
// Define createApp function
function createApp(options, ...args) {
......
/* ckeditor official */
import Alignment from '@ckeditor/ckeditor5-alignment/src/alignment';
import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote';
import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold';
import ClassicEditorBase from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Code from '@ckeditor/ckeditor5-basic-styles/src/code';
import CodeBlock from '@ckeditor/ckeditor5-code-block/src/codeblock';
import EasyImagePlugin from '@ckeditor/ckeditor5-easy-image/src/easyimage';
import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials';
import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
import FindAndReplace from '@ckeditor/ckeditor5-find-and-replace/src/findandreplace';
import FontBackgroundColor from '@ckeditor/ckeditor5-font/src/fontbackgroundcolor.js';
import FontColor from '@ckeditor/ckeditor5-font/src/fontcolor.js';
import GeneralHtmlSupport from '@ckeditor/ckeditor5-html-support/src/generalhtmlsupport';
import HeadingPlugin from '@ckeditor/ckeditor5-heading/src/heading';
import HorizontalLine from '@ckeditor/ckeditor5-horizontal-line/src/horizontalline';
import ImagePlugin from '@ckeditor/ckeditor5-image/src/image';
import ImageUploadPlugin from '@ckeditor/ckeditor5-image/src/imageupload';
import ImageCaptionPlugin from '@ckeditor/ckeditor5-image/src/imagecaption';
import ImageStylePlugin from '@ckeditor/ckeditor5-image/src/imagestyle';
import ImageToolbarPlugin from '@ckeditor/ckeditor5-image/src/imagetoolbar';
import Indent from '@ckeditor/ckeditor5-indent/src/indent';
import IndentBlock from '@ckeditor/ckeditor5-indent/src/indentblock';
import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic';
import LanguageDe from '@ckeditor/ckeditor5-build-classic/build/translations/de.js';
import LinkPlugin from '@ckeditor/ckeditor5-link/src/link';
import List from '@ckeditor/ckeditor5-list/src/list';
import ListProperties from '@ckeditor/ckeditor5-list/src/listproperties';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import RemoveFormat from '@ckeditor/ckeditor5-remove-format/src/removeformat.js';
import SelectAll from '@ckeditor/ckeditor5-select-all/src/selectall';
import SourceEditing from '@ckeditor/ckeditor5-source-editing/src/sourceediting';
import SpecialCharacters from '@ckeditor/ckeditor5-special-characters/src/specialcharacters.js';
import SpecialCharactersCurrency from '@ckeditor/ckeditor5-special-characters/src/specialcharacterscurrency.js';
import SpecialCharactersEssentials from '@ckeditor/ckeditor5-special-characters/src/specialcharactersessentials.js';
import SpecialCharactersLatin from '@ckeditor/ckeditor5-special-characters/src/specialcharacterslatin.js';
import SpecialCharactersMathematical from '@ckeditor/ckeditor5-special-characters/src/specialcharactersmathematical.js';
import SpecialCharactersText from '@ckeditor/ckeditor5-special-characters/src/specialcharacterstext.js';
import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough.js';
import Subscript from '@ckeditor/ckeditor5-basic-styles/src/subscript.js';
import Superscript from '@ckeditor/ckeditor5-basic-styles/src/superscript.js';
import Table from '@ckeditor/ckeditor5-table/src/table.js';
import TableCaption from '@ckeditor/ckeditor5-table/src/tablecaption.js';
import TableCellProperties from '@ckeditor/ckeditor5-table/src/tablecellproperties';
import TableProperties from '@ckeditor/ckeditor5-table/src/tableproperties';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar.js';
import TextTransformation from '@ckeditor/ckeditor5-typing/src/texttransformation';
import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline.js';
/* ckeditor third party */
import Mathematics from 'ckeditor5-math/src/math';
/* ckeditor elan */
import StudipA11YDialog, { updateVoiceLabel } from '../cke/studip-a11y-dialog/a11y-dialog.js';
import StudipBlockQuote from '../cke/studip-quote/StudipBlockQuote.js';
import StudipUpload from '../cke/StudipUpload.js';
import { StudipSettings } from '../cke/StudipSettings.js';
import StudipWikiLink from '../cke/wiki-link/wiki-link.js';
import SpecialCharactersEmojiFood from '../cke/special_characters/SpecialCharactersEmojiFood.js';
import SpecialCharactersEmojiNature from '../cke/special_characters/SpecialCharactersEmojiNature.js';
import SpecialCharactersEmojiObjects from '../cke/special_characters/SpecialCharactersEmojiObjects.js';
import SpecialCharactersEmojiPeople from '../cke/special_characters/SpecialCharactersEmojiPeople.js';
import SpecialCharactersEmojiSport from '../cke/special_characters/SpecialCharactersEmojiSport.js';
import SpecialCharactersEmojiSymbols from '../cke/special_characters/SpecialCharactersEmojiSymbols.js';
import SpecialCharactersEmojiTraffic from '../cke/special_characters/SpecialCharactersEmojiTraffic.js';
import SpecialCharactersGreek from '../cke/special_characters/SpecialCharactersGreek.js';
import '../../stylesheets/studip-cke-ui.css';
export default class ClassicEditor extends ClassicEditorBase {}
ClassicEditor.builtinPlugins = [
ImageUploadPlugin,
Alignment,
Autoformat,
BlockQuote,
BoldPlugin,
Code,
CodeBlock,
EssentialsPlugin,
FindAndReplace,
FontColor,
FontBackgroundColor,
GeneralHtmlSupport,
HeadingPlugin,
HorizontalLine,
ImageCaptionPlugin,
ImagePlugin,
ImageStylePlugin,
ImageToolbarPlugin,
Indent,
IndentBlock,
ItalicPlugin,
LinkPlugin,
ListProperties,
Mathematics,
Paragraph,
RemoveFormat,
SelectAll,
SourceEditing,
SpecialCharacters,
SpecialCharactersCurrency,
SpecialCharactersEmojiPeople,
SpecialCharactersEmojiNature,
SpecialCharactersEmojiFood,
SpecialCharactersEmojiSport,
SpecialCharactersEmojiTraffic,
SpecialCharactersEmojiObjects,
SpecialCharactersEmojiSymbols,
SpecialCharactersEssentials,
SpecialCharactersGreek,
SpecialCharactersLatin,
SpecialCharactersMathematical,
SpecialCharactersText,
Strikethrough,
StudipBlockQuote,
StudipUpload,
Subscript,
Superscript,
Table,
TableCaption,
TableCellProperties,
TableProperties,
TableToolbar,
TextTransformation,
Underline,
FileRepository,
StudipA11YDialog,
StudipSettings,
StudipWikiLink,
];
const customColorPalette = [
{ color: '#000000' },
{ color: '#6c737a' }, //75%
{ color: '#a7abaf' }, //45%
{ color: '#c4c7c9' }, //30%
{ color: '#ffffff', hasBorder: true },
{ color: '#cb1800' }, //red
{ color: '#f26e00' }, //pumpkin
{ color: '#ffbd33' }, //yellow
{ color: '#8bbd40' }, // apple green
{ color: '#00962d' }, //green
{ color: '#41afaa' }, //verdigris
{ color: '#a9b6cb' }, // blue 40%
{ color: '#28497c' }, // blue
{ color: '#bf5796' }, // mulberry
{ color: '#8656a2' }, // royal purple
];
ClassicEditor.defaultConfig = {
toolbar: {
items: [
'undo',
'redo',
'|',
'findAndReplace',
'selectAll',
'|',
'specialCharacters',
'horizontalLine',
'|',
'insertBlockQuote',
'splitBlockQuote',
'removeBlockQuote',
'|',
'link',
'insertTable',
'uploadImage',
'codeBlock',
'math',
'studip-wiki',
'|',
'sourceEditing',
'-',
'heading',
'|',
'bold',
'italic',
'underline',
'strikethrough',
'subscript',
'superscript',
'code',
'removeFormat',
'|',
'fontColor',
'fontBackgroundColor',
'|',
'alignment:left',
'alignment:right',
'alignment:center',
'alignment:justify',
'|',
'bulletedList',
'numberedList',
'|',
'outdent',
'indent',
'|',
'studipSettings',
'open-a11y-dialog',
],
shouldNotGroupWhenFull: true,
},
fontColor: {
colors: customColorPalette,
},
fontBackgroundColor: {
colors: customColorPalette,
},
image: {
toolbar: [
'imageStyle:inline',
'imageStyle:block',
'imageStyle:side',
'|',
'toggleImageCaption',
'imageTextAlternative',
],
},
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
{ model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
{ model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' },
{ model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' },
{ model: 'heading5', view: 'h5', title: 'Heading 5', class: 'ck-heading_heading5' },
{ model: 'heading6', view: 'h6', title: 'Heading 6', class: 'ck-heading_heading6' },
{ model: 'code', view: 'code', title: 'Code', class: 'ck-heading_code' },
],
},
table: {
contentToolbar: [
'toggleTableCaption',
'tableColumn',
'tableRow',
'mergeTableCells',
'tableCellProperties',
'tableProperties',
],
tableProperties: {
borderColors: customColorPalette,
backgroundColors: customColorPalette,
},
tableCellProperties: {
borderColors: customColorPalette,
backgroundColors: customColorPalette,
},
},
typing: {
transformations: {
remove: ['quotes'],
extra: [
{ from: ':)', to: '🙂' },
{ from: '(:', to: '🙃' },
{ from: ':(', to: '🙁' },
{ from: ':D', to: '😄' },
{ from: 'C:', to: '😍' },
{ from: ':P', to: '😜' },
{ from: 'XD', to: '😂' },
{ from: ':O', to: '😮' },
{ from: '=O', to: '😲' },
{ from: ';)', to: '😉' },
{ from: ':S', to: '😟' },
{ from: ':=(', to: '😭' },
{ from: ":'(", to: '😢' },
{ from: ':$', to: '😳' },
{ from: ':X', to: '🤐' },
{ from: '8)', to: '😎' },
{ from: '<3', to: '❤️' },
{ from: ':*', to: '😘' },
{ from: ':+1:', to: '👍' },
{ from: ':-1:', to: '👎' },
{ from: ':rofl:', to: '🤣' },
{ from: ':heart_eyes:', to: '😍' },
{ from: ':sob:', to: '😭' },
{ from: ':cry:', to: '😢' },
{ from: ':fire:', to: '🔥' },
],
},
},
list: {
properties: {
styles: true,
startIndex: true,
reversed: true,
},
},
math: {
engine: 'mathjax',
outputType: 'span',
forceOutputType: false,
enablePreview: false,
},
link: {
defaultProtocol: 'https://',
decorators: {
addTargetToExternalLinks: {
mode: 'automatic',
callback: url => /^(https?:)?\/\//.test( url ),
attributes: {
target: '_blank',
rel: 'noopener noreferrer'
}
}
}
},
language: 'de',
htmlSupport: {
allow: [
/* HTML features to allow */
{
name: 'div',
classes: 'author',
},
],
disallow: [
/* HTML features to disallow */
],
},
};
updateVoiceLabel();
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import { createDropdown, ButtonView, View } from 'ckeditor5/src/ui';
import { $gettext } from '../lib/gettext.js';
const settings = {
url: STUDIP.URLHelper.resolveURL('dispatch.php/wysiwyg/settings/users/current'),
save: function (data) {
return $.ajax({
url: this.url,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(data),
});
},
};
const gearsIcon =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54 54"><path d="M50.58,22.76l-.95-.4a3.12,3.12,0,0,1,0-5.8l.95-.41h0a.69.69,0,0,0,.37-.89h0l-.7-1.69-1.13-2.75A.71.71,0,0,0,49,10.6a.67.67,0,0,0-.74-.15h0l-.95.39a3.05,3.05,0,0,1-3.43-.65,3.15,3.15,0,0,1-.65-3.45l.4-1a.69.69,0,0,0-.36-.89L38.82,3.05a.67.67,0,0,0-.88.37l-.41,1a3.08,3.08,0,0,1-5.75,0l-.41-1a.68.68,0,0,0-.89-.37L26.07,4.9a.68.68,0,0,0-.37.89l.39,1A3.1,3.1,0,0,1,22,10.85h0l-.95-.4a.68.68,0,0,0-.89.37l-1.83,4.44a.69.69,0,0,0,.37.89l1,.41a3.12,3.12,0,0,1,0,5.79l-.95.42a.69.69,0,0,0-.38.89l1.83,4.44a.7.7,0,0,0,.89.37l1-.4a3.05,3.05,0,0,1,3.42.65,3.12,3.12,0,0,1,.64,3.45h0l-.4,1a.68.68,0,0,0,.37.89l4.41,1.84a.68.68,0,0,0,.89-.36l.4-1a3.08,3.08,0,0,1,5.76,0l.4,1a.68.68,0,0,0,.89.36L43.23,34a.68.68,0,0,0,.37-.89l-.4-1h0a3.15,3.15,0,0,1,.65-3.45,3.06,3.06,0,0,1,3.42-.65h0l.95.4a.69.69,0,0,0,.89-.37L51,23.65A.69.69,0,0,0,50.58,22.76ZM36.89,24.9a5.84,5.84,0,0,1-7.65-3.19A5.91,5.91,0,0,1,32.41,14a5.84,5.84,0,0,1,7.65,3.18A5.91,5.91,0,0,1,36.89,24.9Z"/><path d="M25.82,37.11H25.1a2.14,2.14,0,0,1-2-1.33,2.21,2.21,0,0,1,.5-2.41l.51-.51a.5.5,0,0,0,0-.68l-2.36-2.38a.46.46,0,0,0-.67,0l-.52.52a2.16,2.16,0,0,1-2.39.5,2.19,2.19,0,0,1-1.33-2.06V28a.47.47,0,0,0-.47-.48H13a.48.48,0,0,0-.48.47v.73a2.16,2.16,0,0,1-3.72,1.56h0l-.51-.52a.46.46,0,0,0-.67,0L5.24,32.17a.48.48,0,0,0,0,.68l.5.51a2.19,2.19,0,0,1,.5,2.41,2.14,2.14,0,0,1-2,1.33H3.48a.48.48,0,0,0-.48.48V41a.48.48,0,0,0,.48.48H4.2a2.15,2.15,0,0,1,2,1.34,2.17,2.17,0,0,1-.5,2.4h0l-.51.52a.48.48,0,0,0,0,.67l2.36,2.38a.46.46,0,0,0,.67,0l.52-.51a2.16,2.16,0,0,1,2.39-.5A2.18,2.18,0,0,1,12.5,49.8v.72h0A.49.49,0,0,0,13,51h3.34a.47.47,0,0,0,.48-.48h0V49.8a2.18,2.18,0,0,1,1.33-2.06,2.16,2.16,0,0,1,2.39.5l.51.52a.46.46,0,0,0,.67,0l2.37-2.38a.48.48,0,0,0,0-.67l-.51-.53a2.19,2.19,0,0,1-.5-2.4,2.15,2.15,0,0,1,2-1.34h.72A.48.48,0,0,0,26.3,41V37.59A.47.47,0,0,0,25.82,37.11ZM14.65,43.39a4.12,4.12,0,1,1,4.09-4.12A4.1,4.1,0,0,1,14.65,43.39Z"/></svg>';
export class StudipSettings extends Plugin {
init() {
this.editor.ui.componentFactory.add('studipSettings', (locale) => {
const dropdownView = createDropdown(locale);
dropdownView.buttonView.set({
label: $gettext('Stud.IP Einstellungen'),
icon: gearsIcon,
tooltip: true,
});
dropdownView.render();
const studipSettingsView = new StudipSettingsView(locale);
dropdownView.panelView.children.add(studipSettingsView);
studipSettingsView.on('wysiwyg:change', (eventInfo, disabled) => {
this._save(studipSettingsView, disabled).then(() => (dropdownView.isOpen = false));
});
return dropdownView;
});
}
_save(view, disabled) {
view.functional = false;
return settings
.save({ disabled })
.fail(function (xhr) {
console.error("couldn't save changes");
})
.always(() => {
view.functional = true;
});
}
}
class StudipSettingsView extends View {
constructor(locale) {
super(locale);
const bind = this.bindTemplate;
this.set({
checked: false,
functional: true,
});
const button = createButton();
this.button = button;
button.on('execute', () => {
this.fire('wysiwyg:change', this.checked);
});
this.on('checking', (...args) => {
this.checked = !this.checked;
});
this.setTemplate({
tag: 'form',
attributes: {
class: ['default ck-studip-settings-form'],
tabindex: '-1',
style: 'max-width: 20em; padding: 1em;',
},
children: [createCheckbox(), createHelpText(), button],
});
function createCheckbox() {
return {
tag: 'label',
children: [
{
tag: 'input',
attributes: {
id: 'disable',
type: 'checkbox',
checked: bind.to('checked'),
style: 'margin-right: 0.5em'
},
on: {
change: bind.to('checking'),
},
},
{
text: $gettext('WYSIWYG Editor ausschalten'),
},
],
};
}
function createHelpText() {
return {
tag: 'p',
attributes: {
style: 'white-space: normal; font-size: 1em; line-height: 1.5em; margin-bottom: 1em;',
},
children: [
{
text: $gettext(
'Mit dieser Einstellung können Sie den WYSIWYG Editor ausschalten. Dadurch müssen Sie gegebenenfalls Texte in HTML schreiben. Der Editor wird erst vollständig entfernt, wenn die Seite neu geladen wird.'
),
},
],
};
}
function createButton() {
const button = new ButtonView(locale);
button.set({
label: $gettext('Speichern'),
withText: true,
isEnabled: bind.to('functional'),
});
return button;
}
}
}
class StudipUploadAdapter {
constructor(loader) {
this.loader = loader;
}
upload() {
return this.loader.file.then(
(file) =>
new Promise((resolve, reject) => {
var data = new FormData();
data.append('files[]', file);
$.ajax({
url: STUDIP.URLHelper.getURL('dispatch.php/wysiwyg/upload'),
type: 'POST',
data: data,
contentType: false,
async: false,
processData: false,
cache: false,
dataType: 'json',
error: function (err) {
reject(err);
},
success: function (data) {
resolve({ default: data.files[0].url });
},
});
})
);
}
// Aborts the upload process.
abort() {}
}
export default function StudipUpload(editor) {
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return new StudipUploadAdapter(loader);
};
}
export default function SpecialCharactersEmojiFood( editor ) {
editor.plugins.get( 'SpecialCharacters' ).addItems( 'Emoji Food', [
{ title: 'grapes', character: '🍇' },
{ title: 'melon', character: '🍈' },
{ title: 'watermelon', character: '🍉' },
{ title: 'tangerine', character: '🍊' },
{ title: 'lemon', character: '🍋' },
{ title: 'banana', character: '🍌' },
{ title: 'pineapple', character: '🍍' },
{ title: 'mango', character: '🥭' },
{ title: 'red apple', character: '🍎' },
{ title: 'green apple', character: '🍏' },
{ title: 'pear', character: '🍐' },
{ title: 'peach', character: '🍑' },
{ title: 'cherries', character: '🍒' },
{ title: 'strawberry', character: '🍓' },
{ title: 'blueberries', character: '🫐' },
{ title: 'kiwi fruit', character: '🥝' },
{ title: 'tomato', character: '🍅' },
{ title: 'olive', character: '🫒' },
{ title: 'coconut', character: '🥥' },
{ title: 'avocado', character: '🥑' },
{ title: 'eggplant', character: '🍆' },
{ title: 'potato', character: '🥔' },
{ title: 'carrot', character: '🥕' },
{ title: 'ear of corn', character: '🌽' },
{ title: 'hot pepper', character: '🌶' },
{ title: 'bell pepper', character: '🫑' },
{ title: 'cucumber', character: '🥒' },
{ title: 'leafy green', character: '🥬' },
{ title: 'broccoli', character: '🥦' },
{ title: 'garlic', character: '🧄' },
{ title: 'onion', character: '🧅' },
{ title: 'mushroom', character: '🍄' },
{ title: 'peanuts', character: '🥜' },
{ title: 'chestnut', character: '🌰' },
{ character: '🍞', title: 'bread' },
{ character: '🥐', title: 'croissant' },
{ character: '🥖', title: 'baguette bread' },
{ character: '🫓', title: 'flatbread' },
{ character: '🥨', title: 'pretzel' },
{ character: '🥯', title: 'bagel' },
{ character: '🥞', title: 'pancakes' },
{ character: '🧇', title: 'waffle' },
{ character: '🧀', title: 'cheese wedge' },
{ character: '🍖', title: 'meat on bone' },
{ character: '🍗', title: 'poultry leg' },
{ character: '🥩', title: 'cut of meat' },
{ character: '🥓', title: 'bacon' },
{ character: '🍔', title: 'hamburger' },
{ character: '🍟', title: 'french fries' },
{ character: '🍕', title: 'pizza' },
{ character: '🌭', title: 'hot dog' },
{ character: '🥪', title: 'sandwich' },
{ character: '🌮', title: 'taco' },
{ character: '🌯', title: 'burrito' },
{ character: '🫔', title: 'tamale' },
{ character: '🥙', title: 'stuffed flatbread' },
{ character: '🧆', title: 'falafel' },
{ character: '🥚', title: 'egg' },
{ character: '🍳', title: 'cooking' },
{ character: '🥘', title: 'shallow pan of food' },
{ character: '🍲', title: 'pot of food' },
{ character: '🫕', title: 'fondue' },
{ character: '🥣', title: 'bowl with spoon' },
{ character: '🥗', title: 'green salad' },
{ character: '🍿', title: 'popcorn' },
{ character: '🧈', title: 'butter' },
{ character: '🧂', title: 'salt' },
{ character: '🥫', title: 'canned food' },
{ character: '🍱', title: 'bento box' },
{ character: '🍘', title: 'rice cracker' },
{ character: '🍙', title: 'rice ball' },
{ character: '🍚', title: 'cooked rice' },
{ character: '🍛', title: 'curry rice' },
{ character: '🍜', title: 'steaming bowl' },
{ character: '🍝', title: 'spaghetti' },
{ character: '🍠', title: 'roasted sweet potato' },
{ character: '🍢', title: 'oden' },
{ character: '🍣', title: 'sushi' },
{ character: '🍤', title: 'fried shrimp' },
{ character: '🍥', title: 'fish cake with swirl' },
{ character: '🥮', title: 'moon cake' },
{ character: '🍡', title: 'dango' },
{ character: '🥟', title: 'dumpling' },
{ character: '🥠', title: 'fortune cookie' },
{ character: '🥡', title: 'takeout box' },
{ character: '🍦', title: 'soft ice cream' },
{ character: '🍧', title: 'shaved ice' },
{ character: '🍨', title: 'ice cream' },
{ character: '🍩', title: 'doughnut' },
{ character: '🍪', title: 'cookie' },
{ character: '🎂', title: 'birthday cake' },
{ character: '🍰', title: 'shortcake' },
{ character: '🧁', title: 'cupcake' },
{ character: '🥧', title: 'pie' },
{ character: '🍫', title: 'chocolate bar' },
{ character: '🍬', title: 'candy' },
{ character: '🍭', title: 'lollipop' },
{ character: '🍮', title: 'custard' },
{ character: '🍯', title: 'honey pot' },
{ character: '🍼', title: 'baby bottle' },
{ character: '🥛', title: 'glass of milk' },
{ character: '', title: 'hot beverage' },
{ character: '🫖', title: 'teapot' },
{ character: '🍵', title: 'teacup without handle' },
{ character: '🍶', title: 'sake' },
{ character: '🍾', title: 'bottle with popping cork' },
{ character: '🍷', title: 'wine glass' },
{ character: '🍸', title: 'cocktail glass' },
{ character: '🍹', title: 'tropical drink' },
{ character: '🍺', title: 'beer mug' },
{ character: '🍻', title: 'clinking beer mugs' },
{ character: '🥂', title: 'clinking glasses' },
{ character: '🥃', title: 'tumbler glass' },
{ character: '🥤', title: 'cup with straw' },
{ character: '🧋', title: 'bubble tea' },
{ character: '🧃', title: 'beverage box' },
{ character: '🧉', title: 'mate' },
{ character: '🧊', title: 'ice' },
{ character: '🥢', title: 'chopsticks' },
{ character: '🍽', title: 'fork and knife with plate' },
{ character: '🍴', title: 'fork and knife' },
{ character: '🥄', title: 'spoon' },
{ character: '🔪', title: 'kitchen knife' },
{ character: '🏺', title: 'amphora' },
] );
}
\ No newline at end of file
export default function SpecialCharactersEmojiNature( editor ) {
editor.plugins.get( 'SpecialCharacters' ).addItems( 'Emoji Nature', [
{ title: 'dog face', character: '🐶' },
{ title: 'cat face', character: '🐱' },
{ title: 'mouse face', character: '🐭' },
{ title: 'hamster', character: '🐹' },
{ title: 'rabbit face', character: '🐰' },
{ title: 'horse face', character: '🐴' },
{ title: 'unicorn', character: '🦄' },
{ title: 'fox', character: '🦊' },
{ title: 'wolf', character: '🐺' },
{ title: 'raccoon', character: '🦝' },
{ title: 'bear', character: '🐻' },
{ title: 'panda', character: '🐼' },
{ title: 'polar bear', character: '🐻‍❄️' },
{ title: 'koala', character: '🐨' },
{ title: 'tiger face', character: '🐯' },
{ title: 'lion', character: '🦁' },
{ title: 'cow face', character: '🐮' },
{ title: 'pig face', character: '🐷' },
{ title: 'frog', character: '🐸' },
{ title: 'dragon face', character: '🐲' },
{ title: 'monkey face', character: '🐵' },
{ title: 'see-no-evil monkey', character: '🙈' },
{ title: 'hear-no-evil monkey', character: '🙉' },
{ title: 'speak-no-evil monkey', character: '🙊' },
{ title: 'chicken', character: '🐔' },
{ title: 'rooster', character: '🐓' },
{ title: 'hatching chick', character: '🐣' },
{ title: 'baby chick', character: '🐤' },
{ title: 'front-facing baby chick', character: '🐥' },
{ title: 'bird', character: '🐦' },
{ title: 'penguin', character: '🐧' },
{ title: 'dove', character: '🕊' },
{ title: 'eagle', character: '🦅' },
{ title: 'duck', character: '🦆' },
{ title: 'swan', character: '🦢' },
{ title: 'owl', character: '🦉' },
{ title: 'dodo', character: '🦤' },
{ title: 'flamingo', character: '🦩' },
{ title: 'peacock', character: '🦚' },
{ title: 'parrot', character: '🦜' },
{ title: 'turkey', character: '🦃' },
{ title: 'feather', character: '🪶' },
{ title: 'snail', character: '🐌' },
{ title: 'butterfly', character: '🦋' },
{ title: 'bug', character: '🐛' },
{ title: 'ant', character: '🐜' },
{ title: 'honeybee', character: '🐝' },
{ title: 'beetle', character: '🪲' },
{ title: 'lady beetle', character: '🐞' },
{ title: 'cricket', character: '🦗' },
{ title: 'cockroach', character: '🪳' },
{ title: 'spider', character: '🕷' },
{ title: 'spider web', character: '🕸' },
{ title: 'scorpion', character: '🦂' },
{ title: 'mosquito', character: '🦟' },
{ title: 'fly', character: '🪰' },
{ title: 'worm', character: '🪱' },
{ title: 'microbe', character: '🦠' },
{ title: 'crocodile', character: '🐊' },
{ title: 'turtle', character: '🐢' },
{ title: 'lizard', character: '🦎' },
{ title: 'snake', character: '🐍' },
{ title: 'dragon', character: '🐉' },
{ title: 'sauropod', character: '🦕' },
{ title: 'T-Rex', character: '🦖' },
{ title: 'spouting whale', character: '🐳' },
{ title: 'whale', character: '🐋' },
{ title: 'dolphin', character: '🐬' },
{ title: 'seal', character: '🦭' },
{ title: 'fish', character: '🐟' },
{ title: 'tropical fish', character: '🐠' },
{ title: 'blowfish', character: '🐡' },
{ title: 'shark', character: '🦈' },
{ title: 'octopus', character: '🐙' },
{ title: 'spiral shell', character: '🐚' },
{ title: 'crab', character: '🦀' },
{ title: 'lobster', character: '🦞' },
{ title: 'shrimp', character: '🦐' },
{ title: 'squid', character: '🦑' },
{ title: 'monkey', character: '🐒' },
{ title: 'gorilla', character: '🦍' },
{ title: 'orangutan', character: '🦧' },
{ title: 'dog', character: '🐕' },
{ title: 'cat', character: '🐈' },
{ title: 'black cat', character: '🐈‍⬛' },
{ title: 'tiger', character: '🐅' },
{ title: 'leopard', character: '🐆' },
{ title: 'horse', character: '🐎' },
{ title: 'zebra', character: '🦓' },
{ title: 'deer', character: '🦌' },
{ title: 'bison', character: '🦬' },
{ title: 'ox', character: '🐂' },
{ title: 'water buffalo', character: '🐃' },
{ title: 'cow', character: '🐄' },
{ title: 'pig', character: '🐖' },
{ title: 'boar', character: '🐗' },
{ title: 'ram', character: '🐏' },
{ title: 'ewe', character: '🐑' },
{ title: 'goat', character: '🐐' },
{ title: 'camel', character: '🐪' },
{ title: 'two-hump camel', character: '🐫' },
{ title: 'llama', character: '🦙' },
{ title: 'giraffe', character: '🦒' },
{ title: 'elephant', character: '🐘' },
{ title: 'mammoth', character: '🦣' },
{ title: 'rhinoceros', character: '🦏' },
{ title: 'hippopotamus', character: '🦛' },
{ title: 'mouse', character: '🐁' },
{ title: 'rat', character: '🐀' },
{ title: 'rabbit', character: '🐇' },
{ title: 'chipmunk', character: '🐿' },
{ title: 'beaver', character: '🦫' },
{ title: 'hedgehog', character: '🦔' },
{ title: 'bat', character: '🦇' },
{ title: 'sloth', character: '🦥' },
{ title: 'otter', character: '🦦' },
{ title: 'skunk', character: '🦨' },
{ title: 'kangaroo', character: '🦘' },
{ title: 'badger', character: '🦡' },
{ title: 'paw prints', character: '🐾' },
{ title: 'bouquet', character: '💐' },
{ title: 'cherry blossom', character: '🌸' },
{ title: 'white flower', character: '💮' },
{ title: 'rosette', character: '🏵' },
{ title: 'rose', character: '🌹' },
{ title: 'wilted flower', character: '🥀' },
{ title: 'hibiscus', character: '🌺' },
{ title: 'sunflower', character: '🌻' },
{ title: 'blossom', character: '🌼' },
{ title: 'tulip', character: '🌷' },
{ title: 'seedling', character: '🌱' },
{ title: 'potted plant', character: '🪴' },
{ title: 'evergreen tree', character: '🌲' },
{ title: 'Christmas tree', character: '🎄' },
{ title: 'deciduous tree', character: '🌳' },
{ title: 'palm tree', character: '🌴' },
{ title: 'cactus', character: '🌵' },
{ title: 'sheaf of rice', character: '🌾' },
{ title: 'herb', character: '🌿' },
{ title: 'shamrock', character: '☘️' },
{ title: 'four leaf clover', character: '🍀' },
{ title: 'maple leaf', character: '🍁' },
{ title: 'fallen leaf', character: '🍂' },
{ title: 'leaf fluttering in wind', character: '🍃' },
{ title: 'tanabata tree', character: '🎋' },
{ title: 'mushroom', character: '🍄' },
{ title: 'sun', character: '☀️' },
{ title: 'sun with face', character: '🌞' },
{ title: 'full moon face', character: '🌝' },
{ title: 'first quarter moon face', character: '🌛' },
{ title: 'last quarter moon face', character: '🌜' },
{ title: 'globe showing Europe-Africa', character: '🌍' },
{ title: 'globe showing Americas', character: '🌎' },
{ title: 'globe showing Asia-Australia', character: '🌏' },
{ title: 'ringed planet', character: '🪐' },
{ title: 'glowing star', character: '' },
{ title: 'comet', character: '☄️' },
{ title: 'shooting star', character: '🌠' },
{ title: 'sun behind cloud', character: '' },
{ title: 'cloud with lightning and rain', character: '' },
{ title: 'sun behind small cloud', character: '🌤' },
{ title: 'sun behind large cloud', character: '🌥' },
{ title: 'sun behind rain cloud', character: '🌦' },
{ title: 'cloud with rain', character: '🌧' },
{ title: 'cloud with snow', character: '🌨' },
{ title: 'cloud with lightning', character: '🌩' },
{ title: 'fog', character: '🌫' },
{ title: 'tornado', character: '🌪' },
{ title: 'rainbow', character: '🌈' },
{ title: 'snowflake', character: '❄️' },
{ title: 'snowman', character: '☃️' },
{ title: 'snowman', character: '' },
{ title: 'fire', character: '🔥' },
{ title: 'water wave', character: '🌊' },
] );
}
export default function SpecialCharactersEmojiObjects( editor ) {
editor.plugins.get( 'SpecialCharacters' ).addItems( 'Emoji Objects', [
{ title: '', character: '' },
] );
}
\ No newline at end of file
export default function SpecialCharactersEmojiPeople( editor ) {
editor.plugins.get( 'SpecialCharacters' ).addItems( 'Emoji People', [
{ title: 'smiley grinning face', character: '😀' },
{ title: 'smiley grinning face with big eyes', character: '😃' },
{ title: 'smiley grinning face with smiling eyes', character: '😄' },
{ title: 'smiley beaming face with smiling eyes', character: '😁' },
{ title: 'smiley grinning squinting face', character: '😆' },
{ title: 'smiley grinning face with sweat', character: '😅' },
{ title: 'smiley face with tears of joy', character: '😂' },
{ title: 'smiley rolling on the floor laughing', character: '🤣' },
{ title: 'smiley slightly smiling face', character: '🙂' },
{ title: 'smiley upside-down face', character: '🙃' },
{ title: 'smiley winking face', character: '😉' },
{ title: 'smiley smiling face with smiling eyes', character: '😊' },
{ title: 'smiley smiling face with halo', character: '😇' },
{ title: 'smiley smiling face with hearts', character: '🥰' },
{ title: 'smiley smiling face with heart-eyes', character: '😍' },
{ title: 'smiley star-struck', character: '🤩' },
{ title: 'smiley face blowing a kiss', character: '😘' },
{ title: 'smiley kissing face', character: '😗' },
{ title: 'smiley kissing face with smiling eyes', character: '😙' },
{ title: 'smiley kissing face with closed eyes', character: '😚' },
{ title: 'smiley smiling face with tear', character: '🥲' },
{ title: 'smiley face savoring food', character: '😋' },
{ title: 'smiley face with tongue', character: '😛' },
{ title: 'smiley squinting face with tongue', character: '😝' },
{ title: 'smiley winking face with tongue', character: '😜' },
{ title: 'smiley zany face', character: '🤪' },
{ title: 'smiley money-mouth face', character: '🤑' },
{ title: 'smiley smiling face with open hands', character: '🤗' },
{ title: 'smiley face with hand over mouth', character: '🤭' },
{ title: 'smiley shushing face', character: '🤫' },
{ title: 'smiley thinking face', character: '🤔' },
{ title: 'smiley zipper-mouth face', character: '🤐' },
{ title: 'smiley face with raised eyebrow', character: '🤨' },
{ title: 'smiley neutral face', character: '😐' },
{ title: 'smiley expressionless face', character: '😑' },
{ title: 'smiley face without mouth', character: '😶' },
{ title: 'smiley face in clouds', character: '😶‍🌫️' },
{ title: 'smiley smirking face', character: '😏' },
{ title: 'smiley unamused face', character: '😒' },
{ title: 'smiley face with rolling eyes', character: '🙄' },
{ title: 'smiley grimacing face', character: '😬' },
{ title: 'smiley face exhaling', character: '😮‍💨' },
{ title: 'smiley lying face', character: '🤥' },
{ title: 'smiley relieved face', character: '😌' },
{ title: 'smiley pensive face', character: '😔' },
{ title: 'smiley sleepy face', character: '😪' },
{ title: 'smiley drooling face', character: '🤤' },
{ title: 'smiley sleeping face', character: '😴' },
{ title: 'smiley face with medical mask', character: '😷' },
{ title: 'smiley face with thermometer', character: '🤒' },
{ title: 'smiley face with head-bandage', character: '🤕' },
{ title: 'smiley nauseated face', character: '🤢' },
{ title: 'smiley face vomiting', character: '🤮' },
{ title: 'smiley sneezing face', character: '🤧' },
{ title: 'smiley hot face', character: '🥵' },
{ title: 'smiley cold face', character: '🥶' },
{ title: 'smiley woozy face', character: '🥴' },
{ title: 'smiley face with crossed-out eyes', character: '😵' },
{ title: 'smiley face with spiral eyes', character: '😵‍💫' },
{ title: 'smiley exploding head', character: '🤯' },
{ title: 'smiley cowboy hat face', character: '🤠' },
{ title: 'smiley partying face', character: '🥳' },
{ title: 'smiley disguised face', character: '🥸' },
{ title: 'smiley smiling face with sunglasses', character: '😎' },
{ title: 'smiley nerd face', character: '🤓' },
{ title: 'smiley face with monocle', character: '🧐' },
{ title: 'smiley confused face', character: '😕' },
{ title: 'smiley worried face', character: '😟' },
{ title: 'smiley slightly frowning face', character: '🙁' },
{ title: 'smiley frowning face', character: '☹️' },
{ title: 'smiley face with open mouth', character: '😮' },
{ title: 'smiley hushed face', character: '😯' },
{ title: 'smiley astonished face', character: '😲' },
{ title: 'smiley flushed face', character: '😳' },
{ title: 'smiley pleading face', character: '🥺' },
{ title: 'smiley frowning face with open mouth', character: '😦' },
{ title: 'smiley anguished face', character: '😧' },
{ title: 'smiley fearful face', character: '😨' },
{ title: 'smiley anxious face with sweat', character: '😰' },
{ title: 'smiley sad but relieved face', character: '😥' },
{ title: 'smiley crying face', character: '😢' },
{ title: 'smiley loudly crying face', character: '😭' },
{ title: 'smiley face screaming in fear', character: '😱' },
{ title: 'smiley confounded face', character: '😖' },
{ title: 'smiley persevering face', character: '😣' },
{ title: 'smiley disappointed face', character: '😞' },
{ title: 'smiley downcast face with sweat', character: '😓' },
{ title: 'smiley weary face', character: '😩' },
{ title: 'smiley tired face', character: '😫' },
{ title: 'smiley yawning face', character: '🥱' },
{ title: 'smiley face with steam from nose', character: '😤' },
{ title: 'smiley pouting face', character: '😠' },
{ title: 'smiley angry face', character: '😡' },
{ title: 'smiley face with symbols on mouth', character: '🤬' },
{ title: 'smiley smiling face with horns', character: '😈' },
{ title: 'smiley angry face with horns', character: '👿' },
{ title: 'skull', character: '💀' },
{ title: 'skull and crossbones', character: '☠️' },
{ title: 'pile of poo', character: '💩' },
{ title: 'smiley clown face', character: '🤡' },
{ title: 'ogre', character: '👹' },
{ title: 'goblin', character: '👺' },
{ title: 'jack-o-lantern', character: '🎃' },
{ title: 'ghost', character: '👻' },
{ title: 'alien', character: '👽' },
{ title: 'alien monster', character: '👾' },
{ title: 'robot', character: '🤖' },
{ title: 'smiley grinning cat', character: '😺' },
{ title: 'smiley grinning cat with smiling eyes', character: '😸' },
{ title: 'smiley cat with tears of joy', character: '😹' },
{ title: 'smiley smiling cat with heart-eyes', character: '😻' },
{ title: 'smiley cat with wry smile', character: '😼' },
{ title: 'smiley kissing cat', character: '😽' },
{ title: 'smiley weary cat', character: '🙀' },
{ title: 'smiley crying cat', character: '😿' },
{ title: 'smiley pouting cat', character: '😾' },
{ title: 'see-no-evil monkey', character: '🙈' },
{ title: 'hear-no-evil monkey', character: '🙉' },
{ title: 'speak-no-evil monkey', character: '🙊' },
{ title: 'waving hand', character: '👋' },
{ title: 'raised back of hand', character: '🤚' },
{ title: 'hand with fingers splayed', character: '🖐' },
{ title: 'raised hand', character: '' },
{ title: 'vulcan salute', character: '🖖' },
{ title: 'OK hand', character: '👌' },
{ title: 'pinched fingers', character: '🤌' },
{ title: 'pinching hand', character: '🤏' },
{ title: 'victory hand', character: '✌️' },
{ title: 'crossed fingers', character: '🤞' },
{ title: 'love-you gesture', character: '🤟' },
{ title: 'sign of the horns', character: '🤘' },
{ title: 'call me hand', character: '🤙' },
{ title: 'backhand index pointing left', character: '👈' },
{ title: 'backhand index pointing right', character: '👉' },
{ title: 'backhand index pointing up', character: '👆' },
{ title: 'backhand index pointing down', character: '👇' },
{ title: 'index pointing up', character: '☝️' },
{ title: 'thumbs up', character: '👍' },
{ title: 'thumbs down', character: '👎' },
{ title: 'raised fist', character: '' },
{ title: 'clapping hands', character: '👏' },
{ title: 'raising hands', character: '🙌' },
{ title: 'open hands', character: '👐' },
{ title: 'palms up together', character: '🤲' },
{ title: 'handshake', character: '🤝' },
{ title: 'folded hands', character: '🙏' },
{ title: 'writing hand', character: '✍️' },
{ title: 'selfie', character: '🤳' },
{ title: 'flexed biceps', character: '💪' },
{ title: 'ear', character: '👂' },
{ title: 'nose', character: '👃' },
{ title: 'eyes', character: '👀' },
{ title: 'baby', character: '👶' },
{ title: 'child', character: '🧒' },
{ title: 'boy', character: '👦' },
{ title: 'girl', character: '👧' },
{ title: 'person', character: '🧑' },
{ title: 'man', character: '👨' },
{ title: 'woman', character: '👩' },
{ title: 'person frowning', character: '🙍' },
{ title: 'man frowning', character: '🙍‍♂️' },
{ title: 'woman frowning', character: '🙍‍♀️' },
{ title: 'person pouting', character: '🙎' },
{ title: 'man pouting', character: '🙎‍♂️' },
{ title: 'woman pouting', character: '🙎‍♀️' },
{ title: 'person gesturing NO', character: '🙅' },
{ title: 'man gesturing NO', character: '🙅‍♂️' },
{ title: 'woman gesturing NO', character: '🙅‍♀️' },
{ title: 'person gesturing OK', character: '🙆' },
{ title: 'man gesturing OK', character: '🙆‍♂️' },
{ title: 'woman gesturing OK', character: '🙆‍♀️' },
{ title: 'person tipping hand', character: '💁' },
{ title: 'man tipping hand', character: '💁‍♂️' },
{ title: 'woman tipping hand', character: '💁‍♀️' },
{ title: 'person raising hand', character: '🙋' },
{ title: 'man raising hand', character: '🙋‍♂️' },
{ title: 'woman raising hand', character: '🙋‍♀️' },
{ title: 'person facepalming', character: '🤦' },
{ title: 'man facepalming', character: '🤦‍♂️' },
{ title: 'woman facepalming', character: '🤦‍♀️' },
{ title: 'person shrugging', character: '🤷' },
{ title: 'man shrugging', character: '🤷‍♂️' },
{ title: 'woman shrugging', character: '🤷‍♀️' },
{ title: 'speaking head', character: '🗣' },
{ title: 'bust in silhouette', character: '👤' },
{ title: 'busts in silhouette', character: '👥' },
{ title: 'people hugging', character: '🫂' },
{ title: 'footprints', character: '👣' },
] );
}
export default function SpecialCharactersEmojiSport( editor ) {
editor.plugins.get( 'SpecialCharacters' ).addItems( 'Emoji Sport', [
{ title: '', character: '' },
] );
}
\ No newline at end of file
export default function SpecialCharactersEmojiSymbols( editor ) {
editor.plugins.get( 'SpecialCharacters' ).addItems( 'Emoji Symbols', [
{ title: 'red heart', character: '❤️' },
{ title: 'orange heart', character: '🧡' },
{ title: 'yellow heart', character: '💛' },
{ title: 'green heart', character: '💚' },
{ title: 'blue heart', character: '💙' },
{ title: 'purple heart', character: '💜' },
{ title: 'brown heart', character: '🤎' },
{ title: 'black heart', character: '🖤' },
{ title: 'white heart', character: '🤍' },
{ title: 'heart with arrow', character: '💘' },
{ title: 'heart with ribbon', character: '💝' },
{ title: 'sparkling heart', character: '💖' },
{ title: 'growing heart', character: '💗' },
{ title: 'beating heart', character: '💓' },
{ title: 'revolving hearts', character: '💞' },
{ title: 'two hearts', character: '💕' },
{ title: 'heart exclamation', character: '❣️' },
{ title: 'broken heart', character: '💔' },
{ title: 'heart on fire', character: '❤️‍🔥' },
{ title: 'mending heart', character: '❤️‍🩹' },
{ title: 'heart decoration', character: '💟' },
{ title: 'place of worship', character: '🛐' },
{ title: 'atom symbol', character: '⚛️' },
{ title: 'om', character: '🕉' },
{ title: 'star of David', character: '✡️' },
{ title: 'wheel of dharma', character: '☸️' },
{ title: 'yin yang', character: '☯️' },
{ title: 'latin cross', character: '✝️' },
{ title: 'orthodox cross', character: '☦️' },
{ title: 'star and crescent', character: '☪️' },
{ title: 'peace symbol', character: '☮️' },
{ title: 'menorah', character: '🕎' },
{ title: 'dotted six-pointed star', character: '🔯' },
{ title: 'Aries', character: '' },
{ title: 'Taurus', character: '' },
{ title: 'Gemini', character: '' },
{ title: 'Cancer', character: '' },
{ title: 'Leo', character: '' },
{ title: 'Virgo', character: '' },
{ title: 'Libra', character: '' },
{ title: 'Scorpio', character: '' },
{ title: 'Sagittarius', character: '' },
{ title: 'Capricorn', character: '' },
{ title: 'Aquarius', character: '' },
{ title: 'Pisces', character: '' },
{ title: 'Ophiuchus', character: '' },
{ title: 'ATM sign', character: '🏧' },
{ title: 'litter in bin sign', character: '🚮' },
{ title: 'potable water', character: '🚰' },
{ title: 'wheelchair symbol', character: '♿️' },
{ title: 'men’s room', character: '🚹' },
{ title: 'women’s room', character: '🚺' },
{ title: 'restroom', character: '🚻' },
{ title: 'baby symbol', character: '🚼' },
{ title: 'water closet', character: '🚾' },
{ title: 'passport control', character: '🛂' },
{ title: 'customs', character: '🛃' },
{ title: 'baggage claim', character: '🛄' },
{ title: 'left luggage', character: '🛅' },
{ title: 'warning', character: '⚠️' },
{ title: 'children crossing', character: '🚸' },
{ title: 'no entry', character: '⛔️' },
{ title: 'prohibited', character: '🚫' },
{ title: 'no bicycles', character: '🚳' },
{ title: 'no smoking', character: '🚭' },
{ title: 'no littering', character: '🚯' },
{ title: 'non-potable water', character: '🚱' },
{ title: 'no pedestrians', character: '🚷' },
{ title: 'no mobile phones', character: '📵' },
{ title: 'no one under eighteen', character: '🔞' },
{ title: 'radioactive', character: '☢️' },
{ title: 'biohazard', character: '☣️' },
{ title: 'up arrow', character: '⬆️' },
{ title: 'up-right arrow', character: '↗️' },
{ title: 'right arrow', character: '➡️' },
{ title: 'down-right arrow', character: '↘️' },
{ title: 'down arrow', character: '⬇️' },
{ title: 'down-left arrow', character: '↙️' },
{ title: 'left arrow', character: '⬅️' },
{ title: 'up-left arrow', character: '↖️' },
{ title: 'up-down arrow', character: '↕️' },
{ title: 'left-right arrow', character: '↔️' },
{ title: 'right arrow curving left', character: '↩️' },
{ title: 'left arrow curving right', character: '↪️' },
{ title: 'right arrow curving up', character: '⤴️' },
{ title: 'right arrow curving down', character: '⤵️' },
{ title: 'clockwise vertical arrows', character: '🔃' },
{ title: 'counterclockwise arrows button', character: '🔄' },
{ title: 'shuffle tracks button', character: '🔀' },
{ title: 'repeat button', character: '🔁' },
{ title: 'repeat single button', character: '🔂' },
{ title: 'play button', character: '▶️' },
{ title: 'fast-forward button', character: '' },
{ title: 'next track button', character: '⏭️' },
{ title: 'play or pause button', character: '⏯️' },
{ title: 'reverse button', character: '◀️' },
{ title: 'fast reverse button', character: '' },
{ title: 'last track button', character: '⏮️' },
{ title: 'upwards button', character: '🔼' },
{ title: 'fast up button', character: '' },
{ title: 'downwards button', character: '🔽' },
{ title: 'fast down button', character: '' },
{ title: 'pause button', character: '⏸️' },
{ title: 'stop button', character: '⏹️' },
{ title: 'record button', character: '⏺️' },
{ title: 'eject button', character: '⏏️' },
{ title: 'cinema', character: '🎦' },
{ title: 'dim button', character: '🔅' },
{ title: 'bright button', character: '🔆' },
{ title: 'antenna bars', character: '📶' },
{ title: 'vibration mode', character: '📳' },
{ title: 'mobile phone off', character: '📴' },
{ title: 'female sign', character: '♀️' },
{ title: 'male sign', character: '♂️' },
{ title: 'transgender symbol', character: '⚧️' },
{ title: 'multiply', character: '✖️' },
{ title: 'plus', character: '➕️' },
{ title: 'minus', character: '➖️' },
{ title: 'divide', character: '➗️' },
{ title: 'infinity', character: '♾️' },
{ title: 'double exclamation mark', character: '‼️' },
{ title: 'exclamation question mark', character: '⁉️' },
{ title: 'red question mark', character: '❓️' },
{ title: 'red exclamation mark', character: '❗️' },
{ title: 'white question mark', character: '❔️' },
{ title: 'white exclamation mark', character: '❕️' },
{ title: 'wavy dash', character: '〰️' },
{ title: 'currency exchange', character: '💱' },
{ title: 'heavy dollar sign', character: '💲' },
{ title: 'medical symbol', character: '⚕️' },
{ title: 'recycling symbol', character: '♻️' },
{ title: 'fleur-de-lis', character: '⚜️' },
{ title: 'trident emblem', character: '🔱' },
{ title: 'name badge', character: '📛' },
{ title: 'Japanese symbol for beginner', character: '🔰' },
{ title: 'hollow red circle', character: '⭕️' },
{ title: 'check mark button', character: '✅️' },
{ title: 'check box with check', character: '☑️' },
{ title: 'check mark', character: '✔️' },
{ title: 'cross mark', character: '❌️' },
{ title: 'cross mark button', character: '❎️' },
{ title: 'curly loop', character: '➰️' },
{ title: 'double curly loop', character: '➿️' },
{ title: 'part alternation mark', character: '〽️' },
{ title: 'eight-spoked asterisk', character: '✳️' },
{ title: 'eight-pointed star', character: '✴️' },
{ title: 'sparkle', character: '❇️' },
{ title: 'copyright', character: '©️' },
{ title: 'registered', character: '®️' },
{ title: 'trade mark', character: '™️' },
{ title: 'keycap: #', character: '#️⃣' },
{ title: 'keycap: *', character: '*️⃣' },
{ title: 'keycap: 0', character: '0️⃣' },
{ title: 'keycap: 1', character: '1️⃣' },
{ title: 'keycap: 2', character: '2️⃣' },
{ title: 'keycap: 3', character: '3️⃣' },
{ title: 'keycap: 4', character: '4️⃣' },
{ title: 'keycap: 5', character: '5️⃣' },
{ title: 'keycap: 6', character: '6️⃣' },
{ title: 'keycap: 7', character: '7️⃣' },
{ title: 'keycap: 8', character: '8️⃣' },
{ title: 'keycap: 9', character: '9️⃣' },
{ title: 'keycap: 10', character: '🔟' },
{ title: 'input latin uppercase', character: '🔠' },
{ title: 'input latin lowercase', character: '🔡' },
{ title: 'input numbers', character: '🔢' },
{ title: 'input symbols', character: '🔣' },
{ title: 'input latin letters', character: '🔤' },
{ title: 'A button (blood type)', character: '🅰️' },
{ title: 'AB button (blood type)', character: '🆎️' },
{ title: 'B button (blood type)', character: '🅱️' },
{ title: 'O button (blood type)', character: '🅾️' },
{ title: 'CL button', character: '🆑️' },
{ title: 'COOL button', character: '🆒️' },
{ title: 'FREE button', character: '🆓️' },
{ title: 'information', character: 'ℹ️' },
{ title: 'ID button', character: '🆔️' },
{ title: 'circled M', character: 'Ⓜ️' },
{ title: 'NEW button', character: '🆕️' },
{ title: 'NG button', character: '🆖️' },
{ title: 'OK button', character: '🆗️' },
{ title: 'P button', character: '🅿️' },
{ title: 'SOS button', character: '🆘️' },
{ title: 'UP! button', character: '🆙️' },
{ title: 'VS button', character: '🆚️' },
{ title: 'red circle', character: '🔴' },
{ title: 'orange circle', character: '🟠' },
{ title: 'yellow circle', character: '🟡' },
{ title: 'green circle', character: '🟢' },
{ title: 'blue circle', character: '🔵' },
{ title: 'purple circle', character: '🟣' },
{ title: 'brown circle', character: '🟤' },
{ title: 'white circle', character: '⚪️' },
{ title: 'black circle', character: '⚫️' },
{ title: 'red square', character: '🟥' },
{ title: 'orange square', character: '🟧' },
{ title: 'yellow square', character: '🟨' },
{ title: 'green square', character: '🟩' },
{ title: 'blue square', character: '🟦' },
{ title: 'purple square', character: '🟪' },
{ title: 'brown square', character: '🟫' },
{ title: 'black large square', character: '⬛️' },
{ title: 'white large square', character: '⬜️' },
{ title: 'black medium square', character: '◼️' },
{ title: 'white medium square', character: '◻️' },
{ title: 'black medium-small square', character: '◾️' },
{ title: 'white medium-small square', character: '◽️' },
{ title: 'black small square', character: '▪️' },
{ title: 'white small square', character: '▫️' },
{ title: 'large orange diamond', character: '🔶️' },
{ title: 'large blue diamond', character: '🔷️' },
{ title: 'small orange diamond', character: '🔸️' },
{ title: 'small blue diamond', character: '🔹️' },
{ title: 'red triangle pointed up', character: '🔺️' },
{ title: 'red triangle pointed down', character: '🔻' },
{ title: 'diamond with a dot', character: '💠' },
{ title: 'radio button', character: '🔘' },
{ title: 'white square button', character: '🔲' },
{ title: 'black square button', character: '🔳' },
] );
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment