Fix PHP serialization and add Long Text type to Visual Editor

- Fixed PHP serialization byte length calculation for escaped strings
- Added Long Text type with textarea for multiline strings in StructuredEditor
- Auto-detects strings with newlines and displays them as textarea
- Improvements apply to both SerializeTool and JsonTool visual editors
- Resolves parse errors with quoted strings and multiline content
This commit is contained in:
dwindown
2025-08-21 23:45:46 +07:00
parent 65cc3bc54d
commit 6f5bdf5f0d
2 changed files with 33 additions and 13 deletions

View File

@@ -144,6 +144,7 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
// Try to preserve value when changing types if possible // Try to preserve value when changing types if possible
switch (newType) { switch (newType) {
case 'string': case 'string':
case 'longtext':
current[key] = currentValue === null ? '' : currentValue.toString(); current[key] = currentValue === null ? '' : currentValue.toString();
break; break;
case 'number': case 'number':
@@ -314,17 +315,31 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
</span> </span>
</div> </div>
) : ( ) : (
<input typeof value === 'string' && value.includes('\n') ? (
type="text" <textarea
value={ value={
value === null ? 'null' : value === null ? 'null' :
value === undefined ? '' : value === undefined ? '' :
value.toString() value.toString()
} }
onChange={(e) => updateValue(e.target.value, path)} onChange={(e) => updateValue(e.target.value, path)}
className="flex-1 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 min-w-0" className="flex-1 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 min-w-0 resize-y"
placeholder="Value" placeholder="Long text value"
/> rows={3}
/>
) : (
<input
type="text"
value={
value === null ? 'null' :
value === undefined ? '' :
value.toString()
}
onChange={(e) => updateValue(e.target.value, path)}
className="flex-1 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 min-w-0"
placeholder="Value"
/>
)
) )
) : ( ) : (
<span className="flex-1 text-sm text-gray-600 dark:text-gray-400"> <span className="flex-1 text-sm text-gray-600 dark:text-gray-400">
@@ -337,7 +352,7 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
value={ value={
value === null ? 'null' : value === null ? 'null' :
value === undefined ? 'string' : value === undefined ? 'string' :
typeof value === 'string' ? 'string' : typeof value === 'string' ? (value.includes('\n') ? 'longtext' : 'string') :
typeof value === 'number' ? 'number' : typeof value === 'number' ? 'number' :
typeof value === 'boolean' ? 'boolean' : typeof value === 'boolean' ? 'boolean' :
Array.isArray(value) ? 'array' : 'object' Array.isArray(value) ? 'array' : 'object'
@@ -346,6 +361,7 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
className="px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 min-w-0" className="px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 min-w-0"
> >
<option value="string">String</option> <option value="string">String</option>
<option value="longtext">Long Text</option>
<option value="number">Number</option> <option value="number">Number</option>
<option value="boolean">Boolean</option> <option value="boolean">Boolean</option>
<option value="array">Array</option> <option value="array">Array</option>

View File

@@ -21,7 +21,11 @@ const SerializeTool = () => {
return Number.isInteger(data) ? `i:${data};` : `d:${data};`; return Number.isInteger(data) ? `i:${data};` : `d:${data};`;
} }
if (typeof data === 'string') { if (typeof data === 'string') {
return `s:${data.length}:"${data}";`; // Escape quotes and backslashes in the string first
const escapedData = data.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
// PHP serialize requires UTF-8 byte length of the ESCAPED string
const byteLength = new TextEncoder().encode(escapedData).length;
return `s:${byteLength}:"${escapedData}";`;
} }
if (Array.isArray(data)) { if (Array.isArray(data)) {
let result = `a:${data.length}:{`; let result = `a:${data.length}:{`;