diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Cut text between characters, never inside one
The index description was cut at a byte count, which could split a
multibyte character and leave an invalid sequence on the page. Commit
subjects already backed up to the start of the character, so html_ntxt
now does that for every caller.
| -rw-r--r-- | source/html.c | 6 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/html.h | 5 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-shared.c | 8 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rwxr-xr-x | tests/t0101-index.sh | 14 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rwxr-xr-x | tests/t0103-log.sh | 10 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5 files changed, 34 insertions, 9 deletions
diff --git a/source/html.c b/source/html.c index 1a6b7c5..b6e62a6 100644 --- a/source/html.c +++ b/source/html.c @@ -247,6 +247,12 @@ ssize_t html_ntxt(const char *txt, size_t len) } p++; } + // A cut inside a multibyte character would leave an invalid sequence + // on the page, so it backs up to where that character starts. The + // escaped bytes are all ASCII, so no character spans one. + if (left < 0) + while (p > txt && (*p & 0xC0) == 0x80) + p--; if (p != txt) html_raw(txt, p - txt); return left; diff --git a/source/html.h b/source/html.h index 095804c..c6c0e19 100644 --- a/source/html.h +++ b/source/html.h @@ -55,8 +55,9 @@ extern void html_attrf(const char *format, ...); extern void html_txt(const char *txt); /* - * Escape at most len bytes of txt. The return is what is left of that budget, - * and a caller prints an ellipsis when it comes back negative. + * Escape at most len bytes of txt, cutting short of a character the budget + * would split. The return is what is left of that budget, and a caller prints + * an ellipsis when it comes back negative. */ extern ssize_t html_ntxt(const char *txt, size_t len); diff --git a/source/ui-shared.c b/source/ui-shared.c index 7d28c39..f3d815f 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -1039,13 +1039,7 @@ void cgit_commit_link(const char *name, const char *title, const char *class, html("'>"); if (name && name[0] != '\0') { if (ctx.cfg.max_msg_len >= MIN_TRUNCATE_LEN && strlen(name) > (size_t)ctx.cfg.max_msg_len) { - size_t len = ctx.cfg.max_msg_len - ELLIPSIS_LEN; - - // A cut inside a multibyte character would leave an - // invalid sequence on the page. - while (len > 0 && (name[len] & 0xC0) == 0x80) - len--; - html_ntxt(name, len); + html_ntxt(name, ctx.cfg.max_msg_len - ELLIPSIS_LEN); html("..."); } else { html_txt(name); diff --git a/tests/t0101-index.sh b/tests/t0101-index.sh index adad6be..e433beb 100755 --- a/tests/t0101-index.sh +++ b/tests/t0101-index.sh @@ -53,4 +53,18 @@ test_expect_success 'the feed link encodes the repository and the branch' ' grep "title=.Atom feed. href=.http://example.org/foo%2Bbar/atom/?h=1%2B2." tmp ' +# The description limit counts bytes, so a cut has to land between +# characters rather than leave half of one on the page. +test_expect_success 'a cut description keeps whole characters' ' + { + echo "max-repodesc-length=10" && + sed "s/^cache-size=.*/cache-size=0/" cgitrc && + echo "repo.url=mb" && + echo "repo.path=$PWD/repos/foo/.git" && + echo "repo.desc=日本語の説明文です" + } >descrc && + CGIT_CONFIG="$PWD/descrc" QUERY_STRING="url=" cgit >tmp && + grep ">日本語\.\.\.</a>" tmp +' + test_done diff --git a/tests/t0103-log.sh b/tests/t0103-log.sh index ed92a76..f9612e6 100755 --- a/tests/t0103-log.sh +++ b/tests/t0103-log.sh @@ -91,4 +91,14 @@ test_expect_success 'the pager of a followed log keeps the name followed' ' grep "href=./fol/log/b.txt?ofs=6&follow=1.>\[next\]" tmp ' +test_expect_success 'a cut subject keeps whole characters' ' + git -C repos/foo commit --allow-empty -m "日本語の説明文です日本語の説明文です" && + { + echo "max-message-length=20" && + sed "s/^cache-size=.*/cache-size=0/" cgitrc + } >subjectrc && + CGIT_CONFIG="$PWD/subjectrc" QUERY_STRING="url=foo/log/" cgit >tmp && + grep ">日本語の説\.\.\.</a>" tmp +' + test_done |
