Compare commits
5
Commits
v0.4.0
..
f94a813d79
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f94a813d79 | ||
|
|
ca785f5648 | ||
|
|
91757752b8 | ||
|
|
bb2c5e200c | ||
|
|
8474b8eb02 |
@@ -26,7 +26,10 @@ type Attachment struct {
|
||||
SizeHuman string `json:"-"` // template-only: human-readable size
|
||||
}
|
||||
|
||||
const MaxFilenameLen = 255
|
||||
// MaxFilenameLen caps stored attachment filenames (bytes) to bound DB
|
||||
// rows and Content-Disposition echoes. 128 keeps names readable while
|
||||
// stopping filename-bloat abuse; longer names truncate.
|
||||
const MaxFilenameLen = 128
|
||||
|
||||
// ErrFileTooLarge is returned when an attachment exceeds the per-file cap.
|
||||
var ErrFileTooLarge = errors.New("file too large")
|
||||
|
||||
@@ -105,4 +105,9 @@ func TestSanitizeFilename(t *testing.T) {
|
||||
if got := SanitizeFilename(long); len(got) != MaxFilenameLen {
|
||||
t.Errorf("long name len = %d want %d", len(got), MaxFilenameLen)
|
||||
}
|
||||
// issue #248: a 250-char multipart filename must truncate to the cap
|
||||
repro := strings.Repeat("b", 246) + ".txt"
|
||||
if got := SanitizeFilename(repro); len(got) != MaxFilenameLen {
|
||||
t.Errorf("repro name len = %d want %d", len(got), MaxFilenameLen)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if not .AttachmentImage}}
|
||||
{{if not .Attachment}}
|
||||
<div class="float">
|
||||
<div class="code" id="code"><div class="gutter" id="gutter">{{.Gutter}}</div><div class="codebody" id="codebody">{{.ContentHTML}}</div></div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user