Skip to content

Commit

Permalink
Match braces: Fixed JS interpolation punctuation (#2541)
Browse files Browse the repository at this point in the history
  • Loading branch information
RunDevelopment authored Sep 22, 2020
1 parent cb75d9e commit 6b47133
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 45 deletions.
3 changes: 3 additions & 0 deletions plugins/match-braces/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ <h1>Examples</h1>

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

<h2>Lisp</h2>
<pre class="language-lisp"><code>(defun factorial (n)
Expand Down
82 changes: 38 additions & 44 deletions plugins/match-braces/prism-match-braces.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@
return;
}

var MATCH_ALL_CLASS = /(?:^|\s)match-braces(?:\s|$)/;

var BRACE_HOVER_CLASS = /(?:^|\s)brace-hover(?:\s|$)/;
var BRACE_SELECTED_CLASS = /(?:^|\s)brace-selected(?:\s|$)/;

var NO_BRACE_HOVER_CLASS = /(?:^|\s)no-brace-hover(?:\s|$)/;
var NO_BRACE_SELECT_CLASS = /(?:^|\s)no-brace-select(?:\s|$)/;

var PARTNER = {
'(': ')',
'[': ']',
'{': '}',
};

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

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

var LEVEL_WARP = 12;

var pairIdCounter = 0;
Expand All @@ -45,36 +46,32 @@
* @this {HTMLElement}
*/
function hoverBrace() {
for (var parent = this.parentElement; parent; parent = parent.parentElement) {
if (NO_BRACE_HOVER_CLASS.test(parent.className)) {
return;
}
if (!Prism.util.isActive(this, 'brace-hover', true)) {
return;
}

[this, getPartnerBrace(this)].forEach(function (ele) {
ele.className = (ele.className.replace(BRACE_HOVER_CLASS, ' ') + ' brace-hover').replace(/\s+/g, ' ');
[this, getPartnerBrace(this)].forEach(function (e) {
e.classList.add('brace-hover');
});
}
/**
* @this {HTMLElement}
*/
function leaveBrace() {
[this, getPartnerBrace(this)].forEach(function (ele) {
ele.className = ele.className.replace(BRACE_HOVER_CLASS, ' ');
[this, getPartnerBrace(this)].forEach(function (e) {
e.classList.remove('brace-hover');
});
}
/**
* @this {HTMLElement}
*/
function clickBrace() {
for (var parent = this.parentElement; parent; parent = parent.parentElement) {
if (NO_BRACE_SELECT_CLASS.test(parent.className)) {
return;
}
if (!Prism.util.isActive(this, 'brace-select', true)) {
return;
}

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

Expand All @@ -91,11 +88,8 @@
// find the braces to match
/** @type {string[]} */
var toMatch = [];
for (var ele = code; ele; ele = ele.parentElement) {
if (MATCH_ALL_CLASS.test(ele.className)) {
toMatch.push('(', '[', '{');
break;
}
if (Prism.util.isActive(code, 'match-braces')) {
toMatch.push('(', '[', '{');
}

if (toMatch.length == 0) {
Expand All @@ -108,8 +102,8 @@
pre.addEventListener('mousedown', function removeBraceSelected() {
// the code element might have been replaced
var code = pre.querySelector('code');
Array.prototype.slice.call(code.querySelectorAll('.brace-selected')).forEach(function (element) {
element.className = element.className.replace(BRACE_SELECTED_CLASS, ' ');
Array.prototype.slice.call(code.querySelectorAll('.brace-selected')).forEach(function (e) {
e.classList.remove('brace-selected');
});
});
Object.defineProperty(pre, '__listenerAdded', { value: true });
Expand All @@ -134,15 +128,16 @@
var element = punctuation[i];
if (element.childElementCount == 0) {
var text = element.textContent;
text = BRACE_ALIAS_MAP[text] || text;
if (text === open) {
allBraces.push({ index: i, open: true, element: element });
element.className += ' ' + name;
element.className += ' brace-open';
element.classList.add(name);
element.classList.add('brace-open');
openStack.push(i);
} else if (text === close) {
allBraces.push({ index: i, open: false, element: element });
element.className += ' ' + name;
element.className += ' brace-close';
element.classList.add(name);
element.classList.add('brace-close');
if (openStack.length) {
pairs.push([i, openStack.pop()]);
}
Expand All @@ -153,16 +148,16 @@
pairs.forEach(function (pair) {
var pairId = 'pair-' + (pairIdCounter++) + '-';

var openEle = punctuation[pair[0]];
var closeEle = punctuation[pair[1]];
var opening = punctuation[pair[0]];
var closing = punctuation[pair[1]];

openEle.id = pairId + 'open';
closeEle.id = pairId + 'close';
opening.id = pairId + 'open';
closing.id = pairId + 'close';

[openEle, closeEle].forEach(function (ele) {
ele.addEventListener('mouseenter', hoverBrace);
ele.addEventListener('mouseleave', leaveBrace);
ele.addEventListener('click', clickBrace);
[opening, closing].forEach(function (e) {
e.addEventListener('mouseenter', hoverBrace);
e.addEventListener('mouseleave', leaveBrace);
e.addEventListener('click', clickBrace);
});
});
});
Expand All @@ -171,14 +166,13 @@
allBraces.sort(function (a, b) { return a.index - b.index; });
allBraces.forEach(function (brace) {
if (brace.open) {
brace.element.className += ' brace-level-' + (level % LEVEL_WARP + 1);
brace.element.classList.add('brace-level-' + (level % LEVEL_WARP + 1));
level++;
} else {
level = Math.max(0, level - 1);
brace.element.className += ' brace-level-' + (level % LEVEL_WARP + 1);
brace.element.classList.add('brace-level-' + (level % LEVEL_WARP + 1));
}
});

});

}());
2 changes: 1 addition & 1 deletion plugins/match-braces/prism-match-braces.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6b47133

Please sign in to comment.