From 6f9fb3bcb8fc32fbc3a147e429867101a7a4e509 Mon Sep 17 00:00:00 2001 From: Kelly Joseph Price Date: Wed, 17 Apr 2024 13:20:48 -0700 Subject: [PATCH 1/2] feat: use unicode emoji! --- __tests__/__snapshots__/index.test.js.snap | 2 +- __tests__/flavored-compilers/gemoji.test.js | 10 ++++++++ __tests__/gemoji-parser.test.js | 28 ++++++++++++++++++++- package-lock.json | 15 +++++++++++ package.json | 1 + processor/compile/gemoji.js | 6 +++++ processor/compile/index.js | 1 + processor/parse/gemoji-parser.js | 25 ++++++++++-------- 8 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 __tests__/flavored-compilers/gemoji.test.js create mode 100644 processor/compile/gemoji.js diff --git a/__tests__/__snapshots__/index.test.js.snap b/__tests__/__snapshots__/index.test.js.snap index ba04fa5cb..71115eb9c 100644 --- a/__tests__/__snapshots__/index.test.js.snap +++ b/__tests__/__snapshots__/index.test.js.snap @@ -73,7 +73,7 @@ Object { `; exports[`emojis 1`] = ` -"

\\":joy:\\"
+"

😂

:unknown-emoji:

" `; diff --git a/__tests__/flavored-compilers/gemoji.test.js b/__tests__/flavored-compilers/gemoji.test.js new file mode 100644 index 000000000..16be2915a --- /dev/null +++ b/__tests__/flavored-compilers/gemoji.test.js @@ -0,0 +1,10 @@ +import { mdast, md } from '../../index'; + +describe('gemoji compiler', () => { + it('writes an gemojis back to shortcodes', () => { + const doc = ':poop:'; + const tree = mdast(doc); + + expect(md(tree)).toMatch(doc); + }); +}); diff --git a/__tests__/gemoji-parser.test.js b/__tests__/gemoji-parser.test.js index bf50b5d22..c8847cd17 100644 --- a/__tests__/gemoji-parser.test.js +++ b/__tests__/gemoji-parser.test.js @@ -3,9 +3,35 @@ const unified = require('unified'); const parser = require('../processor/parse/gemoji-parser'); -test('should output an image node for a known emoji', () => { +test('should output emoji', () => { const emoji = 'joy'; const markdown = `This is a gemoji :${emoji}:.`; + const ast = { + type: 'root', + children: [ + { + type: 'paragraph', + children: [ + { type: 'text', value: 'This is a gemoji ' }, + { + type: 'gemoji', + value: '😂', + name: emoji, + }, + { type: 'text', value: '.' }, + ], + }, + ], + }; + + expect(unified().use(remarkParse).use(parser).data('settings', { position: false }).parse(markdown)).toStrictEqual( + ast, + ); +}); + +test('should output an image node for a custom readme emoji', () => { + const emoji = 'owlbert'; + const markdown = `This is a gemoji :${emoji}:.`; const ast = { type: 'root', children: [ diff --git a/package-lock.json b/package-lock.json index 9c0210066..c340f12b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@readme/syntax-highlighter": "^13.0.0", "copy-to-clipboard": "^3.3.3", "emoji-regex": "^10.3.0", + "gemoji": "^8.1.0", "hast-util-sanitize": "^4.0.0", "lodash.escape": "^4.0.1", "lodash.kebabcase": "^4.1.1", @@ -12671,6 +12672,15 @@ "node": ">= 4.0.0" } }, + "node_modules/gemoji": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/gemoji/-/gemoji-8.1.0.tgz", + "integrity": "sha512-HA4Gx59dw2+tn+UAa7XEV4ufUKI4fH1KgcbenVA9YKSj1QJTT0xh5Mwv5HMFNN3l2OtUe3ZIfuRwSyZS5pLIWw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -38125,6 +38135,11 @@ "globule": "^1.0.0" } }, + "gemoji": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/gemoji/-/gemoji-8.1.0.tgz", + "integrity": "sha512-HA4Gx59dw2+tn+UAa7XEV4ufUKI4fH1KgcbenVA9YKSj1QJTT0xh5Mwv5HMFNN3l2OtUe3ZIfuRwSyZS5pLIWw==" + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", diff --git a/package.json b/package.json index 30c96511a..8bfcbc2ee 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@readme/syntax-highlighter": "^13.0.0", "copy-to-clipboard": "^3.3.3", "emoji-regex": "^10.3.0", + "gemoji": "^8.1.0", "hast-util-sanitize": "^4.0.0", "lodash.escape": "^4.0.1", "lodash.kebabcase": "^4.1.1", diff --git a/processor/compile/gemoji.js b/processor/compile/gemoji.js new file mode 100644 index 000000000..3010fb368 --- /dev/null +++ b/processor/compile/gemoji.js @@ -0,0 +1,6 @@ +module.exports = function GemojiCompiler() { + const { Compiler } = this; + const { visitors } = Compiler.prototype; + + visitors.gemoji = node => `:${node.name}:`; +}; diff --git a/processor/compile/index.js b/processor/compile/index.js index e55cb7d52..fd111b06f 100644 --- a/processor/compile/index.js +++ b/processor/compile/index.js @@ -3,6 +3,7 @@ export { default as codeTabsCompiler } from './code-tabs'; export { default as divCompiler } from './div'; export { default as escapeCompiler } from './escape'; export { default as figureCompiler } from './figure'; +export { default as gemojiCompiler } from './gemoji'; export { default as htmlBlockCompiler } from './html-block'; export { default as iconCompiler } from './i'; export { default as imageCompiler } from './image'; diff --git a/processor/parse/gemoji-parser.js b/processor/parse/gemoji-parser.js index 523c33010..a544c62fe 100644 --- a/processor/parse/gemoji-parser.js +++ b/processor/parse/gemoji-parser.js @@ -1,4 +1,5 @@ const Emoji = require('@readme/emojis').emoji; +const { nameToEmoji } = require('gemoji'); const { insertInlineTokenizerBefore } = require('./utils'); @@ -14,31 +15,35 @@ function tokenize(eat, value, silent) { if (pos === -1) return false; - const subvalue = value.slice(1, pos); + const name = value.slice(1, pos); // Exit with true in silent if (silent) return true; - const match = colon + subvalue + colon; + const match = colon + name + colon; - if (subvalue.substr(0, 3) === 'fa-') { + if (name in nameToEmoji) { + return eat(match)({ + type: 'gemoji', + value: nameToEmoji[name], + name, + }); + } else if (name.substr(0, 3) === 'fa-') { return eat(match)({ type: 'i', data: { hName: 'i', hProperties: { - className: ['fa', subvalue], + className: ['fa', name], }, }, }); - } - - if (emojis.is(subvalue)) { + } else if (emojis.is(name)) { return eat(match)({ type: 'image', - title: `:${subvalue}:`, - alt: `:${subvalue}:`, - url: `/public/img/emojis/${subvalue}.png`, + title: `:${name}:`, + alt: `:${name}:`, + url: `/public/img/emojis/${name}.png`, data: { hProperties: { className: 'emoji', From 0473e5aad552405f1f1088ad688897bdc1e321e0 Mon Sep 17 00:00:00 2001 From: Kelly Joseph Price Date: Wed, 17 Apr 2024 14:05:46 -0700 Subject: [PATCH 2/2] feat: :salute: @readme/emojis --- Dockerfile | 2 - Dockerfile.legacy | 2 - Makefile | 8 --- assets/img/emojis/owlbert-books.png | Bin 0 -> 3762 bytes assets/img/emojis/owlbert-mask.png | Bin 0 -> 3603 bytes assets/img/emojis/owlbert-reading.png | Bin 0 -> 3069 bytes assets/img/emojis/owlbert-thinking.png | Bin 0 -> 3211 bytes assets/img/emojis/owlbert.png | Bin 0 -> 3772 bytes lib/gemoji.js | 16 ++++++ package.json | 3 +- processor/parse/gemoji-parser.js | 69 ++++++++++++------------- 11 files changed, 50 insertions(+), 50 deletions(-) create mode 100644 assets/img/emojis/owlbert-books.png create mode 100644 assets/img/emojis/owlbert-mask.png create mode 100644 assets/img/emojis/owlbert-reading.png create mode 100644 assets/img/emojis/owlbert-thinking.png create mode 100644 assets/img/emojis/owlbert.png create mode 100644 lib/gemoji.js diff --git a/Dockerfile b/Dockerfile index e1f462b5e..8c9503e44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,6 @@ COPY . ./ RUN mkdir -p __tests__/browser/__image_snapshots__/__diff_output__ -RUN make emojis - EXPOSE 9966 CMD ["test.browser"] diff --git a/Dockerfile.legacy b/Dockerfile.legacy index 9e408ddfb..37f275265 100644 --- a/Dockerfile.legacy +++ b/Dockerfile.legacy @@ -32,8 +32,6 @@ COPY . ./ RUN mkdir -p __tests__/browser/__image_snapshots__/__diff_output__ -RUN make emojis - EXPOSE 9966 CMD ["test.browser"] diff --git a/Makefile b/Makefile index 485120fb8..ca13857a5 100644 --- a/Makefile +++ b/Makefile @@ -6,14 +6,6 @@ DOCKER_WORKSPACE := "/markdown" MOUNTS = --volume ${PWD}:${DOCKER_WORKSPACE} \ --volume ${DOCKER_WORKSPACE}/node_modules -emojis: example/public/img/emojis ## Install our emojis. - -example/public/img/emojis: node_modules/@readme/emojis - rm -rf example/img/emojis - rm -rf example/public/img/emojis - mkdir -p example/public/img/emojis - cp node_modules/@readme/emojis/src/img/*.png example/public/img/emojis/ - ifeq ($(USE_LEGACY), true) dockerfile = -f Dockerfile.legacy endif diff --git a/assets/img/emojis/owlbert-books.png b/assets/img/emojis/owlbert-books.png new file mode 100644 index 0000000000000000000000000000000000000000..bb3e40f0c9cdf06f1397c90da70e714e639e3740 GIT binary patch literal 3762 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 J&$S%F{sjU%!QKD> literal 0 HcmV?d00001 diff --git a/assets/img/emojis/owlbert-mask.png b/assets/img/emojis/owlbert-mask.png new file mode 100644 index 0000000000000000000000000000000000000000..92987a2ec5746da2855ac2e03d0f7be521af160c GIT binary patch literal 3603 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 W@ul(ZIoq}016zV4zSPR^$bSF?(~3m^ literal 0 HcmV?d00001 diff --git a/assets/img/emojis/owlbert.png b/assets/img/emojis/owlbert.png new file mode 100644 index 0000000000000000000000000000000000000000..89a305b361f9e9a10248e370b2b82f1970fabc44 GIT binary patch literal 3772 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 LQ%sTG<=}q-wvwZr literal 0 HcmV?d00001 diff --git a/lib/gemoji.js b/lib/gemoji.js new file mode 100644 index 000000000..e8a859fa2 --- /dev/null +++ b/lib/gemoji.js @@ -0,0 +1,16 @@ +const { nameToEmoji } = require('gemoji'); + +const owlmoji = ['owlbert-books', 'owlbert-mask', 'owlbert', 'owlbert-reading', 'owlbert-thinking']; + +class Emoji { + static kind = name => { + if (name in nameToEmoji) return 'gemoji'; + else if (name.match(/^fa-/)) return 'fontawesome'; + else if (owlmoji.includes(name)) return 'owlmoji'; + return null; + }; + + static nameToEmoji = nameToEmoji; +} + +module.exports = Emoji; diff --git a/package.json b/package.json index 8bfcbc2ee..83c8accd8 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ ], "scripts": { "build": "webpack --mode production", - "heroku-postbuild": "make emojis && webpack --mode production --config ./webpack.dev.js", + "heroku-postbuild": "webpack --mode production --config ./webpack.dev.js", "lint": "npm run lint:js && npm run lint:css", "lint:css": "stylelint '{components,styles}/**/*.{css,scss}'", "lint:js": "eslint --ext ts,tsx,js,jsx .", @@ -28,7 +28,6 @@ "watch": "webpack -w --progress --mode production" }, "dependencies": { - "@readme/emojis": "^6.0.0", "@readme/syntax-highlighter": "^13.0.0", "copy-to-clipboard": "^3.3.3", "emoji-regex": "^10.3.0", diff --git a/processor/parse/gemoji-parser.js b/processor/parse/gemoji-parser.js index a544c62fe..a7ddcc76b 100644 --- a/processor/parse/gemoji-parser.js +++ b/processor/parse/gemoji-parser.js @@ -1,10 +1,7 @@ -const Emoji = require('@readme/emojis').emoji; -const { nameToEmoji } = require('gemoji'); +const Emoji = require('../../lib/gemoji'); const { insertInlineTokenizerBefore } = require('./utils'); -const emojis = new Emoji(); - const colon = ':'; function tokenize(eat, value, silent) { @@ -12,7 +9,6 @@ function tokenize(eat, value, silent) { if (value.charAt(0) !== colon) return false; const pos = value.indexOf(colon, 1); - if (pos === -1) return false; const name = value.slice(1, pos); @@ -22,40 +18,41 @@ function tokenize(eat, value, silent) { const match = colon + name + colon; - if (name in nameToEmoji) { - return eat(match)({ - type: 'gemoji', - value: nameToEmoji[name], - name, - }); - } else if (name.substr(0, 3) === 'fa-') { - return eat(match)({ - type: 'i', - data: { - hName: 'i', - hProperties: { - className: ['fa', name], + switch (Emoji.kind(name)) { + case 'gemoji': + return eat(match)({ + type: 'gemoji', + value: Emoji.nameToEmoji[name], + name, + }); + case 'fontawesome': + return eat(match)({ + type: 'i', + data: { + hName: 'i', + hProperties: { + className: ['fa', name], + }, }, - }, - }); - } else if (emojis.is(name)) { - return eat(match)({ - type: 'image', - title: `:${name}:`, - alt: `:${name}:`, - url: `/public/img/emojis/${name}.png`, - data: { - hProperties: { - className: 'emoji', - align: 'absmiddle', - height: '20', - width: '20', + }); + case 'owlmoji': + return eat(match)({ + type: 'image', + title: `:${name}:`, + alt: `:${name}:`, + url: `/public/img/emojis/${name}.png`, + data: { + hProperties: { + className: 'emoji', + align: 'absmiddle', + height: '20', + width: '20', + }, }, - }, - }); + }); + default: + return false; } - - return false; } function locate(value, fromIndex) {