npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

quill-emoji-parser

v0.9.2

Published

Transform punctuation or shortcode emojis into their visual counterpart while typing or pasting.

Downloads

9

Readme

quill-emoji-parser


npm version License: MIT FOSSA Status

Checks for emojis shortcuts during typing and pasting and replace them by their visual counterpart.

Very much inspired by quill-magic-url and the answer to this Stack Overflow question. Default map is taken from Smile2Emoji 🙏.

Demo

A demo is available here: Quill Emoji Parser

Install

From CDN

<!-- For full module with map included, after quill script includes -->
<script src="https://unpkg.com/[email protected]/dist/quill-emoji-parser.map-incl.min.js"></script>

<!-- For base module without map included, after quill script includes -->
<script src="https://unpkg.com/[email protected]/dist/quill-emoji-parser.min.js"></script>

<!-- Import default emojis map, named EmojiMap -->
<script src="https://unpkg.com/[email protected]/dist/quill-emoji-parser.default-map.min.js"></script>

With NPM or Yarn

npm install quill-emoji-parser

yarn add quill-emoji-parser

With default emojis map included

import Quill from 'quill';
import EmojiParser from 'quill-emoji-parser';

Quill.register('modules/emojiParser', EmojiParser);

With no emojis map included

import Quill from 'quill';
import EmojiParser from 'quill-emoji-parser/base';
// Optionally import default map.
// import { EmojiMap } from 'quill-emoji-parser/default-map';

Quill.register('modules/emojiParser', EmojiParser);

Usage

Basic usage with no options and default map:

const quill = new Quill(editor, {
  modules: {
    // When module was imported with map included (default).
    emojiParser: true,

    // When module was imported with
    // import EmojiParser from 'quill-emoji-parser/base;
    // import { EmojiMap } from 'quill-emoji-parser/default-map;
    emojiParser: {
      map: EmojiMap,
    },

    // When module was included with script tags, to use default map.
    emojiParser: {
      map: EmojiMap.default,
    },
  },
});

Usage with custom options:

const quill = new Quill(editor, {
  modules: {
    emojiParser: {
      // Will remove shortcuts between ':'.
      bypassShortcuts: /:[a-z0-9_-]*:/i,
      // Will remove specific emojis.
      bypassEmojis: ['😈', '😜'],

      // For other options, see below...
    },
  },
});

Options

When importing full package with default map, all options are undefined or false by default. If module was imported without map (ie. ... from 'quill-emoji-parser/base'), you need to explicitly provide a map.

export interface EmojiParserOptions {
  // A custom map to use (mandatory when importing 'base' package).
  map?: Record<string, string>;
  // Shortcuts to be bypassed.
  bypassShortcuts?: RegExp | Array<string> | string;
  // Emojis to be bypassed.
  bypassEmojis?: RegExp | Array<string> | string;
  // The `onblur` behavior.
  parseOnBlur?: boolean;

  // Fired when plugin is instantiated. Gives access to some of its methods.
  onInstance?: (instance: EmojiParserInstance) => void;
  // Fired before parsing the clipboard content.
  onBeforePaste?: (node?: string, delta?: typeof Delta) => void;
  // Fired after parsing the clipboard content.
  onPasted?: (node?: string, delta?: typeof Delta) => void;
  // Fired before parsing typed text.
  onBeforeTextChange?: (delta?: typeof Delta) => void;
  // Fired after parsing typed text.
  onTextChanged?: (delta?: typeof Delta) => void;
  // Fired before each parsed shortcut.
  onBeforeUpdate?: (shortcut?: string, emoji?: string) => boolean | undefined;
  // Fired after a shortcut has been parsed.
  onUpdated?: (
    shortcut?: string,
    emoji?: string,
    delta?: typeof Delta,
    selection?: RangeStatic | null
  ) => void;
}

map

Imports a custom shortcut-to-replacement map. That means that you can eventually use quill-emoji-parser as a... anything parser... With some limitations... Use at your own risk!

To avoid importing the full package when providing a custom map: > import EmojiParser from 'quill-emoji-parser/base';

Record<string, string>;

Example

const myMap = {
  smile: '😄', // A sentence like 'I smile everyday!' will be transformed in 'I 😄 everyday!'
};

// ...

modules: {
  emojiParser: {
    map: myMap;
  }
}

bypassShortcuts

Disallow the transformation of some shortcuts from the emoji map. In the example below :poop: will not be parsed, but :hankey: will. Note that the string will be kept, unlike in bypassEmojis that will delete the pasted emoji from the content.

RegExp | Array<string> | string;

Example

// ...

modules: {
    emojiParser: {
        bypassShortcuts: /(:([^:]+):)/gi,
    }

    // or

    emojiParser: {
        // Strings separated by space.
        bypassShortcuts: ':open_mouth: :poop:'
    }

    // or

    emojiParser: {
        // Array of strings.
        bypassShortcuts: [':open_mouth:', ':poop:']
    }
}

bypassEmojis

Remove some emojis from the emoji map. That means that typed shortcut will not be parsed, and that a pasted blacklisted emoji will be deleted. For example, typing or pasting :poop: or :hankey: will not be parsed, but will be kept as text, and pasting :poop: will simply be deleted from the content.

RegExp | Array<string> | string;

Example

// ...

modules: {
    emojiParser: {
        // Removes some emojis...
        bypassEmojis: /\p{Emoji_Presentation}/gu,
    }

    // or

    emojiParser: {
        // Strings separated by space.
        bypassEmojis: '😮 💩'
    }

    // or

    emojiParser: {
        // Array of strings.
        bypassEmojis: ['😮', '💩']
    }
}

parseOnBlur

Performs a last check before the editor lose focus.

boolean;

Example

// ...

modules: {
  emojiParser: {
    parseOnBlur: true,
  }
}

onInstance

Function called when the module has been instantiated. The returned EmojiParserInstance object exposes some methods to dynamically change the module behavior.

onInstance?: (instance: EmojiParserInstance) => void;

export interface EmojiParserInstance {
  // Refresh the whole content by performing a kind of copy/paste action.
  refresh: () => void;
  // Dynamically add or remove shortcuts to be bypassed.
  // When a bypassed shortcut is removed, note that enterign a space after a shortcut will
  // trigger parse function.
  bypassShortcuts: (
    shortcuts?: RegExp | Array<string> | string
  ) => Record<string, string> | undefined;
  // Dynamically add or remove emojis to be bypassed.
  // Same behavior.
  bypassEmojis: (
    shortcuts?: RegExp | Array<string> | string
  ) => Record<string, string> | undefined;
  // Dynamically change the `onblur` behavior.
  parseOnBlur: (value: boolean) => void;
}

Example


let emojiParser: EmojiParserInstance;

// ...

modules: {
  emojiParser: {
    onInstance(instance: EmojiParserInstance) {
        emojiParser = instance;
    }
  }
}

// ...

button.addEventListener('click', () => {
    emojiParser.refresh();
});

input.addEventListener('change', () => {
    emojiParser.bypassShortcuts(input.value);
});

onBeforePaste

Function called before parsing pasted text. At this time, you still can modify node and delta.

(node?: string, delta?: Delta) => void

Example

// ...

modules: {
    emojiParser: {
        onBeforePaste(node: string, delta: Delta) {
            // The original node
            console.log(node);
            // The original Delta.
            console.log(delta);
        }
    }
}

onPasted

Function called after parsing pasted text. Gives the resulting node and delta of the transformation.

(node?: string, delta?: Delta) => void

Example

// ...

modules: {
    emojiParser: {
        onPasted(node: string, delta: Delta) {
            // The parsed node
            console.log(node);
            // The parsed Delta.
            console.log(delta);
        }
    }
}

onBeforeTextChange

Function called when a character was typed, before parsing. No check was done yet, but we're sure that there is a Delta to check, and that it contains an insert of type string that is not only a space.

(delta?: Delta) => void;

Example

// ...

modules: {
    emojiParser: {
        onBeforeTextChange(delta: Delta) {
            // The original Delta.
            console.log(delta);
        }
    }
}

onTextChanged

Function called when a character was typed, after parsing. It returns the new Delta.

(delta?: Delta) => void;

Example

// ...

modules: {
    emojiParser: {
        onTextChanged(delta: Delta) {
            // The parsed Delta.
            console.log(delta);
        }
    }
}

onBeforeUpdate

Function called for each found emoji. It is the place to put conditions to further parsing. Returning false will bypass the shortcut-to-emoji transformation.

(shortcut?: string, emoji?: string) => boolean;

Example

// ...

modules: {
    emojiParser: {
        onBeforeUpdate(shortcut: string, emoji: string) {
            if (shortcut === ':poop') return false;
            if (emoji === '💩') return false;

            return true;
        }
    }
}

onUpdated

Function called after each emoji is succesfully parsed and rendered by the Quill editor. This module uses queueMicrotask to get the selection after Quill updated the DOM. That means that something else could happen between the transformation and its rendering in the editor.

( shortcut?: string, emoji?: string, delta?: Delta, selection?: RangeStatic | null) => void;

Example

// ...

modules: {
    emojiParser: {
        onUpdated(shortcut: string, emoji: string, delta: Delta, selection: RangeStatic | null) {
            // The shortcut that was parsed.
            console.log(shortcut);

            // The emoji found.
            console.log(emoji);

            // The modified delta.
            console.log(delta);

            // The selection after modification.
            console.log(selection);
        }
    }
}

Bundle size

| | UMD | UMD gzipped | Module | Module gzipped | | --------------- | -------- | ----------- | -------- | -------------- | | . | 22.37 kB | 8.94 kB | 29.47 kB | 9.49 kB | | ./base | 5.34 kB | 1.71 kB | 8.58 kB | 2.14 kB | | ./default-map | 17.43 kB | 7.39 kB | 21.03 kB | 7.35 kB |

Todos

  • [ ] Allow reverting transformation and keeping shortcuts on backspace input.
  • [ ] Tests
  • [x] Two entries: one with default map, one without map v0.9.0.

Known Bugs

  • [ ] When dynamically changing the bypass options, selection is not always accurate.

License

MIT © Benoît Lahoz

FOSSA Status