From 59a114277f2acde21221adb6f46e1b4b9fb1f248 Mon Sep 17 00:00:00 2001 From: Przemyslaw Zan
` element.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class CodeEditing extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'CodeEditing';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ static get requires() {
+ return [ TwoStepCaretMovement ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+
+ // Allow code attribute on text nodes.
+ editor.model.schema.extend( '$text', { allowAttributes: CODE } );
+ editor.model.schema.setAttributeProperties( CODE, {
+ isFormatting: true,
+ copyOnEnter: false
+ } );
+
+ editor.conversion.attributeToElement( {
+ model: CODE,
+ view: 'code',
+ upcastAlso: {
+ styles: {
+ 'word-wrap': 'break-word'
+ }
+ }
+ } );
+
+ // Create code command.
+ editor.commands.add( CODE, new AttributeCommand( editor, CODE ) );
+
+ // Enable two-step caret movement for `code` attribute.
+ editor.plugins.get( TwoStepCaretMovement ).registerAttribute( CODE );
+
+ // Setup highlight over selected element.
+ inlineHighlight( editor, CODE, 'code', HIGHLIGHT_CLASS );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/code/codeui.js b/packages/ckeditor5-basic-styles/_src/code/codeui.js
new file mode 100644
index 00000000000..2948088ef51
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/code/codeui.js
@@ -0,0 +1,62 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/code/codeui
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import { ButtonView } from 'ckeditor5/src/ui';
+
+import codeIcon from '../../theme/icons/code.svg';
+
+import '../../theme/code.css';
+
+const CODE = 'code';
+
+/**
+ * The code UI feature. It introduces the Code button.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class CodeUI extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'CodeUI';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ const t = editor.t;
+
+ // Add code button to feature components.
+ editor.ui.componentFactory.add( CODE, locale => {
+ const command = editor.commands.get( CODE );
+ const view = new ButtonView( locale );
+
+ view.set( {
+ label: t( 'Code' ),
+ icon: codeIcon,
+ tooltip: true,
+ isToggleable: true
+ } );
+
+ view.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
+
+ // Execute command.
+ this.listenTo( view, 'execute', () => {
+ editor.execute( CODE );
+ editor.editing.view.focus();
+ } );
+
+ return view;
+ } );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/index.js b/packages/ckeditor5-basic-styles/_src/index.js
new file mode 100644
index 00000000000..9ce9fbd35cf
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/index.js
@@ -0,0 +1,30 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles
+ */
+
+export { default as Bold } from './bold';
+export { default as BoldEditing } from './bold/boldediting';
+export { default as BoldUI } from './bold/boldui';
+export { default as Code } from './code';
+export { default as CodeEditing } from './code/codeediting';
+export { default as CodeUI } from './code/codeui';
+export { default as Italic } from './italic';
+export { default as ItalicEditing } from './italic/italicediting';
+export { default as ItalicUI } from './italic/italicui';
+export { default as Strikethrough } from './strikethrough';
+export { default as StrikethroughEditing } from './strikethrough/strikethroughediting';
+export { default as StrikethroughUI } from './strikethrough/strikethroughui';
+export { default as Subscript } from './subscript';
+export { default as SubscriptEditing } from './subscript/subscriptediting';
+export { default as SubscriptUI } from './subscript/subscriptui';
+export { default as Superscript } from './superscript';
+export { default as SuperscriptEditing } from './superscript/superscriptediting';
+export { default as SuperscriptUI } from './superscript/superscriptui';
+export { default as Underline } from './underline';
+export { default as UnderlineEditing } from './underline/underlineediting';
+export { default as UnderlineUI } from './underline/underlineui';
diff --git a/packages/ckeditor5-basic-styles/_src/italic.js b/packages/ckeditor5-basic-styles/_src/italic.js
new file mode 100644
index 00000000000..5e8dcc60f56
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/italic.js
@@ -0,0 +1,39 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/italic
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import ItalicEditing from './italic/italicediting';
+import ItalicUI from './italic/italicui';
+
+/**
+ * The italic feature.
+ *
+ * For a detailed overview check the {@glink features/basic-styles Basic styles feature documentation}
+ * and the {@glink api/basic-styles package page}.
+ *
+ * This is a "glue" plugin which loads the {@link module:basic-styles/italic/italicediting~ItalicEditing} and
+ * {@link module:basic-styles/italic/italicui~ItalicUI} plugins.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class Italic extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get requires() {
+ return [ ItalicEditing, ItalicUI ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'Italic';
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/italic/italicediting.js b/packages/ckeditor5-basic-styles/_src/italic/italicediting.js
new file mode 100644
index 00000000000..99792c3b72d
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/italic/italicediting.js
@@ -0,0 +1,63 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/italic/italicediting
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import AttributeCommand from '../attributecommand';
+
+const ITALIC = 'italic';
+
+/**
+ * The italic editing feature.
+ *
+ * It registers the `'italic'` command, the Ctrl+I keystroke and introduces the `italic` attribute in the model
+ * which renders to the view as an `` element.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class ItalicEditing extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'ItalicEditing';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+
+ // Allow italic attribute on text nodes.
+ editor.model.schema.extend( '$text', { allowAttributes: ITALIC } );
+ editor.model.schema.setAttributeProperties( ITALIC, {
+ isFormatting: true,
+ copyOnEnter: true
+ } );
+
+ editor.conversion.attributeToElement( {
+ model: ITALIC,
+ view: 'i',
+ upcastAlso: [
+ 'em',
+ {
+ styles: {
+ 'font-style': 'italic'
+ }
+ }
+ ]
+ } );
+
+ // Create italic command.
+ editor.commands.add( ITALIC, new AttributeCommand( editor, ITALIC ) );
+
+ // Set the Ctrl+I keystroke.
+ editor.keystrokes.set( 'CTRL+I', ITALIC );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/italic/italicui.js b/packages/ckeditor5-basic-styles/_src/italic/italicui.js
new file mode 100644
index 00000000000..2e805c8d498
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/italic/italicui.js
@@ -0,0 +1,61 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/italic/italicui
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import { ButtonView } from 'ckeditor5/src/ui';
+
+import italicIcon from '../../theme/icons/italic.svg';
+
+const ITALIC = 'italic';
+
+/**
+ * The italic UI feature. It introduces the Italic button.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class ItalicUI extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'ItalicUI';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ const t = editor.t;
+
+ // Add bold button to feature components.
+ editor.ui.componentFactory.add( ITALIC, locale => {
+ const command = editor.commands.get( ITALIC );
+ const view = new ButtonView( locale );
+
+ view.set( {
+ label: t( 'Italic' ),
+ icon: italicIcon,
+ keystroke: 'CTRL+I',
+ tooltip: true,
+ isToggleable: true
+ } );
+
+ view.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
+
+ // Execute command.
+ this.listenTo( view, 'execute', () => {
+ editor.execute( ITALIC );
+ editor.editing.view.focus();
+ } );
+
+ return view;
+ } );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/strikethrough.js b/packages/ckeditor5-basic-styles/_src/strikethrough.js
new file mode 100644
index 00000000000..cbf6b5f7353
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/strikethrough.js
@@ -0,0 +1,39 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/strikethrough
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import StrikethroughEditing from './strikethrough/strikethroughediting';
+import StrikethroughUI from './strikethrough/strikethroughui';
+
+/**
+ * The strikethrough feature.
+ *
+ * For a detailed overview check the {@glink features/basic-styles Basic styles feature documentation}
+ * and the {@glink api/basic-styles package page}.
+ *
+ * This is a "glue" plugin which loads the {@link module:basic-styles/strikethrough/strikethroughediting~StrikethroughEditing} and
+ * {@link module:basic-styles/strikethrough/strikethroughui~StrikethroughUI} plugins.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class Strikethrough extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get requires() {
+ return [ StrikethroughEditing, StrikethroughUI ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'Strikethrough';
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/strikethrough/strikethroughediting.js b/packages/ckeditor5-basic-styles/_src/strikethrough/strikethroughediting.js
new file mode 100644
index 00000000000..da34f71ec9e
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/strikethrough/strikethroughediting.js
@@ -0,0 +1,65 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/strikethrough/strikethroughediting
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import AttributeCommand from '../attributecommand';
+
+const STRIKETHROUGH = 'strikethrough';
+
+/**
+ * The strikethrough editing feature.
+ *
+ * It registers the `'strikethrough'` command, the Ctrl+Shift+X keystroke and introduces the
+ * `strikethroughsthrough` attribute in the model which renders to the view
+ * as a `` element.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class StrikethroughEditing extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'StrikethroughEditing';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+
+ // Allow strikethrough attribute on text nodes.
+ editor.model.schema.extend( '$text', { allowAttributes: STRIKETHROUGH } );
+ editor.model.schema.setAttributeProperties( STRIKETHROUGH, {
+ isFormatting: true,
+ copyOnEnter: true
+ } );
+
+ editor.conversion.attributeToElement( {
+ model: STRIKETHROUGH,
+ view: 's',
+ upcastAlso: [
+ 'del',
+ 'strike',
+ {
+ styles: {
+ 'text-decoration': 'line-through'
+ }
+ }
+ ]
+ } );
+
+ // Create strikethrough command.
+ editor.commands.add( STRIKETHROUGH, new AttributeCommand( editor, STRIKETHROUGH ) );
+
+ // Set the Ctrl+Shift+X keystroke.
+ editor.keystrokes.set( 'CTRL+SHIFT+X', 'strikethrough' );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/strikethrough/strikethroughui.js b/packages/ckeditor5-basic-styles/_src/strikethrough/strikethroughui.js
new file mode 100644
index 00000000000..256b88c53e6
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/strikethrough/strikethroughui.js
@@ -0,0 +1,61 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/strikethrough/strikethroughui
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import { ButtonView } from 'ckeditor5/src/ui';
+
+import strikethroughIcon from '../../theme/icons/strikethrough.svg';
+
+const STRIKETHROUGH = 'strikethrough';
+
+/**
+ * The strikethrough UI feature. It introduces the Strikethrough button.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class StrikethroughUI extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'StrikethroughUI';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ const t = editor.t;
+
+ // Add strikethrough button to feature components.
+ editor.ui.componentFactory.add( STRIKETHROUGH, locale => {
+ const command = editor.commands.get( STRIKETHROUGH );
+ const view = new ButtonView( locale );
+
+ view.set( {
+ label: t( 'Strikethrough' ),
+ icon: strikethroughIcon,
+ keystroke: 'CTRL+SHIFT+X',
+ tooltip: true,
+ isToggleable: true
+ } );
+
+ view.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
+
+ // Execute command.
+ this.listenTo( view, 'execute', () => {
+ editor.execute( STRIKETHROUGH );
+ editor.editing.view.focus();
+ } );
+
+ return view;
+ } );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/subscript.js b/packages/ckeditor5-basic-styles/_src/subscript.js
new file mode 100644
index 00000000000..19e44dc9d76
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/subscript.js
@@ -0,0 +1,36 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/subscript
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import SubscriptEditing from './subscript/subscriptediting';
+import SubscriptUI from './subscript/subscriptui';
+
+/**
+ * The subscript feature.
+ *
+ * It loads the {@link module:basic-styles/subscript/subscriptediting~SubscriptEditing} and
+ * {@link module:basic-styles/subscript/subscriptui~SubscriptUI} plugins.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class Subscript extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get requires() {
+ return [ SubscriptEditing, SubscriptUI ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'Subscript';
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/subscript/subscriptediting.js b/packages/ckeditor5-basic-styles/_src/subscript/subscriptediting.js
new file mode 100644
index 00000000000..c2576fd745c
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/subscript/subscriptediting.js
@@ -0,0 +1,60 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/subscript/subscriptediting
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import AttributeCommand from '../attributecommand';
+
+const SUBSCRIPT = 'subscript';
+
+/**
+ * The subscript editing feature.
+ *
+ * It registers the `sub` command and introduces the `sub` attribute in the model which renders to the view
+ * as a `` element.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class SubscriptEditing extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'SubscriptEditing';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ // Allow sub attribute on text nodes.
+ editor.model.schema.extend( '$text', { allowAttributes: SUBSCRIPT } );
+ editor.model.schema.setAttributeProperties( SUBSCRIPT, {
+ isFormatting: true,
+ copyOnEnter: true
+ } );
+
+ // Build converter from model to view for data and editing pipelines.
+
+ editor.conversion.attributeToElement( {
+ model: SUBSCRIPT,
+ view: 'sub',
+ upcastAlso: [
+ {
+ styles: {
+ 'vertical-align': 'sub'
+ }
+ }
+ ]
+ } );
+
+ // Create sub command.
+ editor.commands.add( SUBSCRIPT, new AttributeCommand( editor, SUBSCRIPT ) );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/subscript/subscriptui.js b/packages/ckeditor5-basic-styles/_src/subscript/subscriptui.js
new file mode 100644
index 00000000000..f7b9a64ff28
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/subscript/subscriptui.js
@@ -0,0 +1,60 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/subscript/subscriptui
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import { ButtonView } from 'ckeditor5/src/ui';
+
+import subscriptIcon from '../../theme/icons/subscript.svg';
+
+const SUBSCRIPT = 'subscript';
+
+/**
+ * The subscript UI feature. It introduces the Subscript button.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class SubscriptUI extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'SubscriptUI';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ const t = editor.t;
+
+ // Add subscript button to feature components.
+ editor.ui.componentFactory.add( SUBSCRIPT, locale => {
+ const command = editor.commands.get( SUBSCRIPT );
+ const view = new ButtonView( locale );
+
+ view.set( {
+ label: t( 'Subscript' ),
+ icon: subscriptIcon,
+ tooltip: true,
+ isToggleable: true
+ } );
+
+ view.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
+
+ // Execute command.
+ this.listenTo( view, 'execute', () => {
+ editor.execute( SUBSCRIPT );
+ editor.editing.view.focus();
+ } );
+
+ return view;
+ } );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/superscript.js b/packages/ckeditor5-basic-styles/_src/superscript.js
new file mode 100644
index 00000000000..c82f598320e
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/superscript.js
@@ -0,0 +1,36 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/superscript
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import SuperscriptEditing from './superscript/superscriptediting';
+import SuperscriptUI from './superscript/superscriptui';
+
+/**
+ * The superscript feature.
+ *
+ * It loads the {@link module:basic-styles/superscript/superscriptediting~SuperscriptEditing} and
+ * {@link module:basic-styles/superscript/superscriptui~SuperscriptUI} plugins.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class Superscript extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get requires() {
+ return [ SuperscriptEditing, SuperscriptUI ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'Superscript';
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/superscript/superscriptediting.js b/packages/ckeditor5-basic-styles/_src/superscript/superscriptediting.js
new file mode 100644
index 00000000000..1b3fb1e016d
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/superscript/superscriptediting.js
@@ -0,0 +1,60 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/superscript/superscriptediting
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import AttributeCommand from '../attributecommand';
+
+const SUPERSCRIPT = 'superscript';
+
+/**
+ * The superscript editing feature.
+ *
+ * It registers the `super` command and introduces the `super` attribute in the model which renders to the view
+ * as a `` element.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class SuperscriptEditing extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'SuperscriptEditing';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ // Allow super attribute on text nodes.
+ editor.model.schema.extend( '$text', { allowAttributes: SUPERSCRIPT } );
+ editor.model.schema.setAttributeProperties( SUPERSCRIPT, {
+ isFormatting: true,
+ copyOnEnter: true
+ } );
+
+ // Build converter from model to view for data and editing pipelines.
+
+ editor.conversion.attributeToElement( {
+ model: SUPERSCRIPT,
+ view: 'sup',
+ upcastAlso: [
+ {
+ styles: {
+ 'vertical-align': 'super'
+ }
+ }
+ ]
+ } );
+
+ // Create super command.
+ editor.commands.add( SUPERSCRIPT, new AttributeCommand( editor, SUPERSCRIPT ) );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/superscript/superscriptui.js b/packages/ckeditor5-basic-styles/_src/superscript/superscriptui.js
new file mode 100644
index 00000000000..0a9c3da61b3
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/superscript/superscriptui.js
@@ -0,0 +1,60 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/superscript/superscriptui
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import { ButtonView } from 'ckeditor5/src/ui';
+
+import superscriptIcon from '../../theme/icons/superscript.svg';
+
+const SUPERSCRIPT = 'superscript';
+
+/**
+ * The superscript UI feature. It introduces the Superscript button.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class SuperscriptUI extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'SuperscriptUI';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ const t = editor.t;
+
+ // Add superscript button to feature components.
+ editor.ui.componentFactory.add( SUPERSCRIPT, locale => {
+ const command = editor.commands.get( SUPERSCRIPT );
+ const view = new ButtonView( locale );
+
+ view.set( {
+ label: t( 'Superscript' ),
+ icon: superscriptIcon,
+ tooltip: true,
+ isToggleable: true
+ } );
+
+ view.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
+
+ // Execute command.
+ this.listenTo( view, 'execute', () => {
+ editor.execute( SUPERSCRIPT );
+ editor.editing.view.focus();
+ } );
+
+ return view;
+ } );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/underline.js b/packages/ckeditor5-basic-styles/_src/underline.js
new file mode 100644
index 00000000000..5488cab2e40
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/underline.js
@@ -0,0 +1,39 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/underline
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import UnderlineEditing from './underline/underlineediting';
+import UnderlineUI from './underline/underlineui';
+
+/**
+ * The underline feature.
+ *
+ * For a detailed overview check the {@glink features/basic-styles Basic styles feature documentation}
+ * and the {@glink api/basic-styles package page}.
+ *
+ * This is a "glue" plugin which loads the {@link module:basic-styles/underline/underlineediting~UnderlineEditing} and
+ * {@link module:basic-styles/underline/underlineui~UnderlineUI} plugins.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class Underline extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get requires() {
+ return [ UnderlineEditing, UnderlineUI ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'Underline';
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/underline/underlineediting.js b/packages/ckeditor5-basic-styles/_src/underline/underlineediting.js
new file mode 100644
index 00000000000..e12f1577a29
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/underline/underlineediting.js
@@ -0,0 +1,60 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/underline/underlineediting
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import AttributeCommand from '../attributecommand';
+
+const UNDERLINE = 'underline';
+
+/**
+ * The underline editing feature.
+ *
+ * It registers the `'underline'` command, the Ctrl+U keystroke
+ * and introduces the `underline` attribute in the model which renders to the view as an `` element.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class UnderlineEditing extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'UnderlineEditing';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+
+ // Allow strikethrough attribute on text nodes.
+ editor.model.schema.extend( '$text', { allowAttributes: UNDERLINE } );
+ editor.model.schema.setAttributeProperties( UNDERLINE, {
+ isFormatting: true,
+ copyOnEnter: true
+ } );
+
+ editor.conversion.attributeToElement( {
+ model: UNDERLINE,
+ view: 'u',
+ upcastAlso: {
+ styles: {
+ 'text-decoration': 'underline'
+ }
+ }
+ } );
+
+ // Create underline command.
+ editor.commands.add( UNDERLINE, new AttributeCommand( editor, UNDERLINE ) );
+
+ // Set the Ctrl+U keystroke.
+ editor.keystrokes.set( 'CTRL+U', 'underline' );
+ }
+}
diff --git a/packages/ckeditor5-basic-styles/_src/underline/underlineui.js b/packages/ckeditor5-basic-styles/_src/underline/underlineui.js
new file mode 100644
index 00000000000..4575a049ead
--- /dev/null
+++ b/packages/ckeditor5-basic-styles/_src/underline/underlineui.js
@@ -0,0 +1,61 @@
+/**
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module basic-styles/underline/underlineui
+ */
+
+import { Plugin } from 'ckeditor5/src/core';
+import { ButtonView } from 'ckeditor5/src/ui';
+
+import underlineIcon from '../../theme/icons/underline.svg';
+
+const UNDERLINE = 'underline';
+
+/**
+ * The underline UI feature. It introduces the Underline button.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class UnderlineUI extends Plugin {
+ /**
+ * @inheritDoc
+ */
+ static get pluginName() {
+ return 'UnderlineUI';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ init() {
+ const editor = this.editor;
+ const t = editor.t;
+
+ // Add bold button to feature components.
+ editor.ui.componentFactory.add( UNDERLINE, locale => {
+ const command = editor.commands.get( UNDERLINE );
+ const view = new ButtonView( locale );
+
+ view.set( {
+ label: t( 'Underline' ),
+ icon: underlineIcon,
+ keystroke: 'CTRL+U',
+ tooltip: true,
+ isToggleable: true
+ } );
+
+ view.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );
+
+ // Execute command.
+ this.listenTo( view, 'execute', () => {
+ editor.execute( UNDERLINE );
+ editor.editing.view.focus();
+ } );
+
+ return view;
+ } );
+ }
+}