Skip to content

Commit 6b47133

Browse files
authoredSep 22, 2020
Match braces: Fixed JS interpolation punctuation (#2541)
1 parent cb75d9e commit 6b47133

File tree

3 files changed

+42
-45
lines changed

3 files changed

+42
-45
lines changed
 

‎plugins/match-braces/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ <h1>Examples</h1>
4444

4545
<h2>JavaScript</h2>
4646
<pre data-src="plugins/match-braces/prism-match-braces.js"></pre>
47+
<pre class="language-js"><code>const func = (a, b) => {
48+
return `${a}:${b}`;
49+
}</code></pre>
4750

4851
<h2>Lisp</h2>
4952
<pre class="language-lisp"><code>(defun factorial (n)

‎plugins/match-braces/prism-match-braces.js

+38-44
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,27 @@
44
return;
55
}
66

7-
var MATCH_ALL_CLASS = /(?:^|\s)match-braces(?:\s|$)/;
8-
9-
var BRACE_HOVER_CLASS = /(?:^|\s)brace-hover(?:\s|$)/;
10-
var BRACE_SELECTED_CLASS = /(?:^|\s)brace-selected(?:\s|$)/;
11-
12-
var NO_BRACE_HOVER_CLASS = /(?:^|\s)no-brace-hover(?:\s|$)/;
13-
var NO_BRACE_SELECT_CLASS = /(?:^|\s)no-brace-select(?:\s|$)/;
14-
157
var PARTNER = {
168
'(': ')',
179
'[': ']',
1810
'{': '}',
1911
};
2012

13+
// The names for brace types.
14+
// These names have two purposes: 1) they can be used for styling and 2) they are used to pair braces. Only braces
15+
// of the same type are paired.
2116
var NAMES = {
2217
'(': 'brace-round',
2318
'[': 'brace-square',
2419
'{': 'brace-curly',
2520
};
2621

22+
// A map for brace aliases.
23+
// This is useful for when some braces have a prefix/suffix as part of the punctuation token.
24+
var BRACE_ALIAS_MAP = {
25+
'${': '{', // JS template punctuation (e.g. `foo ${bar + 1}`)
26+
};
27+
2728
var LEVEL_WARP = 12;
2829

2930
var pairIdCounter = 0;
@@ -45,36 +46,32 @@
4546
* @this {HTMLElement}
4647
*/
4748
function hoverBrace() {
48-
for (var parent = this.parentElement; parent; parent = parent.parentElement) {
49-
if (NO_BRACE_HOVER_CLASS.test(parent.className)) {
50-
return;
51-
}
49+
if (!Prism.util.isActive(this, 'brace-hover', true)) {
50+
return;
5251
}
5352

54-
[this, getPartnerBrace(this)].forEach(function (ele) {
55-
ele.className = (ele.className.replace(BRACE_HOVER_CLASS, ' ') + ' brace-hover').replace(/\s+/g, ' ');
53+
[this, getPartnerBrace(this)].forEach(function (e) {
54+
e.classList.add('brace-hover');
5655
});
5756
}
5857
/**
5958
* @this {HTMLElement}
6059
*/
6160
function leaveBrace() {
62-
[this, getPartnerBrace(this)].forEach(function (ele) {
63-
ele.className = ele.className.replace(BRACE_HOVER_CLASS, ' ');
61+
[this, getPartnerBrace(this)].forEach(function (e) {
62+
e.classList.remove('brace-hover');
6463
});
6564
}
6665
/**
6766
* @this {HTMLElement}
6867
*/
6968
function clickBrace() {
70-
for (var parent = this.parentElement; parent; parent = parent.parentElement) {
71-
if (NO_BRACE_SELECT_CLASS.test(parent.className)) {
72-
return;
73-
}
69+
if (!Prism.util.isActive(this, 'brace-select', true)) {
70+
return;
7471
}
7572

76-
[this, getPartnerBrace(this)].forEach(function (ele) {
77-
ele.className = (ele.className.replace(BRACE_SELECTED_CLASS, ' ') + ' brace-selected').replace(/\s+/g, ' ');
73+
[this, getPartnerBrace(this)].forEach(function (e) {
74+
e.classList.add('brace-selected');
7875
});
7976
}
8077

@@ -91,11 +88,8 @@
9188
// find the braces to match
9289
/** @type {string[]} */
9390
var toMatch = [];
94-
for (var ele = code; ele; ele = ele.parentElement) {
95-
if (MATCH_ALL_CLASS.test(ele.className)) {
96-
toMatch.push('(', '[', '{');
97-
break;
98-
}
91+
if (Prism.util.isActive(code, 'match-braces')) {
92+
toMatch.push('(', '[', '{');
9993
}
10094

10195
if (toMatch.length == 0) {
@@ -108,8 +102,8 @@
108102
pre.addEventListener('mousedown', function removeBraceSelected() {
109103
// the code element might have been replaced
110104
var code = pre.querySelector('code');
111-
Array.prototype.slice.call(code.querySelectorAll('.brace-selected')).forEach(function (element) {
112-
element.className = element.className.replace(BRACE_SELECTED_CLASS, ' ');
105+
Array.prototype.slice.call(code.querySelectorAll('.brace-selected')).forEach(function (e) {
106+
e.classList.remove('brace-selected');
113107
});
114108
});
115109
Object.defineProperty(pre, '__listenerAdded', { value: true });
@@ -134,15 +128,16 @@
134128
var element = punctuation[i];
135129
if (element.childElementCount == 0) {
136130
var text = element.textContent;
131+
text = BRACE_ALIAS_MAP[text] || text;
137132
if (text === open) {
138133
allBraces.push({ index: i, open: true, element: element });
139-
element.className += ' ' + name;
140-
element.className += ' brace-open';
134+
element.classList.add(name);
135+
element.classList.add('brace-open');
141136
openStack.push(i);
142137
} else if (text === close) {
143138
allBraces.push({ index: i, open: false, element: element });
144-
element.className += ' ' + name;
145-
element.className += ' brace-close';
139+
element.classList.add(name);
140+
element.classList.add('brace-close');
146141
if (openStack.length) {
147142
pairs.push([i, openStack.pop()]);
148143
}
@@ -153,16 +148,16 @@
153148
pairs.forEach(function (pair) {
154149
var pairId = 'pair-' + (pairIdCounter++) + '-';
155150

156-
var openEle = punctuation[pair[0]];
157-
var closeEle = punctuation[pair[1]];
151+
var opening = punctuation[pair[0]];
152+
var closing = punctuation[pair[1]];
158153

159-
openEle.id = pairId + 'open';
160-
closeEle.id = pairId + 'close';
154+
opening.id = pairId + 'open';
155+
closing.id = pairId + 'close';
161156

162-
[openEle, closeEle].forEach(function (ele) {
163-
ele.addEventListener('mouseenter', hoverBrace);
164-
ele.addEventListener('mouseleave', leaveBrace);
165-
ele.addEventListener('click', clickBrace);
157+
[opening, closing].forEach(function (e) {
158+
e.addEventListener('mouseenter', hoverBrace);
159+
e.addEventListener('mouseleave', leaveBrace);
160+
e.addEventListener('click', clickBrace);
166161
});
167162
});
168163
});
@@ -171,14 +166,13 @@
171166
allBraces.sort(function (a, b) { return a.index - b.index; });
172167
allBraces.forEach(function (brace) {
173168
if (brace.open) {
174-
brace.element.className += ' brace-level-' + (level % LEVEL_WARP + 1);
169+
brace.element.classList.add('brace-level-' + (level % LEVEL_WARP + 1));
175170
level++;
176171
} else {
177172
level = Math.max(0, level - 1);
178-
brace.element.className += ' brace-level-' + (level % LEVEL_WARP + 1);
173+
brace.element.classList.add('brace-level-' + (level % LEVEL_WARP + 1));
179174
}
180175
});
181-
182176
});
183177

184178
}());

‎plugins/match-braces/prism-match-braces.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.