Skip to content

Commit

Permalink
Not displaying unsupported emoji in the emoji picker and mention plugin.
Browse files Browse the repository at this point in the history
  • Loading branch information
martnpaneq committed Dec 30, 2024
1 parent 9697c88 commit de14e29
Showing 1 changed file with 50 additions and 6 deletions.
56 changes: 50 additions & 6 deletions packages/ckeditor5-emoji/src/emojipicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,20 @@ export default class EmojiPicker extends Plugin {
databaseId: number; title: string; exampleEmoji: string;
} ): Promise<EmojiGroup> {
const databaseGroup = await this._emojiDatabase.getEmojiByGroup( databaseId );

return {
title,
exampleEmoji,
items: databaseGroup.map( item => {
const container = this._createEmojiWidthTestingContainer();
const baselineEmojiWidth = this._getNodeWidth( container, '🙂' );

const items = databaseGroup
.filter( item => {
const emojiWidth = this._getNodeWidth( container, item.unicode );

// On Windows, some supported emoji are ~50% bigger than the baseline emoji, but what we really want to guard
// against are the ones that are 2x the size, because those are truly broken (person with red hair = person with
// floating red wig, black cat = cat with black square, polar bear = bear with snowflake, etc.)
// So here we set the threshold at 1.8 times the size of the baseline emoji.
return ( emojiWidth / 1.8 < baselineEmojiWidth ) && ( emojiWidth >= baselineEmojiWidth );
} )
.map( item => {
const name = item.annotation;
const emojis = [ item.unicode ];

Expand All @@ -182,7 +191,15 @@ export default class EmojiPicker extends Plugin {
this._emojis.set( name, emojis );

return { name, emojis };
} )
} );

// Clean up width testing container.
document.body.removeChild( container );

return {
title,
exampleEmoji,
items
};
}

Expand Down Expand Up @@ -432,6 +449,33 @@ export default class EmojiPicker extends Plugin {
} );
}
}

/**
* Creates a div for emoji width testing purposes.
*/
private _createEmojiWidthTestingContainer(): HTMLDivElement {
const container = document.createElement( 'div' );
container.style.position = 'absolute';
container.style.left = '-9999px';
container.style.whiteSpace = 'nowrap';
container.style.fontSize = '24px';
document.body.appendChild( container );

return container;
}

/**
* Returns the width of the provided node.
*/
private _getNodeWidth( container: HTMLDivElement, node: string ): number {
const span = document.createElement( 'span' );
span.textContent = node;
container.appendChild( span );
const nodeWidth = span.offsetWidth;
container.removeChild( span );

return nodeWidth;
}
}

export interface DropdownPanelContent {
Expand Down

0 comments on commit de14e29

Please sign in to comment.