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/editor/Edit.tsx +46 -68 1.27.51.13.0 View file →
@@ -1,25 +1,22 @@
1 1 import {
2 2 useCallback,
3 - useState,
4 3 useEffect,
5 4 useLayoutEffect,
6 5 useRef,
7 6 } from '@wordpress/element';
7 +import { escapeHTML } from '@wordpress/escape-html';
8 8 import { applyFilters } from '@wordpress/hooks';
9 +import { decodeEntities } from '@wordpress/html-entities';
9 10 import { sprintf, __ } from '@wordpress/i18n';
11 +import { colord } from 'colord';
10 12 import Editor from 'react-simple-code-editor';
11 -import { useCanEditHTML } from '../hooks/useCanEditHTML';
12 13 import { useDefaults } from '../hooks/useDefaults';
13 14 import { useTheme } from '../hooks/useTheme';
14 15 import { useLanguageStore } from '../state/language';
15 16 import { AttributesPropsAndSetter, Lang } from '../types';
16 17 import { parseJSONArrayWithRanges } from '../util/arrayHelpers';
17 -import { decode, encode, escapeShortcodes } from '../util/code';
18 -import { computeLineHighlightColor } from '../util/colors';
19 -import { getTextWidth } from '../util/fonts';
20 18 import { getEditorLanguage } from '../util/languages';
21 -import { MissingPermissionsTip } from './components/misc/MissingPermissions';
22 19
23 20 export const Edit = ({
24 21 attributes,
25 22 setAttributes,
@@ -30,12 +27,15 @@
30 27 code = '',
31 28 bgColor: backgroundColor,
32 29 textColor: color,
33 30 disablePadding,
31 + lineNumbersWidth,
34 32 lineNumbers,
35 33 startingLineNumber,
36 34 footerType,
37 35 fontSize,
36 + fontFamily,
37 + lineHeight,
38 38 lineBlurs,
39 39 lineHighlights,
40 40 enableBlurring,
41 41 enableHighlighting,
@@ -42,20 +42,13 @@
42 42 seeMoreAfterLine,
43 43 seeMoreTransition,
44 44 enableMaxHeight,
45 45 editorHeight,
46 - useDecodeURI,
47 - useEscapeShortCodes,
48 - tabSize,
49 - useTabs,
50 46 } = attributes;
51 47
52 48 const textAreaRef = useRef<HTMLDivElement>(null);
53 - const canEdit = useCanEditHTML();
54 - const [editorLeftPadding, setEditorLeftPadding] = useState(0);
55 - const codeAreaRef = useRef<HTMLDivElement>(null);
56 49 const handleChange = (code: string) =>
57 - setAttributes({ code: encode(code, attributes) });
50 + setAttributes({ code: escapeHTML(code) });
58 51 const { previousLanguage } = useLanguageStore();
59 52 const { highlighter, error, loading } = useTheme({
60 53 theme,
61 54 lang: language ?? previousLanguage,
@@ -87,15 +80,15 @@
87 80 setAttributes({
88 81 bgColor: highlighter.getBackgroundColor(),
89 82 textColor: highlighter.getForegroundColor(),
90 83 });
91 - }, [theme, highlighter, setAttributes, canEdit]);
84 + }, [theme, highlighter, setAttributes]);
92 85
93 86 useEffect(() => {
94 87 if (!highlighter) return;
95 88 const l = (language ?? previousLanguage) as Lang | 'ansi';
96 89 const lang = getEditorLanguage(l);
97 - const c = decode(code, { useDecodeURI });
90 + const c = decodeEntities(code);
98 91 const lineOptions = [
99 92 ...getHighlights(),
100 93 ...getBlurs(),
101 94 enableMaxHeight && !Number.isNaN(seeMoreAfterLine)
@@ -116,20 +109,17 @@
116 109 'blocks.codeBlockPro.codeHTML',
117 110 rendered,
118 111 attributes,
119 112 ) as string;
120 - const lineHighlightColor = computeLineHighlightColor(color, attributes);
121 - setAttributes({
122 - codeHTML: useEscapeShortCodes
123 - ? escapeShortcodes(codeHTML)
124 - : codeHTML,
125 - lineHighlightColor,
126 - });
113 + const lineHighlightColor = colord(color)
114 + .saturate(0.5)
115 + .alpha(0.2)
116 + .toRgbString();
117 + setAttributes({ codeHTML, lineHighlightColor });
127 118 }, [
128 119 highlighter,
129 120 seeMoreAfterLine,
130 121 seeMoreTransition,
131 - canEdit,
132 122 color,
133 123 code,
134 124 enableMaxHeight,
135 125 language,
@@ -139,48 +129,52 @@
139 129 lineHighlights,
140 130 lineBlurs,
141 131 getBlurs,
142 132 getHighlights,
143 - useDecodeURI,
144 - useEscapeShortCodes,
145 133 ]);
146 134
147 135 useLayoutEffect(() => {
148 - if (!codeAreaRef.current) return;
136 + if (!textAreaRef.current) return;
149 137 if (!lineNumbers) {
150 138 setAttributes({ lineNumbersWidth: undefined });
151 139 return;
152 140 }
153 -
154 - // Calulate the line numbers width
155 - const codeLines = codeAreaRef?.current?.querySelectorAll('.line');
156 - const highestLineNumber =
157 - Number(startingLineNumber ?? 0) + (codeLines?.length ?? 0);
158 - if (!codeLines?.[0]) return;
159 - setAttributes({ highestLineNumber });
160 -
161 - // Used for the editor, which requires px values
162 - const { font } = getComputedStyle(codeLines?.[0]);
163 - setEditorLeftPadding(getTextWidth(String(highestLineNumber), font));
141 + // Get the last line (assumingly the widest)
142 + const lastLine = Array.from(
143 + textAreaRef?.current?.querySelectorAll('.line') ?? [],
144 + )?.at(-1) as HTMLElement;
145 + // Make sure there are no width constraints
146 + lastLine?.classList?.add('cbp-line-number-width-forced');
147 + const lastLineWidth = lastLine?.getBoundingClientRect()?.width ?? 0;
148 + // Add .cbp-line-number-disabled to disable the line number
149 + lastLine?.classList.add('cbp-line-number-disabled');
150 + // Re calculate the width of the last line
151 + const newWidth = lastLine?.getBoundingClientRect()?.width ?? 0;
152 + // Remove the classes
153 + lastLine?.classList.remove('cbp-line-number-disabled');
154 + lastLine?.classList?.remove('cbp-line-number-width-forced');
155 + // Calculate the difference
156 + if (lastLineWidth - newWidth > 0) {
157 + setAttributes({ lineNumbersWidth: lastLineWidth - newWidth - 12 });
158 + }
164 159 }, [
165 160 lineNumbers,
166 161 startingLineNumber,
167 162 code,
168 163 loading,
169 - canEdit,
170 164 error,
171 165 textAreaRef,
172 - codeAreaRef,
173 166 setAttributes,
174 167 fontSize,
175 - loading,
168 + fontFamily,
169 + lineHeight,
176 170 ]);
177 171
178 172 if (!loading && !highlighter) {
179 173 return (
180 174 <div
181 - className="px-4 text-left flex items-center"
182 - style={{ backgroundColor, color, minHeight: 36 }}>
175 + className="p-8 px-4 text-left"
176 + style={{ backgroundColor, color }}>
183 177 {sprintf(
184 178 __(
185 179 'Theme %s not found. Please select a different theme.',
186 180 'code-block-pro',
@@ -193,20 +187,18 @@
193 187
194 188 if ((loading && code) || error) {
195 189 return (
196 190 <div
197 - className="px-4 text-left flex items-center"
198 - style={{ backgroundColor, color, minHeight: 36 }}>
191 + className="p-6 px-4 text-left"
192 + style={{ backgroundColor, color }}>
199 193 {error?.message ?? ''}
200 194 </div>
201 195 );
202 196 }
203 197
204 - if (canEdit === undefined) return null;
205 -
206 198 return (
207 199 <div
208 - ref={codeAreaRef}
200 + ref={textAreaRef}
209 201 style={{
210 202 maxHeight: Number(editorHeight)
211 203 ? Number(editorHeight)
212 204 : undefined,
@@ -211,20 +203,11 @@
211 203 ? Number(editorHeight)
212 204 : undefined,
213 205 overflow: Number(editorHeight) ? 'auto' : undefined,
214 206 }}>
215 - {canEdit ? null : (
216 - <div className="absolute inset-0 z-10">
217 - <MissingPermissionsTip />
218 - </div>
219 - )}
220 207 <Editor
221 - value={decode(code, { useDecodeURI })}
208 + value={decodeEntities(code)}
222 209 onValueChange={handleChange}
223 - // eslint-disable-next-line jsx-a11y/no-autofocus -- Only autofocus in the unintended case that there is no code (e.g. on initial insert)
224 - autoFocus={!code}
225 - tabSize={useTabs ? 1 : tabSize || 2}
226 - insertSpaces={!useTabs}
227 210 padding={{
228 211 top: disablePadding ? 0 : 16,
229 212 bottom: disablePadding || hasFooter ? 0 : 16,
230 213 left: (() => {
@@ -229,28 +212,23 @@
229 212 bottom: disablePadding || hasFooter ? 0 : 16,
230 213 left: (() => {
231 214 if (!lineNumbers && disablePadding) return 0;
232 215 if (!lineNumbers) return 16;
233 - if (disablePadding)
234 - return (editorLeftPadding ?? 0) + 16;
235 - return (editorLeftPadding ?? 0) + 32;
216 + if (disablePadding) return (lineNumbersWidth ?? 0) + 16;
217 + return (lineNumbersWidth ?? 0) + 32;
236 218 })(),
237 219 right: 0,
238 220 }}
239 - style={{
240 - backgroundColor,
241 - color,
242 - minHeight: canEdit ? undefined : 200,
243 - }}
221 + style={{ backgroundColor, color }}
244 222 // eslint-disable-next-line
245 223 onKeyDown={(e: any) =>
246 224 e.key === 'Tab' &&
247 225 // Tab lock here. Pressing Escape will unlock.
248 - codeAreaRef.current?.querySelector('textarea')?.focus()
226 + textAreaRef.current?.querySelector('textarea')?.focus()
249 227 }
250 228 highlight={(code: string) =>
251 229 highlighter
252 - ?.codeToHtml(decode(code, { useDecodeURI }), {
230 + ?.codeToHtml(decodeEntities(code), {
253 231 lang: getEditorLanguage(
254 232 language ?? previousLanguage,
255 233 ),
256 234 lineOptions: [...getHighlights(), ...getBlurs()],