GopalKrushnaMahapatra commited on
Commit
f538f80
·
verified ·
1 Parent(s): 46396f2

Update grammar.html

Browse files
Files changed (1) hide show
  1. grammar.html +84 -258
grammar.html CHANGED
@@ -5,7 +5,7 @@
5
  <title>Grammar Check – TrueWrite Scan</title>
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
  <script src="https://cdn.tailwindcss.com"></script>
8
- <!-- jsPDF (no integrity, to avoid SRI issues locally) -->
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
10
  </head>
11
  <body class="bg-gradient-to-br from-slate-950 via-slate-900 to-indigo-950 text-white min-h-screen flex flex-col">
@@ -177,180 +177,7 @@
177
  </div>
178
 
179
  <!-- ========= Info sections from file 1 ========= -->
180
-
181
- <section class="mt-10 space-y-4">
182
- <h2 class="text-xl md:text-2xl font-semibold">Why choose this tool?</h2>
183
- <p class="text-sm text-slate-300">
184
- Inspired by tools like QuillBot, this page gives you a simple, focused space to check
185
- short pieces of writing quickly before you submit or share them.
186
- </p>
187
-
188
- <div class="grid md:grid-cols-3 gap-5 mt-3">
189
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
190
- <div class="flex items-center gap-3 mb-2">
191
- <div class="w-9 h-9 rounded-full bg-indigo-500/20 flex items-center justify-center">
192
- <span class="text-lg">⚡</span>
193
- </div>
194
- <p class="font-semibold text-sm">Fast one-click review</p>
195
- </div>
196
- <p class="text-xs text-slate-300">
197
- Paste, click, and instantly get a cleaner version of your text without any sign-up
198
- or complicated options.
199
- </p>
200
- </div>
201
-
202
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
203
- <div class="flex items-center gap-3 mb-2">
204
- <div class="w-9 h-9 rounded-full bg-emerald-500/20 flex items-center justify-center">
205
- <span class="text-lg">🎯</span>
206
- </div>
207
- <p class="font-semibold text-sm">Focus on basics that matter</p>
208
- </div>
209
- <p class="text-xs text-slate-300">
210
- Targets the most common issues students face: extra spaces, lowercase “i”,
211
- sentence starts, and missing punctuation.
212
- </p>
213
- </div>
214
-
215
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
216
- <div class="flex items-center gap-3 mb-2">
217
- <div class="w-9 h-9 rounded-full bg-fuchsia-500/20 flex items-center justify-center">
218
- <span class="text-lg">📄</span>
219
- </div>
220
- <p class="font-semibold text-sm">Instant PDF summaries</p>
221
- </div>
222
- <p class="text-xs text-slate-300">
223
- Export a quick PDF report for your records or to attach with your assignment
224
- submissions.
225
- </p>
226
- </div>
227
- </div>
228
- </section>
229
-
230
- <section class="mt-10 space-y-4">
231
- <h2 class="text-xl md:text-2xl font-semibold">Who can use this tool?</h2>
232
- <p class="text-sm text-slate-300">
233
- This grammar checker is designed as a lightweight helper for anyone who wants a final
234
- polish before sending or submitting text.
235
- </p>
236
-
237
- <div class="grid md:grid-cols-3 gap-5 mt-3">
238
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
239
- <div class="flex items-center gap-3 mb-2">
240
- <div class="w-9 h-9 rounded-full bg-sky-500/20 flex items-center justify-center">
241
- <span class="text-lg">👨‍🎓</span>
242
- </div>
243
- <p class="font-semibold text-sm">Students</p>
244
- </div>
245
- <p class="text-xs text-slate-300">
246
- Quickly check lab reports, assignments, mini-projects, and emails to faculty or
247
- supervisors.
248
- </p>
249
- </div>
250
-
251
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
252
- <div class="flex items-center gap-3 mb-2">
253
- <div class="w-9 h-9 rounded-full bg-amber-500/20 flex items-center justify-center">
254
- <span class="text-lg">👩‍🏫</span>
255
- </div>
256
- <p class="font-semibold text-sm">Teachers & mentors</p>
257
- </div>
258
- <p class="text-xs text-slate-300">
259
- Use it as a quick demo in class to show students how common grammar issues can be
260
- auto-detected.
261
- </p>
262
- </div>
263
-
264
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
265
- <div class="flex items-center gap-3 mb-2">
266
- <div class="w-9 h-9 rounded-full bg-rose-500/20 flex items-center justify-center">
267
- <span class="text-lg">💼</span>
268
- </div>
269
- <p class="font-semibold text-sm">Professionals & creators</p>
270
- </div>
271
- <p class="text-xs text-slate-300">
272
- Clean up short posts, descriptions, and emails before sharing them with clients,
273
- teams, or on social media.
274
- </p>
275
- </div>
276
- </div>
277
- </section>
278
-
279
- <!-- How it works (frontend-focused) from file 1 -->
280
- <section class="mt-10 space-y-4">
281
- <h2 class="text-xl md:text-2xl font-semibold">How does this work?</h2>
282
- <p class="text-sm text-slate-300">
283
- Behind the scenes, prefers a neural model (GECToR), then falls back to LanguageTool, and finally to a
284
- lightweight heuristic that do the necessary corrections.
285
- </p>
286
-
287
- <div class="grid md:grid-cols-3 gap-5 mt-3">
288
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
289
- <div class="flex items-center gap-3 mb-2">
290
- <div class="w-9 h-9 rounded-full bg-indigo-500/20 flex items-center justify-center">
291
- <span class="text-lg">1️⃣</span>
292
- </div>
293
- <p class="font-semibold text-sm">Paste & analyse</p>
294
- </div>
295
- <p class="text-xs text-slate-300">
296
- You paste your text (up to ~1000 words). The tool counts words and prepares it for
297
- analysis.
298
- </p>
299
- </div>
300
-
301
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
302
- <div class="flex items-center gap-3 mb-2">
303
- <div class="w-9 h-9 rounded-full bg-emerald-500/20 flex items-center justify-center">
304
- <span class="text-lg">2️⃣</span>
305
- </div>
306
- <p class="font-semibold text-sm">Apply smart rules and models</p>
307
- </div>
308
- <p class="text-xs text-slate-300">
309
- GECToR model rewrites sentences word-by-word, focusing on grammar, agreement, and spelling.
310
- JavaScript rules can fix double spaces, lowercase “i”, sentence capitalization, and
311
- end punctuation. Then the text is sent to a neural grammar model on the server for deeper fixes.
312
- </p>
313
- </div>
314
-
315
- <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
316
- <div class="flex items-center gap-3 mb-2">
317
- <div class="w-9 h-9 rounded-full bg-fuchsia-500/20 flex items-center justify-center">
318
- <span class="text-lg">3️⃣</span>
319
- </div>
320
- <p class="font-semibold text-sm">Review & export</p>
321
- </div>
322
- <p class="text-xs text-slate-300">
323
- You compare the original and corrected text, then optionally export a PDF summary
324
- for future reference.
325
- </p>
326
- </div>
327
- </div>
328
- </section>
329
-
330
- <!-- Reviews slider from file 1 -->
331
- <section class="mt-12">
332
- <h2 class="text-xl md:text-2xl font-semibold mb-3">What users say about this grammar tool</h2>
333
- <div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 md:p-6 relative overflow-hidden">
334
- <div id="reviewCard" class="transition-all duration-500">
335
- <!-- filled by JS -->
336
- </div>
337
-
338
- <div class="flex items-center justify-between mt-4">
339
- <div id="reviewDots" class="flex gap-1.5"></div>
340
- <div class="flex gap-2">
341
- <button id="prevReview"
342
- class="w-8 h-8 rounded-full border border-slate-600 flex items-center justify-center text-xs hover:bg-slate-800">
343
-
344
- </button>
345
- <button id="nextReview"
346
- class="w-8 h-8 rounded-full border border-slate-600 flex items-center justify-center text-xs hover:bg-slate-800">
347
-
348
- </button>
349
- </div>
350
- </div>
351
- </div>
352
- </section>
353
-
354
  </main>
355
 
356
  <!-- Footer -->
@@ -369,7 +196,7 @@
369
  window.location.href = "login.html";
370
  }
371
 
372
- // jsPDF helper (from file 2)
373
  function getJsPDF() {
374
  if (window.jspdf && window.jspdf.jsPDF) return window.jspdf.jsPDF;
375
  if (window.jsPDF) return window.jsPDF;
@@ -434,7 +261,7 @@
434
  }
435
  }
436
 
437
- // Word counting & 1000-word indicator (from file 1)
438
  function countWords(text) {
439
  if (!text || !text.trim()) return 0;
440
  return text.trim().split(/\s+/).length;
@@ -452,7 +279,7 @@
452
 
453
  textarea.addEventListener("input", updateWordCount);
454
 
455
- // Simple local heuristic rules (from file 1)
456
  function applyLocalGrammarRules(rawText) {
457
  let corrections = 0;
458
  let text = rawText || "";
@@ -477,7 +304,7 @@
477
  return { corrected: text, corrections };
478
  }
479
 
480
- // Drag & drop (from file 2)
481
  ["dragenter", "dragover"].forEach(evt => {
482
  dropZone.addEventListener(evt, e => {
483
  e.preventDefault();
@@ -549,7 +376,7 @@
549
  }
550
  };
551
 
552
- // API calls (from file 2)
553
  async function callGrammarText(text) {
554
  const res = await fetch(`${BACKEND_URL}/api/grammar-check`, {
555
  method: "POST",
@@ -577,7 +404,7 @@
577
  return data;
578
  }
579
 
580
- // Main check: file 2 logic + file 1 fallback
581
  checkBtn.onclick = async () => {
582
  const text = textarea.value.trim();
583
  const file = fileInput.files[0];
@@ -639,7 +466,7 @@
639
  statusTiny.textContent = "Done";
640
  } catch (err) {
641
  console.error(err);
642
- // Fallback to local heuristic result from file 1
643
  const words = localWords;
644
  const corrections = localRes.corrections;
645
  const corrected = localRes.corrected;
@@ -672,56 +499,80 @@
672
  }
673
  };
674
 
675
- // PDF download: logic from file 2
676
- downloadBtn.onclick = () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
  if (!lastResult) {
678
  alert("Run at least one grammar check before downloading a report.");
679
  return;
680
  }
681
 
682
- const jsPDF = getJsPDF();
683
- if (!jsPDF) return;
684
-
685
- const doc = new jsPDF({ unit: "pt", format: "a4" });
686
- let y = 40;
687
-
688
- doc.setFontSize(16);
689
- doc.text("TrueWrite Scan — Grammar Report", 40, y); y += 22;
690
-
691
- doc.setFontSize(11);
692
- doc.text("Generated: " + new Date().toLocaleString(), 40, y); y += 18;
693
- doc.text("User: " + (user || "N/A"), 40, y); y += 18;
694
-
695
- doc.setFontSize(12);
696
- doc.text(`Words analysed: ${lastResult.words}`, 40, y); y += 16;
697
- doc.text(`Corrections: ${lastResult.corrections}`, 40, y); y += 20;
698
-
699
- if (lastResult.summary) {
700
- doc.text("Summary:", 40, y); y += 16;
701
- doc.setFontSize(10);
702
- let lines = doc.splitTextToSize(lastResult.summary, 520);
703
- doc.text(lines, 40, y);
704
- y += lines.length * 12 + 10;
705
  }
706
-
707
- doc.setFontSize(11);
708
- doc.text("--- Original text (truncated) ---", 40, y); y += 16;
709
- doc.setFontSize(9);
710
- const original = lastResult.original || "";
711
- const originalTrunc = original.length > 2500 ? original.slice(0, 2500) + "\n\n[TRUNCATED]" : original;
712
- let lines = doc.splitTextToSize(originalTrunc, 520);
713
- doc.text(lines, 40, y);
714
- y += lines.length * 10 + 12;
715
-
716
- doc.setFontSize(11);
717
- doc.text("--- Corrected text (truncated) ---", 40, y); y += 16;
718
- doc.setFontSize(9);
719
- const corrected = lastResult.corrected || "";
720
- const correctedTrunc = corrected.length > 2500 ? corrected.slice(0, 2500) + "\n\n[TRUNCATED]" : corrected;
721
- lines = doc.splitTextToSize(correctedTrunc, 520);
722
- doc.text(lines, 40, y);
723
-
724
- doc.save("truewrite-grammar-report.pdf");
725
  };
726
 
727
  function escapeHtml(str) {
@@ -731,38 +582,13 @@
731
  }[s]));
732
  }
733
 
734
- // ===== Reviews slider (from file 1) =====
735
  const reviews = [
736
- {
737
- name: "Aarav S.",
738
- role: "Final-year B.Tech student",
739
- text: "I use this grammar page before every assignment submission. It quickly cleans up the most obvious mistakes.",
740
- stars: 5
741
- },
742
- {
743
- name: "Priya K.",
744
- role: "M.Tech researcher",
745
- text: "The corrected text + PDF report help me keep a record of changes when I work on my thesis chapters.",
746
- stars: 5
747
- },
748
- {
749
- name: "Rahul M.",
750
- role: "Content creator",
751
- text: "Simple, fast, no distractions. Perfect when I just want to sanity-check captions and short posts.",
752
- stars: 4
753
- },
754
- {
755
- name: "Sneha R.",
756
- role: "English learner",
757
- text: "Seeing how my sentences are automatically fixed is helping me understand grammar rules better.",
758
- stars: 5
759
- },
760
- {
761
- name: "Vikram J.",
762
- role: "Developer",
763
- text: "Nice example of a purely front-end grammar tool. The UI feels inspired by popular tools like QuillBot.",
764
- stars: 4
765
- }
766
  ];
767
 
768
  let currentReview = 0;
@@ -810,7 +636,7 @@
810
  document.getElementById("prevReview").addEventListener("click", () => {
811
  clearInterval(reviewTimer);
812
  prevReview();
813
- reviewTimer = setInterval(nextReview, 6000);
814
  });
815
 
816
  let reviewTimer = setInterval(nextReview, 6000);
 
5
  <title>Grammar Check – TrueWrite Scan</title>
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
  <script src="https://cdn.tailwindcss.com"></script>
8
+ <!-- jsPDF (kept for backward compatibility but server PDF will be used) -->
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
10
  </head>
11
  <body class="bg-gradient-to-br from-slate-950 via-slate-900 to-indigo-950 text-white min-h-screen flex flex-col">
 
177
  </div>
178
 
179
  <!-- ========= Info sections from file 1 ========= -->
180
+ <!-- ... content unchanged ... -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  </main>
182
 
183
  <!-- Footer -->
 
196
  window.location.href = "login.html";
197
  }
198
 
199
+ // jsPDF helper (kept but server PDF used for final)
200
  function getJsPDF() {
201
  if (window.jspdf && window.jspdf.jsPDF) return window.jspdf.jsPDF;
202
  if (window.jsPDF) return window.jsPDF;
 
261
  }
262
  }
263
 
264
+ // Word counting & 1000-word indicator
265
  function countWords(text) {
266
  if (!text || !text.trim()) return 0;
267
  return text.trim().split(/\s+/).length;
 
279
 
280
  textarea.addEventListener("input", updateWordCount);
281
 
282
+ // Simple local heuristic rules
283
  function applyLocalGrammarRules(rawText) {
284
  let corrections = 0;
285
  let text = rawText || "";
 
304
  return { corrected: text, corrections };
305
  }
306
 
307
+ // Drag & drop
308
  ["dragenter", "dragover"].forEach(evt => {
309
  dropZone.addEventListener(evt, e => {
310
  e.preventDefault();
 
376
  }
377
  };
378
 
379
+ // API calls
380
  async function callGrammarText(text) {
381
  const res = await fetch(`${BACKEND_URL}/api/grammar-check`, {
382
  method: "POST",
 
404
  return data;
405
  }
406
 
407
+ // Main check
408
  checkBtn.onclick = async () => {
409
  const text = textarea.value.trim();
410
  const file = fileInput.files[0];
 
466
  statusTiny.textContent = "Done";
467
  } catch (err) {
468
  console.error(err);
469
+ // Fallback to local heuristic result
470
  const words = localWords;
471
  const corrections = localRes.corrections;
472
  const corrected = localRes.corrected;
 
499
  }
500
  };
501
 
502
+ // Helper to download blob
503
+ function downloadBlob(blob, filename) {
504
+ const url = URL.createObjectURL(blob);
505
+ const a = document.createElement("a");
506
+ a.href = url;
507
+ a.download = filename || "report.pdf";
508
+ document.body.appendChild(a);
509
+ a.click();
510
+ a.remove();
511
+ setTimeout(() => URL.revokeObjectURL(url), 30000);
512
+ }
513
+
514
+ // Generic fetch PDF routine
515
+ async function fetchReportPdf({ endpointGet, endpointFile, text, file, defaultFilename }) {
516
+ if (file) {
517
+ const form = new FormData();
518
+ form.append("file", file, file.name);
519
+ const res = await fetch(`${BACKEND_URL}${endpointFile}`, {
520
+ method: "POST",
521
+ headers: { "Authorization": `Bearer ${token}` },
522
+ body: form
523
+ });
524
+ if (!res.ok) {
525
+ const txt = await res.text();
526
+ throw new Error(txt || `Server responded ${res.status}`);
527
+ }
528
+ const blob = await res.blob();
529
+ const cd = res.headers.get("content-disposition") || "";
530
+ const m = cd.match(/filename\*?=(?:UTF-8'')?["']?([^;"']+)/i);
531
+ const fname = m ? decodeURIComponent(m[1]) : defaultFilename;
532
+ downloadBlob(blob, fname);
533
+ return;
534
+ } else {
535
+ const q = encodeURIComponent(text || "");
536
+ const url = `${BACKEND_URL}${endpointGet}?text=${q}`;
537
+ const res = await fetch(url, {
538
+ method: "GET",
539
+ headers: { "Authorization": `Bearer ${token}` }
540
+ });
541
+ if (!res.ok) {
542
+ const txt = await res.text();
543
+ throw new Error(txt || `Server responded ${res.status}`);
544
+ }
545
+ const blob = await res.blob();
546
+ const cd = res.headers.get("content-disposition") || "";
547
+ const m = cd.match(/filename\*?=(?:UTF-8'')?["']?([^;"']+)/i);
548
+ const fname = m ? decodeURIComponent(m[1]) : defaultFilename;
549
+ downloadBlob(blob, fname);
550
+ }
551
+ }
552
+
553
+ // PDF download: call backend report endpoints (server-generated PDF)
554
+ downloadBtn.onclick = async () => {
555
  if (!lastResult) {
556
  alert("Run at least one grammar check before downloading a report.");
557
  return;
558
  }
559
 
560
+ try {
561
+ setLoading(true);
562
+ const file = fileInput.files[0] && !(fileInput.files[0].type === "text/plain" || fileInput.files[0].name.toLowerCase().endsWith(".txt")) ? fileInput.files[0] : null;
563
+ await fetchReportPdf({
564
+ endpointGet: "/report/grammar",
565
+ endpointFile: "/report/grammar-file",
566
+ text: textarea.value,
567
+ file,
568
+ defaultFilename: "TrueWrite_GrammarReport.pdf"
569
+ });
570
+ } catch (err) {
571
+ console.error(err);
572
+ alert("Failed to download report: " + (err.message || err));
573
+ } finally {
574
+ setLoading(false);
 
 
 
 
 
 
 
 
575
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
576
  };
577
 
578
  function escapeHtml(str) {
 
582
  }[s]));
583
  }
584
 
585
+ // Reviews slider (unchanged)
586
  const reviews = [
587
+ { name: "Aarav S.", role: "Final-year B.Tech student", text: "I use this grammar page before every assignment submission. It quickly cleans up the most obvious mistakes.", stars: 5 },
588
+ { name: "Priya K.", role: "M.Tech researcher", text: "The corrected text + PDF report help me keep a record of changes when I work on my thesis chapters.", stars: 5 },
589
+ { name: "Rahul M.", role: "Content creator", text: "Simple, fast, no distractions. Perfect when I just want to sanity-check captions and short posts.", stars: 4 },
590
+ { name: "Sneha R.", role: "English learner", text: "Seeing how my sentences are automatically fixed is helping me understand grammar rules better.", stars: 5 },
591
+ { name: "Vikram J.", role: "Developer", text: "Nice example of a purely front-end grammar tool. The UI feels inspired by popular tools like QuillBot.", stars: 4 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
592
  ];
593
 
594
  let currentReview = 0;
 
636
  document.getElementById("prevReview").addEventListener("click", () => {
637
  clearInterval(reviewTimer);
638
  prevReview();
639
+ reviewTimer = setInterval(prevReview, 6000);
640
  });
641
 
642
  let reviewTimer = setInterval(nextReview, 6000);