summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile83
-rw-r--r--README.adoc5
-rw-r--r--deps.mk65
-rw-r--r--src/content/img/icon/add/light.svg22
-rw-r--r--src/content/img/icon/archive/light.svg43
-rw-r--r--src/content/img/icon/arrow-down/light.svg20
-rw-r--r--src/content/img/icon/bookmark/light.svg30
-rw-r--r--src/content/img/icon/calendar/light.svg32
-rw-r--r--src/content/img/icon/check/light.svg17
-rw-r--r--src/content/img/icon/chevron-down/light.svg17
-rw-r--r--src/content/img/icon/chevron-left/light.svg18
-rw-r--r--src/content/img/icon/chevron-right/light.svg18
-rw-r--r--src/content/img/icon/clipboard/light.svg41
-rw-r--r--src/content/img/icon/close/light.svg26
-rw-r--r--src/content/img/icon/code-file/light.svg52
-rw-r--r--src/content/img/icon/code/light.svg28
-rw-r--r--src/content/img/icon/crop/light.svg49
-rw-r--r--src/content/img/icon/delete/light.svg46
-rw-r--r--src/content/img/icon/download/light.svg26
-rw-r--r--src/content/img/icon/edit/light.svg29
-rw-r--r--src/content/img/icon/filter/light.svg28
-rw-r--r--src/content/img/icon/folder/light.svg27
-rw-r--r--src/content/img/icon/fullscreen/light.svg30
-rw-r--r--src/content/img/icon/hash-sign/light.svg22
-rw-r--r--src/content/img/icon/heart/light.svg23
-rw-r--r--src/content/img/icon/help/light.svg44
-rw-r--r--src/content/img/icon/info/light.svg23
-rw-r--r--src/content/img/icon/launch/light.svg28
-rw-r--r--src/content/img/icon/link/light.svg28
-rw-r--r--src/content/img/icon/lock/light.svg38
-rw-r--r--src/content/img/icon/logout/light.svg30
-rw-r--r--src/content/img/icon/needs-update/light.svg38
-rw-r--r--src/content/img/icon/notifications-off/light.svg75
-rw-r--r--src/content/img/icon/notifications/light.svg114
-rw-r--r--src/content/img/icon/offline/light.svg61
-rw-r--r--src/content/img/icon/online/light.svg99
-rw-r--r--src/content/img/icon/password/light.svg60
-rw-r--r--src/content/img/icon/payment-card/light.svg37
-rw-r--r--src/content/img/icon/photo/light.svg35
-rw-r--r--src/content/img/icon/pin/light.svg57
-rw-r--r--src/content/img/icon/remove/light.svg13
-rw-r--r--src/content/img/icon/sad/light.svg48
-rw-r--r--src/content/img/icon/save/light.svg57
-rw-r--r--src/content/img/icon/scissors/light.svg55
-rw-r--r--src/content/img/icon/search/light.svg21
-rw-r--r--src/content/img/icon/settings/light.svg462
-rw-r--r--src/content/img/icon/share/light.svg38
-rw-r--r--src/content/img/icon/shield-bad/light.svg36
-rw-r--r--src/content/img/icon/shield-good/light.svg31
-rw-r--r--src/content/img/icon/shield-info/light.svg36
-rw-r--r--src/content/img/icon/shield-off/light.svg51
-rw-r--r--src/content/img/icon/shopping-cart/light.svg54
-rw-r--r--src/content/img/icon/star-full/light.svg36
-rw-r--r--src/content/img/icon/star/light.svg36
-rw-r--r--src/content/img/icon/support/light.svg40
-rw-r--r--src/content/img/icon/tag/light.svg32
-rw-r--r--src/content/img/icon/threads/light.svg27
-rw-r--r--src/content/img/icon/upload/light.svg26
-rw-r--r--src/content/img/icon/user-add/light.svg32
-rw-r--r--src/content/img/icon/user-check/light.svg27
-rw-r--r--src/content/img/icon/user-circle/light.svg32
-rw-r--r--src/content/img/icon/user-group/light.svg33
-rw-r--r--src/content/img/icon/user-remove/light.svg32
-rw-r--r--src/content/img/icon/user/light.svg26
-rw-r--r--src/content/img/icon/warning/light.svg38
-rw-r--r--src/content/img/icon/zoom-in/light.svg41
-rw-r--r--src/content/img/icon/zoom-out/light.svg29
-rw-r--r--src/content/img/profile/fallback.svg1
-rw-r--r--src/content/index.html415
-rw-r--r--src/content/papo.js42
-rw-r--r--src/content/style.css43
-rw-r--r--src/content/sw.js270
-rw-r--r--tests/browser-driver.js1
-rw-r--r--tests/driver.html12
-rw-r--r--tests/driver.js20
-rw-r--r--tests/node-driver.js43
-rw-r--r--tests/papo.js50
-rw-r--r--tests/sw.js118
79 files changed, 3746 insertions, 223 deletions
diff --git a/.gitignore b/.gitignore
index d2b9f22..21335e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/src/sw-pre.js
/src/content/papo.exported.js
/src/content/sw.exported.js
/src/content/service-worker.js
diff --git a/Makefile b/Makefile
index 669e9cc..f1e01eb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,24 @@
.POSIX:
-NAME = webapp
+DATE = 1970-01-01
+VERSION = 0.1.0
+NAME = chat.papo.im
+NAME_UC = $(NAME)
+LANGUAGES = en
+## Installation prefix. Defaults to "/usr".
PREFIX = /usr
+BINDIR = $(PREFIX)/bin
+LIBDIR = $(PREFIX)/lib
+INCLUDEDIR = $(PREFIX)/include
SRCDIR = $(PREFIX)/src/$(NAME)
SHAREDIR = $(PREFIX)/share
-# DOCDIR? JavaScript goes to DOCDIR? Really?
+LOCALEDIR = $(SHAREDIR)/locale
+MANDIR = $(SHAREDIR)/man
DOCDIR = $(SHAREDIR)/doc/$(NAME)
+HTMLDIR = $(SHAREDIR)/html/$(NAME)
+EXEC = ./
+## Where to store the installation. Empty by default.
+DESTDIR =
+LDLIBS =
@@ -12,37 +26,51 @@ DOCDIR = $(SHAREDIR)/doc/$(NAME)
.SUFFIXES: .js
+
all:
include deps.mk
-
-static-contents = \
+sources = \
src/content/papo.js \
src/content/style.css \
src/content/index.html \
+ src/content/sw.js \
+ $(img.svg) \
contents = \
+ src/content/papo.js \
+ src/content/style.css \
+ src/content/index.html \
src/content/service-worker.js \
$(img.svg) \
derived-assets = \
+ src/sw-pre.js \
src/content/papo.exported.js \
src/content/sw.exported.js \
src/content/service-worker.js \
+side-assets = \
+
+## Default target. Builds all artifacts required for testing
+## and installation.
all: $(derived-assets)
+src/sw-pre.js: Makefile deps.mk
+ printf 'const IMG_PATHS = [\n' > $@
+ printf '\t"%s",\n' $(img.svg) >> $@
+ printf '];\n\n' >> $@
## The use of static `import` statements inside service workers
## isn't supported. So in order to have tests for the code in
## it, a "main()" function is included in the generated file
## so that is can be ran as a standalone file.
-src/content/service-worker.js: src/content/sw.js src/sw-main.js Makefile
- cat src/content/sw.js src/sw-main.js > $@
+src/content/service-worker.js: src/sw-pre.js src/content/sw.js src/sw-main.js
+ tail -n+2 src/content/sw.js | cat src/sw-pre.js - src/sw-main.js > $@
src/content/papo.exported.js src/content/sw.exported.js: \
Makefile src/exported.sh
@@ -60,38 +88,63 @@ tests/sw.js-check: src/content/sw.exported.js
tests/papo.js-check tests/sw.js-check:
node tests/node-driver.js $*.js
+src/content/service-worker.js-check: src/content/service-worker.js
+ test "`grep -c '^const IMG_PATHS ' $*.js`" = 1
check-unit: tests/papo.js-check tests/sw.js-check
+check-unit: src/content/service-worker.js-check
+
+
+integration-tests = \
-check-integration:
+.PRECIOUS: $(integration-tests)
+$(integration-tests): ALWAYS
+ sh $@
+check-integration: $(integration-tests)
+
+
+## Run all tests. Each test suite is isolated, so that a parallel
+## build can run tests at the same time. The required artifacts
+## are created if missing.
check: check-unit check-integration
+
+## Remove *all* derived artifacts produced during the build.
+## A dedicated test asserts that this is always true.
clean:
rm -rf $(derived-assets) $(side-assets)
-install: all
- mkdir -p \
- '$(DESTDIR)$(SRCDIR)' \
- for f in $(contents) $(static-contents); do \
- dir='$(DESTDIR)$(DOCDIR)'/"`dirname "$${f#src/content/}"`"; \
+## Installs into $(DESTDIR)$(PREFIX). Its dependency target
+## ensures that all installable artifacts are crafted beforehand.
+install: all
+ for f in $(contents); do \
+ dir='$(DESTDIR)$(HTMLDIR)'/"`dirname "$${f#src/content/}"`"; \
+ mkdir -p "$$dir"; \
+ cp -P "$$f" "$$dir"; \
+ done
+ for f in $(sources); do \
+ dir='$(DESTDIR)$(SRCDIR)'/"`dirname "$${f#src/content/}"`"; \
mkdir -p "$$dir"; \
cp -P "$$f" "$$dir"; \
done
+## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror
+## of the "install" target, and removes *all* that was installed.
+## A dedicated test asserts that this is always true.
uninstall:
rm -rf \
'$(DESTDIR)$(SRCDIR)' \
- '$(DESTDIR)$(DOCDIR)' \
+ '$(DESTDIR)$(HTMLDIR)' \
PORT = 3334
-## Run file server for local static files
+## Run file server for local static files.
run:
- serve -n -p $(PORT) -d '$(DESTDIR)$(DOCDIR)'
+ serve -n -p $(PORT) -d '$(DESTDIR)$(HTMLDIR)'
ALWAYS:
diff --git a/README.adoc b/README.adoc
new file mode 100644
index 0000000..cf16c69
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,5 @@
+https://www.svgrepo.com/collection/kalai-oval-interface-icons/
+
+https://www.svgrepo.com/collection/minimal-ui-icons/
+https://www.svgrepo.com/collection/chunk-16px-thick-interface-icons/
+https://perchance.org/ai-face-generator
diff --git a/deps.mk b/deps.mk
index b5d3842..f79c950 100644
--- a/deps.mk
+++ b/deps.mk
@@ -1,5 +1,70 @@
img.svg = \
src/content/img/favicon.svg \
+ src/content/img/icon/add/light.svg \
+ src/content/img/icon/archive/light.svg \
+ src/content/img/icon/arrow-down/light.svg \
+ src/content/img/icon/bookmark/light.svg \
+ src/content/img/icon/calendar/light.svg \
+ src/content/img/icon/check/light.svg \
+ src/content/img/icon/chevron-down/light.svg \
+ src/content/img/icon/chevron-left/light.svg \
+ src/content/img/icon/chevron-right/light.svg \
+ src/content/img/icon/clipboard/light.svg \
+ src/content/img/icon/close/light.svg \
+ src/content/img/icon/code-file/light.svg \
+ src/content/img/icon/code/light.svg \
+ src/content/img/icon/crop/light.svg \
+ src/content/img/icon/delete/light.svg \
+ src/content/img/icon/download/light.svg \
+ src/content/img/icon/edit/light.svg \
+ src/content/img/icon/filter/light.svg \
+ src/content/img/icon/folder/light.svg \
+ src/content/img/icon/fullscreen/light.svg \
+ src/content/img/icon/hash-sign/light.svg \
+ src/content/img/icon/heart/light.svg \
+ src/content/img/icon/help/light.svg \
+ src/content/img/icon/info/light.svg \
+ src/content/img/icon/launch/light.svg \
+ src/content/img/icon/link/light.svg \
+ src/content/img/icon/lock/light.svg \
+ src/content/img/icon/logout/light.svg \
+ src/content/img/icon/needs-update/light.svg \
+ src/content/img/icon/notifications-off/light.svg \
+ src/content/img/icon/notifications/light.svg \
+ src/content/img/icon/offline/light.svg \
+ src/content/img/icon/online/light.svg \
+ src/content/img/icon/password/light.svg \
+ src/content/img/icon/payment-card/light.svg \
+ src/content/img/icon/photo/light.svg \
+ src/content/img/icon/pin/light.svg \
+ src/content/img/icon/remove/light.svg \
+ src/content/img/icon/sad/light.svg \
+ src/content/img/icon/save/light.svg \
+ src/content/img/icon/scissors/light.svg \
+ src/content/img/icon/search/light.svg \
+ src/content/img/icon/settings/light.svg \
+ src/content/img/icon/share/light.svg \
+ src/content/img/icon/shield-bad/light.svg \
+ src/content/img/icon/shield-good/light.svg \
+ src/content/img/icon/shield-info/light.svg \
+ src/content/img/icon/shield-off/light.svg \
+ src/content/img/icon/shopping-cart/light.svg \
+ src/content/img/icon/star-full/light.svg \
+ src/content/img/icon/star/light.svg \
+ src/content/img/icon/support/light.svg \
+ src/content/img/icon/tag/light.svg \
+ src/content/img/icon/threads/light.svg \
+ src/content/img/icon/upload/light.svg \
+ src/content/img/icon/user-add/light.svg \
+ src/content/img/icon/user-check/light.svg \
+ src/content/img/icon/user-circle/light.svg \
+ src/content/img/icon/user-group/light.svg \
+ src/content/img/icon/user-remove/light.svg \
+ src/content/img/icon/user/light.svg \
+ src/content/img/icon/warning/light.svg \
+ src/content/img/icon/zoom-in/light.svg \
+ src/content/img/icon/zoom-out/light.svg \
src/content/img/logo/dark.svg \
src/content/img/logo/light.svg \
+ src/content/img/profile/fallback.svg \
diff --git a/src/content/img/icon/add/light.svg b/src/content/img/icon/add/light.svg
new file mode 100644
index 0000000..213a211
--- /dev/null
+++ b/src/content/img/icon/add/light.svg
@@ -0,0 +1,22 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 7 12
+ L 12 12
+ M 12 12
+ L 17 12
+ M 12 12
+ V 7
+ M 12 12
+ L 12 17
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/archive/light.svg b/src/content/img/icon/archive/light.svg
new file mode 100644
index 0000000..39229c0
--- /dev/null
+++ b/src/content/img/icon/archive/light.svg
@@ -0,0 +1,43 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <rect
+ x="3"
+ y="4"
+ width="18"
+ height="5"
+ rx="1"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 5 9
+ H 19
+ V 18
+ C 19 19.1046 18.1046 20 17 20
+ H 7
+ C 5.89543 20 5 19.1046 5 18
+ V 9
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 10 13
+ H 14
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/arrow-down/light.svg b/src/content/img/icon/arrow-down/light.svg
new file mode 100644
index 0000000..943a86f
--- /dev/null
+++ b/src/content/img/icon/arrow-down/light.svg
@@ -0,0 +1,20 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 12 4
+ L 12 20
+ M 12 20
+ L 6 14
+ M 12 20
+ L 18 14
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+/>
+</svg>
diff --git a/src/content/img/icon/bookmark/light.svg b/src/content/img/icon/bookmark/light.svg
new file mode 100644
index 0000000..f61f094
--- /dev/null
+++ b/src/content/img/icon/bookmark/light.svg
@@ -0,0 +1,30 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 7 7.2
+ C 7 6.07989 7 5.51984 7.21799 5.09202
+ C 7.40973 4.71569 7.71569 4.40973 8.09202 4.21799
+ C 8.51984 4 9.07989 4 10.2 4
+ H 13.8
+ C 14.9201 4 15.4802 4 15.908 4.21799
+ C 16.2843 4.40973 16.5903 4.71569 16.782 5.09202
+ C 17 5.51984 17 6.07989 17 7.2
+ V 20
+ L 14.126 17.4453
+ C 13.3737 16.7766 12.9976 16.4423 12.5732 16.3154
+ C 12.1992 16.2035 11.8008 16.2035 11.4268 16.3154
+ C 11.0024 16.4423 10.6263 16.7766 9.87404 17.4453
+ L 7 20
+ V 7.2
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/calendar/light.svg b/src/content/img/icon/calendar/light.svg
new file mode 100644
index 0000000..3ac4583
--- /dev/null
+++ b/src/content/img/icon/calendar/light.svg
@@ -0,0 +1,32 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 20 10
+ V 7
+ C 20 5.89543 19.1046 5 18 5
+ H 6
+ C 4.89543 5 4 5.89543 4 7
+ V 10
+ M 20 10
+ V 19
+ C 20 20.1046 19.1046 21 18 21
+ H 6
+ C 4.89543 21 4 20.1046 4 19
+ V 10
+ M 20 10
+ H 4
+ M 8 3
+ V 7
+ M 16 3
+ V 7
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/check/light.svg b/src/content/img/icon/check/light.svg
new file mode 100644
index 0000000..b226735
--- /dev/null
+++ b/src/content/img/icon/check/light.svg
@@ -0,0 +1,17 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 7 13
+ L 10 16
+ L 17 9
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/chevron-down/light.svg b/src/content/img/icon/chevron-down/light.svg
new file mode 100644
index 0000000..de1f8b1
--- /dev/null
+++ b/src/content/img/icon/chevron-down/light.svg
@@ -0,0 +1,17 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 19 9
+ L 12.7071 15.2929
+ C 12.3166 15.6834 11.6834 15.6834 11.2929 15.2929
+ L 5 9"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/chevron-left/light.svg b/src/content/img/icon/chevron-left/light.svg
new file mode 100644
index 0000000..bbdc4bc
--- /dev/null
+++ b/src/content/img/icon/chevron-left/light.svg
@@ -0,0 +1,18 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 15.5 19
+ L 9.20711 12.7071
+ C 8.81658 12.3166 8.81658 11.6834 9.20711 11.2929
+ L 15.5 5
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/chevron-right/light.svg b/src/content/img/icon/chevron-right/light.svg
new file mode 100644
index 0000000..58631ed
--- /dev/null
+++ b/src/content/img/icon/chevron-right/light.svg
@@ -0,0 +1,18 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 9.5 5
+ L 15.7929 11.2929
+ C 16.1834 11.6834 16.1834 12.3166 15.7929 12.7071
+ L 9.5 19
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/clipboard/light.svg b/src/content/img/icon/clipboard/light.svg
new file mode 100644
index 0000000..5705904
--- /dev/null
+++ b/src/content/img/icon/clipboard/light.svg
@@ -0,0 +1,41 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 9 5
+ C 9 3.89543 9.89543 3 11 3
+ H 13
+ C 14.1046 3 15 3.89543 15 5
+ V 7
+ H 9
+ V 5
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 9 5
+ H 7
+ C 5.89543 5 5 5.89543 5 7
+ V 19
+ C 5 20.1046 5.89543 21 7 21
+ H 12
+ H 17
+ C 18.1046 21 19 20.1046 19 19
+ V 7
+ C 19 5.89543 18.1046 5 17 5
+ H 15
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/close/light.svg b/src/content/img/icon/close/light.svg
new file mode 100644
index 0000000..0a29350
--- /dev/null
+++ b/src/content/img/icon/close/light.svg
@@ -0,0 +1,26 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 8 8
+ L 16 16
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 16 8
+ L 8 16
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/code-file/light.svg b/src/content/img/icon/code-file/light.svg
new file mode 100644
index 0000000..ae40206
--- /dev/null
+++ b/src/content/img/icon/code-file/light.svg
@@ -0,0 +1,52 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 13.5 3
+ H 12
+ H 8
+ C 6.34315 3 5 4.34315 5 6
+ V 18
+ C 5 19.6569 6.34315 21 8 21
+ H 16
+ C 17.6569 21 19 19.6569 19 18
+ V 10.8125
+ V 8.625
+ M 13.5 3
+ L 19 8.625
+ M 13.5 3
+ V 7.625
+ C 13.5 8.17728 13.9477 8.625 14.5 8.625
+ H 19
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 10 12
+ L 8 14
+ L 10 16
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 14 12
+ L 16 14
+ L 14 16
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/code/light.svg b/src/content/img/icon/code/light.svg
new file mode 100644
index 0000000..7537e04
--- /dev/null
+++ b/src/content/img/icon/code/light.svg
@@ -0,0 +1,28 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 9 7
+ L 4 12
+ L 9 17
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 15 7
+ L 20 12
+ L 15 17
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/crop/light.svg b/src/content/img/icon/crop/light.svg
new file mode 100644
index 0000000..f90ae13
--- /dev/null
+++ b/src/content/img/icon/crop/light.svg
@@ -0,0 +1,49 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 20 16
+ L 10 16
+ C 8.89543 16 8 15.1046 8 14
+ L 8 4
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ d="
+ M 17 13
+ V 10
+ C 17 8.34315 15.6569 7 14 7
+ H 11
+ V 9
+ H 14
+ C 14.5523 9 15 9.44772 15 10
+ V 13
+ H 17
+ Z
+ M 9 9
+ V 7
+ H 4
+ C 3.44772 7 3 7.44772 3 8
+ C 3 8.55228 3.44772 9 4 9
+ H 9
+ Z
+ M 15 15
+ H 17
+ V 20
+ C 17 20.5523 16.5523 21 16 21
+ C 15.4477 21 15 20.5523 15 20
+ V 15
+ Z
+ "
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/delete/light.svg b/src/content/img/icon/delete/light.svg
new file mode 100644
index 0000000..a3e2adf
--- /dev/null
+++ b/src/content/img/icon/delete/light.svg
@@ -0,0 +1,46 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 4 7
+ H 20
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 6 7
+ V 18
+ C 6 19.6569 7.34315 21 9 21
+ H 15
+ C 16.6569 21 18 19.6569 18 18
+ V 7
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 9 5
+ C 9 3.89543 9.89543 3 11 3
+ H 13
+ C 14.1046 3 15 3.89543 15 5
+ V 7
+ H 9
+ V 5
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/download/light.svg b/src/content/img/icon/download/light.svg
new file mode 100644
index 0000000..e937c56
--- /dev/null
+++ b/src/content/img/icon/download/light.svg
@@ -0,0 +1,26 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 19 15
+ V 17
+ C 19 18.1046 18.1046 19 17 19
+ H 7
+ C 5.89543 19 5 18.1046 5 17
+ V 15
+ M 12 5
+ V 15
+ M 12 15
+ L 10 13
+ M 12 15
+ L 14 13
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/edit/light.svg b/src/content/img/icon/edit/light.svg
new file mode 100644
index 0000000..eea0cef
--- /dev/null
+++ b/src/content/img/icon/edit/light.svg
@@ -0,0 +1,29 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 18.3785 8.44975
+ L 8.9636 17.8648
+ C 8.6844 18.144 8.3288 18.3343 7.94161 18.4117
+ L 4.99988 19.0001
+ L 5.58823 16.0583
+ c 5.66566 15.6711 5.85597 15.3155 6.13517 15.0363
+ L 15.5501 5.62132
+ M 18.3785 8.44975
+ L 19.7927 7.03553
+ C 20.1832 6.64501 20.1832 6.01184 19.7927 5.62132
+ L 18.3785 4.20711
+ C 17.988 3.81658 17.3548 3.81658 16.9643 4.20711
+ L 15.5501 5.62132
+ M 18.3785 8.44975
+ L 15.5501 5.62132
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/filter/light.svg b/src/content/img/icon/filter/light.svg
new file mode 100644
index 0000000..dfb45ea
--- /dev/null
+++ b/src/content/img/icon/filter/light.svg
@@ -0,0 +1,28 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 17.8258 5
+ H 6.17422
+ C 5.31987 5 4.85896 6.00212 5.41496 6.65079
+ L 9.75926 11.7191
+ C 9.91461 11.9004 10 12.1312 10 12.3699
+ V 17.382
+ C 10 17.7607 10.214 18.107 10.5528 18.2764
+ L 12.5528 19.2764
+ C 13.2177 19.6088 14 19.1253 14 18.382
+ V 12.3699
+ C 14 12.1312 14.0854 11.9004 14.2407 11.7191
+ L 18.585 6.65079
+ C 19.141 6.00212 18.6801 5 17.8258 5
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/folder/light.svg b/src/content/img/icon/folder/light.svg
new file mode 100644
index 0000000..06bf56a
--- /dev/null
+++ b/src/content/img/icon/folder/light.svg
@@ -0,0 +1,27 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 3 17
+ V 7
+ C 3 5.89543 3.89543 5 5 5
+ H 9.58579
+ C 9.851 5 10.1054 5.10536 10.2929 5.29289
+ L 12 7
+ H 19
+ C 20.1046 7 21 7.89543 21 9
+ V 17
+ C 21 18.1046 20.1046 19 19 19
+ H 5
+ C 3.89543 19 3 18.1046 3 17
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/fullscreen/light.svg b/src/content/img/icon/fullscreen/light.svg
new file mode 100644
index 0000000..3dc2668
--- /dev/null
+++ b/src/content/img/icon/fullscreen/light.svg
@@ -0,0 +1,30 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 4 15
+ V 18
+ C 4 19.1046 4.89543 20 6 20
+ H 9
+ M 15.2173 20
+ H 18
+ C 19.1046 20 20 19.1046 20 18
+ V 15
+ M 20 9
+ V 6
+ C 20 4.89543 19.1046 4 18 4
+ H 15
+ M 4 9
+ V 6
+ C 4 4.89543 4.89543 4 6 4
+ H 9
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/hash-sign/light.svg b/src/content/img/icon/hash-sign/light.svg
new file mode 100644
index 0000000..7dc713e
--- /dev/null
+++ b/src/content/img/icon/hash-sign/light.svg
@@ -0,0 +1,22 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 4 8
+ H 20
+ M 4 16
+ H 20
+ M 8 3
+ V 21
+ M 16 3
+ V 21
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/heart/light.svg b/src/content/img/icon/heart/light.svg
new file mode 100644
index 0000000..ddf97cf
--- /dev/null
+++ b/src/content/img/icon/heart/light.svg
@@ -0,0 +1,23 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 4.42602 12.3115
+ L 12 19.8854
+ L 19.574 12.3115
+ C 21.4753 10.4101 21.4753 7.32738 19.574 5.42602
+ C 17.6726 3.52466 14.5899 3.52466 12.6885 5.42602
+ L 12 6.11456
+ L 11.3115 5.42602
+ C 9.4101 3.52466 6.32738 3.52466 4.42602 5.42602
+ C 2.52466 7.32738 2.52466 10.4101 4.42602 12.3115
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/help/light.svg b/src/content/img/icon/help/light.svg
new file mode 100644
index 0000000..07ee03b
--- /dev/null
+++ b/src/content/img/icon/help/light.svg
@@ -0,0 +1,44 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 10 9
+ C 10 8.60444 10.1173 8.21776 10.3371 7.88886
+ C 10.5568 7.55996 10.8692 7.30362 11.2346 7.15224
+ C 11.6001 7.00087 12.0022 6.96126 12.3902 7.03843
+ C 12.7781 7.1156 13.1345 7.30608 13.4142 7.58579
+ C 13.6939 7.86549 13.8844 8.22186 13.9616 8.60982
+ C 14.0387 8.99778 13.9991 9.39992 13.8478 9.76537
+ C 13.6964 10.1308 13.44 10.4432 13.1111 10.6629
+ C 12.7822 10.8827 12.3956 11 12 11
+ V 12
+ M 14.25 19
+ L 12.8 20.9333
+ C 12.4 21.4667 11.6 21.4667 11.2 20.9333
+ L 9.75 19
+ H 7
+ C 4.79086 19 3 17.2091 3 15
+ V 7
+ C 3 4.79086 4.79086 3 7 3
+ H 17
+ C 19.2091 3 21 4.79086 21 7
+ V 15
+ C 21 17.2091 19.2091 19 17 19
+ H 14.25
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="12"
+ cy="15"
+ r="1"
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/info/light.svg b/src/content/img/icon/info/light.svg
new file mode 100644
index 0000000..1f533f3
--- /dev/null
+++ b/src/content/img/icon/info/light.svg
@@ -0,0 +1,23 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 12 11
+ V 16
+ M 21 12
+ C 21 16.9706 16.9706 21 12 21
+ C 7.02944 21 3 16.9706 3 12
+ C 3 7.02944 7.02944 3 12 3
+ C 16.9706 3 21 7.02944 21 12
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle cx="12" cy="7.5" r="1" fill="black" />
+</svg>
diff --git a/src/content/img/icon/launch/light.svg b/src/content/img/icon/launch/light.svg
new file mode 100644
index 0000000..78edfda
--- /dev/null
+++ b/src/content/img/icon/launch/light.svg
@@ -0,0 +1,28 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 10.1429 7
+ H 7
+ C 5.89543 7 5 7.89543 5 9
+ V 17
+ C 5 18.1046 5.89543 19 7 19
+ H 15
+ C 16.1046 19 17 18.1046 17 17
+ V 13.2143
+ M 19 5
+ H 15
+ M 19 5
+ V 9
+ M 19 5
+ L 9 15
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/link/light.svg b/src/content/img/icon/link/light.svg
new file mode 100644
index 0000000..672c0d4
--- /dev/null
+++ b/src/content/img/icon/link/light.svg
@@ -0,0 +1,28 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 7.7574 10.5858
+ L 4.92897 13.4142
+ C 3.7574 14.5858 3.7574 16.4853 4.92897 17.6569
+ L 6.34319 19.0711
+ C 7.51476 20.2427 9.41425 20.2427 10.5858 19.0711
+ L 13.4143 16.2427
+ M 9.87873 14.1214
+ L 14.1214 9.87873
+ M 10.5858 7.7574
+ L 13.4142 4.92897
+ C 14.5858 3.7574 16.4853 3.7574 17.6569 4.92897
+ L 19.0711 6.34319
+ C 20.2427 7.51476 20.2427 9.41425 19.0711 10.5858
+ L 16.2427 13.4143
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/lock/light.svg b/src/content/img/icon/lock/light.svg
new file mode 100644
index 0000000..61a2d11
--- /dev/null
+++ b/src/content/img/icon/lock/light.svg
@@ -0,0 +1,38 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 16 9
+ V 6
+ C 16 4.34315 14.6569 3 13 3
+ H 11
+ C 9.34315 3 8 4.34315 8 6
+ V 9
+ M 16 9
+ H 8
+ M 16 9
+ C 17.6569 9 19 10.3431 19 12
+ V 18
+ C 19 19.6569 17.6569 21 16 21
+ H 8
+ C 6.34315 21 5 19.6569 5 18
+ V 12
+ C 5 10.3431 6.34315 9 8 9
+ M 12 14
+ V 17
+ M 13 14
+ C 13 14.5523 12.5523 15 12 15
+ C 11.4477 15 11 14.5523 11 14
+ C 11 13.4477 11.4477 13 12 13
+ C 12.5523 13 13 13.4477 13 14
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/logout/light.svg b/src/content/img/icon/logout/light.svg
new file mode 100644
index 0000000..1af7165
--- /dev/null
+++ b/src/content/img/icon/logout/light.svg
@@ -0,0 +1,30 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 15 16.5
+ V 19
+ C 15 20.1046 14.1046 21 13 21
+ H 6
+ C 4.89543 21 4 20.1046 4 19
+ V 5
+ C 4 3.89543 4.89543 3 6 3
+ H 13
+ C 14.1046 3 15 3.89543 15 5
+ V 8.0625
+ M 11 12
+ H 21
+ M 21 12
+ L 18.5 9.5
+ M 21 12
+ L 18.5 14.5
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/needs-update/light.svg b/src/content/img/icon/needs-update/light.svg
new file mode 100644
index 0000000..8609c4e
--- /dev/null
+++ b/src/content/img/icon/needs-update/light.svg
@@ -0,0 +1,38 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 18.4721 16.7023
+ C 17.3398 18.2608 15.6831 19.3584 13.8064 19.7934
+ C 11.9297 20.2284 9.95909 19.9716 8.25656 19.0701
+ C 6.55404 18.1687 5.23397 16.6832 4.53889 14.8865
+ C 3.84381 13.0898 3.82039 11.1027 4.47295 9.29011
+ C 5.12551 7.47756 6.41021 5.96135 8.09103 5.02005
+ C 9.77184 4.07875 11.7359 3.77558 13.6223 4.16623
+ C 15.5087 4.55689 17.1908 5.61514 18.3596 7.14656
+ C 19.5283 8.67797 20.1052 10.5797 19.9842 12.5023
+ M 19.9842 12.5023
+ L 21.4842 11.0023
+ M 19.9842 12.5023
+ L 18.4842 11.0023
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 12 8
+ V 12
+ L 15 15
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/notifications-off/light.svg b/src/content/img/icon/notifications-off/light.svg
new file mode 100644
index 0000000..10a9fbc
--- /dev/null
+++ b/src/content/img/icon/notifications-off/light.svg
@@ -0,0 +1,75 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ d="
+ M 6.90904 5.82325
+ C 6.33296 6.7445 6 7.83337 6 9
+ V 11.7564
+ C 6 12.1579 5.70766 12.6054 5.09976 13.2452
+ C 4.41915 13.9616 4 14.9329 4 16
+ C 4 17.1046 4.89543 18 6 18
+ H 7
+ H 16
+ C 16.8342 18 17.5492 17.4892 17.8492 16.7634
+ L 16 14.9142
+ V 16
+ H 7
+ H 6
+ C 6 15.4658 6.20812 14.9823 6.54971 14.6228
+ C 7.10947 14.0336 8 13.05 8 11.7564
+ V 9
+ C 8 8.3901 8.1365 7.81208 8.38062 7.29483
+ L 6.90904 5.82325
+ Z
+ M 16 12.0858
+ V 9
+ C 16 6.79086 14.2091 5 12 5
+ C 11.1288 5 10.3226 5.27854 9.66565 5.75143
+ L 8.23901 4.3248
+ C 9.26789 3.49606 10.576 3 12 3
+ C 15.3137 3 18 5.68629 18 9
+ V 14.0858
+ L 16 12.0858
+ Z
+ "
+ fill="black"
+ />
+ <path
+ d="
+ M 3 3
+ L 21 21
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 13.7976 19.8767
+ C 13.6312 20.2179 13.3712 20.5046 13.048 20.7035
+ C 12.7247 20.9023 12.3516 21.0051 11.9721 20.9998
+ C 11.5926 20.9945 11.2224 20.8813 10.9049 20.6735
+ C 10.5873 20.4657 10.3354 20.1718 10.1786 19.8262
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 12 3
+ V 4
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/notifications/light.svg b/src/content/img/icon/notifications/light.svg
new file mode 100644
index 0000000..22d3290
--- /dev/null
+++ b/src/content/img/icon/notifications/light.svg
@@ -0,0 +1,114 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 5.82474 13.934
+ L 5.09976 13.2452
+ L 5.82474 13.934
+ Z
+ M 8 9
+ C 8 6.79086 9.79086 5 12 5
+ V 3
+ C 8.68629 3 6 5.68629 6 9
+ H 8
+ Z
+ M 8 11.7564
+ V 9
+ H 6
+ V 11.7564
+ H 8
+ Z
+ M 6 16
+ C 6 15.4658 6.20812 14.9823 6.54971 14.6228
+ L 5.09976 13.2452
+ C 4.41915 13.9616 4 14.9329 4 16
+ H 6
+ Z
+ M 7 16
+ H 6
+ V 18
+ H 7
+ V 16
+ Z
+ M 17 16
+ H 7
+ V 18
+ H 17
+ V 16
+ Z
+ M 18 16
+ H 17
+ V 18
+ H 18
+ V 16
+ Z
+ M 17.4503 14.6228
+ C 17.7919 14.9823 18 15.4658 18 16
+ H 20
+ C 20 14.9329 19.5809 13.9616 18.9002 13.2452
+ L 17.4503 14.6228
+ Z
+ M 16 9
+ V 11.7564
+ H 18
+ V 9
+ H 16
+ Z
+ M 12 5
+ C 14.2091 5 16 6.79086 16 9
+ H 18
+ C 18 5.68629 15.3137 3 12 3
+ V 5
+ Z
+ M 18.9002 13.2452
+ C 18.2923 12.6054 18 12.1579 18 11.7564
+ H 16
+ C 16 13.05 16.8905 14.0336 17.4503 14.6228
+ L 18.9002 13.2452
+ Z
+ M 4 16
+ C 4 17.1046 4.89543 18 6 18
+ V 16
+ H 4
+ Z
+ M 18 18
+ C 19.1046 18 20 17.1046 20 16
+ H 18
+ V 18
+ Z
+ M 6 11.7564
+ C 6 12.1579 5.70766 12.6054 5.09976 13.2452
+ L 6.54971 14.6228
+ C 7.10947 14.0336 8 13.05 8 11.7564
+ H 6
+ Z
+ "
+ fill="black"
+ />
+ <path
+ d="
+ M 13.7976 19.8767
+ C 13.6312 20.2179 13.3712 20.5046 13.048 20.7035
+ C 12.7247 20.9023 12.3516 21.0051 11.9721 20.9998
+ C 11.5926 20.9945 11.2224 20.8813 10.9049 20.6735
+ C 10.5873 20.4657 10.3354 20.1718 10.1786 19.8262
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 12 3
+ V 4
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/offline/light.svg b/src/content/img/icon/offline/light.svg
new file mode 100644
index 0000000..ad170d8
--- /dev/null
+++ b/src/content/img/icon/offline/light.svg
@@ -0,0 +1,61 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ d="
+ M 6.94676 5.86111
+ C 5.91334 6.87554 5.2174 8.23258 5.04286 9.74832
+ C 3.01731 10.4886 1.57129 12.4316 1.57129 14.7142
+ C 1.57129 17.6334 3.93778 19.9999 6.857 19.9999
+ H 8.97059
+ L 8.99986 20
+ H 16.9999
+ C 18.1475 20 19.2049 19.6133 20.0488 18.9631
+ L 18.6145 17.5289
+ C 18.1484 17.8271 17.5943 18 16.9999 18
+ H 8.99986
+ L 8.97773 17.9999
+ V 17.9999
+ H 8.97059
+ H 6.857
+ C 5.04235 17.9999 3.57129 16.5288 3.57129 14.7142
+ C 3.57129 13.1257 4.69946 11.7986 6.19881 11.4942
+ C 6.66583 11.3994 7.00108 10.9882 6.99988 10.5117
+ L 6.99986 10.5
+ C 6.99986 9.23554 7.52138 8.09289 8.36106 7.27541
+ L 6.94676 5.86111
+ Z
+ M 19.8507 15.9367
+ C 19.9475 15.642 19.9999 15.3271 19.9999 15
+ C 19.9999 13.3431 18.6567 12 16.9999 12
+ H 16.9774
+ C 16.6966 12 16.4287 11.8819 16.2393 11.6746
+ C 16.0498 11.4673 15.9563 11.1899 15.9815 10.9102
+ C 15.9936 10.7754 15.9999 10.6385 15.9999 10.5
+ C 15.9999 8.01472 13.9851 6 11.4999 6
+ C 11.0212 6 10.56 6.07474 10.1273 6.21318
+ L 8.5968 4.68272
+ C 9.47056 4.24583 10.4565 4 11.4999 4
+ C 14.9546 4 17.7798 6.69515 17.9876 10.0975
+ C 20.276 10.5561 21.9999 12.5767 21.9999 15
+ C 21.9999 15.889 21.7679 16.7237 21.3611 17.4471
+ L 19.8507 15.9367
+ Z
+ "
+ fill="black"
+ />
+ <path
+ d="
+ M 4 4
+ L 20 20
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/online/light.svg b/src/content/img/icon/online/light.svg
new file mode 100644
index 0000000..34d9a76
--- /dev/null
+++ b/src/content/img/icon/online/light.svg
@@ -0,0 +1,99 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 16.9774 11
+ L 15.9815 10.9102
+ C 15.9563 11.1899 16.0498 11.4673 16.2393 11.6746
+ C 16.4287 11.8819 16.6966 12 16.9774 12
+ V 11
+ Z
+ M 8.97059 18.9999
+ L 8.97773 17.9999
+ H 8.97059
+ V 18.9999
+ Z
+ M 5.99988 10.5142
+ L 6.19881 11.4942
+ C 6.66583 11.3994 7.00108 10.9882 6.99988 10.5117
+ L 5.99988 10.5142
+ Z
+ M 17.9734 11.0898
+ C 17.9909 10.8953 17.9999 10.6985 17.9999 10.5
+ H 15.9999
+ C 15.9999 10.6385 15.9936 10.7754 15.9815 10.9102
+ L 17.9734 11.0898
+ Z
+ M 16.9999 10
+ H 16.9774
+ V 12
+ H 16.9999
+ V 10
+ Z
+ M 21.9999 15
+ C 21.9999 12.2386 19.7613 10 16.9999 10
+ V 12
+ C 18.6567 12 19.9999 13.3431 19.9999 15
+ H 21.9999
+ Z
+ M 16.9999 20
+ C 19.7613 20 21.9999 17.7614 21.9999 15
+ H 19.9999
+ C 19.9999 16.6569 18.6567 18 16.9999 18
+ V 20
+ Z
+ M 8.99986 20
+ H 16.9999
+ V 18
+ H 8.99986
+ V 20
+ Z
+ M 8.96345 19.9999
+ C 8.97555 20 8.98769 20 8.99986 20
+ V 18
+ C 8.9925 18 8.98512 18 8.97773 17.9999
+ L 8.96345 19.9999
+ Z
+ M 8.97059 17.9999
+ H 6.857
+ V 19.9999
+ H 8.97059
+ V 17.9999
+ Z
+ M 6.857 17.9999
+ C 5.04235 17.9999 3.57129 16.5288 3.57129 14.7142
+ H 1.57129
+ C 1.57129 17.6334 3.93778 19.9999 6.857 19.9999
+ V 17.9999
+ Z
+ M 3.57129 14.7142
+ C 3.57129 13.1257 4.69946 11.7986 6.19881 11.4942
+ L 5.80095 9.53418
+ C 3.38787 10.024 1.57129 12.1558 1.57129 14.7142
+ H 3.57129
+ Z
+ M 4.99986 10.5
+ C 4.99986 10.5056 4.99987 10.5111 4.99988 10.5167
+ L 6.99988 10.5117
+ C 6.99987 10.5078 6.99986 10.5039 6.99986 10.5
+ H 4.99986
+ Z
+ M 11.4999 4
+ C 7.91001 4 4.99986 6.91015 4.99986 10.5
+ H 6.99986
+ C 6.99986 8.01472 9.01458 6 11.4999 6
+ V 4
+ Z
+ M 17.9999 10.5
+ C 17.9999 6.91015 15.0897 4 11.4999 4
+ V 6
+ C 13.9851 6 15.9999 8.01472 15.9999 10.5
+ H 17.9999
+ Z
+ "
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/password/light.svg b/src/content/img/icon/password/light.svg
new file mode 100644
index 0000000..e967263
--- /dev/null
+++ b/src/content/img/icon/password/light.svg
@@ -0,0 +1,60 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 9 17.5
+ C 9 18.8807 7.88071 20 6.5 20
+ C 5.11929 20 4 18.8807 4 17.5
+ C 4 16.1193 5.11929 15 6.5 15
+ C 7.88071 15 9 16.1193 9 17.5
+ Z
+ M 9 17.5
+ H 15.125
+ M 19 20
+ V 17.75
+ C 19 17.6119 18.8881 17.5 18.75 17.5
+ M 15.125 17.5
+ H 18.75
+ M 15.125 17.5
+ V 20
+ M 18.75 17.5
+ L 18.75 17.5
+ Z
+ M 5 11
+ H 19
+ C 20.1046 11 21 10.1046 21 9
+ V 6
+ C 21 4.89543 20.1046 4 19 4
+ H 5
+ C 3.89543 4 3 4.89543 3 6
+ V 9
+ C 3 10.1046 3.89543 11 5 11
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="7.5"
+ cy="7.5"
+ r="1.5"
+ fill="black"
+ />
+ <circle
+ cx="12"
+ cy="7.5"
+ r="1.5"
+ fill="black"
+ />
+ <circle
+ cx="16.5"
+ cy="7.5"
+ r="1.5"
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/payment-card/light.svg b/src/content/img/icon/payment-card/light.svg
new file mode 100644
index 0000000..144f1bb
--- /dev/null
+++ b/src/content/img/icon/payment-card/light.svg
@@ -0,0 +1,37 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <rect
+ x="3"
+ y="6"
+ width="18"
+ height="13"
+ rx="2"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 3 10
+ H 20.5
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 7 15
+ H 9
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/photo/light.svg b/src/content/img/icon/photo/light.svg
new file mode 100644
index 0000000..ff7e5fb
--- /dev/null
+++ b/src/content/img/icon/photo/light.svg
@@ -0,0 +1,35 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <rect
+ x="4"
+ y="4"
+ width="16"
+ height="16"
+ rx="3"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 4 16
+ L 8.29289 11.7071
+ C 8.68342 11.3166 9.31658 11.3166 9.70711 11.7071
+ L 13 15
+ M 13 15
+ L 15.7929 12.2071
+ C 16.1834 11.8166 16.8166 11.8166 17.2071 12.2071
+ L 20 15
+ M 13 15
+ L 15.25 17.25
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/pin/light.svg b/src/content/img/icon/pin/light.svg
new file mode 100644
index 0000000..8ba078c
--- /dev/null
+++ b/src/content/img/icon/pin/light.svg
@@ -0,0 +1,57 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ d="
+ M 8.84699 5
+ H 8
+ C 7.44772 5 7 4.55228 7 4
+ C 7 3.44772 7.44772 3 8 3
+ H 10
+ H 14
+ H 16
+ C 16.5523 3 17 3.44772 17 4
+ C 17 4.55228 16.5523 5 16 5
+ H 15.153
+ L 15.8666 9.99517
+ C 16.2261 10.1989 16.5668 10.4329 16.8828 10.6962
+ C 18.2091 11.8015 19 13.3437 19 15
+ C 19 15.5523 18.5523 16 18 16
+ H 12
+ L 6 16
+ C 5.44772 16 5 15.5523 5 15
+ C 5 13.3437 5.79093 11.8015 7.11718 10.6962
+ C 7.43316 10.4329 7.77385 10.1989 8.13339 9.99517
+ L 8.84699 5
+ Z
+ M 10.8673 5
+ L 10.0406 10.7872
+ C 9.99294 11.1205 9.78085 11.4074 9.47623 11.5507
+ C 9.07954 11.7373 8.71669 11.9667 8.39754 12.2327
+ C 7.78492 12.7432 7.3704 13.3553 7.16053 14
+ L 12 14
+ H 16.8395
+ C 16.6296 13.3553 16.2151 12.7432 15.6025 12.2327
+ C 15.2833 11.9667 14.9205 11.7373 14.5238 11.5507
+ C 14.2191 11.4074 14.0071 11.1205 13.9594 10.7872
+ L 13.1327 5
+ H 10.8673
+ Z
+ "
+ fill="black"
+ />
+ <path
+ d="
+ M 12 15
+ V 20
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/remove/light.svg b/src/content/img/icon/remove/light.svg
new file mode 100644
index 0000000..8fa74e6
--- /dev/null
+++ b/src/content/img/icon/remove/light.svg
@@ -0,0 +1,13 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="M 7 12 L 17 12"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/sad/light.svg b/src/content/img/icon/sad/light.svg
new file mode 100644
index 0000000..72cece1
--- /dev/null
+++ b/src/content/img/icon/sad/light.svg
@@ -0,0 +1,48 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <g clip-path="url(#clip0_443_3604)">
+ <circle
+ cx="12"
+ cy="12"
+ r="9"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="9.5"
+ cy="9.5"
+ r="1.5"
+ fill="black"
+ />
+ <circle
+ cx="14.5"
+ cy="9.5"
+ r="1.5"
+ fill="black"
+ />
+ <path
+ d="
+ M 7.53803 15.6064
+ C 8.79314 14.5681 10.3711 14 12 14
+ C 13.6289 14 15.2069 14.5681 16.462 15.6064"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ </g>
+ <defs>
+ <clipPath id="clip0_443_3604">
+ <rect
+ width="24"
+ height="24"
+ fill="white"
+ />
+ </clipPath>
+ </defs>
+</svg>
diff --git a/src/content/img/icon/save/light.svg b/src/content/img/icon/save/light.svg
new file mode 100644
index 0000000..a83069f
--- /dev/null
+++ b/src/content/img/icon/save/light.svg
@@ -0,0 +1,57 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 4 6
+ C 4 4.89543 4.89543 4 6 4
+ H 12
+ H 14.1716
+ C 14.702 4 15.2107 4.21071 15.5858 4.58579
+ L 19.4142 8.41421
+ C 19.7893 8.78929 20 9.29799 20 9.82843
+ V 12
+ V 18
+ C 20 19.1046 19.1046 20 18 20
+ H 6
+ C 4.89543 20 4 19.1046 4 18
+ V 6
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"/>
+ <path
+ d="
+ M 8 4
+ H 13
+ V 7
+ C 13 7.55228 12.5523 8 12 8
+ H 9
+ C 8.44772 8 8 7.55228 8 7
+ V 4
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"/>
+ <path
+ d="
+ M 7 15
+ C 7 13.8954 7.89543 13 9 13
+ H 15
+ C 16.1046 13 17 13.8954 17 15
+ V 20
+ H 7
+ V 15
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"/>
+</svg>
diff --git a/src/content/img/icon/scissors/light.svg b/src/content/img/icon/scissors/light.svg
new file mode 100644
index 0000000..e344df3
--- /dev/null
+++ b/src/content/img/icon/scissors/light.svg
@@ -0,0 +1,55 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <circle
+ cx="6.5"
+ cy="6.5"
+ r="2.5"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="6.5"
+ cy="17.5"
+ r="2.5"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 6 14.9999
+ L 20 6.26758
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ d="
+ M 12.6985 11.9995
+ L 6.52936 8.15153
+ C 6.06076 7.85925 5.44394 8.00218 5.15166 8.47078
+ C 4.85937 8.93939 5.0023 9.55621 5.47091 9.84849
+ L 10.809 13.1781
+ L 12.6985 11.9995
+ Z
+ M 14.5881 13.1781
+ L 12.6985 14.3566
+ L 19.4709 18.5809
+ C 19.9395 18.8731 20.5564 18.7302 20.8486 18.2616
+ C 21.1409 17.793 20.998 17.1762 20.5294 16.8839
+ L 14.5881 13.1781
+ Z
+ "
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/search/light.svg b/src/content/img/icon/search/light.svg
new file mode 100644
index 0000000..eb13d7b
--- /dev/null
+++ b/src/content/img/icon/search/light.svg
@@ -0,0 +1,21 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <circle
+ cx="10"
+ cy="10"
+ r="6"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path d="M14.5 14.5L19 19"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/settings/light.svg b/src/content/img/icon/settings/light.svg
new file mode 100644
index 0000000..a727183
--- /dev/null
+++ b/src/content/img/icon/settings/light.svg
@@ -0,0 +1,462 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 6.07194 6.26794
+ L 6.57194 5.40192
+ L 6.07194 6.26794
+ Z
+ M 4.70592 6.63397
+ L 3.83989 6.13397
+ L 3.83989 6.13397
+ L 4.70592 6.63397
+ Z
+ M 3.70592 8.36602
+ L 2.83989 7.86602
+ H 2.83989
+ L 3.70592 8.36602
+ Z
+ M 4.07194 9.73205
+ L 3.57194 10.5981
+ H 3.57194
+ L 4.07194 9.73205
+ Z
+ M 4.07194 14.2679
+ L 3.57194 13.4019
+ H 3.57194
+ L 4.07194 14.2679
+ Z
+ M 3.70592 15.634
+ L 4.57194 15.134
+ H 4.57194
+ L 3.70592 15.634
+ Z
+ M 4.70592 17.366
+ L 3.83989 17.866
+ H 3.83989
+ L 4.70592 17.366
+ Z
+ M 6.07194 17.732
+ L 6.57194 18.5981
+ L 6.07194 17.732
+ Z
+ M 17.9284 17.732
+ L 17.4283 18.5981
+ L 17.4284 18.5981
+ L 17.9284 17.732
+ Z
+ M 19.2944 17.366
+ L 18.4284 16.866
+ L 19.2944 17.366
+ Z
+ M 20.2944 15.634
+ L 21.1604 16.134
+ L 20.2944 15.634
+ Z
+ M 19.9284 14.2679
+ L 19.4284 15.134
+ V 15.134
+ L 19.9284 14.2679
+ Z
+ M 19.9284 9.73205
+ L 20.4284 10.5981
+ V 10.5981
+ L 19.9284 9.73205
+ Z
+ M 20.2944 8.36602
+ L 19.4284 8.86602
+ L 19.4284 8.86602
+ L 20.2944 8.36602
+ Z
+ M 19.2944 6.63397
+ L 18.4284 7.13397
+ L 19.2944 6.63397
+ Z
+ M 17.9284 6.26794
+ L 18.4284 7.13397
+ L 17.9284 6.26794
+ Z
+ M 14.6514 6.61604
+ L 14.2089 7.51283
+ L 14.6514 6.61604
+ Z
+ M 16.5119 7.08573
+ L 17.0119 7.95175
+ L 16.5119 7.08573
+ Z
+ M 15.336 7.01204
+ L 14.7793 7.84277
+ L 15.336 7.01204
+ Z
+ M 17.9873 11.6035
+ L 16.9894 11.6686
+ L 17.9873 11.6035
+ Z
+ M 18.5118 10.5499
+ L 18.0118 9.68388
+ L 18.5118 10.5499
+ Z
+ M 15.336 16.988
+ L 14.7793 16.1572
+ L 15.336 16.988
+ Z
+ M 16.5119 16.9143
+ L 16.0119 17.7803
+ L 16.5119 16.9143
+ Z
+ M 18.5118 13.4501
+ L 18.0118 14.3161
+ L 18.5118 13.4501
+ Z
+ M 9.34892 17.384
+ L 9.79137 16.4872
+ L 9.34892 17.384
+ Z
+ M 7.48838 16.9143
+ L 6.98838 16.0482
+ L 7.48838 16.9143
+ Z
+ M 8.6643 16.988
+ L 8.10763 17.8187
+ L 8.6643 16.988
+ Z
+ M 14.6514 17.384
+ L 15.0938 18.2808
+ L 14.6514 17.384
+ Z
+ M 5.48852 10.5499
+ L 4.98852 11.4159
+ L 5.48852 10.5499
+ Z
+ M 6.01304 11.6035
+ L 5.01516 11.5385
+ L 6.01304 11.6035
+ Z
+ M 7.48839 7.08573
+ L 6.98839 7.95176
+ L 7.48839 7.08573
+ Z
+ M 11.0001 4
+ V 4
+ V 2
+ C 9.89558 2 9.00015 2.89543 9.00015 4
+ H 11.0001
+ Z
+ M 11.0001 5.63424
+ V 4
+ H 9.00015
+ V 5.63424
+ H 11.0001
+ Z
+ M 9.22099 7.84277
+ C 9.40312 7.72073 9.59361 7.6104 9.79137 7.51283
+ L 8.90647 5.71924
+ C 8.62922 5.85603 8.36245 6.01056 8.10764 6.18131
+ L 9.22099 7.84277
+ Z
+ M 5.57194 7.13397
+ L 6.98839 7.95176
+ L 7.98839 6.2197
+ L 6.57194 5.40192
+ L 5.57194 7.13397
+ Z
+ M 5.57194 7.13397
+ L 6.57194 5.40192
+ C 5.61536 4.84963 4.39218 5.17738 3.83989 6.13397
+ L 5.57194 7.13397
+ Z
+ M 4.57194 8.86602
+ L 5.57194 7.13397
+ L 3.83989 6.13397
+ L 2.83989 7.86602
+ L 4.57194 8.86602
+ Z
+ M 4.57194 8.86602
+ L 4.57194 8.86602
+ L 2.83989 7.86602
+ C 2.28761 8.82261 2.61536 10.0458 3.57194 10.5981
+ L 4.57194 8.86602
+ Z
+ M 5.98852 9.68388
+ L 4.57194 8.86602
+ L 3.57194 10.5981
+ L 4.98852 11.4159
+ L 5.98852 9.68388
+ Z
+ M 7.00015 12
+ C 7.00015 11.8885 7.00378 11.778 7.01092 11.6686
+ L 5.01516 11.5385
+ C 5.0052 11.6912 5.00015 11.8451 5.00015 12
+ H 7.00015
+ Z
+ M 7.01092 12.3314
+ C 7.00378 12.222 7.00015 12.1115 7.00015 12
+ H 5.00015
+ C 5.00015 12.1549 5.0052 12.3088 5.01516 12.4615
+ L 7.01092 12.3314
+ Z
+ M 4.57194 15.134
+ L 5.98852 14.3161
+ L 4.98852 12.5841
+ L 3.57194 13.4019
+ L 4.57194 15.134
+ Z
+ M 4.57194 15.134
+ L 4.57194 15.134
+ L 3.57194 13.4019
+ C 2.61536 13.9542 2.28761 15.1774 2.83989 16.134
+ L 4.57194 15.134
+ Z
+ M 5.57194 16.866
+ L 4.57194 15.134
+ L 2.83989 16.134
+ L 3.83989 17.866
+ L 5.57194 16.866
+ Z
+ M 5.57194 16.866
+ L 5.57194 16.866
+ L 3.83989 17.866
+ C 4.39218 18.8226 5.61536 19.1504 6.57194 18.5981
+ L 5.57194 16.866
+ Z
+ M 6.98838 16.0482
+ L 5.57194 16.866
+ L 6.57194 18.5981
+ L 7.98838 17.7803
+ L 6.98838 16.0482
+ Z
+ M 9.79137 16.4872
+ C 9.59361 16.3896 9.40312 16.2793 9.22098 16.1572
+ L 8.10763 17.8187
+ C 8.36245 17.9894 8.62922 18.144 8.90647 18.2808
+ L 9.79137 16.4872
+ Z
+ M 11.0001 20
+ V 18.3658
+ H 9.00015
+ V 20
+ H 11.0001
+ Z
+ M 11.0001 20
+ H 9.00015
+ C 9.00015 21.1046 9.89558 22 11.0001 22
+ V 20
+ Z
+ M 13.0001 20
+ H 11.0001
+ V 22
+ H 13.0001
+ V 20
+ Z
+ M 13.0001 20
+ V 22
+ C 14.1047 22 15.0001 21.1046 15.0001 20
+ H 13.0001
+ Z
+ M 13.0001 18.3658
+ V 20
+ H 15.0001
+ V 18.3658
+ H 13.0001
+ Z
+ M 14.7793 16.1572
+ C 14.5972 16.2793 14.4067 16.3896 14.2089 16.4872
+ L 15.0938 18.2808
+ C 15.3711 18.144 15.6378 17.9894 15.8927 17.8187
+ L 14.7793 16.1572
+ Z
+ M 18.4284 16.866
+ L 17.0119 16.0482
+ L 16.0119 17.7803
+ L 17.4283 18.5981
+ L 18.4284 16.866
+ Z
+ M 18.4284 16.866
+ H 18.4283
+ L 17.4284 18.5981
+ C 18.3849 19.1504 19.6081 18.8226 20.1604 17.866
+ L 18.4284 16.866
+ Z
+ M 19.4284 15.134
+ L 18.4284 16.866
+ L 20.1604 17.866
+ L 21.1604 16.134
+ L 19.4284 15.134
+ Z
+ M 19.4284 15.134
+ V 15.134
+ L 21.1604 16.134
+ C 21.7127 15.1774 21.3849 13.9542 20.4284 13.4019
+ L 19.4284 15.134
+ Z
+ M 18.0118 14.3161
+ L 19.4284 15.134
+ L 20.4284 13.4019
+ L 19.0118 12.5841
+ L 18.0118 14.3161
+ Z
+ M 17.0001 12
+ C 17.0001 12.1115 16.9965 12.222 16.9894 12.3314
+ L 18.9851 12.4615
+ C 18.9951 12.3088 19.0001 12.1549 19.0001 12
+ H 17.0001
+ Z
+ M 16.9894 11.6686
+ C 16.9965 11.778 17.0001 11.8885 17.0001 12
+ H 19.0001
+ C 19.0001 11.8451 18.9951 11.6912 18.9851 11.5385
+ L 16.9894 11.6686
+ Z
+ M 19.4284 8.86602
+ L 18.0118 9.68388
+ L 19.0118 11.4159
+ L 20.4284 10.5981
+ L 19.4284 8.86602
+ Z
+ M 19.4284 8.86602
+ L 19.4284 8.86602
+ L 20.4284 10.5981
+ C 21.3849 10.0458 21.7127 8.82261 21.1604 7.86602
+ L 19.4284 8.86602
+ Z
+ M 18.4284 7.13397
+ L 19.4284 8.86602
+ L 21.1604 7.86602
+ L 20.1604 6.13397
+ L 18.4284 7.13397
+ Z
+ M 18.4284 7.13397
+ V 7.13397
+ L 20.1604 6.13397
+ C 19.6081 5.17738 18.3849 4.84963 17.4284 5.40192
+ L 18.4284 7.13397
+ Z
+ M 17.0119 7.95175
+ L 18.4284 7.13397
+ L 17.4284 5.40192
+ L 16.0119 6.2197
+ L 17.0119 7.95175
+ Z
+ M 14.2089 7.51283
+ C 14.4067 7.6104 14.5972 7.72072 14.7793 7.84277
+ L 15.8927 6.18131
+ C 15.6378 6.01056 15.3711 5.85603 15.0938 5.71924
+ L 14.2089 7.51283
+ Z
+ M 13.0001 4
+ V 5.63423
+ H 15.0001
+ V 4
+ H 13.0001
+ Z
+ M 13.0001 4
+ H 15.0001
+ C 15.0001 2.89543 14.1047 2 13.0001 2
+ V 4
+ Z
+ M 11.0001 4
+ H 13.0001
+ V 2
+ H 11.0001
+ V 4
+ Z
+ M 15.0938 5.71924
+ C 15.0511 5.69815 15.0232 5.67053 15.0094 5.65025
+ C 14.9972 5.63248 15.0001 5.62788 15.0001 5.63423
+ H 13.0001
+ C 13.0001 6.50299 13.5491 7.18731 14.2089 7.51283
+ L 15.0938 5.71924
+ Z
+ M 16.0119 6.2197
+ C 16.0174 6.21655 16.0149 6.22132 15.9937 6.21972
+ C 15.9694 6.21789 15.9319 6.20762 15.8927 6.18131
+ L 14.7793 7.84277
+ C 15.3915 8.25303 16.2594 8.38623 17.0119 7.95175
+ L 16.0119 6.2197
+ Z
+ M 18.9851 11.5385
+ C 18.9821 11.4913 18.992 11.4537 19.0025 11.4318
+ C 19.0118 11.4126 19.0172 11.4128 19.0118 11.4159
+ L 18.0118 9.68388
+ C 17.2604 10.1177 16.9415 10.9342 16.9894 11.6686
+ L 18.9851 11.5385
+ Z
+ M 15.8927 17.8187
+ C 15.9319 17.7924 15.9694 17.7821 15.9937 17.7803
+ C 16.0149 17.7787 16.0174 17.7834 16.0119 17.7803
+ L 17.0119 16.0482
+ C 16.2594 15.6138 15.3915 15.747 14.7793 16.1572
+ L 15.8927 17.8187
+ Z
+ M 19.0118 12.5841
+ C 19.0172 12.5872 19.0118 12.5874 19.0025 12.5682
+ C 18.992 12.5462 18.9821 12.5087 18.9851 12.4615
+ L 16.9894 12.3314
+ C 16.9415 13.0658 17.2604 13.8823 18.0118 14.3161
+ L 19.0118 12.5841
+ Z
+ M 8.90647 18.2808
+ C 8.94923 18.3019 8.97711 18.3295 8.99094 18.3497
+ C 9.00306 18.3675 9.00015 18.3721 9.00015 18.3658
+ H 11.0001
+ C 11.0001 17.497 10.4512 16.8127 9.79137 16.4872
+ L 8.90647 18.2808
+ Z
+ M 7.98838 17.7803
+ C 7.98292 17.7834 7.98539 17.7787 8.00661 17.7803
+ C 8.03085 17.7821 8.06836 17.7924 8.10763 17.8187
+ L 9.22098 16.1572
+ C 8.60875 15.747 7.74092 15.6138 6.98838 16.0482
+ L 7.98838 17.7803
+ Z
+ M 15.0001 18.3658
+ C 15.0001 18.3721 14.9972 18.3675 15.0094 18.3497
+ C 15.0232 18.3295 15.0511 18.3019 15.0938 18.2808
+ L 14.2089 16.4872
+ C 13.5491 16.8127 13.0001 17.497 13.0001 18.3658
+ H 15.0001
+ Z
+ M 5.01516 12.4615
+ C 5.01823 12.5086 5.00833 12.5462 4.99777 12.5682
+ C 4.98851 12.5874 4.9831 12.5872 4.98852 12.5841
+ L 5.98852 14.3161
+ C 6.73991 13.8823 7.05882 13.0658 7.01092 12.3314
+ L 5.01516 12.4615
+ Z
+ M 4.98852 11.4159
+ C 4.9831 11.4128 4.98851 11.4126 4.99777 11.4318
+ C 5.00833 11.4537 5.01823 11.4913 5.01516 11.5385
+ L 7.01092 11.6686
+ C 7.05882 10.9342 6.73991 10.1177 5.98852 9.68388
+ L 4.98852 11.4159
+ Z
+ M 8.10764 6.18131
+ C 8.06837 6.20763 8.03085 6.21789 8.00662 6.21972
+ C 7.9854 6.22133 7.98293 6.21655 7.98839 6.2197
+ L 6.98839 7.95176
+ C 7.74092 8.38623 8.60876 8.25303 9.22099 7.84277
+ L 8.10764 6.18131
+ Z
+ M 9.00015 5.63424
+ C 9.00015 5.62788 9.00306 5.63248 8.99094 5.65025
+ C 8.97711 5.67053 8.94923 5.69815 8.90647 5.71924
+ L 9.79137 7.51283
+ C 10.4512 7.18731 11.0001 6.50299 11.0001 5.63424
+ H 9.00015
+ Z
+ "
+ fill="black"
+ />
+ <circle
+ cx="12"
+ cy="12"
+ r="3"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/share/light.svg b/src/content/img/icon/share/light.svg
new file mode 100644
index 0000000..83aabdf
--- /dev/null
+++ b/src/content/img/icon/share/light.svg
@@ -0,0 +1,38 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 15.2141 7.39294
+ L 8.68387 10.6581
+ M 8.68387 10.6581
+ C 8.19134 9.67492 7.17449 9 6 9
+ C 4.34315 9 3 10.3431 3 12
+ C 3 13.6569 4.34315 15 6 15
+ C 7.17449 15 8.19134 14.3251 8.68387 13.3419
+ M 8.68387 10.6581
+ C 8.88616 11.0619 9 11.5176 9 12
+ C 9 12.4824 8.88616 12.9381 8.68387 13.3419
+ M 15.2141 16.6071
+ L 8.68387 13.3419
+ M 21 6
+ C 21 7.65685 19.6569 9 18 9
+ C 16.3431 9 15 7.65685 15 6
+ C 15 4.34315 16.3431 3 18 3
+ C 19.6569 3 21 4.34315 21 6
+ Z
+ M 21 18
+ C 21 19.6569 19.6569 21 18 21
+ C 16.3431 21 15 19.6569 15 18
+ C 15 16.3431 16.3431 15 18 15
+ C 19.6569 15 21 16.3431 21 18
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/shield-bad/light.svg b/src/content/img/icon/shield-bad/light.svg
new file mode 100644
index 0000000..1ec8b64
--- /dev/null
+++ b/src/content/img/icon/shield-bad/light.svg
@@ -0,0 +1,36 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 10 9.00002
+ L 12 11
+ M 12 11
+ L 14 13
+ M 12 11
+ L 14 9.00002
+ M 12 11
+ L 10 13
+ M 11.7253 3.07852
+ L 5.72528 4.7928
+ C 5.29598 4.91546 5 5.30784 5 5.75432
+ L 5 10.8538
+ C 5 14.0834 6.55966 17.1141 9.18762 18.9912
+ L 11.4188 20.5849
+ C 11.7665 20.8332 12.2335 20.8332 12.5812 20.5849
+ L 14.8124 18.9912
+ C 17.4403 17.1141 19 14.0834 19 10.8538
+ V 5.75432
+ C 19 5.30784 18.704 4.91546 18.2747 4.7928
+ L 12.2747 3.07852
+ C 12.0952 3.02721 11.9048 3.02721 11.7253 3.07852
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/shield-good/light.svg b/src/content/img/icon/shield-good/light.svg
new file mode 100644
index 0000000..18bf29a
--- /dev/null
+++ b/src/content/img/icon/shield-good/light.svg
@@ -0,0 +1,31 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 9.34875 11.5
+ L 11.3488 13.5
+ L 15.5 9.34878
+ M 11.7253 3.07852
+ L 5.72528 4.7928
+ C 5.29598 4.91546 5 5.30784 5 5.75432
+ L 5 10.8538
+ C 5 14.0834 6.55966 17.1141 9.18762 18.9912
+ L 11.4188 20.5849
+ C 11.7665 20.8332 12.2335 20.8332 12.5812 20.5849
+ L 14.8124 18.9912
+ C 17.4403 17.1141 19 14.0834 19 10.8538
+ V 5.75432
+ C 19 5.30784 18.704 4.91546 18.2747 4.7928
+ L 12.2747 3.07852
+ C 12.0952 3.02721 11.9048 3.02721 11.7253 3.07852
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/shield-info/light.svg b/src/content/img/icon/shield-info/light.svg
new file mode 100644
index 0000000..6553c91
--- /dev/null
+++ b/src/content/img/icon/shield-info/light.svg
@@ -0,0 +1,36 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 12 11
+ V 14
+ M 11.7253 3.07852
+ L 5.72528 4.7928
+ L 5.29598 4.91546 5 5.30784 5 5.75432
+ L 5 10.8538
+ L 5 14.0834 6.55966 17.1141 9.18762 18.9912
+ L 11.4188 20.5849
+ L 11.7665 20.8332 12.2335 20.8332 12.5812 20.5849
+ L 14.8124 18.9912
+ L 17.4403 17.1141 19 14.0834 19 10.8538
+ V 5.75432
+ L 19 5.30784 18.704 4.91546 18.2747 4.7928
+ L 12.2747 3.07852
+ L 12.0952 3.02721 11.9048 3.02721 11.7253 3.07852
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="12"
+ cy="8"
+ r="1"
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/shield-off/light.svg b/src/content/img/icon/shield-off/light.svg
new file mode 100644
index 0000000..4e657b8
--- /dev/null
+++ b/src/content/img/icon/shield-off/light.svg
@@ -0,0 +1,51 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="M 3 3 L 19 19"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ fill-rule="evenodd"
+ clip-rule="evenodd"
+ d="
+ M 5.06954 3.98378
+ C 4.42172 4.324 4 5.00062 4 5.75432
+ V 10.8538
+ C 4 14.4063 5.71562 17.7401 8.60638 19.8049
+ L 10.8375 21.3986
+ C 11.5329 21.8953 12.4671 21.8953 13.1625 21.3986
+ L 15.3936 19.8049
+ C 16.4709 19.0354 17.385 18.0897 18.1079 17.0221
+ L 16.6617 15.576
+ C 16.0413 16.5828 15.2203 17.4709 14.2311 18.1774
+ L 12 19.7711
+ L 9.76886 18.1774
+ C 7.40369 16.488 6 13.7604 6 10.8538
+ V 5.75432
+ L 6.6534 5.56764
+ L 5.06954 3.98378
+ Z
+ M 17.557 13.6428
+ C 17.847 12.7533 18 11.8133 18 10.8538
+ L 18 5.75432
+ L 12 4.04004
+ L 8.85329 4.9391
+ L 7.23549 3.3213
+ L 11.4506 2.11699
+ C 11.8097 2.01439 12.1903 2.01439 12.5494 2.11699
+ L 18.5494 3.83128
+ C 19.408 4.07659 20 4.86136 20 5.75432
+ V 10.8538
+ C 20 12.3672 19.6887 13.8408 19.1078 15.1936
+ L 17.557 13.6428
+ Z
+ "
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/shopping-cart/light.svg b/src/content/img/icon/shopping-cart/light.svg
new file mode 100644
index 0000000..efb1072
--- /dev/null
+++ b/src/content/img/icon/shopping-cart/light.svg
@@ -0,0 +1,54 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 3 3
+ H 4.37144
+ C 5.31982 3 6.13781 3.66607 6.32996 4.59479
+ L 8.67004 15.9052
+ C 8.86219 16.8339 9.68018 17.5 10.6286 17.5
+ H 17.5
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 6.82422 7
+ H 19.6743
+ C 20.3386 7 20.8183 7.6359 20.6358 8.27472
+ L 19.6217 11.8242
+ C 19.2537 13.1121 18.0765 14 16.7371 14
+ H 8.27734"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="16.5"
+ cy="20.5"
+ r="0.5"
+ fill="black"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="0.5"
+ cy="0.5"
+ r="0.5"
+ transform="matrix(1, 0, 0, -1, 10, 21)"
+ fill="black"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/star-full/light.svg b/src/content/img/icon/star-full/light.svg
new file mode 100644
index 0000000..6de5029
--- /dev/null
+++ b/src/content/img/icon/star-full/light.svg
@@ -0,0 +1,36 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="black"
+>
+ <path
+ d="
+ M 11.0489 4.92705
+ C 11.3483 4.00574 12.6517 4.00574 12.9511 4.92705
+ L 14.2451 8.90983
+ C 14.379 9.32185 14.763 9.60081 15.1962 9.60081
+ H 19.3839
+ C 20.3527 9.60081 20.7554 10.8404 19.9717 11.4098
+ L 16.5838 13.8713
+ C 16.2333 14.126 16.0866 14.5773 16.2205 14.9894
+ L 17.5146 18.9721
+ C 17.8139 19.8934 16.7595 20.6596 15.9757 20.0902
+ L 12.5878 17.6287
+ C 12.2373 17.374 11.7627 17.374 11.4122 17.6287
+ L 8.02426 20.0902
+ C 7.24054 20.6596 6.18607 19.8934 6.48542 18.9721
+ L 7.7795 14.9894
+ C 7.91338 14.5773 7.76672 14.126 7.41623 13.8713
+ L 4.02827 11.4098
+ C 3.24456 10.8404 3.64734 9.60081 4.61606 9.60081
+ H 8.8038
+ C 9.23703 9.60081 9.62099 9.32185 9.75486 8.90983
+ L 11.0489 4.92705
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/star/light.svg b/src/content/img/icon/star/light.svg
new file mode 100644
index 0000000..d60f636
--- /dev/null
+++ b/src/content/img/icon/star/light.svg
@@ -0,0 +1,36 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 11.0489 4.92705
+ C 11.3483 4.00574 12.6517 4.00574 12.9511 4.92705
+ L 14.2451 8.90983
+ C 14.379 9.32185 14.763 9.60081 15.1962 9.60081
+ H 19.3839
+ C 20.3527 9.60081 20.7554 10.8404 19.9717 11.4098
+ L 16.5838 13.8713
+ C 16.2333 14.126 16.0866 14.5773 16.2205 14.9894
+ L 17.5146 18.9721
+ C 17.8139 19.8934 16.7595 20.6596 15.9757 20.0902
+ L 12.5878 17.6287
+ C 12.2373 17.374 11.7627 17.374 11.4122 17.6287
+ L 8.02426 20.0902
+ C 7.24054 20.6596 6.18607 19.8934 6.48542 18.9721
+ L 7.7795 14.9894
+ C 7.91338 14.5773 7.76672 14.126 7.41623 13.8713
+ L 4.02827 11.4098
+ C 3.24456 10.8404 3.64734 9.60081 4.61606 9.60081
+ H 8.8038
+ C 9.23703 9.60081 9.62099 9.32185 9.75486 8.90983
+ L 11.0489 4.92705
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/support/light.svg b/src/content/img/icon/support/light.svg
new file mode 100644
index 0000000..2f651fc
--- /dev/null
+++ b/src/content/img/icon/support/light.svg
@@ -0,0 +1,40 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 18 6
+ L 14.8284 9.17157
+ M 14.8284 9.17157
+ C 14.1046 8.44772 13.1046 8 12 8
+ C 10.8954 8 9.89543 8.44772 9.17157 9.17157
+ M 14.8284 9.17157
+ C 15.5523 9.89543 16 10.8954 16 12
+ C 16 13.1046 15.5523 14.1046 14.8284 14.8284
+ M 18 18
+ L 14.8284 14.8284
+ M 14.8284 14.8284
+ C 14.1046 15.5523 13.1046 16 12 16
+ C 10.8954 16 9.89543 15.5523 9.17157 14.8284
+ M 6 18
+ L 9.17157 14.8284
+ M 9.17157 14.8284
+ C 8.44772 14.1046 8 13.1046 8 12
+ C 8 10.8954 8.44772 9.89543 9.17157 9.17157
+ M 6 6
+ L 9.17157 9.17157
+ M 21 12
+ C 21 16.9706 16.9706 21 12 21
+ C 7.02944 21 3 16.9706 3 12
+ C 3 7.02944 7.02944 3 12 3
+ C 16.9706 3 21 7.02944 21 12
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/tag/light.svg b/src/content/img/icon/tag/light.svg
new file mode 100644
index 0000000..4867adc
--- /dev/null
+++ b/src/content/img/icon/tag/light.svg
@@ -0,0 +1,32 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 11.1716 3
+ H 5
+ C 3.89543 3 3 3.89543 3 5
+ V 11.1716
+ C 3 11.702 3.21071 12.2107 3.58579 12.5858
+ L 10.8787 19.8787
+ C 12.0503 21.0503 13.9497 21.0503 15.1213 19.8787
+ L 19.8787 15.1213
+ C 21.0503 13.9497 21.0503 12.0503 19.8787 10.8787
+ L 12.5858 3.58579
+ C 12.2107 3.21071 11.702 3 11.1716 3
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <circle
+ cx="7.5"
+ cy="7.5"
+ r="1.5"
+ fill="black"
+ />
+</svg>
diff --git a/src/content/img/icon/threads/light.svg b/src/content/img/icon/threads/light.svg
new file mode 100644
index 0000000..01e6383
--- /dev/null
+++ b/src/content/img/icon/threads/light.svg
@@ -0,0 +1,27 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="M 5 7 H 15"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M 5 12 H 19"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M 5 17 H 19"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/upload/light.svg b/src/content/img/icon/upload/light.svg
new file mode 100644
index 0000000..0abfd7b
--- /dev/null
+++ b/src/content/img/icon/upload/light.svg
@@ -0,0 +1,26 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 19 15
+ V 17
+ C 19 18.1046 18.1046 19 17 19
+ H 7
+ C 5.89543 19 5 18.1046 5 17
+ V 15
+ M 12 15
+ L 12 5
+ M 12 5
+ L 14 7
+ M 12 5
+ L 10 7
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/user-add/light.svg b/src/content/img/icon/user-add/light.svg
new file mode 100644
index 0000000..eaf415b
--- /dev/null
+++ b/src/content/img/icon/user-add/light.svg
@@ -0,0 +1,32 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 4 20
+ V 19
+ C 4 16.2386 6.23858 14 9 14
+ H 12.75
+ M 17.5355 13.9645
+ V 17.5
+ M 17.5355 17.5
+ V 21.0355
+ M 17.5355 17.5
+ H 21.0711
+ M 17.5355 17.5
+ H 14
+ M 15 7
+ C 15 9.20914 13.2091 11 11 11
+ C 8.79086 11 7 9.20914 7 7
+ C 7 4.79086 8.79086 3 11 3
+ C 13.2091 3 15 4.79086 15 7
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/user-check/light.svg b/src/content/img/icon/user-check/light.svg
new file mode 100644
index 0000000..91d8e1b
--- /dev/null
+++ b/src/content/img/icon/user-check/light.svg
@@ -0,0 +1,27 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 14 18
+ L 16 20
+ L 22 14
+ M 4 20
+ V 19
+ C 4 16.2386 6.23858 14 9 14
+ H 12.75
+ M 15 7
+ C 15 9.20914 13.2091 11 11 11
+ C 8.79086 11 7 9.20914 7 7
+ C 7 4.79086 8.79086 3 11 3
+ C 13.2091 3 15 4.79086 15 7
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/user-circle/light.svg b/src/content/img/icon/user-circle/light.svg
new file mode 100644
index 0000000..39a5cca
--- /dev/null
+++ b/src/content/img/icon/user-circle/light.svg
@@ -0,0 +1,32 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 16.9696 19.5047
+ C 16.7257 17.5293 15.0414 16 13 16
+ H 11
+ C 8.95858 16 7.27433 17.5293 7.03036 19.5047
+ M 16.9696 19.5047
+ C 19.3986 17.893 21 15.1335 21 12
+ C 21 7.02944 16.9706 3 12 3
+ C 7.02944 3 3 7.02944 3 12
+ C 3 15.1335 4.60137 17.893 7.03036 19.5047
+ M 16.9696 19.5047
+ C 15.5456 20.4496 13.8371 21 12 21
+ C 10.1629 21 8.45441 20.4496 7.03036 19.5047
+ M 15 10
+ C 15 11.6569 13.6569 13 12 13
+ C 10.3431 13 9 11.6569 9 10
+ C 9 8.34315 10.3431 7 12 7
+ C 13.6569 7 15 8.34315 15 10
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/user-group/light.svg b/src/content/img/icon/user-group/light.svg
new file mode 100644
index 0000000..dd713ee
--- /dev/null
+++ b/src/content/img/icon/user-group/light.svg
@@ -0,0 +1,33 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 3 19
+ V 18
+ C 3 15.7909 4.79086 14 7 14
+ H 11
+ C 13.2091 14 15 15.7909 15 18
+ V 19
+ M 15 11
+ C 16.6569 11 18 9.65685 18 8
+ C 18 6.34315 16.6569 5 15 5
+ M 21 19
+ V 18
+ C 21 15.7909 19.2091 14 17 14
+ H 16.5
+ M 12 8
+ C 12 9.65685 10.6569 11 9 11
+ C 7.34315 11 6 9.65685 6 8
+ C 6 6.34315 7.34315 5 9 5
+ C 10.6569 5 12 6.34315 12 8
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/user-remove/light.svg b/src/content/img/icon/user-remove/light.svg
new file mode 100644
index 0000000..83d91b5
--- /dev/null
+++ b/src/content/img/icon/user-remove/light.svg
@@ -0,0 +1,32 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 4 20
+ V 19
+ C 4 16.2386 6.23858 14 9 14
+ H 12.75
+ M 16 15
+ L 18.5 17.5
+ M 18.5 17.5
+ L 21 20
+ M 18.5 17.5
+ L 21 15
+ M 18.5 17.5
+ L 16 20
+ M 15 7
+ C 15 9.20914 13.2091 11 11 11
+ C 8.79086 11 7 9.20914 7 7
+ C 7 4.79086 8.79086 3 11 3
+ C 13.2091 3 15 4.79086 15 7
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/user/light.svg b/src/content/img/icon/user/light.svg
new file mode 100644
index 0000000..9f68ab9
--- /dev/null
+++ b/src/content/img/icon/user/light.svg
@@ -0,0 +1,26 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <path
+ d="
+ M 5 20
+ V 19
+ C 5 16.2386 7.23858 14 10 14
+ H 14
+ C 16.7614 14 19 16.2386 19 19
+ V 20
+ M 16 7
+ C 16 9.20914 14.2091 11 12 11
+ C 9.79086 11 8 9.20914 8 7
+ C 8 4.79086 9.79086 3 12 3
+ C 14.2091 3 16 4.79086 16 7
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+/>
+</svg>
diff --git a/src/content/img/icon/warning/light.svg b/src/content/img/icon/warning/light.svg
new file mode 100644
index 0000000..d42c8f6
--- /dev/null
+++ b/src/content/img/icon/warning/light.svg
@@ -0,0 +1,38 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <circle
+ cx="12"
+ cy="17"
+ r="1"
+ fill="black"
+ />
+ <path
+ d="
+ M 12 10
+ L 12 14
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 3.44722 18.1056
+ L 10.2111 4.57771
+ C 10.9482 3.10361 13.0518 3.10362 13.7889 4.57771
+ L 20.5528 18.1056
+ C 21.2177 19.4354 20.2507 21 18.7639 21
+ H 5.23607
+ C 3.7493 21 2.78231 19.4354 3.44722 18.1056
+ Z
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/zoom-in/light.svg b/src/content/img/icon/zoom-in/light.svg
new file mode 100644
index 0000000..b8f3022
--- /dev/null
+++ b/src/content/img/icon/zoom-in/light.svg
@@ -0,0 +1,41 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <circle
+ cx="10"
+ cy="10"
+ r="6"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 14.5 14.5
+ L 19 19
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="
+ M 8 10
+ H 10
+ M 12 10
+ H 10
+ M 10 10
+ V 8
+ M 10 10
+ V 12
+ "
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/icon/zoom-out/light.svg b/src/content/img/icon/zoom-out/light.svg
new file mode 100644
index 0000000..a5b24bb
--- /dev/null
+++ b/src/content/img/icon/zoom-out/light.svg
@@ -0,0 +1,29 @@
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+>
+ <circle
+ cx="10"
+ cy="10"
+ r="6"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M 14.5 14.5 L 19 19"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+ <path
+ d="M 8 10 H 10 H 12"
+ stroke="black"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ />
+</svg>
diff --git a/src/content/img/profile/fallback.svg b/src/content/img/profile/fallback.svg
new file mode 100644
index 0000000..9d6cf4b
--- /dev/null
+++ b/src/content/img/profile/fallback.svg
@@ -0,0 +1 @@
+FIXME
diff --git a/src/content/index.html b/src/content/index.html
index ca012d4..ea7d5cc 100644
--- a/src/content/index.html
+++ b/src/content/index.html
@@ -1,22 +1,421 @@
<!DOCTYPE html>
-<html lang="en" manifest="manifest.appcache">
+<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
- <!--
- FIXME
- - metadata
- - canonical link
- -->
<link rel="stylesheet" type="text/css" href="./style.css" />
<link rel="shortcut icon" type="image/svg+xml" href="./img/favicon.svg" />
- <title>Chat with Freedom | Papo FIXME</title>
+ <title>Papo</title>
<script type="module">
import { main } from "./papo.js";
main();
</script>
</head>
<body>
- <p id="static-loading">Loading...</p>
+ <header>
+ <search>
+ <form id="search" role="search">
+ <input type="search" name="name" spellcheck="false" placeholder="Search Papo... (Ctrl+K)" />
+ </form>
+ </search>
+ <button type="button" id="show-help" aria-label="Show the help menu for Papo">
+ <picture>
+ <source srcset="./img/icon/questionmark/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/questionmark/light.svg" alt="An outlined icon of a questiong mark inside a circle" />
+ </picture>
+ </button>
+ </header>
+ <main>
+ <section class="sidebar">
+ <section class="sidebar_server-list">
+ <nav aria-label="List of connected servers">
+ <ul>
+ <li>
+ <a href="#/0001/" aria-current="page">
+ <img src="./uploads/0001/image.png" alt="Bubble Corp" />
+ </a>
+ </li>
+ <li>
+ <a href="#/0002/" aria-current="false">
+ <img src="./uploads/0002/image.png" alt="The Runner non-profit" />
+ </a>
+ </li>
+ </ol>
+ </nav>
+ <button type="button" id="new-server" aria-label="Add new server">
+ <picture>
+ <source srcset="./img/icon/plus-sign/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/plus-sing/light.svg" alt="Plus-sign icon in simple outline, with no background" />
+ </picture>
+ </button>
+ </section>
+ <section class="main-sidebar">
+ <nav aria-label="FIXME">
+ <section id="user-menu">
+ <button type="button">
+ <h3>
+ Jane Wolf
+ </h3>
+ <picture>
+ <source srcset="./img/icon/arrow-line-down/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/arrow-line-down/light.svg" alt="An outline curve of an arrowhead pointing down" />
+ </picture>
+ </button>
+ </section>
+ <section id="unread">
+ <button type="button">
+ <picture>
+ <source srcset="./img/icon/thread-list/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/thread-list/light.svg" alt="FIXME" />
+ </picture>
+ <h3>
+ All unread
+ </h3>
+ </button>
+ <ul>
+ <li>
+ <a href="#/0001/threads">
+ <picture>
+ <source srcset="./img/icon/thread-bubble/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/thread-bubble/light.svg" alt="An icon of a small chat bubble with ellipsis points inside" />
+ </picture>
+ <span>
+ Threads
+ </span>
+ </a>
+ </li>
+ <li>
+ <a href="#/0001/mentions-and-reactions">
+ <picture>
+ <source srcset="./img/icon/mention-at-sign/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/mention-at-sign/light.svg" alt="An at-sign symbol" />
+ </picture>
+ <span>
+ Mentions & reactions
+ </span>
+ </a>
+ </li>
+ <li>
+ <a href="#/0001/show-more?">
+ <picture>
+ <source srcset="./img/icon/arrow-down/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/arrow-down/light.svg" alt="An outlined icon of a down arrow" />
+ </picture>
+ <span>
+ Show more
+ </span>
+ </a>
+ </li>
+ </ul>
+ </section>
+ <section id="channels">
+ <button>
+ <picture>
+ <source srcset="./img/icon/arrowhead-down/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/arrowhead-down/light.svg" alt="An arrowhead pointing down" />
+ </picture>
+ <h3>
+ Channels
+ </h3>
+ </button>
+ <ol>
+ <li>
+ <a id="0001" href="#/0001/channels/0001/" class="has-unread">
+ <picture aria-labe="Public channel">
+ <source srcset="./img/icon/hash-sign/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/hash-sign/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ announcements
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0002" href="#/0001/channels/0002/" class="has-unread">
+ <picture aria-label="Private channel">
+ <source srcset="./img/icon/lock/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/lock/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ secret-project
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0003" href="#/0001/channels/0003/">
+ <picture aria-labe="Public channel">
+ <source srcset="./img/icon/hash-sign/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/hash-sign/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ hiring-process
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0004" href="#/0001/channels/0004/">
+ <picture aria-label="Public channel">
+ <source srcset="./img/icon/hash-sign/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/hash-sign/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ marketing
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0005" href="#/0001/channels/0005/">
+ <picture aria-labe="Private channel">
+ <source srcset="./img/icon/lock/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/lock/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ transactions-tf
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0006" href="#/0001/channels/0006/">
+ <picture aria-label="Public channel">
+ <source srcset="./img/icon/hash-sign/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/hash-sign/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ really-random
+ </span>
+ </a>
+ </li>
+ </ol>
+ </section>
+ <section>
+ <button>
+ <picture>
+ <source srcset="./img/icon/arrowhead-down/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/arrowhead-down/light.svg" alt="An arrowhead pointing down" />
+ </picture>
+ <h3>
+ Direct messages
+ </h3>
+ </button>
+ <ol>
+ <li>
+ <a id="0007" href="#/0001/channels/00007/" class="has-unread">
+ <picture aria-label="User is online now">
+ <source srcset="./img/icon/user-online/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-online/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ devmeto
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0008" href="#/0001/channels/00008/" class="has-unread">
+ <picture aria-label="User is connected">
+ <source srcset="./img/icon/user-connected/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-connected/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ krebf5
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0016" href="#/0001/channels/00016/" class="has-unread">
+ <picture aria-label="User is offline">
+ <source srcset="./img/icon/user-offline/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-offline/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ alli-t.
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0009" href="#/0001/channels/00009/">
+ <picture aria-label="User is online now">
+ <source srcset="./img/icon/user-online/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-online/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ anna.h
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0010" href="#/0001/channels/00010/">
+ <picture aria-label="User is connected">
+ <source srcset="./img/icon/user-connected/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-connected/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ h.masters
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0011" href="#/0001/channels/00011/">
+ <picture aria-label="User is connected">
+ <source srcset="./img/icon/user-connected/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-connected/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ maxwell
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0012" href="#/0001/channels/00012/">
+ <picture aria-label="User is connected">
+ <source srcset="./img/icon/user-connected/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-connected/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ primer
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0013" href="#/0001/channels/00013/">
+ <picture aria-label="User is offline">
+ <source srcset="./img/icon/user-offline/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-offline/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ bret
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0014" href="#/0001/channels/00014/">
+ <picture aria-label="User is offline">
+ <source srcset="./img/icon/user-offline/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-offline/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ just-max
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0015" href="#/0001/channels/00015/">
+ <picture aria-label="User is offline">
+ <source srcset="./img/icon/user-offline/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/user-offline/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ vicky
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0017" href="#/0001/channels/00017/">
+ <picture aria-label="Bot is online">
+ <source srcset="./img/icon/bot-online/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/bot-online/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ notifier
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0018" href="#/0001/channels/00018/">
+ <picture aria-label="Bot is online">
+ <source srcset="./img/icon/bot-online/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/bot-online/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ papobot
+ </span>
+ </a>
+ </li>
+ <li>
+ <a id="0019" href="#/0001/channels/00019/">
+ <picture aria-label="Bot is offline">
+ <source srcset="./img/icon/bot-offline/dark.svg" media="(prefers-color-scheme: dark") />
+ <img src="./img/icon/bot-offline/light.svg" alt="FIXME - disable" />
+ </picture>
+ <span>
+ automator
+ </span>
+ </a>
+ </li>
+ <ol>
+ </section>
+ </nav>
+ </section>
+ </section>
+ <section>
+ <section>
+ <header>
+ <article>
+ <h2>
+ #announcements
+ <button type="button">
+ <picture>
+ <source srcset="./img/icon/star-empty/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/star-empty/light.svg" alt="A emptied outline of a blue star" />
+ </picture>
+ </button>
+ </h2>
+ <section>
+ <div>
+ <picture aria-label="Number of users in channel">
+ <source srcset="./img/icon/user-count/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/user-count/light.svg" alt="A hollowed outline icon of a person head and torso" />
+ </picture>
+ <span>
+ 12
+ </span>
+ </div>
+ <div>
+ <picture aria-label="Pinned items count">
+ <source srcset="./img/icon/pin/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/pin/light.svg" alt="FIXME" />
+ </picture>
+ </div>
+ <p>
+ Channel description goes here. When it is too long, I need to add some logic to add trailing ellipsis... (and on hover show the rest?)
+ </p>
+ </section>
+ </article>
+ <button type="button">
+ <picture>
+ <source srcset="./img/icon/info/dark.svg" media="(prefers-color-scheme: dark)" />
+ <img src="./img/icon/info/light.svg" alt="A circle with a letter i inside" />
+ </picture>
+ </button>
+ </header>
+ <section id="feed">
+ <article>
+ <figure>
+ <img src="./uploads/0001/users/1234.png" alt="Profile picture of user lisa>
+ <figcaption>
+ <h3>
+ lisa
+ </h3>
+ <time datetime="2000-01-01T00:00:00Z">
+ 12:33PM
+ </time>
+ </figcaption>
+ </figure>
+ <p>
+ yep, probably something that needs more work
+ </p>
+ <p>
+ we'll see how far we can go with the current solution
+ </p>
+ </article>
+ </section>
+ <form>
+ <input id="text-input" />
+ <!-- https://sirneij.github.io/slack-clone-ui/# -->
+ </form>
+ </section>
+ <aside>
+ </aside>
+ </section
+ </main>
</body>
</html>
diff --git a/src/content/papo.js b/src/content/papo.js
index 6935d55..5a68d56 100644
--- a/src/content/papo.js
+++ b/src/content/papo.js
@@ -1,15 +1,22 @@
-// import * as assert from "node:assert/strict";
-
+const f1 = x => x + 1;
+const f2 = x => x - 1;
-// assert.deepEqual({a: 1}, {a: 1});
-// console.log(123);
-// console.log({ navigator });
+const configureStorage = async ({ navigator, err }) => {
+ const persistent = await navigator.storage?.persist?.();
+ if (persistent === undefined) {
+ err(`Persistent storage is not supported.`);
+ return;
+ }
-const f1 = x => x + 1;
-const f2 = x => x - 1;
+ if (!persistent) {
+ err(`Persistent storage is not enabled.`);
+ return;
+ }
+};
-const registerServiceWorker = async ({ serviceWorkerPath, err }) => {
+const registerServiceWorker = async ({ serviceWorkerPath, navigator, err }) => {
+ // FIXME: add explanation for permission before requesting it.
try {
await navigator.serviceWorker?.register(serviceWorkerPath)
} catch (e) {
@@ -17,26 +24,19 @@ const registerServiceWorker = async ({ serviceWorkerPath, err }) => {
}
};
+
+
export const main = async ({
serviceWorkerPath = "./service-worker.js",
- out = console.log,
- err = console.warn,
+ mknavigator = () => navigator,
+ out = console.log,
+ err = console.warn,
} = {}) => {
const env = {
serviceWorkerPath,
out,
err,
+ navigator: mknavigator(),
};
- setTimeout(() => {
- fetch("index.html", {
- headers: {
- "Connection": "upgrade",
- "Content-Type": "application/json",
- },
- });
- }, 1000);
await registerServiceWorker(env);
- // out("main called");
};
-
-// <body onload="setOnline()" ononline="setOnline()" onoffline="setOnline()" >
diff --git a/src/content/style.css b/src/content/style.css
index e69de29..ab5e956 100644
--- a/src/content/style.css
+++ b/src/content/style.css
@@ -0,0 +1,43 @@
+:root {
+ --color-fg: black;
+ --color-bg: white;
+ --color-pre-bg: #eee;
+
+ --green: #1a7320;
+
+ color: var(--color-fg);
+ background-color: var(--color-bg);
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-fg: white;
+ --color-bg: black;
+ --color-pre-bg: #111;
+ }
+
+ a {
+ color: hsl(211, 100%, 60%);
+ &:visited {
+ color: hsl(242, 100%, 80%);
+ }
+ }
+}
+
+
+pre, code {
+ background-color: var(--color-pre-bg);
+ border-radius: 5px;
+ padding: 5px;
+}
+
+body {
+ font-family: sans-serif;
+ /* prevent pull to refresh */
+ overscroll-behaviour-y: contain;
+}
+
+
+.unselectable {
+ user-select: none;
+}
diff --git a/src/content/sw.js b/src/content/sw.js
index 03a09e4..51089f2 100644
--- a/src/content/sw.js
+++ b/src/content/sw.js
@@ -1,11 +1,6 @@
-const CACHE_NAME = "static-shared-assets";
+const IMG_PATHS = [];
-const FALLBACK_PATHS = {
- img: "/fallback-image-FIXME.svg",
- data: {
- static: "/fallback-data-FIXME.json",
- },
-};
+const CACHE_NAME = "static-shared-assets";
const leafValues = tree =>
Object.values(tree).map(x =>
@@ -17,65 +12,86 @@ const leafValues = tree =>
const collectLeaves = tree =>
leafValues(tree).flat(Infinity);
-const DEFAULT_INSTALL_PATHS = [
- "/",
- "index.html",
- "style.css",
- "img/favicon.svg",
- // "papo.js",
-// ].concat(collectLeaves(FALLBACK_PATHS));
-];
-
-const mkInstallHandler = ({ self, caches }) => event => {
- self.skipWaiting();
- event.waitUntil(
- caches.open(CACHE_NAME).then(
- cache => cache.addAll(DEFAULT_INSTALL_PATHS),
- ),
- );
-};
const store = async (caches, request, response) => {
const cache = await caches.open(CACHE_NAME);
await cache.put(request, response);
};
-const getPrefixIn = (paths, segments) => {
- if (paths === undefined) {
- return null;
+const matchRoute = (segments, table) => {
+ if (segments.length === 0) {
+ return table ?? null;
}
- if (segments.length === 0) {
+ const simpleMatch = matchRoute(segments.slice(1), table?.[segments[0]]);
+ if (simpleMatch !== null) {
+ return simpleMatch;
+ }
+
+ const hasGlob = table?.["*"] !== undefined;
+ if (!hasGlob) {
return null;
}
- if (typeof paths === "string") {
- return paths;
+ const keys = Object.keys(table);
+ const isTrailing = keys.length === 1 || (
+ keys.length === 2 &&
+ table[""] !== undefined
+ );
+ if (isTrailing) {
+ return table["*"][""];
+ }
+
+ return matchRoute(segments.slice(1), table["*"]);
+};
+
+const fromCache = async ({ caches }, { event: { request } }) => {
+ const cache = await caches.open(CACHE_NAME);
+ return await cache.match(request);
+}
+
+const fromNetwork = async (
+ _env,
+ { fetch, event: { request, preloadResponse } },
+) => {
+ const preloadedResponse = await preloadResponse;
+ if (preloadResponse) {
+ return preloadResponse;
}
- return getPrefixIn(paths[segments[0]], segments.slice(1));
+ return await fetch(request);
+};
+
+const networkThanCache = async (env, ctx) => {
+ const networkResponse = fromNetwork(env, ctx);
+ store(env.caches, ctx.event.request, networkResponse.clone());
+ return networkResponse;
};
-const fromCache = async (caches, fetch, { request, preloadResponse }) => {
- const cachedResponse = await caches.match(request);
+const immutableGet = async (env, ctx) => {
+ const cachedResponse = await fromCache(env, ctx);
if (cachedResponse) {
- fetch(request).then(async freshResponse =>
- store(caches, request, freshResponse));
return cachedResponse;
}
- const preloadedResponse = await preloadResponse;
- if (preloadedResponse) {
- store(caches, request, preloadeResponse.clone());
- return preloadedResponse;
- }
+ const response = fromNetwork(env, ctx);
+ store(env.caches, ctx.event.request, response);
+ return response;
+}
+const staleOK = async (env, ctx) => {
+ return Promise.any([
+ fromCache(env, ctx),
+ networkThanCache(env, ctx),
+ ]);
+};
+
+const staleOrFallback = async (env, ctx) => {
try {
- const fetchedResponse = await fetch(request);
- store(caches, request, fetchedResponse.clone());
- return fetchedResponse;
+ return await staleOK(env, ctx);
} catch (e) {
- const fallbackResponse = await maybeFallback(caches, request);
+ const fallbackRoute = ctx.strategy.match;
+ const fallbackResponse = await env.caches.match(fallbackRoute);
if (fallbackResponse) {
return fallbackResponse;
}
@@ -84,121 +100,105 @@ const fromCache = async (caches, fetch, { request, preloadResponse }) => {
}
};
-const maybeFallback = async (caches, request, paths = FALLBACK_PATHS) => {
- const url = new URL(request.url)
- const segments = url.pathname.split("/").filter(s => !!s)
- const fallbackPath = getPrefixIn(paths, segments);
-
- if (fallbackPath) {
- return await caches.match(fallbackPath);
- }
- return null;
-}
-
-const CONFIG_PATHS = {
- immutable: {
- "some": {
- "path": true,
- },
- },
- staleOK: {
- },
-};
-const PRIORITY_ORDERING = [
- "immutable",
- "staleFallback",
- "stale",
-];
-
-const pullThroughCache = (env, ctx) => {
-};
-
-/*
-// FIXME: handle base paths
- const STRATEGIES = [
+const STRATEGIES = [
{
- name: "immutable",
+ fn: immutableGet,
routes: new Set([
- "/cas",
+ "cas/*",
]),
- fn: immutable,
},
{
- name: "staleFallback",
- routes: {
- "/img/icon/": "",
- },
- fn: staleFallback,
+ fn: staleOK,
+ routes: new Set([
+ "", // FIXME: should be equivalent to "./", not "/"
+ "index.html",
+ "style.css",
+ "papo.js",
+ ...IMG_PATHS,
+ ]),
},
{
- name: "staleOnly",
+ fn: staleOrFallback,
routes: new Set([
- // FIXME: add "/"
- "/index.html": true,
- "/style.css": true,
- "/papo.js": true,
+ ["img/profile/*", "img/profile/fallback.svg"],
]),
- img: "/fallback-image-FIXME.svg",
- data: {
- static: "/fallback-data-FIXME.json",
},
- fn: staleOnly,
+ {
+ fn: fromNetwork,
+ routes: new Set([
+ "*"
+ ]),
},
-};
-*/
-
-const asSegments = pathname =>
- pathname.split("/").filter(s => !!s);
-
-const requestSegments = ({ url }) =>
- asSegments(new URL(url).pathname);
+];
-/*
- const strategyFor = (segments, paths = CONFIG_PATHS) => {
- for (const strategy of PRIORITY_ORDERING) {
- if (getPrefixIn(paths[strategy.name], segments)) {
- return strategy;
+const strategyFor = (segments, baseSegments, strategies = STRATEGIES) => {
+ const effectiveSegments = segments.slice(baseSegments.length);
+ for (const strategy of strategies) {
+ const match = matchRoute(effectiveSegments, strategy.routes);
+ if (match) {
+ return { ...strategy, match };
}
}
};
-*/
-const networkOnly = async (_env, { fetch, event }) => {
- const preloaded = await event.preloadResponse;
- if (preloaded) {
- return preloaded;
- }
+const normalizeSegments = segments =>
+ segments.concat(
+ segments.length === 1 && segments[0] === ""
+ ? []
+ : [""]
+ );
+
+const pathToSegments = path =>
+ normalizeSegments(path
+ .replace(/^\/*/, "")
+ .replace( /\/*$/, "")
+ .replace(/\/+/, "/")
+ .split("/"));
- return await fetch(event.request);
+const hasPathParams = segments =>
+ segments.some(s => s.startsWith(":"));
+
+const flatten = arr =>
+ arr.flat(Infinity);
+
+
+/// We don't use `cache.addAll()` since we can tolerate failure to add individual
+/// items, and we'd rather have a partially filled cache over an empty one.
+const populateCache = async ({ caches }, paths = DEFAULT_INSTALL_PATHS) => {
+ const cache = await caches.open(CACHE_NAME);
+ return Promise.all(paths.map(cache.add));
};
-const strategyFor = (segments, paths = CONFIG_PATHS) => {
- return networkOnly;
+/// We don't `event.waitUntil()`, so that we can be activated sooner.
+const mkInstallHandler = env => async event => {
+ self.skipWaiting();
+ populateCache(env);
};
+const mkActivateHandler = ({ self, clients }) => event =>
+ event.waitUntil(Promise.all([
+ self.registration.navigationPreload?.enable(),
+ clients.claim(),
+ ]));
+
// FIXME: noop if "Connection": "Upgrade" is in header
// if (event.request.headers.get("Connection").toLowerCase() == "upgrade");
// out([...event.request.headers.entries()]);
-const mkFetchHandler = env => (event, mkfetch = () => fetch) => {
+const mkFetchHandler = env => async (event, mkfetch = () => fetch) => {
if (event.request.method !== "GET") {
return;
}
- const segments = requestSegments(event.request);
- const strategyFn = strategyFor(segments);
- event.respondWith(strategyFn(env, {
+ const segments = pathToSegments(new URL(event.request.url).pathname);
+ const strategy = strategyFor(segments, env.baseSegments);
+ event.respondWith(strategy.fn(env, {
event,
segments,
+ strategy,
fetch: mkfetch(),
}));
};
-const mkActivateHandler = ({ self, clients }) => event =>
- event.waitUntil(Promise.all([
- clients.claim(),
- self.registration.navigationPreload?.enable(),
- ]));
-
const registerListeners = env => {
env.self.addEventListener("install", mkInstallHandler(env));
env.self.addEventListener("activate", mkActivateHandler(env));
@@ -220,3 +220,23 @@ const main = ({
out,
err,
});
+
+// handy resources for pushes:
+// https://web.dev/articles/offline-cookbook
+// https://web.dev/articles/push-notifications-overview
+// https://developer.chrome.com/blog/background-sync
+// https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/push
+// https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/background-syncs
+
+// https://web.dev/learn/forms
+
+// https://alistapart.com/article/responsive-web-design/
+
+// https://developer.chrome.com/docs/workbox/modules/workbox-background-sync
+
+// https://www.npmjs.com/package/idb
+// https://web.dev/articles/indexeddb-best-practices-app-state
+
+// https://web.dev/learn/pwa/app-design
+// https://web.dev/articles/accent-color
+// https://jakearchibald.com/2016/caching-best-practices/#max-age-on-mutable-content-is-often-the-wrong-choice
diff --git a/tests/browser-driver.js b/tests/browser-driver.js
index 529d824..aa02c07 100644
--- a/tests/browser-driver.js
+++ b/tests/browser-driver.js
@@ -38,6 +38,7 @@ const conf = {
},
};
+
const TEST_PATHS = [
"tests/papo.js",
"tests/sw.js",
diff --git a/tests/driver.html b/tests/driver.html
index e4508ec..687d704 100644
--- a/tests/driver.html
+++ b/tests/driver.html
@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" type="image/svg+xml" href="../src/content/img/favicon.svg" />
- <title>Papo | webapp tests</title>
+ <title>Papo | chat.papo.im test suite</title>
<style>
:root {
--color-fg: black;
@@ -12,15 +12,17 @@
--color-red: red;
--color-green: green;
--color-yellow: goldenrod;
+ --color-pre-bg: #eee;
}
- @media(prefers-color-scheme: dark) {
+ @media (prefers-color-scheme: dark) {
:root {
--color-fg: white;
--color-bg: black;
--color-red: orangered;
--color-green: lightgreen;
--color-yellow: yellow;
+ --color-pre-bg: #111;
}
}
@@ -42,6 +44,12 @@
.yellow {
color: var(--color-yellow);
}
+
+ pre, code {
+ background-color: var(--color-pre-bg);
+ border-radius: 5px;
+ padding: 5px;
+ }
</style>
<script type="module">
import { main } from "./browser-driver.js";
diff --git a/tests/driver.js b/tests/driver.js
index d273c5d..d3c1f7b 100644
--- a/tests/driver.js
+++ b/tests/driver.js
@@ -1,9 +1,8 @@
-const isAsync = f =>
- typeof f.then === 'function' &&
- f[Symbol.toStringTag] === 'Promise';
-
-const t = ({ colors, err, assert }) => ({
- assert,
+const t = ({ colors, err, assert: { equal, deepEqual }}) => ({
+ assert: {
+ equal,
+ deepEqual,
+ },
tap: x => {
err(`tap: ${x}\n`);
return x;
@@ -14,11 +13,7 @@ const t = ({ colors, err, assert }) => ({
test: async (msg, fn) => {
err(`${colors.yellow("testing")}: ${msg}... `);
try {
- if (isAsync(fn)) {
- await fn();
- } else {
- fn();
- }
+ await fn();
} catch (e) {
err(`${colors.red("ERR")}.\n`);
throw e;
@@ -28,7 +23,8 @@ const t = ({ colors, err, assert }) => ({
});
export const runTests = async (conf, tests) => {
+ const tFinal = t(conf);
for (const testFn of tests) {
- await testFn(t(conf));
+ await testFn(tFinal);
}
};
diff --git a/tests/node-driver.js b/tests/node-driver.js
index 3393dca..5da5526 100644
--- a/tests/node-driver.js
+++ b/tests/node-driver.js
@@ -1,50 +1,29 @@
import assert from "node:assert/strict";
import process from "node:process";
+import { runTests } from "./driver.js";
+
+const err = x => process.stderr.write(x);
+
const red = s => `\x1b[31m${s}\x1b[0m`;
const green = s => `\x1b[32m${s}\x1b[0m`;
const yellow = s => `\x1b[33m${s}\x1b[0m`;
-const isAsync = f =>
- typeof f.then === 'function' &&
- f[Symbol.toStringTag] === 'Promise';
-
-const t = {
+const conf = {
+ err,
assert,
- tap: x => {
- process.stderr.write(`tap: ${x}\n`);
- return x;
- },
- start: msg => {
- process.stderr.write(`${msg}:\n`);
+ colors: {
+ red,
+ green,
+ yellow,
},
- test: async (msg, fn) => {
- process.stderr.write(`${yellow("testing")}: ${msg}... `);
- try {
- if (isAsync(fn)) {
- await fn();
- } else {
- fn();
- }
- } catch (e) {
- process.stderr.write(`${red("ERR")}.\n}`);
- throw e;
- }
- process.stderr.write(`${green("OK")}.\n`);
- },
-};
-
-const runTests = async tests => {
- for (const testFn of tests) {
- await testFn(t);
- }
};
const main = async (path = process.argv[2]) => {
const module = await import("../" + path);
- await runTests(module.allTests);
+ await runTests(conf, module.allTests);
};
diff --git a/tests/papo.js b/tests/papo.js
index 188ca67..2a4f2e6 100644
--- a/tests/papo.js
+++ b/tests/papo.js
@@ -1,19 +1,55 @@
import {
- f1,
+ configureStorage,
} from "../src/content/papo.exported.js";
-const test_f1 = async t => {
- t.start("f1()");
- t.test("addition", () => {
- t.assert.equal(f1(1), 2);
- // t.assert.equal(f1(1), 3);
+const test_configureStorage = async t => {
+ t.start("configureStorage()");
+
+ const contents = [];
+ const err = x => contents.push(x);
+
+ const navigator = {
+ storage: {
+ persist: () => Promise.resolve(true),
+ },
+ };
+
+ const env = {
+ err,
+ navigator,
+ };
+
+
+ return
+ t.test("noop when successful", async () => {
+ console.log(1);
+ await configureStorage(env);
+ console.log(2);
+ t.assert.deepEqual(contents, []);
+ });
+
+ t.test("noop if not available", async () => {
+ delete env.navigator.storage.persist;
+ console.log(3);
+ await configureStorage(env);
+ console.log(4);
+ t.assert.deepEqual(contents, [
+ "Persistent storage is not supported",
+ ]);
+
+ delete env.navigator.storage;
+ await configureStorage(env);
+ t.assert.deepEqual(contents, [
+ "Persistent storage is not supported",
+ "Persistent storage is not supported",
+ ]);
});
};
export const allTests = [
- test_f1,
+ test_configureStorage,
];
diff --git a/tests/sw.js b/tests/sw.js
index cff37bc..25ef93e 100644
--- a/tests/sw.js
+++ b/tests/sw.js
@@ -1,10 +1,11 @@
import {
leafValues,
+ matchRoute,
} from "../src/content/sw.exported.js";
-const test_leafValues = async t => {
+const test_leafValues = t => {
t.start("leafValues()");
t.test("noop on empty object", () => {
@@ -19,8 +20,123 @@ const test_leafValues = async t => {
});
};
+const test_buildTable = t => {
+ t.start("buildTable()");
+
+ t.test("", () => {
+ });
+};
+
+const test_matchRoutes = t => {
+ t.start("matchRoutes()");
+
+ t.test("null on empty values", () => {
+ t.assert.equal(matchRoute([""], {}), null);
+
+ t.assert.equal(matchRoute(["", ""], {}), null);
+ t.assert.equal(matchRoute(["some", ""], {}), null);
+ t.assert.equal(matchRoute(["path", ""], undefined), null);
+
+ t.assert.equal(matchRoute([""], { k: "v" }), null);
+ t.assert.equal(matchRoute([""], {some:{nested:"values"}}), null);
+ });
+
+ t.test("shallow routes match returns the matched value", () => {
+ const table = {
+ boolean: { "": "values" },
+ true: { "": true },
+ false: { "": false },
+ string: { "": "a-string" },
+ number: { "": 123 },
+ };
+
+ t.assert.equal(matchRoute(["boolean", ""], table), "values");
+ t.assert.equal(matchRoute(["true", ""], table), true);
+ t.assert.equal(matchRoute(["false", ""], table), false);
+ t.assert.equal(matchRoute(["string", ""], table), "a-string");
+ t.assert.equal(matchRoute(["number", ""], table), 123);
+ });
+
+ t.test("special case for `null` provides equivalent value", () => {
+ // given that `null` us an object
+ t.assert.equal(typeof null, typeof {});
+ t.assert.equal(typeof null, "object");
+
+ // the else case of the recursion base returns a differenc null
+ // from the one in the `routes` object.
+ const table = {
+ path: {
+ "": null,
+ },
+ };
+ t.assert.equal(matchRoute(["path", ""], table), null);
+ });
+
+ t.test("we can match nested routes", () => {
+ const table = {
+ p0: {
+ p1: {
+ "": "match",
+ },
+ },
+ };
+ t.assert.equal(matchRoute(["not", "valid", ""], table), null);
+ t.assert.equal(matchRoute(["p0", ""], table), null);
+ t.assert.equal(matchRoute(["p0", "p1", ""], table), "match");
+ t.assert.equal(matchRoute([ "p1", ""], table), null);
+ });
+
+ t.test("longer routes have more priority than shorter ones", () => {
+ // FIXME
+ // /root/* => catchall
+ // /root/skip/leaf =>
+ const table = {
+ root: {
+ "": "lower",
+ "*": {
+ "": "catchall",
+ },
+ skip: {
+ leaf: {
+ "": "higher",
+ },
+ },
+ },
+ };
+ t.assert.equal(
+ matchRoute(["root", "skip", "leaf", ""], table),
+ "higher",
+ );
+ t.assert.equal(
+ matchRoute(["root", "skip", ""], table),
+ "catchall",
+ );
+ t.assert.equal(
+ matchRoute(["root", ""], table),
+ "lower",
+ );
+ });
+
+ t.test("catchall at root captures everything", () => {
+ const routes = {
+ "*": {
+ "": "all",
+ },
+ };
+ t.assert.equal(
+ matchRoute(["anything", "goes", "here", ""], routes),
+ "all",
+ );
+ t.assert.equal(matchRoute(["here", ""], routes), "all");
+ t.assert.equal(matchRoute(["here", ""], routes), "all");
+ t.assert.equal(matchRoute([""], routes), "all");
+ });
+};
+
export const allTests = [
test_leafValues,
+ test_buildTable,
+ test_matchRoutes,
];