Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
62fbac6
Merge pull request #113 from Questionable-Content-Extensions/main
ilyvion Jul 6, 2026
b4d5f24
chore(deps-dev): bump esbuild from 0.18.20 to 0.28.1
dependabot[bot] Jul 6, 2026
3893eaf
fix: only send changed comic fields when saving advance comics
ilyvion Jul 7, 2026
4400945
feat: highlight current pagination page with a pill and dim only when…
ilyvion Jul 7, 2026
d01d90e
test: add coverage for FilteredComicsNavElement and label filter title
ilyvion Jul 7, 2026
cb35312
feat: default new advance comic id to latest published comic + 1
ilyvion Jul 7, 2026
fb8a9e2
test: silence passing tests
ilyvion Jul 7, 2026
d8ee518
feat: add setting to remember comic filter between page loads
ilyvion Jul 7, 2026
0981fdb
chore: remove hotfix release workflow in favor of patch releases
ilyvion Jul 7, 2026
e0459a7
chore(deps): bump lodash-es from 4.17.21 to 4.18.1
dependabot[bot] Jul 7, 2026
9b86de3
chore(deps-dev): bump shell-quote from 1.7.3 to 1.9.0
dependabot[bot] Jul 7, 2026
cfa6a26
chore(deps): bump @babel/runtime from 7.22.15 to 7.29.7
dependabot[bot] Jul 7, 2026
aa42c78
chore(deps): bump lodash from 4.17.21 to 4.18.1
dependabot[bot] Jul 7, 2026
41b6b20
Merge dependabot PRs into develop
ilyvion Jul 7, 2026
25a3fb5
chore: npm audit fix
ilyvion Jul 7, 2026
4c8b3c7
chore(deps): upgrade TypeScript to v6
ilyvion Jul 7, 2026
253f9e6
fix: prevent crash when item color is not yet synced to editor state
ilyvion Jul 7, 2026
25fd7b1
fix: prevent crash when item color is not yet synced to editor state
ilyvion Jul 7, 2026
0b908c0
fix: register Storybook mock service worker at deployed subpath in pr…
ilyvion Jul 7, 2026
6a65e88
fix(storybook): work around Rolldown bug and exclude userscript CSS p…
ilyvion Jul 7, 2026
38870b0
chore: prepare release 1.4.1
web-flow Jul 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 0 additions & 67 deletions .github/workflows/draft_new_hotfix.yml

This file was deleted.

15 changes: 3 additions & 12 deletions .github/workflows/publish_new_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,18 @@ jobs:
release:
name: Publish new release
runs-on: ubuntu-latest
# only merged pull requests that begin with 'release/' or 'hotfix/' must trigger this job
# only merged pull requests that begin with 'release/' must trigger this job
if: github.event.pull_request.merged == true &&
(startsWith(github.event.pull_request.head.ref, 'release/') || startsWith(github.event.pull_request.head.ref, 'hotfix/'))
startsWith(github.event.pull_request.head.ref, 'release/')

steps:
- name: Extract version from branch name (for release branches)
if: startsWith(github.event.pull_request.head.ref, 'release/')
- name: Extract version from branch name
run: |
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
VERSION=${BRANCH_NAME#release/}

echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV

- name: Extract version from branch name (for hotfix branches)
if: startsWith(github.event.pull_request.head.ref, 'hotfix/')
run: |
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
VERSION=${BRANCH_NAME#hotfix/}

echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV

- uses: actions/checkout@v7

- name: Use Node.js 24.x
Expand Down
113 changes: 105 additions & 8 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import { mergeConfig } from 'vite'
import { readdirSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { InlineConfig, mergeConfig } from 'vite'

import type { StorybookConfig } from '@storybook/react-vite'

const publicDir = join(dirname(fileURLToPath(import.meta.url)), '../public')

// Mirror `public/` into the Storybook build, minus `index.html` — that file
// is a dev-only placeholder page (served by `vite preview`), and copying it
// here would overwrite Storybook's own generated `index.html` in the build
// output. Reading the directory (rather than hardcoding names) keeps this in
// sync automatically as files are added to/removed from `public/`.
const staticDirs = readdirSync(publicDir)
.filter((name) => name !== 'index.html')
.map((name) => ({ from: join(publicDir, name), to: name }))

const config: StorybookConfig = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],

Expand All @@ -16,14 +30,97 @@ const config: StorybookConfig = {
options: {},
},

staticDirs: ['../public'],
staticDirs,

viteFinal: (config) =>
mergeConfig(config, {
resolve: {
tsconfigPaths: true,
},
}),
viteFinal: (config) => {
// Plugin entries can themselves be arrays (e.g. `@vitejs/plugin-react`
// and `vite-plugin-css-injected-by-js` each return one), so a
// shallow filter over `config.plugins` wouldn't see the plugins
// nested inside those - recurse into them instead.
const excludeCssInjectedByJs = (
plugins: typeof config.plugins
): typeof config.plugins =>
plugins
?.map((plugin) =>
Array.isArray(plugin)
? excludeCssInjectedByJs(plugin)
: plugin
)
.filter(
(plugin) =>
!(
plugin &&
!Array.isArray(plugin) &&
!(plugin instanceof Promise) &&
plugin.name?.startsWith(
'vite-plugin-css-injected-by-js'
)
)
)

return mergeConfig(
{
...config,
// The root vite.config.mts adds this plugin so the userscript
// build (a single injected <script>, which can't link a
// separate stylesheet) ships its CSS inline. Storybook is a
// normal web page and inherits this plugin only because it
// merges on top of that same root config. Unlike Vite's own
// CSS handling, this plugin concatenates collected CSS
// without hoisting `@import`/`@charset` to the top - which
// silently breaks any `@import` that isn't first in the
// combined output (a CSS spec requirement), so it must be
// excluded here.
plugins: excludeCssInjectedByJs(config.plugins),
} satisfies InlineConfig,
{
resolve: {
tsconfigPaths: true,
},
// The root vite.config.mts doesn't set `publicDir`, so it
// falls back to Vite's default of `public`. Storybook picks
// up that same config and, on build, copies the whole
// publicDir into its output dir *in addition to* `staticDirs`
// above — which used to overwrite Storybook's own generated
// `index.html` with `public/index.html` (a dev-only
// placeholder page). Disable it here since `staticDirs`
// already covers what Storybook needs from `public/`.
publicDir: false,
plugins: [
// Rolldown (the Rust bundler this project's Vite uses for
// production builds) mis-bundles `msw/lib/core/index.mjs`:
// that file imports `checkGlobals` from a sibling module
// and calls it at the top level purely for a side effect
// (a runtime assertion that `URL` exists). Across
// Storybook's per-story chunk graph, Rolldown ends up
// emitting the call in one chunk while dropping the
// module that defines it, throwing `checkGlobals is not
// defined` at runtime for every story that touches MSW
// (dev mode isn't affected — native ESM per file, no
// bundling). Inlining the one-line check directly into
// this file removes the cross-module reference that
// Rolldown mishandles.
{
name: 'fix-msw-checkglobals-bundling',
transform(code: string, id: string) {
if (!id.endsWith('msw/lib/core/index.mjs')) {
return null
}
return code
.replace(
"import { checkGlobals } from './utils/internal/checkGlobals.mjs';\n",
''
)
.replace(
'checkGlobals();',
"if (typeof URL === 'undefined') { throw new Error('[MSW] Global \"URL\" class is not defined.'); }"
)
},
},
],
} satisfies InlineConfig
)
},
}

export default config
6 changes: 6 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ setup()
const unhandled: string[] = []

mswInitialize({
serviceWorker: {
url:
process.env.NODE_ENV === 'production'
? '/client/storybook/mockServiceWorker.js'
: '/mockServiceWorker.js',
},
onUnhandledRequest(req, _print) {
const url = new URL(req.url)
if (
Expand Down
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.4.1] - 2026-07-07

### Added ✨

- Added a "Remember comic filter" setting (enabled by default) that restores the "Go to comic" dialog's active filter when the page reloads, and forgets it when disabled.

### Changed 🔧

- Highlight the current pagination page in the Edit Log dialog with a pill-shaped outline, and only dim it when the whole pagination control is disabled instead of whenever it isn't the active page.

## [1.4.0] - 2026-07-05

### Added ✨
Expand Down Expand Up @@ -400,7 +410,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Attempt to fix Travis build

[unreleased]: https://github.com/Questionable-Content-Extensions/client/compare/v1.4.0...HEAD
[unreleased]: https://github.com/Questionable-Content-Extensions/client/compare/v1.4.1...HEAD
[1.4.1]: https://github.com/Questionable-Content-Extensions/client/compare/v1.4.0...v1.4.1
[1.4.0]: https://github.com/Questionable-Content-Extensions/client/compare/1.3.0...v1.4.0
[1.3.0]: https://github.com/Questionable-Content-Extensions/client/compare/1.2.1...1.3.0
[1.2.1]: https://github.com/Questionable-Content-Extensions/client/compare/1.2.0...1.2.1
Expand Down
3 changes: 1 addition & 2 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
☐ Add a setting for remembering the filter between reloads
☐ Don't allow an editor to navigate away from a comic when the edit state is dirty before showing a confirmation dialog.
Loading
Loading