You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2026/07/06 18:58:32 UTC
(superset) 01/01: fix(ace-editor): carry token classes onto emoji boxes
This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch fix/ace-emoji-token-classes
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 0f51c61370f287d517adf5d7cd8972ad7887d616
Author: Evan Rusackas <ev...@rusackas.com>
AuthorDate: Mon Jul 6 11:58:17 2026 -0700
fix(ace-editor): carry token classes onto emoji boxes
Follow-up to #41697: the emoji spans were appended outside the
token-class wrapper ace puts around non-text tokens, so token styling
that isn't glyph color (comment italics, invalid-token backgrounds)
stopped applying to emoji segments. Mirror ace's text_util token-class
handling directly on the emoji box.
Co-Authored-By: Claude Fable 5 <no...@anthropic.com>
---
.../AsyncAceEditor/emojiWidthPatch.test.ts | 29 ++++++++++++++++++++++
.../components/AsyncAceEditor/emojiWidthPatch.ts | 14 ++++++++++-
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.test.ts b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.test.ts
index 2da3e2bdd9e..36c1a5d4af3 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.test.ts
+++ b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.test.ts
@@ -132,6 +132,35 @@ test('renderer leaves emoji-free tokens entirely to the original path', () => {
expect(screenColumn).toBe(8);
});
+test('emoji boxes carry the token-class styling of their token', () => {
+ const container = document.createElement('div');
+ const layer = new TextLayer(container);
+ layer.config = { characterWidth: 10 };
+
+ const parent = document.createElement('div');
+ layer.$renderToken(
+ parent,
+ 0,
+ { type: 'constant.language', value: '✨' },
+ '✨',
+ );
+
+ const box = parent.querySelector<HTMLElement>('.ace_cjk');
+ expect(box?.className).toBe('ace_cjk ace_constant ace_language');
+});
+
+test('emoji boxes in plain text tokens carry no extra classes', () => {
+ const container = document.createElement('div');
+ const layer = new TextLayer(container);
+ layer.config = { characterWidth: 10 };
+
+ const parent = document.createElement('div');
+ layer.$renderToken(parent, 0, { type: 'text', value: '✨' }, '✨');
+
+ const box = parent.querySelector<HTMLElement>('.ace_cjk');
+ expect(box?.className).toBe('ace_cjk');
+});
+
test('patch is idempotent', () => {
const before = EditSession.prototype.$getStringScreenWidth;
patchAceEmojiWidths(EditSession, TextLayer);
diff --git a/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.ts b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.ts
index 816ce06e631..55a0c5c889a 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.ts
+++ b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/emojiWidthPatch.ts
@@ -49,6 +49,10 @@
const VS16 = 0xfe0f;
+// Tokens ace renders as bare text nodes with no token-class span; mirrors
+// ace/layer/text_util's textTokens set.
+const TEXT_TOKENS = new Set(['text', 'rparen', 'lparen']);
+
// Emoji_Presentation covers exactly the codepoints browsers render as color
// emoji without a variation selector. Lone surrogates never match it (the
// astral path is already consistent), so only BMP emoji change behavior.
@@ -243,6 +247,14 @@ export function patchAceEmojiWidths(
if (!EMOJI_RUN_TEST_RE.test(value)) {
return origRenderToken.call(this, parent, screenColumn, token, value);
}
+ // Non-text tokens normally have their whole fragment wrapped in a
+ // token-class span ("ace_" + dotted type); carry those classes on the
+ // emoji box itself so syntax styling that isn't glyph color (comment
+ // italics, invalid-token backgrounds, …) still applies to emoji.
+ // Mirrors ace's text_util.isTextToken and $renderToken class handling.
+ const tokenClasses = TEXT_TOKENS.has(token.type)
+ ? ''
+ : ` ace_${token.type.replace(/\./g, ' ace_')}`;
let column = screenColumn;
value.split(EMOJI_RUN_SPLIT_RE).forEach((part, index) => {
if (!part) {
@@ -256,7 +268,7 @@ export function patchAceEmojiWidths(
cluster => {
const span = this.dom.createElement('span');
span.style.width = `${this.config.characterWidth * 2}px`;
- span.className = 'ace_cjk';
+ span.className = `ace_cjk${tokenClasses}`;
span.textContent = cluster;
parent.appendChild(span);
column += 2;