chore: Update everything
This commit is contained in:
+251
@@ -0,0 +1,251 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Text Corrector App</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsdiff/5.1.0/diff.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: "JetBrains Mono", Menlo, Consolas, monospace;
|
||||
font-optical-sizing: auto;
|
||||
font-size: 16px;
|
||||
padding: 2rem;
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
details {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
summary > h2 {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 0.75rem 1.5rem;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background-color: #222;
|
||||
color: #f9f9f9;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
/* Minimal styling for diff readability */
|
||||
#diffOutput ins {
|
||||
background-color: #d4ffd4;
|
||||
text-decoration: none;
|
||||
color: #22863a;
|
||||
}
|
||||
#diffOutput del {
|
||||
background-color: #ffd4d4;
|
||||
text-decoration: none;
|
||||
color: #cb2431;
|
||||
}
|
||||
.text-container {
|
||||
border: 1px solid #eee;
|
||||
margin-bottom: 1rem;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
#loadingMessage,
|
||||
#errorMessage {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<details>
|
||||
<summary><h2>Original Text</h2></summary>
|
||||
<div id="originalText" class="text-container"></div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div id="loadingMessage">Loading suggestion...</div>
|
||||
<div id="errorMessage" style="color: red; display: none"></div>
|
||||
|
||||
<div id="suggestionArea" style="display: none">
|
||||
<div>
|
||||
<h2>Suggestion (Diff View):</h2>
|
||||
<div id="diffOutput" class="text-container"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<details>
|
||||
<summary><h2>Suggested Text (Clean)</h2></summary>
|
||||
<div id="cleanSuggestionOutput" class="text-container"></div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<button id="acceptButton" disabled>Accept</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// DOM Elements
|
||||
const originalTextEl = document.getElementById("originalText");
|
||||
const loadingMessageEl = document.getElementById("loadingMessage");
|
||||
const errorMessageEl = document.getElementById("errorMessage");
|
||||
const suggestionAreaEl = document.getElementById("suggestionArea");
|
||||
const diffOutputEl = document.getElementById("diffOutput");
|
||||
const cleanSuggestionOutputEl = document.getElementById("cleanSuggestionOutput");
|
||||
const acceptButtonEl = document.getElementById("acceptButton");
|
||||
|
||||
let currentSuggestedText = null;
|
||||
|
||||
async function getChatGPTSuggestion(textToReview, apiKey) {
|
||||
// System prompt: Instructions for the AI model
|
||||
const systemPrompt = `You are an English language assistant. Your task is to help a user who is learning English.
|
||||
When presented with their text, please:
|
||||
1. Identify and correct grammatical errors. Pay specific attention to:
|
||||
- Missing or incorrect articles (a, an, the).
|
||||
- Incorrect preposition usage.
|
||||
- Errors in subject-verb agreement.
|
||||
- Past tense and past perfect tense mistakes.
|
||||
- Awkward or unnatural phrasing.
|
||||
2. Rephrase sentences to be simpler, clearer, and more natural, while preserving the original meaning.
|
||||
3. Preserve the original formatting (new lines, punctuation, etc.) as much as possible, unless a change is necessary for clarity or correctness.
|
||||
4. Provide ONLY the fully revised text. Do not include any explanations, apologies, preambles, or surrounding quotes like """ or \`\`\`. Just the corrected and improved plain text.
|
||||
5. If the text is already grammatically perfect and clearly phrased according to these instructions, return the original text without any changes.`;
|
||||
|
||||
try {
|
||||
const response = await fetch("https://api.openai.com/v1/chat/completions", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
// Assuming window.env.OPENAI_MODEL is available as in your snippet
|
||||
// If not, replace with a hardcoded model or pass it as an argument
|
||||
model: window.env && window.env.OPENAI_MODEL ? window.env.OPENAI_MODEL : "gpt-5.1-nano",
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: systemPrompt,
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: textToReview,
|
||||
},
|
||||
],
|
||||
temperature: 0.8,
|
||||
max_tokens: Math.max(250, textToReview.length * 2 + 50),
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
console.error("ChatGPT API Error:", errorData);
|
||||
return { error: `API Error: ${errorData.error?.message || response.statusText}` };
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (data.choices && data.choices.length > 0 && data.choices[0].message) {
|
||||
return { suggestion: data.choices[0].message.content.trim() };
|
||||
} else {
|
||||
console.error("ChatGPT API Error: No choices in response", data);
|
||||
return { error: "No suggestion received from API (empty response)." };
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching ChatGPT suggestion:", error);
|
||||
return { error: `Network/Request Error: ${error.message}` };
|
||||
}
|
||||
}
|
||||
|
||||
function displayDiff(original, revised, diffContainer) {
|
||||
if (typeof Diff === "undefined" || !Diff.diffWordsWithSpace) {
|
||||
diffContainer.textContent = "jsdiff library not loaded or diffWordsWithSpace not working.";
|
||||
console.error("jsdiff (Diff.diffWordsWithSpace) is not available.");
|
||||
return;
|
||||
}
|
||||
const diffs = Diff.diffWordsWithSpace(original, revised, { ignoreCase: true, ignoreWhitespace: true });
|
||||
const fragment = document.createDocumentFragment();
|
||||
diffs.forEach(function (part) {
|
||||
const textNode = document.createTextNode(part.value);
|
||||
if (part.added) {
|
||||
const ins = document.createElement("ins");
|
||||
ins.appendChild(textNode);
|
||||
fragment.appendChild(ins);
|
||||
} else if (part.removed) {
|
||||
const del = document.createElement("del");
|
||||
del.appendChild(textNode);
|
||||
fragment.appendChild(del);
|
||||
} else {
|
||||
fragment.appendChild(textNode);
|
||||
}
|
||||
});
|
||||
diffContainer.innerHTML = "";
|
||||
diffContainer.appendChild(fragment);
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
loadingMessageEl.style.display = "none";
|
||||
errorMessageEl.textContent = message;
|
||||
errorMessageEl.style.display = "block";
|
||||
suggestionAreaEl.style.display = "none";
|
||||
}
|
||||
|
||||
async function initializeApp() {
|
||||
if (typeof window.env.USER_INPUT === "undefined" || window.env.USER_INPUT === null) {
|
||||
showError("Error: window.USER_INPUT is not defined. Please set it before loading the app.");
|
||||
return;
|
||||
}
|
||||
if (typeof window.env.OPENAI_TOKEN === "undefined" || !window.env.OPENAI_TOKEN) {
|
||||
showError("Error: window.OPENAI_TOKEN is not defined. Please set your OpenAI API key.");
|
||||
return;
|
||||
}
|
||||
if (typeof Diff === "undefined") {
|
||||
showError("Error: jsdiff library could not be loaded. Check your internet connection or the CDN link.");
|
||||
return;
|
||||
}
|
||||
|
||||
const originalText = window.env.USER_INPUT;
|
||||
originalTextEl.textContent = originalText;
|
||||
|
||||
const result = await getChatGPTSuggestion(originalText, window.env.OPENAI_TOKEN);
|
||||
|
||||
loadingMessageEl.style.display = "none";
|
||||
|
||||
if (result.error) {
|
||||
showError(result.error);
|
||||
} else if (result.suggestion) {
|
||||
currentSuggestedText = result.suggestion;
|
||||
suggestionAreaEl.style.display = "block";
|
||||
displayDiff(originalText, currentSuggestedText, diffOutputEl);
|
||||
cleanSuggestionOutputEl.textContent = currentSuggestedText;
|
||||
acceptButtonEl.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
acceptButtonEl.addEventListener("click", () => {
|
||||
if (currentSuggestedText !== null) {
|
||||
if (window.app && typeof window.app.finish === "function") {
|
||||
window.app.finish(currentSuggestedText);
|
||||
// Optionally, provide feedback or close the "app" view
|
||||
acceptButtonEl.textContent = "Accepted!";
|
||||
acceptButtonEl.disabled = true;
|
||||
} else {
|
||||
alert("Error: window.app.finish is not defined. Cannot complete action.");
|
||||
console.error("window.app.finish is not defined.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize the app when the DOM is ready
|
||||
document.addEventListener("DOMContentLoaded", initializeApp);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user