fix: keep touch copy controls visible and pass POSIX lint

This commit is contained in:
2026-10-12 23:16:36 +08:00
parent 5798bf8900
commit be1e50fd54
5 changed files with 63 additions and 14 deletions
+12 -4
View File
@@ -10,14 +10,22 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
cache: npm
- run: npm ci
- name: Install shell test interpreters
run: sudo apt-get update && sudo apt-get install -y busybox shellcheck
run: |
if ! command -v busybox >/dev/null || ! command -v shellcheck >/dev/null; then
sudo apt-get update
sudo apt-get install -y busybox-static shellcheck
fi
busybox sh -c 'echo "BusyBox shell ready"'
shellcheck --version
- name: Run unit, shell, and real-browser tests
run: npm test
env:
@@ -29,7 +37,7 @@ jobs:
run: npx wrangler deploy --dry-run --config cf-worker/wrangler.toml --outdir /tmp/worker-dry-run
- name: Upload browser evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: browser-evidence
path: /tmp/quickly-browser-artifacts
+11 -3
View File
@@ -17,14 +17,22 @@ jobs:
timeout-minutes: 15
environment: production
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22'
cache: npm
- run: npm ci
- name: Install shell test interpreters
run: sudo apt-get update && sudo apt-get install -y busybox shellcheck
run: |
if ! command -v busybox >/dev/null || ! command -v shellcheck >/dev/null; then
sudo apt-get update
sudo apt-get install -y busybox-static shellcheck
fi
busybox sh -c 'echo "BusyBox shell ready"'
shellcheck --version
- run: npm test
env:
BROWSER_TESTS: '1'
+27 -7
View File
@@ -54,7 +54,11 @@ select_mode() {
}
while [ "$#" -gt 0 ]; do
case $1 in
-h|--help) [ "$#" -eq 1 ] && [ "$mode" = sync ] && [ "$cron_requested" = no ] || fail '--help must be used alone.'; usage; exit 0 ;;
-h|--help)
if [ "$#" -ne 1 ] || [ "$mode" != sync ] || [ "$cron_requested" != no ]; then
fail '--help must be used alone.'
fi
usage; exit 0 ;;
-o|--only-update-keys) select_mode keys ;;
-u|--update-self) select_mode update ;;
--uninstall) select_mode uninstall ;;
@@ -219,9 +223,13 @@ sha256() {
}
check_expected_file() {
if [ "$2" = absent ]; then
[ ! -e "$1" ] && [ ! -L "$1" ] || fail "File appeared concurrently; retry after reviewing: $1"
if [ -e "$1" ] || [ -L "$1" ]; then
fail "File appeared concurrently; retry after reviewing: $1"
fi
else
[ -f "$1" ] && cmp -s "$1" "$2" || fail "File changed concurrently; retry after reviewing: $1"
if [ ! -f "$1" ] || ! cmp -s "$1" "$2"; then
fail "File changed concurrently; retry after reviewing: $1"
fi
fi
}
replace_file() {
@@ -394,17 +402,29 @@ sync_keys() {
if [ "$positions" = absent ]; then
cat "$auth_snapshot" > "$new_auth"
if [ -s "$new_auth" ] && ! last_lf "$new_auth"; then printf '\n' >> "$new_auth"; fi
printf '%s\n' "$BEGIN_KEYS" >> "$new_auth"; cat "$payload" >> "$new_auth"; printf '%s\n' "$END_KEYS" >> "$new_auth"
{
printf '%s\n' "$BEGIN_KEYS"
cat "$payload"
printf '%s\n' "$END_KEYS"
} >> "$new_auth"
else
# Validated awk output: two decimal offsets.
# shellcheck disable=SC2086
set -- $positions
dd if="$auth_snapshot" bs=1 count="$1" 2>/dev/null > "$new_auth"
printf '%s\n' "$BEGIN_KEYS" >> "$new_auth"; cat "$payload" >> "$new_auth"; printf '%s\n' "$END_KEYS" >> "$new_auth"
dd if="$auth_snapshot" bs=1 skip="$2" 2>/dev/null >> "$new_auth"
{
printf '%s\n' "$BEGIN_KEYS"
cat "$payload"
printf '%s\n' "$END_KEYS"
dd if="$auth_snapshot" bs=1 skip="$2" 2>/dev/null
} >> "$new_auth"
fi
else
printf '%s\n' "$BEGIN_KEYS" > "$new_auth"; cat "$payload" >> "$new_auth"; printf '%s\n' "$END_KEYS" >> "$new_auth"
{
printf '%s\n' "$BEGIN_KEYS"
cat "$payload"
printf '%s\n' "$END_KEYS"
} > "$new_auth"
fi
check_path "$auth_file" file
check_expected_file "$auth_file" "$auth_snapshot"
+5
View File
@@ -165,6 +165,11 @@ dialog::backdrop { background: rgb(10 22 15 / 52%); }
.code-block > .copy-button { opacity: 0; transition: opacity 120ms ease; }
.code-block:hover > .copy-button, .code-block:focus-within > .copy-button, .code-block > .copy-button[data-state="success"] { opacity: 1; }
}
/* Keep copies discoverable on touch/hybrid devices and narrow layouts, even
when the browser reports a fine pointer or changes its emulated media. */
@media (hover: none), (pointer: coarse), (any-pointer: coarse), (max-width: 680px) {
.code-block > .copy-button { opacity: 1; transition: none; }
}
@media (max-width: 900px) {
.page-shell { width: calc(100% - 56px); }
.hero { grid-template-columns: 1fr 305px; gap: 36px; padding-block: 45px; }
+8
View File
@@ -223,3 +223,11 @@ test("CSS covers system theme, narrow viewports, touch copies, focus, and reduce
assert.match(css, /prefers-reduced-motion/);
assert.doesNotMatch(script, /innerHTML|insertAdjacentHTML|\beval\s*\(|\bfetch\s*\(/);
});
test("touch and narrow layouts explicitly override desktop copy-button hiding", () => {
const override = css.match(/@media \(hover: none\), \(pointer: coarse\), \(any-pointer: coarse\), \(max-width: 680px\) \{[\s\S]*?\n\}/);
assert.ok(override, "touch, hybrid, and narrow layouts need an explicit visibility rule");
assert.match(override[0], /\.code-block > \.copy-button \{ opacity: 1; transition: none; \}/);
assert.ok(override.index > css.indexOf("@media (hover: hover) and (pointer: fine)"), "touch visibility must win the CSS cascade");
});