Configure special characters

Not all users recall the keyboard shortcuts for special characters such as "en dash" or "em dash", non breaking spaces, currency symbols and so on. This guide explains how several of Fonto Editor's features can be configured to make those symbols more accessible.

What you need

Before you start this guide you should already have an editor configuration. We'll use the recipe editor as a starting point. Moreover, it helps to already have a masthead configured.

Fonto Editor does not restrict which characters a user can insert using their keyboard, or copy-pasting from another application. The steps that we'll go through in this guide are designed to make inserting these characters more accessible through the editor's own interface.

1

Install the special characters add-on

This add-on gives you access to the API's that we'll use, and provides a few UI components such as the SymbolsGrid, RecentSymbolsGrid and special characters modal.

A user-friendly way of installing an add-on is by using the fdt editor add-ons command in your terminal from anywhere within your editor configuration.

You can install the special characters add-on without additional prompts by using that command with a few options:

Shell

fdt editor add-ons --non-interactive --add fontoxml-special-characters
2

Create a package

Create a folder called recipe-special-characters/ in your packages/ directory. We'll use this folder to contain all the character sets and operations that we add in later steps.

Don't forget to also add a dependency to this package! The best location to do that is from config/fonto-manifest.json. You'll notice this is also where a dependency on fontoxml-special-characters is added after Step 1!

Make sure config/fonto-manifest.json contains at least the following:

JSON

{
	"dependencies": {
		"fontoxml-platform-base": "platform/fontoxml-platform-base",
		"fontoxml-special-characters": "platform/fontoxml-special-characters",
		"recipe-special-characters": "packages/recipe-special-characters"
	}
}
3

Add some character sets

A character set is a group of special characters registered with the specialCharactersManager. Registering those lists makes them accessible to the UI components that use them.

You should choose which characters you want in any particular set based on your users' use cases. For example, some industries may prefer to use a character set with mathematical symbols or arrows, whereas another industry may find the Greek alphabet more relevant.

For the recipe editor that we're starting out with, a character set with fractions and one with emojis are probably relevant.

Using the specialCharactersManager API we can create a file called src/install.js in our package and register our first set with the following code;

JavaScript

import specialCharactersManager from 'fontoxml-special-characters/src/specialCharactersManager.js';

export default function install() {
	specialCharactersManager.addCharacterSet('fractions', [
		{
			codePoints: ['U+2155'],
			id: 'U+2155',
			labels: ['Number Forms'],
			name: 'Vulgar fraction one fifth'
		},
		{
			codePoints: ['U+00BC'],
			id: 'U+00BC',
			labels: ['Latin-1 Supplement'],
			name: 'Vulgar fraction one quarter'
		},
		{
			codePoints: ['U+2153'],
			id: 'U+2153',
			labels: ['Number Forms'],
			name: 'Vulgar fraction one third'
		},
		{
			codePoints: ['U+2156'],
			id: 'U+2156',
			labels: ['Number Forms'],
			name: 'Vulgar fraction two fifths'
		},
		{
			codePoints: ['U+00BD'],
			id: 'U+00BD',
			labels: ['Latin-1 Supplement'],
			name: 'Vulgar fraction one half'
		},
		{
			codePoints: ['U+2157'],
			id: 'U+2157',
			labels: ['Number Forms'],
			name: 'Vulgar fraction three fifths'
		},
		{
			codePoints: ['U+2154'],
			id: 'U+2154',
			labels: ['Number Forms'],
			name: 'Vulgar fraction two thirds'
		},
		{
			codePoints: ['U+2158'],
			id: 'U+2158',
			labels: ['Number Forms'],
			name: 'Vulgar fraction four fifths'
		},
		{
			codePoints: ['U+00BE'],
			id: 'U+00BE',
			labels: ['Latin-1 Supplement'],
			name: 'Vulgar fraction three quarters'
		}
	]);
}

You can use vanilla Javascript to look up the code points associated with a character! You can combine the codePointAt method on String with the toString method on Number. Keep in mind that characters can consist of multiple code points!

The following code looks up the code point associated with an emoji, and converts it to a hexidecimal value:

JavaScript

'πŸ”₯'.codePointAt(0).toString(16)

Using that trick, we can more easily add our second character set:

JavaScript

specialCharactersManager.addCharacterSet(
	'emojis',
	Array.from('πŸ˜€πŸ˜ƒπŸ˜„πŸ˜πŸ˜†πŸ˜…πŸ˜‚πŸ€£πŸ˜ŠπŸ˜‡πŸ™‚πŸ™ƒπŸ˜‰').map((character) => ({
		codePoints: Array.from(character).map(
			(char) => `U+${char.codePointAt(0).toString(16)}`
		),
		id: character
	}))
);

Notice that we didn't add a labels and name property to each object? That's because those properties are only used by the special characters modal. We will be using a different component in the next step.

4

Create a drop-down component

This is the part where we're making our favorite special characters really easy to find by adding them to the masthead. We'll use the SymbolsGrid component, which is designed to be used in a drop-down such as ButtonWithDrop. It works well in any place where you would normally use a MenuItem or FxOperationMenuItem, so you can put it in a sub-menu of a dropdown too.

To keep our masthead code lean and mean, we can create a new component in our recipe-special-characters package to compose the drop button in.

Create a file called packages/recipe-special-characters/src/SpecialCharactersButton.jsx and give it the following contents:

JSX

import { ButtonWithDrop, Drop, Menu, MenuGroup, MenuItemWithDrop } from 'fds/components';
import FxOperationMenuItem from 'fontoxml-fx/src/FxOperationMenuItem.jsx';
import t from 'fontoxml-localization/src/t.js';
import SymbolsGrid from 'fontoxml-special-characters/src/SymbolsGrid.jsx';
import React from 'react';

export default function SpecialCharacterDropButton({
	icon = 'omega',
	label = '',
	tooltipContent = t('Insert a symbol.')
}) {
	return (
		<ButtonWithDrop
			icon={icon}
			label={label}
			tooltipContent={tooltipContent}
			renderDrop={({ closeDrop }) => (
				<Drop>
					<Menu>
						<MenuGroup>
							<MenuItemWithDrop
								label={t('Fractions')}
								renderDrop={({ closeOuterDrop }) => (
									<Drop>
										<SymbolsGrid
											characterSet="fractions"
											columns={5}
											onItemClick={closeOuterDrop}
										/>
									</Drop>
								)}
							/>
							<MenuItemWithDrop
								label={t('Emojis')}
								renderDrop={({ closeOuterDrop }) => (
									<Drop>
										<SymbolsGrid
											characterSet="emojis"
											columns={5}
											onItemClick={closeOuterDrop}
										/>
									</Drop>
								)}
							/>
						</MenuGroup>
					</Menu>
				</Drop>
			)}
		/>
	);
}
5

Add drop-down into the masthead

Open packages/editor-masthead/src/toolbars/ExampleToolbar.jsx or whichever file you've used to configure one of the toolbars in your masthead.

You can import the React component we made in the previous step and give it a nice place;

JSX

const ExampleToolbar = () => (
	<MastheadToolbar>
		<MastheadToolbarButtons>
			<FxOperationButton operationName="toggle-bold" />
			<FxOperationButton operationName="toggle-italic" />
			<FxOperationButton operationName="toggle-underline" />
		</MastheadToolbarButtons>
		<MastheadToolbarButtons>
			<SpecialCharactersButton />
		</MastheadToolbarButtons>
	</MastheadToolbar>
);

We're pretty far along already, your masthead should look a little like this:

With a few more steps we'll add in quick access to the users' most recently used special characters, and give the user access to the special characters modal that contains almost 4000 special characters and an interface to search them.

6

Add the recently used characters to the drop-down

This step is actually pretty easy, all that we need to do is add another component to the packages/recipe-special-characters/src/SpecialCharactersButton.jsx file that we created earlier. Instead of the SymbolsGrid component we'll use RecentSymbolsGrid.

Open SpecialCharactersButton.jsx back up, and at the top of the menu add in the RecentSymbolsGrid component according to its documentation.

Your code should end up looking a little like the following (truncated) example:

JSX

import RecentSymbolsGrid from 'fontoxml-special-characters/src/RecentSymbolsGrid.jsx';

export default function SpecialCharacterDropButton({
	icon = 'omega',
	label = '',
	tooltipContent = t('Insert a symbol.')
}) {
	return (
		<ButtonWithDrop
			icon={icon}
			label={label}
			renderDrop={({ closeDrop }) => (
				<Drop>
					<Menu>
						<MenuGroup>
							<RecentSymbolsGrid
								fallbackCharacterSet="quick-access-grid"
								maxCharacters={10}
								columns={5}
								onItemClick={closeDrop}
							/>
						</MenuGroup>

The reference to "quick-access-grid" is another character set, that you can add as per Step 3. The characters in this set are slowly replaced with the most recently inserted characters as the user uses the dropdown or modal.

7

Add a button for the special characters modal to the drop-down

The cherry on top of special characters is the modal to rule them all. We can use an operation that comes with the special characters add-on without further configuration, default-special-character-insert. Because we've used a drop-down menu so far, adding another FxOperationMenuItem to it is easy!

To the bottom of your drop-down menu, add the FxOperationMenuItem so that it looks a little like this (truncated):

JSX

						</MenuGroup>

						<MenuGroup>
							<FxOperationMenuItem
								label={t('All symbols')}
								operationName="default-special-character-insert"
							/>
						</MenuGroup>
					</Menu>
				</Drop>
			)}
		/>
	);
}

When opened, the modal will look like this:

Alternatively, you can compose your own modal by using the open-special-character-modal operation directly and passing it the name of a character set that you've assembled yourself.

Your toolbar now has a nifty component that provides access to the most useful special characters as categorized by you, as well as the most recently used special characters, and access to the modal with all available special characters.

8

Optionally, add keybindings for special characters

Inserting a special character is technically the same as inserting any other character. We can therefore use operations to associate inserting one special character or another with a key binding.

On top of the special characters normally supported by the keyboard or operating system, Fonto Editor SDK 7.14 and onwards provide additional key bindings familiar from Microsoft Word. See also Shortcut keys.

Create file packages/recipe-special-characters/src/operations.json and give it the following contents. You can add more operations in the same file for whichever characters and keybindings you want, as long as the operation names are unique.

JSON

{
	"_insert-special-character:smile": {
		"keyBinding": "ctrl+s",
		"osxKeyBinding": "cmd+s",
		"steps": [
			{
				"type": "operation/insert-text",
				"data": {
					"text": "πŸ˜„"
				}
			}
		]
	}
}

Notice that in operations.json we can use the special character directly, without referring to its codepoint.