Skip to content

Commit 59d4876

Browse files
committed
tool for replacing
1 parent c710f05 commit 59d4876

1 file changed

Lines changed: 370 additions & 0 deletions

File tree

wordpress-pattern-replacer.html

Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>WordPress Pattern Replacer</title>
7+
<style>
8+
body {
9+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
10+
max-width: 1200px;
11+
margin: 0 auto;
12+
padding: 20px;
13+
background-color: #f5f5f5;
14+
}
15+
h1 {
16+
color: #0073aa;
17+
text-align: center;
18+
}
19+
.container {
20+
display: flex;
21+
gap: 20px;
22+
margin-top: 20px;
23+
}
24+
.col {
25+
flex: 1;
26+
background-color: white;
27+
border-radius: 8px;
28+
padding: 20px;
29+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
30+
}
31+
textarea {
32+
width: 100%;
33+
height: 300px;
34+
padding: 10px;
35+
border: 1px solid #ddd;
36+
border-radius: 4px;
37+
font-family: monospace;
38+
resize: vertical;
39+
}
40+
button {
41+
background-color: #0073aa;
42+
color: white;
43+
border: none;
44+
padding: 10px 15px;
45+
border-radius: 4px;
46+
cursor: pointer;
47+
margin-top: 10px;
48+
font-size: 16px;
49+
}
50+
button:hover {
51+
background-color: #005177;
52+
}
53+
.pattern-container {
54+
margin-top: 20px;
55+
border-top: 1px solid #ddd;
56+
padding-top: 20px;
57+
}
58+
.pattern-row {
59+
display: flex;
60+
gap: 10px;
61+
margin-bottom: 10px;
62+
}
63+
.pattern-row button {
64+
padding: 5px 10px;
65+
margin-top: 0;
66+
}
67+
h3 {
68+
margin-top: 0;
69+
}
70+
.header-with-button {
71+
display: flex;
72+
justify-content: space-between;
73+
align-items: center;
74+
}
75+
#patternList {
76+
margin-top: 20px;
77+
max-height: 300px;
78+
overflow-y: auto;
79+
border: 1px solid #eee;
80+
border-radius: 4px;
81+
padding: 10px;
82+
}
83+
.pattern-item {
84+
padding: 10px;
85+
background-color: #f9f9f9;
86+
border-radius: 4px;
87+
margin-bottom: 10px;
88+
font-family: monospace;
89+
font-size: 12px;
90+
white-space: pre-wrap;
91+
}
92+
.pattern-item h4 {
93+
margin-top: 0;
94+
margin-bottom: 5px;
95+
color: #0073aa;
96+
}
97+
.copy-button {
98+
background-color: #4CAF50;
99+
}
100+
.copy-button:hover {
101+
background-color: #388E3C;
102+
}
103+
.info {
104+
margin-top: 20px;
105+
padding: 10px;
106+
background-color: #e7f5fe;
107+
border-left: 4px solid #0073aa;
108+
border-radius: 4px;
109+
}
110+
</style>
111+
</head>
112+
<body>
113+
<h1>WordPress Pattern Replacer</h1>
114+
115+
<div class="container">
116+
<div class="col">
117+
<h3>Input WordPress Content</h3>
118+
<textarea id="inputText" placeholder="Paste your WordPress content here..."></textarea>
119+
<button id="processButton">Process Content</button>
120+
<button id="copyInputButton" class="copy-button">Copy Input</button>
121+
</div>
122+
<div class="col">
123+
<h3>Processed Content</h3>
124+
<textarea id="outputText" placeholder="Processed content will appear here..." readonly></textarea>
125+
<button id="copyOutputButton" class="copy-button">Copy Output</button>
126+
</div>
127+
</div>
128+
129+
<div class="col pattern-container">
130+
<div class="header-with-button">
131+
<h3>Pattern Configuration</h3>
132+
<button id="addPatternButton">Add New Pattern</button>
133+
</div>
134+
135+
<div id="patternList">
136+
<!-- Pattern items will be displayed here -->
137+
</div>
138+
</div>
139+
140+
<div class="info">
141+
<p><strong>How to use:</strong> Paste your WordPress content in the left text area, then click "Process Content" to apply all the defined patterns. You can add, edit, or remove patterns as needed.</p>
142+
<p><strong>Default pattern:</strong> The tool comes pre-configured with a pattern that converts paragraph blocks with images to image blocks.</p>
143+
</div>
144+
145+
<script>
146+
// Initialize pattern mappings
147+
let patternMappings = [
148+
{
149+
name: "Convert Paragraph-Image to Image Block",
150+
findPattern: /<!-- wp:paragraph -->\s*<p>(<img[^>]*>)\s*<\/p>\s*<!-- \/wp:paragraph -->/g,
151+
replacePattern: '<!-- wp:image -->\n<figure class="wp-block-image">$1</figure>\n<!-- /wp:image -->'
152+
},
153+
{
154+
name: "Remove Empty WP Paragraph",
155+
findPattern: /<!-- wp:paragraph -->\n<p><\/p>\n<!-- \/wp:paragraph -->/g,
156+
replacePattern: ''
157+
},
158+
{
159+
name: "Remove Empty WP Paragraph",
160+
findPattern: /<p><\/p>/g,
161+
replacePattern: ''
162+
},
163+
{
164+
name: "Remove Paragraph with whitespace",
165+
findPattern: /<p>\s*<\/p>/g,
166+
replacePattern: ''
167+
},
168+
{
169+
name: "Replace four newlines with one",
170+
findPattern: /\n\n\n\n/g,
171+
replacePattern: '\n'
172+
},
173+
{
174+
name: "Replace three newlines with one",
175+
findPattern: /\n\n\n/g,
176+
replacePattern: '\n'
177+
},
178+
{
179+
name: "Replace two newlines with one",
180+
findPattern: /\n\n/g,
181+
replacePattern: '\n'
182+
}
183+
];
184+
185+
// DOM Elements
186+
const inputText = document.getElementById('inputText');
187+
const outputText = document.getElementById('outputText');
188+
const processButton = document.getElementById('processButton');
189+
const copyInputButton = document.getElementById('copyInputButton');
190+
const copyOutputButton = document.getElementById('copyOutputButton');
191+
const addPatternButton = document.getElementById('addPatternButton');
192+
const patternList = document.getElementById('patternList');
193+
194+
// Process content with all patterns
195+
function processContent() {
196+
let content = inputText.value;
197+
198+
patternMappings.forEach(mapping => {
199+
content = content.replace(mapping.findPattern, mapping.replacePattern);
200+
});
201+
202+
outputText.value = content;
203+
}
204+
205+
// Copy text to clipboard
206+
function copyToClipboard(text, buttonElement) {
207+
navigator.clipboard.writeText(text).then(() => {
208+
const originalText = buttonElement.textContent;
209+
buttonElement.textContent = 'Copied!';
210+
setTimeout(() => {
211+
buttonElement.textContent = originalText;
212+
}, 2000);
213+
}).catch(err => {
214+
console.error('Failed to copy: ', err);
215+
alert('Failed to copy text to clipboard');
216+
});
217+
}
218+
219+
// Render all pattern mappings in the UI
220+
function renderPatternList() {
221+
patternList.innerHTML = '';
222+
223+
if (patternMappings.length === 0) {
224+
patternList.innerHTML = '<p>No patterns defined. Click "Add New Pattern" to create one.</p>';
225+
return;
226+
}
227+
228+
patternMappings.forEach((pattern, index) => {
229+
const patternItem = document.createElement('div');
230+
patternItem.className = 'pattern-item';
231+
232+
patternItem.innerHTML = `
233+
<h4>${pattern.name}</h4>
234+
<strong>Find:</strong> ${escapeHtml(pattern.findPattern.toString())}
235+
<br>
236+
<strong>Replace:</strong> ${escapeHtml(pattern.replacePattern)}
237+
<br>
238+
<button class="edit-button" data-index="${index}">Edit</button>
239+
<button class="delete-button" data-index="${index}">Delete</button>
240+
`;
241+
242+
patternList.appendChild(patternItem);
243+
});
244+
245+
// Add event listeners for edit and delete buttons
246+
document.querySelectorAll('.edit-button').forEach(button => {
247+
button.addEventListener('click', function() {
248+
const index = parseInt(this.dataset.index);
249+
editPattern(index);
250+
});
251+
});
252+
253+
document.querySelectorAll('.delete-button').forEach(button => {
254+
button.addEventListener('click', function() {
255+
const index = parseInt(this.dataset.index);
256+
deletePattern(index);
257+
});
258+
});
259+
}
260+
261+
// Escape HTML for safe display
262+
function escapeHtml(unsafe) {
263+
return unsafe
264+
.replace(/&/g, "&amp;")
265+
.replace(/</g, "&lt;")
266+
.replace(/>/g, "&gt;")
267+
.replace(/"/g, "&quot;")
268+
.replace(/'/g, "&#039;");
269+
}
270+
271+
// Add new pattern
272+
function addNewPattern() {
273+
const name = prompt('Enter a name for this pattern:');
274+
if (!name) return;
275+
276+
const findPatternStr = prompt('Enter the find pattern (as a regular expression):');
277+
if (!findPatternStr) return;
278+
279+
const replacePattern = prompt('Enter the replace pattern:');
280+
if (replacePattern === null) return;
281+
282+
try {
283+
// Extract regex pattern and flags
284+
const regexMatch = findPatternStr.match(/^\/(.*?)\/([gimuy]*)$/);
285+
let findPattern;
286+
287+
if (regexMatch) {
288+
// User entered a regex with slashes and possibly flags
289+
findPattern = new RegExp(regexMatch[1], regexMatch[2]);
290+
} else {
291+
// User entered a simple string or invalid regex
292+
findPattern = new RegExp(findPatternStr, 'g');
293+
}
294+
295+
patternMappings.push({
296+
name,
297+
findPattern,
298+
replacePattern
299+
});
300+
301+
renderPatternList();
302+
} catch (error) {
303+
alert('Invalid regular expression: ' + error.message);
304+
}
305+
}
306+
307+
// Edit existing pattern
308+
function editPattern(index) {
309+
const pattern = patternMappings[index];
310+
311+
const name = prompt('Edit pattern name:', pattern.name);
312+
if (!name) return;
313+
314+
const findPatternStr = prompt('Edit find pattern (as a regular expression):', pattern.findPattern.toString());
315+
if (!findPatternStr) return;
316+
317+
const replacePattern = prompt('Edit replace pattern:', pattern.replacePattern);
318+
if (replacePattern === null) return;
319+
320+
try {
321+
// Extract regex pattern and flags
322+
const regexMatch = findPatternStr.match(/^\/(.*?)\/([gimuy]*)$/);
323+
let findPattern;
324+
325+
if (regexMatch) {
326+
// User entered a regex with slashes and possibly flags
327+
findPattern = new RegExp(regexMatch[1], regexMatch[2]);
328+
} else {
329+
// User entered a simple string or invalid regex
330+
findPattern = new RegExp(findPatternStr, 'g');
331+
}
332+
333+
patternMappings[index] = {
334+
name,
335+
findPattern,
336+
replacePattern
337+
};
338+
339+
renderPatternList();
340+
} catch (error) {
341+
alert('Invalid regular expression: ' + error.message);
342+
}
343+
}
344+
345+
// Delete pattern
346+
function deletePattern(index) {
347+
if (confirm('Are you sure you want to delete this pattern?')) {
348+
patternMappings.splice(index, 1);
349+
renderPatternList();
350+
}
351+
}
352+
353+
// Event Listeners
354+
processButton.addEventListener('click', processContent);
355+
356+
copyInputButton.addEventListener('click', function() {
357+
copyToClipboard(inputText.value, this);
358+
});
359+
360+
copyOutputButton.addEventListener('click', function() {
361+
copyToClipboard(outputText.value, this);
362+
});
363+
364+
addPatternButton.addEventListener('click', addNewPattern);
365+
366+
// Initialize the UI
367+
renderPatternList();
368+
</script>
369+
</body>
370+
</html>

0 commit comments

Comments
 (0)