adobe-ps-scripts-loreal/text_editor.php
DJP 4a192a8c97 Initial commit: Adobe Photoshop API text management scripts
Local and cloud-based workflows for extracting and updating
text layers in PSD files via ExtendScript and Adobe PS API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:46:52 -05:00

278 lines
No EOL
9.6 KiB
PHP

<?php
/**
* Photoshop Text Layer Editor
*
* A simple PHP tool to edit the text content of JSON files exported by ExtractTextWithBreaks.jsx
* Shows only the text parts (original text and updatedText fields) for easy editing.
* Saves the edited version with "-updated" appended to the filename.
*/
// Handle form submissions
$message = '';
$jsonData = null;
$filename = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Check if we're uploading a file
if (isset($_FILES['jsonFile']) && $_FILES['jsonFile']['error'] === UPLOAD_ERR_OK) {
$filename = $_FILES['jsonFile']['name'];
$jsonContent = file_get_contents($_FILES['jsonFile']['tmp_name']);
$jsonData = json_decode($jsonContent, true);
if ($jsonData === null) {
$message = "Error: Invalid JSON file.";
}
}
// Check if we're saving edits
elseif (isset($_POST['saveEdits']) && isset($_POST['jsonData']) && isset($_POST['originalFilename'])) {
$jsonData = json_decode($_POST['jsonData'], true);
$filename = $_POST['originalFilename'];
// Update the text content with the edited values
foreach ($_POST as $key => $value) {
if (preg_match('/^updatedText_(\d+)$/', $key, $matches)) {
$index = $matches[1];
$jsonData['textLayers'][$index]['updatedText'] = $value;
}
}
// Create new filename with "-textonly-updated" suffix
// If filename already ends with -textonly.json, replace with -textonly-updated.json
if (strpos($filename, '-textonly.json') !== false) {
$newFilename = str_replace('-textonly.json', '-textonly-updated.json', $filename);
} else {
// Otherwise, just add -updated before .json
$newFilename = pathinfo($filename, PATHINFO_FILENAME) . '-textonly-updated.json';
}
// Save the updated JSON
$updatedJson = json_encode($jsonData, JSON_PRETTY_PRINT);
header('Content-Type: application/json');
header('Content-Disposition: attachment; filename="' . $newFilename . '"');
echo $updatedJson;
exit;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Photoshop Text Layer Editor</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Montserrat', sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 12px;
line-height: 1.4;
font-size: 14px;
}
h1 {
color: #333;
border-bottom: 1px solid #ddd;
padding-bottom: 8px;
margin-top: 10px;
margin-bottom: 10px;
font-size: 22px;
}
form {
margin: 12px 0;
}
label {
display: block;
margin-bottom: 3px;
font-weight: 600;
}
input[type="file"] {
margin-bottom: 10px;
}
input[type="submit"] {
background-color: #4CAF50;
color: white;
padding: 8px 12px;
border: none;
border-radius: 3px;
cursor: pointer;
font-family: 'Montserrat', sans-serif;
font-weight: 500;
}
input[type="submit"]:hover {
background-color: #45a049;
}
.message {
padding: 8px;
margin: 8px 0;
border-radius: 3px;
font-size: 13px;
}
.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.text-pair {
background-color: #f9f9f9;
padding: 10px;
margin-bottom: 12px;
border-radius: 3px;
border: 1px solid #ddd;
}
.text-pair h3 {
margin-top: 0;
margin-bottom: 5px;
color: #444;
font-size: 14px;
font-weight: 600;
}
textarea {
width: 100%;
min-height: 60px;
padding: 6px;
box-sizing: border-box;
border: 1px solid #ddd;
border-radius: 3px;
resize: vertical;
font-family: 'Montserrat', sans-serif;
font-size: 13px;
}
.original-text {
background-color: #f0f0f0;
padding: 6px;
border-radius: 3px;
border: 1px solid #ddd;
margin-bottom: 6px;
white-space: pre-wrap;
font-size: 13px;
}
.layer-info {
font-size: 12px;
color: #666;
margin-bottom: 4px;
}
.instructions {
background-color: #e7f3fe;
border-left: 4px solid #2196F3;
padding: 8px;
margin-bottom: 12px;
font-size: 13px;
}
.instructions p {
margin: 0 0 4px 0;
}
.instructions ol {
margin: 5px 0;
padding-left: 20px;
}
.instructions li {
margin-bottom: 2px;
}
button.format-button {
margin-top: 4px;
background-color: #f0f0f0;
border: 1px solid #ddd;
border-radius: 3px;
padding: 4px 8px;
cursor: pointer;
font-size: 12px;
font-family: 'Montserrat', sans-serif;
}
button.format-button:hover {
background-color: #e0e0e0;
}
a {
color: #2196F3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>Photoshop Text Layer Editor</h1>
<div class="instructions">
<p><strong>Instructions:</strong></p>
<ol>
<li>Upload a JSON file exported from the ExtractTextWithBreaks.jsx script</li>
<li>Edit the "Updated Text" field for any text layers you want to modify</li>
<li>Click "Save Changes" to download the updated JSON file</li>
<li>Use the updated JSON with the updateTextLayers.jsx script in Photoshop</li>
</ol>
</div>
<?php if (!empty($message)): ?>
<div class="message <?php echo strpos($message, 'Error') === 0 ? 'error' : 'success'; ?>">
<?php echo $message; ?>
</div>
<?php endif; ?>
<?php if ($jsonData === null): ?>
<!-- File Upload Form -->
<form method="post" enctype="multipart/form-data">
<label for="jsonFile">Select a JSON file:</label>
<input type="file" name="jsonFile" id="jsonFile" accept=".json" required>
<input type="submit" value="Upload">
</form>
<?php else: ?>
<!-- Text Editor Form -->
<form method="post">
<input type="hidden" name="saveEdits" value="1">
<input type="hidden" name="jsonData" value="<?php echo htmlspecialchars(json_encode($jsonData)); ?>">
<input type="hidden" name="originalFilename" value="<?php echo htmlspecialchars($filename); ?>">
<?php if (isset($jsonData['textLayers']) && is_array($jsonData['textLayers'])): ?>
<p>Found <?php echo count($jsonData['textLayers']); ?> text layers in the file <strong><?php echo htmlspecialchars($filename); ?></strong>.</p>
<?php foreach ($jsonData['textLayers'] as $index => $layer): ?>
<div class="text-pair">
<div class="layer-info">
<strong>Layer:</strong> <?php echo htmlspecialchars($layer['name']); ?>
<br>
<strong>Path:</strong> <?php echo htmlspecialchars($layer['path']); ?>
</div>
<h3>Original Text:</h3>
<div class="original-text"><?php echo htmlspecialchars($layer['text']); ?></div>
<h3>Updated Text:</h3>
<textarea name="updatedText_<?php echo $index; ?>" rows="4"><?php
echo htmlspecialchars($layer['updatedText']);
?></textarea>
<button type="button" class="format-button" onclick="copyOriginalText(<?php echo $index; ?>)">Copy Original Text</button>
</div>
<?php endforeach; ?>
<input type="submit" value="Save Changes">
<?php else: ?>
<p class="error">No text layers found in the JSON file.</p>
<?php endif; ?>
</form>
<!-- Link to upload another file -->
<p>
<a href="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">Upload another file</a>
</p>
<?php endif; ?>
<script>
function copyOriginalText(index) {
var originalTextElement = document.getElementsByClassName('original-text')[index];
var updatedTextArea = document.getElementsByName('updatedText_' + index)[0];
if (originalTextElement && updatedTextArea) {
updatedTextArea.value = originalTextElement.innerText;
}
}
</script>
</body>
</html>