Release v0.5.0: dev -> main #288
@@ -299,8 +299,14 @@ html[data-wrap] .float { overflow-x: hidden; }
|
||||
.code-head .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
|
||||
.code {
|
||||
font-family: var(--font-mono); font-size: var(--code-fs); line-height: var(--code-lh);
|
||||
padding: 14px 0; display: flex; overflow-x: auto;
|
||||
padding: 14px 0; display: flex; overflow-x: hidden;
|
||||
}
|
||||
/* #261: horizontal scroll must live on the codebody, not the .code flex
|
||||
container — a container-level scroll takes the gutter with it when the
|
||||
user scrolls long lines. The gutter sits OUTSIDE the scroll container and
|
||||
stays visible; the codebody shrinks to the remaining space and scrolls
|
||||
(min-width: 0 lets it shrink below its content width inside the flex row). */
|
||||
.code .codebody { flex: 1 1 auto; min-width: 0; overflow-x: auto; }
|
||||
/* #167: the gutter must not drive the flex layout — its content width
|
||||
(row count × number width) shrinks the code column, which re-wraps lines,
|
||||
which grows the gutter: a feedback loop. Pin the gutter with a fixed
|
||||
@@ -310,7 +316,7 @@ html[data-wrap] .float { overflow-x: hidden; }
|
||||
.code .gutter { flex-shrink: 0; }
|
||||
/* gutter/code share line metrics; the editor gutter keeps its own padding (#50) */
|
||||
.code .gutter { padding-top: 0; padding-bottom: 0; }
|
||||
.codebody { padding: 0 18px; white-space: pre; }
|
||||
.codebody { padding: 0 18px; white-space: pre; overflow-x: auto; }
|
||||
/* #167: each logical line is its own block so offsetTop identifies its first visual row */
|
||||
.codeline { display: block; }
|
||||
/* #167 rev: gutter number spans must stack one per visual row (wrap on) */
|
||||
@@ -869,6 +875,9 @@ button[type="submit"]:focus-visible,
|
||||
.col-a { width: 260px; } .col-b { width: 140px; } .col-c { width: 120px; }
|
||||
.col-d { width: 96px; } .col-d2 { width: 150px; } .col-e { width: 190px; }
|
||||
.col-f { width: 100px; } .col-g { width: 190px; }
|
||||
/* #255: history's URL column had its own narrow width (col-f doubles as
|
||||
/mine's ID column); give it a dedicated class. */
|
||||
.col-url { width: 150px; }
|
||||
/* #210: /mine rows render a delete button cell that had no declared column,
|
||||
so under table-layout:fixed it overlapped the ID column. */
|
||||
.col-del { width: 64px; }
|
||||
@@ -884,3 +893,17 @@ button[type="submit"]:focus-visible,
|
||||
.created-banner { display: block; }
|
||||
/* #167: gutter rows for wrapped paste view — one row per visual code line */
|
||||
.gutline { display: block; }
|
||||
|
||||
/* #267: jump to top/bottom pills for long pastes and the editor.
|
||||
Hidden unless JS (jump.js) detects content more than 2x the viewport. */
|
||||
.jumpnav {
|
||||
position: fixed;
|
||||
right: 18px;
|
||||
bottom: 18px;
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.jumpnav.hidden { display: none; }
|
||||
.jump-btn { box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); }
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/* #267: jump to top / bottom controls for long content.
|
||||
Paste view scrolls the window; the /new editor scrolls its textarea.
|
||||
The active scroller is chosen via data-jump-scroll on the script tag. */
|
||||
(function () {
|
||||
var nav = document.getElementById('jumpnav');
|
||||
if (!nav) return;
|
||||
var scroller = window;
|
||||
var sel = nav.dataset.jumpScroll;
|
||||
if (sel) scroller = document.querySelector(sel);
|
||||
|
||||
function el() {
|
||||
return scroller === window ? document.scrollingElement : scroller;
|
||||
}
|
||||
function isLarge() {
|
||||
var e = el();
|
||||
if (!e) return false;
|
||||
var visible = scroller === window ? window.innerHeight : e.clientHeight;
|
||||
return e.scrollHeight > visible * 2;
|
||||
}
|
||||
function refresh() {
|
||||
nav.classList.toggle('hidden', !isLarge());
|
||||
}
|
||||
function jump(toTop) {
|
||||
var e = el();
|
||||
if (!e) return;
|
||||
if (scroller === window) {
|
||||
window.scrollTo({ top: toTop ? 0 : e.scrollHeight });
|
||||
} else {
|
||||
e.scrollTop = toTop ? 0 : e.scrollHeight;
|
||||
}
|
||||
}
|
||||
nav.addEventListener('click', function (ev) {
|
||||
var b = ev.target.closest('[data-jump]');
|
||||
if (!b) return;
|
||||
ev.preventDefault();
|
||||
jump(b.dataset.jump === 'top');
|
||||
});
|
||||
window.addEventListener('resize', refresh);
|
||||
if (scroller !== window && scroller) scroller.addEventListener('input', refresh);
|
||||
refresh();
|
||||
})();
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="search"><input id="filter" placeholder="Search…"><span class="search-spinner" id="search-spinner"></span></div>
|
||||
<div class="float">
|
||||
<table>
|
||||
<colgroup><col class="col-a"><col class="col-b"><col class="col-c"><col class="col-d"><col class="col-e"><col class="col-f"><col class="col-g"></colgroup>
|
||||
<colgroup><col class="col-a"><col class="col-b"><col class="col-c"><col class="col-d"><col class="col-e"><col class="col-url"><col class="col-g"></colgroup>
|
||||
<thead><tr>
|
||||
<th data-sort="title" class="sortable">Paste<span class="sort-ind"></span></th>
|
||||
<th data-sort="type" class="sortable">Type<span class="sort-ind"></span></th>
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
<div class="spacer spacer-flex"></div>
|
||||
<button class="btn" id="create">Create</button>
|
||||
</div>
|
||||
<div class="jumpnav hidden" id="jumpnav" data-jump-scroll="#content">
|
||||
<button type="button" class="btn jump-btn" data-jump="top">Top</button>
|
||||
<button type="button" class="btn jump-btn" data-jump="bottom">Bottom</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pane-r">
|
||||
@@ -90,4 +94,5 @@
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/new.js" defer></script>
|
||||
<script src="/static/jump.js" defer></script>
|
||||
{{template "foot" .}}
|
||||
|
||||
@@ -55,8 +55,13 @@
|
||||
<div class="code" id="code"><div class="gutter" id="gutter">{{.Gutter}}</div><div class="codebody" id="codebody">{{.ContentHTML}}</div></div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="jumpnav hidden" id="jumpnav">
|
||||
<button type="button" class="btn jump-btn" data-jump="top">Top</button>
|
||||
<button type="button" class="btn jump-btn" data-jump="bottom">Bottom</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" id="raw-content" value="{{.ContentAttr}}">
|
||||
<script src="/static/paste.js" defer data-paste-id="{{.ID}}"></script>
|
||||
<script src="/static/paste-lines.js" defer></script>
|
||||
<script src="/static/jump.js" defer></script>
|
||||
{{template "foot" .}}
|
||||
|
||||
Reference in New Issue
Block a user