diff --git a/CHANGELOG.md b/CHANGELOG.md index fa6df2d6..20175f0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Changed +- Change CDN for Twemoji images from default to jsDelivr ([#320](https://github.com/marp-team/marp-core/issues/320), [#321](https://github.com/marp-team/marp-core/pull/321)) - Upgrade Marpit to [v2.4.2](https://github.com/marp-team/marpit/releases/v2.4.2) ([#318](https://github.com/marp-team/marp-core/pull/318)) - Upgrade development Node.js and dependent packages ([#318](https://github.com/marp-team/marp-core/pull/318)) diff --git a/README.md b/README.md index 573097df..738a79b7 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Theme author does not have to worry an unintended design being used with unexpec ### Emoji support -Emoji shortcode (like `:smile:`) and Unicode emoji 😄 will convert into the SVG vector image provided by [twemoji](https://github.com/twitter/twemoji) 😄. It could render emoji with high resolution. +Emoji shortcode (like `:smile:`) and Unicode emoji 😄 will convert into the SVG vector image provided by [twemoji](https://github.com/twitter/twemoji) 😄. It could render emoji with high resolution. --- @@ -275,14 +275,14 @@ Setting about emoji conversions. - **`shortcode`**: _`boolean` | `"twemoji"`_ - By setting `false`, it does not convert any emoji shortcodes. - By setting `true`, it converts emoji shortcodes into Unicode emoji. `:dog:` → 🐶 - - By setting `"twemoji"` string, it converts into twemoji vector image. `:dog:` → 🐶 _(default)_ + - By setting `"twemoji"` string, it converts into twemoji vector image. `:dog:` → 🐶 _(default)_ * **`unicode`**: _`boolean` | `"twemoji"`_ - - It can convert Unicode emoji into twemoji when setting `"twemoji"`. 🐶 → 🐶 _(default)_ + - It can convert Unicode emoji into twemoji when setting `"twemoji"`. 🐶 → 🐶 _(default)_ - If you not want this aggressive conversion, please set `false`. - **`twemoji`**: _`object`_ - - **`base`**: _`string`_ - It is corresponded to [twemoji's `base` option](https://github.com/twitter/twemoji#object-as-parameter). By default, marp-core will use online emoji images [through MaxCDN (twemoji's default)](https://github.com/twitter/twemoji#cdn-support). + - **`base`**: _`string`_ - Corresponds to [twemoji's `base` option](https://github.com/twitter/twemoji#object-as-parameter). If not specified, Marp Core will use [online emoji images through jsDelivr CDN](https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/). - **`ext`**: _`"svg"` | `"png"`_ - Setting the file type of twemoji images. _(`svg` by default)_ > **For developers:** When you setting `unicode` option as `true`, Markdown parser will convert Unicode emoji into tokens internally. The rendering result is same as in `false`. diff --git a/src/emoji/emoji.ts b/src/emoji/emoji.ts index 3e4e1120..38465074 100644 --- a/src/emoji/emoji.ts +++ b/src/emoji/emoji.ts @@ -2,6 +2,7 @@ import marpitPlugin from '@marp-team/marpit/plugin' import emojiRegex from 'emoji-regex' import markdownItEmoji from 'markdown-it-emoji' import twemoji from 'twemoji' +import { version as twemojiVersion } from 'twemoji/package.json' import twemojiCSS from './twemoji.scss' export interface EmojiOptions { @@ -30,10 +31,16 @@ export const markdown = marpitPlugin((md) => { const twemojiParse = (content: string): string => twemoji.parse(content, { attributes: () => ({ 'data-marp-twemoji': '' }), - base: twemojiOpts.base || undefined, + // Twemoji's default CDN (MaxCDN) shuts down at December 31, 2022. + // Unfortunately, continuous updates of Twemoji (including the update of + // base path) can not be expected due to Elon's acquisition for now. So + // Marp uses the CDN of jsDelivr unless the user specifies the base path. + base: Object.hasOwnProperty.call(twemojiOpts, 'base') + ? twemojiOpts.base + : `https://cdn.jsdelivr.net/gh/twitter/twemoji@${twemojiVersion}/assets/`, ext: `.${twemojiExt}`, size: twemojiExt === 'svg' ? 'svg' : undefined, - }) as any // TODO: Remove any casting (https://github.com/twitter/twemoji/pull/535) + }) const twemojiRenderer = (token: any[], idx: number): string => twemojiParse(token[idx].content) diff --git a/test/marp.ts b/test/marp.ts index e9e5c8da..b5e045a4 100644 --- a/test/marp.ts +++ b/test/marp.ts @@ -162,26 +162,37 @@ describe('Marp', () => { const instance = (twemoji: EmojiOptions['twemoji'] = {}) => new Marp({ emoji: { twemoji } }) - it('uses SVG via twemoji CDN by default', () => { - const $ = load(instance().render('# :ok_hand:').html) - const src = $('h1 > img[data-marp-twemoji]').attr('src') + const emojiSrc = (emoji: string, marp = instance()) => { + const $ = load(marp.render(`# ${emoji}`).html) + return $('h1 > img').attr('src') + } - expect(src).toMatchInlineSnapshot( - `"https://twemoji.maxcdn.com/v/14.0.2/svg/1f44c.svg"` + it('uses SVG via jsDelivr CDN by default', () => { + expect(emojiSrc(':ok_hand:')).toMatchInlineSnapshot( + `"https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/svg/1f44c.svg"` ) }) describe('base option', () => { it('uses specified base', () => expect( - instance({ base: '/assets/twemoji/' }).render(':+1:').html - ).toContain('/assets/twemoji/svg/1f44d.svg')) + emojiSrc(':+1:', instance({ base: '/assets/twemoji/' })) + ).toMatchInlineSnapshot(`"/assets/twemoji/svg/1f44d.svg"`)) + + it("uses Twemoji's default CDN if the base option was undefined", () => + expect( + emojiSrc(':+1:', instance({ base: undefined })) + ).toMatchInlineSnapshot( + `"https://twemoji.maxcdn.com/v/14.0.2/svg/1f44d.svg"` + )) }) describe('ext option', () => { it('uses PNG emoji by setting png', () => - expect(instance({ ext: 'png' }).render(':+1:').html).toMatch( - /https:\/\/twemoji\.maxcdn\.com\/[\w/.]+\/1f44d\.png/ + expect( + emojiSrc(':+1:', instance({ ext: 'png' })) + ).toMatchInlineSnapshot( + `"https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/72x72/1f44d.png"` )) }) })