Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/workflows/project-assign.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ run-name: Assign project under issue and pull requests
on:
issues:
types: [opened]
pull_request:
pull_request_target:
types: [opened, reopened]

permissions:
Expand Down
18 changes: 16 additions & 2 deletions app/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re
from datetime import datetime, timezone
from typing import Optional
from app.utils.cache import list_cache_clean, clear_cache
Expand Down Expand Up @@ -98,12 +99,25 @@ async def create_short_url(
qr_type: str = Form("short"),
):
session = request.session
original_url = sanitize_url(original_url)
original_url = original_url.strip()

if not original_url or not is_valid_url(original_url):
if not original_url.startswith(("http://", "https://")):
if re.match(r"^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+){1,2}$", original_url):
Copy link
Owner

Choose a reason for hiding this comment

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

this is incorrect approach; create separate method and use that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sir if i romve this then if anyone type like https://kdkfjclkdclkd.....it will pass and generate qr ...because it is syntactically valid. ...if u told i will remove it and check only valid urls.

original_url = "https://" + original_url
Copy link
Owner

Choose a reason for hiding this comment

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

why do you add https by yourself?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

if i don't add this ...then the url like google.com which is valid ,but can't show it as a valid
that's why i add this

else:
session["error"] = "Please enter a valid URL."
return RedirectResponse("/", status_code=status.HTTP_303_SEE_OTHER)

if not is_valid_url(original_url):
session["error"] = "Please enter a valid URL."
return RedirectResponse("/", status_code=status.HTTP_303_SEE_OTHER)

# original_url = sanitize_url(original_url)

# if not original_url or not is_valid_url(original_url):
# session["error"] = "Please enter a valid URL."
# return RedirectResponse("/", status_code=status.HTTP_303_SEE_OTHER)

short_code: Optional[str] = get_short_from_cache(original_url)

if not short_code and db.is_connected():
Expand Down
81 changes: 32 additions & 49 deletions app/static/css/tiny.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,21 @@ body {
background-image: radial-gradient(circle at 50% -20%, #1e1e2e 0%, transparent 50%);
}

/* Light theme overrides */

body.light-theme {
/* background + glass */
--bg: #f9fafb;
--glass: rgba(0, 0, 0, 0.03);
--glass-border: rgba(0, 0, 0, 0.07);

/* main card + text */
--card: #ffffff;
--text-primary: #111827;
--text-secondary: #4b5563;
--text-color: #111827;

/* accent */
--accent: #2563eb;

/* Remove the dark radial gradient */
background-image: none;
}

/* Layout */
.main-layout {
max-width: 900px;
max-width: 940px;
margin: 0 auto;
padding: 6rem 1rem 4rem;
display: flex;
Expand Down Expand Up @@ -69,9 +61,7 @@ body.light-theme {

body.light-theme .app-header {
background: #ffffff;
/* solid background */
border-bottom: 1px solid #e5e7eb;
/* clear separation */
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
}

Expand Down Expand Up @@ -202,6 +192,16 @@ body.dark-theme .app-header {
-webkit-text-fill-color: transparent;
}

.alert-error {
background: #ffecec;
border: 1px solid #ffb3b3;
color: #cc0000;
padding: 10px 14px;
border-radius: 8px;
margin-bottom: 14px;
font-size: 14px;
}

.input-wrapper {
display: flex;
gap: 1rem;
Expand Down Expand Up @@ -250,7 +250,7 @@ body.dark-theme .app-header {
cursor: pointer;
}

/* Result card */

.result-card {
width: 100%;
background: linear-gradient(145deg, rgba(99, 102, 241, 0.1), rgba(0, 0, 0, 0));
Expand Down Expand Up @@ -323,10 +323,10 @@ body.dark-theme .app-header {
color: var(--accent);
}

/* Recent tray */
.recent-tray {
width: 100%;
margin-top: 2rem;
overflow: visible;
}

.recent-header {
Expand All @@ -337,19 +337,23 @@ body.dark-theme .app-header {
align-items: center;
}


.scroll-container {
display: flex;
gap: 1rem;
overflow-x: auto;
padding: 1rem 0;
padding: 1rem 16px;
scroll-padding-right: 16px;
box-sizing: border-box;
}

.scroll-container::-webkit-scrollbar {
display: none;
}

.recent-item {
min-width: 220px;
width: 260px;
flex: 0 0 auto;
background: var(--glass);
border: 1px solid var(--glass-border);
padding: 1rem;
Expand All @@ -360,6 +364,10 @@ body.dark-theme .app-header {
flex-shrink: 0;
}

.recent-item:last-child {
margin-right: 16px;
}

.short-code {
color: var(--accent);
font-weight: bold;
Expand All @@ -378,23 +386,16 @@ body.dark-theme .app-header {
/* ===============================
MODERN GLASS RECENT TABLE
================================= */
/* PAGE CONTAINER */
.recent-page-container {
width: 100%;
max-width: 1200px;
/* controls table width */
margin: 0 auto;
/* centers */
padding: 0 24px;
/* space left & right */
box-sizing: border-box;
}

/* Wrapper */
.recent-table-wrapper {
width: 100%;
/*margin-top: 20px;
margin-bottom: 20px;*/
overflow-x: auto;
}

Expand All @@ -411,7 +412,6 @@ body.dark-theme .app-header {
min-width: 800px;
}

/* Header */
.recent-table thead {
background: var(--glass);
}
Expand All @@ -428,7 +428,6 @@ body.dark-theme .app-header {
white-space: nowrap;
}

/* Body cells */
.recent-table td {
padding: 14px;
font-size: 14px;
Expand All @@ -439,7 +438,6 @@ body.dark-theme .app-header {
white-space: nowrap;
}

/* Row hover */
.recent-table tbody tr:hover {
background: rgba(255, 255, 255, 0.05);
}
Expand All @@ -448,7 +446,6 @@ body.dark-theme .app-header {
COLUMN WIDTH CONTROL
================================= */

/* # column */
.recent-table th:nth-child(1),
.recent-table td:nth-child(1) {
width: 45px;
Expand All @@ -457,26 +454,22 @@ body.dark-theme .app-header {
padding-right: 6px;
}

/* Short URL */
.recent-table th:nth-child(2),
.recent-table td:nth-child(2) {
width: 170px;
}

/* Original URL (main space owner) */
.recent-table th:nth-child(3),
.recent-table td:nth-child(3) {
width: 45%;
min-width: 0;
}

/* Created */
.recent-table th:nth-child(4),
.recent-table td:nth-child(4) {
width: 170px;
}

/* Visits */
.recent-table th:nth-child(5),
.recent-table td:nth-child(5) {
width: 80px;
Expand All @@ -485,7 +478,6 @@ body.dark-theme .app-header {
color: var(--accent-2);
}

/* Actions */
.recent-table th:nth-child(6),
.recent-table td:nth-child(6) {
width: 120px;
Expand All @@ -506,7 +498,6 @@ body.dark-theme .app-header {
text-decoration: underline;
}

/* Original URL truncate */
.original-url {
word-break: break-all;
}
Expand All @@ -523,7 +514,6 @@ body.dark-theme .app-header {
color: var(--accent);
}

/* Created time */
.created-time {
font-size: 13px;
color: var(--muted);
Expand Down Expand Up @@ -572,21 +562,19 @@ body.dark-theme .app-header {
border-bottom: 1px solid var(--glass-border);
}

/* Tablet */

@media (max-width: 1024px) {
.recent-page-container {
padding: 0 18px;
}
}

/* Mobile */
@media (max-width: 768px) {
.recent-page-container {
padding: 0 12px;
}
}

/* Small phones */
@media (max-width: 480px) {
.recent-page-container {
padding: 0 8px;
Expand Down Expand Up @@ -739,31 +727,26 @@ body.dark-theme .footer-bottom a {
}
}

.recent-tray .recent-item .original-url {
max-width: 350px;
min-width: 0;
}



/* allow wrapping */
.recent-tray .recent-item .original-url,
.recent-tray .recent-item .original-url a {

display: -webkit-box;
-webkit-box-orient: vertical;

-webkit-line-clamp: 3;
/* ⭐ change 2 or 3 lines here */
line-clamp: 3;

-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;

white-space: normal;
word-break: break-word;
word-break: break-all;
overflow-wrap: anywhere;
}

/* IMPORTANT — remove width restriction */
.recent-tray .recent-item {
min-width: 0;
/* allows shrinking inside flex/grid */
max-width: 100%;
}

Expand Down
9 changes: 8 additions & 1 deletion app/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
<main class="main-layout">
<div class="hero-input-card">
<h1>Shorten Your Links</h1>
{% if error %}
<div class="alert-error">
⚠ {{ error }}
</div>
{% endif %}
<form method="POST" id="shortenForm" action="/shorten">
<div class="input-wrapper"> <input type="text" name="original_url" placeholder="Paste your long link here..."
value="{{ original_url or '' }}" required> <button type="submit" class="btn-primary">Shorten</button> </div>
value="{{ original_url or '' }}" required>
<button type="submit" class="btn-primary">Shorten</button>
</div>
<div class="options-row"> <label class="checkbox-label"> <input type="checkbox" name="generate_qr" checked>
Generate QR Code </label> <span class="info-text">Analytics Enabled</span> </div>
</form>
Expand Down
Loading