PluginProbe
Code Block Pro – Beautiful Syntax Highlighting / 1.13.0
Code Block Pro – Beautiful Syntax Highlighting v1.13.0
1.27.1 1.27.2 1.27.3 1.27.4 1.27.5 1.27.6 1.27.7 1.28.0 1.3.0 1.4.0 1.5.0 1.5.1 1.5.2 1.6.0 1.7.0 1.8.0 1.9.0 1.9.1 1.9.2 1.9.3 trunk 1.1.0 1.10.0 1.11.0 1.11.1 All 63 releases
← All changes | src/front/front.js +138 -13 1.8.01.13.0 View file →
@@ -1,12 +1,16 @@
1 1 import copy from 'copy-to-clipboard';
2 2
3 -// Handle copy button
4 -addEventListener('DOMContentLoaded', () => {
3 +const containerClass = '.wp-block-kevinbatdorf-code-block-pro';
4 +
5 +const handleCopyButton = () => {
5 6 const buttons = Array.from(
6 - document.querySelectorAll('.code-block-pro-copy-button'),
7 + document.querySelectorAll(
8 + '.code-block-pro-copy-button:not(.cbp-cb-loaded)',
9 + ),
7 10 );
8 11 buttons.forEach((button) => {
12 + button.classList.add('cbp-cb-loaded');
9 13 // Setting it to block here lets users deactivate the plugin safely
10 14 button.style.display = 'block';
11 15 button.addEventListener('click', (event) => {
12 16 const b = event.target?.closest('span');
@@ -18,20 +22,61 @@
18 22 b.classList.remove('copying');
19 23 }, 2000);
20 24 });
21 25 });
22 -});
26 +};
23 27
24 -// Handle font loading
25 -addEventListener('DOMContentLoaded', () => {
28 +const handleHighlighter = () => {
29 + const codeBlocks = Array.from(
30 + document.querySelectorAll(`${containerClass} pre:not(.cbp-hl-loaded)`),
31 + );
32 +
33 + codeBlocks.forEach((codeBlock) => {
34 + codeBlock.classList.add('cbp-hl-loaded');
35 + // Search for highlights
36 + const highlighters = codeBlock.querySelectorAll('.cbp-line-highlight');
37 + if (!highlighters.length) return;
38 +
39 + // We need to track the block width so we can adjust the
40 + // highlighter width in case of overflow
41 + const resizeObserver = new ResizeObserver((entries) => {
42 + entries.forEach((entry) => {
43 + // get width of inner code block
44 + codeBlock.style.setProperty('--cbp-block-width', '0');
45 + const codeWidth =
46 + entry.target.querySelector('code').offsetWidth;
47 + const computed =
48 + codeWidth + 16 === entry.target.scrollWidth
49 + ? codeWidth + 16
50 + : entry.target.scrollWidth + 16;
51 + codeBlock.style.setProperty(
52 + '--cbp-block-width',
53 + `${computed}px`,
54 + );
55 + });
56 + });
57 + resizeObserver.observe(codeBlock);
58 +
59 + // add the highlighter
60 + highlighters.forEach((highlighter) => {
61 + highlighter.insertAdjacentHTML(
62 + 'beforeend',
63 + '<span aria-hidden="true" class="cbp-line-highlighter"></span>',
64 + );
65 + });
66 + });
67 +};
68 +
69 +const handleFontLoading = () => {
26 70 if (!window.codeBlockPro?.pluginUrl) return;
71 + const elements = Array.from(
72 + document.querySelectorAll(
73 + '[data-code-block-pro-font-family]:not(.cbp-ff-loaded)',
74 + ) || [],
75 + );
76 + elements.forEach((e) => e.classList.add('cbp-ff-loaded'));
27 77 const fontsToLoad = new Set(
28 - Array.from(
29 - document.querySelectorAll('[data-code-block-pro-font-family]') ??
30 - [],
31 - )
32 - .map((f) => f.dataset.codeBlockProFontFamily)
33 - .filter(Boolean),
78 + elements.map((f) => f.dataset.codeBlockProFontFamily).filter(Boolean),
34 79 );
35 80 [...fontsToLoad].forEach(async (fontName) => {
36 81 const font = new FontFace(
37 82 fontName,
@@ -39,5 +84,85 @@
39 84 );
40 85 await font.load();
41 86 document.fonts.add(font);
42 87 });
43 -});
88 +};
89 +
90 +const handleSeeMore = () => {
91 + const seeMoreLines = Array.from(
92 + document.querySelectorAll(
93 + `${containerClass}:not(.cbp-see-more-loaded) .cbp-see-more-line`,
94 + ),
95 + );
96 + seeMoreLines.forEach((line) => {
97 + const currentContainer = line.closest(containerClass);
98 + currentContainer.classList.add('cbp-see-more-loaded');
99 + const pre = line.closest('pre');
100 + const initialHeight = pre.offsetHeight;
101 + let animationSpeed = 0;
102 +
103 + if (line.classList.contains('cbp-see-more-transition')) {
104 + const lineCount = pre.querySelectorAll('code > *').length;
105 + const linesBeforeCurrent = Array.from(
106 + line.closest('code').children,
107 + ).filter((l) => l.offsetTop < line.offsetTop)?.length;
108 + animationSpeed = 0.5 + (lineCount - linesBeforeCurrent) * 0.01;
109 + pre.style.transition = `max-height ${animationSpeed}s ease-out`;
110 + }
111 +
112 + // if the first child it a span then get the height of that span
113 + const headerHeight =
114 + currentContainer.children[0].tagName === 'SPAN'
115 + ? currentContainer.children[0].offsetHeight
116 + : 0;
117 + const lineHeight = parseFloat(window.getComputedStyle(line).lineHeight);
118 + pre.style.maxHeight = `${line.offsetTop + lineHeight - headerHeight}px`;
119 +
120 + const buttonContainer = line
121 + .closest(containerClass)
122 + .querySelector('.cbp-see-more-container');
123 + if (!buttonContainer) return;
124 + buttonContainer.style.display = 'flex';
125 + const button = buttonContainer.querySelector(
126 + '.cbp-see-more-simple-btn',
127 + );
128 + if (!button) return;
129 + if (currentContainer.classList.contains('padding-disabled')) {
130 + button.classList.remove('cbp-see-more-simple-btn-hover');
131 + }
132 + button.style.transition = `all ${
133 + Math.max(animationSpeed, 1) / 1.5
134 + }s linear`;
135 +
136 + const handle = (event) => {
137 + event.preventDefault();
138 + button.classList.remove('cbp-see-more-simple-btn-hover');
139 + pre.style.maxHeight = initialHeight + 'px';
140 + setTimeout(() => {
141 + button.style.opacity = 0;
142 + button.style.transform = 'translateY(-100%)';
143 + setTimeout(
144 + () => button.remove(),
145 + Math.max(animationSpeed, 1) * 1000,
146 + );
147 + }, animationSpeed * 1000);
148 + };
149 + button.addEventListener('click', handle);
150 + button.addEventListener('keypress', (event) => {
151 + if (event.key === 'Enter') handle(event);
152 + });
153 + });
154 +};
155 +
156 +const init = () => {
157 + handleSeeMore();
158 + handleCopyButton();
159 + handleHighlighter();
160 + handleFontLoading();
161 +};
162 +
163 +// Functions are idempotent, so we can run them on load and DOMContentLoaded
164 +init();
165 +// Useful for when the DOM is modified or loaded in late
166 +window.codeBlockProInit = init;
167 +window.addEventListener('DOMContentLoaded', init);
168 +window.addEventListener('load', init);