PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / regex-tester / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/regex-tester/index.js

266 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var useState = wp.element.useState;
4 var Fragment = wp.element.Fragment;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var __ = wp.i18n.__;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var TextControl = wp.components.TextControl;
13 var ToggleControl = wp.components.ToggleControl;
14
15 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
16 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
17
18 var v1Attributes = {
19 title: { type: 'string', default: 'Regex Tester' },
20 subtitle: { type: 'string', default: 'Test regular expressions with live match highlighting' },
21 defaultPattern: { type: 'string', default: '\\b\\w+@\\w+\\.\\w+\\b' },
22 defaultFlags: { type: 'string', default: 'gi' },
23 defaultTestStr: { type: 'string', default: 'Contact us at hello@example.com or support@company.org\nVisit our site at https://example.com for more info.' },
24 showGroups: { type: 'boolean', default: true },
25 showCheatsheet: { type: 'boolean', default: false },
26 editorHeight: { type: 'integer', default: 160 },
27 editorFontSize: { type: 'integer', default: 14 },
28 accentColor: { type: 'string', default: '#f59e0b' },
29 matchBg: { type: 'string', default: '#fef3c7' },
30 matchBorder: { type: 'string', default: '#f59e0b' },
31 groupColors: { type: 'string', default: '#bfdbfe,#bbf7d0,#fecaca,#e9d5ff' },
32 cardBg: { type: 'string', default: '#ffffff' },
33 editorBg: { type: 'string', default: '#1e1e2e' },
34 editorText: { type: 'string', default: '#cdd6f4' },
35 sectionBg: { type: 'string', default: '#f9fafb' },
36 titleColor: { type: 'string', default: '#111827' },
37 subtitleColor: { type: 'string', default: '#6b7280' },
38 labelColor: { type: 'string', default: '#374151' },
39 errorColor: { type: 'string', default: '#dc2626' },
40 titleFontSize: { type: 'integer', default: 26 },
41 contentMaxWidth: { type: 'integer', default: 780 },
42 titleFontWeight: { type: 'integer', default: 700 },
43 titleLineHeight: { type: 'number', default: 1.2 },
44 editorFontWeight: { type: 'integer', default: 400 },
45 editorLineHeight: { type: 'number', default: 1.6 }
46 };
47
48 var CHEATSHEET = [
49 { sym: '.', desc: 'Any character except newline' },
50 { sym: '\\d', desc: 'Digit [0-9]' },
51 { sym: '\\w', desc: 'Word char [a-zA-Z0-9_]' },
52 { sym: '\\s', desc: 'Whitespace' },
53 { sym: '^', desc: 'Start of string/line' },
54 { sym: '$', desc: 'End of string/line' },
55 { sym: '*', desc: 'Zero or more' },
56 { sym: '+', desc: 'One or more' },
57 { sym: '?', desc: 'Zero or one' },
58 { sym: '()', desc: 'Capture group' },
59 { sym: '(?:)', desc: 'Non-capture group' },
60 { sym: '|', desc: 'Alternation (or)' },
61 { sym: '[]', desc: 'Character class' },
62 { sym: '{n,m}', desc: 'Between n and m times' }
63 ];
64
65 function tryRegex(pattern, flags) {
66 try {
67 return { re: new RegExp(pattern, flags), error: null };
68 } catch(e) {
69 return { re: null, error: e.message };
70 }
71 }
72
73 function countMatches(re, str) {
74 if (!re) return [];
75 var matches = [], m;
76 var r = new RegExp(re.source, re.flags.includes('g') ? re.flags : re.flags + 'g');
77 while ((m = r.exec(str)) !== null) {
78 matches.push(m);
79 if (!r.global) break;
80 }
81 return matches;
82 }
83
84 function MatchBadge(props) {
85 return el('div', { className: 'bkbg-rt-match-badge', style: { borderColor: props.accentColor + '55', background: props.accentColor + '14' } },
86 el('span', { className: 'bkbg-rt-match-idx', style: { color: props.accentColor } }, '#' + (props.idx + 1)),
87 el('span', { className: 'bkbg-rt-match-val', style: { color: props.labelColor } }, props.val),
88 props.groups && props.groups.length > 0 && el('span', { className: 'bkbg-rt-match-groups', style: { color: '#9ca3af' } },
89 ' Groups: ' + props.groups.filter(function(g){ return g !== undefined; }).join(', ')
90 )
91 );
92 }
93
94 function Editor(props) {
95 var a = props.attributes, sa = props.setAttributes;
96 var TC = getTypoControl();
97 var lc = a.labelColor || '#374151';
98 var patState = useState(a.defaultPattern || ''); var pat = patState[0]; var setPat = patState[1];
99 var flagState = useState(a.defaultFlags || 'gi'); var flags = flagState[0]; var setFlags = flagState[1];
100 var testState = useState(a.defaultTestStr || ''); var testStr = testState[0]; var setTest = testState[1];
101
102 var result = tryRegex(pat, flags);
103 var matches = result.re ? countMatches(result.re, testStr) : [];
104
105 function toggleFlag(f) {
106 var newF = flags.includes(f) ? flags.replace(f,'') : flags + f;
107 setFlags(newF);
108 sa({ defaultFlags: newF });
109 }
110
111 var blockProps = useBlockProps((function() {
112 var _tvFn = getTypoCssVars();
113 var s = {};
114 if (_tvFn) {
115 Object.assign(s, _tvFn(a.titleTypo || {}, '--bkbgrt-tt-'));
116 Object.assign(s, _tvFn(a.editorTypo || {}, '--bkbgrt-et-'));
117 }
118 return { className: 'bkbg-rt-app', style: s };
119 })());
120
121 return el(Fragment, null,
122 el(InspectorControls, null,
123 el(PanelBody, { title: __('Content'), initialOpen: true },
124 el(TextControl, { label: __('Title'), value: a.title || '', onChange: function(v){ sa({ title: v }); } }),
125 el(TextControl, { label: __('Subtitle'), value: a.subtitle || '', onChange: function(v){ sa({ subtitle: v }); } }),
126 el(TextControl, { label: __('Default Pattern'), value: a.defaultPattern || '', onChange: function(v){ sa({ defaultPattern: v }); setPat(v); } }),
127 el(TextControl, { label: __('Default Flags'), value: a.defaultFlags || 'gi', onChange: function(v){ sa({ defaultFlags: v }); setFlags(v); } }),
128 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Capture Groups'), checked: a.showGroups !== false, onChange: function(v){ sa({ showGroups: v }); } }),
129 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Cheatsheet'), checked: a.showCheatsheet === true, onChange: function(v){ sa({ showCheatsheet: v }); } })
130 ),
131
132 el(PanelBody, { title: __('Typography'), initialOpen: false },
133 TC && el(TC, { label: __('Title'), value: a.titleTypo || {}, onChange: function(v) { sa({ titleTypo: v }); } }),
134 TC && el(TC, { label: __('Code / Editor'), value: a.editorTypo || {}, onChange: function(v) { sa({ editorTypo: v }); } })
135 ),
136 el(PanelColorSettings, {
137 title: __('Colors'),
138 initialOpen: false,
139 colorSettings: [
140 { value: a.accentColor ||'#f59e0b', onChange: function(v){ sa({ accentColor: v }); }, label: 'Accent / Matches' },
141 { value: a.matchBg ||'#fef3c7', onChange: function(v){ sa({ matchBg: v }); }, label: 'Match Highlight Bg' },
142 { value: a.editorBg ||'#1e1e2e', onChange: function(v){ sa({ editorBg: v }); }, label: 'Code Editor Bg' },
143 { value: a.editorText ||'#cdd6f4', onChange: function(v){ sa({ editorText: v }); }, label: 'Code Editor Text' },
144 { value: a.errorColor ||'#dc2626', onChange: function(v){ sa({ errorColor: v }); }, label: 'Error Color' },
145 { value: a.cardBg ||'#ffffff', onChange: function(v){ sa({ cardBg: v }); }, label: 'Card Background' },
146 { value: a.sectionBg ||'#f9fafb', onChange: function(v){ sa({ sectionBg: v }); }, label: 'Section Background' },
147 { value: a.titleColor ||'#111827', onChange: function(v){ sa({ titleColor: v }); }, label: 'Title' },
148 { value: a.subtitleColor ||'#6b7280', onChange: function(v){ sa({ subtitleColor: v }); }, label: 'Subtitle' },
149 { value: a.labelColor ||'#374151', onChange: function(v){ sa({ labelColor: v }); }, label: 'Labels' }
150 ]
151 }),
152 el(PanelBody, { title: __('Sizing'), initialOpen: false },
153 el(RangeControl, { label: __('Editor Height (px)'), value: a.editorHeight || 160, min: 80, max: 600, onChange: function(v){ sa({ editorHeight: v }); } }),
154 el(RangeControl, { label: __('Max Width (px)'), value: a.contentMaxWidth || 780, min: 360, max: 1400, step: 10, onChange: function(v){ sa({ contentMaxWidth: v }); } })
155 )
156 ),
157
158 el('div', blockProps,
159 el('div', { className: 'bkbg-rt-card', style: { background: a.cardBg||'#fff', maxWidth:(a.contentMaxWidth||780)+'px' } },
160 el('h2', { className: 'bkbg-rt-title', style: { color: a.titleColor||'#111827' } },
161 a.title || 'Regex Tester'
162 ),
163 el('p', { className: 'bkbg-rt-subtitle', style: { color: a.subtitleColor||'#6b7280' } },
164 a.subtitle || 'Test regular expressions with live match highlighting'
165 ),
166
167 // Pattern row
168 el('div', { className: 'bkbg-rt-pattern-row' },
169 el('div', { className: 'bkbg-rt-pattern-wrap', style: { background: a.editorBg||'#1e1e2e' } },
170 el('span', { className: 'bkbg-rt-slash', style: { color: a.accentColor||'#f59e0b' } }, '/'),
171 el('input', {
172 className: 'bkbg-rt-pattern-input',
173 style: { color: a.editorText||'#cdd6f4', background: 'transparent' },
174 value: pat, placeholder: 'Enter pattern…',
175 onChange: function(e){ setPat(e.target.value); sa({ defaultPattern: e.target.value }); }
176 }),
177 el('span', { className: 'bkbg-rt-slash', style: { color: a.accentColor||'#f59e0b' } }, '/'),
178 el('input', {
179 className: 'bkbg-rt-flags-input',
180 style: { color: a.accentColor||'#f59e0b', background: 'transparent' },
181 value: flags, placeholder: 'gi',
182 onChange: function(e){ var f = e.target.value.replace(/[^gimsuy]/g,''); setFlags(f); sa({ defaultFlags: f }); }
183 })
184 ),
185 result.error && el('div', { className: 'bkbg-rt-error', style: { color: a.errorColor||'#dc2626' } }, '' + result.error),
186
187 // Flag toggles
188 el('div', { className: 'bkbg-rt-flags-row' },
189 ['g','i','m','s'].map(function(f) {
190 var active = flags.includes(f);
191 return el('button', {
192 key: f,
193 className: 'bkbg-rt-flag-btn',
194 style: {
195 background: active ? (a.accentColor||'#f59e0b') : '#f3f4f6',
196 color: active ? '#fff' : lc
197 },
198 onClick: function(){ toggleFlag(f); }
199 },
200 el('strong', null, f),
201 el('span', null, { g:'global', i:'ignore case', m:'multiline', s:'dotAll' }[f])
202 );
203 })
204 )
205 ),
206
207 // Test string
208 el('div', { className: 'bkbg-rt-section' },
209 el('label', { className: 'bkbg-rt-label', style: { color: lc } }, 'Test String'),
210 el('textarea', {
211 className: 'bkbg-rt-textarea',
212 style: { background: a.sectionBg||'#f9fafb', color: lc, minHeight:(a.editorHeight||160)+'px' },
213 value: testStr,
214 onChange: function(e){ setTest(e.target.value); sa({ defaultTestStr: e.target.value }); }
215 })
216 ),
217
218 // Stats bar
219 el('div', { className: 'bkbg-rt-stats', style: { background: a.sectionBg||'#f9fafb', color: lc } },
220 result.error
221 ? el('span', { style: { color: a.errorColor||'#dc2626' } }, '⚠ Invalid pattern')
222 : el(Fragment, null,
223 el('span', null,
224 'Matches: ',
225 el('strong', { style: { color: a.accentColor||'#f59e0b' } }, matches.length)
226 ),
227 matches.length > 0 && el('span', null,
228 ' Groups per match: ',
229 el('strong', null, matches[0].length - 1)
230 )
231 )
232 ),
233
234 // Matches list
235 matches.length > 0 && a.showGroups !== false && el('div', { className: 'bkbg-rt-matches' },
236 el('div', { className: 'bkbg-rt-matches-title', style: { color: lc } }, 'Matches'),
237 matches.slice(0, 20).map(function(m, i) {
238 return el(MatchBadge, { key: i, idx: i, val: m[0], groups: Array.from(m).slice(1), accentColor: a.accentColor||'#f59e0b', labelColor: lc });
239 }),
240 matches.length > 20 && el('div', { className: 'bkbg-rt-more', style: { color: '#9ca3af' } }, '+ ' + (matches.length - 20) + ' more matches')
241 )
242 )
243 )
244 );
245 }
246
247 registerBlockType('blockenberg/regex-tester', {
248 edit: Editor,
249 save: function(props) {
250 var a = props.attributes;
251 return el('div', useBlockProps.save(),
252 el('div', { className: 'bkbg-rt-app', 'data-opts': JSON.stringify(a) })
253 );
254 },
255 deprecated: [{
256 attributes: v1Attributes,
257 save: function(props) {
258 var a = props.attributes;
259 return el('div', useBlockProps.save(),
260 el('div', { className: 'bkbg-rt-app', 'data-opts': JSON.stringify(a) })
261 );
262 }
263 }]
264 });
265 }() );
266