Skip to content

Commit 334341e

Browse files
authored
fix: certain characters make Obsidian freeze (#647)
This issue happens when certain characters like "©" are parsed by twemoji.parse() as non-emoji, while isEmoji() passes those. Fix #641
1 parent 5510e52 commit 334341e

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

src/editor/markdown-processors/icon-in-text.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,20 @@ export const processIconInTextMarkdown = (
153153
}
154154

155155
if (plugin.getSettings().emojiStyle === 'twemoji') {
156-
const toReplace = text.splitText(code.index);
157-
158-
const tagName = toReplace.parentElement?.tagName?.toLowerCase() ?? '';
156+
157+
const tagName = text.parentElement?.tagName?.toLowerCase() ?? ''; // "text" has the same parent as "toReplace"
159158
let fontSize = calculateFontTextSize();
160159

161160
if (isHeader(tagName)) {
162161
fontSize = calculateHeaderSize(tagName as HTMLHeader);
163162
}
164163

164+
// If emojiValue was an unparsed HTML img string, it will be skipped
165+
// by the treewalker, as img doesn't have any text node derived from it.
166+
// But, unfortunately, when passing certain character like "©" as the
167+
// second parameter of emoji.parseEmoji (before it was fixed), it will return
168+
// the string itself due to twemoji.parse perceive it as a normal character (non-emoji).
169+
// If it is the case, the string will be interpreted as a text node.
165170
const emojiValue = emoji.parseEmoji(
166171
plugin.getSettings().emojiStyle,
167172
code.text,
@@ -171,7 +176,13 @@ export const processIconInTextMarkdown = (
171176
return;
172177
}
173178

179+
// Split the text node only after checking emojiValue.
180+
const toReplace = text.splitText(code.index);
174181
const emojiNode = createSpan();
182+
// emojiValue should not be interpreted as a text node or as an element
183+
// containing text node, otherwise it will cause endlessly loop
184+
// due to TreeWalker considering the first part as its current node,
185+
// not the second one (except you add another TreeWalker.nextNode() here).
175186
emojiNode.innerHTML = emojiValue;
176187
toReplace.parentElement?.insertBefore(emojiNode, toReplace);
177188
toReplace.textContent = toReplace.wholeText.substring(code.text.length);

src/emoji.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1879,14 +1879,17 @@ const parseEmoji = (
18791879
): string | null => {
18801880
switch (style) {
18811881
case 'twemoji':
1882-
return twemoji.parse(str, {
1882+
let parsedStr = twemoji.parse(str, {
18831883
folder: 'svg',
18841884
ext: '.svg',
18851885
attributes: () => ({
18861886
width: `${size}px`,
18871887
height: `${size}px`,
18881888
}),
18891889
});
1890+
// Some characters like "©" are treated as non-emoji, and
1891+
// isEmoji method passes those. Use below expression to anticipate that.
1892+
return parsedStr === str ? null : parsedStr;
18901893
case 'native':
18911894
return str;
18921895
default:

0 commit comments

Comments
 (0)