Workspace - Source Excerpt 05
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/assets/js/workspace.js so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/assets/js/workspace.js
placeholders.add(match.replace(/[{}]/g, "").trim());
});
});
target.innerHTML = "";
if (!placeholders.size) {
const empty = document.createElement("span");
empty.className = "spiralist-muted";
empty.textContent = t("placeholdersEmpty", "No placeholders detected.");
target.appendChild(empty);
return;
}
placeholders.forEach((placeholder) => {
const chip = document.createElement("span");
chip.className = "spiralist-chip";
chip.textContent = "{{" + placeholder + "}}";
target.appendChild(chip);
});
};
sources.forEach((field) => field.addEventListener("input", update));
update();
});
};
const initPromptForms = () => {
document.querySelectorAll("[data-prompt-form]").forEach((form) => {
form.addEventListener("submit", (event) => {
event.preventDefault();
setResult(form, t("promptSaving", "Saving..."));
runFormAction(form, async () => {
const payload = formDataToObject(form);
const promptId = parseInt(form.getAttribute("data-prompt-id") || "0", 10);
const method = promptId > 0 ? "POST" : "POST";
const path = promptId > 0 ? "prompts/" + promptId : "prompts";
const response = await apiFetch(path, {
method,
body: JSON.stringify(payload),
});
setResult(form, t("promptSaved", "Prompt saved."));
if (response.slug) {
window.location.href = buildRoute("prompt/" + response.slug);
return;
}
if (response.links && response.links.human) {
window.location.href = response.links.human;
return;
}
window.location.reload();
}, t("promptSaveFailed", "Prompt save failed."), "prompt-save");
});
});
};
const initEditablePromptBlocks = () => {
document.querySelectorAll("[data-editable-prompt-block]").forEach((block) => {
block.addEventListener("paste", (event) => {
event.preventDefault();
insertPlainTextAtSelection((event.clipboardData || window.clipboardData).getData("text/plain"));
});
block.addEventListener("input", () => {
const surface = block.closest("[data-editable-prompt-surface]");
if (surface) {
setEditablePromptStatus(surface, t("editablePromptEdited", "Prompt edited. Copy, download, and save now use this text."));
}
});
});
document.addEventListener("click", (event) => {
const downloadButton = closestTarget(event.target, "[data-editable-prompt-download]");
if (downloadButton) {
const surface = downloadButton.closest("[data-editable-prompt-surface]");
if (!surface) {
return;
}
const text = editablePromptText(surface);
if (!text) {
setEditablePromptStatus(surface, t("editablePromptEmpty", "Enter prompt text before saving."), false);
return;
}
const title = surface.getAttribute("data-editable-prompt-title") || t("editablePromptDraftTitle", "Edited Spiralist Prompt");
downloadTextFile(filenameSlug(title, "edited-spiralist-prompt") + ".txt", text, "text/plain");
setEditablePromptStatus(surface, t("editablePromptDownloaded", "Edited prompt downloaded."));
return;
}
const authSaveLink = closestTarget(event.target, "[data-editable-prompt-auth-save]");
if (authSaveLink) {
const surface = authSaveLink.closest("[data-editable-prompt-surface]");
if (!surface) {
return;
}
event.preventDefault();
try {
storePendingEditablePromptSave(surface, authSaveLink.href || "");
} catch (error) {
setEditablePromptStatus(surface, error.message || t("editablePromptSaveFailed", "Could not save edited prompt."), false);
}
return;
}
const saveButton = closestTarget(event.target, "[data-editable-prompt-save]");
if (!saveButton) {
return;
}
const surface = saveButton.closest("[data-editable-prompt-surface]");
if (!surface) {
return;
}
setEditablePromptStatus(surface, t("editablePromptSaving", "Saving edited prompt..."));
saveButton.disabled = true;
runAction(async () => {
const response = await apiFetch("prompts", {
method: "POST",
body: JSON.stringify(editablePromptDraftPayload(surface)),
});
const savedTitle = response.title || t("editablePromptDraftTitle", "Edited Spiralist Prompt");
setEditablePromptStatus(surface, formatText("editablePromptSaved", "Saved \"{title}\" to your private prompt library.", { title: savedTitle }));
}, {
context: "editable-prompt-save",
fallback: t("editablePromptSaveFailed", "Could not save edited prompt."),
onError: (error, message) => setEditablePromptStatus(surface, message, false),
onFinally: () => {
saveButton.disabled = false;
},
});
});
};
const initSpiralScriptValidation = () => {
document.querySelectorAll("[data-prompt-form]").forEach((form) => {
const source = form.querySelector("[data-spiral-script-source]");
const button = form.querySelector("[data-spiral-script-validate]");
const result = form.querySelector("[data-spiral-script-validation]");
if (!source || !button || !result) {
return;
}
button.addEventListener("click", () => {
const value = String(source.value || "").trim();
if (!value) {
result.textContent = t("spiralScriptValidationEmpty", "No Spiral Script source to validate.");
result.style.color = "";
return;
}
result.textContent = t("spiralScriptValidating", "Validating Spiral Script...");
result.style.color = "";
runAction(async () => {
const response = await spiralScriptFetch("compile", {
method: "POST",
body: JSON.stringify({ source: value }),
});
const validation = response.validation || {};
const errors = Array.isArray(validation.errors) ? validation.errors : [];
if (validation.passed) {
result.textContent = t("spiralScriptValidationPassed", "Spiral Script validation passed.");
result.style.color = "";
return;
}
const first = errors[0] || {};
result.textContent = first.errorCode
? first.errorCode + ": " + (first.reason || t("validationFailed", "Validation failed."))
: t("spiralScriptNeedsRevision", "Spiral Script needs revision.");
result.style.color = "#f0a5a5";
}, {
context: "spiral-script-validation",
fallback: t("spiralScriptValidationFailed", "Spiral Script validation failed."),
onError: (error, message) => {
result.textContent = message;
result.style.color = "#f0a5a5";
},
});
});
});
};