280 Commits

Author SHA1 Message Date
Sped0n
758a2d1a62 ci: update bundled artifacts [skip ci] 2026-03-22 13:16:08 +00:00
Ryan
ec1df7f070 Merge pull request #612 from Sped0n/vite-8
build(deps-dev): migrate to vite 8
2026-03-22 21:15:44 +08:00
Sped0n
f09988f32d build(deps-dev): migrate to vite 8
Signed-off-by: Sped0n <hi@sped0n.com>
2026-03-22 21:13:40 +08:00
Ryan
e16aaca42b Merge pull request #596 from Sped0n/dependabot/npm_and_yarn/eslint-config-love-151.0.0
build(deps-dev): bump eslint-config-love from 149.0.0 to 151.0.0
2026-03-22 20:34:26 +08:00
dependabot[bot]
80442eb569 build(deps-dev): bump eslint-config-love from 149.0.0 to 151.0.0
Bumps [eslint-config-love](https://github.com/mightyiam/eslint-config-love) from 149.0.0 to 151.0.0.
- [Release notes](https://github.com/mightyiam/eslint-config-love/releases)
- [Changelog](https://github.com/mightyiam/eslint-config-love/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mightyiam/eslint-config-love/compare/v149.0.0...v151.0.0)

---
updated-dependencies:
- dependency-name: eslint-config-love
  dependency-version: 151.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-22 12:33:58 +00:00
Ryan
9039e04b38 Merge pull request #609 from Sped0n/dependabot/npm_and_yarn/typescript-eslint-8.57.1
build(deps-dev): bump typescript-eslint from 8.53.1 to 8.57.1
2026-03-22 20:32:47 +08:00
dependabot[bot]
56304e09f1 build(deps-dev): bump typescript-eslint from 8.53.1 to 8.57.1
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.53.1 to 8.57.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.57.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-22 12:32:15 +00:00
Ryan
0cbaacbc0e Merge pull request #610 from Sped0n/dependabot/npm_and_yarn/typescript-eslint/parser-8.57.1
build(deps-dev): bump @typescript-eslint/parser from 8.53.1 to 8.57.1
2026-03-22 20:31:25 +08:00
dependabot[bot]
f78449adb9 build(deps-dev): bump @typescript-eslint/parser from 8.53.1 to 8.57.1
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.53.1 to 8.57.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.57.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-22 12:30:32 +00:00
Ryan
4d55bca248 Merge pull request #604 from Sped0n/dependabot/npm_and_yarn/eslint/js-9.39.4
build(deps-dev): bump @eslint/js from 9.39.2 to 9.39.4
2026-03-22 20:30:00 +08:00
dependabot[bot]
ad998ba153 build(deps-dev): bump @eslint/js from 9.39.2 to 9.39.4
Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.39.2 to 9.39.4.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/commits/v9.39.4/packages/js)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.39.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-22 12:29:25 +00:00
Ryan
bd95ab861b Merge pull request #606 from Sped0n/dependabot/npm_and_yarn/vite-plugin-solid-2.11.11
build(deps-dev): bump vite-plugin-solid from 2.11.10 to 2.11.11
2026-03-22 20:28:20 +08:00
dependabot[bot]
919489c7e9 build(deps-dev): bump vite-plugin-solid from 2.11.10 to 2.11.11
Bumps [vite-plugin-solid](https://github.com/solidjs/vite-plugin-solid) from 2.11.10 to 2.11.11.
- [Release notes](https://github.com/solidjs/vite-plugin-solid/releases)
- [Changelog](https://github.com/solidjs/vite-plugin-solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/vite-plugin-solid/compare/vite-plugin-solid@2.11.10...vite-plugin-solid@2.11.11)

---
updated-dependencies:
- dependency-name: vite-plugin-solid
  dependency-version: 2.11.11
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-22 12:27:47 +00:00
Ryan
efa72bb763 Merge pull request #608 from Sped0n/dependabot/npm_and_yarn/types/node-25.5.0
build(deps-dev): bump @types/node from 25.0.10 to 25.5.0
2026-03-22 20:27:08 +08:00
dependabot[bot]
90f79113c7 build(deps-dev): bump @types/node from 25.0.10 to 25.5.0
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 25.0.10 to 25.5.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-22 12:26:40 +00:00
Ryan
b5d0754c45 Merge pull request #607 from Sped0n/dependabot/npm_and_yarn/sass-embedded-1.98.0
build(deps-dev): bump sass-embedded from 1.97.3 to 1.98.0
2026-03-22 20:25:20 +08:00
dependabot[bot]
8a751b7437 build(deps-dev): bump sass-embedded from 1.97.3 to 1.98.0
Bumps [sass-embedded](https://github.com/sass/embedded-host-node) from 1.97.3 to 1.98.0.
- [Changelog](https://github.com/sass/embedded-host-node/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/embedded-host-node/compare/1.97.3...1.98.0)

---
updated-dependencies:
- dependency-name: sass-embedded
  dependency-version: 1.98.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-22 12:24:52 +00:00
Sped0n
212dca53e8 ci: update bundled artifacts [skip ci] 2026-03-22 12:17:14 +00:00
Ryan
989a7f4951 Merge pull request #611 from Sped0n/fix-432
Fix 432
2026-03-22 20:16:50 +08:00
Sped0n
f25b71a858 refactor: split monolithic state into context-based modules
Extract image, desktop, mobile, and config state into separate context
providers to improve modularity and reduce unnecessary re-renders.

Signed-off-by: Sped0n <hi@sped0n.com>
2026-03-22 19:45:05 +08:00
Sped0n
1c386386f3 refactor: extract image reveal logic and improve GSAP loading reliability
Signed-off-by: Sped0n <hi@sped0n.com>
2026-03-22 17:30:41 +08:00
Sped0n
797b59a38a fix: improve mobile device detection reliability
Signed-off-by: Sped0n <hi@sped0n.com>
2026-03-22 17:29:11 +08:00
Sped0n
dbbc063353 ci: update bundled artifacts [skip ci] 2026-02-22 19:34:18 +00:00
Ryan
f7e87c3c15 Merge pull request #595 from Sped0n/dependabot/npm_and_yarn/swiper-12.1.2 2026-02-23 03:33:56 +08:00
dependabot[bot]
1242146140 build(deps): bump swiper from 12.1.1 to 12.1.2
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 12.1.1 to 12.1.2.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v12.1.1...v12.1.2)

---
updated-dependencies:
- dependency-name: swiper
  dependency-version: 12.1.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-20 21:55:28 +00:00
Sped0n
a8c1f948db ci: update bundled artifacts [skip ci] 2026-02-17 20:05:08 +00:00
Ryan
dc30a8cd16 Merge pull request #594 from Sped0n/dependabot/npm_and_yarn/swiper-12.1.1 2026-02-18 04:04:43 +08:00
dependabot[bot]
71c7b02c1d build(deps): bump swiper from 12.1.0 to 12.1.1
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 12.1.0 to 12.1.1.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v12.1.0...v12.1.1)

---
updated-dependencies:
- dependency-name: swiper
  dependency-version: 12.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 23:34:24 +00:00
Ryan
6cfcfb272a Merge pull request #583 from Sped0n/dependabot/npm_and_yarn/eslint-config-love-149.0.0 2026-02-12 02:08:27 +08:00
dependabot[bot]
c239112cb2 build(deps-dev): bump eslint-config-love from 147.0.0 to 149.0.0
Bumps [eslint-config-love](https://github.com/mightyiam/eslint-config-love) from 147.0.0 to 149.0.0.
- [Release notes](https://github.com/mightyiam/eslint-config-love/releases)
- [Changelog](https://github.com/mightyiam/eslint-config-love/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mightyiam/eslint-config-love/compare/v147.0.0...v149.0.0)

---
updated-dependencies:
- dependency-name: eslint-config-love
  dependency-version: 149.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-03 20:30:02 +00:00
Sped0n
637391bb34 ci: update bundled artifacts [skip ci] 2026-02-03 20:29:01 +00:00
Ryan
fe38e1289a Merge pull request #584 from Sped0n/dependabot/npm_and_yarn/swiper-12.1.0
build(deps): bump swiper from 12.0.3 to 12.1.0
2026-02-04 04:28:37 +08:00
dependabot[bot]
08bd9a76ef build(deps): bump swiper from 12.0.3 to 12.1.0
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 12.0.3 to 12.1.0.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v12.0.3...v12.1.0)

---
updated-dependencies:
- dependency-name: swiper
  dependency-version: 12.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-03 20:25:47 +00:00
Ryan
14f481b2c0 Merge pull request #586 from Sped0n/fix-bundle
build(ci): add pre-build cleanup for bundled directory
2026-02-04 04:23:40 +08:00
Sped0n
546791e90b ci: add pre-build cleanup step for artifact updates
Add a cleanup step to remove the bundled directory before building when
running the latest Hugo version on push or merged PR events. This ensures
old or unused JavaScript files are not included in the updated artifacts.

Signed-off-by: Sped0n <hi@sped0n.com>
2026-02-04 04:22:40 +08:00
Ryan
136c2303f9 Merge pull request #577 from Sped0n/dependabot/npm_and_yarn/sass-embedded-1.97.3
build(deps-dev): bump sass-embedded from 1.97.2 to 1.97.3
2026-01-31 18:12:11 +08:00
dependabot[bot]
b13f1bf454 build(deps-dev): bump sass-embedded from 1.97.2 to 1.97.3
Bumps [sass-embedded](https://github.com/sass/embedded-host-node) from 1.97.2 to 1.97.3.
- [Changelog](https://github.com/sass/embedded-host-node/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/embedded-host-node/compare/1.97.2...1.97.3)

---
updated-dependencies:
- dependency-name: sass-embedded
  dependency-version: 1.97.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-31 10:11:41 +00:00
Ryan
313a6f294a Merge pull request #580 from Sped0n/dependabot/npm_and_yarn/prettier-3.8.1
build(deps-dev): bump prettier from 3.8.0 to 3.8.1
2026-01-31 18:10:25 +08:00
dependabot[bot]
2804be174d build(deps-dev): bump prettier from 3.8.0 to 3.8.1
Bumps [prettier](https://github.com/prettier/prettier) from 3.8.0 to 3.8.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.0...3.8.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.8.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-31 10:07:58 +00:00
Ryan
fec976ad9e Merge pull request #582 from Sped0n/update-flake-and-codeql
Update flake and codeql
2026-01-31 18:04:22 +08:00
Sped0n
582433874c ci: update CodeQL action
Bumps checkout to v6 and codeql-action to v3

Signed-off-by: Sped0n <hi@sped0n.com>
2026-01-31 18:03:43 +08:00
Sped0n
037cdbd679 build(deps): bump nixpkgs from 891611 to 935279
Bumps nixpkgs flake input (https://github.com/NixOS/nixpkgs) from
revision b6a8526db03f735b89dd5ff348f53f752e7ddc8e (891611) to
bfc1b8a4574108ceef22f02bafcf6611380c100d (935279).

Signed-off-by: Sped0n <hi@sped0n.com>
2026-01-31 18:03:43 +08:00
Ryan
50ff7f62bb Merge pull request #581 from Sped0n/update-ci
ci: migrate workflows to mise-action and update actions
2026-01-31 17:50:43 +08:00
Sped0n
3fe8477646 ci: migrate workflows to mise-action and update actions
Signed-off-by: Sped0n <hi@sped0n.com>
2026-01-31 17:41:57 +08:00
Ryan
64b43597a4 Merge pull request #578 from Sped0n/dependabot/npm_and_yarn/solid-js-1.9.11 2026-01-28 15:41:34 +08:00
dependabot[bot]
94603999d7 build(deps): bump solid-js from 1.9.10 to 1.9.11
Bumps [solid-js](https://github.com/solidjs/solid) from 1.9.10 to 1.9.11.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/commits)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-version: 1.9.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-27 00:36:06 +00:00
Ryan
c3c42e4aca Merge pull request #573 from Sped0n/dependabot/npm_and_yarn/types/node-25.0.9 2026-01-24 03:54:26 +08:00
dependabot[bot]
38f4895233 build(deps-dev): bump @types/node from 25.0.3 to 25.0.9
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 25.0.3 to 25.0.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.0.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-23 19:50:16 +00:00
Ryan
636fea3496 Merge pull request #575 from Sped0n/dependabot/npm_and_yarn/eslint-plugin-prettier-5.5.5 2026-01-24 03:48:51 +08:00
dependabot[bot]
c15b8a3e46 build(deps-dev): bump eslint-plugin-prettier from 5.5.4 to 5.5.5
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.5.4 to 5.5.5.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.4...v5.5.5)

---
updated-dependencies:
- dependency-name: eslint-plugin-prettier
  dependency-version: 5.5.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-23 19:44:50 +00:00
Ryan
0cd891d16b Merge pull request #571 from Sped0n/dependabot/npm_and_yarn/typescript-eslint/parser-8.53.1 2026-01-24 03:43:32 +08:00
dependabot[bot]
4670c00157 build(deps-dev): bump @typescript-eslint/parser from 8.52.0 to 8.53.1
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.52.0 to 8.53.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.53.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.53.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-23 19:39:18 +00:00
Ryan
032a75f581 Merge pull request #570 from Sped0n/dependabot/npm_and_yarn/typescript-eslint-8.53.1 2026-01-24 03:37:59 +08:00
dependabot[bot]
5e40e9041e build(deps-dev): bump typescript-eslint from 8.53.0 to 8.53.1
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.53.0 to 8.53.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.53.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.53.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-23 19:33:44 +00:00
Ryan
9c7731b8e5 Merge pull request #574 from Sped0n/dependabot/npm_and_yarn/eslint-config-love-145.0.0 2026-01-24 03:32:43 +08:00
dependabot[bot]
d59475fbdc build(deps-dev): bump eslint-config-love from 140.0.0 to 145.0.0
Bumps [eslint-config-love](https://github.com/mightyiam/eslint-config-love) from 140.0.0 to 145.0.0.
- [Release notes](https://github.com/mightyiam/eslint-config-love/releases)
- [Changelog](https://github.com/mightyiam/eslint-config-love/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mightyiam/eslint-config-love/compare/v140.0.0...v145.0.0)

---
updated-dependencies:
- dependency-name: eslint-config-love
  dependency-version: 145.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-23 19:28:38 +00:00
Ryan
27c3b754ac Merge pull request #572 from Sped0n/dependabot/npm_and_yarn/prettier-3.8.0 2026-01-24 03:26:53 +08:00
dependabot[bot]
1359adee59 build(deps-dev): bump prettier from 3.7.4 to 3.8.0
Bumps [prettier](https://github.com/prettier/prettier) from 3.7.4 to 3.8.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.7.4...3.8.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-20 00:06:53 +00:00
Ryan
b8d7193fb9 Merge pull request #566 from Sped0n/dependabot/npm_and_yarn/typescript-eslint-8.53.0 2026-01-18 14:00:28 +08:00
dependabot[bot]
a06027401b build(deps-dev): bump typescript-eslint from 8.52.0 to 8.53.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.52.0 to 8.53.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.53.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.53.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-13 03:46:44 +00:00
Ryan
5501d10cd0 Merge pull request #564 from Sped0n/dependabot/npm_and_yarn/vite-7.3.1 2026-01-09 22:31:06 +08:00
dependabot[bot]
31e20f752a build(deps-dev): bump vite from 7.3.0 to 7.3.1
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.3.0 to 7.3.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.1/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-09 14:26:53 +00:00
Ryan
fd300d8104 Merge pull request #565 from Sped0n/dependabot/npm_and_yarn/sass-embedded-1.97.2 2026-01-08 18:43:00 +08:00
dependabot[bot]
e91a7c6633 build(deps-dev): bump sass-embedded from 1.97.1 to 1.97.2
Bumps [sass-embedded](https://github.com/sass/embedded-host-node) from 1.97.1 to 1.97.2.
- [Changelog](https://github.com/sass/embedded-host-node/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/embedded-host-node/compare/1.97.1...1.97.2)

---
updated-dependencies:
- dependency-name: sass-embedded
  dependency-version: 1.97.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-07 16:56:59 +00:00
Ryan
321e4b618a Merge pull request #562 from Sped0n/dependabot/npm_and_yarn/typescript-eslint/parser-8.52.0 2026-01-07 18:45:19 +08:00
dependabot[bot]
f630b85669 build(deps-dev): bump @typescript-eslint/parser from 8.51.0 to 8.52.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.51.0 to 8.52.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.52.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.52.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-07 10:40:59 +00:00
Ryan
a431d74e8c Merge pull request #563 from Sped0n/dependabot/npm_and_yarn/typescript-eslint-8.52.0 2026-01-07 03:49:05 +08:00
dependabot[bot]
975e084ea8 build(deps-dev): bump typescript-eslint from 8.51.0 to 8.52.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.51.0 to 8.52.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.52.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.52.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-05 23:05:28 +00:00
Ryan
771b9b34ab Merge pull request #561 from Sped0n/dependabot/npm_and_yarn/typescript-eslint/parser-8.51.0 2025-12-30 13:11:39 +08:00
dependabot[bot]
1e5155c49e build(deps-dev): bump @typescript-eslint/parser from 8.50.1 to 8.51.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.50.1 to 8.51.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.51.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 05:07:27 +00:00
Ryan
44750037f3 Merge pull request #560 from Sped0n/dependabot/npm_and_yarn/typescript-eslint-8.51.0 2025-12-30 13:06:04 +08:00
dependabot[bot]
9af0090644 build(deps-dev): bump typescript-eslint from 8.49.0 to 8.51.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.49.0 to 8.51.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.51.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 03:20:49 +00:00
Ryan
b05eec64cb Merge pull request #558 from Sped0n/dependabot/npm_and_yarn/eslint-config-love-140.0.0 2025-12-30 11:09:43 +08:00
dependabot[bot]
284cfa4e84 build(deps-dev): bump eslint-config-love from 136.0.0 to 140.0.0
Bumps [eslint-config-love](https://github.com/mightyiam/eslint-config-love) from 136.0.0 to 140.0.0.
- [Release notes](https://github.com/mightyiam/eslint-config-love/releases)
- [Changelog](https://github.com/mightyiam/eslint-config-love/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mightyiam/eslint-config-love/compare/v136.0.0...v140.0.0)

---
updated-dependencies:
- dependency-name: eslint-config-love
  dependency-version: 140.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 03:05:34 +00:00
Ryan
11ea5c101b Merge pull request #557 from Sped0n/dependabot/npm_and_yarn/types/node-25.0.3 2025-12-30 11:04:28 +08:00
dependabot[bot]
d4b9a4588a build(deps-dev): bump @types/node from 24.10.2 to 25.0.3
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.10.2 to 25.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 03:00:19 +00:00
Ryan
4ed332314d Merge pull request #549 from Sped0n/dependabot/npm_and_yarn/eslint-9.39.2 2025-12-30 10:58:59 +08:00
dependabot[bot]
82ab5b996f build(deps-dev): bump eslint from 9.39.1 to 9.39.2
Bumps [eslint](https://github.com/eslint/eslint) from 9.39.1 to 9.39.2.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.39.1...v9.39.2)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.39.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 02:54:52 +00:00
Ryan
81c14d9f2b Merge pull request #556 from Sped0n/dependabot/npm_and_yarn/sass-embedded-1.97.1 2025-12-30 10:53:48 +08:00
dependabot[bot]
7cf5f9ad2d build(deps-dev): bump sass-embedded from 1.93.3 to 1.97.1
Bumps [sass-embedded](https://github.com/sass/embedded-host-node) from 1.93.3 to 1.97.1.
- [Changelog](https://github.com/sass/embedded-host-node/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/embedded-host-node/compare/1.93.3...1.97.1)

---
updated-dependencies:
- dependency-name: sass-embedded
  dependency-version: 1.97.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 02:49:39 +00:00
Ryan
0f69ec5f96 Merge pull request #546 from Sped0n/dependabot/npm_and_yarn/eslint/js-9.39.2 2025-12-30 10:13:08 +08:00
dependabot[bot]
e6a9cacfef build(deps-dev): bump @eslint/js from 9.39.1 to 9.39.2
Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.39.1 to 9.39.2.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/commits/v9.39.2/packages/js)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.39.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 02:09:03 +00:00
Ryan
b24e401a28 Merge pull request #559 from Sped0n/dependabot/npm_and_yarn/typescript-eslint/parser-8.50.1 2025-12-23 13:15:33 +08:00
dependabot[bot]
ca9fef6c2d build(deps-dev): bump @typescript-eslint/parser from 8.49.0 to 8.50.1
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.49.0 to 8.50.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.50.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.50.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 23:05:03 +00:00
Ryan
2835d46a57 Merge pull request #554 from Sped0n/dependabot/npm_and_yarn/vite-7.3.0 2025-12-23 03:22:07 +08:00
dependabot[bot]
3779bc7ce6 build(deps-dev): bump vite from 7.2.7 to 7.3.0
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.2.7 to 7.3.0.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.0/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-16 12:38:14 +00:00
Sped0n
de16c6b443 ci: update bundled artifacts [skip ci] 2025-12-16 01:50:14 +00:00
Ryan
d536303f8e Merge pull request #547 from Sped0n/dependabot/npm_and_yarn/gsap-3.14.2 2025-12-16 09:49:41 +08:00
dependabot[bot]
76d420c2c9 build(deps): bump gsap from 3.14.1 to 3.14.2
Bumps [gsap](https://github.com/greensock/GSAP) from 3.14.1 to 3.14.2.
- [Commits](https://github.com/greensock/GSAP/compare/3.14.1...3.14.2)

---
updated-dependencies:
- dependency-name: gsap
  dependency-version: 3.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 23:05:55 +00:00
Ryan
c448648127 Merge pull request #542 from Sped0n/dependabot/npm_and_yarn/typescript-eslint-8.49.0 2025-12-12 22:55:30 +08:00
dependabot[bot]
7e0e6244b0 build(deps-dev): bump typescript-eslint from 8.48.0 to 8.49.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.48.0 to 8.49.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.49.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.49.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 09:45:18 +00:00
Ryan
c76835d474 Merge pull request #544 from Sped0n/dependabot/npm_and_yarn/typescript-eslint/parser-8.49.0 2025-12-09 17:08:25 +08:00
dependabot[bot]
39c13e242d build(deps-dev): bump @typescript-eslint/parser from 8.48.0 to 8.49.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.48.0 to 8.49.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.49.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.49.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 09:07:44 +00:00
Ryan
61c86692ee Merge pull request #543 from Sped0n/dependabot/npm_and_yarn/types/node-24.10.2 2025-12-09 16:08:59 +08:00
dependabot[bot]
cd63e9fec5 build(deps-dev): bump @types/node from 24.10.1 to 24.10.2
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.10.1 to 24.10.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.10.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 08:08:21 +00:00
Ryan
8bc8fded81 Merge pull request #541 from Sped0n/dependabot/npm_and_yarn/eslint-config-love-136.0.0 2025-12-09 16:07:53 +08:00
dependabot[bot]
8bc54835e5 build(deps-dev): bump eslint-config-love from 133.0.0 to 136.0.0
Bumps [eslint-config-love](https://github.com/mightyiam/eslint-config-love) from 133.0.0 to 136.0.0.
- [Release notes](https://github.com/mightyiam/eslint-config-love/releases)
- [Changelog](https://github.com/mightyiam/eslint-config-love/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mightyiam/eslint-config-love/compare/v133.0.0...v136.0.0)

---
updated-dependencies:
- dependency-name: eslint-config-love
  dependency-version: 136.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 08:07:10 +00:00
Ryan
bd632b0ca4 Merge pull request #539 from Sped0n/dependabot/npm_and_yarn/vite-7.2.7 2025-12-09 15:11:28 +08:00
dependabot[bot]
b550dcd236 build(deps-dev): bump vite from 7.2.6 to 7.2.7
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.2.6 to 7.2.7.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.2.7/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.2.7/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.2.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 07:10:19 +00:00
Ryan
1b067c26d0 Merge pull request #540 from Sped0n/dependabot/npm_and_yarn/prettier-3.7.4 2025-12-09 15:09:56 +08:00
dependabot[bot]
665522c8d1 build(deps-dev): bump prettier from 3.7.3 to 3.7.4
Bumps [prettier](https://github.com/prettier/prettier) from 3.7.3 to 3.7.4.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.7.3...3.7.4)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.7.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 07:09:12 +00:00
Sped0n
e67865b82b ci: update bundled artifacts [skip ci] 2025-12-09 04:30:31 +00:00
Ryan
6440556242 Merge pull request #545 from Sped0n/dependabot/npm_and_yarn/gsap-3.14.1 2025-12-09 12:29:49 +08:00
dependabot[bot]
59227fb265 build(deps): bump gsap from 3.13.0 to 3.14.1
Bumps [gsap](https://github.com/greensock/GSAP) from 3.13.0 to 3.14.1.
- [Commits](https://github.com/greensock/GSAP/compare/3.13.0...3.14.1)

---
updated-dependencies:
- dependency-name: gsap
  dependency-version: 3.14.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 23:06:02 +00:00
dependabot[bot]
d291aab64f build(deps-dev): bump vite from 7.2.4 to 7.2.6 (#537) 2025-12-02 20:41:51 +00:00
dependabot[bot]
c290595a35 build(deps-dev): bump prettier from 3.6.2 to 3.7.3 (#538) 2025-12-03 04:39:45 +08:00
Sped0n
a6a576246f ci: update bundled artifacts [skip ci] 2025-11-25 17:52:23 +00:00
Ryan
93629a4e6b refactor(gallery): refine navClose with flexbox alignment and z-index (#536)
Replace text-align: right with display: flex, justify-content: flex-end for
consistent right alignment. Add height, z-index for layering, and adjust
margin/padding for better mobile gallery nav positioning.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 17:51:47 +00:00
Sped0n
a909afee97 ci: update bundled artifacts [skip ci] 2025-11-25 13:21:07 +00:00
Ryan
9c15a367ea refactor(gallery): adjust navClose min-width to 25% (#535)
Reduce min-width from 30% to 25% for better mobile gallery layout balance.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 13:20:22 +00:00
Sped0n
73ee16c6fb ci: update bundled artifacts [skip ci] 2025-11-25 13:14:31 +00:00
Sped0n
91b0314c5d ci(vercel): fix vercel preview
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 21:13:53 +08:00
Sped0n
d1a1dba210 feat(gallery): enhance close button accessibility
Add .navClose styles for 30% min-width, right alignment, and pointer cursor.
Apply class to close div in mobile gallery nav for consistent keyboard support.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 21:13:53 +08:00
Sped0n
110ff665e7 fix(gallery): add overflow hidden to prevent scrolling
Ensure the fixed gallery modal doesn't allow overflow beyond viewport.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 21:13:53 +08:00
Ryan
b39d563e77 chore: remove dummy bundled/js/critical.js (#533)
Update .gitignore to reflect the correct path before deletion.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 12:07:21 +00:00
Sped0n
0e74655820 ci: update bundled artifacts [skip ci] 2025-11-25 11:59:43 +00:00
Sped0n
8926caed69 ci(build): add labels to Hugo matrix for better job names
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 19:59:06 +08:00
Sped0n
19f54640f9 build(deps-dev): bump various dev dependencies
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 19:59:06 +08:00
Sped0n
56b87d6393 fix(gallery): adjust image sizing to fit window height
Update gallery image styles to use max-height based on window minus nav,
max-width 100%, and auto width for proper scaling with contain fit.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-25 19:59:06 +08:00
dependabot[bot]
75d8310953 build(deps-dev): bump vite from 7.2.2 to 7.2.4
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.2.2 to 7.2.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.2.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.2.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-25 19:28:09 +08:00
dependabot[bot]
a9f164f2af build(deps-dev): bump @typescript-eslint/parser from 8.47.0 to 8.48.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.47.0 to 8.48.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.48.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.48.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-25 19:26:57 +08:00
dependabot[bot]
7773f184aa build(deps-dev): bump typescript-eslint from 8.47.0 to 8.48.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.47.0 to 8.48.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.48.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.48.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-25 19:24:50 +08:00
dependabot[bot]
bc501934ae build(deps-dev): bump typescript-eslint from 8.46.4 to 8.47.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.46.4 to 8.47.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.47.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.47.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-20 17:56:48 +08:00
dependabot[bot]
44b619e49b build(deps-dev): bump @types/node from 24.10.0 to 24.10.1
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.10.0 to 24.10.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.10.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-20 17:55:45 +08:00
dependabot[bot]
024d013219 build(deps-dev): bump @typescript-eslint/parser from 8.46.4 to 8.47.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.46.4 to 8.47.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.47.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.47.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-20 17:53:41 +08:00
Sped0n
268159e7d2 refactor: unify bundled assets with subdirs and Hugo mounts
Move bundled outputs to dedicated css/js subdirs. Update Vite
config to output directly to bundled/ with simplified naming.
Add Hugo module mounts to expose as assets/bundled and
static/bundled. Adjust gitignore and partial accordingly.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-14 18:15:24 +08:00
Sped0n
2e7131a5a5 ci: update bundled artifacts [skip ci] 2025-11-12 09:15:02 +00:00
Sped0n
1de3926c49 docs: correct Solid.js to SolidJS in theme description
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 17:14:20 +08:00
Sped0n
4b1f529589 refactor: migrate to vite for critical scss bundling, remove dart sass dependency
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 17:14:20 +08:00
Sped0n
8b3b5cd77a fix: use absolute URL for fw font in scss
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 17:14:20 +08:00
Sped0n
3a0025ebd1 docs: update documentations
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 05:41:50 +08:00
Sped0n
283f386371 refactor: remove redundant ESLint config import
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 05:15:58 +08:00
Sped0n
4c91cd269e refactor: upgrade to pnpm 10 and update docs
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 05:15:58 +08:00
Sped0n
304abf3b65 refactor: switch to sass-embedded and remove manual install
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 05:15:58 +08:00
Sped0n
99a2866d4a docs: update README.md
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 03:25:59 +08:00
Sped0n
ba46f52d55 ci: build with multiple Hugo versions and update caches
Add matrix strategy for 'latest' and '0.114.0' in build job. Update
pnpm and Hugo cache keys for better reliability. Push artifacts only
for 'latest' version. Add [skip ci] to format commit message.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 02:40:38 +08:00
Sped0n
48eaa9d95b docs: restructure documentation
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 02:40:38 +08:00
Sped0n
6be1a924de refactor: update hugo npm scripts
Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 00:27:13 +08:00
Sped0n
ba0def753e refactor: remove i18n labels and centralize in config
Delete multilingual i18n files for UI labels. Add English labels to
params.toml under [labels]. Update 404.html, single.html, and nav.html
to use site.Params.labels instead of i18n.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 00:27:13 +08:00
Sped0n
c9410c9644 ci: update bundled artifacts [skip ci] 2025-11-11 16:10:49 +00:00
Sped0n
1d1f893c92 ci: format code 2025-11-12 00:10:06 +08:00
Sped0n
7d4bed3ba6 feat: use absolute URLs for assets
closes #473, closes #476

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 00:10:06 +08:00
Sped0n
72b830def9 refactor: remove multilingual support and language-specific fonts
Simplify to Geist font family for all languages. Update README, SCSS,
partials, and config. Fix style template execution order.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-12 00:10:06 +08:00
Ryan
6b2c1de9d8 Misc (#516)
* chore: remove obsolete modern Sass API config in Vite

Signed-off-by: Sped0n <hi@sped0n.com>

* docs: update README thumbnail to absolute URL

Signed-off-by: Sped0n <hi@sped0n.com>

---------

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-11 21:07:35 +08:00
Sped0n
ae899035ae ci: update bundled artifacts [skip ci] 2025-11-11 12:22:05 +00:00
Ryan
36721f8bf6 Bump deps (#515)
* chore: add nix flake for reproducible dev environment

Signed-off-by: Sped0n <hi@sped0n.com>

* refactor: migrate SCSS to modern Sass (@use/@forward)

Update mixins to use Sass module functions (map.has-key/get).
Configure Vite for modern Sass API.
Introduce _foundation.scss for forwarding core modules.

Signed-off-by: Sped0n <hi@sped0n.com>

* fix: replace deprecated _build with build in frontmatter

Signed-off-by: Sped0n <hi@sped0n.com>

* chore: add vcache.sh script for vercel build cache management

Signed-off-by: Sped0n <hi@sped0n.com>

* refactor: migrate to ESLint v9 flat config

Remove legacy .eslintrc.json, .eslintignore, and .prettierrc.json.

Add eslint.config.mjs with love, prettier, solid, and import rules.

Update devDependencies (eslint@9, @typescript-eslint@8, etc.) and scripts.

Minor TS fixes: remove eslint-disable, add error logging, simplify conditional.

Signed-off-by: Sped0n <hi@sped0n.com>

* chore: replace vcache.sh with vercel.sh for Vercel build process

Delete vcache.sh script.

Add vercel.sh: install Dart Sass v1.93.3, copy generated assets between
node_modules and project dirs, run vite:build + hugo build, then copy back.

Signed-off-by: Sped0n <hi@sped0n.com>

* chore: setup dart-sass and split build steps in GitHub workflow

Signed-off-by: Sped0n <hi@sped0n.com>

---------

Signed-off-by: Sped0n <hi@sped0n.com>
2025-11-11 20:20:29 +08:00
Sped0n
2dcbb5e5d5 ci: update bundled artifacts [skip ci] 2025-10-22 12:32:34 +00:00
dependabot[bot]
07aa48f2db build(deps-dev): bump vite-plugin-solid from 2.10.2 to 2.11.9 (#496)
Bumps [vite-plugin-solid](https://github.com/solidjs/vite-plugin-solid) from 2.10.2 to 2.11.9.
- [Release notes](https://github.com/solidjs/vite-plugin-solid/releases)
- [Changelog](https://github.com/solidjs/vite-plugin-solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/vite-plugin-solid/commits/vite-plugin-solid@2.11.9)

---
updated-dependencies:
- dependency-name: vite-plugin-solid
  dependency-version: 2.11.9
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 20:31:38 +08:00
dependabot[bot]
099513500c build(deps-dev): bump eslint-plugin-import from 2.31.0 to 2.32.0 (#495)
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.31.0 to 2.32.0.
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.31.0...v2.32.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-version: 2.32.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 12:15:18 +00:00
dependabot[bot]
f0da771dca build(deps-dev): bump typescript from 5.7.2 to 5.9.3 (#494)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.7.2 to 5.9.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.2...v5.9.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.9.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 12:13:11 +00:00
Sped0n
dfd4abdf2a ci: update bundled artifacts [skip ci] 2025-10-22 12:12:05 +00:00
dependabot[bot]
6f8ce6bbd8 build(deps-dev): bump terser from 5.37.0 to 5.44.0 (#499)
Bumps [terser](https://github.com/terser/terser) from 5.37.0 to 5.44.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.37.0...v5.44.0)

---
updated-dependencies:
- dependency-name: terser
  dependency-version: 5.44.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 12:11:21 +00:00
dependabot[bot]
543a08d472 build(deps-dev): bump eslint-config-prettier from 9.1.0 to 10.1.8 (#498)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 9.1.0 to 10.1.8.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v9.1.0...v10.1.8)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-version: 10.1.8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 12:10:10 +00:00
Sped0n
05599ef190 ci: update bundled artifacts [skip ci] 2025-10-22 12:08:56 +00:00
dependabot[bot]
95bd4d1c28 build(deps): bump solid-js from 1.9.4 to 1.9.9 (#502)
Bumps [solid-js](https://github.com/solidjs/solid) from 1.9.4 to 1.9.9.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/compare/v1.9.4...v1.9.9)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-version: 1.9.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-22 20:08:12 +08:00
dependabot[bot]
835cd6f343 build(deps-dev): bump prettier-plugin-organize-imports (#497)
Bumps [prettier-plugin-organize-imports](https://github.com/simonhaenisch/prettier-plugin-organize-imports) from 4.1.0 to 4.3.0.
- [Release notes](https://github.com/simonhaenisch/prettier-plugin-organize-imports/releases)
- [Changelog](https://github.com/simonhaenisch/prettier-plugin-organize-imports/blob/master/changelog.md)
- [Commits](https://github.com/simonhaenisch/prettier-plugin-organize-imports/compare/v4.1.0...v4.3.0)

---
updated-dependencies:
- dependency-name: prettier-plugin-organize-imports
  dependency-version: 4.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 10:00:57 +00:00
dependabot[bot]
479164bc83 build(deps-dev): bump prettier from 3.3.3 to 3.6.2 (#503)
* build(deps-dev): bump prettier from 3.3.3 to 3.6.2

Bumps [prettier](https://github.com/prettier/prettier) from 3.3.3 to 3.6.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.3...3.6.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.6.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* ci: format code

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 09:58:56 +00:00
dependabot[bot]
9ea37b8a3f build(deps): bump tj-actions/changed-files in /.github/workflows (#507)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 41 to 46.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](https://github.com/tj-actions/changed-files/compare/v41...v46)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-version: '46'
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 09:52:27 +00:00
Sped0n
5df519e55f ci: update bundled artifacts [skip ci] 2025-10-21 09:50:35 +00:00
dependabot[bot]
860428d03b build(deps-dev): bump vite from 5.4.2 to 5.4.21 (#508)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.2 to 5.4.21.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.21/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.21/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.21
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 17:49:52 +08:00
Sped0n
c1ad92fbeb ci: update bundled artifacts [skip ci] 2025-10-21 08:52:02 +00:00
dependabot[bot]
78f657618e build(deps): bump gsap from 3.12.5 to 3.13.0 (#504)
Bumps [gsap](https://github.com/greensock/GSAP) from 3.12.5 to 3.13.0.
- [Commits](https://github.com/greensock/GSAP/compare/3.12.5...3.13.0)

---
updated-dependencies:
- dependency-name: gsap
  dependency-version: 3.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 08:51:20 +00:00
dependabot[bot]
1fe7095898 build(deps-dev): bump eslint-import-resolver-typescript (#505)
Bumps [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) from 3.6.3 to 4.4.4.
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v3.6.3...v4.4.4)

---
updated-dependencies:
- dependency-name: eslint-import-resolver-typescript
  dependency-version: 4.4.4
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 08:48:42 +00:00
dependabot[bot]
0471af5085 build(deps-dev): bump eslint-plugin-prettier from 5.2.1 to 5.5.4 (#506)
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.2.1 to 5.5.4.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.2.1...v5.5.4)

---
updated-dependencies:
- dependency-name: eslint-plugin-prettier
  dependency-version: 5.5.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-21 16:46:40 +08:00
Sped0n
543d630535 chore: update demo site config
Signed-off-by: Sped0n <hi@sped0n.com>
2025-10-21 16:29:11 +08:00
dependabot[bot]
b7ed5a2834 build(deps-dev): bump prettier-plugin-organize-imports (#405)
Bumps [prettier-plugin-organize-imports](https://github.com/simonhaenisch/prettier-plugin-organize-imports) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/simonhaenisch/prettier-plugin-organize-imports/releases)
- [Changelog](https://github.com/simonhaenisch/prettier-plugin-organize-imports/blob/master/changelog.md)
- [Commits](https://github.com/simonhaenisch/prettier-plugin-organize-imports/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: prettier-plugin-organize-imports
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:27:30 +00:00
dependabot[bot]
5ba7d77c07 build(deps-dev): bump eslint-plugin-import from 2.29.1 to 2.31.0 (#413)
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.29.1 to 2.31.0.
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.29.1...v2.31.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:26:23 +00:00
dependabot[bot]
af82026d1a build(deps-dev): bump sass from 1.77.8 to 1.83.1 (#434)
Bumps [sass](https://github.com/sass/dart-sass) from 1.77.8 to 1.83.1.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.77.8...1.83.1)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:24:19 +00:00
dependabot[bot]
b5ef661e1c build(deps-dev): bump rollup from 4.21.1 to 4.30.1 (#437)
Bumps [rollup](https://github.com/rollup/rollup) from 4.21.1 to 4.30.1.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.21.1...v4.30.1)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:23:27 +00:00
dependabot[bot]
883eec1a3b build(deps-dev): bump eslint-plugin-solid from 0.14.2 to 0.14.5 (#435)
Bumps [eslint-plugin-solid](https://github.com/solidjs-community/eslint-plugin-solid) from 0.14.2 to 0.14.5.
- [Release notes](https://github.com/solidjs-community/eslint-plugin-solid/releases)
- [Commits](https://github.com/solidjs-community/eslint-plugin-solid/compare/v0.14.2...v0.14.5)

---
updated-dependencies:
- dependency-name: eslint-plugin-solid
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:22:33 +00:00
Sped0n
b027cd03cf ci: update bundled artifacts [skip ci] 2025-01-08 07:21:16 +00:00
dependabot[bot]
aa34979bb4 build(deps-dev): bump terser from 5.31.6 to 5.37.0 (#436)
Bumps [terser](https://github.com/terser/terser) from 5.31.6 to 5.37.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.31.6...v5.37.0)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:20:34 +00:00
dependabot[bot]
08bbfaa3ba build(deps-dev): bump typescript from 5.5.4 to 5.7.2 (#428)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.5.4 to 5.7.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.5.4...v5.7.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:19:13 +00:00
Sped0n
b8c6ce2b04 ci: update bundled artifacts [skip ci] 2025-01-08 07:02:54 +00:00
dependabot[bot]
27083c0336 build(deps): bump solid-js from 1.8.22 to 1.9.4 (#433)
Bumps [solid-js](https://github.com/solidjs/solid) from 1.8.22 to 1.9.4.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/compare/v1.8.22...v1.9.4)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 07:02:16 +00:00
Sped0n
082458b2aa ci: update bundled artifacts [skip ci] 2025-01-08 06:59:26 +00:00
dependabot[bot]
1c05eb2633 build(deps): bump swiper from 11.1.11 to 11.1.15 (#427)
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 11.1.11 to 11.1.15.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v11.1.11...v11.1.15)

---
updated-dependencies:
- dependency-name: swiper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 06:58:51 +00:00
Ananth
9016cfb035 Add tamil translation (#430) 2025-01-03 16:19:41 +08:00
Spedon
d9b4100d17 ci: fallback to github.token in ESLint workflow (#431)
- Use `github.token` as a fallback if `secrets.PAT` is not available in the ESLint workflow.

Signed-off-by: Sped0n <hi@sped0n.com>
2025-01-01 13:44:12 +00:00
dependabot[bot]
082f5f4961 build(deps-dev): bump sass from 1.77.6 to 1.77.8 (#359)
Bumps [sass](https://github.com/sass/dart-sass) from 1.77.6 to 1.77.8.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.77.6...1.77.8)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 17:20:59 +00:00
Sped0n
9d91becbd5 ci: update bundled artifacts [skip ci] 2024-08-29 16:37:42 +00:00
dependabot[bot]
2e51b7eb89 build(deps): bump solid-js from 1.8.18 to 1.8.22 (#391)
Bumps [solid-js](https://github.com/solidjs/solid) from 1.8.18 to 1.8.22.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/commits)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:37:05 +00:00
Sped0n
7dd8c2242c ci: update bundled artifacts [skip ci] 2024-08-29 16:35:57 +00:00
dependabot[bot]
2a10e4944e build(deps): bump swiper from 11.1.4 to 11.1.11 (#390)
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 11.1.4 to 11.1.11.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v11.1.4...v11.1.11)

---
updated-dependencies:
- dependency-name: swiper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-30 00:35:03 +08:00
dependabot[bot]
7893586d24 build(deps-dev): bump typescript from 5.5.3 to 5.5.4 (#367)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.5.3 to 5.5.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.5.3...v5.5.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:31:03 +00:00
dependabot[bot]
5a51f83654 build(deps-dev): bump eslint-plugin-promise from 6.4.0 to 6.6.0 (#364)
Bumps [eslint-plugin-promise](https://github.com/eslint-community/eslint-plugin-promise) from 6.4.0 to 6.6.0.
- [Release notes](https://github.com/eslint-community/eslint-plugin-promise/releases)
- [Changelog](https://github.com/eslint-community/eslint-plugin-promise/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint-community/eslint-plugin-promise/compare/v6.4.0...v6.6.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-promise
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:29:27 +00:00
Sped0n
e4d5ac4389 ci: update bundled artifacts [skip ci] 2024-08-29 16:28:26 +00:00
dependabot[bot]
ea3d58760b build(deps-dev): bump vite from 5.3.3 to 5.4.2 (#385)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.3 to 5.4.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:27:48 +00:00
dependabot[bot]
4812cdb191 build(deps-dev): bump eslint-plugin-solid from 0.14.1 to 0.14.2 (#380)
Bumps [eslint-plugin-solid](https://github.com/solidjs-community/eslint-plugin-solid) from 0.14.1 to 0.14.2.
- [Release notes](https://github.com/solidjs-community/eslint-plugin-solid/releases)
- [Commits](https://github.com/solidjs-community/eslint-plugin-solid/compare/v0.14.1...v0.14.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-solid
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:26:52 +00:00
dependabot[bot]
b93b8d3ac6 build(deps-dev): bump prettier from 3.3.2 to 3.3.3 (#362)
Bumps [prettier](https://github.com/prettier/prettier) from 3.3.2 to 3.3.3.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.2...3.3.3)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:25:59 +00:00
dependabot[bot]
a7bc6b2df5 build(deps-dev): bump eslint-plugin-prettier from 5.1.3 to 5.2.1 (#368)
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.1.3 to 5.2.1.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.1.3...v5.2.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:25:07 +00:00
Sped0n
1cfbc8ac28 ci: update bundled artifacts [skip ci] 2024-08-29 16:24:18 +00:00
dependabot[bot]
c4cea2648e build(deps-dev): bump terser from 5.31.1 to 5.31.6 (#381)
Bumps [terser](https://github.com/terser/terser) from 5.31.1 to 5.31.6.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:23:32 +00:00
dependabot[bot]
26bdddc5ff build(deps-dev): bump eslint-import-resolver-typescript (#386)
Bumps [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) from 3.6.1 to 3.6.3.
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v3.6.1...v3.6.3)

---
updated-dependencies:
- dependency-name: eslint-import-resolver-typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 16:22:15 +00:00
Spedon
437bbf17e0 docs: clarify relative path usage in documentation (#389)
- Clarify the relative path requirement in the installation documentation
- Update the comment in the configuration file to specify the relative path context

Signed-off-by: Spedon Wen <realsped0n@outlook.com>
2024-08-29 08:04:19 +00:00
Sped0n
2a715327f6 ci: update bundled artifacts [skip ci] 2024-07-11 05:36:52 +00:00
Spedon
c111de15b1 feat: enhance mobile detection logic (#358) 2024-07-11 13:36:15 +08:00
dependabot[bot]
1b9826f582 build(deps-dev): bump vite from 5.3.2 to 5.3.3 (#357) 2024-07-09 14:41:09 +08:00
Sped0n
6a3ce498a9 ci: update bundled artifacts [skip ci] 2024-07-06 14:37:33 +00:00
Spedon
8d48e6347e fix keyboard input (#356)
* fix: enhance accessibility with `tabIndex`

- Add `tabIndex="-1"` to the navigation item for accessibility

* refactor: refactor event handling with SolidJS effects

- Import `createEffect` from 'solid-js'
- Add an `AbortController` for managing event listeners
- Use `createEffect` to conditionally add and remove keydown event listener based on component state
- Remove `onKeyDown` and `tabIndex` attributes from the overlay div
2024-07-06 14:36:50 +00:00
Sped0n
4599a5dfc2 ci: update bundled artifacts [skip ci] 2024-07-04 15:53:45 +00:00
Spedon
7536288baa fix: enhance accessibility with tabIndex (#355)
- Add `tabIndex="-1"` to the navigation item for accessibility
2024-07-04 23:52:54 +08:00
dependabot[bot]
e12c32388b build(deps-dev): bump eslint-plugin-solid from 0.14.0 to 0.14.1 (#345)
Bumps [eslint-plugin-solid](https://github.com/solidjs-community/eslint-plugin-solid) from 0.14.0 to 0.14.1.
- [Release notes](https://github.com/solidjs-community/eslint-plugin-solid/releases)
- [Commits](https://github.com/solidjs-community/eslint-plugin-solid/compare/v0.14.0...v0.14.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-solid
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:23:50 +00:00
dependabot[bot]
4198a5fa90 build(deps-dev): bump prettier from 3.2.5 to 3.3.2 (#342)
Bumps [prettier](https://github.com/prettier/prettier) from 3.2.5 to 3.3.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.2.5...3.3.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:22:15 +00:00
dependabot[bot]
089e9b285a build(deps-dev): bump sass from 1.77.1 to 1.77.6 (#341)
Bumps [sass](https://github.com/sass/dart-sass) from 1.77.1 to 1.77.6.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.77.1...1.77.6)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:20:57 +00:00
dependabot[bot]
60e19fed00 build(deps-dev): bump terser from 5.31.0 to 5.31.1 (#337)
Bumps [terser](https://github.com/terser/terser) from 5.31.0 to 5.31.1.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.31.0...v5.31.1)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:19:11 +00:00
Sped0n
626433e67d ci: update bundled artifacts [skip ci] 2024-07-02 09:17:20 +00:00
dependabot[bot]
cb5080ce41 build(deps-dev): bump vite from 5.2.11 to 5.3.2 (#348)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.11 to 5.3.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.3.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:16:45 +00:00
dependabot[bot]
e2f8317669 build(deps-dev): bump eslint-plugin-promise from 6.1.1 to 6.4.0 (#352)
Bumps [eslint-plugin-promise](https://github.com/eslint-community/eslint-plugin-promise) from 6.1.1 to 6.4.0.
- [Release notes](https://github.com/eslint-community/eslint-plugin-promise/releases)
- [Changelog](https://github.com/eslint-community/eslint-plugin-promise/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint-community/eslint-plugin-promise/compare/v6.1.1...v6.4.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-promise
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:15:26 +00:00
Sped0n
5d9e32f62b ci: update bundled artifacts [skip ci] 2024-07-02 09:14:03 +00:00
dependabot[bot]
b96ecd6042 build(deps): bump solid-js from 1.8.17 to 1.8.18 (#349)
Bumps [solid-js](https://github.com/solidjs/solid) from 1.8.17 to 1.8.18.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/commits)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:13:22 +00:00
dependabot[bot]
5b7ec62106 build(deps-dev): bump prettier-plugin-organize-imports (#351)
Bumps [prettier-plugin-organize-imports](https://github.com/simonhaenisch/prettier-plugin-organize-imports) from 3.2.4 to 4.0.0.
- [Release notes](https://github.com/simonhaenisch/prettier-plugin-organize-imports/releases)
- [Changelog](https://github.com/simonhaenisch/prettier-plugin-organize-imports/blob/master/changelog.md)
- [Commits](https://github.com/simonhaenisch/prettier-plugin-organize-imports/compare/v3.2.4...v4.0.0)

---
updated-dependencies:
- dependency-name: prettier-plugin-organize-imports
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:12:06 +00:00
dependabot[bot]
3ca4a0d803 build(deps-dev): bump typescript from 5.4.5 to 5.5.3 (#350)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.5 to 5.5.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.5...v5.5.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:10:51 +00:00
Sped0n
a8d8802d9f ci: update bundled artifacts [skip ci] 2024-07-02 09:09:28 +00:00
dependabot[bot]
28782217f1 build(deps): bump swiper from 11.1.1 to 11.1.4 (#333)
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 11.1.1 to 11.1.4.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v11.1.1...v11.1.4)

---
updated-dependencies:
- dependency-name: swiper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:08:50 +00:00
dependabot[bot]
cfcda29524 build(deps-dev): bump braces from 3.0.2 to 3.0.3 (#343)
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 17:07:09 +08:00
Spedon
fb498971c7 chore: update domain (#330) 2024-05-20 14:08:58 +00:00
dependabot[bot]
9dbb3cb624 build(deps-dev): bump typescript from 5.4.4 to 5.4.5 (#320)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.4 to 5.4.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.4...v5.4.5)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-12 08:20:10 +00:00
Sped0n
129f26dd54 ci: update bundled artifacts [skip ci] 2024-05-12 08:18:26 +00:00
dependabot[bot]
d1f9b843c3 build(deps): bump solid-js from 1.8.16 to 1.8.17 (#322)
Bumps [solid-js](https://github.com/solidjs/solid) from 1.8.16 to 1.8.17.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/commits)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-12 08:17:46 +00:00
dependabot[bot]
a7b5ec45ed build(deps-dev): bump eslint-plugin-solid from 0.13.2 to 0.14.0 (#325)
Bumps [eslint-plugin-solid](https://github.com/solidjs-community/eslint-plugin-solid) from 0.13.2 to 0.14.0.
- [Release notes](https://github.com/solidjs-community/eslint-plugin-solid/releases)
- [Commits](https://github.com/solidjs-community/eslint-plugin-solid/compare/v0.13.2...v0.14.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-solid
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-12 08:16:24 +00:00
dependabot[bot]
5d82276734 build(deps-dev): bump sass from 1.74.1 to 1.77.1 (#328)
Bumps [sass](https://github.com/sass/dart-sass) from 1.74.1 to 1.77.1.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.74.1...1.77.1)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-12 08:11:54 +00:00
dependabot[bot]
b0c4fa8ea7 build(deps-dev): bump terser from 5.30.3 to 5.31.0 (#324)
Bumps [terser](https://github.com/terser/terser) from 5.30.3 to 5.31.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.30.3...v5.31.0)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-12 08:09:16 +00:00
Sped0n
a6f983de5d ci: update bundled artifacts [skip ci] 2024-05-12 08:06:38 +00:00
dependabot[bot]
3bc232638a build(deps): bump swiper from 11.1.0 to 11.1.1 (#318)
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 11.1.0 to 11.1.1.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v11.1.0...v11.1.1)

---
updated-dependencies:
- dependency-name: swiper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-12 08:05:42 +00:00
dependabot[bot]
67944df12f build(deps-dev): bump vite from 5.2.8 to 5.2.11 (#327)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.8 to 5.2.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-12 16:03:54 +08:00
Sped0n
e82fe6cab2 ci: update bundled artifacts [skip ci] 2024-04-08 09:16:30 +00:00
dependabot[bot]
819df6b2ed build(deps-dev): bump vite from 5.1.7 to 5.2.8 (#315)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.1.7 to 5.2.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.8/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 09:15:40 +00:00
Sped0n
dfef87ca55 ci: update bundled artifacts [skip ci] 2024-04-08 09:14:07 +00:00
dependabot[bot]
477b6d748a build(deps): bump swiper from 11.0.7 to 11.1.0 (#311)
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 11.0.7 to 11.1.0.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v11.0.7...v11.1.0)

---
updated-dependencies:
- dependency-name: swiper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 09:13:28 +00:00
dependabot[bot]
31a59c5e9e build(deps-dev): bump terser from 5.29.2 to 5.30.3 (#316)
Bumps [terser](https://github.com/terser/terser) from 5.29.2 to 5.30.3.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.29.2...v5.30.3)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 09:12:06 +00:00
dependabot[bot]
e8cdd12151 build(deps-dev): bump sass from 1.71.1 to 1.74.1 (#317)
Bumps [sass](https://github.com/sass/dart-sass) from 1.71.1 to 1.74.1.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.71.1...1.74.1)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 09:10:48 +00:00
dependabot[bot]
a8bc17ca12 build(deps-dev): bump typescript from 5.4.2 to 5.4.4 (#314)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.2 to 5.4.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.2...v5.4.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 09:09:35 +00:00
dependabot[bot]
4d04fe1945 build(deps-dev): bump eslint-plugin-solid from 0.13.1 to 0.13.2 (#308)
Bumps [eslint-plugin-solid](https://github.com/solidjs-community/eslint-plugin-solid) from 0.13.1 to 0.13.2.
- [Release notes](https://github.com/solidjs-community/eslint-plugin-solid/releases)
- [Commits](https://github.com/solidjs-community/eslint-plugin-solid/compare/v0.13.1...v0.13.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-solid
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 09:08:26 +00:00
Sped0n
bafd2aa3b3 ci: update bundled artifacts [skip ci] 2024-04-08 09:07:11 +00:00
dependabot[bot]
acf50d10d7 build(deps): bump solid-js from 1.8.15 to 1.8.16 (#306)
Bumps [solid-js](https://github.com/solidjs/solid) from 1.8.15 to 1.8.16.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/compare/v1.8.15...v1.8.16)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 09:06:34 +00:00
dependabot[bot]
30a6a3bd23 build(deps-dev): bump vite from 5.1.6 to 5.1.7 (#313)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.1.6 to 5.1.7.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.1.7/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.1.7/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 17:05:10 +08:00
Spedon
d808782afd docs: update documentation (#303) 2024-03-17 16:23:43 +08:00
Sped0n
5327d7c585 ci: update bundled artifacts [skip ci] 2024-03-17 08:15:57 +00:00
Spedon
d7e7fc68ba refactor: improve top position calculation in stylesheets (#302)
* refactor: improve top position calculation in stylesheets

- Update the top position calculation in the `_collection.scss` file

* refactor: tweak it harder

* Revert "refactor: tweak it harder"

This reverts commit b7bf7e50f8.
2024-03-17 16:15:13 +08:00
dependabot[bot]
7b637637a1 build(deps-dev): bump vite-plugin-solid from 2.10.0 to 2.10.2 (#300)
Bumps [vite-plugin-solid](https://github.com/solidjs/vite-plugin-solid) from 2.10.0 to 2.10.2.
- [Release notes](https://github.com/solidjs/vite-plugin-solid/releases)
- [Changelog](https://github.com/solidjs/vite-plugin-solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/vite-plugin-solid/commits)

---
updated-dependencies:
- dependency-name: vite-plugin-solid
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:38:24 +08:00
Sped0n
4a2ef258ba ci: update bundled artifacts [skip ci] 2024-03-16 13:38:04 +00:00
dependabot[bot]
b2c1c96f56 build(deps): bump solid-js from 1.8.14 to 1.8.15 (#290)
Bumps [solid-js](https://github.com/solidjs/solid) from 1.8.14 to 1.8.15.
- [Release notes](https://github.com/solidjs/solid/releases)
- [Changelog](https://github.com/solidjs/solid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/solidjs/solid/commits)

---
updated-dependencies:
- dependency-name: solid-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:37:22 +08:00
Sped0n
6d98671856 ci: update bundled artifacts [skip ci] 2024-03-16 13:36:35 +00:00
dependabot[bot]
0b7605b3ff build(deps): bump swiper from 11.0.6 to 11.0.7 (#294)
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 11.0.6 to 11.0.7.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v11.0.6...v11.0.7)

---
updated-dependencies:
- dependency-name: swiper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:35:58 +08:00
dependabot[bot]
c9ca9c682a build(deps-dev): bump vite from 5.1.2 to 5.1.6 (#296)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.1.2 to 5.1.6.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.1.6/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:35:27 +08:00
Sped0n
417a00b9c4 ci: update bundled artifacts [skip ci] 2024-03-16 13:33:45 +00:00
dependabot[bot]
d7a4345f53 build(deps): bump tiny-invariant from 1.3.1 to 1.3.3 (#287)
Bumps [tiny-invariant](https://github.com/alexreardon/tiny-invariant) from 1.3.1 to 1.3.3.
- [Release notes](https://github.com/alexreardon/tiny-invariant/releases)
- [Commits](https://github.com/alexreardon/tiny-invariant/compare/v1.3.1...v1.3.3)

---
updated-dependencies:
- dependency-name: tiny-invariant
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:33:10 +08:00
dependabot[bot]
2e47be5635 build(deps-dev): bump eslint from 8.56.0 to 8.57.0 (#291)
Bumps [eslint](https://github.com/eslint/eslint) from 8.56.0 to 8.57.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.56.0...v8.57.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:32:46 +08:00
dependabot[bot]
0e6fc9384f build(deps-dev): bump terser from 5.27.0 to 5.29.2 (#301)
Bumps [terser](https://github.com/terser/terser) from 5.27.0 to 5.29.2.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.27.0...v5.29.2)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:32:17 +08:00
dependabot[bot]
81eba485d4 build(deps-dev): bump typescript from 5.3.3 to 5.4.2 (#297)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.3.3 to 5.4.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.3.3...v5.4.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 21:31:01 +08:00
Spedon
b1553a9a8b fix: fix hugo module version bug (#299)
* docs: Update getStarted.md

* fix: update module version in example site config

* chore: Update index.md

* revert
2024-03-16 21:30:40 +08:00
Spedon
66735f4c65 fix: Update go.mod (#298) 2024-03-16 21:10:25 +08:00
Spedon
3ff49b1106 docs: update doc for version 2 (#286)
* feat: update issue template

* docs: update doc for v2.0.0
2024-02-23 19:12:15 +08:00
Spedon
633f6a40e2 ci: update actions to resolve github's complain about deprecated Node.js v16 env (#285)
* ci: update the action to utilize Node.js version 20

* ci: update key for Hugo action to include 'resources' folder
2024-02-23 16:13:46 +08:00
Sped0n
1ff94546e0 ci: update bundled artifacts [skip ci] 2024-02-23 08:00:15 +00:00
Spedon
e081e139fc refactor: reduce amount of createEffect and improve imports (#284)
* refactor: update import syntax

* feat: add GalleryImage component for simplicity

* refactor: replace createEffect in GalleryNav with createMemo

* refactor: refactor Gallery component logic and improve imports
2024-02-23 15:59:32 +08:00
Spedon
875113448b refactor: migrate part of the sass compilation to vite (#283)
* refactor: migrate part of the sass compilation to vite

now `bundled` option is deprecated

* fix: update build script

* chore: add a “type” field to the package.json file to resolve Vite’s complaints about CommonJS modules.
2024-02-22 23:44:16 +08:00
Sped0n
53a44776de ci: update bundled artifacts [skip ci] 2024-02-21 17:49:42 +00:00
Sped0n
ecdaebb6cd refactor: don't render unneeded elements on raw info page 2024-02-22 01:48:48 +08:00
Sped0n
1a02360214 ci: manually update bundled js 2024-02-22 01:32:46 +08:00
Spedon
febbd7d45d feat: migrate to Solid.js (#282)
* refactor: change hires loader function name

* feat: add loading transition animation and improve performance

* refactor: refactor gallery creation and update functions

* feat: update dependencies, configuration, and input file for solidjs

- Update dependencies in package.json
- Modify the input file in rollup.config.mjs
- Update tsconfig.json with new configuration options

* feat: update ESLint config for TypeScript and Solid integration

- Add `plugin:solid/typescript` to the ESLint config
- Add `prettier`, `@typescript-eslint`, and `solid` plugins to the ESLint config
- Remove the `overrides` and `plugins` properties from the ESLint config
- Modify the `memberSyntaxSortOrder` property in the ESLint config

* feat: update build scripts and configuration for Vite

* GitButler Integration Commit

This is an integration commit for the virtual branches that GitButler is tracking.

Due to GitButler managing multiple virtual branches, you cannot switch back and
forth between git branches and virtual branches easily. 

If you switch to another branch, GitButler will need to be reinitialized.
If you commit on this branch, GitButler will throw it away.

Here are the branches that are currently applied:
 - solid (refs/gitbutler/solid)
   branch head: dc6860991c
   - .eslintrc.json
   - assets/ts/main.tsx
   - assets/ts/desktop/stage.tsx
   - static/bundled/js/main.js
   - rollup.config.mjs
   - pnpm-lock.yaml
   - vite.config.ts
   - package.json
   - tsconfig.json
   - assets/ts/globalState.ts
   - assets/ts/mobile/collection.ts
   - assets/ts/container.ts
   - assets/ts/mobile/init.ts
   - assets/ts/mobile/gallery.ts
   - assets/ts/desktop/customCursor.ts
   - assets/ts/mobile/state.ts
   - assets/ts/globalUtils.ts
   - static/bundled/js/zXhbFx.js
   - static/bundled/js/EY5BO_.js
   - static/bundled/js/bBHMTk.js
   - assets/ts/nav.tsx
   - assets/ts/utils.ts
   - assets/ts/desktop/stageNav.ts
   - assets/ts/mobile/utils.ts
   - assets/ts/main.ts
   - assets/ts/desktop/state.ts
   - assets/ts/desktop/init.ts
   - assets/ts/state.tsx
   - assets/ts/desktop/utils.ts
   - assets/ts/nav.ts
   - assets/ts/resources.ts
   - assets/ts/desktop/stage.ts
   - static/bundled/js/GAHquF.js

Your previous branch was: refs/heads/solid

The sha for that commit was: dc6860991c

For more information about what we're doing here, check out our docs:
https://docs.gitbutler.com/features/virtual-branches/integration-branch

* refactor: remove .hide class from _base.scss file

* feat: migrate to Solid.js

* refactor: change i18n loading text with trailing dots

* fix: fix broken pnpm lock file

* chore: update eslint configuration for better code organization

- Update the eslint plugins array by removing newlines and maintaining plugins order
- Disable the rule "@typescript-eslint/non-nullable-type-assertion-style"
- Change the configuration of "sort-imports" rule

* feat: add tiny-invariant and eslint-plugin-solid to deps

* refactor: fix multiple eslint warnings

---------

Co-authored-by: GitButler <gitbutler@gitbutler.com>
2024-02-22 01:18:29 +08:00
Sped0n
1acf24a519 ci: update bundled artifacts [skip ci] 2024-02-20 20:17:00 +00:00
dependabot[bot]
e2afe91131 build(deps): bump rollup from 4.9.6 to 4.12.0 (#281)
Bumps [rollup](https://github.com/rollup/rollup) from 4.9.6 to 4.12.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.9.6...v4.12.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-21 04:15:25 +08:00
Sped0n
3e51b96825 ci: update bundled artifacts [skip ci] 2024-02-11 06:23:22 +00:00
Spedon
c84b4cf234 refactor: better event listener cleanup (#279)
* refactor: change hires loader function name

* feat: add loading transition animation and improve performance

* refactor: refactor gallery creation and update functions

* feat: create createDivWithClass utility function

* feat: refactor abort signal handling in event listener and promise chain

- Add functionality to set up an abort controller for cleanup
- Add an event listener to abort the controller when necessary
- Modify event listener to include the abort signal
- Modify promise chain to include the abort signal
2024-02-11 14:22:48 +08:00
Spedon
997207fa90 feat: remove source image in public to prevent leakage (#278)
* refactor: change hires loader function name

* feat: add loading transition animation and improve performance

* feat: hide image source in exampleSite

* docs: update docs for publishResources
2024-02-06 23:40:46 +08:00
Sped0n
f7d2c7962c ci: update bundled artifacts [skip ci] 2024-02-06 15:13:23 +00:00
Spedon
0812a5a6b8 feat: loading transition (#277)
* refactor: change hires loader function name

* feat: add loading transition animation and improve performance

* refactor: refactor mutation handling in desktop codebase

- Modify the `initStage` function in `assets/ts/desktop/stage.ts`:
  - Change the `onMutation` callback to accept a single mutation instead of an array of mutations.
  - Update the conditions inside the callback to use `hold` instead of `skip`.
- Modify the `onMutation` function in `assets/ts/desktop/utils.ts`:
  - Change the `callback` parameter to `trigger`.
  - Update the implementation of the function to iterate over each mutation and check if it triggers the `trigger` function. If it does, disconnect the observer and break the loop.

* style: refactor state section and remove unnecessary code

- Remove the declaration of `lastIndex` on line 21
- Add a comment block for the state section
- Add a declaration of `lastIndex` for the state section

* refactor: refactor mobile collection and intersection functions

- Modify the `initCollection` function in `assets/ts/mobile/collection.ts`
- Remove the nested loop in the `initCollection` function
- Modify the `onIntersection` function in `assets/ts/mobile/utils.ts`
- Replace the callback parameter with a trigger parameter in the `onIntersection` function
- Remove the nested loop in the `onIntersection` function

* refactor: refactor Watchable class constructor to include lazy parameter

- Add a second parameter `lazy` in the constructor of the `Watchable` class in `globalUtils.ts`
- Set the default value of `lazy` to `true` in the constructor
- Add a condition to check if `e` is equal to `this.obj` and `this.lazy` is `true` to return in `watch`
- Delete the previous constructor definition in the `Watchable` class in `globalUtils.ts`

* fix: set state's lazy param to false

* refactor: refactor third party lib import
2024-02-06 23:12:44 +08:00
dependabot[bot]
7fd971eb13 build(deps-dev): bump @typescript-eslint/eslint-plugin (#275)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.20.0 to 6.21.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.21.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 22:18:13 +08:00
Sped0n
881b0b6490 ci: update commit message for bundled artifacts 2024-02-06 22:17:41 +08:00
Sped0n
50d7b14133 ci: update bundled artifacts 2024-02-06 14:13:56 +00:00
dependabot[bot]
872d23ad13 build(deps-dev): bump @typescript-eslint/parser from 6.20.0 to 6.21.0 (#274)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.20.0 to 6.21.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.21.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 22:13:14 +08:00
dependabot[bot]
eeca83a74b build(deps-dev): bump prettier from 3.2.4 to 3.2.5 (#273)
Bumps [prettier](https://github.com/prettier/prettier) from 3.2.4 to 3.2.5.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.2.4...3.2.5)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 22:12:58 +08:00
dependabot[bot]
3170f5b65a build(deps): bump swiper from 11.0.5 to 11.0.6 (#272)
Bumps [swiper](https://github.com/nolimits4web/Swiper) from 11.0.5 to 11.0.6.
- [Release notes](https://github.com/nolimits4web/Swiper/releases)
- [Changelog](https://github.com/nolimits4web/swiper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nolimits4web/Swiper/compare/v11.0.5...v11.0.6)

---
updated-dependencies:
- dependency-name: swiper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 22:12:31 +08:00
Spedon
bf1c5e21bc ci: prefine github action (#276)
* ci: migrate bundled artifacts update from pull request to direct commit

* ci: update lint workflow to include code formatting and auto-commit

* chore: update .prettierignore to include yaml files

- Remove the exclusion of `*.yaml` and `*.yml` files from being formatted by Prettier in the `.prettierignore` file.

* ci: update lint workflow conditions

* ci: format code

---------

Co-authored-by: Sped0n <Sped0n@users.noreply.github.com>
2024-02-06 22:03:50 +08:00
Spedon
d08e2c92b8 ci: update bundled artifacts (#270)
Co-authored-by: Sped0n <Sped0n@users.noreply.github.com>
2024-02-05 16:03:54 +08:00
Spedon
ba07636f8f refactor: prefine for version v1.0.2 (#269)
* refactor: refactor navigateVector logic and remove unused functions

* refactor: refactor HTML structure and styling in single.html

- Modify the `.info` class to `article` in `_article.scss`
- Remove the `nav.html` partial in `single.html`
- Change the class name from `info` to `article` in `single.html`
- Add the `nav.html` partial in `single.html`

* refactor: update handling of 404 page
- Now hugo will set unknown page title as "404"
- Add condition to return an empty image array if the document title starts with "404"

* docs: update documentation
2024-02-05 16:02:10 +08:00
Spedon
a98c6a4a60 ci: update bundled artifacts (#268)
Co-authored-by: Sped0n <Sped0n@users.noreply.github.com>
2024-02-04 00:47:15 +08:00
Spedon
c1414bbfc5 fix: fix mobile loading issue (#267)
* fix: update navigateVector reset behavior

* fix: remove unnecessary function call

* fix: update loading text to include ellipsis
2024-02-04 00:45:09 +08:00
131 changed files with 7398 additions and 4310 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

View File

@@ -1,3 +0,0 @@
node_modules
static
exampleSite

View File

@@ -1,56 +0,0 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"standard-with-typescript",
"prettier",
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/recommended"
],
"overrides": [],
"plugins": ["prettier", "@typescript-eslint"],
"parserOptions": {
"ecmaVersion": "latest",
"project": "./tsconfig.json",
"sourceType": "module"
},
"rules": {
"prettier/prettier": "error",
"arrow-body-style": "off",
"prefer-arrow-callback": "off",
"import/no-cycle": "error",
"@typescript-eslint/non-nullable-type-assertion-style": "off",
"sort-imports": [
"error",
{
"ignoreCase": false,
"ignoreDeclarationSort": true,
"ignoreMemberSort": false,
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
"allowSeparatedGroups": true
}
],
"import/no-unresolved": "error",
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal", "parent", "sibling", "index"],
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
]
},
"settings": {
"import/resolver": {
"typescript": {
"project": "./tsconfig.json"
}
}
}
}

View File

@@ -1,33 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- OS: [e.g. macOS]
- Browser [e.g. chrome, safari]
- Hugo Version [e.g. v0.114.0 extended]
**Additional context**
Add any other context about the problem here.

115
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@@ -0,0 +1,115 @@
name: Bug report
description: Create a bug report
labels:
- 'T: Bug'
- 'S: Untriaged'
body:
- type: markdown
attributes:
value: |
Please finish verify steps which list in the end first before create bug report
- type: textarea
id: reproduce
attributes:
label: Step to reproduce
description: |
Please write down the reproduction steps here and include the error log. If necessary, please provide screenshots or recordings.
placeholder: |
1.
2.
3.
[Screen recording]
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behaviour
description: |
Describe what should happened here
placeholder: |
It should be ...
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Behaviour
description: |
Describe what actually happened here, screenshots is better
placeholder: |
Actually it ...
[Screenshots]
validations:
required: true
- type: textarea
id: env
attributes:
label: Logs
description: |
CLI output or browser log.
placeholder: |
pnpm run server
> bridget@v1.0.0 server /Users/spedon/eden/hugo/bridget
> run-p vite:server hugo:server
validations:
required: false
- type: textarea
id: more
attributes:
label: Addition details
description: |
Describe addition details here
placeholder: |
Additional details and attachments
validations:
required: false
- type: input
id: hugo-version
attributes:
label: Hugo version
description: You can get version output with hugo --version
placeholder: v0.114.0
validations:
required: true
- type: input
id: bridget-version
attributes:
label: Bridget version
description: Release version or commit SHA
placeholder: v1.0.1 or 633f6a40e202a023471c58c09f05a92ec2130c93
validations:
required: true
- type: input
id: system
attributes:
label: OS version
description: OS + version code
placeholder: Windows 11, macOS 14
validations:
required: true
- type: checkboxes
id: check
attributes:
label: Verify steps
description: |
Please ensure you have obtained all needed options
options:
- label: Pull request is welcome. Check this if you want to start a pull request
required: false
- label: I have searched on [Issue Tracker](https://github.com/Sped0n/bridget/issues), No duplicate or related open issue has been found
required: true
- label: Ensure there is only one bug report in this issue. Please make mutiply issue for mutiply bugs
required: true

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: All other questions
url: https://github.com/Sped0n/bridget/discussions
about: Turn to discussions

View File

@@ -1,19 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,60 @@
name: Feature request
description: Suggest an idea
labels:
- 'T: Feature'
- 'S: Untriaged'
body:
- type: markdown
attributes:
value: |
Please finish verify steps which list in the end first before suggest an idea
- type: textarea
id: request
attributes:
label: Requirement
description: |
Ddescribe what you need here.
placeholder: |
I want ABC feature ...
validations:
required: true
- type: textarea
id: impl
attributes:
label: Suggested implements
description: |
Describe your suggested implements here, It's recommend to add a photo if you are making a UI feature request.
placeholder: |
I recommend add ABC feature to DEF...
Photos (if exists)
validations:
required: true
- type: textarea
id: more
attributes:
label: Addition details
description: |
Describe addition details here
placeholder: |
Additional details and attachments
validations:
required: false
- type: checkboxes
id: check
attributes:
label: Verify steps
description: |
Please ensure you have obtained all needed options
options:
- label: Pull request is welcome. Check this if you want to start a pull request
required: false
- label: I have searched on [Issue Tracker](https://github.com/Sped0n/bridget/issues), No duplicate or related open issue has been found
required: true
- label: Ensure there is only one feature request in this issue. Please make mutiply issue for mutiply feature request
required: true

View File

@@ -12,82 +12,72 @@ permissions:
contents: write
jobs:
filter:
runs-on: ubuntu-latest
name: Filter
outputs:
any_changed: ${{ steps.changed-files-specific.outputs.any_changed }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get changed files in scope
id: changed-files-specific
uses: tj-actions/changed-files@v41
with:
files: |
package.json
assets/**
build:
timeout-minutes: 30
runs-on: ubuntu-latest
name: Build
needs: [filter]
if: |
github.ref == 'refs/heads/main' &&
github.event.repository.fork == false
name: Build (Hugo ${{ matrix.hugo-label }})
if: github.event.repository.fork == false
strategy:
matrix:
hugo-version: ['latest', '0.114.0']
include:
- hugo-version: latest
hugo-label: Latest
- hugo-version: '0.114.0'
hugo-label: 'v0.114.0'
steps:
- name: Set current date as env variable
run: |
echo "builddate=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
id: version
- name: Checkout
uses: actions/checkout@v3
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.114.0'
extended: true
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Get pnpm store directory
id: pnpm-cache
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@v3
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store-
- name: Setup hugo cache
uses: actions/cache@v3
with:
path: ./exampleSite/resources
key: ${{ runner.os }}-hugo-${{ hashFiles('./exampleSite') }}
restore-keys: ${{ runner.os }}-hugo-
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build
- name: Push artifacts
if: ${{ (github.event_name == 'push' || github.event.pull_request.merged == true) && needs.filter.outputs.any_changed == 'true' }}
uses: peter-evans/create-pull-request@v5
uses: actions/checkout@v6
with:
token: ${{ secrets.PAT }}
title: "ci: update bundled artifacts"
commit-message: "ci: update bundled artifacts"
branch: update-artifacts-${{ steps.version.outputs.builddate }}
base: main
- name: Setup Mise
uses: jdx/mise-action@v3
with:
install_args: node@latest pnpm@10 hugo-extended@${{ matrix.hugo-version }}
tool_versions: |
node latest
pnpm 10
hugo-extended ${{ matrix.hugo-version }}
cache: true
- name: Get pnpm store path
id: pnpm-cache
run: 'echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT'
- name: Setup pnpm cache
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: pnpm-store-${{ hashFiles('./pnpm-lock.yaml') }}
restore-keys: |
pnpm-store-
- name: Setup Hugo cache
uses: actions/cache@v5
with:
path: exampleSite/resources/_gen
key: hugo-${{ matrix.hugo-version }}-${{ hashFiles('./exampleSite/**/*.jpg') }}
restore-keys: |
hugo-${{ matrix.hugo-version }}-
- name: Install project dependencies
run: 'pnpm install'
- name: Pre-build cleanup
if: >
matrix.hugo-version == 'latest' &&
(github.event_name == 'push' || github.event.pull_request.merged == true)
run: 'rm -rf bundled'
- name: Build
run: 'pnpm run build'
- name: Push artifacts
if: >
matrix.hugo-version == 'latest' &&
(github.event_name == 'push' || github.event.pull_request.merged == true)
uses: stefanzweifel/git-auto-commit-action@v7
with:
file_pattern: 'bundled/**/*.js bundled/**/*.css'
commit_message: 'ci: update bundled artifacts [skip ci]'

View File

@@ -46,11 +46,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -64,7 +64,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -77,6 +77,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: '/language:${{matrix.language}}'

View File

@@ -1,42 +0,0 @@
name: 'ESLint && Prettier'
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
permissions:
contents: write
jobs:
lint:
runs-on: ubuntu-latest
name: Lint
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Get pnpm store directory
id: pnpm-cache
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@v3
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- name: Lint
run: pnpm run lint:check

58
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: 'Lint'
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
permissions:
contents: write
jobs:
lint:
runs-on: ubuntu-latest
name: Lint
steps:
- name: Checkout
uses: actions/checkout@v6
with:
# github.token as a fallback, since other user might trigger this
# workflow in their pull request
token: ${{ secrets.PAT || github.token }}
- name: Setup Mise
uses: jdx/mise-action@v3
with:
install_args: node@latest pnpm@10
tool_versions: |
node latest
pnpm 10
cache: true
- name: Get pnpm store path
id: pnpm-cache
run: 'echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT'
- name: Setup pnpm cache
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: pnpm-store-${{ hashFiles('./pnpm-lock.yaml') }}
restore-keys: |
pnpm-store-
- name: Install project dependencies
run: 'pnpm install'
- name: Lint
id: lint
run: 'pnpm run lint:check || pnpm run lint'
- name: Commit
if: ${{ steps.format.lint == 'success' }}
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: 'ci: lint [skip ci]'

5
.gitignore vendored
View File

@@ -1,6 +1,6 @@
# Hugo default output directory
public/
/exampleSite/resources/
exampleSite/resources/
node_modules/
build/
@@ -25,3 +25,6 @@ jsconfig.json
# css map
*.css.map
# dummmy file
bundled/js/critical.js

View File

@@ -1,6 +1,6 @@
node_modules
static
exmapleSite
*.yaml
*.yml
node_modules/
static/
exmapleSite/
single.json
pnpm-lock.yaml
bundled/

View File

@@ -1,18 +0,0 @@
{
"useTabs": false,
"tabWidth": 2,
"printWidth": 88,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"semi": false,
"plugins": ["prettier-plugin-go-template", "prettier-plugin-organize-imports"],
"overrides": [
{
"files": ["*.html"],
"options": {
"parser": "go-template"
}
}
]
}

View File

@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
hi@sped0nwen.com.
hi@sped0n.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -2,47 +2,41 @@
![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/Sped0n/bridget/build.yml?logo=github) ![GitHub deployments](https://img.shields.io/github/deployments/Sped0n/bridget/Production?logo=vercel&label=deploy)
Bridget is a minimal [Hugo](https://gohugo.io) theme designed for photographers / visual artists.
Bridget is a minimal [Hugo](https://gohugo.io) theme for photographers/visual artists, based on https://github.com/tylermcrobert/bridget-pictures-www.
Its based on the https://github.com/tylermcrobert/bridget-pictures-www.
Here is a [live demo](https://bridget-demo.sped0n.com).
![thumbnail](images/tn.jpg)
![thumbnail](https://raw.githubusercontent.com/Sped0n/bridget/main/images/tn.jpg)
## [Demo Site](https://bridget-demo.sped0nwen.com)
To see this theme in action, here is a live [demo site](https://bridget-demo.sped0nwen.com) which is rendered with **Bridget** theme.
> [!NOTE]
> This repository is currently in **maintaince mode** for two reasons:
>
> 1. I want to keep this theme minimal.
> 2. My bandwith after work is limited.
>
> BUT, bug fixes will be addressed (including related issues and PRs), and they are the **number one priority** for this project.
>
> Please understand that feature request might **NOT** be addressed or may take a long time to be implemented.
>
> Anyway, forks are welcomed, and I'm looking forward to seeing what you can do with the theme.
## Getting Started
Head to this [documentation](https://github.com/Sped0n/bridget/blob/main/doc/getStarted.md) for a complete guidance to get started with the Bridget theme.
Head to this [documentation](https://github.com/Sped0n/bridget/blob/main/docs.md) for a complete guidance to get started with the theme.
## Features
- **Blazingly fast**: 99/100 on mobile and 100/100 on desktop in [Google PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights)
- JS **dynamic loading** (powered by ES6 syntax)
- JS **code splitting** by [rollup.js](https://rollupjs.org)
- Image **Preloading**/**Lazy loading**
- **Blazingly fast**: 100/100 on both desktop and mobile in [Google PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights)
- Powered by **[SolidJS](https://www.solidjs.com)**, a declarative, efficient, and flexible JavaScript library for building user interfaces
- JS **dynamic loading**
- Image **preloading** + **lazy loading**
- **Dynamic resolution** based on view mode
- Multiple **analytics** services supported
- Search engine **verification** supported (Google, Bind, Yandex and Baidu)
## Multilingual and i18n
Bridget supports the following languages:
- English
- Simplified Chinese
- Traditional Chinese
- Japanese
- Korean
- Deutsch
- Spanish
- Italian
- [Contribute with a new language](https://github.com/Sped0n/bridget/pulls)
## Credits
- https://github.com/tylermcrobert/bridget-pictures-www
- https://www.youtube.com/watch?v=Jt3A2lNN2aE
- https://github.com/d4cho/bridget-pictures-clone
- https://www.solidjs.com/tutorial

View File

@@ -17,7 +17,3 @@ a,
button {
cursor: pointer;
}
.hide {
display: none;
}

View File

@@ -1,48 +1,10 @@
@font-face {
font-family: 'Geist';
src:
url('/lib/fonts/GeistVF.woff2') format('woff2 supports variations'),
url('/lib/fonts/GeistVF.woff2') format('woff2-variations');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Noto Sans CJK SC';
src: url('/lib/fonts/NotoSansCJKsc-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Noto Sans CJK TC';
src: url('/lib/fonts/NotoSansCJKtc-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Noto Sans CJK JP';
src: url('/lib/fonts/NotoSansCJKjp-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Noto Sans CJK KR';
src: url('/lib/fonts/NotoSansCJKkr-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Noto Sans';
src: url('/lib/fonts/NotoSans-Regular.woff2') format('woff2');
url(/* @vite-ignore */'{{- "lib/fonts/GeistVF.woff2" | absURL -}}')
format('woff2 supports variations'),
url(/* @vite-ignore */'{{- "lib/fonts/GeistVF.woff2" | absURL -}}')
format('woff2-variations');
font-weight: 400;
font-style: normal;
font-display: swap;
@@ -50,7 +12,7 @@
@font-face {
font-family: 'FW';
src: url('/lib/fonts/fw.woff2') format('woff2');
src: url(/* @vite-ignore */'{{- "lib/fonts/fw.woff2" | absURL -}}') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;

View File

@@ -0,0 +1,4 @@
@forward 'reset';
@forward 'font';
@forward 'typography';
@forward 'mixins';

View File

@@ -1,3 +1,5 @@
@use 'sass:map';
$breakpoints: (
'mobile': 375px,
'tablet': 768px,
@@ -8,8 +10,8 @@ $breakpoints: (
// Breakpoints
@mixin min-width($breakpoint) {
@if map-has-key($breakpoints, $breakpoint) {
@media (min-width: map-get($breakpoints, $breakpoint)) {
@if map.has-key($breakpoints, $breakpoint) {
@media (min-width: map.get($breakpoints, $breakpoint)) {
@content;
}
} @else {
@@ -18,8 +20,8 @@ $breakpoints: (
}
@mixin max-width($breakpoint) {
@if map-has-key($breakpoints, $breakpoint) {
@media (max-width: (map-get($breakpoints, $breakpoint) - 1px)) {
@if map.has-key($breakpoints, $breakpoint) {
@media (max-width: (map.get($breakpoints, $breakpoint) - 1px)) {
@content;
}
} @else {

View File

@@ -1,12 +1,12 @@
@import 'mixins';
@use 'mixins' as *;
body {
line-height: 1.2;
font-size: 16px;
font-family: sans-serif;
font-family: 'Geist', sans-serif;
button {
font-family: 'FW';
font-family: 'FW', sans-serif;
}
@include min-width('tablet') {
@@ -16,51 +16,3 @@ body {
font-size: 19px;
}
}
body:lang(en) {
font-family: 'Geist', sans-serif;
}
body:lang(de) {
font-family: 'Geist', sans-serif;
}
body:lang(es) {
font-family: 'Geist', sans-serif;
}
body:lang(fr) {
font-family: 'Geist', sans-serif;
}
body:lang(it) {
font-family: 'Geist', sans-serif;
}
body:lang(zh-cn) {
font-family: 'Noto Sans', 'Noto Sans CJK SC', sans-serif;
}
body:lang(zh-sg) {
font-family: 'Noto Sans', 'Noto Sans CJK SC', sans-serif;
}
body:lang(zh-hk) {
font-family: 'Noto Sans', 'Noto Sans CJK TC', sans-serif;
}
body:lang(zh-mo) {
font-family: 'Noto Sans', 'Noto Sans CJK TC', sans-serif;
}
body:lang(zh-tw) {
font-family: 'Noto Sans', 'Noto Sans CJK TC', sans-serif;
}
body:lang(ja) {
font-family: 'Noto Sans', 'Noto Sans CJK JP', sans-serif;
}
body:lang(ko) {
font-family: 'Noto Sans', 'Noto Sans CJK KR', sans-serif;
}

View File

@@ -1,4 +1,10 @@
.info {
@use 'sass:map';
@use '_core/mixins' as *;
$tablet: map.get($breakpoints, 'tablet') - 1;
article {
padding: var(--space-standard);
max-width: 25em;
@@ -42,7 +48,7 @@
}
@media (max-width: $tablet), (hover: none) {
.info {
article {
margin-top: var(--nav-height);
}
}

View File

@@ -3,12 +3,12 @@
flex-direction: column;
gap: 20vh;
padding-top: 50vh;
padding-top: calc(var(--window-height) * 0.4);
margin-top: calc(var(--nav-height) * -1);
img {
position: sticky;
top: 50vh;
top: calc(var(--window-height) * 0.4);
width: 60vw;
height: 20vh;
@@ -19,7 +19,7 @@
align-self: center;
&:last-child {
margin-bottom: 20vh;
margin-bottom: calc(var(--window-height) * 0.35);
}
}
}

View File

@@ -1,4 +1,8 @@
$tablet: map-get($breakpoints, 'tablet') - 1;
@use 'sass:map';
@use '_core/mixins' as *;
$tablet: map.get($breakpoints, 'tablet') - 1;
@media (max-width: $tablet), (hover: none) {
.container {

View File

@@ -4,6 +4,7 @@
position: fixed;
top: var(--nav-height);
z-index: var(--z-nav-gallery);
overflow: hidden;
display: flex;
flex-direction: column;
@@ -25,8 +26,9 @@
}
img {
width: 100%;
height: 100%;
max-height: calc(var(--window-height) - 2 * var(--nav-height));
max-width: 100%;
width: auto;
object-fit: contain;
}
@@ -49,6 +51,21 @@
display: flex;
justify-content: space-between;
align-items: center;
.navClose {
cursor: pointer;
z-index: calc(var(--z-nav-gallery) + 1);
min-width: 25%;
height: calc(var(--nav-height) * 2.5);
display: flex;
align-items: center;
justify-content: flex-end;
margin-right: calc(var(--space-standard) * -1);
padding-right: var(--space-standard);
}
}
}

View File

@@ -1,4 +1,8 @@
$tablet: map-get($breakpoints, 'tablet') - 1;
@use 'sass:map';
@use '_core/mixins' as *;
$tablet: map.get($breakpoints, 'tablet') - 1;
nav {
display: flex;

View File

@@ -1,5 +1,3 @@
@import '_core/mixins';
:root {
--window-height: 100vh;
--nav-height: 2rem;

View File

@@ -1,12 +1,9 @@
@charset "utf-8";
@import '_core/reset';
@import '_core/font';
@import '_core/typography';
@import '_core/mixins';
@import '_variables';
@import '_core/base';
@use '_core/foundation';
@use '_variables';
@use '_core/base';
@import '_partial/nav';
@import '_partial/article';
@import '_partial/container';
@use '_partial/nav';
@use '_partial/article';
@use '_partial/container';

View File

@@ -1,10 +1,9 @@
@charset "utf-8";
@import '_partial/customCursor';
@import '_partial/stage';
@import '_partial/stageNav';
@use '_partial/customCursor';
@use '_partial/stage';
@use '_partial/stageNav';
@use '_partial/collection';
@use '_partial/gallery';
@import '_partial/collection';
@import '_partial/gallery';
@import 'node_modules/swiper/swiper.scss';
@use '../../node_modules/swiper/swiper.css';

91
assets/ts/configState.tsx Normal file
View File

@@ -0,0 +1,91 @@
import {
createContext,
createMemo,
createSignal,
useContext,
type Accessor,
type JSX
} from 'solid-js'
import invariant from 'tiny-invariant'
import { getThresholdSessionIndex } from './utils'
export interface ThresholdRelated {
threshold: number
trailLength: number
}
export interface ConfigState {
thresholdIndex: number
threshold: number
trailLength: number
}
export type ConfigStateContextType = readonly [
Accessor<ConfigState>,
{
readonly incThreshold: () => void
readonly decThreshold: () => void
}
]
const thresholds: ThresholdRelated[] = [
{ threshold: 20, trailLength: 20 },
{ threshold: 40, trailLength: 10 },
{ threshold: 80, trailLength: 5 },
{ threshold: 140, trailLength: 5 },
{ threshold: 200, trailLength: 5 }
]
const ConfigStateContext = createContext<ConfigStateContextType>()
function getSafeThresholdIndex(): number {
const index = getThresholdSessionIndex()
if (index < 0 || index >= thresholds.length) return 2
return index
}
export function ConfigStateProvider(props: { children?: JSX.Element }): JSX.Element {
const [thresholdIndex, setThresholdIndex] = createSignal(getSafeThresholdIndex())
const state = createMemo<ConfigState>(() => {
const current = thresholds[thresholdIndex()]
return {
thresholdIndex: thresholdIndex(),
threshold: current.threshold,
trailLength: current.trailLength
}
})
const updateThreshold = (stride: number): void => {
const nextIndex = thresholdIndex() + stride
if (nextIndex < 0 || nextIndex >= thresholds.length) return
sessionStorage.setItem('thresholdsIndex', nextIndex.toString())
setThresholdIndex(nextIndex)
}
return (
<ConfigStateContext.Provider
value={[
state,
{
incThreshold: () => {
updateThreshold(1)
},
decThreshold: () => {
updateThreshold(-1)
}
}
]}
>
{props.children}
</ConfigStateContext.Provider>
)
}
export function useConfigState(): ConfigStateContextType {
const context = useContext(ConfigStateContext)
invariant(context, 'undefined config context')
return context
}

View File

@@ -1,29 +0,0 @@
import { Watchable } from './globalUtils'
export const scrollable = new Watchable<boolean>(true)
export let container: Container
/**
* interfaces
*/
export interface Container extends HTMLDivElement {
dataset: {
next: string
close: string
prev: string
loading: string
}
}
export function initContainer(): void {
container = document.getElementsByClassName('container').item(0) as Container
scrollable.addWatcher((o) => {
if (o) {
container.classList.remove('disableScroll')
} else {
container.classList.add('disableScroll')
}
})
}

2
assets/ts/critical.ts Normal file
View File

@@ -0,0 +1,2 @@
// this is a dummy file to trick vite to generate a critical.css file
import '../scss/critical.scss'

View File

@@ -1,48 +0,0 @@
import { container } from '../container'
import { active } from './state'
/**
* variables
*/
const cursor = document.createElement('div')
const cursorInner = document.createElement('div')
/**
* main functions
*/
function onMouse(e: MouseEvent): void {
const x = e.clientX
const y = e.clientY
cursor.style.transform = `translate3d(${x}px, ${y}px, 0)`
}
export function setCustomCursor(text: string): void {
cursorInner.innerText = text
}
/**
* init
*/
export function initCustomCursor(): void {
// cursor class name
cursor.className = 'cursor'
// cursor inner class name
cursorInner.className = 'cursorInner'
// append cursor inner to cursor
cursor.append(cursorInner)
// append cursor to main
container.append(cursor)
// bind mousemove event to window
window.addEventListener('mousemove', onMouse, { passive: true })
// add active callback
active.addWatcher((o) => {
if (o) {
cursor.classList.add('active')
} else {
cursor.classList.remove('active')
}
})
}

View File

@@ -0,0 +1,51 @@
import { createSignal, onCleanup, onMount, type Accessor, type JSX } from 'solid-js'
export default function CustomCursor(props: {
children?: JSX.Element
active: Accessor<boolean>
cursorText: Accessor<string>
}): JSX.Element {
// types
interface XY {
x: number
y: number
}
// variables
let controller: AbortController | undefined
// states
const [xy, setXy] = createSignal<XY>({ x: 0, y: 0 })
// helper functions
const onMouse: (e: MouseEvent) => void = (e) => {
const { clientX, clientY } = e
setXy({ x: clientX, y: clientY })
}
// effects
onMount(() => {
controller = new AbortController()
const abortSignal = controller.signal
window.addEventListener('mousemove', onMouse, {
passive: true,
signal: abortSignal
})
})
onCleanup(() => {
controller?.abort()
})
return (
<>
<div
class="cursor"
classList={{ active: props.active() }}
style={{ transform: `translate3d(${xy().x}px, ${xy().y}px, 0)` }}
>
<div class="cursorInner">{props.cursorText()}</div>
</div>
</>
)
}

View File

@@ -1,15 +0,0 @@
import { type ImageJSON } from '../resources'
import { initCustomCursor } from './customCursor'
import { initStage } from './stage'
import { initStageNav } from './stageNav'
/**
* main functions
*/
export function initDesktop(ijs: ImageJSON[]): void {
initCustomCursor()
initStage(ijs)
initStageNav()
}

View File

@@ -0,0 +1,61 @@
import { Show, createMemo, type JSX } from 'solid-js'
import { useImageState } from '../imageState'
import CustomCursor from './customCursor'
import Nav from './nav'
import Stage from './stage'
import StageNav from './stageNav'
import { useDesktopState } from './state'
/**
* interfaces and types
*/
export interface DesktopImage extends HTMLImageElement {
dataset: {
hiUrl: string
hiImgH: string
hiImgW: string
loUrl: string
loImgH: string
loImgW: string
}
}
/**
* components
*/
export default function Desktop(props: {
children?: JSX.Element
prevText: string
closeText: string
nextText: string
loadingText: string
}): JSX.Element {
const imageState = useImageState()
const [desktop] = useDesktopState()
const active = createMemo(() => desktop.isOpen() && !desktop.isAnimating())
const cursorText = createMemo(() =>
desktop.isLoading() ? props.loadingText : desktop.hoverText()
)
return (
<>
<Nav />
<Show when={imageState().length > 0}>
<Stage />
<Show when={desktop.isOpen()}>
<CustomCursor cursorText={cursorText} active={active} />
<StageNav
prevText={props.prevText}
closeText={props.closeText}
nextText={props.nextText}
/>
</Show>
</Show>
</>
)
}

68
assets/ts/desktop/nav.tsx Normal file
View File

@@ -0,0 +1,68 @@
import { createEffect, onCleanup, onMount } from 'solid-js'
import { useConfigState } from '../configState'
import { useImageState } from '../imageState'
import { expand } from '../utils'
import { useDesktopState } from './state'
export default function Nav(): null {
let thresholdNums: HTMLSpanElement[] = []
let indexNums: HTMLSpanElement[] = []
let decButton: HTMLButtonElement | undefined
let incButton: HTMLButtonElement | undefined
let controller: AbortController | undefined
const imageState = useImageState()
const [config, { incThreshold, decThreshold }] = useConfigState()
const [desktop] = useDesktopState()
const updateThresholdText = (thresholdValue: string): void => {
thresholdNums.forEach((element, i) => {
element.innerText = thresholdValue[i]
})
}
const updateIndexText = (indexValue: string, indexLength: string): void => {
indexNums.forEach((element, i) => {
if (i < 4) {
element.innerText = indexValue[i]
} else {
element.innerText = indexLength[i - 4]
}
})
}
onMount(() => {
const thresholdDiv = document.getElementsByClassName(
'threshold'
)[0] as HTMLDivElement
const indexDiv = document.getElementsByClassName('index').item(0) as HTMLDivElement
thresholdNums = Array.from(
thresholdDiv.getElementsByClassName('num')
) as HTMLSpanElement[]
indexNums = Array.from(indexDiv.getElementsByClassName('num')) as HTMLSpanElement[]
decButton = thresholdDiv.getElementsByClassName('dec').item(0) as HTMLButtonElement
incButton = thresholdDiv.getElementsByClassName('inc').item(0) as HTMLButtonElement
controller = new AbortController()
const signal = controller.signal
decButton.addEventListener('click', decThreshold, { signal })
incButton.addEventListener('click', incThreshold, { signal })
})
createEffect(() => {
if (thresholdNums.length === 0 || indexNums.length === 0) return
updateIndexText(expand(desktop.index() + 1), expand(imageState().length))
updateThresholdText(expand(config().threshold))
})
onCleanup(() => {
controller?.abort()
})
return null
}

View File

@@ -1,368 +0,0 @@
import { type Power3, type gsap } from 'gsap'
import { container } from '../container'
import { incIndex, isAnimating, navigateVector, state } from '../globalState'
import { decrement, increment, loadGsap } from '../globalUtils'
import { type ImageJSON } from '../resources'
import { active, cordHist, isLoading, isOpen } from './state'
// eslint-disable-next-line sort-imports
import { onMutation, type DesktopImage } from './utils'
/**
* variables
*/
let imgs: DesktopImage[] = []
let last = { x: 0, y: 0 }
let _gsap: typeof gsap
let _Power3: typeof Power3
let gsapLoaded = false
/**
* getter
*/
function getTrailElsIndex(): number[] {
return cordHist.get().map((item) => item.i)
}
function getTrailCurrentElsIndex(): number[] {
return getTrailElsIndex().slice(-state.get().trailLength)
}
function getTrailInactiveElsIndex(): number[] {
const trailCurrentElsIndex = getTrailCurrentElsIndex()
return trailCurrentElsIndex.slice(0, trailCurrentElsIndex.length - 1)
}
function getCurrentElIndex(): number {
const trailElsIndex = getTrailElsIndex()
return trailElsIndex[trailElsIndex.length - 1]
}
function getPrevElIndex(): number {
const c = cordHist.get()
const s = state.get()
return decrement(c[c.length - 1].i, s.length)
}
function getNextElIndex(): number {
const c = cordHist.get()
const s = state.get()
return increment(c[c.length - 1].i, s.length)
}
/**
* main functions
*/
// on mouse
function onMouse(e: MouseEvent): void {
if (isOpen.get() || isAnimating.get()) return
if (!gsapLoaded) {
loadLib()
return
}
const cord = { x: e.clientX, y: e.clientY }
const travelDist = Math.hypot(cord.x - last.x, cord.y - last.y)
if (travelDist > state.get().threshold) {
last = cord
incIndex()
const newHist = { i: state.get().index, ...cord }
cordHist.set([...cordHist.get(), newHist].slice(-state.get().length))
}
}
// set image position with gsap (in both stage and navigation)
function setPositions(): void {
const trailElsIndex = getTrailElsIndex()
if (trailElsIndex.length === 0 || !gsapLoaded) return
const elsTrail = getImagesWithIndexArray(trailElsIndex)
_gsap.set(elsTrail, {
x: (i: number) => cordHist.get()[i].x - window.innerWidth / 2,
y: (i: number) => cordHist.get()[i].y - window.innerHeight / 2,
opacity: (i: number) =>
i + 1 + state.get().trailLength <= cordHist.get().length ? 0 : 1,
zIndex: (i: number) => i,
scale: 0.6
})
if (isOpen.get()) {
const elc = getImagesWithIndexArray([getCurrentElIndex()])[0]
elc.classList.add('hide') // hide image to prevent flash
const indexArrayToHires: number[] = []
switch (navigateVector.get()) {
case 'prev':
indexArrayToHires.push(getPrevElIndex())
break
case 'next':
indexArrayToHires.push(getNextElIndex())
break
default:
break
}
hires(getImagesWithIndexArray(indexArrayToHires)) // preload
setLoaderForImage(elc)
_gsap.set(imgs, { opacity: 0 })
_gsap.set(elc, { opacity: 1, x: 0, y: 0, scale: 1 })
} else {
lores(elsTrail)
}
}
// open image into navigation
function expandImage(): void {
if (isAnimating.get()) return
isOpen.set(true)
isAnimating.set(true)
const elcIndex = getCurrentElIndex()
const elc = getImagesWithIndexArray([elcIndex])[0]
// don't hide here because we want a better transition
// elc.classList.add('hide')
hires(getImagesWithIndexArray([elcIndex, getPrevElIndex(), getNextElIndex()]))
setLoaderForImage(elc)
const tl = _gsap.timeline()
const trailInactiveEls = getImagesWithIndexArray(getTrailInactiveElsIndex())
// move down and hide trail inactive
tl.to(trailInactiveEls, {
y: '+=20',
ease: _Power3.easeIn,
stagger: 0.075,
duration: 0.3,
delay: 0.1,
opacity: 0
})
// current move to center
tl.to(elc, {
x: 0,
y: 0,
ease: _Power3.easeInOut,
duration: 0.7,
delay: 0.3
})
// current expand
tl.to(elc, {
delay: 0.1,
scale: 1,
ease: _Power3.easeInOut
})
// finished
tl.then(() => {
isAnimating.set(false)
}).catch((e) => {
console.log(e)
})
}
// close navigation and back to stage
export function minimizeImage(): void {
if (isAnimating.get()) return
isOpen.set(false)
isAnimating.set(true)
navigateVector.set('none') // cleanup
lores(
getImagesWithIndexArray([...getTrailInactiveElsIndex(), ...[getCurrentElIndex()]])
)
const tl = _gsap.timeline()
const elc = getImagesWithIndexArray([getCurrentElIndex()])[0]
const elsTrailInactive = getImagesWithIndexArray(getTrailInactiveElsIndex())
// shrink current
tl.to(elc, {
scale: 0.6,
duration: 0.6,
ease: _Power3.easeInOut
})
// move current to original position
tl.to(elc, {
delay: 0.3,
duration: 0.7,
ease: _Power3.easeInOut,
x: cordHist.get()[cordHist.get().length - 1].x - window.innerWidth / 2,
y: cordHist.get()[cordHist.get().length - 1].y - window.innerHeight / 2
})
// show trail inactive
tl.to(elsTrailInactive, {
y: '-=20',
ease: _Power3.easeOut,
stagger: -0.1,
duration: 0.3,
opacity: 1
})
// finished
tl.then(() => {
isAnimating.set(false)
}).catch((e) => {
console.log(e)
})
}
/**
* init
*/
export function initStage(ijs: ImageJSON[]): void {
// create stage element
createStage(ijs)
// get stage
const stage = document.getElementsByClassName('stage').item(0) as HTMLDivElement
// get image elements
imgs = Array.from(stage.getElementsByTagName('img')) as DesktopImage[]
imgs.forEach((img, i) => {
// preload first 5 images on page load
if (i < 5) {
img.src = img.dataset.loUrl
}
// lores preloader for rest of the images
onMutation(img, (mutations, observer) => {
mutations.every((mutation) => {
// if open or animating, skip
if (isOpen.get() || isAnimating.get()) return true
// if mutation is not about style attribute, skip
if (mutation.attributeName !== 'style') return true
const opacity = parseFloat(img.style.opacity)
// if opacity is not 1, skip
if (opacity !== 1) return true
// preload the i + 5th image
if (i + 5 < imgs.length) {
imgs[i + 5].src = imgs[i + 5].dataset.loUrl
}
// disconnect observer and return false to break the loop
observer.disconnect()
return false
})
})
})
// event listeners
stage.addEventListener(
'click',
() => {
expandImage()
},
{ passive: true }
)
stage.addEventListener(
'keydown',
() => {
expandImage()
},
{ passive: true }
)
window.addEventListener('mousemove', onMouse, { passive: true })
// watchers
isOpen.addWatcher((o) => {
active.set(o && !isAnimating.get())
})
isAnimating.addWatcher((o) => {
active.set(isOpen.get() && !o)
})
cordHist.addWatcher((_) => {
setPositions()
})
// dynamic import
window.addEventListener(
'mousemove',
() => {
loadLib()
},
{ once: true, passive: true }
)
}
/**
* hepler
*/
function createStage(ijs: ImageJSON[]): void {
// create container for images
const stage: HTMLDivElement = document.createElement('div')
stage.className = 'stage'
// append images to container
for (const ij of ijs) {
const e = document.createElement('img') as DesktopImage
e.height = ij.loImgH
e.width = ij.loImgW
// set data attributes
e.dataset.hiUrl = ij.hiUrl
e.dataset.hiImgH = ij.hiImgH.toString()
e.dataset.hiImgW = ij.hiImgW.toString()
e.dataset.loUrl = ij.loUrl
e.dataset.loImgH = ij.loImgH.toString()
e.dataset.loImgW = ij.loImgW.toString()
e.alt = ij.alt
// append
stage.append(e)
}
container.append(stage)
}
function getImagesWithIndexArray(indexArray: number[]): DesktopImage[] {
return indexArray.map((i) => imgs[i])
}
function hires(imgs: DesktopImage[]): void {
imgs.forEach((img) => {
if (img.src === img.dataset.hiUrl) return
img.src = img.dataset.hiUrl
img.height = parseInt(img.dataset.hiImgH)
img.width = parseInt(img.dataset.hiImgW)
})
}
function lores(imgs: DesktopImage[]): void {
imgs.forEach((img) => {
if (img.src === img.dataset.loUrl) return
img.src = img.dataset.loUrl
img.height = parseInt(img.dataset.loImgH)
img.width = parseInt(img.dataset.loImgW)
})
}
function setLoaderForImage(e: HTMLImageElement): void {
if (!e.complete) {
isLoading.set(true)
e.addEventListener(
'load',
() => {
isLoading.set(false)
e.classList.remove('hide')
},
{ once: true, passive: true }
)
e.addEventListener(
'error',
() => {
isLoading.set(false)
},
{ once: true, passive: true }
)
} else {
e.classList.remove('hide')
isLoading.set(false)
}
}
function loadLib(): void {
loadGsap()
.then((g) => {
_gsap = g[0]
_Power3 = g[1]
gsapLoaded = true
})
.catch((e) => {
console.log(e)
})
}

235
assets/ts/desktop/stage.tsx Normal file
View File

@@ -0,0 +1,235 @@
import { type gsap } from 'gsap'
import { For, createEffect, on, onMount, type JSX } from 'solid-js'
import { useConfigState } from '../configState'
import { useImageState } from '../imageState'
import { increment, loadGsap } from '../utils'
import type { DesktopImage } from './layout'
import { expandStage, minimizeStage, syncStagePosition } from './stageAnimations'
import { onMutation } from './stageUtils'
import { useDesktopState } from './state'
export default function Stage(): JSX.Element {
let _gsap: typeof gsap
let gsapPromise: Promise<void> | undefined
const imageState = useImageState()
const [config] = useConfigState()
const [
desktop,
{ setIndex, setCordHist, setIsOpen, setIsAnimating, setIsLoading, setNavVector }
] = useDesktopState()
const imgs: DesktopImage[] = Array<DesktopImage>(imageState().length)
let last = { x: 0, y: 0 }
let abortController: AbortController | undefined
let gsapLoaded = false
let mounted = false
const ensureGsapReady: () => Promise<void> = async () => {
if (gsapPromise !== undefined) return await gsapPromise
gsapPromise = loadGsap()
.then((g) => {
_gsap = g
gsapLoaded = true
})
.catch((e) => {
gsapPromise = undefined
console.log(e)
})
await gsapPromise
}
const onMouse: (e: MouseEvent) => void = (e) => {
if (desktop.isOpen() || desktop.isAnimating() || !gsapLoaded || !mounted) return
const length = imageState().length
if (length <= 0) return
const cord = { x: e.clientX, y: e.clientY }
const travelDist = Math.hypot(cord.x - last.x, cord.y - last.y)
if (travelDist > config().threshold) {
const nextIndex = increment(desktop.index(), length)
last = cord
setIndex(nextIndex)
setCordHist((prev) => [...prev, { i: nextIndex, ...cord }].slice(-length))
}
}
const onClick: () => Promise<void> = async () => {
if (!gsapLoaded) {
await ensureGsapReady()
}
if (desktop.isAnimating() || !gsapLoaded) return
if (desktop.index() < 0 || desktop.cordHist().length === 0) return
setIsOpen(true)
}
const setPosition: () => void = () => {
syncStagePosition({
gsap: _gsap,
imgs,
cordHist: desktop.cordHist(),
trailLength: config().trailLength,
length: imageState().length,
isOpen: desktop.isOpen(),
navVector: desktop.navVector(),
mounted,
setIsLoading
})
}
const expandImage: () => Promise<void> = async () => {
if (!mounted || !gsapLoaded) throw new Error('not mounted or gsap not loaded')
await expandStage({
gsap: _gsap,
imgs,
cordHist: desktop.cordHist(),
trailLength: config().trailLength,
length: imageState().length,
mounted,
setIsLoading,
setIsAnimating
})
}
const minimizeImage: () => Promise<void> = async () => {
if (!mounted || !gsapLoaded) throw new Error('not mounted or gsap not loaded')
setNavVector('none')
await minimizeStage({
gsap: _gsap,
imgs,
cordHist: desktop.cordHist(),
trailLength: config().trailLength,
mounted,
setIsAnimating
})
}
onMount(() => {
imgs.forEach((img, i) => {
if (i < 5) {
img.src = img.dataset.loUrl
}
onMutation(img, (mutation) => {
if (desktop.isOpen() || desktop.isAnimating()) return false
if (mutation.attributeName !== 'style') return false
const opacity = parseFloat(img.style.opacity)
if (opacity !== 1) return false
if (i + 5 < imgs.length) {
imgs[i + 5].src = imgs[i + 5].dataset.loUrl
}
return true
})
})
window.addEventListener('pointermove', () => void ensureGsapReady(), {
passive: true,
once: true
})
window.addEventListener('pointerdown', () => void ensureGsapReady(), {
passive: true,
once: true
})
window.addEventListener('click', () => void ensureGsapReady(), {
passive: true,
once: true
})
abortController = new AbortController()
const abortSignal = abortController.signal
window.addEventListener('mousemove', onMouse, {
passive: true,
signal: abortSignal
})
mounted = true
})
createEffect(
on(
() => desktop.cordHist(),
() => {
setPosition()
},
{ defer: true }
)
)
createEffect(
on(
desktop.isOpen,
async (isOpen) => {
if (desktop.isAnimating()) return
if (isOpen) {
if (desktop.index() < 0 || desktop.cordHist().length === 0) {
setIsOpen(false)
return
}
await expandImage()
.catch(() => {
setIsOpen(false)
setIsAnimating(false)
setIsLoading(false)
})
.then(() => {
abortController?.abort()
})
} else {
await minimizeImage()
.catch(() => {
void 0
})
.then(() => {
abortController = new AbortController()
const abortSignal = abortController.signal
window.addEventListener('mousemove', onMouse, {
passive: true,
signal: abortSignal
})
setIsLoading(false)
})
}
},
{ defer: true }
)
)
return (
<>
<div class="stage" onClick={onClick} onKeyDown={onClick}>
<For each={imageState().images}>
{(ij, i) => (
<img
ref={imgs[i()]}
height={ij.loImgH}
width={ij.loImgW}
data-hi-url={ij.hiUrl}
data-hi-img-h={ij.hiImgH}
data-hi-img-w={ij.hiImgW}
data-lo-url={ij.loUrl}
data-lo-img-h={ij.loImgH}
data-lo-img-w={ij.loImgW}
alt={ij.alt}
/>
)}
</For>
</div>
</>
)
}

View File

@@ -0,0 +1,263 @@
import { type gsap } from 'gsap'
import type { Vector } from '../utils'
import type { DesktopImage } from './layout'
import {
getCurrentElIndex,
getImagesFromIndexes,
getNextElIndex,
getPrevElIndex,
getTrailElsIndex,
getTrailInactiveElsIndex,
hires,
lores
} from './stageUtils'
import type { HistoryItem } from './state'
type SetLoading = (value: boolean) => void
export function setLoaderForHiresImage(args: {
gsap: typeof gsap
img: DesktopImage
mounted: boolean
setIsLoading: SetLoading
}): void {
const { gsap, img, mounted, setIsLoading } = args
if (!mounted) return
if (img.complete) {
gsap
.set(img, { opacity: 1 })
.then(() => {
setIsLoading(false)
})
.catch((e) => {
console.log(e)
})
return
}
setIsLoading(true)
const controller = new AbortController()
const abortSignal = controller.signal
img.addEventListener(
'load',
() => {
gsap
.to(img, { opacity: 1, ease: 'power3.out', duration: 0.5 })
.then(() => {
setIsLoading(false)
})
.catch((e) => {
console.log(e)
})
.finally(() => {
controller.abort()
})
},
{ once: true, passive: true, signal: abortSignal }
)
img.addEventListener(
'error',
() => {
gsap
.set(img, { opacity: 1 })
.then(() => {
setIsLoading(false)
})
.catch((e) => {
console.log(e)
})
.finally(() => {
controller.abort()
})
},
{ once: true, passive: true, signal: abortSignal }
)
}
export function syncStagePosition(args: {
gsap: typeof gsap
imgs: DesktopImage[]
cordHist: HistoryItem[]
trailLength: number
length: number
isOpen: boolean
navVector: Vector
mounted: boolean
setIsLoading: SetLoading
}): void {
const {
gsap,
imgs,
cordHist,
trailLength,
length,
isOpen,
navVector,
mounted,
setIsLoading
} = args
if (!mounted || imgs.length === 0) return
const trailElsIndex = getTrailElsIndex(cordHist)
if (trailElsIndex.length === 0) return
const elsTrail = getImagesFromIndexes(imgs, trailElsIndex)
gsap.set(elsTrail, {
x: (i: number) => cordHist[i].x - window.innerWidth / 2,
y: (i: number) => cordHist[i].y - window.innerHeight / 2,
opacity: (i: number) =>
Math.max((i + 1 + trailLength <= cordHist.length ? 0 : 1) - (isOpen ? 1 : 0), 0),
zIndex: (i: number) => i,
scale: 0.6
})
if (!isOpen) {
lores(elsTrail)
return
}
const current = getImagesFromIndexes(imgs, [getCurrentElIndex(cordHist)])[0]
const indexArrayToHires: number[] = []
const indexArrayToCleanup: number[] = []
switch (navVector) {
case 'prev':
indexArrayToHires.push(getPrevElIndex(cordHist, length))
indexArrayToCleanup.push(getNextElIndex(cordHist, length))
break
case 'next':
indexArrayToHires.push(getNextElIndex(cordHist, length))
indexArrayToCleanup.push(getPrevElIndex(cordHist, length))
break
default:
break
}
hires(getImagesFromIndexes(imgs, indexArrayToHires))
gsap.set(getImagesFromIndexes(imgs, indexArrayToCleanup), { opacity: 0 })
gsap.set(current, { x: 0, y: 0, scale: 1 })
setLoaderForHiresImage({ gsap, img: current, mounted, setIsLoading })
}
export async function expandStage(args: {
gsap: typeof gsap
imgs: DesktopImage[]
cordHist: HistoryItem[]
trailLength: number
length: number
mounted: boolean
setIsLoading: SetLoading
setIsAnimating: (value: boolean) => void
}): Promise<void> {
const {
gsap,
imgs,
cordHist,
trailLength,
length,
mounted,
setIsLoading,
setIsAnimating
} = args
if (!mounted) throw new Error('not mounted')
setIsAnimating(true)
const currentIndex = getCurrentElIndex(cordHist)
const current = imgs[currentIndex]
hires(
getImagesFromIndexes(imgs, [
currentIndex,
getPrevElIndex(cordHist, length),
getNextElIndex(cordHist, length)
])
)
setLoaderForHiresImage({ gsap, img: current, mounted, setIsLoading })
const tl = gsap.timeline()
const trailInactiveEls = getImagesFromIndexes(
imgs,
getTrailInactiveElsIndex(cordHist, trailLength)
)
tl.to(trailInactiveEls, {
y: '+=20',
ease: 'power3.in',
stagger: 0.075,
duration: 0.3,
delay: 0.1,
opacity: 0
})
tl.to(current, {
x: 0,
y: 0,
ease: 'power3.inOut',
duration: 0.7,
delay: 0.3
})
tl.to(current, {
delay: 0.1,
scale: 1,
ease: 'power3.inOut'
})
await tl.then(() => {
setIsAnimating(false)
})
}
export async function minimizeStage(args: {
gsap: typeof gsap
imgs: DesktopImage[]
cordHist: HistoryItem[]
trailLength: number
mounted: boolean
setIsAnimating: (value: boolean) => void
}): Promise<void> {
const { gsap, imgs, cordHist, trailLength, mounted, setIsAnimating } = args
if (!mounted) throw new Error('not mounted')
setIsAnimating(true)
const currentIndex = getCurrentElIndex(cordHist)
const trailInactiveIndexes = getTrailInactiveElsIndex(cordHist, trailLength)
lores(getImagesFromIndexes(imgs, [...trailInactiveIndexes, currentIndex]))
const tl = gsap.timeline()
const current = getImagesFromIndexes(imgs, [currentIndex])[0]
const trailInactiveEls = getImagesFromIndexes(imgs, trailInactiveIndexes)
tl.to(current, {
scale: 0.6,
duration: 0.6,
ease: 'power3.inOut'
})
tl.to(current, {
delay: 0.3,
duration: 0.7,
ease: 'power3.inOut',
x: cordHist.slice(-1)[0].x - window.innerWidth / 2,
y: cordHist.slice(-1)[0].y - window.innerHeight / 2
})
tl.to(trailInactiveEls, {
y: '-=20',
ease: 'power3.out',
stagger: -0.1,
duration: 0.3,
opacity: 1
})
await tl.then(() => {
setIsAnimating(false)
})
}

View File

@@ -1,194 +0,0 @@
import { container } from '../container'
import { decIndex, incIndex, isAnimating, navigateVector, state } from '../globalState'
import { decrement, increment } from '../globalUtils'
import { setCustomCursor } from './customCursor'
import { minimizeImage } from './stage'
import { active, cordHist, isLoading, isOpen } from './state'
/**
* types
*/
type NavItem = (typeof navItems)[number]
/**
* variables
*/
const navItems = [
container.dataset.prev,
container.dataset.close,
container.dataset.next
] as const
const loadingText = container.dataset.loading + '...'
let loadedText = ''
/**
* main functions
*/
function handleClick(type: NavItem): void {
if (type === navItems[0]) {
prevImage()
} else if (type === navItems[1]) {
minimizeImage()
} else {
nextImage()
}
}
function handleKey(e: KeyboardEvent): void {
if (isOpen.get() || isAnimating.get()) return
switch (e.key) {
case 'ArrowLeft':
prevImage()
break
case 'Escape':
minimizeImage()
break
case 'ArrowRight':
nextImage()
break
}
}
/**
* init
*/
export function initStageNav(): void {
// isLoading
isLoading.addWatcher((o) => {
if (o) setCustomCursor(loadingText)
else setCustomCursor(loadedText)
})
// navOverlay
const navOverlay = document.createElement('div')
navOverlay.className = 'navOverlay'
for (const [index, navItem] of navItems.entries()) {
const overlay = document.createElement('div')
overlay.className = 'overlay'
const isClose = index === 1
// close
if (isClose) {
overlay.addEventListener(
'click',
() => {
handleCloseClick(navItem)
},
{ passive: true }
)
overlay.addEventListener(
'keydown',
() => {
handleCloseClick(navItem)
},
{ passive: true }
)
overlay.addEventListener(
'mouseover',
() => {
handleCloseHover(navItem)
},
{ passive: true }
)
overlay.addEventListener(
'focus',
() => {
handleCloseHover(navItem)
},
{ passive: true }
)
}
// prev and next
else {
overlay.addEventListener(
'click',
() => {
handlePNClick(navItem)
},
{ passive: true }
)
overlay.addEventListener(
'keydown',
() => {
handlePNClick(navItem)
},
{ passive: true }
)
overlay.addEventListener(
'mouseover',
() => {
handlePNHover(navItem)
},
{ passive: true }
)
overlay.addEventListener(
'focus',
() => {
handlePNHover(navItem)
},
{ passive: true }
)
}
navOverlay.append(overlay)
}
active.addWatcher(() => {
if (active.get()) {
navOverlay.classList.add('active')
} else {
navOverlay.classList.remove('active')
}
})
container.append(navOverlay)
window.addEventListener('keydown', handleKey, { passive: true })
}
/**
* hepler
*/
function nextImage(): void {
if (isAnimating.get()) return
navigateVector.set('next')
cordHist.set(
cordHist.get().map((item) => {
return { ...item, i: increment(item.i, state.get().length) }
})
)
incIndex()
}
function prevImage(): void {
if (isAnimating.get()) return
navigateVector.set('prev')
cordHist.set(
cordHist.get().map((item) => {
return { ...item, i: decrement(item.i, state.get().length) }
})
)
decIndex()
}
function handleCloseClick(navItem: NavItem): void {
handleClick(navItem)
isLoading.set(false)
}
function handleCloseHover(navItem: NavItem): void {
loadedText = navItem
setCustomCursor(navItem)
}
function handlePNClick(navItem: NavItem): void {
if (!isLoading.get()) handleClick(navItem)
}
function handlePNHover(navItem: NavItem): void {
loadedText = navItem
if (isLoading.get()) setCustomCursor(loadingText)
else setCustomCursor(navItem)
}

View File

@@ -0,0 +1,107 @@
import { For, createEffect, createMemo, on, onCleanup, type JSX } from 'solid-js'
import { useImageState } from '../imageState'
import { decrement, increment } from '../utils'
import { useDesktopState } from './state'
export default function StageNav(props: {
children?: JSX.Element
prevText: string
closeText: string
nextText: string
}): JSX.Element {
// types
type NavItem = (typeof navItems)[number]
// variables
let controller: AbortController | undefined
// eslint-disable-next-line solid/reactivity
const navItems = [props.prevText, props.closeText, props.nextText] as const
// states
const imageState = useImageState()
const [
desktop,
{ incIndex, decIndex, setCordHist, setHoverText, setIsOpen, setNavVector }
] = useDesktopState()
const active = createMemo(() => desktop.isOpen() && !desktop.isAnimating())
const prevImage: () => void = () => {
setNavVector('prev')
setCordHist((c) =>
c.map((item) => {
return { ...item, i: decrement(item.i, imageState().length) }
})
)
decIndex()
}
const closeImage: () => void = () => {
setIsOpen(false)
}
const nextImage: () => void = () => {
setNavVector('next')
setCordHist((c) =>
c.map((item) => {
return { ...item, i: increment(item.i, imageState().length) }
})
)
incIndex()
}
const handleClick: (item: NavItem) => void = (item) => {
if (!desktop.isOpen() || desktop.isAnimating()) return
if (item === navItems[0]) prevImage()
else if (item === navItems[1]) closeImage()
else nextImage()
}
const handleKey: (e: KeyboardEvent) => void = (e) => {
if (!desktop.isOpen() || desktop.isAnimating()) return
if (e.key === 'ArrowLeft') prevImage()
else if (e.key === 'Escape') closeImage()
else if (e.key === 'ArrowRight') nextImage()
}
createEffect(
on(desktop.isOpen, (isOpen) => {
controller?.abort()
if (isOpen) {
controller = new AbortController()
const abortSignal = controller.signal
window.addEventListener('keydown', handleKey, {
passive: true,
signal: abortSignal
})
}
})
)
onCleanup(() => {
controller?.abort()
})
return (
<>
<div class="navOverlay" classList={{ active: active() }}>
<For each={navItems}>
{(item) => (
<div
class="overlay"
onClick={() => {
handleClick(item)
}}
onFocus={() => setHoverText(item)}
onMouseOver={() => setHoverText(item)}
tabIndex="-1"
/>
)}
</For>
</div>
</>
)
}

View File

@@ -0,0 +1,67 @@
import { decrement, increment } from '../utils'
import type { DesktopImage } from './layout'
import type { HistoryItem } from './state'
export function getTrailElsIndex(cordHistValue: HistoryItem[]): number[] {
return cordHistValue.map((el) => el.i)
}
export function getTrailInactiveElsIndex(
cordHistValue: HistoryItem[],
trailLength: number
): number[] {
return getTrailElsIndex(cordHistValue).slice(-trailLength).slice(0, -1)
}
export function getCurrentElIndex(cordHistValue: HistoryItem[]): number {
return getTrailElsIndex(cordHistValue).slice(-1)[0]
}
export function getPrevElIndex(cordHistValue: HistoryItem[], length: number): number {
return decrement(cordHistValue.slice(-1)[0].i, length)
}
export function getNextElIndex(cordHistValue: HistoryItem[], length: number): number {
return increment(cordHistValue.slice(-1)[0].i, length)
}
export function getImagesFromIndexes(
imgs: DesktopImage[],
indexes: number[]
): DesktopImage[] {
return indexes.map((i) => imgs[i])
}
export function hires(imgs: DesktopImage[]): void {
imgs.forEach((img) => {
if (img.src === img.dataset.hiUrl) return
img.src = img.dataset.hiUrl
img.height = parseInt(img.dataset.hiImgH)
img.width = parseInt(img.dataset.hiImgW)
})
}
export function lores(imgs: DesktopImage[]): void {
imgs.forEach((img) => {
if (img.src === img.dataset.loUrl) return
img.src = img.dataset.loUrl
img.height = parseInt(img.dataset.loImgH)
img.width = parseInt(img.dataset.loImgW)
})
}
export function onMutation<T extends HTMLElement>(
element: T,
trigger: (arg0: MutationRecord) => boolean,
observeOptions: MutationObserverInit = { attributes: true }
): void {
new MutationObserver((mutations, observer) => {
for (const mutation of mutations) {
if (trigger(mutation)) {
observer.disconnect()
break
}
}
}).observe(element, observeOptions)
}

View File

@@ -1,8 +1,16 @@
import { Watchable } from '../globalUtils'
import {
createComponent,
createContext,
createSignal,
useContext,
type Accessor,
type JSX,
type Setter
} from 'solid-js'
import invariant from 'tiny-invariant'
/**
* types
*/
import { useImageState } from '../imageState'
import { decrement, increment, type Vector } from '../utils'
export interface HistoryItem {
i: number
@@ -10,11 +18,79 @@ export interface HistoryItem {
y: number
}
/**
* variables
*/
export interface DesktopState {
index: Accessor<number>
cordHist: Accessor<HistoryItem[]>
hoverText: Accessor<string>
isOpen: Accessor<boolean>
isAnimating: Accessor<boolean>
isLoading: Accessor<boolean>
navVector: Accessor<Vector>
}
export const cordHist = new Watchable<HistoryItem[]>([])
export const isOpen = new Watchable<boolean>(false)
export const active = new Watchable<boolean>(false)
export const isLoading = new Watchable<boolean>(false)
export type DesktopStateContextType = readonly [
DesktopState,
{
readonly setIndex: Setter<number>
readonly incIndex: () => void
readonly decIndex: () => void
readonly setCordHist: Setter<HistoryItem[]>
readonly setHoverText: Setter<string>
readonly setIsOpen: Setter<boolean>
readonly setIsAnimating: Setter<boolean>
readonly setIsLoading: Setter<boolean>
readonly setNavVector: Setter<Vector>
}
]
const DesktopStateContext = createContext<DesktopStateContextType>()
export function DesktopStateProvider(props: { children?: JSX.Element }): JSX.Element {
const imageState = useImageState()
const [index, setIndex] = createSignal(-1)
const [cordHist, setCordHist] = createSignal<HistoryItem[]>([])
const [hoverText, setHoverText] = createSignal('')
const [isOpen, setIsOpen] = createSignal(false)
const [isAnimating, setIsAnimating] = createSignal(false)
const [isLoading, setIsLoading] = createSignal(false)
const [navVector, setNavVector] = createSignal<Vector>('none')
const updateIndex = (stride: 1 | -1): void => {
const length = imageState().length
if (length <= 0) return
setIndex((current) =>
stride === 1 ? increment(current, length) : decrement(current, length)
)
}
return createComponent(DesktopStateContext.Provider, {
value: [
{ index, cordHist, hoverText, isOpen, isAnimating, isLoading, navVector },
{
setIndex,
incIndex: () => {
updateIndex(1)
},
decIndex: () => {
updateIndex(-1)
},
setCordHist,
setHoverText,
setIsOpen,
setIsAnimating,
setIsLoading,
setNavVector
}
],
get children() {
return props.children
}
})
}
export function useDesktopState(): DesktopStateContextType {
const context = useContext(DesktopStateContext)
invariant(context, 'undefined desktop context')
return context
}

View File

@@ -1,28 +0,0 @@
/**
* interfaces
*/
export interface DesktopImage extends HTMLImageElement {
dataset: {
hiUrl: string
hiImgH: string
hiImgW: string
loUrl: string
loImgH: string
loImgW: string
}
}
/**
* utils
*/
export function onMutation<T extends HTMLElement>(
element: T,
callback: (arg0: MutationRecord[], arg1: MutationObserver) => void,
observeOptions: MutationObserverInit = { attributes: true }
): void {
new MutationObserver((mutations, observer) => {
callback(mutations, observer)
}).observe(element, observeOptions)
}

View File

@@ -1,91 +0,0 @@
import {
Watchable,
decrement,
getThresholdSessionIndex,
increment
} from './globalUtils'
/**
* types
*/
export type State = typeof defaultState
export type NavVec = 'next' | 'none' | 'prev'
/**
* variables
*/
const thresholds = [
{ threshold: 20, trailLength: 20 },
{ threshold: 40, trailLength: 10 },
{ threshold: 80, trailLength: 5 },
{ threshold: 140, trailLength: 5 },
{ threshold: 200, trailLength: 5 }
]
const defaultState = {
index: -1,
length: 0,
threshold: thresholds[getThresholdSessionIndex()].threshold,
trailLength: thresholds[getThresholdSessionIndex()].trailLength
}
export const state = new Watchable<State>(defaultState)
export const isAnimating = new Watchable<boolean>(false)
export const navigateVector = new Watchable<NavVec>('none')
/**
* main functions
*/
export function initState(length: number): void {
const s = state.get()
s.length = length
updateThreshold(s, 0)
state.set(s)
}
export function setIndex(index: number): void {
const s = state.get()
s.index = index
state.set(s)
}
export function incIndex(): void {
const s = state.get()
s.index = increment(s.index, s.length)
state.set(s)
}
export function decIndex(): void {
const s = state.get()
s.index = decrement(s.index, s.length)
state.set(s)
}
export function incThreshold(): void {
let s = state.get()
s = updateThreshold(s, 1)
state.set(s)
}
export function decThreshold(): void {
let s = state.get()
s = updateThreshold(s, -1)
state.set(s)
}
/**
* helper
*/
function updateThreshold(state: State, inc: number): State {
const i = thresholds.findIndex((t) => state.threshold === t.threshold) + inc
// out of bounds
if (i < 0 || i >= thresholds.length) return state
// storage the index so we can restore it even if we go to another page
sessionStorage.setItem('thresholdsIndex', i.toString())
const newItems = thresholds[i]
return { ...state, ...newItems }
}

41
assets/ts/imageState.tsx Normal file
View File

@@ -0,0 +1,41 @@
import {
createContext,
createMemo,
useContext,
type Accessor,
type JSX
} from 'solid-js'
import invariant from 'tiny-invariant'
import type { ImageJSON } from './resources'
export interface ImageState {
images: ImageJSON[]
length: number
}
type ImageStateContextType = Accessor<ImageState>
const ImageStateContext = createContext<ImageStateContextType>()
export function ImageStateProvider(props: {
children?: JSX.Element
images: ImageJSON[]
}): JSX.Element {
const state = createMemo<ImageState>(() => ({
images: props.images,
length: props.images.length
}))
return (
<ImageStateContext.Provider value={state}>
{props.children}
</ImageStateContext.Provider>
)
}
export function useImageState(): ImageStateContextType {
const context = useContext(ImageStateContext)
invariant(context, 'undefined image context')
return context
}

View File

@@ -1,54 +0,0 @@
import { initContainer } from './container'
import { initState } from './globalState'
import { initNav } from './nav'
import { initResources } from './resources'
// this is the main entry point for the app
document.addEventListener('DOMContentLoaded', () => {
main().catch((e) => {
console.log(e)
})
})
/**
* main functions
*/
async function main(): Promise<void> {
initContainer()
const ijs = await initResources()
initState(ijs.length)
initNav()
if (ijs.length === 0) {
return
}
// NOTE: it seems firefox and chromnium don't like top layer await
// so we are using import then instead
if (!isMobile()) {
await import('./desktop/init')
.then((d) => {
d.initDesktop(ijs)
})
.catch((e) => {
console.log(e)
})
} else {
await import('./mobile/init')
.then((m) => {
m.initMobile(ijs)
})
.catch((e) => {
console.log(e)
})
}
}
/**
* hepler
*/
function isMobile(): boolean {
return window.matchMedia('(hover: none)').matches
}

91
assets/ts/main.tsx Normal file
View File

@@ -0,0 +1,91 @@
import { Match, Show, Switch, createResource, lazy, type JSX } from 'solid-js'
import { render } from 'solid-js/web'
import { ConfigStateProvider } from './configState'
import { DesktopStateProvider } from './desktop/state'
import { ImageStateProvider } from './imageState'
import { MobileStateProvider } from './mobile/state'
import { getImageJSON } from './resources'
import '../scss/style.scss'
/**
* interfaces
*/
export interface Container extends HTMLDivElement {
dataset: {
next: string
close: string
prev: string
loading: string
}
}
// container
const container = document.getElementsByClassName('container')[0] as Container
// lazy components
const Desktop = lazy(async () => await import('./desktop/layout'))
const Mobile = lazy(async () => await import('./mobile/layout'))
function AppContent(props: {
isMobile: boolean
prevText: string
closeText: string
nextText: string
loadingText: string
}): JSX.Element {
return (
<Switch fallback={<div>Error</div>}>
<Match when={props.isMobile}>
<MobileStateProvider>
<Mobile closeText={props.closeText} loadingText={props.loadingText} />
</MobileStateProvider>
</Match>
<Match when={!props.isMobile}>
<DesktopStateProvider>
<Desktop
prevText={props.prevText}
closeText={props.closeText}
nextText={props.nextText}
loadingText={props.loadingText}
/>
</DesktopStateProvider>
</Match>
</Switch>
)
}
function Main(): JSX.Element {
// variables
const [ijs] = createResource(getImageJSON)
const ua = window.navigator.userAgent.toLowerCase()
const hasTouchInput = 'ontouchstart' in window || window.navigator.maxTouchPoints > 0
const hasTouchLayout =
window.matchMedia('(pointer: coarse)').matches ||
window.matchMedia('(hover: none)').matches
const isMobileUA = /android|iphone|ipad|ipod|mobile/.test(ua)
const isWindowsDesktop = /windows nt/.test(ua)
const isMobile = isMobileUA || (hasTouchInput && hasTouchLayout && !isWindowsDesktop)
return (
<>
<Show when={ijs.state === 'ready'}>
<ImageStateProvider images={ijs() ?? []}>
<ConfigStateProvider>
<AppContent
isMobile={isMobile}
prevText={container.dataset.prev}
closeText={container.dataset.close}
nextText={container.dataset.next}
loadingText={container.dataset.loading}
/>
</ConfigStateProvider>
</ImageStateProvider>
</Show>
</>
)
}
render(() => <Main />, container)

View File

@@ -1,106 +0,0 @@
import { container } from '../container'
import { setIndex } from '../globalState'
import { type ImageJSON } from '../resources'
import { slideUp } from './gallery'
import { mounted } from './state'
// eslint-disable-next-line sort-imports
import { getRandom, onIntersection, type MobileImage } from './utils'
/**
* variables
*/
export let imgs: MobileImage[] = []
/**
* main functions
*/
function handleClick(i: number): void {
setIndex(i)
slideUp()
}
/**
* init
*/
export function initCollection(ijs: ImageJSON[]): void {
createCollection(ijs)
// get container
const collection = document
.getElementsByClassName('collection')
.item(0) as HTMLDivElement
// add watcher
mounted.addWatcher((o) => {
if (o) {
collection.classList.remove('hidden')
} else {
collection.classList.add('hidden')
}
})
// get image elements
imgs = Array.from(collection.getElementsByTagName('img')) as MobileImage[]
// add event listeners
imgs.forEach((img, i) => {
// preload first 5 images on page load
if (i < 5) {
img.src = img.dataset.src
}
// event listeners
img.addEventListener(
'click',
() => {
handleClick(i)
},
{ passive: true }
)
img.addEventListener(
'keydown',
() => {
handleClick(i)
},
{ passive: true }
)
// preload
onIntersection(img, (entries, observer) => {
entries.every((entry) => {
// no intersection, skip
if (entry.intersectionRatio <= 0) return true
// preload the i + 5th image
if (i + 5 < imgs.length) {
imgs[i + 5].src = imgs[i + 5].dataset.src
}
// disconnect observer and return false to break the loop
observer.disconnect()
return false
})
})
})
}
/**
* helper
*/
function createCollection(ijs: ImageJSON[]): void {
// create container for images
const _collection: HTMLDivElement = document.createElement('div')
_collection.className = 'collection'
// append images to container
for (const [i, ij] of ijs.entries()) {
// random x and y
const x = i !== 0 ? getRandom(-25, 25) : 0
const y = i !== 0 ? getRandom(-30, 30) : 0
// element
const e = document.createElement('img') as MobileImage
e.dataset.src = ij.loUrl
e.height = ij.loImgH
e.width = ij.loImgW
e.alt = ij.alt
e.style.transform = `translate3d(${x}%, ${y - 50}%, 0)`
_collection.append(e)
}
container.append(_collection)
}

View File

@@ -0,0 +1,120 @@
import { For, createEffect, on, onMount, type JSX } from 'solid-js'
import { useImageState } from '../imageState'
import type { MobileImage } from './layout'
import { useMobileState } from './state'
function getRandom(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min
}
function onIntersection<T extends HTMLElement>(
element: T,
trigger: (arg0: IntersectionObserverEntry) => boolean
): void {
new IntersectionObserver((entries, observer) => {
for (const entry of entries) {
if (trigger(entry)) {
observer.disconnect()
break
}
}
}).observe(element)
}
export default function Collection(): JSX.Element {
// variables
const imageState = useImageState()
const imgs: MobileImage[] = Array<MobileImage>(imageState().length)
// states
const [mobile, { setIndex, setIsOpen }] = useMobileState()
// helper functions
const handleClick: (i: number) => void = (i) => {
if (mobile.isAnimating()) return
setIndex(i)
setIsOpen(true)
}
const scrollToActive: () => void = () => {
const index = mobile.index()
if (index < 0) return
imgs[index].scrollIntoView({ behavior: 'auto', block: 'center' })
}
// effects
onMount(() => {
imgs.forEach((img, i) => {
// preload first 5 images on page load
if (i < 5) {
img.src = img.dataset.src
}
// event listeners
img.addEventListener(
'click',
() => {
handleClick(i)
},
{ passive: true }
)
img.addEventListener(
'keydown',
() => {
handleClick(i)
},
{ passive: true }
)
// preload
onIntersection(img, (entry) => {
// no intersection, hold
if (entry.intersectionRatio <= 0) return false
// preload the i + 5th image, if it exists
if (i + 5 < imgs.length) {
imgs[i + 5].src = imgs[i + 5].dataset.src
}
// triggered
return true
})
})
})
createEffect(
on(
mobile.isOpen,
() => {
if (!mobile.isOpen()) scrollToActive() // scroll to active when closed
},
{ defer: true }
)
)
return (
<>
<div class="collection">
<For each={imageState().images}>
{(ij, i) => (
<img
ref={imgs[i()]}
height={ij.loImgH}
width={ij.loImgW}
data-src={ij.loUrl}
alt={ij.alt}
style={{
transform: `translate3d(${i() !== 0 ? getRandom(-25, 25) : 0}%, ${i() !== 0 ? getRandom(-35, 35) : 0}%, 0)`
}}
onClick={() => {
handleClick(i())
}}
onKeyDown={() => {
handleClick(i())
}}
/>
)}
</For>
</div>
</>
)
}

View File

@@ -1,308 +0,0 @@
import { type Power3, type gsap } from 'gsap'
import { type Swiper } from 'swiper'
import { container, scrollable } from '../container'
import { isAnimating, navigateVector, setIndex, state } from '../globalState'
import { expand, loadGsap, removeDuplicates } from '../globalUtils'
import { type ImageJSON } from '../resources'
import { mounted } from './state'
// eslint-disable-next-line sort-imports
import { capitalizeFirstLetter, loadSwiper, type MobileImage } from './utils'
/**
* variables
*/
let swiperNode: HTMLDivElement
let gallery: HTMLDivElement
let curtain: HTMLDivElement
let swiper: Swiper
let lastIndex = -1
let indexDispNums: HTMLSpanElement[] = []
let galleryImages: MobileImage[] = []
let collectionImages: MobileImage[] = []
let _Swiper: typeof Swiper
let _gsap: typeof gsap
let _Power3: typeof Power3
let libLoaded = false
/**
* main functions
*/
export function slideUp(): void {
if (isAnimating.get() || !libLoaded) return
isAnimating.set(true)
// load active image
galleryLoadImages()
_gsap.to(curtain, {
opacity: 1,
duration: 1
})
_gsap.to(gallery, {
y: 0,
ease: _Power3.easeInOut,
duration: 1,
delay: 0.4
})
setTimeout(() => {
scrollable.set(false)
isAnimating.set(false)
}, 1400)
}
function slideDown(): void {
if (isAnimating.get()) return
isAnimating.set(true)
scrollToActive()
_gsap.to(gallery, {
y: '100%',
ease: _Power3.easeInOut,
duration: 1
})
_gsap.to(curtain, {
opacity: 0,
duration: 1.2,
delay: 0.4
})
setTimeout(() => {
scrollable.set(true)
isAnimating.set(false)
}, 1600)
}
/**
* init
*/
export function initGallery(ijs: ImageJSON[]): void {
// create gallery
createGallery(ijs)
// get elements
indexDispNums = Array.from(
document.getElementsByClassName('nav').item(0)?.getElementsByClassName('num') ?? []
) as HTMLSpanElement[]
swiperNode = document.getElementsByClassName('galleryInner').item(0) as HTMLDivElement
gallery = document.getElementsByClassName('gallery').item(0) as HTMLDivElement
curtain = document.getElementsByClassName('curtain').item(0) as HTMLDivElement
galleryImages = Array.from(gallery.getElementsByTagName('img')) as MobileImage[]
collectionImages = Array.from(
document
.getElementsByClassName('collection')
.item(0)
?.getElementsByTagName('img') ?? []
) as MobileImage[]
// state watcher
state.addWatcher(() => {
const s = state.get()
// change slide only when index is changed
if (s.index === lastIndex) return
else if (lastIndex === -1)
navigateVector.set('none') // lastIndex before first set
else if (s.index < lastIndex) navigateVector.set('prev')
else navigateVector.set('next')
changeSlide(s.index)
updateIndexText()
lastIndex = s.index
})
// mounted watcher
mounted.addWatcher((o) => {
if (!o) return
scrollable.set(true)
})
// dynamic import
window.addEventListener(
'touchstart',
() => {
loadGsap()
.then((g) => {
_gsap = g[0]
_Power3 = g[1]
})
.catch((e) => {
console.log(e)
})
loadSwiper()
.then((s) => {
_Swiper = s
swiper = new _Swiper(swiperNode, { spaceBetween: 20 })
swiper.on('slideChange', ({ realIndex }) => {
setIndex(realIndex)
})
})
.catch((e) => {
console.log(e)
})
libLoaded = true
},
{ once: true, passive: true }
)
// mounted
mounted.set(true)
}
/**
* helper
*/
function changeSlide(slide: number): void {
galleryLoadImages()
swiper.slideTo(slide, 0)
}
function scrollToActive(): void {
collectionImages[state.get().index].scrollIntoView({
block: 'center',
behavior: 'auto'
})
}
function updateIndexText(): void {
const indexValue: string = expand(state.get().index + 1)
const indexLength: string = expand(state.get().length)
indexDispNums.forEach((e: HTMLSpanElement, i: number) => {
if (i < 4) {
e.innerText = indexValue[i]
} else {
e.innerText = indexLength[i - 4]
}
})
}
function galleryLoadImages(): void {
let activeImagesIndex: number[] = []
const currentIndex = state.get().index
const nextIndex = Math.min(currentIndex + 1, state.get().length - 1)
const prevIndex = Math.max(currentIndex - 1, 0)
switch (navigateVector.get()) {
case 'next':
activeImagesIndex = [nextIndex]
break
case 'prev':
activeImagesIndex = [prevIndex]
break
case 'none':
activeImagesIndex = [currentIndex, nextIndex, prevIndex]
break
}
removeDuplicates(activeImagesIndex).forEach((i) => {
const e = galleryImages[i]
if (e.src === e.dataset.src) return // already loaded
e.src = e.dataset.src
})
}
function createGallery(ijs: ImageJSON[]): void {
/**
* gallery
* |- galleryInner
* |- swiper-wrapper
* |- swiper-slide
* |- img
* |- swiper-slide
* |- img
* |- ...
* |- nav
* |- index
* |- close
*/
// swiper wrapper
const _swiperWrapper = document.createElement('div')
_swiperWrapper.className = 'swiper-wrapper'
// loading text
const loadingText = container.dataset.loading
for (const ij of ijs) {
// swiper slide
const _swiperSlide = document.createElement('div')
_swiperSlide.className = 'swiper-slide'
// loading indicator
const l = document.createElement('div')
l.className = 'loadingText'
l.innerText = loadingText
// img
const e = document.createElement('img') as MobileImage
e.dataset.src = ij.hiUrl
e.height = ij.hiImgH
e.width = ij.hiImgW
e.alt = ij.alt
e.classList.add('hide')
// load event
e.addEventListener(
'load',
() => {
e.classList.remove('hide')
l.classList.add('hide')
},
{ once: true, passive: true }
)
// parent container
const p = document.createElement('div')
p.className = 'slideContainer'
// append
p.append(e)
p.append(l)
_swiperSlide.append(p)
_swiperWrapper.append(_swiperSlide)
}
// swiper node
const _swiperNode = document.createElement('div')
_swiperNode.className = 'galleryInner'
_swiperNode.append(_swiperWrapper)
// index
const _index = document.createElement('div')
_index.insertAdjacentHTML(
'afterbegin',
`<span class="num"></span><span class="num"></span><span class="num"></span><span class="num"></span>
<span>/</span>
<span class="num"></span><span class="num"></span><span class="num"></span><span class="num"></span>`
)
// close
const _close = document.createElement('div')
_close.innerText = capitalizeFirstLetter(container.dataset.close)
_close.addEventListener(
'click',
() => {
slideDown()
},
{ passive: true }
)
_close.addEventListener(
'keydown',
() => {
slideDown()
},
{ passive: true }
)
// nav
const _navDiv = document.createElement('div')
_navDiv.className = 'nav'
_navDiv.append(_index, _close)
// gallery
const _gallery = document.createElement('div')
_gallery.className = 'gallery'
_gallery.append(_swiperNode)
_gallery.append(_navDiv)
/**
* curtain
*/
const _curtain = document.createElement('div')
_curtain.className = 'curtain'
/**
* container
* |- gallery
* |- curtain
*/
container.append(_gallery, _curtain)
}

View File

@@ -0,0 +1,193 @@
import { type gsap } from 'gsap'
import {
createEffect,
createMemo,
createSignal,
For,
on,
onMount,
untrack,
type JSX
} from 'solid-js'
import { createStore } from 'solid-js/store'
import { type Swiper } from 'swiper'
import invariant from 'tiny-invariant'
import { useImageState } from '../imageState'
import { loadGsap, removeDuplicates, type Vector } from '../utils'
import GalleryImage from './galleryImage'
import GalleryNav, { capitalizeFirstLetter } from './galleryNav'
import { closeGallery, openGallery } from './galleryTransitions'
import { getActiveImageIndexes, loadSwiper } from './galleryUtils'
import { useMobileState } from './state'
export default function Gallery(props: {
children?: JSX.Element
closeText: string
loadingText: string
}): JSX.Element {
let _gsap: typeof gsap
let _swiper: Swiper | undefined
let initPromise: Promise<void> | undefined
let curtain: HTMLDivElement | undefined
let gallery: HTMLDivElement | undefined
let galleryInner: HTMLDivElement | undefined
const imageState = useImageState()
const [mobile, { setIndex, setIsAnimating, setIsScrollLocked }] = useMobileState()
const loadingText = createMemo(() => capitalizeFirstLetter(props.loadingText))
let lastIndex = -1
let mounted = false
let navigateVector: Vector = 'none'
const [libLoaded, setLibLoaded] = createSignal(false)
const [swiperReady, setSwiperReady] = createSignal(false)
const [loads, setLoads] = createStore(Array<boolean>(imageState().length).fill(false))
const slideUp: () => void = () => {
if (!libLoaded() || !mounted) return
invariant(curtain, 'curtain is not defined')
invariant(gallery, 'gallery is not defined')
openGallery({
gsap: _gsap,
curtain,
gallery,
setIsAnimating,
setIsScrollLocked
})
}
const slideDown: () => void = () => {
invariant(gallery, 'curtain is not defined')
invariant(curtain, 'gallery is not defined')
closeGallery({
gsap: _gsap,
curtain,
gallery,
setIsAnimating,
setIsScrollLocked,
onClosed: () => {
lastIndex = -1
}
})
}
const galleryLoadImages: () => void = () => {
const currentIndex = mobile.index()
setLoads(
removeDuplicates(
getActiveImageIndexes(currentIndex, imageState().length, navigateVector)
),
true
)
}
const changeSlide: (slide: number) => void = (slide) => {
if (!swiperReady() || _swiper === undefined) return
galleryLoadImages()
_swiper.slideTo(slide, 0)
}
const ensureGalleryReady: () => Promise<void> = async () => {
if (initPromise !== undefined) return await initPromise
initPromise = (async () => {
try {
const [g, S] = await Promise.all([loadGsap(), loadSwiper()])
_gsap = g
invariant(galleryInner, 'galleryInner is not defined')
_swiper = new S(galleryInner, { spaceBetween: 20 })
_swiper.on('slideChange', ({ realIndex }) => {
setIndex(realIndex)
})
setLibLoaded(true)
setSwiperReady(true)
const initialIndex = untrack(mobile.index)
if (initialIndex >= 0) {
changeSlide(initialIndex)
lastIndex = initialIndex
}
} catch (e) {
initPromise = undefined
setSwiperReady(false)
console.log(e)
}
})()
await initPromise
}
onMount(() => {
window.addEventListener('touchstart', () => void ensureGalleryReady(), {
once: true,
passive: true
})
mounted = true
})
createEffect(
on(
() => [swiperReady(), mobile.index()] as const,
([ready, index]) => {
if (!ready || index < 0) return
if (index === lastIndex) return
if (lastIndex === -1) navigateVector = 'none'
else if (index < lastIndex) navigateVector = 'prev'
else if (index > lastIndex) navigateVector = 'next'
else navigateVector = 'none'
changeSlide(index)
lastIndex = index
}
)
)
createEffect(
on(
() => mobile.isOpen(),
async (isOpen) => {
if (isOpen && !swiperReady()) {
await ensureGalleryReady()
}
if (!libLoaded() || !swiperReady()) return
if (mobile.isAnimating()) return
if (isOpen) slideUp()
else slideDown()
},
{ defer: true }
)
)
return (
<>
<div ref={gallery} class="gallery">
<div ref={galleryInner} class="galleryInner">
<div class="swiper-wrapper">
<For each={imageState().images}>
{(ij, i) => (
<div class="swiper-slide">
<GalleryImage load={loads[i()]} ij={ij} loadingText={loadingText()} />
</div>
)}
</For>
</div>
</div>
<GalleryNav closeText={props.closeText} />
</div>
<div ref={curtain} class="curtain" />
</>
)
}

View File

@@ -0,0 +1,114 @@
import { type gsap } from 'gsap'
import { createEffect, on, onMount, type JSX } from 'solid-js'
import invariant from 'tiny-invariant'
import type { ImageJSON } from '../resources'
import { loadGsap } from '../utils'
import { useMobileState } from './state'
export default function GalleryImage(props: {
children?: JSX.Element
load: boolean
ij: ImageJSON
loadingText: string
}): JSX.Element {
let img: HTMLImageElement | undefined
let loadingDiv: HTMLDivElement | undefined
let _gsap: typeof gsap | undefined
let gsapPromise: Promise<typeof gsap> | undefined
let revealed = false
const [mobile] = useMobileState()
const revealImage = async (): Promise<void> => {
if (revealed) return
revealed = true
invariant(img, 'ref must be defined')
invariant(loadingDiv, 'loadingDiv must be defined')
gsapPromise ??= loadGsap()
try {
_gsap ??= await gsapPromise
} catch (e) {
console.log(e)
}
if (_gsap === undefined) {
img.style.opacity = '1'
loadingDiv.style.opacity = '0'
return
}
if (mobile.index() !== props.ij.index) {
_gsap.set(img, { opacity: 1 })
_gsap.set(loadingDiv, { opacity: 0 })
return
}
_gsap.to(img, {
opacity: 1,
delay: 0.5,
duration: 0.5,
ease: 'power3.out'
})
_gsap.to(loadingDiv, { opacity: 0, duration: 0.5, ease: 'power3.in' })
}
onMount(() => {
gsapPromise = loadGsap()
.then((g) => {
_gsap = g
return g
})
.catch((e) => {
console.log(e)
throw e
})
img?.addEventListener(
'load',
() => {
void revealImage()
},
{ once: true, passive: true }
)
if (props.load && img?.complete && img.currentSrc !== '') {
void revealImage()
}
})
createEffect(
on(
() => props.load,
(load) => {
if (!load || img === undefined || !img.complete || img.currentSrc === '') return
void revealImage()
},
{ defer: true }
)
)
return (
<>
<div class="slideContainer">
<img
ref={img}
{...(props.load && { src: props.ij.hiUrl })}
height={props.ij.hiImgH}
width={props.ij.hiImgW}
data-src={props.ij.hiUrl}
alt={props.ij.alt}
style={{ opacity: 0 }}
/>
<div ref={loadingDiv} class="loadingText">
{props.loadingText}
</div>
</div>
</>
)
}

View File

@@ -0,0 +1,54 @@
import { createMemo, type JSX } from 'solid-js'
import { useImageState } from '../imageState'
import { expand } from '../utils'
import { useMobileState } from './state'
export function capitalizeFirstLetter(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1)
}
export default function GalleryNav(props: {
children?: JSX.Element
closeText: string
}): JSX.Element {
// states
const imageState = useImageState()
const [mobile, { setIsOpen }] = useMobileState()
const indexValue = createMemo(() => expand(mobile.index() + 1))
const indexLength = createMemo(() => expand(imageState().length))
const onClick: () => void = () => {
if (mobile.isAnimating()) return
setIsOpen(false)
}
return (
<>
<div class="nav">
<div>
<span class="num">{indexValue()[0]}</span>
<span class="num">{indexValue()[1]}</span>
<span class="num">{indexValue()[2]}</span>
<span class="num">{indexValue()[3]}</span>
<span>/</span>
<span class="num">{indexLength()[0]}</span>
<span class="num">{indexLength()[1]}</span>
<span class="num">{indexLength()[2]}</span>
<span class="num">{indexLength()[3]}</span>
</div>
<div
class="navClose"
onClick={onClick}
onTouchEnd={onClick}
onKeyDown={onClick}
role="button"
tabIndex="0"
>
{capitalizeFirstLetter(props.closeText)}
</div>
</div>
</>
)
}

View File

@@ -0,0 +1,64 @@
import { type gsap } from 'gsap'
const OPEN_DELAY_MS = 1200
const CLOSE_DELAY_MS = 1400
export function openGallery(args: {
gsap: typeof gsap
curtain: HTMLDivElement
gallery: HTMLDivElement
setIsAnimating: (value: boolean) => void
setIsScrollLocked: (value: boolean) => void
}): void {
const { gsap, curtain, gallery, setIsAnimating, setIsScrollLocked } = args
setIsAnimating(true)
gsap.to(curtain, {
opacity: 1,
duration: 1
})
gsap.to(gallery, {
y: 0,
ease: 'power3.inOut',
duration: 1,
delay: 0.4
})
setTimeout(() => {
setIsScrollLocked(true)
setIsAnimating(false)
}, OPEN_DELAY_MS)
}
export function closeGallery(args: {
gsap: typeof gsap
curtain: HTMLDivElement
gallery: HTMLDivElement
setIsAnimating: (value: boolean) => void
setIsScrollLocked: (value: boolean) => void
onClosed: () => void
}): void {
const { gsap, curtain, gallery, setIsAnimating, setIsScrollLocked, onClosed } = args
setIsAnimating(true)
gsap.to(gallery, {
y: '100%',
ease: 'power3.inOut',
duration: 1
})
gsap.to(curtain, {
opacity: 0,
duration: 1.2,
delay: 0.4
})
setTimeout(() => {
setIsScrollLocked(false)
setIsAnimating(false)
onClosed()
}, CLOSE_DELAY_MS)
}

View File

@@ -0,0 +1,26 @@
import { type Swiper } from 'swiper'
import type { Vector } from '../utils'
export async function loadSwiper(): Promise<typeof Swiper> {
const swiper = await import('swiper')
return swiper.Swiper
}
export function getActiveImageIndexes(
currentIndex: number,
length: number,
navigateVector: Vector
): number[] {
const nextIndex = Math.min(currentIndex + 1, length - 1)
const prevIndex = Math.max(currentIndex - 1, 0)
switch (navigateVector) {
case 'next':
return [nextIndex]
case 'prev':
return [prevIndex]
case 'none':
return [currentIndex, nextIndex, prevIndex]
}
}

View File

@@ -1,9 +0,0 @@
import { type ImageJSON } from '../resources'
import { initCollection } from './collection'
import { initGallery } from './gallery'
export function initMobile(ijs: ImageJSON[]): void {
initCollection(ijs)
initGallery(ijs)
}

View File

@@ -0,0 +1,52 @@
import { Show, createEffect, onCleanup, type JSX } from 'solid-js'
import { useImageState } from '../imageState'
import Collection from './collection'
import Gallery from './gallery'
import { useMobileState } from './state'
/**
* interfaces
*/
export interface MobileImage extends HTMLImageElement {
dataset: {
src: string
index: string
}
}
export default function Mobile(props: {
children?: JSX.Element
closeText: string
loadingText: string
}): JSX.Element {
const imageState = useImageState()
const [mobile] = useMobileState()
createEffect(() => {
const container = document.getElementsByClassName('container').item(0)
if (container === null) return
if (mobile.isScrollLocked()) {
container.classList.add('disableScroll')
} else {
container.classList.remove('disableScroll')
}
})
onCleanup(() => {
const container = document.getElementsByClassName('container').item(0)
container?.classList.remove('disableScroll')
})
return (
<>
<Show when={imageState().length > 0}>
<Collection />
<Gallery closeText={props.closeText} loadingText={props.loadingText} />
</Show>
</>
)
}

View File

@@ -1,3 +1,78 @@
import { Watchable } from '../globalUtils'
import {
createComponent,
createContext,
createSignal,
useContext,
type Accessor,
type JSX,
type Setter
} from 'solid-js'
import invariant from 'tiny-invariant'
export const mounted = new Watchable<boolean>(false)
import { useImageState } from '../imageState'
import { decrement, increment } from '../utils'
export interface MobileState {
index: Accessor<number>
isOpen: Accessor<boolean>
isAnimating: Accessor<boolean>
isScrollLocked: Accessor<boolean>
}
export type MobileStateContextType = readonly [
MobileState,
{
readonly setIndex: Setter<number>
readonly incIndex: () => void
readonly decIndex: () => void
readonly setIsOpen: Setter<boolean>
readonly setIsAnimating: Setter<boolean>
readonly setIsScrollLocked: Setter<boolean>
}
]
const MobileStateContext = createContext<MobileStateContextType>()
export function MobileStateProvider(props: { children?: JSX.Element }): JSX.Element {
const imageState = useImageState()
const [index, setIndex] = createSignal(-1)
const [isOpen, setIsOpen] = createSignal(false)
const [isAnimating, setIsAnimating] = createSignal(false)
const [isScrollLocked, setIsScrollLocked] = createSignal(false)
const updateIndex = (stride: 1 | -1): void => {
const length = imageState().length
if (length <= 0) return
setIndex((current) =>
stride === 1 ? increment(current, length) : decrement(current, length)
)
}
return createComponent(MobileStateContext.Provider, {
value: [
{ index, isOpen, isAnimating, isScrollLocked },
{
setIndex,
incIndex: () => {
updateIndex(1)
},
decIndex: () => {
updateIndex(-1)
},
setIsOpen,
setIsAnimating,
setIsScrollLocked
}
],
get children() {
return props.children
}
})
}
export function useMobileState(): MobileStateContextType {
const context = useContext(MobileStateContext)
invariant(context, 'undefined mobile context')
return context
}

View File

@@ -1,37 +0,0 @@
import { type Swiper } from 'swiper'
/**
* interfaces
*/
export interface MobileImage extends HTMLImageElement {
dataset: {
src: string
}
}
/**
* utils
*/
export function getRandom(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min
}
export function onIntersection<T extends HTMLElement>(
element: T,
callback: (arg0: IntersectionObserverEntry[], arg1: IntersectionObserver) => void
): void {
new IntersectionObserver((entries, observer) => {
callback(entries, observer)
}).observe(element)
}
export function capitalizeFirstLetter(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1)
}
export async function loadSwiper(): Promise<typeof Swiper> {
const s = await import('swiper')
return s.Swiper
}

View File

@@ -1,78 +0,0 @@
import { decThreshold, incThreshold, state } from './globalState'
import { expand } from './globalUtils'
/**
* variables
*/
// threshold div
const thresholdDiv = document
.getElementsByClassName('threshold')
.item(0) as HTMLDivElement
// threshold nums span
const thresholdDispNums = Array.from(
thresholdDiv.getElementsByClassName('num')
) as HTMLSpanElement[]
// threshold buttons
const decButton = thresholdDiv
.getElementsByClassName('dec')
.item(0) as HTMLButtonElement
const incButton = thresholdDiv
.getElementsByClassName('inc')
.item(0) as HTMLButtonElement
// index div
const indexDiv = document.getElementsByClassName('index').item(0) as HTMLDivElement
// index nums span
const indexDispNums = Array.from(
indexDiv.getElementsByClassName('num')
) as HTMLSpanElement[]
/**
* init
*/
export function initNav(): void {
// add watcher for updating nav text
state.addWatcher((o) => {
updateIndexText(expand(o.index + 1), expand(o.length))
updateThresholdText(expand(o.threshold))
})
// event listeners
decButton.addEventListener(
'click',
() => {
decThreshold()
},
{ passive: true }
)
incButton.addEventListener(
'click',
() => {
incThreshold()
},
{ passive: true }
)
}
// helper
export function updateThresholdText(thresholdValue: string): void {
thresholdDispNums.forEach((e: HTMLSpanElement, i: number) => {
e.innerText = thresholdValue[i]
})
}
export function updateIndexText(indexValue: string, indexLength: string): void {
indexDispNums.forEach((e: HTMLSpanElement, i: number) => {
if (i < 4) {
e.innerText = indexValue[i]
} else {
e.innerText = indexLength[i - 4]
}
})
}

View File

@@ -10,9 +10,20 @@ export interface ImageJSON {
hiImgW: number
}
export async function initResources(): Promise<ImageJSON[]> {
export async function getImageJSON(): Promise<ImageJSON[]> {
if (document.title.split(' | ')[0] === '404') {
return [] // no images on 404 page
}
const ogUrlMetaTag = document.querySelector(
'meta[property="og:url"]'
) as HTMLMetaElement | null
const indexJsonUrl = ogUrlMetaTag?.content
? new URL('index.json', ogUrlMetaTag.content).href
: new URL('index.json', window.location.href).href
try {
const response = await fetch(`${window.location.href}index.json`, {
const response = await fetch(indexJsonUrl, {
headers: {
Accept: 'application/json'
}
@@ -24,7 +35,8 @@ export async function initResources(): Promise<ImageJSON[]> {
}
return 1
})
} catch (_) {
} catch (e) {
console.error(e)
return []
}
}

View File

@@ -1,4 +1,10 @@
import { type Power3, type gsap } from 'gsap'
import { type gsap } from 'gsap'
/**
* types
*/
export type Vector = 'prev' | 'next' | 'none'
/**
* utils
@@ -16,9 +22,9 @@ export function expand(num: number): string {
return ('0000' + num.toString()).slice(-4)
}
export async function loadGsap(): Promise<[typeof gsap, typeof Power3]> {
export async function loadGsap(): Promise<typeof gsap> {
const g = await import('gsap')
return [g.gsap, g.Power3]
return g.gsap
}
export function getThresholdSessionIndex(): number {
@@ -31,27 +37,3 @@ export function removeDuplicates<T>(arr: T[]): T[] {
if (arr.length < 2) return arr // optimization
return [...new Set(arr)]
}
/**
* custom "reactive" object
*/
export class Watchable<T> {
constructor(private obj: T) {}
private readonly watchers: Array<(arg0: T) => void> = []
get(): T {
return this.obj
}
set(e: T): void {
this.obj = e
this.watchers.forEach((watcher) => {
watcher(this.obj)
})
}
addWatcher(watcher: (arg0: T) => void): void {
this.watchers.push(watcher)
}
}

1
bundled/css/critical.css Normal file
View File

@@ -0,0 +1 @@
*:where(:not(html,iframe,canvas,img,svg,video,audio):not(svg *,symbol *)){all:unset;display:revert}*,*:before,*:after{box-sizing:border-box}html{-moz-text-size-adjust:none;-webkit-text-size-adjust:none;text-size-adjust:none}a,button{cursor:revert}ol,ul,menu,summary{list-style:none}img{max-inline-size:100%;max-block-size:100%}table{border-collapse:collapse}input,textarea{-webkit-user-select:auto}textarea{white-space:revert}meter{-webkit-appearance:revert;appearance:revert}:where(pre){all:revert;box-sizing:border-box}::placeholder{color:unset}:where([hidden]){display:none}:where([contenteditable]:not([contenteditable=false])){-moz-user-modify:read-write;-webkit-user-modify:read-write;overflow-wrap:break-word;-webkit-line-break:after-white-space;-webkit-user-select:auto}:where([draggable=true]){-webkit-user-drag:element}:where(dialog:modal){all:revert;box-sizing:border-box}@font-face{font-family:Geist;src:url('{{- "lib/fonts/GeistVF.woff2" | absURL -}}') format("woff2 supports variations"),url('{{- "lib/fonts/GeistVF.woff2" | absURL -}}') format("woff2-variations");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:FW;src:url('{{- "lib/fonts/fw.woff2" | absURL -}}') format("woff2");font-weight:400;font-style:normal;font-display:swap}body{line-height:1.2;font-size:16px;font-family:Geist,sans-serif}body button{font-family:FW,sans-serif}@media(min-width:768px){body{font-size:18px}}@media(min-width:1024px){body{font-size:19px}}:root{--window-height: 100vh;--nav-height: 2rem;--space-standard: .625rem;--z-curtain: 200;--z-nav-gallery: 500;--z-cursor: 600;--z-nav: 800}*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{-webkit-user-select:none;user-select:none;background:#fff}html,body{overscroll-behavior-y:none}a,button{cursor:pointer}nav{display:flex;justify-content:space-between;align-items:center;width:100%;height:var(--nav-height);padding:0 var(--space-standard);position:fixed;bottom:0;background:#fff;z-index:var(--z-nav);pointer-events:all}.num{width:.625em;display:inline-block;text-align:center}.current{font-style:italic;text-decoration:underline}@media(max-width:767px),(hover:none){nav{top:0}.index,.threshold{display:none}}article{padding:var(--space-standard);max-width:25em}article p{margin-bottom:1em}article u{text-decoration:underline}article>h1{font-size:1.6em}article>h2{font-size:1.5em}article>h3{font-size:1.375em}article>h4{font-size:1.25em}article>h5{font-size:1.125em}article h1,article h2,article h3,article h4,article h5,article h6{font-weight:700;margin:1.2rem 0}@media(max-width:767px),(hover:none){article{margin-top:var(--nav-height)}}@media(max-width:767px),(hover:none){.container{position:fixed;top:0;z-index:0;width:100vw;height:var(--window-height);overflow-y:scroll;overflow-x:hidden;background:#fff;overscroll-behavior:none;-webkit-overflow-scrolling:none}.disableScroll{pointer-events:none}}

1
bundled/css/main.css Normal file

File diff suppressed because one or more lines are too long

1
bundled/js/CO8Cxe.js Normal file

File diff suppressed because one or more lines are too long

1
bundled/js/DaqdZh.js Normal file

File diff suppressed because one or more lines are too long

1
bundled/js/fZjYgW.js Normal file

File diff suppressed because one or more lines are too long

1
bundled/js/h6I38a.js Normal file

File diff suppressed because one or more lines are too long

2
bundled/js/main.js Normal file
View File

@@ -0,0 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["js/fZjYgW.js","js/h6I38a.js","js/zA1TQP.js"])))=>i.map(i=>d[i]);
import{B as e,C as t,D as n,E as r,M as i,P as a,S as o,_ as s,a as c,j as l,k as u,l as d,n as f,o as p,p as m,r as h,t as g,u as _,w as v}from"./h6I38a.js";var y=[{threshold:20,trailLength:20},{threshold:40,trailLength:10},{threshold:80,trailLength:5},{threshold:140,trailLength:5},{threshold:200,trailLength:5}],b=n();function x(){let e=c();return e<0||e>=y.length?2:e}function S(e){let[t,n]=i(x()),a=u(()=>{let e=y[t()];return{thresholdIndex:t(),threshold:e.threshold,trailLength:e.trailLength}}),o=e=>{let r=t()+e;r<0||r>=y.length||(sessionStorage.setItem(`thresholdsIndex`,r.toString()),n(r))};return r(b.Provider,{value:[a,{incThreshold:()=>{o(1)},decThreshold:()=>{o(-1)}}],get children(){return e.children}})}function C(){let t=e(b);return _(t,`undefined config context`),t}var w=n();function T(e){let t=f(),[n,a]=i(-1),[o,s]=i([]),[c,l]=i(``),[u,d]=i(!1),[m,g]=i(!1),[_,v]=i(!1),[y,b]=i(`none`),x=e=>{let n=t().length;n<=0||a(t=>e===1?p(t,n):h(t,n))};return r(w.Provider,{value:[{index:n,cordHist:o,hoverText:c,isOpen:u,isAnimating:m,isLoading:_,navVector:y},{setIndex:a,incIndex:()=>{x(1)},decIndex:()=>{x(-1)},setCordHist:s,setHoverText:l,setIsOpen:d,setIsAnimating:g,setIsLoading:v,setNavVector:b}],get children(){return e.children}})}function E(){let t=e(w);return _(t,`undefined desktop context`),t}var D=n();function O(e){let t=f(),[n,a]=i(-1),[o,s]=i(!1),[c,l]=i(!1),[u,d]=i(!1),m=e=>{let n=t().length;n<=0||a(t=>e===1?p(t,n):h(t,n))};return r(D.Provider,{value:[{index:n,isOpen:o,isAnimating:c,isScrollLocked:u},{setIndex:a,incIndex:()=>{m(1)},decIndex:()=>{m(-1)},setIsOpen:s,setIsAnimating:l,setIsScrollLocked:d}],get children(){return e.children}})}function k(){let t=e(D);return _(t,`undefined mobile context`),t}async function A(){if(document.title.split(` | `)[0]===`404`)return[];let e=document.querySelector(`meta[property="og:url"]`),t=e?.content?new URL(`index.json`,e.content).href:new URL(`index.json`,window.location.href).href;try{return(await(await fetch(t,{headers:{Accept:`application/json`}})).json()).sort((e,t)=>e.index<t.index?-1:1)}catch(e){return console.error(e),[]}}var j=s(`<div>Error`),M=document.getElementsByClassName(`container`)[0],N=a(async()=>await d(()=>import(`./fZjYgW.js`),__vite__mapDeps([0,1]))),P=a(async()=>await d(()=>import(`./zA1TQP.js`),__vite__mapDeps([2,1])));function F(e){return r(v,{get fallback(){return j()},get children(){return[r(o,{get when(){return e.isMobile},get children(){return r(O,{get children(){return r(P,{get closeText(){return e.closeText},get loadingText(){return e.loadingText}})}})}}),r(o,{get when(){return!e.isMobile},get children(){return r(T,{get children(){return r(N,{get prevText(){return e.prevText},get closeText(){return e.closeText},get nextText(){return e.nextText},get loadingText(){return e.loadingText}})}})}})]}})}function I(){let[e]=l(A),n=window.navigator.userAgent.toLowerCase(),i=`ontouchstart`in window||window.navigator.maxTouchPoints>0,a=window.matchMedia(`(pointer: coarse)`).matches||window.matchMedia(`(hover: none)`).matches,o=/android|iphone|ipad|ipod|mobile/.test(n),s=/windows nt/.test(n),c=o||i&&a&&!s;return r(t,{get when(){return e.state===`ready`},get children(){return r(g,{get images(){return e()??[]},get children(){return r(S,{get children(){return r(F,{isMobile:c,get prevText(){return M.dataset.prev},get closeText(){return M.dataset.close},get nextText(){return M.dataset.next},get loadingText(){return M.dataset.loading}})}})}})}})}m(()=>r(I,{}),M);export{E as n,C as r,k as t};

1
bundled/js/zA1TQP.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,215 +0,0 @@
# Getting Started
The files in `exampleSite` is just a simple example. Now, we will introduce it based on the same structure.
## Requirements
Before you start, make sure you have installed Hugo **extended version**. For more information, see [Hugo's documentation](https://gohugo.io/getting-started/installing/).
Once you have installed Hugo, you can check the version by running the following command:
```shell
hugo version
```
Which should output something like this (the version number may be different), notice the `extended` keyword:
```shell
hugo v0.120.3-a4892a07b41b7b3f1f143140ee4ec0a9a5cf3970+extended darwin/arm64 BuildDate=2023-11-01T17:57:00Z VendorInfo=brew
```
The minimum required Hugo version can be seen in the [`theme.toml`](https://github.com/Sped0n/bridget/blob/main/theme.toml#L19).
## Installation
### Git (for adavanced user)
On the main branch, you can find the theme's latest source code. To use the latest version, you can clone the repository to `themes/bridget` by running the following command in the root directory of your Hugo site:
```shell
git clone https://github.com/Sped0n/bridget themes/bridget
```
If you are already using Git for your site, you can add the theme as a submodule by running the following command in the root directory of your Hugo site:
```shell
git submodule add https://github.com/Sped0n/bridget themes/bridget
```
> ⚠️⚠️⚠️
>
> Please refer to the config section for the following content.
### Module (recommended)
> If you want to have some customizations, use Git installation instead.
This theme is also available as a [Hugo module](https://gohugo.io/hugo-modules/). Run the following command in the root directory of your Hugo site:
First turn your site into a Hugo module (in case you haven't done it yet):
```shell
hugo mod init github.com/me/my-new-site
# or whatever you like, it doesnt necessarily have to be a GitHub repo link.
hugo mod init blablabla
```
Then import the theme as a dependency adding the following line to the `module` section of your site's configuration file.
```toml
# config/_default/hugo.toml
[module]
[[module.imports]]
path = "github.com/Sped0n/bridget"
```
If you want to upgrade the theme, just run:
```shell
hugo mod get -u
```
> ⚠️⚠️⚠️
>
> Please refer to the config section for the following content.
## Content Management
The content is where the pictures/text is stored, while the static refers to the website icons.
```
.
├── content
│ ├── Erwitt
│ │ ├── 1.jpg
│ │ ├── ***
│ │ └── index.md
│ ├── Gruyaert
│ │ ├── 1.jpg
│ │ ├── ***
│ │ └── index.md
│ ├── Info
│ │ └── index.md
│ └── Webb
│ ├── 1.jpg
│ ├── ***
│ └── index.md
└── static
├── dot.png
└── dot.svg
```
In each index.md file, there is a configuration file like this:
```markdown
---
type: _default
layout: single
url: /erwitt/
menu:
main:
weight: 3
identifier: Erwitt
title: Erwitt
unifiedAlt: '© Elliott Erwitt'
---
```
- keep the `type` and `layout` **untouched**;
- `url` is the href link to this page, in this case, you can visit this page with `blabla.com/erwitt`;
- `main` is the entry to `menu`;
- `weight` determines the position of this link in the navigation bar, with the first one being 1, the second one being 2, and so on;
- `identifier` should be the **same** as the name of the **upper-level directory**;
- `title` refers to the text that appears on the navigation bar;
- `unifiedAlt` is **optional**, If you left it empty, the alt attribute of the image will default to its file name; if it is set, the alt attributes of all images will be unified to the value you have set;
- If this is a **showcase** page, simply place the images in the same directory as index.md.
- If this is an **information** page, you can continue writing the information you want to display in index.md.
> However, please note that the CSS for the information page **only provides simple styling for text**. If you have any requirements beyond text and the browser rendering does not meet your expectations, please modify [`_article.scss`](https://github.com/Sped0n/bridget/blob/main/assets/scss/_partial/_article.scss).
As for the **website icon**, place the files in static and then go to config part for further reading.
## Config
You can simply copy this to the root directory of your site with minor modifications, and youll be ready to proceed.
```
.
└── config
└── _default
├── hugo.toml
├── markup.toml
├── params.toml
└── sitemap.toml
```
### `hugo.toml`
We will focus on introducing the part about `theme as module`, detailed comments are provided for other options, so we wont repeat them here.
```toml
# theme as module
[module]
replacements = "github.com/Sped0n/bridget -> ../.."
[[module.imports]]
path = "github.com/Sped0n/bridget"
```
- If you have <u>installation with Git</u>
- `replacement`: replace the <u>path after the arrow</u>(`../..`) with the location of your local theme file (⚠️⚠️⚠️**relative path only**, example: `themes/bridget`)
- `path`: no change
- If you have <u>installation with Module</u>, **remove the `replacements` configuration**.
### `markup.toml`
**DO NOT TOUCH THIS**
### `params.toml`
Detailed description in the comments.
> ⚠️⚠️⚠️
>
> Only thing that you need to pay **extra attention** is the [`bundled`](https://github.com/Sped0n/bridget/blob/1e2f1fadde9c16989eef1ab771f2ac8463dec5a4/exampleSite/config/_default/params.toml#L6) option, please read the corresponding doc and set it as your need.
>
> For users who have installation with module, please always set this option to `true`, unless you know what you are doing.
>
> Or you might get the error related to `node_modules/swiper/swiper.scss`.
### `sitemap.toml`
https://gohugo.io/templates/sitemap-template/#configuration
## Customization (AKA for developer)
> Before heading to this section, please make sure you have **installation with Git**.
### Option 1: _it just works_ way
> If you want to modify js/ts file, please use option 2.
1. Use hugo create a site and move the bridget theme into the theme directory.
2. Run `npm install` in the <u>bridget theme root dir</u>, not <u>your hugo site root dir</u>.
3. After the command is done, copy the `node_modules` dir from <u>bridget theme root dir</u> to <u>your hugo site root dir</u>.
4. In <u>your hugo site root dir</u>, write/modify configuration files according to your needs, remember to set `bundled` option to `false`, so hugo will not use prebuilt css file.
5. Run `hugo server` in <u>your hugo site root dir</u>, and you are good to go.
### Option 2: recommended way
1. Use hugo create a site and move the bridget theme into the theme directory.
2. Run `npm install` in the <u>bridget theme root dir</u>, not <u>your hugo site root dir</u>.
3. Run `npm run dev` in the <u>bridget theme root dir</u>, we will use content in exampleSite to debug.
4. Make your customization.
5. After modification, run `npm run build` in the <u>bridget theme root dir</u> to build artifacts.
6. In <u>your hugo site root dir</u>, write/modify configuration files according to your needs, remember to set `bundled` option to `true`, so hugo will use the artifacts you built in step 5.
7. Run `hugo server` in <u>your hugo site root dir</u>, and you are good to go.

307
docs.md Normal file
View File

@@ -0,0 +1,307 @@
### Contents
- [Prequisites](#prequisites)
- [Installation](#installation)
- [Hugo Modules (Recommended)](#hugo-modules-recommended)
- [Git Repository (For Customizations)](#git-repository-for-customizations)
- [Content Management](#content-management)
- [`index.md`](#indexmd)
- [Front Matter](#front-matter)
- [Markdown Content](#markdown-content)
- [Favicon](#favicon)
- [Configuration](#configuration)
- [`hugo.toml`](#hugotoml)
- [`markup.toml`](#markuptoml)
- [`outputs.toml`](#outputstoml)
- [`params.toml`](#paramstoml)
- [`sitemap.toml`](#sitemaptoml)
- [Usage](#usage)
- [Customizations](#customizations)
- [Change Font](#change-font)
- [Add a Custom Analytic Script](#add-a-custom-analytic-script)
---
## Prequisites
_[Contents](#contents)_
- [Hugo (extended)](https://gohugo.io/installation/), minimum required version can be seen in the [`theme.toml`](https://github.com/Sped0n/bridget/blob/main/theme.toml#L19)
```bash
hugo version
hugo v0.152.2+extended+withdeploy darwin/arm64 BuildDate=unknown VendorInfo=nixpkgs
```
- [pnpm](https://pnpm.io/installation) and [Node.js](https://nodejs.org/en/download), please note that these two are only needed for customizations or development.
```bash
pnpm --version && node --version
10.20.0
v22.20.0
```
## Installation
_[Contents](#contents)_
### Hugo Modules (Recommended)
_[Contents](#contents)_
> [!IMPORTANT]
> Checkout https://gohugo.io/hugo-modules/use-modules/#prerequisite before using Hugo Modules.
First turn your site into a Hugo module (in case you haven't done it yet):
```bash
hugo mod init github.com/me/my-new-site
# or whatever you like, it doesnt need to be a valid GitHub repo link.
hugo mod init blablabla
```
Then import the theme as a dependency adding the following line to the `module` section of your site's configuration file.
```toml
# config/_default/hugo.toml
[module]
[[module.imports]]
path = "github.com/Sped0n/bridget/v2"
```
If you want to upgrade the theme, just run:
```shell
hugo mod get -u
```
### Git Repository (For Customizations)
_[Contents](#contents)_
First clone the repository into your `themes` directory:
```bash
# latest version (main branch, might be unstable)
git clone https://github.com/Sped0n/bridget themes/bridget
# and you can checkout to a specific stable version, see https://github.com/Sped0n/bridget/releases
cd themes/bridget
git checkout v1.0.0
```
If you are already using Git for your site, you can add the theme as a submodule by running the following command in the root directory of your Hugo site:
```bash
git submodule add https://github.com/Sped0n/bridget themes/bridget
```
## Content Management
_[Contents](#contents)_
The content is where the pictures/text is stored, while the static refers to the website icons.
```
.
├── content
│ ├── Erwitt
│ │ ├── 1.jpg
│ │ ├── ***
│ │ └── index.md
│ ├── Gruyaert
│ │ ├── 1.jpg
│ │ ├── ***
│ │ └── index.md
│ ├── Info
│ │ └── index.md
│ └── Webb
│ ├── 1.jpg
│ ├── ***
│ └── index.md
└── static
├── dot.png
└── dot.svg
```
### `index.md`
_[Contents](#contents)_
#### Front Matter
_[Contents](#contents)_
Inside each index.md file, there is a front matter like this:
```markdown
---
type: _default # just copy
layout: single # just copy
url: /erwitt/
menu:
main:
weight: 3
identifier: Erwitt
title: Erwitt
unifiedAlt: '© Elliott Erwitt'
build:
publishResources: false # just copy
---
```
- `url` is the href link to this page, in this case, you can visit this page with `blabla.com/erwitt`;
- `main` is the entry to `menu`;
- `weight` determines the position of this link in the navigation bar, with the first one being 1, the second one being 2, and so on;
- `identifier` should be the **same** as the name of the **upper-level directory**;
- `title` refers to the text that appears on the navigation bar;
- `unifiedAlt` is **optional**, If you left it empty, the alt attribute of the image will default to its file name; if it is set, the alt attributes of all images will be unified to the value you have set;
#### Markdown Content
_[Contents](#contents)_
- If this is a **showcase** page:
- No need to write anything in index.md.
- Place the images in the same directory as `index.md`.
- If this is an **information** page:
- You can write anything in index.md, and it will be rendered as HTML.
- However, please note that the CSS for the information page **only provides simple styling for text**. If you have any requirements beyond text and the browser rendering does not meet your expectations, please modify [`_article.scss`](https://github.com/Sped0n/bridget/blob/main/assets/scss/_partial/_article.scss).
### Favicon
_[Contents](#contents)_
As for the **website icon**, place the files under `static` directory and then go to [config](#configuration) part for further reading.
## Configuration
_[Contents](#contents)_
You can simply copy `exampleSite/config` to the root directory, with some minor modifications and you should be good to go.
```
.
└── config
└── _default
├── hugo.toml
├── markup.toml
├── outputs.toml
├── params.toml
└── sitemap.toml
```
### `hugo.toml`
_[Contents](#contents)_
First, what you need to modify is the `baseURL` and `title`:
```toml
# timeout
timeout = "1200s"
# your website url
baseURL = 'https://bridget-demo.sped0n.com' # <-- MODIFY ME
# website title
title = 'Bridget' # <-- MODIFY ME
# don't touch this
disableKinds = ["section", "taxonomy", "term", "home"]
# robots.txt
enableRobotsTXT = true
```
Depend on which [installation](#installation) method you choose, you need to modify the `module` section:
- If you use [Hugo Modules](#hugo-modules-recommended):
```toml
[module]
[[module.imports]]
path = "github.com/Sped0n/bridget/v2"
```
- If you use [Git Repository](#git-repository-for-customizations):
```toml
[module]
# This is the relative path to hugo theme directory([official doc](https://gohugo.io/hugo-modules/configuration/#module-configuration-top-level))**.
replacements = "github.com/Sped0n/bridget/v2 -> ../.."
[[module.imports]]
path = "github.com/Sped0n/bridget/v2"
```
### `markup.toml`
_[Contents](#contents)_
**Just copy it.**
### `outputs.toml`
_[Contents](#contents)_
**Just copy it.**
_[Contents](#contents)_
### `params.toml`
_[Contents](#contents)_
Detailed description in the comments.
### `sitemap.toml`
_[Contents](#contents)_
https://gohugo.io/templates/sitemap-template/#configuration
## Usage
_[Contents](#contents)_
Bridget will work as a normal Hugo theme (if you don't have needs to customize), https://gohugo.io/getting-started/usage/ is a great start.
For further reading, you can refer to the `scripts` field of `package.json`.
## Customizations
_[Contents](#contents)_
> [!IMPORTANT]
> Please make sure you have [installation with Git](#git-repository-for-customizations).
>
> If you want to try some changes on the `exampleSite`, below are some commands you might need:
>
> - `pnpm install` to install dependencies.
> - `pnpm run dev` to start a dev server (`http://localhost:1313`).
> - `pnpm run build` to update artifacts.
### Change Font
_[Contents](#contents)_
These are the places you need to focus on:
- `assets/scss/_core/_font.scss` (`@font-face`)
- `assets/scss/_core/_typography.scss` (`body.font-family`)
- `layouts/partials/head/link.html` (`preload`)
- `static/lib/fonts/GeistVF.woff2` (font file itself)
### Add a Custom Analytic Script
_[Contents](#contents)_
Go to `layouts/_default/baseof.html`:
```html
<!doctype html>
<html lang="{{- site.LanguageCode -}}">
<head>
/* ---------- INSERT HERE ---------- */
</head>
<body lang="{{- site.LanguageCode -}}">
<div class="analytics">/* ---------- OR HERE ---------- */</div>
</body>
</html>
```

79
eslint.config.mjs Normal file
View File

@@ -0,0 +1,79 @@
import js from '@eslint/js'
import tsParser from '@typescript-eslint/parser'
import love from 'eslint-config-love'
import importPlugin from 'eslint-plugin-import'
import prettier from 'eslint-plugin-prettier/recommended'
import solid from 'eslint-plugin-solid/configs/recommended'
import { defineConfig, globalIgnores } from 'eslint/config'
import tseslint from 'typescript-eslint'
export default defineConfig([
js.configs.recommended,
tseslint.configs.recommended,
importPlugin.flatConfigs.recommended,
solid,
globalIgnores(['node_modules/', 'static/', 'exampleSite/', '*.mjs', 'bundled/']),
{
...love,
...prettier,
languageOptions: {
parser: tsParser,
ecmaVersion: 'latest',
sourceType: 'module',
parserOptions: {
project: './tsconfig.json'
}
},
settings: {
'import/resolver': {
typescript: {
project: './tsconfig.json'
}
}
},
rules: {
'prettier/prettier': 'error',
'arrow-body-style': 'off',
'prefer-arrow-callback': 'off',
'import/no-cycle': 'error',
'sort-imports': [
'error',
{
ignoreCase: false,
ignoreDeclarationSort: true,
ignoreMemberSort: true,
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
allowSeparatedGroups: true
}
],
'import/no-unresolved': 'error',
'import/order': [
'error',
{
groups: [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index',
'unknown'
],
'newlines-between': 'always',
alphabetize: {
order: 'asc',
caseInsensitive: true
}
}
]
}
}
])

View File

@@ -1,27 +1,16 @@
# timeout
timeout = "1200s"
# your website url
baseURL = 'https://www.example.com/'
baseURL = 'https://bridget-demo.sped0n.com'
# website title
title = 'Bridget'
# don't touch this
disableKinds = ["section", "taxonomy", "term", "home"]
# robots.txt
enableRobotsTXT = true
# available options
# * en (powered by Geist)
# * de (powered by Geist)
# * es (powered by Geist)
# * fr (powered by Geist)
# * it (powered by Geist)
# * zh-sg zh-cn (powered by Noto Sans SC)
# * zh-hk zh-tw zh-mo (powered by Noto Sans TC)
# * ja (powered by Noto Sans JP)
# * ko (powered by Noto Sans KR)
defaultContentLanguage = 'en'
# theme as module
[module]
replacements = "github.com/Sped0n/bridget -> ../.." # deploy with local dir WARN: delete this line if you want to deploy with git
replacements = "github.com/Sped0n/bridget/v2 -> ../.." # deploy with local dir (relative to hugo site theme dir) WARN: delete this line if you want to deploy with git
[[module.imports]]
path = "github.com/Sped0n/bridget" # deploy with git (recommended) WARN: you should also set `bundled` to true in params.toml !!!
path = "github.com/Sped0n/bridget/v2" # deploy with git (recommended)

View File

@@ -1,9 +1,22 @@
# --- REQUIRED -----------------------------------------------------------------
# description of the site (will be placed in meta)
description = "Bridget is a minimal Hugo theme designed for photographers/visual artists."
# use bundled js and css
# * if you want to build the js and css from scratch, set this to false and run `npm install` and `npm run build`
# * tldr: set this to false if you want to develop and edit the js and css
bundled = false
# resize options for dynamic resolution, please refer to https://gohugo.io/content-management/image-processing/#image-processing-options
loResOpt = "800x webp Lanczos q60"
hiResOpt = "2500x webp Lanczos q75"
# labels (text shown on the UI)
[labels]
next = "next"
prev = "prev"
close = "close"
threshold = "Threshold"
error = "page not found"
loading = "loading..."
# --- OPTIONAL -----------------------------------------------------------------
# whether to use favicon resource links
# generate these with https://realfavicongenerator.net
@@ -13,16 +26,7 @@ svgFavicon = "/dot.svg"
# fallback png favicon for unsupported browsers
svgFaviconFallback = "/dot.png"
# resize options for dynamic resolution, please refer to https://gohugo.io/content-management/image-processing/#image-processing-options
loResOpt = "800x webp Lanczos q60"
hiResOpt = "2500x webp Lanczos q75"
# page config
[page]
# unified alt text for all images in the page
unifiedAlt = ''
# Site verification code for Google/Bing/Yandex/Pinterest/Baidu
# site verification code for Google/Bing/Yandex/Pinterest/Baidu
[verification]
google = ""
bing = ""
@@ -32,7 +36,7 @@ baidu = ""
so = ""
sogou = ""
# Analytics config
# analytics config
[analytics]
enable = true
# Google Analytics
@@ -50,10 +54,10 @@ server = ""
id = ""
# Umami Analytics
[analytics.umami]
data_website_id = "44a4a42d-ec8e-44c9-a38c-7533929e9845"
src = "https://umami.sped0nwen.com/script.js"
data_website_id = "942d4c0d-ebd0-4da7-936a-bd278af32e5e"
src = "https://umami.sped0n.com/script.js"
data_host_url = ""
data_domains = "bridget-demo.sped0nwen.com"
data_domains = "bridget-demo.sped0n.com"
# Plausible Analytics
[analytics.plausible]
data_domain = ""
@@ -65,8 +69,8 @@ token = ""
[analytics.splitbee]
enable = false
# no cookie mode
No_cookie = true
no_cookie = true
# respect the do not track setting of the browser
Do_not_track = true
do_not_track = true
# token(optional), more info on https://splitbee.io/docs/embed-the-script
data_token = ""

View File

@@ -8,4 +8,6 @@ menu:
identifier: Erwitt
title: Erwitt
unifiedAlt: '© Elliott Erwitt'
build:
publishResources: false
---

View File

@@ -8,4 +8,6 @@ menu:
identifier: Gruyaert
title: Gruyaert
unifiedAlt: '© Harry Gruyaert'
build:
publishResources: false
---

View File

@@ -8,16 +8,18 @@ menu:
identifier: Info
title: Info
unifiedAlt: ''
build:
publishResources: false
---
Bridget is a _minimal_ Hugo theme designed for photographers/visual artists.
Bridget is a _minimal_ Hugo theme designed for photographers/visual artists, powered by <u>[SolidJS](https://www.solidjs.com)</u>.
The inspiration for this theme came from a video by <u>[Hyperlexed](https://www.youtube.com/@Hyperplexed)</u>, which can be found <u>[here](https://www.youtube.com/watch?v=Jt3A2lNN2aE)</u>. Initially, it was developed using raw TypeScript and CSS. However, after website designer <u>[Tyler McRobert](https://tylermcrobert.com)</u> made the source code publicly available, I realized that I have invented many unnecessary components, and this project was modified to porting the original design to hugo while focusing on _performance_.
The inspiration for this theme came from a video by <u>[Hyperlexed](https://www.youtube.com/@Hyperplexed)</u>, which can be found <u>[here](https://www.youtube.com/watch?v=Jt3A2lNN2aE)</u>. Initially, it was developed using no third-party dependencies. However, after website designer <u>[Tyler McRobert](https://tylermcrobert.com)</u> made the source code publicly available, I realized that I have invented many unnecessary wheels, and this project was modified to porting the original design to Hugo while focusing on _performance_.
Once again, great shout out to <u>[Tyler McRobert](https://tylermcrobert.com)</u> for his inspiration to this project.
[Repo ↗](https://github.com/Sped0n/bridget)
[GitHub Repo ↗](https://github.com/Sped0n/bridget)
Original site design by <u>[Tyler McRobert](https://tylermcrobert.com)</u>.
&copy; {{< year >}} <u>[Spedon](https://github.com/Sped0n)</u> | Powered by [Hugo](https://gohugo.io)
&copy; {{< year >}} <u>[Spedon](https://github.com/Sped0n)</u> | Built with Hugo

View File

@@ -8,4 +8,6 @@ menu:
identifier: Webb
title: Webb
unifiedAlt: '© Alex Webb'
build:
publishResources: false
---

25
flake.lock generated Normal file
View File

@@ -0,0 +1,25 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1769461804,
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"revCount": 935279,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.935279%2Brev-bfc1b8a4574108ceef22f02bafcf6611380c100d/019c02ef-f13d-717e-8527-f1603ec205db/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

37
flake.nix Normal file
View File

@@ -0,0 +1,37 @@
{
description = "bridget";
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1";
outputs =
{ self, ... }@inputs:
let
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forEachSupportedSystem =
f:
inputs.nixpkgs.lib.genAttrs supportedSystems (
system:
f {
pkgs = import inputs.nixpkgs { inherit system; };
}
);
in
{
devShells = forEachSupportedSystem (
{ pkgs }:
{
default = pkgs.mkShellNoCC {
packages = with pkgs; [
nodejs
nodePackages.pnpm
hugo
go
];
};
}
);
};
}

2
go.mod
View File

@@ -1,3 +1,3 @@
module github.com/Sped0n/bridget
module github.com/Sped0n/bridget/v2
go 1.21.3

18
hugo.toml Normal file
View File

@@ -0,0 +1,18 @@
[[module.mounts]]
source = 'archetypes'
target = 'archetypes'
[[module.mounts]]
source = 'assets'
target = 'assets'
[[module.mounts]]
source = 'layouts'
target = 'layouts'
[[module.mounts]]
source = 'static'
target = 'static'
[[module.mounts]]
source = "bundled"
target = "assets/bundled"
[[module.mounts]]
source = "bundled"
target = "static/bundled"

View File

@@ -1,12 +0,0 @@
[next]
other = "nächste"
[prev]
other = "vorher"
[close]
other = "schließen"
[threshold]
other = "schwelle"
[404]
other = "seite nicht gefunden"
[loading]
other = "lade"

View File

@@ -1,12 +0,0 @@
[next]
other = "next"
[prev]
other = "prev"
[close]
other = "close"
[threshold]
other = "threshold"
[404]
other = "page not found"
[loading]
other = "loading"

View File

@@ -1,12 +0,0 @@
[next]
other = "siguiente"
[prev]
other = "previo"
[close]
other = "cerrar"
[threshold]
other = "umbral"
[404]
other = "página no encontrada"
[loading]
other = "cargando"

View File

@@ -1,12 +0,0 @@
[next]
other = "suivant"
[prev]
other = "précédent"
[close]
other = "fermer"
[threshold]
other = "seuil"
[404]
other = "page non trouvée"
[loading]
other = "chargement"

View File

@@ -1,12 +0,0 @@
[next]
other = "prossimo"
[prev]
other = "precedente"
[close]
other = "chiudi"
[threshold]
other = "soglia"
[404]
other = "pagina non trovata"
[loading]
other = "caricamento"

View File

@@ -1,12 +0,0 @@
[next]
other = "進む"
[prev]
other = "後退"
[close]
other = "閉じる"
[threshold]
other = "しきい値"
[404]
other = "ページが見つかりません"
[loading]
other = "読み込み中"

View File

@@ -1,12 +0,0 @@
[next]
other = "전진"
[prev]
other = "물러나세요"
[close]
other = "닫기"
[threshold]
other = "임계값"
[404]
other = "페이지를 찾을 수 없습니다"
[loading]
other = "로딩중"

View File

@@ -1,12 +0,0 @@
[next]
other = "前进"
[prev]
other = "后退"
[close]
other = "关闭"
[threshold]
other = "阈值"
[404]
other = "页面不存在"
[loading]
other = "加载中"

View File

@@ -1,12 +0,0 @@
[next]
other = "前進"
[prev]
other = "後退"
[close]
other = "關閉"
[threshold]
other = "閾值"
[404]
other = "找不到頁面"
[loading]
other = "載入中"

View File

@@ -1,12 +0,0 @@
[next]
other = "前進"
[prev]
other = "後退"
[close]
other = "關閉"
[threshold]
other = "閾值"
[404]
other = "找不到頁面"
[loading]
other = "載入中"

View File

@@ -1,12 +0,0 @@
[next]
other = "前进"
[prev]
other = "后退"
[close]
other = "关闭"
[threshold]
other = "阈值"
[404]
other = "页面不存在"
[loading]
other = "加载中"

View File

@@ -1,12 +0,0 @@
[next]
other = "前進"
[prev]
other = "後退"
[close]
other = "關閉"
[threshold]
other = "閾值"
[404]
other = "找不到頁面"
[loading]
other = "載入中"

View File

@@ -1,10 +1,16 @@
{{- define "main" -}}
<div class="container">
{{- partial "nav.html" . -}}
<article>
<p class="error">
&#9949; <u>404</u>&nbsp;{{- site.Params.labels.error -}}&nbsp;&#9949;
</p>
<p class="error">
&#9949; <u>404</u>&nbsp;{{- site.Params.labels.error -}}&nbsp;&#9949;
</p>
<p class="error">
&#9949; <u>404</u>&nbsp;{{- site.Params.labels.error -}}&nbsp;&#9949;
</p>
</article>
</div>
<article class="info">
<p class="error">&#9949; <u>404</u>&nbsp;{{- i18n 404 -}}&nbsp;&#9949;</p>
<p class="error">&#9949; <u>404</u>&nbsp;{{- i18n 404 -}}&nbsp;&#9949;</p>
<p class="error">&#9949; <u>404</u>&nbsp;{{- i18n 404 -}}&nbsp;&#9949;</p>
</article>
{{- end -}}

View File

@@ -1,16 +1,17 @@
{{- define "main" -}}
<div
class="container"
data-next="{{- i18n "next" -}}"
data-prev="{{- i18n "prev" -}}"
data-close="{{- i18n "close" -}}"
data-loading="{{- i18n "loading" -}}"
data-next="{{- site.Params.labels.next -}}"
data-prev="{{- site.Params.labels.prev -}}"
data-close="{{- site.Params.labels.close -}}"
data-loading="{{- site.Params.labels.loading -}}"
>
{{- partial "nav.html" . -}}
{{- with .Content -}}
<article class="info">
<article>
{{- . -}}
</article>
{{- end -}}
{{- partial "nav.html" . -}}
</div>
{{- end -}}

Some files were not shown because too many files have changed in this diff Show More