From 1bc2c5c7f29c733de0f6bc417e726f56b2a1de93 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Sun, 10 May 2026 22:31:53 +0200 Subject: [PATCH] Release v0.2.10 --- .claude/worktrees/admiring-noether-621bfe | 1 + .codex | 0 build-and-push.sh | 93 ++++++++++++++++++++--- containers/novela/changelog.py | 14 ++++ containers/novela/templates/reader.html | 4 +- docs/changelog-develop.md | 10 +++ docs/changelog.md | 8 ++ 7 files changed, 119 insertions(+), 11 deletions(-) create mode 160000 .claude/worktrees/admiring-noether-621bfe create mode 100644 .codex diff --git a/.claude/worktrees/admiring-noether-621bfe b/.claude/worktrees/admiring-noether-621bfe new file mode 160000 index 0000000..6083744 --- /dev/null +++ b/.claude/worktrees/admiring-noether-621bfe @@ -0,0 +1 @@ +Subproject commit 6083744b3f3e7b5ec52f5f7b935f1d7e06b97a1d diff --git a/.codex b/.codex new file mode 100644 index 0000000..e69de29 diff --git a/build-and-push.sh b/build-and-push.sh index 6b4be0e..c785c26 100755 --- a/build-and-push.sh +++ b/build-and-push.sh @@ -8,10 +8,9 @@ set -euo pipefail # - Build & push Docker images for each service under ./containers/* # - Two modes: # t (test) = only push :dev -# r (release) = push :, :dev, :latest -# version is read from the top of changelog.md -# -# No git operations: committing and tagging is done manually. +# r (release) = push :, :dev, :latest, then commit + tag and +# push a release/ branch + tag to origin. +# Version is read from the top of changelog.md. # # Usage: # ./build-and-push.sh [mode] @@ -25,14 +24,67 @@ set -euo pipefail # ## vX.Y.Z — YYYY-MM-DD # (the version is parsed from the first such line) # - One Dockerfile per service under ./containers//Dockerfile +# +# ---------------------------------------------------------------------------- +# Self-update notice (for humans AND for Claude): +# +# The canonical/master copy of this script lives at: +# /docker/develop/shared-integrations/tooling/docker-build-and-push/build-and-push.sh +# +# When this script is copied into a project repo, it may drift from master. +# On startup the script compares its own SCRIPT_VERSION to the master copy and +# warns if a newer version exists. It does NOT auto-overwrite (too risky during +# a release run). +# +# CLAUDE INSTRUCTION: +# If you (Claude) are about to invoke this script in a project repo, first +# check whether the master copy at the path above is newer (different +# SCRIPT_VERSION or differing file contents). If so, copy the master over +# the local copy BEFORE running, then proceed. Mention the update to the user. # ============================================================================ +SCRIPT_VERSION="1.2.0" +SCRIPT_MASTER_PATH="/docker/develop/shared-integrations/tooling/docker-build-and-push/build-and-push.sh" + DOCKER_REGISTRY="gitea.oskamp.info" DOCKER_NAMESPACE="ivooskamp" CHANGELOG_FILE="docs/changelog.md" CONTAINERS_DIR="containers" +# --- Self-update check ------------------------------------------------------- +# Compare this script to the canonical master copy and warn (don't overwrite). +self_update_check() { + local self_path="${BASH_SOURCE[0]}" + # Resolve to absolute path so a comparison against itself is detected. + local self_abs + self_abs="$(cd "$(dirname "$self_path")" 2>/dev/null && pwd)/$(basename "$self_path")" || self_abs="$self_path" + + if [[ "$self_abs" == "$SCRIPT_MASTER_PATH" ]]; then + return 0 # We ARE the master copy. + fi + if [[ ! -f "$SCRIPT_MASTER_PATH" ]]; then + return 0 # Master not reachable from this host; silently skip. + fi + + local master_version + master_version="$(grep -m1 -E '^SCRIPT_VERSION=' "$SCRIPT_MASTER_PATH" | sed -E 's/.*"([^"]+)".*/\1/')" + + if [[ -n "$master_version" && "$master_version" != "$SCRIPT_VERSION" ]]; then + echo "[WARN] A newer build-and-push.sh is available." + echo " local : $SCRIPT_VERSION" + echo " master : $master_version ($SCRIPT_MASTER_PATH)" + echo " Update with: cp \"$SCRIPT_MASTER_PATH\" \"$self_abs\"" + echo "" + elif ! cmp -s "$self_abs" "$SCRIPT_MASTER_PATH"; then + echo "[WARN] Local build-and-push.sh differs from master (same SCRIPT_VERSION=$SCRIPT_VERSION)." + echo " master : $SCRIPT_MASTER_PATH" + echo " Diff or update with: cp \"$SCRIPT_MASTER_PATH\" \"$self_abs\"" + echo "" + fi +} +self_update_check + # --- Input: prompt if missing ------------------------------------------------ MODE="${1:-}" if [[ -z "${MODE}" ]]; then @@ -227,10 +279,33 @@ for img in "${BUILT_IMAGES[@]}"; do done echo "============================================================" echo "" -echo "[REMINDER] No git operations were performed. If this was a release," -echo " commit and tag manually, e.g.:" + +# --- Git: commit + release branch + tag (release mode only) ----------------- if [[ "$MODE" == "r" ]]; then - echo " git add -A && git commit -m \"Release ${VERSION}\"" - echo " git tag -a ${VERSION} -m \"Release ${VERSION}\"" - echo " git push && git push --tags" + if [[ ! -d ".git" ]]; then + echo "[WARN] Not a git checkout — skipping git commit/tag/push." + exit 0 + fi + + RELEASE_BRANCH="release/${VERSION}" + echo "[INFO] Preparing git release: branch=${RELEASE_BRANCH}, tag=${VERSION}" + + # Stage everything and commit only if there's something to commit. + git add -A + if git diff --cached --quiet; then + echo "[INFO] Working tree clean — no commit needed." + else + git commit -m "Release ${VERSION}" + fi + + # Create or move the annotated tag to current HEAD. + if git rev-parse -q --verify "refs/tags/${VERSION}" >/dev/null; then + echo "[WARN] Tag ${VERSION} already exists locally — leaving it as-is." + else + git tag -a "${VERSION}" -m "Release ${VERSION}" + fi + + git push origin "HEAD:refs/heads/${RELEASE_BRANCH}" + git push origin "refs/tags/${VERSION}" + echo "[INFO] Pushed ${RELEASE_BRANCH} and tag ${VERSION} to origin." fi diff --git a/containers/novela/changelog.py b/containers/novela/changelog.py index 9ecb9eb..7e573fc 100644 --- a/containers/novela/changelog.py +++ b/containers/novela/changelog.py @@ -3,6 +3,20 @@ Changelog data for Novela """ CHANGELOG = [ + { + "version": "v0.2.10", + "date": "2026-05-10", + "summary": "Subheading and chat styling now also renders when the wrapper is a
instead of a (e.g. when applied around or inside a heading).", + "sections": [ + { + "title": "Bug fixes", + "type": "bugfix", + "changes": [ + "Editor / Reader: subheading (S) and chat (C) styling now also applies when the wrapper is a
instead of a . wrapSpan() in editor.js falls back to
whenever the selection contains a block element (e.g. ,

,

) to keep the HTML valid; the previous CSS in reader.html only matched the form, so anything wrapped around or inside a heading silently lost its color/weight. CSS selectors are now class-only (#chapter-content .subheading / .chat), matching both span and div wrappers.", + ], + }, + ], + }, { "version": "v0.2.9", "date": "2026-05-09", diff --git a/containers/novela/templates/reader.html b/containers/novela/templates/reader.html index 621ba81..34fca6d 100644 --- a/containers/novela/templates/reader.html +++ b/containers/novela/templates/reader.html @@ -219,8 +219,8 @@ margin-bottom: 2.5rem; padding-bottom: 1rem; border-bottom: 1px solid var(--border); } - #chapter-content span.subheading { color: rgb(224, 62, 45); font-weight: bold; } - #chapter-content span.chat { color: rgb(230, 126, 35); } + #chapter-content .subheading { color: rgb(224, 62, 45); font-weight: bold; } + #chapter-content .chat { color: rgb(230, 126, 35); } #chapter-content p[style*="padding-left"] { padding-left: 40px; } #chapter-content .novela-comment { border-left: 3px solid #6b9dd6; diff --git a/docs/changelog-develop.md b/docs/changelog-develop.md index 1f86e9e..64a8d05 100644 --- a/docs/changelog-develop.md +++ b/docs/changelog-develop.md @@ -1,5 +1,14 @@ # Develop Changelog +*Released as v0.2.10 on 2026-05-10* + +## 2026-05-09 (2) +- Editor / Reader: subheading (**S**) and chat (**C**) styling now also applies when the wrapper is a `
` instead of a `` + - `wrapSpan()` in `editor.js` falls back to `
` whenever the selection contains a block element (``, `

`, `

`, etc.) so the resulting HTML stays valid; the previous CSS in `reader.html` (`#chapter-content span.subheading` / `span.chat`) only matched the `` form, so anything wrapped around or inside a heading silently lost its color/weight + - CSS selectors are now class-only (`#chapter-content .subheading` / `.chat`), matching both span and div wrappers + +--- + ## 2026-05-09 - Reader: progress is now monotonic across devices — saved position only advances, never rewinds - `POST /library/progress/{filename}` in `routers/reader.py` parses the incoming `cfi` as `(chapterIndex, scrollFrac)` and the currently stored row the same way, then skips the write when `new_pos <= cur_pos` @@ -8,6 +17,7 @@ - Reason: when reading the same book on device A (chapter 12) and then continuing on device B (chapter 15), opening device A again previously sent its stale chapter-12 cfi back to the server and overwrote the further progress; now the older position is ignored --- +*Released as v0.2.9 on 2026-05-09* ## 2026-04-22 (5) - Grabber: newly converted books now appear in the **New** view again diff --git a/docs/changelog.md b/docs/changelog.md index e126e93..89c7d4e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,13 @@ # Changelog +## v0.2.10 — 2026-05-10 + +### Bug fixes + +- Editor / Reader: subheading (**S**) and chat (**C**) styling now also renders correctly when the wrapper is a `
` instead of a ``. When the selection contained a block element (e.g. an ``, `

` or `

`), `wrapSpan()` in `editor.js` falls back to `
` to keep the HTML valid; the previous CSS in `reader.html` only targeted `span.subheading` / `span.chat`, so anything wrapped around or inside a heading silently lost its color/weight. CSS selectors are now class-only (`#chapter-content .subheading` / `.chat`), matching both span and div wrappers. + +--- + ## v0.2.9 — 2026-05-09 ### Bug fixes