Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 52 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,97 @@
# [Project Name] 🎯
# Find AND Replace 🎯


## Basic Details
### Team Name: [Name]
### Team Name: Crew


### Team Members
- Member 1: [Name] - [College]
- Member 2: [Name] - [College]
- Member 3: [Name] - [College]
- Member 1: Sneha.S - SSET
- Member 2: Saniya.V.S - SSET
- Member 3: Zeba Saithalavi - SSET

### Hosted Project Link
[mention your project hosted project link here]

### Project Description
[2-3 lines about what your project does]
Find AND Replace is a fast, browser-based tool that allows users to replace words in PDFs without altering formatting. It preserves the original layout, fonts, and text alignment while ensuring real-time word replacements—all without uploading files to a server!

### The Problem statement
[What ridiculous problem are you solving?]



### The Problem statement}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove Stray Curly Bracket in Heading
The heading "### The Problem statement}" contains an extra curly bracket. Please remove it to ensure proper Markdown syntax.

Proposed change:

-### The Problem statement}
+### The Problem statement
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### The Problem statement}
### The Problem statement

As a computer science student we have to change the user name in every program to take print outs for lab records ,it take almost 1-2 hours to edit all the files .we noted that a lot of time was wasted through this process ,Hence the idea
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve Grammar and Clarity in Problem Statement
The problem statement has several grammatical issues that affect readability. Consider revising the text for clarity and correctness. For example:

-As a computer science student we have to change the user name in every program to take print outs for lab records ,it take almost 1-2 hours to edit all the files .we noted that a lot of time was wasted through this process ,Hence the idea
+As a computer science student, we have to change the username in every program to generate printouts for lab records. It takes almost 1–2 hours to edit all the files. We noted that a lot of time was wasted through this process; hence, the idea...
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
As a computer science student we have to change the user name in every program to take print outs for lab records ,it take almost 1-2 hours to edit all the files .we noted that a lot of time was wasted through this process ,Hence the idea
As a computer science student, we have to change the username in every program to generate printouts for lab records. It takes almost 12 hours to edit all the files. We noted that a lot of time was wasted through this process; hence, the idea...
🧰 Tools
🪛 LanguageTool

[style] ~23-~23: It’s more common nowadays to write this noun as one word.
Context: ...r science student we have to change the user name in every program to take print outs for...

(RECOMMENDED_COMPOUNDS)


[uncategorized] ~23-~23: This plural noun needs to be hyphenated.
Context: ... the user name in every program to take print outs for lab records ,it take almost 1-2 hou...

(VERB_NOUN_CONFUSION)


[uncategorized] ~23-~23: This verb does not appear to agree with the subject. Consider using a different form.
Context: ... to take print outs for lab records ,it take almost 1-2 hours to edit all the files ...

(AI_EN_LECTOR_REPLACEMENT_VERB_AGREEMENT)


[typographical] ~23-~23: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...nt outs for lab records ,it take almost 1-2 hours to edit all the files .we noted t...

(HYPHEN_TO_EN)


### The Solution
[How are you solving it? Keep it fun!]
Our browser-based tool streamlines PDF text replacement by allowing users to upload a PDF, specify the word to be changed, and download the modified version instantly. It ensures original formatting, font styles, and alignment are preserved while making the edits.


### **Project Description**
We developed a web-based tool that allows users to upload a PDF, specify a word to be replaced, and provide the updated word. The website then automatically processes the PDF, replaces the specified word while preserving the original formatting, and generates a downloadable version of the edited PDF—all within seconds.

This eliminates the need for manual editing, making the process faster, more efficient, and error-free. Since the tool runs entirely in the browser, users can edit PDFs without uploading files to external servers, ensuring data privacy and security.

## Technical Details
### Technologies/Components Used
For Software:
- [Languages used]
- [Frameworks used]
- [Libraries used]
- [Tools used]

For Hardware:
- [List main components]
- [List specifications]
- [List tools required]
Languages: HTML, CSS, JavaScript
Libraries:
pdf-lib → Modify PDFs while keeping formatting intact.
pdf.js → Render and display PDF previews.

### Implementation
For Software:
# Installation
[commands]
Tools:
Visual Studio Code
GitHub
Netlify / Vercel (for deployment)

# Run
[commands]

### Project Documentation
For Software:

# Screenshots (Add at least 3)
![Screenshot1](Add screenshot 1 here with proper name)
*Add caption explaining what this shows*

![Screenshot2](Add screenshot 2 here with proper name)
*Add caption explaining what this shows*
![Screenshot1](first page ))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix Image Markdown Formatting Error
The markdown for Screenshot1 appears to have an extra parenthesis. Please remove the stray " ))" to ensure proper image rendering.
Proposed change:

-![Screenshot1](first page ))
+![Screenshot1](first page)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
![Screenshot1](first page ))
![Screenshot1](first page)

![alt text](<WhatsApp Image 2025-02-09 at 10.05.54 AM (1).jpeg>)

![Screenshot3](Add screenshot 3 here with proper name)
*Add caption explaining what this shows*
![Screenshot2](web page after eter the inputs)
![alt text](<WhatsApp Image 2025-02-09 at 10.05.42 AM.jpeg>)

# Diagrams
![Workflow](Add your workflow/architecture diagram here)
*Add caption explaining your workflow*
![Screenshot3](web page after the process)
![alt text](<WhatsApp Image 2025-02-09 at 10.05.42 AM (5).jpeg>)

For Hardware:

# Schematic & Circuit
![Circuit](Add your circuit diagram here)
*Add caption explaining connections*

![Schematic](Add your schematic diagram here)
*Add caption explaining the schematic*

# Build Photos
![Team](Add photo of your team here)


![Components](Add photo of your components here)
*List out all components shown*

![Build](Add photos of build process here)
*Explain the build steps*

![Final](Add photo of final product here)
*Explain the final build*
![Final]
![alt text](<WhatsApp Image 2025-02-09 at 10.05.42 AM copy.jpeg>)

Find and Replace is a frontend-only web application that allows users to upload a PDF, replace specific words, and download the modified version while preserving the original formatting. It eliminates the need for manual PDF editing, which is often time-consuming and tedious.

The tool works by extracting text from the uploaded PDF using pdf.js, replacing the specified words using pdf-lib, and regenerating the document while ensuring that the original font, alignment, and layout remain intact. Built with HTML, CSS, and JavaScript, it runs entirely in the browser, ensuring speed, security, and privacy, as no data is sent to external servers.

Hosted on Vercel, GitHub Pages, Find and Replace is easily accessible and automatically updates when changes are made. It provides a fast, free, and efficient way to edit PDFs without requiring additional software installations, making it an ideal solution for students, professionals, and anyone needing quick text replacements in documents

### Project Demo
# Video
[Add your demo video link here]
*Explain what the video demonstrates*
<video controls src="WhatsApp Video 2025-02-09 at 10.23.59 AM (1).mp4" title="Title"></video>
The video showcases how the Find and Replace web application functions:

1️⃣ The user uploads a PDF file.
2️⃣ They enter the word to be replaced and specify the new word.
3️⃣ Clicking the "Replace & Download" button initiates the replacement process.
4️⃣ The modified PDF is automatically downloaded, retaining the original formatting.

This streamlined process enables quick and effortless text modifications in PDFs without requiring extra software or backend support

# Additional Demos
[Add any extra demo materials/links]

## Team Contributions
- [Name 1]: [Specific contributions]
- [Name 2]: [Specific contributions]
- [Name 3]: [Specific contributions]
- Sneha.S:CSS
- Saniya.V.S: Javascript
- Zeba Saithalavi: html,

---
Made with ❤️ at TinkerHub
39 changes: 39 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Find & Replace in PDF</title>
<link rel="stylesheet" href="styles.css">


<script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"></script>
Comment on lines +10 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add integrity hashes for CDN scripts.

Add integrity hashes to prevent supply chain attacks.

-    <script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"></script>
+    <script src="https://unpkg.com/[email protected]/dist/pdf-lib.min.js" 
+            integrity="sha384-..." 
+            crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js" 
+            integrity="sha384-..." 
+            crossorigin="anonymous"></script>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/pdf-lib.min.js"
integrity="sha384-..."
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"
integrity="sha384-..."
crossorigin="anonymous"></script>

<script>
pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.worker.min.js";
</script>
</head>
<body>

<header>
<h2>PDF Word Replacer</h2>
<h3>Presented by SSET MADIYANZZ</h3>
<p>Upload a PDF, replace words, and download the updated file!</p>
</header>

<main class="container">
<input type="file" id="fileInput" accept="application/pdf">

<label for="oldWord">Find word:</label>
<input type="text" id="oldWord" placeholder="Enter word to replace">

<label for="newWord">Replace with:</label>
<input type="text" id="newWord" placeholder="Enter new word">

<button id="replaceBtn">Replace & Download</button>
</main>

<script src="script.js"></script>

</body>
</html>
95 changes: 95 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
document.addEventListener("DOMContentLoaded", async () => {
const fileInput = document.getElementById("fileInput");
const oldWordInput = document.getElementById("oldWord");
const newWordInput = document.getElementById("newWord");
const replaceBtn = document.getElementById("replaceBtn");

replaceBtn.addEventListener("click", async () => {
const file = fileInput.files[0];
const oldWord = oldWordInput.value.trim();
const newWord = newWordInput.value.trim();

if (!file) return alert("Please upload a PDF file.");
if (!oldWord) return alert("Enter the word to replace.");
if (oldWord === newWord) return alert("New word must be different.");
Comment on lines +12 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance input validation.

Add validation for:

  1. File type (ensure it's PDF)
  2. File size limit
  3. Empty new word
  4. Special characters in words
-        if (!file) return alert("Please upload a PDF file.");
-        if (!oldWord) return alert("Enter the word to replace.");
-        if (oldWord === newWord) return alert("New word must be different.");
+        if (!file) return alert("Please upload a PDF file.");
+        if (file.type !== "application/pdf") return alert("Please upload a valid PDF file.");
+        if (file.size > 10 * 1024 * 1024) return alert("File size must be less than 10MB.");
+        if (!oldWord) return alert("Enter the word to replace.");
+        if (!newWord) return alert("Enter the new word.");
+        if (oldWord === newWord) return alert("New word must be different.");
+        if (/[^\w\s]/.test(oldWord) || /[^\w\s]/.test(newWord)) 
+            return alert("Words can only contain letters, numbers, and spaces.");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!file) return alert("Please upload a PDF file.");
if (!oldWord) return alert("Enter the word to replace.");
if (oldWord === newWord) return alert("New word must be different.");
if (!file) return alert("Please upload a PDF file.");
if (file.type !== "application/pdf") return alert("Please upload a valid PDF file.");
if (file.size > 10 * 1024 * 1024) return alert("File size must be less than 10MB.");
if (!oldWord) return alert("Enter the word to replace.");
if (!newWord) return alert("Enter the new word.");
if (oldWord === newWord) return alert("New word must be different.");
if (/[^\w\s]/.test(oldWord) || /[^\w\s]/.test(newWord))
return alert("Words can only contain letters, numbers, and spaces.");


try {
const fileReader = new FileReader();
fileReader.readAsArrayBuffer(file);
fileReader.onload = async function () {
const pdfBytes = new Uint8Array(fileReader.result);
const modifiedPdfBytes = await processPdf(pdfBytes, oldWord, newWord);

if (modifiedPdfBytes) {
const blob = new Blob([modifiedPdfBytes], { type: "application/pdf" });
downloadPdf(blob, file.name);
} else {
alert("Failed to replace text.");
}
};
} catch (error) {
console.error(error);
alert("Error processing the PDF.");
}
});

async function processPdf(pdfBytes, oldWord, newWord) {
const pdf = await pdfjsLib.getDocument({ data: pdfBytes }).promise;
const pdfDoc = await PDFLib.PDFDocument.load(pdfBytes);
const font = await pdfDoc.embedFont(PDFLib.StandardFonts.Helvetica);
const pages = pdfDoc.getPages();

for (let i = 0; i < pdf.numPages; i++) {
const page = await pdf.getPage(i + 1);
const textContent = await page.getTextContent();

let modifiedLines = [];
let originalText = textContent.items.map(item => item.str).join(" ");

if (!originalText.includes(oldWord)) continue; // Skip page if no match

// Replace words line by line
for (let item of textContent.items) {
let newText = item.str.replace(new RegExp(escapeRegExp(oldWord), "g"), newWord);
modifiedLines.push({ text: newText, x: item.transform[4], y: item.transform[5] });
}

// Clear the original text by drawing a white rectangle
const { width, height } = pages[i].getSize();
pages[i].drawRectangle({
x: 0,
y: 0,
width,
height,
color: PDFLib.rgb(1, 1, 1),
opacity: 1,
});


for (let line of modifiedLines) {
pages[i].drawText(line.text, {
x: line.x,
y: height - line.y,
font,
size: 12,
color: PDFLib.rgb(0, 0, 0),
});
Comment on lines +58 to +76
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve text replacement strategy.

Current implementation has several limitations:

  1. Fixed font size doesn't match original text
  2. White rectangle might cover overlapping content
  3. Original text styles are lost
  4. No progress indication for large files

Consider:

  1. Extract and use original font size
  2. Use more precise content replacement
  3. Preserve text styles
  4. Add progress callback
-            pages[i].drawRectangle({
-                x: 0,
-                y: 0,
-                width,
-                height,
-                color: PDFLib.rgb(1, 1, 1),
-                opacity: 1,
-            });
+            // Get text bounds for precise replacement
+            const textBounds = await page.getTextBounds();
+            for (const bound of textBounds.items) {
+                if (bound.str.includes(oldWord)) {
+                    pages[i].drawRectangle({
+                        x: bound.x,
+                        y: height - bound.y,
+                        width: bound.width,
+                        height: bound.height,
+                        color: PDFLib.rgb(1, 1, 1),
+                        opacity: 1,
+                    });
+                }
+            }

             for (let line of modifiedLines) {
                 pages[i].drawText(line.text, {
                     x: line.x,
                     y: height - line.y, 
                     font,
-                    size: 12,
+                    size: line.fontSize || 12,
                     color: PDFLib.rgb(0, 0, 0),
+                    opacity: line.opacity || 1,
                 });
             }

Committable suggestion skipped: line range outside the PR's diff.

}
}

return await pdfDoc.save();
}

function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

function downloadPdf(blob, fileName) {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = fileName.replace(".pdf", "_modified.pdf");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
});
101 changes: 101 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* Full-page layout */
body {
font-family: "Times New Roman", serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
text-align: center;
background-color: #f4f4f4; /* Light background for better visibility */
background-image: url("Light-Blue-Abstract-Webpage-Background-Graphics-1.jpg");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed;
}

/* Header Styling */
header {
background: rgba(114, 235, 251, 0.8); /* Fixed background color */
padding: 15px;
border-radius: 10px;
margin-bottom: 20px;
width: 100%;
max-width: 600px;
}

/* Paragraph Styling */
p {
font-size: 20px;
color: #333;
font-weight: normal;
margin-bottom: 15px;
}

/* Heading Styling */
h2 {
font-size: 50px;
font-weight: bold;
color: #1331c6;
margin: 0;
}

/* Heading Styling */
h3 {
font-size: 18px;
font-weight: bold;
color: #4458bd;
margin: 0;
}

/* Centered Box */
.container {
background: rgba(255, 255, 255, 0.3); /* More transparency for better blending */
padding: 20px;
border-radius: 15px; /* Softer rounded corners */
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); /* Soft diffused shadow */
width: 320px;
margin-right: 20px; /* Added space on the right */
backdrop-filter: blur(15px); /* Stronger blur for a glassy effect */
-webkit-backdrop-filter: blur(15px); /* Ensures compatibility */
border: 1px solid rgba(255, 255, 255, 0.4); /* Light border to blend edges */
}




/* Input & Button Styling */
input, button {
display: block;
width: 90%;
margin: 10px auto;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}


button {
background-color: #007BFF;
color: white;
cursor: pointer;
border: none;
transition: background-color 0.3s ease-in-out;
font-weight: bold;
}

button:hover {
background-color: #0056b3;
}


label {
font-size: 18px;
font-weight: bold;
display: block;
margin-top: 10px;
color: #333;
}
Loading