remark-emoji
Advanced tools
Comparing version 2.0.2 to 2.1.0
@@ -10,2 +10,4 @@ const assert = require('assert'); | ||
const padded = remark().use(github).use(headings).use(slug).use(emoji, {padSpaceAfter: true}); | ||
const emoticon = remark().use(github).use(headings).use(slug).use(emoji, {emoticon: true}); | ||
const padAndEmoticon = remark().use(github).use(headings).use(slug).use(emoji, {padSpaceAfter: true, emoticon: true}); | ||
@@ -24,68 +26,168 @@ function process(contents) { | ||
function processEmoticon(contents) { | ||
return emoticon.process(contents).then(function (file) { | ||
return file.contents; | ||
}); | ||
} | ||
function processPadAndEmoticon(contents) { | ||
return padAndEmoticon.process(contents).then(function (file) { | ||
return file.contents; | ||
}); | ||
} | ||
describe('remark-emoji', () => { | ||
it('replaces emojis in text', () => { | ||
const cases = { | ||
'This is :dog:': 'This is 🐶\n', | ||
':dog: is not :cat:': '🐶 is not 🐱\n', | ||
'Please vote with :+1: or :-1:': 'Please vote with 👍 or 👎\n', | ||
':triumph:': '😤\n' | ||
}; | ||
describe('default compiler', () => { | ||
it('replaces emojis in text', () => { | ||
const cases = { | ||
'This is :dog:': 'This is 🐶\n', | ||
':dog: is not :cat:': '🐶 is not 🐱\n', | ||
'Please vote with :+1: or :-1:': 'Please vote with 👍 or 👎\n', | ||
':triumph:': '😤\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('does not replace emoji-like but not-a-emoji stuffs', () => { | ||
const cases = { | ||
'This text does not include emoji.': 'This text does not include emoji.\n', | ||
':++: or :foo: or :dog': ':++: or :foo: or :dog\n', | ||
'::': '::\n' | ||
}; | ||
it('does not replace emoji-like but not-a-emoji stuffs', () => { | ||
const cases = { | ||
'This text does not include emoji.': 'This text does not include emoji.\n', | ||
':++: or :foo: or :cat': ':++: or :foo: or :cat\n', | ||
'::': '::\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('replaces in link text', () => { | ||
const cases = { | ||
'In inline code, `:dog: is not replaced`': 'In inline code, `:dog: is not replaced`\n', | ||
'In code, \n```\n:dog: is not replaced\n```': 'In code, \n\n :dog: is not replaced\n', | ||
'[here :dog: and :cat: pictures!](https://example.com)': '[here 🐶 and 🐱 pictures!](https://example.com)\n' | ||
}; | ||
it('replaces in link text', () => { | ||
const cases = { | ||
'In inline code, `:dog: and :-) is not replaced`': 'In inline code, `:dog: and :-) is not replaced`\n', | ||
'In code, \n```\n:dog: and :-) is not replaced\n```': 'In code, \n\n :dog: and :-) is not replaced\n', | ||
'[here :dog: and :cat: and :-) pictures!](https://example.com)': '[here 🐶 and 🐱 and :-) pictures!](https://example.com)\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('can handle an emoji including 2 underscores', () => { | ||
return process(':heavy_check_mark:').then(r => assert.equal(r, '✔️\n')); | ||
}); | ||
it('can handle an emoji including 2 underscores', () => { | ||
return process(':heavy_check_mark:').then(r => assert.equal(r, '✔️\n')); | ||
}); | ||
it('adds an white space after emoji when padSpaceAfter is set to true', () => { | ||
const cases = { | ||
':dog: is dog': '🐶 is dog\n', | ||
'dog is :dog:': 'dog is 🐶 \n', | ||
':dog: is not :cat:': '🐶 is not 🐱 \n', | ||
':triumph:': '😤 \n' | ||
}; | ||
it('adds an white space after emoji when padSpaceAfter is set to true', () => { | ||
const cases = { | ||
':dog: is dog': '🐶 is dog\n', | ||
'dog is :dog:': 'dog is 🐶 \n', | ||
':dog: is not :cat:': '🐶 is not 🐱 \n', | ||
':triumph:': '😤 \n', | ||
':-)': ':-)\n', | ||
'Smile :-), not >:(!': 'Smile :-), not >:(!\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => processPad(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
return Promise.all( | ||
Object.keys(cases).map(c => processPad(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('can handle emoji that use dashes to separate words instead of underscores', () => { | ||
const cases = { | ||
'The Antarctic flag is represented by :flag-aq:': 'The Antarctic flag is represented by 🇦🇶\n', | ||
':man-woman-girl-boy:': '👨👩👧👦\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
}); | ||
it('can handle emoji that use dashes to separate words instead of underscores', () => { | ||
const cases = { | ||
'The Antarctic flag is represented by :flag-aq:': 'The Antarctic flag is represented by 🇦🇶\n', | ||
':man-woman-girl-boy:': '👨👩👧👦\n' | ||
}; | ||
describe('emoticon support', () => { | ||
it('replaces emojis in text', () => { | ||
const cases = { | ||
'This is :dog:': 'This is 🐶\n', | ||
':dog: is not :cat:': '🐶 is not 🐱\n', | ||
'Please vote with :+1: or :-1:': 'Please vote with 👍 or 👎\n', | ||
':triumph:': '😤\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => process(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
return Promise.all( | ||
Object.keys(cases).map(c => processEmoticon(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('does not replace emoji-like but not-a-emoji stuffs', () => { | ||
const cases = { | ||
'This text does not include emoji.': 'This text does not include emoji.\n', | ||
':++: or :foo: or :cat': ':++: or :foo: or :cat\n', | ||
'::': '::\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => processEmoticon(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('replaces in link text', () => { | ||
const cases = { | ||
'In inline code, `:dog: and :-) is not replaced`': 'In inline code, `:dog: and :-) is not replaced`\n', | ||
'In code, \n```\n:dog: and :-) is not replaced\n```': 'In code, \n\n :dog: and :-) is not replaced\n', | ||
'[here :dog: and :cat: and :-) pictures!](https://example.com)': '[here 🐶 and 🐱 and 😃 pictures!](https://example.com)\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => processEmoticon(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('can handle an emoji including 2 underscores', () => { | ||
return processEmoticon(':heavy_check_mark:').then(r => assert.equal(r, '✔️\n')); | ||
}); | ||
it('adds an white space after emoji when padSpaceAfter is set to true', () => { | ||
const cases = { | ||
':dog: is dog': '🐶 is dog\n', | ||
'dog is :dog:': 'dog is 🐶 \n', | ||
':dog: is not :cat:': '🐶 is not 🐱 \n', | ||
':triumph:': '😤 \n', | ||
':-)': '😃 \n', | ||
'Smile :-), not >:(!': 'Smile 😃 , not 😠 !\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => processPadAndEmoticon(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('can handle emoji that use dashes to separate words instead of underscores', () => { | ||
const cases = { | ||
'The Antarctic flag is represented by :flag-aq:': 'The Antarctic flag is represented by 🇦🇶\n', | ||
':man-woman-girl-boy:': '👨👩👧👦\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => processEmoticon(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
it('can handle emoji shortcodes (emoticon)', () => { | ||
const cases = { | ||
':p': '😛\n', | ||
':-)': '😃\n', | ||
'With-in some text :-p, also with some :o spaces :-)!': 'With-in some text 😛, also with some 😮 spaces 😃!\n', | ||
'Four char code ]:-)': 'Four char code 😈\n', | ||
'No problem with :dog: - :d': 'No problem with 🐶 - 😛\n', | ||
'With double quotes :"D': 'With double quotes 😊\n' | ||
}; | ||
return Promise.all( | ||
Object.keys(cases).map(c => processEmoticon(c).then(r => assert.equal(r, cases[c]))) | ||
); | ||
}); | ||
}); | ||
}); |
38
index.js
const visit = require('unist-util-visit'); | ||
const emoji = require('node-emoji'); | ||
const emoticon = require('emoticon'); | ||
const RE_EMOJI = /:\+1:|:-1:|:[\w-]+:/g; | ||
const RE_SHORT = /[$@|*'",;.=:\-)([\]\\/<>038BOopPsSdDxXzZ]{2,5}/g; | ||
function plugin(settings) { | ||
const pad = !!(settings || {}).padSpaceAfter; | ||
const DEFAULT_SETTINGS = { | ||
padSpaceAfter: false, | ||
emoticon: false | ||
}; | ||
function plugin(options) { | ||
const settings = Object.assign({}, DEFAULT_SETTINGS, options); | ||
const pad = !!settings.padSpaceAfter; | ||
const emoticonEnable = !!settings.emoticon; | ||
function getEmojiByShortCode(match) { | ||
// find emoji by shortcode - full match or with-out last char as it could be from text e.g. :-), | ||
const iconFull = emoticon.find(e => e.emoticons.includes(match)); // full match | ||
const iconPart = emoticon.find(e => e.emoticons.includes(match.slice(0, -1))); // second search pattern | ||
const trimmedChar = iconPart ? match.slice(-1): ''; | ||
const addPad = pad ? ' ': ''; | ||
let icon = iconFull ? | ||
iconFull.emoji + addPad: | ||
iconPart && (iconPart.emoji + addPad + trimmedChar); | ||
return icon || match; | ||
} | ||
function getEmoji(match) { | ||
const got = emoji.get(match); | ||
if (!pad || got === match) { | ||
return got; | ||
if (pad && got !== match) { | ||
return got + ' '; | ||
} | ||
return got + ' '; | ||
return got; | ||
} | ||
function transformer(tree) { | ||
visit(tree, 'text', function (node) { | ||
visit(tree, 'text', function(node) { | ||
node.value = node.value.replace(RE_EMOJI, getEmoji); | ||
if (emoticonEnable) { | ||
node.value = node.value.replace(RE_SHORT, getEmojiByShortCode); | ||
} | ||
}); | ||
@@ -22,0 +46,0 @@ } |
{ | ||
"name": "remark-emoji", | ||
"version": "2.0.2", | ||
"version": "2.1.0", | ||
"description": "Emoji transformer plugin for Remark", | ||
@@ -27,13 +27,14 @@ "main": "index.js", | ||
"devDependencies": { | ||
"eslint": "^5.7.0", | ||
"mocha": "^5.2.0", | ||
"remark": "^7.0.0", | ||
"remark-autolink-headings": "^5.0.0", | ||
"remark-github": "^7.0.0", | ||
"remark-slug": "^4.2.2" | ||
"eslint": "^6.8.0", | ||
"mocha": "^7.1.0", | ||
"remark": "^11.0.2", | ||
"remark-autolink-headings": "^5.2.2", | ||
"remark-github": "^8.0.0", | ||
"remark-slug": "^5.1.2" | ||
}, | ||
"dependencies": { | ||
"node-emoji": "^1.8.1", | ||
"unist-util-visit": "^1.4.0" | ||
"emoticon": "^3.2.0", | ||
"node-emoji": "^1.10.0", | ||
"unist-util-visit": "^2.0.2" | ||
} | ||
} |
@@ -7,2 +7,6 @@ remark-emoji | ||
## Demo | ||
You can find a demo in the following [Codesandbox](https://codesandbox.io/s/remark-emoji-example-osvyi). | ||
## Usage | ||
@@ -31,4 +35,9 @@ | ||
### `options.emoticon` | ||
Setting to `true` means that [emoticon](https://www.npmjs.com/package/emoticon) shortcodes are supported (e.g. :-) will be replaced by 😃). | ||
Default value is `false`. | ||
## License | ||
Distributed under [the MIT License](LICENSE). |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13146
239
42
3
+ Addedemoticon@^3.2.0
+ Added@types/unist@2.0.11(transitive)
+ Addedemoticon@3.2.0(transitive)
+ Addedunist-util-is@4.1.0(transitive)
+ Addedunist-util-visit@2.0.3(transitive)
+ Addedunist-util-visit-parents@3.1.1(transitive)
- Removedunist-util-is@3.0.0(transitive)
- Removedunist-util-visit@1.4.1(transitive)
- Removedunist-util-visit-parents@2.1.2(transitive)
Updatednode-emoji@^1.10.0
Updatedunist-util-visit@^2.0.2