perf(audit): emojibase lazy-split, SW precache, Prism subset, lazy images
- emojibase (~965 KB) is now fully lazy: plugins/emoji.ts loads compact data + shortcode maps via a memoized dynamic import (rejections reset the memo so a mid-deploy chunk 404 can retry); reaction labels degrade to the raw glyph until loaded. Consumers get FRESH array references on load (the module arrays populate in place — same-ref state updates would skip re-render and leave emoji search empty; reviewer-caught). Verified out of the eager graph. - Service worker precaches hashed assets (workbox precacheAndRoute, 82 entries ~10.8 MB incl. the crypto wasm): repeat visits stop re-downloading the app. index.html is NOT precached — navigations stay network-first so deploys are picked up immediately; the media-auth fetch handler is untouched. - ReactPrism: curated 21-language set — chunk 574 KB → 71 KB. - Timeline inline images get loading="lazy". - Removed dead dompurify (+types); sanitize-html is the real sanitizer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+110
-63
@@ -1,7 +1,4 @@
|
||||
import { CompactEmoji, fromUnicodeToHexcode } from 'emojibase';
|
||||
import emojisData from 'emojibase-data/en/compact.json';
|
||||
import joypixels from 'emojibase-data/en/shortcodes/joypixels.json';
|
||||
import emojibase from 'emojibase-data/en/shortcodes/emojibase.json';
|
||||
import type { CompactEmoji } from 'emojibase';
|
||||
|
||||
export type IEmoji = CompactEmoji & {
|
||||
shortcode: string;
|
||||
@@ -24,57 +21,76 @@ export type IEmojiGroup = {
|
||||
emojis: IEmoji[];
|
||||
};
|
||||
|
||||
export const getShortcodesFor = (hexcode: string): string[] | string | undefined =>
|
||||
joypixels[hexcode] || emojibase[hexcode];
|
||||
export type EmojiData = {
|
||||
emojis: IEmoji[];
|
||||
emojiGroups: IEmojiGroup[];
|
||||
};
|
||||
|
||||
type ShortcodeMap = Record<string, string | string[]>;
|
||||
|
||||
/**
|
||||
* PERF (lazy emojibase split): the heavy `emojibase-data` JSON (compact emoji
|
||||
* data + the joypixels/emojibase shortcode maps, ~965 KB combined) used to be
|
||||
* imported statically at module top-level. Because reaction/message rendering
|
||||
* (`Reaction`, `scaleSystemEmoji`) import this module eagerly, that dragged the
|
||||
* whole `emojibase` chunk into the initial (eager) bundle graph.
|
||||
*
|
||||
* It is now loaded on demand via `loadEmojiData()` (a memoized dynamic import).
|
||||
* Only lazy emoji surfaces (EmojiBoard, EmoticonAutocomplete, recent-emoji)
|
||||
* trigger the load. Anything that renders eagerly (reaction/emoji tooltips and
|
||||
* aria-labels via `getShortcodeFor`) gracefully degrades to `undefined` until
|
||||
* the data has been loaded — the visible emoji glyph itself never depended on
|
||||
* this data, so on-screen UX is unchanged; the shortcode label simply resolves
|
||||
* once emoji data is loaded. `getHexcodeForEmoji` is inlined below so it stays
|
||||
* synchronous WITHOUT pulling the `emojibase` runtime into the eager graph.
|
||||
*/
|
||||
|
||||
// Inlined from emojibase's `fromUnicodeToHexcode` so this synchronous helper
|
||||
// does not import the `emojibase` package (and thus the emojibase chunk) into
|
||||
// the eager graph. Kept byte-for-byte behaviourally identical.
|
||||
const SEQUENCE_REMOVAL_PATTERN = /200D|FE0E|FE0F/g;
|
||||
|
||||
export const getHexcodeForEmoji = (unicode: string, strip = true): string => {
|
||||
const hexcode: string[] = [];
|
||||
[...unicode].forEach((codepoint) => {
|
||||
let hex = codepoint.codePointAt(0)?.toString(16).toUpperCase() ?? '';
|
||||
while (hex.length < 4) {
|
||||
hex = `0${hex}`;
|
||||
}
|
||||
if (!strip || !hex.match(SEQUENCE_REMOVAL_PATTERN)) {
|
||||
hexcode.push(hex);
|
||||
}
|
||||
});
|
||||
return hexcode.join('-');
|
||||
};
|
||||
|
||||
// Populated by loadEmojiData(); `undefined` until the data has been loaded.
|
||||
let joypixelsShortcodes: ShortcodeMap | undefined;
|
||||
let emojibaseShortcodes: ShortcodeMap | undefined;
|
||||
|
||||
export const getShortcodesFor = (hexcode: string): string[] | string | undefined => {
|
||||
if (!joypixelsShortcodes || !emojibaseShortcodes) return undefined;
|
||||
return joypixelsShortcodes[hexcode] || emojibaseShortcodes[hexcode];
|
||||
};
|
||||
|
||||
export const getShortcodeFor = (hexcode: string): string | undefined => {
|
||||
const shortcode = joypixels[hexcode] || emojibase[hexcode];
|
||||
const shortcode = getShortcodesFor(hexcode);
|
||||
return Array.isArray(shortcode) ? shortcode[0] : shortcode;
|
||||
};
|
||||
|
||||
export const getHexcodeForEmoji = fromUnicodeToHexcode;
|
||||
|
||||
// Shared, stable array references. They start empty and are populated in place
|
||||
// the first time loadEmojiData() resolves (mirroring the previous eager module
|
||||
// side-effect). React consumers await loadEmojiData() and re-render to observe
|
||||
// the populated data; non-React consumers (recent-emoji) read them after load.
|
||||
export const emojiGroups: IEmojiGroup[] = [
|
||||
{
|
||||
id: EmojiGroupId.People,
|
||||
order: 0,
|
||||
emojis: [],
|
||||
},
|
||||
{
|
||||
id: EmojiGroupId.Nature,
|
||||
order: 1,
|
||||
emojis: [],
|
||||
},
|
||||
{
|
||||
id: EmojiGroupId.Food,
|
||||
order: 2,
|
||||
emojis: [],
|
||||
},
|
||||
{
|
||||
id: EmojiGroupId.Activity,
|
||||
order: 3,
|
||||
emojis: [],
|
||||
},
|
||||
{
|
||||
id: EmojiGroupId.Travel,
|
||||
order: 4,
|
||||
emojis: [],
|
||||
},
|
||||
{
|
||||
id: EmojiGroupId.Object,
|
||||
order: 5,
|
||||
emojis: [],
|
||||
},
|
||||
{
|
||||
id: EmojiGroupId.Symbol,
|
||||
order: 6,
|
||||
emojis: [],
|
||||
},
|
||||
{
|
||||
id: EmojiGroupId.Flag,
|
||||
order: 7,
|
||||
emojis: [],
|
||||
},
|
||||
{ id: EmojiGroupId.People, order: 0, emojis: [] },
|
||||
{ id: EmojiGroupId.Nature, order: 1, emojis: [] },
|
||||
{ id: EmojiGroupId.Food, order: 2, emojis: [] },
|
||||
{ id: EmojiGroupId.Activity, order: 3, emojis: [] },
|
||||
{ id: EmojiGroupId.Travel, order: 4, emojis: [] },
|
||||
{ id: EmojiGroupId.Object, order: 5, emojis: [] },
|
||||
{ id: EmojiGroupId.Symbol, order: 6, emojis: [] },
|
||||
{ id: EmojiGroupId.Flag, order: 7, emojis: [] },
|
||||
];
|
||||
|
||||
export const emojis: IEmoji[] = [];
|
||||
@@ -95,20 +111,51 @@ function getGroupIndex(emoji: IEmoji): number | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
emojisData.forEach((emoji) => {
|
||||
const myShortCodes = getShortcodesFor(emoji.hexcode);
|
||||
if (!myShortCodes) return;
|
||||
if (Array.isArray(myShortCodes) && myShortCodes.length === 0) return;
|
||||
let emojiDataPromise: Promise<EmojiData> | undefined;
|
||||
|
||||
const em: IEmoji = {
|
||||
...emoji,
|
||||
shortcode: Array.isArray(myShortCodes) ? myShortCodes[0] : myShortCodes,
|
||||
shortcodes: Array.isArray(myShortCodes) ? myShortCodes : emoji.shortcodes,
|
||||
};
|
||||
/**
|
||||
* Lazily load emojibase data (dynamic import → the `emojibase` chunk). Memoized:
|
||||
* the JSON is fetched/parsed and `emojis`/`emojiGroups` are built exactly once.
|
||||
*/
|
||||
export const loadEmojiData = (): Promise<EmojiData> => {
|
||||
if (!emojiDataPromise) {
|
||||
emojiDataPromise = (async (): Promise<EmojiData> => {
|
||||
const [emojisModule, joypixelsModule, emojibaseModule] = await Promise.all([
|
||||
import('emojibase-data/en/compact.json'),
|
||||
import('emojibase-data/en/shortcodes/joypixels.json'),
|
||||
import('emojibase-data/en/shortcodes/emojibase.json'),
|
||||
]);
|
||||
|
||||
const groupIndex = getGroupIndex(em);
|
||||
if (groupIndex !== undefined) {
|
||||
addEmojiToGroup(groupIndex, em);
|
||||
emojis.push(em);
|
||||
joypixelsShortcodes = joypixelsModule.default as ShortcodeMap;
|
||||
emojibaseShortcodes = emojibaseModule.default as ShortcodeMap;
|
||||
|
||||
const emojisData = emojisModule.default as unknown as CompactEmoji[];
|
||||
emojisData.forEach((emoji) => {
|
||||
const myShortCodes = getShortcodesFor(emoji.hexcode);
|
||||
if (!myShortCodes) return;
|
||||
if (Array.isArray(myShortCodes) && myShortCodes.length === 0) return;
|
||||
|
||||
const em: IEmoji = {
|
||||
...emoji,
|
||||
shortcode: Array.isArray(myShortCodes) ? myShortCodes[0] : myShortCodes,
|
||||
shortcodes: Array.isArray(myShortCodes) ? myShortCodes : emoji.shortcodes,
|
||||
};
|
||||
|
||||
const groupIndex = getGroupIndex(em);
|
||||
if (groupIndex !== undefined) {
|
||||
addEmojiToGroup(groupIndex, em);
|
||||
emojis.push(em);
|
||||
}
|
||||
});
|
||||
|
||||
return { emojis, emojiGroups };
|
||||
})();
|
||||
// Don't cache a rejection: a transient chunk-load failure (e.g. mid-deploy
|
||||
// 404) would otherwise permanently disable emoji data until a full reload.
|
||||
emojiDataPromise = emojiDataPromise.catch((err) => {
|
||||
emojiDataPromise = undefined;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
});
|
||||
return emojiDataPromise;
|
||||
};
|
||||
|
||||
@@ -577,12 +577,12 @@ export const getReactCustomHtmlParser = (
|
||||
return (
|
||||
<span className={css.EmoticonBase}>
|
||||
<span className={css.Emoticon()}>
|
||||
<img {...props} className={css.EmoticonImg} src={htmlSrc} />
|
||||
<img {...props} className={css.EmoticonImg} src={htmlSrc} loading="lazy" />
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (htmlSrc) return <img {...props} className={css.Img} src={htmlSrc} />;
|
||||
if (htmlSrc) return <img {...props} className={css.Img} src={htmlSrc} loading="lazy" />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,307 +2,33 @@ import React, { MutableRefObject, ReactNode, useEffect, useRef } from 'react';
|
||||
|
||||
import Prism from 'prismjs';
|
||||
|
||||
import 'prismjs/components/prism-abap.js';
|
||||
import 'prismjs/components/prism-abnf.js';
|
||||
import 'prismjs/components/prism-actionscript.js';
|
||||
import 'prismjs/components/prism-ada.js';
|
||||
import 'prismjs/components/prism-agda.js';
|
||||
import 'prismjs/components/prism-al.js';
|
||||
import 'prismjs/components/prism-antlr4.js';
|
||||
import 'prismjs/components/prism-apacheconf.js';
|
||||
import 'prismjs/components/prism-apex.js';
|
||||
import 'prismjs/components/prism-apl.js';
|
||||
import 'prismjs/components/prism-applescript.js';
|
||||
import 'prismjs/components/prism-aql.js';
|
||||
import 'prismjs/components/prism-arff.js';
|
||||
import 'prismjs/components/prism-armasm.js';
|
||||
import 'prismjs/components/prism-arturo.js';
|
||||
import 'prismjs/components/prism-asciidoc.js';
|
||||
import 'prismjs/components/prism-asm6502.js';
|
||||
import 'prismjs/components/prism-asmatmel.js';
|
||||
import 'prismjs/components/prism-aspnet.js';
|
||||
import 'prismjs/components/prism-autohotkey.js';
|
||||
import 'prismjs/components/prism-autoit.js';
|
||||
import 'prismjs/components/prism-avisynth.js';
|
||||
import 'prismjs/components/prism-avro-idl.js';
|
||||
import 'prismjs/components/prism-awk.js';
|
||||
import 'prismjs/components/prism-bash.js';
|
||||
import 'prismjs/components/prism-basic.js';
|
||||
import 'prismjs/components/prism-batch.js';
|
||||
import 'prismjs/components/prism-bbcode.js';
|
||||
import 'prismjs/components/prism-bbj.js';
|
||||
import 'prismjs/components/prism-bicep.js';
|
||||
import 'prismjs/components/prism-birb.js';
|
||||
import 'prismjs/components/prism-bnf.js';
|
||||
import 'prismjs/components/prism-bqn.js';
|
||||
import 'prismjs/components/prism-brainfuck.js';
|
||||
import 'prismjs/components/prism-brightscript.js';
|
||||
import 'prismjs/components/prism-bro.js';
|
||||
import 'prismjs/components/prism-bsl.js';
|
||||
import 'prismjs/components/prism-c.js';
|
||||
import 'prismjs/components/prism-cfscript.js';
|
||||
import 'prismjs/components/prism-cil.js';
|
||||
import 'prismjs/components/prism-cilkc.js';
|
||||
import 'prismjs/components/prism-cilkcpp.js';
|
||||
// PERF: Prism used to import every bundled language (~574 KB lazy chunk). We now
|
||||
// ship a curated subset covering the languages actually seen in chat. Imports
|
||||
// MUST stay in dependency order (Prism component files assume their base grammar
|
||||
// is already registered): base grammars (markup/css/clike/javascript) first,
|
||||
// then languages that extend them (e.g. c→cpp, javascript→typescript,
|
||||
// markup+javascript→jsx, jsx+typescript→tsx, markup→markdown).
|
||||
import 'prismjs/components/prism-markup.js'; // markup / html / xml / svg
|
||||
import 'prismjs/components/prism-css.js';
|
||||
import 'prismjs/components/prism-clike.js';
|
||||
import 'prismjs/components/prism-clojure.js';
|
||||
import 'prismjs/components/prism-cmake.js';
|
||||
import 'prismjs/components/prism-cobol.js';
|
||||
import 'prismjs/components/prism-coffeescript.js';
|
||||
import 'prismjs/components/prism-concurnas.js';
|
||||
import 'prismjs/components/prism-cooklang.js';
|
||||
import 'prismjs/components/prism-coq.js';
|
||||
import 'prismjs/components/prism-javascript.js'; // js
|
||||
import 'prismjs/components/prism-json.js';
|
||||
import 'prismjs/components/prism-yaml.js';
|
||||
import 'prismjs/components/prism-bash.js'; // bash / shell / sh
|
||||
import 'prismjs/components/prism-python.js';
|
||||
import 'prismjs/components/prism-rust.js';
|
||||
import 'prismjs/components/prism-go.js';
|
||||
import 'prismjs/components/prism-java.js';
|
||||
import 'prismjs/components/prism-c.js';
|
||||
import 'prismjs/components/prism-cpp.js';
|
||||
import 'prismjs/components/prism-csharp.js';
|
||||
import 'prismjs/components/prism-cshtml.js';
|
||||
import 'prismjs/components/prism-csp.js';
|
||||
import 'prismjs/components/prism-css-extras.js';
|
||||
import 'prismjs/components/prism-css.js';
|
||||
import 'prismjs/components/prism-csv.js';
|
||||
import 'prismjs/components/prism-cue.js';
|
||||
import 'prismjs/components/prism-cypher.js';
|
||||
import 'prismjs/components/prism-d.js';
|
||||
import 'prismjs/components/prism-dart.js';
|
||||
import 'prismjs/components/prism-dataweave.js';
|
||||
import 'prismjs/components/prism-dax.js';
|
||||
import 'prismjs/components/prism-dhall.js';
|
||||
import 'prismjs/components/prism-diff.js';
|
||||
import 'prismjs/components/prism-dns-zone-file.js';
|
||||
import 'prismjs/components/prism-docker.js';
|
||||
import 'prismjs/components/prism-dot.js';
|
||||
import 'prismjs/components/prism-ebnf.js';
|
||||
import 'prismjs/components/prism-editorconfig.js';
|
||||
import 'prismjs/components/prism-eiffel.js';
|
||||
import 'prismjs/components/prism-ejs.js';
|
||||
import 'prismjs/components/prism-elixir.js';
|
||||
import 'prismjs/components/prism-elm.js';
|
||||
import 'prismjs/components/prism-erb.js';
|
||||
import 'prismjs/components/prism-erlang.js';
|
||||
import 'prismjs/components/prism-etlua.js';
|
||||
import 'prismjs/components/prism-excel-formula.js';
|
||||
import 'prismjs/components/prism-factor.js';
|
||||
import 'prismjs/components/prism-false.js';
|
||||
import 'prismjs/components/prism-firestore-security-rules.js';
|
||||
import 'prismjs/components/prism-flow.js';
|
||||
import 'prismjs/components/prism-fortran.js';
|
||||
import 'prismjs/components/prism-fsharp.js';
|
||||
import 'prismjs/components/prism-ftl.js';
|
||||
import 'prismjs/components/prism-gap.js';
|
||||
import 'prismjs/components/prism-gcode.js';
|
||||
import 'prismjs/components/prism-gdscript.js';
|
||||
import 'prismjs/components/prism-gedcom.js';
|
||||
import 'prismjs/components/prism-gettext.js';
|
||||
import 'prismjs/components/prism-gherkin.js';
|
||||
import 'prismjs/components/prism-git.js';
|
||||
import 'prismjs/components/prism-glsl.js';
|
||||
import 'prismjs/components/prism-gml.js';
|
||||
import 'prismjs/components/prism-gn.js';
|
||||
import 'prismjs/components/prism-go-module.js';
|
||||
import 'prismjs/components/prism-go.js';
|
||||
import 'prismjs/components/prism-gradle.js';
|
||||
import 'prismjs/components/prism-graphql.js';
|
||||
import 'prismjs/components/prism-groovy.js';
|
||||
import 'prismjs/components/prism-haml.js';
|
||||
import 'prismjs/components/prism-handlebars.js';
|
||||
import 'prismjs/components/prism-haskell.js';
|
||||
import 'prismjs/components/prism-haxe.js';
|
||||
import 'prismjs/components/prism-hcl.js';
|
||||
import 'prismjs/components/prism-hlsl.js';
|
||||
import 'prismjs/components/prism-hoon.js';
|
||||
import 'prismjs/components/prism-hpkp.js';
|
||||
import 'prismjs/components/prism-hsts.js';
|
||||
import 'prismjs/components/prism-http.js';
|
||||
import 'prismjs/components/prism-ichigojam.js';
|
||||
import 'prismjs/components/prism-icon.js';
|
||||
import 'prismjs/components/prism-icu-message-format.js';
|
||||
import 'prismjs/components/prism-idris.js';
|
||||
import 'prismjs/components/prism-iecst.js';
|
||||
import 'prismjs/components/prism-ignore.js';
|
||||
import 'prismjs/components/prism-inform7.js';
|
||||
import 'prismjs/components/prism-ini.js';
|
||||
import 'prismjs/components/prism-io.js';
|
||||
import 'prismjs/components/prism-j.js';
|
||||
import 'prismjs/components/prism-java.js';
|
||||
import 'prismjs/components/prism-javadoclike.js';
|
||||
import 'prismjs/components/prism-javascript.js';
|
||||
import 'prismjs/components/prism-javastacktrace.js';
|
||||
import 'prismjs/components/prism-jexl.js';
|
||||
import 'prismjs/components/prism-jolie.js';
|
||||
import 'prismjs/components/prism-jq.js';
|
||||
import 'prismjs/components/prism-js-extras.js';
|
||||
import 'prismjs/components/prism-js-templates.js';
|
||||
import 'prismjs/components/prism-json.js';
|
||||
import 'prismjs/components/prism-json5.js';
|
||||
import 'prismjs/components/prism-jsonp.js';
|
||||
import 'prismjs/components/prism-jsstacktrace.js';
|
||||
import 'prismjs/components/prism-jsx.js';
|
||||
import 'prismjs/components/prism-julia.js';
|
||||
import 'prismjs/components/prism-keepalived.js';
|
||||
import 'prismjs/components/prism-keyman.js';
|
||||
import 'prismjs/components/prism-kotlin.js';
|
||||
import 'prismjs/components/prism-kumir.js';
|
||||
import 'prismjs/components/prism-kusto.js';
|
||||
import 'prismjs/components/prism-latex.js';
|
||||
import 'prismjs/components/prism-latte.js';
|
||||
import 'prismjs/components/prism-less.js';
|
||||
import 'prismjs/components/prism-lilypond.js';
|
||||
import 'prismjs/components/prism-linker-script.js';
|
||||
import 'prismjs/components/prism-liquid.js';
|
||||
import 'prismjs/components/prism-lisp.js';
|
||||
import 'prismjs/components/prism-livescript.js';
|
||||
import 'prismjs/components/prism-llvm.js';
|
||||
import 'prismjs/components/prism-log.js';
|
||||
import 'prismjs/components/prism-lolcode.js';
|
||||
import 'prismjs/components/prism-lua.js';
|
||||
import 'prismjs/components/prism-magma.js';
|
||||
import 'prismjs/components/prism-makefile.js';
|
||||
import 'prismjs/components/prism-markdown.js';
|
||||
import 'prismjs/components/prism-markup-templating.js';
|
||||
import 'prismjs/components/prism-markup.js';
|
||||
import 'prismjs/components/prism-mata.js';
|
||||
import 'prismjs/components/prism-matlab.js';
|
||||
import 'prismjs/components/prism-maxscript.js';
|
||||
import 'prismjs/components/prism-mel.js';
|
||||
import 'prismjs/components/prism-mermaid.js';
|
||||
import 'prismjs/components/prism-metafont.js';
|
||||
import 'prismjs/components/prism-mizar.js';
|
||||
import 'prismjs/components/prism-mongodb.js';
|
||||
import 'prismjs/components/prism-monkey.js';
|
||||
import 'prismjs/components/prism-moonscript.js';
|
||||
import 'prismjs/components/prism-n1ql.js';
|
||||
import 'prismjs/components/prism-n4js.js';
|
||||
import 'prismjs/components/prism-nand2tetris-hdl.js';
|
||||
import 'prismjs/components/prism-naniscript.js';
|
||||
import 'prismjs/components/prism-nasm.js';
|
||||
import 'prismjs/components/prism-neon.js';
|
||||
import 'prismjs/components/prism-nevod.js';
|
||||
import 'prismjs/components/prism-nginx.js';
|
||||
import 'prismjs/components/prism-nim.js';
|
||||
import 'prismjs/components/prism-nix.js';
|
||||
import 'prismjs/components/prism-nsis.js';
|
||||
import 'prismjs/components/prism-objectivec.js';
|
||||
import 'prismjs/components/prism-ocaml.js';
|
||||
import 'prismjs/components/prism-odin.js';
|
||||
import 'prismjs/components/prism-opencl.js';
|
||||
import 'prismjs/components/prism-openqasm.js';
|
||||
import 'prismjs/components/prism-oz.js';
|
||||
import 'prismjs/components/prism-parigp.js';
|
||||
import 'prismjs/components/prism-parser.js';
|
||||
import 'prismjs/components/prism-pascal.js';
|
||||
import 'prismjs/components/prism-pascaligo.js';
|
||||
import 'prismjs/components/prism-pcaxis.js';
|
||||
import 'prismjs/components/prism-peoplecode.js';
|
||||
import 'prismjs/components/prism-perl.js';
|
||||
import 'prismjs/components/prism-php-extras.js';
|
||||
import 'prismjs/components/prism-php.js';
|
||||
import 'prismjs/components/prism-phpdoc.js';
|
||||
import 'prismjs/components/prism-plant-uml.js';
|
||||
import 'prismjs/components/prism-powerquery.js';
|
||||
import 'prismjs/components/prism-powershell.js';
|
||||
import 'prismjs/components/prism-processing.js';
|
||||
import 'prismjs/components/prism-prolog.js';
|
||||
import 'prismjs/components/prism-promql.js';
|
||||
import 'prismjs/components/prism-properties.js';
|
||||
import 'prismjs/components/prism-protobuf.js';
|
||||
import 'prismjs/components/prism-psl.js';
|
||||
import 'prismjs/components/prism-pug.js';
|
||||
import 'prismjs/components/prism-puppet.js';
|
||||
import 'prismjs/components/prism-pure.js';
|
||||
import 'prismjs/components/prism-purebasic.js';
|
||||
import 'prismjs/components/prism-purescript.js';
|
||||
import 'prismjs/components/prism-python.js';
|
||||
import 'prismjs/components/prism-q.js';
|
||||
import 'prismjs/components/prism-qml.js';
|
||||
import 'prismjs/components/prism-qore.js';
|
||||
import 'prismjs/components/prism-qsharp.js';
|
||||
import 'prismjs/components/prism-r.js';
|
||||
import 'prismjs/components/prism-reason.js';
|
||||
import 'prismjs/components/prism-regex.js';
|
||||
import 'prismjs/components/prism-rego.js';
|
||||
import 'prismjs/components/prism-renpy.js';
|
||||
import 'prismjs/components/prism-rescript.js';
|
||||
import 'prismjs/components/prism-rest.js';
|
||||
import 'prismjs/components/prism-rip.js';
|
||||
import 'prismjs/components/prism-roboconf.js';
|
||||
import 'prismjs/components/prism-robotframework.js';
|
||||
import 'prismjs/components/prism-ruby.js';
|
||||
import 'prismjs/components/prism-rust.js';
|
||||
import 'prismjs/components/prism-sas.js';
|
||||
import 'prismjs/components/prism-sass.js';
|
||||
import 'prismjs/components/prism-scala.js';
|
||||
import 'prismjs/components/prism-scheme.js';
|
||||
import 'prismjs/components/prism-scss.js';
|
||||
import 'prismjs/components/prism-shell-session.js';
|
||||
import 'prismjs/components/prism-smali.js';
|
||||
import 'prismjs/components/prism-smalltalk.js';
|
||||
import 'prismjs/components/prism-smarty.js';
|
||||
import 'prismjs/components/prism-sml.js';
|
||||
import 'prismjs/components/prism-solidity.js';
|
||||
import 'prismjs/components/prism-solution-file.js';
|
||||
import 'prismjs/components/prism-soy.js';
|
||||
import 'prismjs/components/prism-splunk-spl.js';
|
||||
import 'prismjs/components/prism-sqf.js';
|
||||
import 'prismjs/components/prism-sql.js';
|
||||
import 'prismjs/components/prism-squirrel.js';
|
||||
import 'prismjs/components/prism-stan.js';
|
||||
import 'prismjs/components/prism-stata.js';
|
||||
import 'prismjs/components/prism-stylus.js';
|
||||
import 'prismjs/components/prism-supercollider.js';
|
||||
import 'prismjs/components/prism-swift.js';
|
||||
import 'prismjs/components/prism-systemd.js';
|
||||
import 'prismjs/components/prism-t4-templating.js';
|
||||
import 'prismjs/components/prism-t4-vb.js';
|
||||
import 'prismjs/components/prism-tap.js';
|
||||
import 'prismjs/components/prism-tcl.js';
|
||||
import 'prismjs/components/prism-textile.js';
|
||||
import 'prismjs/components/prism-toml.js';
|
||||
import 'prismjs/components/prism-tremor.js';
|
||||
import 'prismjs/components/prism-diff.js';
|
||||
import 'prismjs/components/prism-docker.js';
|
||||
import 'prismjs/components/prism-markdown.js';
|
||||
import 'prismjs/components/prism-typescript.js'; // ts
|
||||
import 'prismjs/components/prism-jsx.js';
|
||||
import 'prismjs/components/prism-tsx.js';
|
||||
import 'prismjs/components/prism-tt2.js';
|
||||
import 'prismjs/components/prism-turtle.js';
|
||||
import 'prismjs/components/prism-twig.js';
|
||||
import 'prismjs/components/prism-typescript.js';
|
||||
import 'prismjs/components/prism-typoscript.js';
|
||||
import 'prismjs/components/prism-unrealscript.js';
|
||||
import 'prismjs/components/prism-uorazor.js';
|
||||
import 'prismjs/components/prism-uri.js';
|
||||
import 'prismjs/components/prism-v.js';
|
||||
import 'prismjs/components/prism-vala.js';
|
||||
import 'prismjs/components/prism-vbnet.js';
|
||||
import 'prismjs/components/prism-velocity.js';
|
||||
import 'prismjs/components/prism-verilog.js';
|
||||
import 'prismjs/components/prism-vhdl.js';
|
||||
import 'prismjs/components/prism-vim.js';
|
||||
import 'prismjs/components/prism-visual-basic.js';
|
||||
import 'prismjs/components/prism-warpscript.js';
|
||||
import 'prismjs/components/prism-wasm.js';
|
||||
import 'prismjs/components/prism-web-idl.js';
|
||||
import 'prismjs/components/prism-wgsl.js';
|
||||
import 'prismjs/components/prism-wiki.js';
|
||||
import 'prismjs/components/prism-wolfram.js';
|
||||
import 'prismjs/components/prism-wren.js';
|
||||
import 'prismjs/components/prism-xeora.js';
|
||||
import 'prismjs/components/prism-xml-doc.js';
|
||||
import 'prismjs/components/prism-xojo.js';
|
||||
import 'prismjs/components/prism-xquery.js';
|
||||
import 'prismjs/components/prism-yaml.js';
|
||||
import 'prismjs/components/prism-yang.js';
|
||||
import 'prismjs/components/prism-zig.js';
|
||||
import 'prismjs/components/prism-arduino.js';
|
||||
|
||||
// Broken:
|
||||
//
|
||||
// import 'prismjs/components/prism-bison.js';
|
||||
// import 'prismjs/components/prism-chaiscript.js';
|
||||
// import 'prismjs/components/prism-core.js';
|
||||
// import 'prismjs/components/prism-crystal.js';
|
||||
// import 'prismjs/components/prism-django.js';
|
||||
// import 'prismjs/components/prism-javadoc.js';
|
||||
// import 'prismjs/components/prism-jsdoc.js';
|
||||
// import 'prismjs/components/prism-plsql.js';
|
||||
// import 'prismjs/components/prism-racket.js';
|
||||
// import 'prismjs/components/prism-sparql.js';
|
||||
// import 'prismjs/components/prism-t4-cs.js';
|
||||
|
||||
import './ReactPrism.css';
|
||||
// using classNames .prism-dark .prism-light from ReactPrism.css
|
||||
|
||||
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
||||
import { MatrixClient, MatrixEvent } from 'matrix-js-sdk';
|
||||
import { addRecentEmoji, getRecentEmojis, IRecentEmojiContent } from './recent-emoji';
|
||||
import { AccountDataEvent } from '../../types/matrix/accountData';
|
||||
import { emojis } from './emoji';
|
||||
import { emojis, loadEmojiData } from './emoji';
|
||||
|
||||
// A Map-backed MatrixClient stub supporting get/setAccountData.
|
||||
const createMx = () => {
|
||||
@@ -25,6 +25,9 @@ const createMx = () => {
|
||||
const getStored = (store: Map<string, unknown>): IRecentEmojiContent['recent_emoji'] =>
|
||||
(store.get(AccountDataEvent.ElementRecentEmoji) as IRecentEmojiContent | undefined)?.recent_emoji;
|
||||
|
||||
// Emoji data is now loaded lazily; populate `emojis` before the round trips.
|
||||
await loadEmojiData();
|
||||
|
||||
// Pick two real unicode emojis to drive add->get round trips.
|
||||
const u1 = emojis[0].unicode;
|
||||
const u2 = emojis[1].unicode;
|
||||
|
||||
Reference in New Issue
Block a user