retext-emoji
Advanced tools
Comparing version 8.1.0 to 9.0.0
@@ -1,28 +0,34 @@ | ||
/** | ||
* Plugin to support emoji, gemoji, and emoticons. | ||
* | ||
* @type {import('unified').Plugin<[Options?], Root>} | ||
*/ | ||
export default function retextEmoji( | ||
options?: Options | undefined | ||
): | ||
| void | ||
| import('unified').Transformer<import('nlcst').Root, import('nlcst').Root> | ||
export type Root = import('nlcst').Root | ||
export type DoNotTouchAsThisImportIncludesEmoticonsInTree = | ||
typeof import('nlcst-emoticon-modifier') | ||
/** | ||
* Configuration. | ||
*/ | ||
export type Options = { | ||
/** | ||
* If, and *how* to convert (`'encode'` or `'decode'`, optional). | ||
* | ||
* When `encode` is given, converts short-codes and emoticons to their unicode | ||
* equivalent (`:heart:` and `<3` to `❤️`). | ||
* | ||
* When `decode` is given, converts unicode emoji and emoticons to their short-code | ||
* equivalent (`❤️` and `<3` to `:heart:`). | ||
*/ | ||
convert?: 'encode' | 'decode' | undefined | ||
export type {Options} from './lib/index.js' | ||
export {default} from './lib/index.js' | ||
// Add custom data supported when `retext-emoji` is added. | ||
declare module 'nlcst-emoticon-modifier' { | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions | ||
interface EmoticonData { | ||
/** | ||
* Emoji of emoticon node (example: `'😀'`). | ||
* | ||
* Registered by `retext-emoji`. | ||
*/ | ||
emoji?: string | ||
/** | ||
* Short description of emoticon node (example: `'grinning face'`). | ||
* | ||
* Registered by `retext-emoji`. | ||
*/ | ||
description?: string | ||
/** | ||
* Name of emoji (example: `['grinning']`). | ||
* | ||
* Registered by `retext-emoji`. | ||
*/ | ||
names?: string[] | ||
/** | ||
* Tags of emoji (example: `['smile', 'happy']`). | ||
* | ||
* Registered by `retext-emoji`. | ||
*/ | ||
tags?: string[] | ||
} | ||
} |
163
index.js
@@ -1,161 +0,2 @@ | ||
/** | ||
* @typedef {import('nlcst').Root} Root | ||
* | ||
* @typedef {import('nlcst-emoticon-modifier')} DoNotTouchAsThisImportIncludesEmoticonsInTree | ||
* | ||
* @typedef Options | ||
* Configuration. | ||
* @property {'encode'|'decode'} [convert] | ||
* If, and *how* to convert (`'encode'` or `'decode'`, optional). | ||
* | ||
* When `encode` is given, converts short-codes and emoticons to their unicode | ||
* equivalent (`:heart:` and `<3` to `❤️`). | ||
* | ||
* When `decode` is given, converts unicode emoji and emoticons to their short-code | ||
* equivalent (`❤️` and `<3` to `:heart:`). | ||
*/ | ||
import {affixEmoticonModifier} from 'nlcst-affix-emoticon-modifier' | ||
import {emoticonModifier} from 'nlcst-emoticon-modifier' | ||
import {emojiModifier} from 'nlcst-emoji-modifier' | ||
import {toString} from 'nlcst-to-string' | ||
import {visit} from 'unist-util-visit' | ||
import {emoticon} from 'emoticon' | ||
import {gemoji} from 'gemoji' | ||
const own = {}.hasOwnProperty | ||
const vs16 = 0xfe_0f | ||
/** @type {Record<string, gemoji[number]>} */ | ||
const emoji2info = {} | ||
/** @type {Record<string, string>} */ | ||
const emoticon2emoji = {} | ||
/** @type {Record<string, string>} */ | ||
const gemoji2emoji = {} | ||
/** | ||
* Map of visitors. | ||
* | ||
* @type {Record<string, (value: string) => string>} | ||
*/ | ||
const fns = { | ||
/** | ||
* Change to an emoji. | ||
* | ||
* @param {string} emoji | ||
* @returns {string} | ||
*/ | ||
encode: (emoji) => emoji, | ||
/** | ||
* Change to a GitHub emoji short-code. | ||
* | ||
* @param {string} emoji | ||
* @returns {string} | ||
*/ | ||
decode: (emoji) => ':' + emoji2info[emoji].names[0] + ':' | ||
} | ||
init() | ||
/** | ||
* Plugin to support emoji, gemoji, and emoticons. | ||
* | ||
* @type {import('unified').Plugin<[Options?], Root>} | ||
*/ | ||
export default function retextEmoji(options = {}) { | ||
const Parser = this.Parser | ||
// Hush. | ||
/* c8 ignore next */ | ||
if (!Parser) throw new Error('Expected parser') | ||
const convert = options.convert | ||
/** @type {fns[keyof fns]|undefined} */ | ||
let fn | ||
// Hush. | ||
// type-coverage:ignore-next-line | ||
const proto = Parser.prototype | ||
// Hush. | ||
// type-coverage:ignore-next-line | ||
proto.useFirst('tokenizeSentence', emoticonModifier) | ||
// Hush. | ||
// type-coverage:ignore-next-line | ||
proto.useFirst('tokenizeSentence', emojiModifier) | ||
// Hush. | ||
// type-coverage:ignore-next-line | ||
proto.useFirst('tokenizeParagraph', affixEmoticonModifier) | ||
if (convert !== null && convert !== undefined) { | ||
if (!Object.keys(fns).includes(convert)) { | ||
throw new TypeError( | ||
'Invalid `convert` value `' + | ||
convert + | ||
"`, expected `'encode'` or `'decode'`" | ||
) | ||
} | ||
fn = fns[convert] | ||
} | ||
return (node) => { | ||
visit(node, 'EmoticonNode', (node) => { | ||
const emoji = parse(toString(node)) | ||
if (!emoji) return | ||
if (fn) { | ||
node.value = fn(emoji) | ||
} | ||
const info = emoji2info[emoji] | ||
const data = node.data || (node.data = {}) | ||
data.emoji = info.emoji | ||
data.description = info.description | ||
data.names = info.names.concat() | ||
data.tags = info.tags.concat() | ||
}) | ||
} | ||
} | ||
/** | ||
* Map a value to an emoji. | ||
* | ||
* @param {string} value | ||
*/ | ||
function parse(value) { | ||
if (own.call(emoji2info, value)) return value | ||
if (own.call(emoticon2emoji, value)) return emoticon2emoji[value] | ||
if (own.call(gemoji2emoji, value)) return gemoji2emoji[value] | ||
if (value.charCodeAt(value.length - 1) === vs16) { | ||
const without = value.slice(0, -1) | ||
if (own.call(emoji2info, without)) return without | ||
} | ||
} | ||
// Construct dictionaries. | ||
function init() { | ||
let index = -1 | ||
while (++index < gemoji.length) { | ||
const info = gemoji[index] | ||
const values = info.names | ||
let offset = -1 | ||
emoji2info[info.emoji] = info | ||
while (++offset < values.length) { | ||
gemoji2emoji[':' + values[offset] + ':'] = info.emoji | ||
} | ||
} | ||
index = -1 | ||
while (++index < emoticon.length) { | ||
const info = emoticon[index] | ||
let offset = -1 | ||
while (++offset < info.emoticons.length) { | ||
emoticon2emoji[info.emoticons[offset]] = info.emoji | ||
} | ||
} | ||
} | ||
// Note: types exposed from `index.d.ts`. | ||
export {default} from './lib/index.js' |
{ | ||
"name": "retext-emoji", | ||
"version": "8.1.0", | ||
"version": "9.0.0", | ||
"description": "retext plugin to support emoji, gemoji, and emoticons", | ||
"license": "MIT", | ||
"keywords": [ | ||
"unified", | ||
"emoji", | ||
"emoticon", | ||
"gemoji", | ||
"plugin", | ||
"retext", | ||
"retext-plugin", | ||
"plugin", | ||
"gemoji", | ||
"emoticon", | ||
"emoji" | ||
"unified" | ||
], | ||
@@ -27,5 +27,5 @@ "repository": "retextjs/retext-emoji", | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"exports": "./index.js", | ||
"files": [ | ||
"lib/", | ||
"index.d.ts", | ||
@@ -35,47 +35,43 @@ "index.js" | ||
"dependencies": { | ||
"@types/nlcst": "^1.0.0", | ||
"@types/nlcst": "^2.0.0", | ||
"emoticon": "^4.0.0", | ||
"gemoji": "^7.0.0", | ||
"nlcst-affix-emoticon-modifier": "^2.0.0", | ||
"nlcst-emoji-modifier": "^5.0.0", | ||
"nlcst-emoticon-modifier": "^2.0.0", | ||
"nlcst-to-string": "^3.0.0", | ||
"unified": "^10.0.0", | ||
"unist-util-visit": "^4.0.0" | ||
"gemoji": "^8.0.0", | ||
"nlcst-affix-emoticon-modifier": "^3.0.0", | ||
"nlcst-emoji-modifier": "^6.0.0", | ||
"nlcst-emoticon-modifier": "^3.0.0", | ||
"nlcst-to-string": "^4.0.0", | ||
"unified": "^11.0.0", | ||
"unist-util-visit": "^5.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/tape": "^4.0.0", | ||
"c8": "^7.0.0", | ||
"prettier": "^2.0.0", | ||
"remark-cli": "^10.0.0", | ||
"@types/node": "^20.0.0", | ||
"c8": "^8.0.0", | ||
"prettier": "^3.0.0", | ||
"remark-cli": "^11.0.0", | ||
"remark-preset-wooorm": "^9.0.0", | ||
"retext": "^8.0.0", | ||
"rimraf": "^3.0.0", | ||
"tape": "^5.0.0", | ||
"retext": "^9.0.0", | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^4.0.0", | ||
"unist-builder": "^3.0.0", | ||
"xo": "^0.44.0" | ||
"typescript": "^5.0.0", | ||
"unist-builder": "^4.0.0", | ||
"xo": "^0.56.0" | ||
}, | ||
"scripts": { | ||
"build": "rimraf \"*.d.ts\" && tsc && type-coverage", | ||
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", | ||
"build": "tsc --build --clean && tsc --build && type-coverage", | ||
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix", | ||
"prepack": "npm run build && npm run format", | ||
"test": "npm run build && npm run format && npm run test-coverage", | ||
"test-api": "node --conditions development test.js", | ||
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node --conditions development test.js", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
"test-coverage": "c8 --100 --check-coverage --reporter lcov npm run test-api" | ||
}, | ||
"prettier": { | ||
"tabWidth": 2, | ||
"useTabs": false, | ||
"bracketSpacing": false, | ||
"singleQuote": true, | ||
"bracketSpacing": false, | ||
"semi": false, | ||
"trailingComma": "none" | ||
"tabWidth": 2, | ||
"trailingComma": "none", | ||
"useTabs": false | ||
}, | ||
"xo": { | ||
"prettier": true | ||
}, | ||
"remarkConfig": { | ||
"plugins": [ | ||
"preset-wooorm" | ||
"remark-preset-wooorm" | ||
] | ||
@@ -86,5 +82,12 @@ }, | ||
"detail": true, | ||
"strict": true, | ||
"ignoreCatch": true | ||
"ignoreCatch": true, | ||
"strict": true | ||
}, | ||
"xo": { | ||
"prettier": true, | ||
"rules": { | ||
"unicorn/prefer-code-point": "off", | ||
"unicorn/prefer-switch": "off" | ||
} | ||
} | ||
} |
159
readme.md
@@ -11,11 +11,38 @@ # retext-emoji | ||
[**retext**][retext] plugin to support emoji, gemoji, and emoticons. | ||
**[retext][]** plugin to support emoji (`❤️`), gemoji (`:heart:`), and | ||
emoticons (`<3`). | ||
## Contents | ||
* [What is this?](#what-is-this) | ||
* [When should I use this?](#when-should-i-use-this) | ||
* [Install](#install) | ||
* [Use](#use) | ||
* [API](#api) | ||
* [`unified().use(retextEmoji[, options])`](#unifieduseretextemoji-options) | ||
* [`Options`](#options) | ||
* [Data](#data) | ||
* [Syntax tree](#syntax-tree) | ||
* [Types](#types) | ||
* [Compatibility](#compatibility) | ||
* [Contribute](#contribute) | ||
* [License](#license) | ||
## What is this? | ||
This package is a [unified][] ([retext][]) plugin to classify emoji (`❤️`), | ||
gemoji (`:heart:`), and emoticons (`<3`) as a specific node, and to optionally | ||
transform them from one type to another. | ||
## When should I use this? | ||
You can either use this plugin any time there are emoji, gemoji, or emoticons | ||
in prose that are (incorrectly) warned about by linting plugins, or you can | ||
use it to transform them. | ||
## Install | ||
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): | ||
Node 12+ is needed to use it and it must be `import`ed instead of `require`d. | ||
This package is [ESM only][esm]. | ||
In Node.js (version 16+), install with [npm][]: | ||
[npm][]: | ||
```sh | ||
@@ -25,2 +52,16 @@ npm install retext-emoji | ||
In Deno with [`esm.sh`][esmsh]: | ||
```js | ||
import retextEmoji from 'https://esm.sh/retext-emoji@9' | ||
``` | ||
In browsers with [`esm.sh`][esmsh]: | ||
```html | ||
<script type="module"> | ||
import retextEmoji from 'https://esm.sh/retext-emoji@9?bundle' | ||
</script> | ||
``` | ||
## Use | ||
@@ -32,5 +73,5 @@ | ||
const file = retext() | ||
const file = await retext() | ||
.use(emoji, {convert: 'encode'}) | ||
.processSync('I’m going to bed. :zzz:') | ||
.process('I’m going to bed. :zzz:') | ||
@@ -49,45 +90,59 @@ console.log(String(file)) | ||
This package exports no identifiers. | ||
The default export is `retextEmoji`. | ||
The default export is [`retextEmoji`][api-retext-emoji]. | ||
### `unified().use(retextEmoji[, options])` | ||
Support emoji, gemoji, and emoticons. | ||
Plugin to support emoji (`❤️`), gemoji (`:heart:`), and emoticons (`<3`). | ||
###### `options.convert` | ||
###### Parameters | ||
If, and *how* to convert (`'encode'` or `'decode'`, optional). | ||
* `options` ([`Options`][api-options], optional) | ||
— configuration | ||
When `encode` is given, converts short-codes and emoticons to their unicode | ||
equivalent (`:heart:` and `<3` to `❤️`). | ||
###### Returns | ||
When `decode` is given, converts unicode emoji and emoticons to their short-code | ||
equivalent (`❤️` and `<3` to `:heart:`). | ||
Transform ([`Transformer`][unified-transformer]). | ||
### `EmoticonNode` | ||
### `Options` | ||
`retext-emoji` adds a new node to [**nlcst**][nlcst]: | ||
**Emoticon** ([**Literal**][literal]). | ||
Configuration (TypeScript type). | ||
Whether emoji (`❤️`), emoticon (`<3`), or gemoji (`:heart:`), all are classified | ||
as `EmoticonNode`s. | ||
###### Fields | ||
```idl | ||
interface Emoticon < Symbol { | ||
type: "EmoticonNode" | ||
data: EmoticonData | ||
} | ||
* `convert` (`'encode'` or `'decode'`, optional) | ||
— whether to decode (`❤️` and `<3` to `:heart:`), encode (`:heart:` and | ||
`<3` to `❤️`), or do nothing | ||
interface EmoticonData { | ||
emoji: string | ||
names: [string] | ||
description: string? | ||
tags: [string] | ||
} | ||
``` | ||
## Data | ||
## Support | ||
`retext-emoji` supports every [`emoticon`][emoticon] and [`gemoji`][gemoji]. | ||
`retext-emoji` supports every [`gemoji`][gemoji] and every | ||
[`emoticon`][emoticon]. | ||
## Syntax tree | ||
This plugin applies several nlcst utilities to build the AST. | ||
See their readmes for the node types supported in the tree: | ||
* [`nlcst-emoticon-modifier`][nlcst-emoticon-modifier] | ||
— emoticons | ||
* [`nlcst-emoji-modifier`][nlcst-emoji-modifier] | ||
— emoji and gemoji | ||
## Types | ||
This package is fully typed with [TypeScript][]. | ||
It exports the additional type [`Options`][api-options]. | ||
The `Emoticon` node is exposed from | ||
[`nlcst-emoticon-modifier`][nlcst-emoticon-modifier]. | ||
## Compatibility | ||
Projects maintained by the unified collective are compatible with maintained | ||
versions of Node.js. | ||
When we cut a new major release, we drop support for unmaintained versions of | ||
Node. | ||
This means we try to keep the current release line, `retext-emoji@^9`, | ||
compatible with Node.js 16. | ||
## Contribute | ||
@@ -99,3 +154,3 @@ | ||
This project has a [Code of Conduct][coc]. | ||
This project has a [code of conduct][coc]. | ||
By interacting with this repository, organisation, or community you agree to | ||
@@ -122,5 +177,5 @@ abide by its terms. | ||
[size-badge]: https://img.shields.io/bundlephobia/minzip/retext-emoji.svg | ||
[size-badge]: https://img.shields.io/bundlejs/size/retext-emoji | ||
[size]: https://bundlephobia.com/result?p=retext-emoji | ||
[size]: https://bundlejs.com/?q=retext-emoji | ||
@@ -139,9 +194,15 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg | ||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c | ||
[esmsh]: https://esm.sh | ||
[typescript]: https://www.typescriptlang.org | ||
[health]: https://github.com/retextjs/.github | ||
[contributing]: https://github.com/retextjs/.github/blob/HEAD/contributing.md | ||
[contributing]: https://github.com/retextjs/.github/blob/main/contributing.md | ||
[support]: https://github.com/retextjs/.github/blob/HEAD/support.md | ||
[support]: https://github.com/retextjs/.github/blob/main/support.md | ||
[coc]: https://github.com/retextjs/.github/blob/HEAD/code-of-conduct.md | ||
[coc]: https://github.com/retextjs/.github/blob/main/code-of-conduct.md | ||
@@ -152,10 +213,18 @@ [license]: license | ||
[emoticon]: https://github.com/wooorm/emoticon/blob/main/support.md | ||
[gemoji]: https://github.com/wooorm/gemoji/blob/main/support.md | ||
[nlcst-emoticon-modifier]: https://github.com/syntax-tree/nlcst-emoticon-modifier | ||
[nlcst-emoji-modifier]: https://github.com/syntax-tree/nlcst-emoji-modifier | ||
[retext]: https://github.com/retextjs/retext | ||
[nlcst]: https://github.com/syntax-tree/nlcst | ||
[unified]: https://github.com/unifiedjs/unified | ||
[literal]: https://github.com/syntax-tree/nlcst#literal | ||
[unified-transformer]: https://github.com/unifiedjs/unified#transformer | ||
[gemoji]: https://github.com/wooorm/gemoji/blob/main/support.md | ||
[api-retext-emoji]: #unifieduseretextemoji-options | ||
[emoticon]: https://github.com/wooorm/emoticon/blob/main/support.md | ||
[api-options]: #options |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
14999
10
7
211
223
1
+ Added@types/nlcst@2.0.3(transitive)
+ Added@types/unist@3.0.3(transitive)
+ Addeddequal@2.0.3(transitive)
+ Addeddevlop@1.1.0(transitive)
+ Addednlcst-affix-emoticon-modifier@3.0.0(transitive)
+ Addednlcst-emoji-modifier@6.0.2(transitive)
+ Addednlcst-emoticon-modifier@3.0.1(transitive)
+ Addednlcst-to-string@4.0.0(transitive)
+ Addedunified@11.0.5(transitive)
+ Addedunist-util-generated@3.0.0(transitive)
+ Addedunist-util-is@6.0.0(transitive)
+ Addedunist-util-modify-children@4.0.0(transitive)
+ Addedunist-util-position@5.0.0(transitive)
+ Addedunist-util-stringify-position@4.0.0(transitive)
+ Addedunist-util-visit@5.0.0(transitive)
+ Addedunist-util-visit-parents@6.0.1(transitive)
+ Addedvfile@6.0.3(transitive)
+ Addedvfile-message@4.0.2(transitive)
- Removed@types/nlcst@1.0.4(transitive)
- Removed@types/unist@2.0.11(transitive)
- Removedgemoji@7.1.0(transitive)
- Removedis-buffer@2.0.5(transitive)
- Removednlcst-affix-emoticon-modifier@2.1.1(transitive)
- Removednlcst-emoji-modifier@5.2.0(transitive)
- Removednlcst-emoticon-modifier@2.1.1(transitive)
- Removednlcst-to-string@3.1.1(transitive)
- Removedunified@10.1.2(transitive)
- Removedunist-util-generated@2.0.1(transitive)
- Removedunist-util-is@5.2.1(transitive)
- Removedunist-util-modify-children@3.1.1(transitive)
- Removedunist-util-position@4.0.4(transitive)
- Removedunist-util-stringify-position@3.0.3(transitive)
- Removedunist-util-visit@4.1.2(transitive)
- Removedunist-util-visit-parents@5.1.3(transitive)
- Removedvfile@5.3.7(transitive)
- Removedvfile-message@3.1.4(transitive)
Updated@types/nlcst@^2.0.0
Updatedgemoji@^8.0.0
Updatednlcst-emoji-modifier@^6.0.0
Updatednlcst-to-string@^4.0.0
Updatedunified@^11.0.0
Updatedunist-util-visit@^5.0.0