Merge pull request #840 from tscburak/main

Allow Users to Edit Prompt Variables via Input Fields
This commit is contained in:
Fatih Kadir Akın 2025-02-12 00:00:30 +03:00 committed by GitHub
commit 3682225a5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 322 additions and 87 deletions

View File

@ -2658,6 +2658,23 @@ Contributed by: [@awesomesolution](https://github.com/awesomesolution)
> challenges to resolve complex issues and scaling the application with zero
> issues and high performance of application in low or no network as well.
## Act as Devops Engineer
Contributed by: [@tscburak](https://github.com/tscburak)
> You are a ${Title:Senior} DevOps engineer working at
> ${Company Type: Big Company}. Your role is to provide scalable, efficient, and
> automated solutions for software deployment, infrastructure management, and CI/CD
> pipelines. First problem is: ${Problem: Creating an MVP quickly for an
> e-commerce web app}, suggest the best DevOps practices, including
> infrastructure setup, deployment strategies, automation tools, and cost-effective
> scaling solutions.
## Contributors 😍
Many thanks to these AI whisperers:

View File

@ -1347,6 +1347,59 @@
font-size: 0.9rem;
}
}
/* Variable Input Field Styles */
.variable-container {
margin-bottom: 24px;
padding: 16px;
background: rgba(16, 185, 129, 0.05);
border-radius: 8px;
border: 1px solid var(--accent-color);
}
.variable-form {
display: grid;
gap: 12px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.variable-input-wrapper {
display: flex;
flex-direction: column;
gap: 4px;
}
.variable-input-wrapper label {
font-size: 0.8rem;
color: var(--accent-color);
font-weight: 500;
}
.variable-input {
padding: 8px;
border: 1px solid #e1e4e8;
border-radius: 4px;
font-size: 0.9rem;
background: var(--bg-color-light);
color: var(--text-color-light);
transition: all 0.2s ease;
}
.dark-mode .variable-input {
background: var(--bg-color-dark);
color: var(--text-color-dark);
border-color: #2d2d2d;
}
.variable-input:focus {
outline: none;
border-color: var(--accent-color);
box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.1);
}
.modal-content {
white-space: pre-wrap;
}
</style>
{% include head-custom.html %}
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6945602608405209" crossorigin="anonymous"></script>
@ -1423,13 +1476,13 @@
</div>
<div class="main-content">
<div class="container-lg markdown-body">
{{ content }}
{{ content }}
{% if site.github.private != true and site.github.license %}
<div class="footer border-top border-gray-light mt-5 pt-3 text-right text-gray">
<div class="footer border-top border-gray-light mt-5 pt-3 text-right text-gray">
Awesome ChatGPT Prompts is open source. {% github_edit_link "Improve this page" %}.
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>

View File

@ -210,3 +210,4 @@ act,prompt,for_devs
"Virtual Event Planner","I want you to act as a virtual event planner, responsible for organizing and executing online conferences, workshops, and meetings. Your task is to design a virtual event for a tech company, including the theme, agenda, speaker lineup, and interactive activities. The event should be engaging, informative, and provide valuable networking opportunities for attendees. Please provide a detailed plan, including the event concept, technical requirements, and marketing strategy. Ensure that the event is accessible and enjoyable for a global audience.",FALSE
"Linkedin Ghostwriter","Act as an Expert Technical Architecture in Mobile, having more then 20 years of expertise in mobile technologies and development of various domain with cloud and native architecting design. Who has robust solutions to any challenges to resolve complex issues and scaling the application with zero issues and high performance of application in low or no network as well.",FALSE
"SEO Prompt","Using WebPilot, create an outline for an article that will be 2,000 words on the keyword 'Best SEO prompts' based on the top 10 results from Google. Include every relevant heading possible. Keep the keyword density of the headings high. For each section of the outline, include the word count. Include FAQs section in the outline too, based on people also ask section from Google for the keyword. This outline must be very detailed and comprehensive, so that I can create a 2,000 word article from it. Generate a long list of LSI and NLP keywords related to my keyword. Also include any other words related to the keyword. Give me a list of 3 relevant external links to include and the recommended anchor text. Make sure they're not competing articles. Split the outline into part 1 and part 2.",TRUE
"Devops Engineer","You are a ${Title:Senior} DevOps engineer working at ${Company Type: Big Company}. Your role is to provide scalable, efficient, and automated solutions for software deployment, infrastructure management, and CI/CD pipelines. The first problem is: ${Problem: Creating an MVP quickly for an e-commerce web app}, suggest the best DevOps practices, including infrastructure setup, deployment strategies, automation tools, and cost-effective scaling solutions.",TRUE
1 act prompt for_devs
210 Virtual Event Planner I want you to act as a virtual event planner, responsible for organizing and executing online conferences, workshops, and meetings. Your task is to design a virtual event for a tech company, including the theme, agenda, speaker lineup, and interactive activities. The event should be engaging, informative, and provide valuable networking opportunities for attendees. Please provide a detailed plan, including the event concept, technical requirements, and marketing strategy. Ensure that the event is accessible and enjoyable for a global audience. FALSE
211 Linkedin Ghostwriter Act as an Expert Technical Architecture in Mobile, having more then 20 years of expertise in mobile technologies and development of various domain with cloud and native architecting design. Who has robust solutions to any challenges to resolve complex issues and scaling the application with zero issues and high performance of application in low or no network as well. FALSE
212 SEO Prompt Using WebPilot, create an outline for an article that will be 2,000 words on the keyword 'Best SEO prompts' based on the top 10 results from Google. Include every relevant heading possible. Keep the keyword density of the headings high. For each section of the outline, include the word count. Include FAQs section in the outline too, based on people also ask section from Google for the keyword. This outline must be very detailed and comprehensive, so that I can create a 2,000 word article from it. Generate a long list of LSI and NLP keywords related to my keyword. Also include any other words related to the keyword. Give me a list of 3 relevant external links to include and the recommended anchor text. Make sure they're not competing articles. Split the outline into part 1 and part 2. TRUE
213 Devops Engineer You are a ${Title:Senior} DevOps engineer working at ${Company Type: Big Company}. Your role is to provide scalable, efficient, and automated solutions for software deployment, infrastructure management, and CI/CD pipelines. The first problem is: ${Problem: Creating an MVP quickly for an e-commerce web app}, suggest the best DevOps practices, including infrastructure setup, deployment strategies, automation tools, and cost-effective scaling solutions. TRUE

330
script.js
View File

@ -13,6 +13,95 @@ function toggleDarkMode() {
moonIcon.style.display = isDarkMode ? "block" : "none";
}
// Add these new functions at the top
function extractVariables(text) {
const regex = /\${([^}]+)}/g;
const variables = [];
let match;
while ((match = regex.exec(text)) !== null) {
const [variable, defaultValue] = match[1].split(":").map((s) => s.trim());
variables.push({ name: variable, default: defaultValue || "" });
}
return [...new Set(variables.map((v) => JSON.stringify(v)))].map((v) =>
JSON.parse(v)
); // Remove duplicates
}
function createVariableInputs(variables, container) {
const form = document.createElement("div");
form.className = "variable-form";
variables.forEach((variable) => {
const wrapper = document.createElement("div");
wrapper.className = "variable-input-wrapper";
const label = document.createElement("label");
label.textContent = variable.name;
label.style.fontWeight = "600";
const input = document.createElement("input");
input.type = "text";
input.className = "variable-input";
input.placeholder = variable.default || `Enter ${variable.name}`;
input.dataset.variable = variable.name;
input.dataset.default = variable.default || "";
wrapper.appendChild(label);
wrapper.appendChild(input);
form.appendChild(wrapper);
});
container.appendChild(form);
return form;
}
// Function to update the prompt preview with user input or default values
function updatePromptPreview(promptText, form) {
const variables = extractVariables(promptText);
if (variables.length === 0) {
return promptText; // Return original text if no variables found
}
let previewText = promptText;
// Replace variables with their default values without editting (for prompt cards, copy buttons, chat)
if (!form) {
variables.forEach(variable => {
const pattern = new RegExp(`\\$\{${variable.name}[^}]*\}`, 'g');
const replacement = variable.default || `<b>${variable.name}</b>`;
previewText = previewText.replace(pattern, replacement);
});
}
// Replace variables according to the user inputs.
else {
const inputs = form.querySelectorAll(".variable-input");
inputs.forEach((input) => {
const value = input.value.trim();
const variable = input.dataset.variable;
const defaultValue = input.dataset.default;
const pattern = new RegExp(`\\$\{${variable}[^}]*\}`, 'g');
let replacement;
if (value) {
// User entered value
replacement = value;
} else if (defaultValue) {
// Show default value with highlight
replacement = defaultValue;
} else {
// No value or default, show variable name
replacement = variable;
}
replacement = `<b>${replacement}</b>`;
previewText = previewText.replace(pattern, replacement);
});
}
return previewText;
}
// Initialize everything after DOM loads
document.addEventListener("DOMContentLoaded", () => {
// Initialize dev mode
@ -127,11 +216,12 @@ async function initializeSearch() {
const searchTerm = e.target.value.toLowerCase();
const filteredPrompts = prompts.filter((prompt) => {
const matchesSearch = prompt.act.toLowerCase().includes(searchTerm) ||
const matchesSearch =
prompt.act.toLowerCase().includes(searchTerm) ||
prompt.prompt.toLowerCase().includes(searchTerm);
return isDevMode
? (matchesSearch && prompt.for_devs === true)
? matchesSearch && prompt.for_devs === true
: matchesSearch;
});
@ -165,29 +255,32 @@ function updatePromptCount(filteredCount, totalCount) {
function parseCSV(csv) {
const lines = csv.split("\n");
const headers = lines[0].split(",").map((header) =>
header.replace(/"/g, "").trim()
);
const headers = lines[0]
.split(",")
.map((header) => header.replace(/"/g, "").trim());
return lines.slice(1).map((line) => {
const values = line.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g) || [];
const entry = {};
return lines
.slice(1)
.map((line) => {
const values = line.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g) || [];
const entry = {};
headers.forEach((header, index) => {
let value = values[index] ? values[index].replace(/"/g, "").trim() : "";
// Remove backticks from the act/title
if (header === "act") {
value = value.replace(/`/g, "");
}
// Convert 'TRUE'/'FALSE' strings to boolean for for_devs
if (header === "for_devs") {
value = value.toUpperCase() === "TRUE";
}
entry[header] = value;
});
headers.forEach((header, index) => {
let value = values[index] ? values[index].replace(/"/g, "").trim() : "";
// Remove backticks from the act/title
if (header === "act") {
value = value.replace(/`/g, "");
}
// Convert 'TRUE'/'FALSE' strings to boolean for for_devs
if (header === "for_devs") {
value = value.toUpperCase() === "TRUE";
}
entry[header] = value;
});
return entry;
}).filter((entry) => entry.act && entry.prompt);
return entry;
})
.filter((entry) => entry.act && entry.prompt);
}
function displaySearchResults(results) {
@ -231,8 +324,9 @@ function displaySearchResults(results) {
// Find the prompt card with matching title
const cards = document.querySelectorAll(".prompt-card");
const targetCard = Array.from(cards).find((card) => {
const cardTitle = card.querySelector(".prompt-title").textContent
.replace(/\s+/g, " ") // Normalize whitespace
const cardTitle = card
.querySelector(".prompt-title")
.textContent.replace(/\s+/g, " ") // Normalize whitespace
.replace(/[\n\r]/g, "") // Remove newlines
.trim();
@ -241,8 +335,10 @@ function displaySearchResults(results) {
.replace(/[\n\r]/g, "") // Remove newlines
.trim();
return cardTitle.toLowerCase().includes(searchTitle.toLowerCase()) ||
searchTitle.toLowerCase().includes(cardTitle.toLowerCase());
return (
cardTitle.toLowerCase().includes(searchTitle.toLowerCase()) ||
searchTitle.toLowerCase().includes(cardTitle.toLowerCase())
);
});
if (targetCard) {
@ -262,8 +358,8 @@ function displaySearchResults(results) {
if (isMobile) {
// On mobile, scroll the window
const cardRect = targetCard.getBoundingClientRect();
const scrollTop = window.pageYOffset + cardRect.top - headerHeight -
20;
const scrollTop =
window.pageYOffset + cardRect.top - headerHeight - 20;
window.scrollTo({
top: scrollTop,
@ -273,8 +369,8 @@ function displaySearchResults(results) {
// On desktop, scroll the main-content container
const mainContent = document.querySelector(".main-content");
const cardRect = targetCard.getBoundingClientRect();
const scrollTop = mainContent.scrollTop + cardRect.top -
headerHeight - 20;
const scrollTop =
mainContent.scrollTop + cardRect.top - headerHeight - 20;
mainContent.scrollTo({
top: scrollTop,
@ -315,12 +411,13 @@ function filterPrompts() {
.then((csvText) => {
const prompts = parseCSV(csvText);
const filteredPrompts = prompts.filter((prompt) => {
const matchesSearch = !searchTerm ||
const matchesSearch =
!searchTerm ||
prompt.act.toLowerCase().includes(searchTerm) ||
prompt.prompt.toLowerCase().includes(searchTerm);
return isDevMode
? (matchesSearch && prompt.for_devs === true)
? matchesSearch && prompt.for_devs === true
: matchesSearch;
});
@ -329,7 +426,7 @@ function filterPrompts() {
filteredPrompts.length,
isDevMode
? prompts.filter((p) => p.for_devs === true).length
: prompts.length,
: prompts.length
);
displaySearchResults(filteredPrompts);
@ -337,23 +434,29 @@ function filterPrompts() {
const promptsGrid = document.querySelector(".prompts-grid");
if (promptsGrid) {
const cards = promptsGrid.querySelectorAll(
".prompt-card:not(.contribute-card)",
".prompt-card:not(.contribute-card)"
);
cards.forEach((card) => {
const title = card.querySelector(".prompt-title").textContent.trim();
const matchingPrompt = prompts.find((p) => {
const pTitle = p.act.replace(/\s+/g, " ").replace(/[\n\r]/g, "")
const pTitle = p.act
.replace(/\s+/g, " ")
.replace(/[\n\r]/g, "")
.trim();
const cardTitle = title.replace(/\s+/g, " ").replace(/[\n\r]/g, "")
const cardTitle = title
.replace(/\s+/g, " ")
.replace(/[\n\r]/g, "")
.trim();
return pTitle.toLowerCase() === cardTitle.toLowerCase() ||
return (
pTitle.toLowerCase() === cardTitle.toLowerCase() ||
pTitle.toLowerCase().includes(cardTitle.toLowerCase()) ||
cardTitle.toLowerCase().includes(pTitle.toLowerCase());
cardTitle.toLowerCase().includes(pTitle.toLowerCase())
);
});
// Show card if not in dev mode or if it's a dev prompt in dev mode
card.style.display =
(!isDevMode || (matchingPrompt && matchingPrompt.for_devs === true))
!isDevMode || (matchingPrompt && matchingPrompt.for_devs === true)
? ""
: "none";
});
@ -396,23 +499,29 @@ function createPromptCards() {
const isDevMode = document.getElementById("devModeToggle").checked;
const promptElements = document.querySelectorAll(
"h2[id^=act] + p + blockquote",
"h2[id^=act] + p + blockquote"
);
promptElements.forEach((blockquote) => {
const title = blockquote.previousElementSibling.previousElementSibling
.textContent.trim();
const title =
blockquote.previousElementSibling.previousElementSibling.textContent.trim();
const content = blockquote.textContent.trim();
// Find matching prompt in CSV
const matchingPrompt = prompts.find((p) => {
const csvTitle = p.act.replace(/\s+/g, " ").replace(/[\n\r]/g, "")
const csvTitle = p.act
.replace(/\s+/g, " ")
.replace(/[\n\r]/g, "")
.trim();
const elementTitle = title.replace(/\s+/g, " ").replace(/[\n\r]/g, "")
const elementTitle = title
.replace(/\s+/g, " ")
.replace(/[\n\r]/g, "")
.trim();
return csvTitle.toLowerCase() === elementTitle.toLowerCase() ||
return (
csvTitle.toLowerCase() === elementTitle.toLowerCase() ||
csvTitle.toLowerCase().includes(elementTitle.toLowerCase()) ||
elementTitle.toLowerCase().includes(csvTitle.toLowerCase());
elementTitle.toLowerCase().includes(csvTitle.toLowerCase())
);
});
// Extract contributor from the paragraph element
@ -457,9 +566,9 @@ function createPromptCards() {
<div class="prompt-title">
${title}
<div class="action-buttons">
<button class="chat-button" title="Open in AI Chat" onclick="openInChat(this, '${
encodeURIComponent(content.trim())
}')">
<button class="chat-button" title="Open in AI Chat" onclick="openInChat(this, '${encodeURIComponent(
updatePromptPreview(content.trim())
)}')">
<svg class="chat-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
@ -468,9 +577,9 @@ function createPromptCards() {
<line x1="12" y1="19" x2="20" y2="19"></line>
</svg>
</button>
<button class="copy-button" title="Copy prompt" onclick="copyPrompt(this, '${
encodeURIComponent(content.trim())
}')">
<button class="copy-button" title="Copy prompt" onclick="copyPrompt(this, '${encodeURIComponent(
updatePromptPreview(content.trim())
)}')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
<rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
@ -478,7 +587,7 @@ function createPromptCards() {
</button>
</div>
</div>
<p class="prompt-content">${content}</p>
<p class="prompt-content">${updatePromptPreview(content)}</p>
<a href="https://github.com/${contributor}" class="contributor-badge" target="_blank" rel="noopener">@${contributor}</a>
`;
@ -496,7 +605,7 @@ function createPromptCards() {
copyButton.addEventListener("click", async (e) => {
e.stopPropagation();
try {
await navigator.clipboard.writeText(content);
await navigator.clipboard.writeText(updatePromptPreview(content));
copyButton.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
@ -596,6 +705,7 @@ function createModal() {
initializeModalListeners();
}
// Modify the existing showModal function
function showModal(title, content) {
let modalOverlay = document.getElementById("modalOverlay");
if (!modalOverlay) {
@ -605,22 +715,53 @@ function showModal(title, content) {
const modalTitle = modalOverlay.querySelector(".modal-title");
const modalContent = modalOverlay.querySelector(".modal-content");
// Extract variables from content
const variables = extractVariables(content);
// Create variable inputs container if variables exist
if (variables.length > 0) {
const variableContainer = document.createElement("div");
variableContainer.className = "variable-container";
const form = createVariableInputs(variables, variableContainer);
// Initialize the modal content with updated prompt preview if variables exist
const previewText = updatePromptPreview(content, form);
modalContent.innerHTML = previewText;
// Add event listeners for real-time updates
form.addEventListener("input", () => {
const previewText = updatePromptPreview(content, form);
modalContent.innerHTML = previewText;
// Update chat button data
const modalChatButton = modalOverlay.querySelector(".modal-chat-button");
if (modalChatButton) {
modalChatButton.dataset.content = previewText;
}
});
// Insert variable container before content
modalContent.parentElement.insertBefore(variableContainer, modalContent);
} else {
modalTitle.textContent = title;
modalContent.textContent = content;
}
const modalCopyButton = modalOverlay.querySelector(".modal-copy-button");
const modalContributor = modalOverlay.querySelector(".modal-contributor");
const modalChatButton = modalOverlay.querySelector(".modal-chat-button");
if (!modalTitle || !modalContent) return;
modalTitle.textContent = title;
modalContent.textContent = content;
// Update chat button text with platform name and handle visibility
const platform = document.querySelector(".platform-tag.active");
const isDevMode = document.getElementById("devModeToggle").checked;
if (platform) {
const shouldHideChat = ["gemini", "llama"].includes(
platform.dataset.platform,
platform.dataset.platform
);
modalChatButton.style.display = shouldHideChat ? "none" : "flex";
@ -635,13 +776,13 @@ function showModal(title, content) {
modalChatButton.innerHTML = `
<svg class="chat-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: ${
isDevMode ? "none" : "block"
}">
isDevMode ? "none" : "block"
}">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
<svg class="terminal-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: ${
isDevMode ? "block" : "none"
}">
isDevMode ? "block" : "none"
}">
<polyline points="4 17 10 11 4 5"></polyline>
<line x1="12" y1="19" x2="20" y2="19"></line>
</svg>
@ -651,27 +792,26 @@ function showModal(title, content) {
}
// Store content for chat button
modalChatButton.dataset.content = content;
modalChatButton.dataset.content = modalContent.textContent;
// Find the contributor for this prompt
const promptCard = Array.from(document.querySelectorAll(".prompt-card")).find(
(card) =>
card.querySelector(".prompt-title").textContent.trim() === title.trim(),
card.querySelector(".prompt-title").textContent.trim() === title.trim()
);
if (promptCard) {
const contributorBadge = promptCard.querySelector(".contributor-badge");
if (contributorBadge) {
modalContributor.href = contributorBadge.href;
modalContributor.textContent =
`Contributed by ${contributorBadge.textContent}`;
modalContributor.textContent = `Contributed by ${contributorBadge.textContent}`;
}
}
// Add copy functionality
modalCopyButton.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(content);
await navigator.clipboard.writeText(modalContent.textContent);
modalCopyButton.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
@ -705,22 +845,22 @@ function hideModal() {
modalOverlay.remove();
}
let selectedPlatform = localStorage.getItem("selected-platform") ||
"github-copilot"; // Get from localStorage or default to github
let selectedPlatform =
localStorage.getItem("selected-platform") || "github-copilot"; // Get from localStorage or default to github
// Platform toggle functionality
document.querySelectorAll(".platform-tag").forEach((button) => {
button.addEventListener("click", () => {
document.querySelectorAll(".platform-tag").forEach((btn) =>
btn.classList.remove("active")
);
document
.querySelectorAll(".platform-tag")
.forEach((btn) => btn.classList.remove("active"));
button.classList.add("active");
selectedPlatform = button.dataset.platform;
localStorage.setItem("selected-platform", selectedPlatform);
// Hide/show chat buttons based on platform
const chatButtons = document.querySelectorAll(
".chat-button, .modal-chat-button",
".chat-button, .modal-chat-button"
);
const shouldHideChat = ["gemini", "llama"].includes(selectedPlatform);
chatButtons.forEach((btn) => {
@ -776,15 +916,39 @@ function openInChat(button, encodedPrompt) {
// Existing copy function
async function copyPrompt(button, encodedPrompt) {
const promptText = decodeURIComponent(encodedPrompt);
let promptText = decodeURIComponent(encodedPrompt);
// If there's a modal open, use the current state of variables
const modalContent = document.querySelector(".modal-content");
if (modalContent) {
// Get all variable inputs
const form = document.querySelector(".variable-form");
if (form) {
const inputs = form.querySelectorAll(".variable-input");
inputs.forEach((input) => {
const value = input.value.trim();
const variable = input.dataset.variable;
const defaultValue = input.dataset.default;
const pattern = new RegExp(`\\$\{${variable}[^}]*\}`, "g");
// Use value or default value
const replacement = value || defaultValue || variable;
promptText = promptText.replace(pattern, replacement);
});
}
}
try {
await navigator.clipboard.writeText(promptText);
await navigator.clipboard.writeText(updatePromptPreview(promptText));
const originalHTML = button.innerHTML;
button.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17 4 12"/></svg>';
button.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
`;
setTimeout(() => {
button.innerHTML = originalHTML;
}, 1000);
}, 2000);
} catch (err) {
console.error("Failed to copy text: ", err);
}
@ -826,7 +990,7 @@ function hideCopilotSuggestion(switchToCopilot) {
if (switchToCopilot) {
const copilotButton = document.querySelector(
'[data-platform="github-copilot"]',
'[data-platform="github-copilot"]'
);
if (copilotButton) {
copilotButton.click();
@ -844,14 +1008,14 @@ function hideCopilotSuggestion(switchToCopilot) {
// Function to update chat button icons based on dev mode
function updateChatButtonIcons(isDevMode) {
document.querySelectorAll(".chat-button, .modal-chat-button").forEach(
(button) => {
document
.querySelectorAll(".chat-button, .modal-chat-button")
.forEach((button) => {
const chatIcon = button.querySelector(".chat-icon");
const terminalIcon = button.querySelector(".terminal-icon");
if (chatIcon && terminalIcon) {
chatIcon.style.display = isDevMode ? "none" : "block";
terminalIcon.style.display = isDevMode ? "block" : "none";
}
},
);
});
}