commit 5ec023afa32753527a057c560f4d7c1da8e68b74
parent ece368e219e9165e8094446c1dbbf4150948c39a
Author: David Eisinger <[email protected]>
Date: Sat, 11 Oct 2025 21:40:43 -0400
URL truncation
Diffstat:
4 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/internal/web/app.js b/internal/web/app.js
@@ -23,6 +23,14 @@ createApp({
this.initView();
},
methods: {
+ normalizeResults(arr) {
+ return arr.map((x) => ({
+ ...x,
+ description: x.description ?? null,
+ public: !!x.public,
+ urlTrunc: true,
+ }));
+ },
async initView() {
// Determine logged-in user from server-embedded data
if (window.MARKY_ME) this.me = { username: window.MARKY_ME };
@@ -51,7 +59,8 @@ createApp({
// Initialize from server-embedded data when available
try {
if (window.MARKY_INITIAL && window.MARKY_INITIAL.view === 'self' && window.MARKY_INITIAL.user === this.me.username) {
- this.results = Array.isArray(window.MARKY_INITIAL.results) ? window.MARKY_INITIAL.results : [];
+ const r = Array.isArray(window.MARKY_INITIAL.results) ? window.MARKY_INITIAL.results : [];
+ this.results = this.normalizeResults(r);
}
} catch {}
// Do not auto-fetch all bookmarks on initial load
@@ -60,7 +69,8 @@ createApp({
// Initialize from server-embedded data when available; no network fallback
try {
if (window.MARKY_INITIAL && window.MARKY_INITIAL.view === 'public' && window.MARKY_INITIAL.user === this.viewUser) {
- this.results = Array.isArray(window.MARKY_INITIAL.results) ? window.MARKY_INITIAL.results : [];
+ const r = Array.isArray(window.MARKY_INITIAL.results) ? window.MARKY_INITIAL.results : [];
+ this.results = this.normalizeResults(r);
}
} catch {}
}
@@ -212,11 +222,7 @@ createApp({
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const arr = await res.json();
- this.results = arr.map((x) => ({
- ...x,
- description: x.description ?? null,
- public: !!x.public,
- }));
+ this.results = this.normalizeResults(arr);
} catch (e) {
console.error(e);
} finally {
@@ -265,5 +271,8 @@ createApp({
// Our API wraps matches with guillemets « » — convert to <mark>
return ex.replace(/«/g, '<mark>').replace(/»/g, '</mark>');
},
+ toggleURL(b) {
+ b.urlTrunc = !b.urlTrunc;
+ },
},
}).mount("#app");
diff --git a/internal/web/index.html b/internal/web/index.html
@@ -89,7 +89,7 @@
<h3>
<a :href="b.url" target="_blank" rel="noopener noreferrer">{{ b.title || b.url }}</a>
</h3>
- <p class="url">{{ b.url }}</p>
+ <p :class="['url', { truncate: b.urlTrunc }]" :title="b.url" @click="toggleURL(b)">{{ b.url }}</p>
<p v-if="b.referrer" class="referrer">Referrer: <a :href="b.referrer" target="_blank" rel="noopener noreferrer">{{ b.referrer }}</a></p>
<div v-if="b.editing" class="edit-form">
<label>URL <input v-model.trim="b.editUrl" type="url" required /></label>
@@ -132,7 +132,7 @@
<div class="results">
<article v-for="b in results" :key="b.id" class="card">
<h3><a :href="b.url" target="_blank" rel="noopener noreferrer">{{ b.title || b.url }}</a></h3>
- <p class="url">{{ b.url }}</p>
+ <p :class="['url', { truncate: b.urlTrunc }]" :title="b.url" @click="toggleURL(b)">{{ b.url }}</p>
<p v-if="b.referrer" class="referrer">Referrer: <a :href="b.referrer" target="_blank" rel="noopener noreferrer">{{ b.referrer }}</a></p>
<div v-if="b.description" class="desc" v-html="renderMarkdown(b.description)"></div>
<p class="action-links">
diff --git a/internal/web/styles.css b/internal/web/styles.css
@@ -44,11 +44,15 @@ button.btn { border: none; }
.card.private { background: #f6f7f8; }
@media (prefers-color-scheme: dark) { .card.private { background: #202225; } }
.card h3 { margin: 0 0 6px 0; font-size: 16px; }
+/* Allow grid children to shrink so long strings don't expand layout */
+.grid > * { min-width: 0; }
+.card { min-width: 0; }
.archive-link { display:none; }
.icon { display:none; }
.edit-form { display: grid; gap: 8px; margin: 8px 0; }
.edit-form .actions { display: flex; gap: 8px; }
-.url { color: #666; font-size: 12px; margin: 0 0 6px 0; word-break: break-all; }
+.url { color: #666; font-size: 12px; margin: 0 0 6px 0; overflow-wrap: anywhere; word-break: break-word; }
+.url.truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; max-width: 100%; }
.referrer { color: #999; font-size: 12px; margin: 0 0 6px 0; word-break: break-all; }
.referrer a { color: inherit; }
.action-links { margin: 6px 0 0 0; font-size: 13px; color: #555; }
diff --git a/internal/web/user.html b/internal/web/user.html
@@ -49,7 +49,7 @@
<div class="results">
<article v-for="b in results" :key="b.id" :class="['card', { private: !b.public }]">
<h3><a :href="b.url" target="_blank" rel="noopener noreferrer">{{ b.title || b.url }}</a></h3>
- <p class="url">{{ b.url }}</p>
+ <p :class="['url', { truncate: b.urlTrunc }]" :title="b.url" @click="toggleURL(b)">{{ b.url }}</p>
<p v-if="b.referrer" class="referrer">Referrer: <a :href="b.referrer" target="_blank" rel="noopener noreferrer">{{ b.referrer }}</a></p>
<div v-if="b.editing" class="edit-form">
<label>URL <input v-model.trim="b.editUrl" type="url" required /></label>
@@ -91,7 +91,7 @@
<div class="results">
<article v-for="b in results" :key="b.id" class="card">
<h3><a :href="b.url" target="_blank" rel="noopener noreferrer">{{ b.title || b.url }}</a></h3>
- <p class="url">{{ b.url }}</p>
+ <p :class="['url', { truncate: b.urlTrunc }]" :title="b.url" @click="toggleURL(b)">{{ b.url }}</p>
<p v-if="b.referrer" class="referrer">Referrer: <a :href="b.referrer" target="_blank" rel="noopener noreferrer">{{ b.referrer }}</a></p>
<div v-if="b.description" class="desc" v-html="renderMarkdown(b.description)"></div>
<p class="action-links">