PluginProbe
Code Block Pro – Beautiful Syntax Highlighting / 1.28.0
Code Block Pro – Beautiful Syntax Highlighting v1.28.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
code-block-pro / src / editor / controls / Sidebar.tsx

Sidebar.tsx in Code Block Pro – Beautiful Syntax Highlighting 1.28.0, at src/editor/controls/Sidebar.tsx

437 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { InspectorControls } from '@wordpress/block-editor';
2 import {
3 BaseControl,
4 Button,
5 CheckboxControl,
6 ExternalLink,
7 PanelBody,
8 SelectControl,
9 TextControl,
10 } from '@wordpress/components';
11 import { useDispatch } from '@wordpress/data';
12 // @ts-expect-error-next-line - store is not typed
13 import { store as editPostStore } from '@wordpress/edit-post';
14 import { useEffect, useState } from '@wordpress/element';
15 import { __ } from '@wordpress/i18n';
16 import { useCanEditHTML } from '../../hooks/useCanEditHTML';
17 import { useLanguage } from '../../hooks/useLanguage';
18 import { useGlobalStore } from '../../state/global';
19 import { useLanguageStore } from '../../state/language';
20 import { useThemeStore } from '../../state/theme';
21 import type { AttributesPropsAndSetter, Lang } from '../../types';
22 import { languages } from '../../util/languages';
23 import { ButtonsPanel } from '../components/ButtonsPanel';
24 import {
25 FontFamilySelect,
26 FontLineHeightSelect,
27 FontSizeSelect,
28 } from '../components/FontSelect';
29 import { FooterSelect } from '../components/FooterSelect';
30 import { HeaderSelect } from '../components/HeaderSelect';
31 import { HeightPanel } from '../components/HeightPanel';
32 import { MissingPermissionsTip } from '../components/misc/MissingPermissions';
33 import { SlotFactory } from '../components/SlotFactory';
34 import { ThemesPanel } from '../components/ThemesPanel';
35 import { BlurControl } from './BlurControl';
36 import { HighlightingControl } from './HighlightingControl';
37
38 export const SidebarControls = ({
39 attributes,
40 setAttributes,
41 }: AttributesPropsAndSetter) => {
42 const [language, setLanguage] = useLanguage({ attributes, setAttributes });
43 const { recentLanguages } = useLanguageStore();
44 const { updateThemeHistory } = useThemeStore();
45 const { bringAttentionToPanel } = useGlobalStore();
46 const { headerType, footerType } = attributes;
47 const languagesSorted = new Map(
48 Object.entries(languages).sort((a, b) => a[1].localeCompare(b[1])),
49 );
50 const canEdit = useCanEditHTML();
51 const footersNeedingLinks = ['simpleStringEnd', 'simpleStringStart'];
52 const showHeaderTextEdit = [
53 'simpleString',
54 'pillString',
55 'stringSmall',
56 ].includes(headerType);
57 const showFooterTextEdit = footersNeedingLinks.includes(footerType ?? '');
58 const showFooterLinkEdit = footersNeedingLinks.includes(footerType ?? '');
59 const showFooterLinkTargetEdit = footersNeedingLinks.includes(
60 footerType ?? '',
61 );
62 const [bringAttention, setBringAttention] = useState<string | false>(false);
63 const { openGeneralSidebar, closeGeneralSidebar } =
64 useDispatch(editPostStore);
65
66 useEffect(() => {
67 if (!bringAttentionToPanel) return;
68 closeGeneralSidebar('edit-post/block').then(() => {
69 setBringAttention(bringAttentionToPanel);
70 openGeneralSidebar('edit-post/block');
71 });
72 }, [bringAttentionToPanel, closeGeneralSidebar, openGeneralSidebar]);
73
74 if (!canEdit)
75 return (
76 <InspectorControls>
77 {canEdit ? null : <MissingPermissionsTip />}
78 </InspectorControls>
79 );
80
81 return (
82 <InspectorControls>
83 {window?.codeBlockProThemes &&
84 // If they have the pro versoin, aren't using the update server
85 !window?.codeBlockProThemes?.hasUpdateServer ? (
86 <div className="code-block-pro-editor">
87 <div className="m-4 p-2 border border-solid border-gray-900 rounded">
88 <p className="m-0 p-0 text-sm mb-1">
89 <span className="font-medium text-wp-alert-red">
90 Action required:
91 </span>{' '}
92 The theme add-on pack has an update available that requires manual
93 installation.
94 </p>
95 <div className="flex flex-col gap-2">
96 <ExternalLink href="https://code-block-pro.com/auth/signin?callbackUrl=https%3A%2F%2Fcode-block-pro.com%2Fpurchases">
97 Code Block Pro Dashboard
98 </ExternalLink>
99 <ExternalLink href="https://github.com/KevinBatdorf/code-block-pro/discussions/384">
100 Learn more about it
101 </ExternalLink>
102 </div>
103 </div>
104 </div>
105 ) : null}
106 <SlotFactory
107 name="CodeBlockPro.Sidebar.Start"
108 attributes={attributes}
109 setAttributes={setAttributes}
110 />
111 <PanelBody
112 title={__('Line Settings', 'code-block-pro')}
113 initialOpen={false}
114 >
115 <div className="code-block-pro-editor">
116 <BaseControl id="code-block-pro-show-line-numbers">
117 <CheckboxControl
118 data-cy="show-line-numbers"
119 label={__('Line numbers', 'code-block-pro')}
120 help={__(
121 'Enable line numbers and set a starting number.',
122 'code-block-pro',
123 )}
124 checked={attributes.lineNumbers}
125 onChange={(lineNumbers) => {
126 setAttributes({ lineNumbers });
127 updateThemeHistory({ lineNumbers });
128 }}
129 />
130 {attributes.lineNumbers && (
131 <BaseControl id="code-block-pro-line-number-start">
132 <TextControl
133 id="code-block-pro-line-number-start"
134 spellCheck={false}
135 autoComplete="off"
136 label={__('Start from', 'code-block-pro')}
137 onChange={(startingLineNumber) => {
138 setAttributes({ startingLineNumber });
139 }}
140 value={attributes.startingLineNumber}
141 />
142 </BaseControl>
143 )}
144 </BaseControl>
145 <HighlightingControl
146 attributes={attributes}
147 setAttributes={setAttributes}
148 />
149 <BlurControl attributes={attributes} setAttributes={setAttributes} />
150 </div>
151 </PanelBody>
152 <ThemesPanel
153 bringAttentionToThemes={bringAttention === 'theme-select'}
154 attributes={attributes}
155 setAttributes={setAttributes}
156 />
157 <PanelBody
158 title={__('Language', 'code-block-pro')}
159 initialOpen={bringAttention === 'language-select'}
160 >
161 <div className="code-block-pro-editor">
162 <BaseControl id="code-block-pro-language">
163 <SelectControl
164 id="code-block-pro-language"
165 label={__('Code Language', 'code-block-pro')}
166 data-cy-cbp="language-select"
167 value={language}
168 onChange={(v) => setLanguage(v as Lang)}
169 help={
170 language === 'ansi'
171 ? __(
172 'Some code themes may not render ANSI correctly. Control sequences render only on the front.',
173 'code-block-pro',
174 )
175 : null
176 }
177 options={[...languagesSorted.entries()].map(([value, label]) => ({
178 label: label.replace('ANSI', 'ANSI (experimental)'),
179 value,
180 }))}
181 />
182 {recentLanguages?.length > 0 ? (
183 <>
184 <span className="mb-2 block">
185 {__('Recently Used', 'code-block-pro')}
186 </span>
187 <div className="flex flex-col gap-1">
188 {recentLanguages?.map((lang) => (
189 <Button
190 key={lang}
191 variant="link"
192 onClick={() => setLanguage(lang)}
193 >
194 {languages[lang] ?? lang}
195 </Button>
196 ))}
197 </div>
198 </>
199 ) : null}
200 </BaseControl>
201 </div>
202 </PanelBody>
203 <PanelBody
204 title={__('Header Type', 'code-block-pro')}
205 initialOpen={false}
206 >
207 {showHeaderTextEdit && (
208 <BaseControl id="code-block-pro-header-text">
209 <TextControl
210 id="code-block-pro-header-text"
211 spellCheck={false}
212 autoComplete="off"
213 label={__('Header Text', 'code-block-pro')}
214 placeholder={languages[language]}
215 onChange={(headerString) => {
216 setAttributes({ headerString });
217 }}
218 value={attributes.headerString ?? ''}
219 />
220 </BaseControl>
221 )}
222 <HeaderSelect
223 attributes={attributes}
224 onClick={(headerType) => {
225 setAttributes({ headerType });
226 updateThemeHistory({ headerType });
227 }}
228 />
229 </PanelBody>
230 <PanelBody
231 title={__('Footer Type', 'code-block-pro')}
232 initialOpen={false}
233 >
234 {showFooterTextEdit && (
235 <BaseControl id="code-block-pro-footer-text">
236 <TextControl
237 id="code-block-pro-footer-text"
238 spellCheck={false}
239 autoComplete="off"
240 label={__('Footer Text', 'code-block-pro')}
241 placeholder={languages[language]}
242 onChange={(footerString) => {
243 setAttributes({ footerString });
244 }}
245 value={attributes.footerString ?? ''}
246 />
247 </BaseControl>
248 )}
249 {showFooterLinkEdit && (
250 <BaseControl id="code-block-pro-footer-link">
251 <TextControl
252 id="code-block-pro-footer-link"
253 spellCheck={false}
254 type="url"
255 autoComplete="off"
256 label={__('Footer Link', 'code-block-pro')}
257 placeholder="https://example.com"
258 help={__('Leave blank to disable', 'code-block-pro')}
259 onChange={(footerLink) => {
260 setAttributes({ footerLink });
261 }}
262 value={attributes.footerLink ?? ''}
263 />
264 </BaseControl>
265 )}
266 {showFooterLinkTargetEdit && (
267 <BaseControl id="code-block-pro-footer-link-target">
268 <CheckboxControl
269 id="code-block-pro-footer-link-target"
270 label={__('Open in new tab?', 'code-block-pro')}
271 checked={attributes.footerLinkTarget}
272 onChange={(footerLinkTarget) => {
273 setAttributes({ footerLinkTarget });
274 updateThemeHistory({ footerLinkTarget });
275 }}
276 />
277 </BaseControl>
278 )}
279 <FooterSelect
280 attributes={attributes}
281 onClick={(footerType) => {
282 setAttributes({ footerType });
283 updateThemeHistory({ footerType });
284 }}
285 />
286 </PanelBody>
287 <SlotFactory
288 name="CodeBlockPro.Sidebar.Middle"
289 attributes={attributes}
290 setAttributes={setAttributes}
291 />
292 <ButtonsPanel attributes={attributes} setAttributes={setAttributes} />
293 <PanelBody
294 title={__('Font Styling', 'code-block-pro')}
295 initialOpen={false}
296 >
297 <div className="code-block-pro-editor" data-cy="font-size-select">
298 <h2 className="m-0">{__('Font Size', 'code-block-pro')}</h2>
299 <FontSizeSelect
300 value={attributes.fontSize}
301 onChange={(fontSize) => {
302 setAttributes({ fontSize });
303 updateThemeHistory({ fontSize });
304 }}
305 />
306 </div>
307 <div
308 className="code-block-pro-editor"
309 data-cy="font-line-height-select"
310 >
311 <h2 className="m-0">{__('Line Height', 'code-block-pro')}</h2>
312 <FontLineHeightSelect
313 value={attributes.lineHeight}
314 onChange={(lineHeight) => {
315 setAttributes({ lineHeight });
316 updateThemeHistory({ lineHeight });
317 }}
318 />
319 </div>
320 <div className="code-block-pro-editor" data-cy="font-family-select">
321 <FontFamilySelect
322 value={attributes.fontFamily}
323 onChange={(fontFamily) => {
324 setAttributes({ fontFamily });
325 updateThemeHistory({ fontFamily });
326 }}
327 />
328 </div>
329 <div className="code-block-pro-editor" data-cy="clamp-fonts">
330 <div className="mt-6">
331 <CheckboxControl
332 label={__('Clamp Font Sizes', 'code-block-pro')}
333 help={__(
334 'Check this if your font sizes are unusually large or tiny.',
335 'code-block-pro',
336 )}
337 checked={attributes.clampFonts}
338 onChange={(clampFonts) => {
339 setAttributes({ clampFonts });
340 updateThemeHistory({ clampFonts });
341 }}
342 />
343 </div>
344 </div>
345 </PanelBody>
346 <HeightPanel attributes={attributes} setAttributes={setAttributes} />
347 <PanelBody
348 title={__('Extra Settings', 'code-block-pro')}
349 initialOpen={false}
350 >
351 <BaseControl id="code-block-pro-disable-padding">
352 <CheckboxControl
353 data-cy="disable-padding"
354 label={__('Disable Padding', 'code-block-pro')}
355 help={__(
356 'This is useful if you pick a theme that matches your background color, and want the code to line up to the edge of your content. You may need to add your own padding with CSS.',
357 'code-block-pro',
358 )}
359 checked={attributes.disablePadding}
360 onChange={(disablePadding) => {
361 setAttributes({ disablePadding });
362 updateThemeHistory({ disablePadding });
363 }}
364 />
365 </BaseControl>
366 <BaseControl id="code-block-pro-decode-uri">
367 <CheckboxControl
368 data-cy="use-decode-uri"
369 label={__('Encode special characters', 'code-block-pro')}
370 help={__(
371 'Select this to allow HTML entities such as &lt; and &gt; and others to be displayed. You may need to re-add the code after changing this',
372 'code-block-pro',
373 )}
374 checked={attributes.useDecodeURI}
375 onChange={(useDecodeURI) => {
376 setAttributes({ useDecodeURI });
377 updateThemeHistory({ useDecodeURI });
378 }}
379 />
380 </BaseControl>
381 <BaseControl id="code-block-pro-escape-shortcodes">
382 <CheckboxControl
383 data-cy="use-escape-shortcodes"
384 label={__('Escape WordPress shortcodes', 'code-block-pro')}
385 help={__(
386 'Select this to prevent php shortcodes from executing.',
387 'code-block-pro',
388 )}
389 checked={attributes.useEscapeShortCodes}
390 onChange={(useEscapeShortCodes) => {
391 setAttributes({ useEscapeShortCodes });
392 updateThemeHistory({ useEscapeShortCodes });
393 }}
394 />
395 </BaseControl>
396 <BaseControl id="code-block-pro-editor-tab-size">
397 <TextControl
398 spellCheck={false}
399 autoComplete="off"
400 type="number"
401 data-cy="editor-tab-size"
402 label={__('Editor tab size', 'code-block-pro')}
403 help={__(
404 'The number of spaces to insert when pressing tab key.',
405 'code-block-pro',
406 )}
407 value={attributes.tabSize}
408 onChange={(size) => {
409 const tabSize = size ? Number(size) : undefined;
410 setAttributes({ tabSize });
411 updateThemeHistory({ tabSize });
412 }}
413 />
414 <CheckboxControl
415 data-cy="use-tabs"
416 label={__('Use real tabs', 'code-block-pro')}
417 help={__(
418 'Inserts an actual tab character instead of a space. The width defined above.',
419 'code-block-pro',
420 )}
421 checked={attributes.useTabs}
422 onChange={(useTabs) => {
423 setAttributes({ useTabs });
424 updateThemeHistory({ useTabs });
425 }}
426 />
427 </BaseControl>
428 </PanelBody>
429 <SlotFactory
430 name="CodeBlockPro.Sidebar.End"
431 attributes={attributes}
432 setAttributes={setAttributes}
433 />
434 </InspectorControls>
435 );
436 };
437