Paste messy HTML, get clean text back.
Welcome to another official UVF IT build session. Today we are creating a minimal, server-side clone of 'Jack the Snipper', a tool designed to strip HTML tags and formatting from pasted content, leaving you with clean, readable plain text.
This project uses Python and Flask to handle the heavy lifting of HTML sanitization. You will learn how to accept user input, process it using a robust library like bleach, and return a sanitized result, all within a simple, self-contained application.
pip to manage dependencies, so ensure your environment is set up correctly.bleach for security. Do not skip this; raw HTML parsing without sanitization can lead to XSS vulnerabilities if you ever deploy this publicly.Create a new directory for your project and initialize a virtual environment to keep dependencies isolated. This is the standard practice for Python web apps, ensuring your system Python remains clean and your project dependencies are version-controlled.
mkdir html-cleaner-clone
cd html-cleaner-clone
python3 -m venv venv
source venv/bin/activateWe need Flask for the web server and bleach for cleaning the HTML. bleach is a trusted library that removes unwanted tags and attributes while preserving safe text, making it perfect for this sanitization task.
pip install flask bleachCreate the main application file. We will define a single endpoint /clean that accepts a POST request with JSON data containing the 'html' field. The bleach.clean function will strip all tags, leaving only plain text.
We configure bleach to allow no tags (tags=[]) and no attributes (attributes={}), ensuring that even inline styles or scripts are completely removed. This creates a strict plain-text output from any messy HTML input.
app.py
from flask import Flask, request, jsonify
import bleach
app = Flask(__name__)
@app.route('/clean', methods=['POST'])
def clean_html():
data = request.get_json()
if not data or 'html' not in data:
return jsonify({'error': 'No HTML provided'}), 400
raw_html = data['html']
# Strip all tags and attributes to get plain text
clean_text = bleach.clean(raw_html, tags=[], attributes={}, strip=True)
return jsonify({'clean_text': clean_text})
if __name__ == '__main__':
app.run(debug=True)Create an templates folder and an index.html file. This simple HTML page will contain a textarea for input and a button to send the data to our API. We use vanilla JavaScript to handle the fetch request.
The frontend is kept minimal to focus on the core functionality. We use a standard POST request to send the HTML content to the /clean endpoint we defined earlier. The response is then displayed in a result div.
We include basic error handling in the JavaScript to ensure the user is notified if the server fails to respond. This makes the application more robust and user-friendly.
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML Cleaner</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
textarea {
width: 100%;
height: 150px;
margin-bottom: 10px;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
#result {
margin-top: 20px;
padding: 10px;
background-color: #f8f9fa;
border: 1px solid #dee2e6;
white-space: pre-wrap;
}
</style>
</head>
<body>
<h1>HTML Cleaner</h1>
<textarea id="htmlInput" placeholder="Paste your HTML here..."></textarea>
<button onclick="cleanHtml()">Clean Text</button>
<div id="result"></div>
<script>
async function cleanHtml() {
const htmlContent = document.getElementById('htmlInput').value;
const resultDiv = document.getElementById('result');
try {
const response = await fetch('/clean', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ html: htmlContent })
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
resultDiv.textContent = data.clean_text;
} catch (error) {
resultDiv.textContent = 'Error: ' + error.message;
}
}
</script>
</body>
</html>Update app.py to serve the index page on the root route, then run the application. Open your browser to localhost:5000 to test the tool.
We add a simple route for the root URL that renders the index.html template. This allows users to access the UI directly by visiting the base URL of the application.
Finally, we run the Flask development server. This will start the application locally, and you can interact with it through your web browser to verify that the HTML cleaning functionality works as expected.
app.py
from flask import Flask, request, jsonify, render_template
import bleach
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/clean', methods=['POST'])
def clean_html():
data = request.get_json()
if not data or 'html' not in data:
return jsonify({'error': 'No HTML content provided'}), 400
html_content = data['html']
# Strip all tags, leaving only plain text
clean_text = bleach.clean(html_content, tags=[], attributes={}, strip=True)
return jsonify({'clean_text': clean_text})
if __name__ == '__main__':
app.run(debug=True)| Check | Command / Why it matters |
|---|---|
| Server starts without errors | Run python app.py and see 'Running on http://127.0.0.1:5000' in the terminal. |
| UI loads correctly | Open http://localhost:5000 in your browser; you should see the textarea and button. |
| HTML is stripped | Paste <p>Hello <b>World</b></p> into the textarea, click 'Clean Text', and verify the result is Hello World. |
You now have a working HTML cleaner. Try extending it by adding options to preserve specific tags like <a> or <img>, or by adding a 'Copy to Clipboard' button for better UX.