Refactor, create service-assets
This commit is contained in:
22
crates/service/service-assets/Cargo.toml
Normal file
22
crates/service/service-assets/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "service-assets"
|
||||
version = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
libservice = { workspace = true }
|
||||
|
||||
axum = { workspace = true }
|
||||
maud = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
tower-http = { workspace = true }
|
||||
servable = { workspace = true }
|
||||
mime = { workspace = true }
|
||||
grass = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true }
|
||||
BIN
crates/service/service-assets/assets/fonts/fa/fa-brands-400.ttf
Normal file
BIN
crates/service/service-assets/assets/fonts/fa/fa-brands-400.ttf
Normal file
Binary file not shown.
Binary file not shown.
BIN
crates/service/service-assets/assets/fonts/fa/fa-regular-400.ttf
Normal file
BIN
crates/service/service-assets/assets/fonts/fa/fa-regular-400.ttf
Normal file
Binary file not shown.
Binary file not shown.
BIN
crates/service/service-assets/assets/fonts/fa/fa-solid-900.ttf
Normal file
BIN
crates/service/service-assets/assets/fonts/fa/fa-solid-900.ttf
Normal file
Binary file not shown.
BIN
crates/service/service-assets/assets/fonts/fa/fa-solid-900.woff2
Normal file
BIN
crates/service/service-assets/assets/fonts/fa/fa-solid-900.woff2
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
crates/service/service-assets/assets/icon.png
Normal file
BIN
crates/service/service-assets/assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
28
crates/service/service-assets/css/fira.scss
Normal file
28
crates/service/service-assets/css/fira.scss
Normal file
@@ -0,0 +1,28 @@
|
||||
@import "fontawesome/fontawesome";
|
||||
@import "fontawesome/brands";
|
||||
@import "fontawesome/regular";
|
||||
@import "fontawesome/solid";
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Bold.woff2") format("woff2");
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Light.woff2") format("woff2");
|
||||
font-weight: light;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Medium.woff2") format("woff2");
|
||||
font-weight: medium;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Regular.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
}
|
||||
28
crates/service/service-assets/css/fontawesome.scss
vendored
Normal file
28
crates/service/service-assets/css/fontawesome.scss
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
@import "fontawesome/fontawesome";
|
||||
@import "fontawesome/brands";
|
||||
@import "fontawesome/regular";
|
||||
@import "fontawesome/solid";
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Bold.woff2") format("woff2");
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Light.woff2") format("woff2");
|
||||
font-weight: light;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Medium.woff2") format("woff2");
|
||||
font-weight: medium;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira";
|
||||
src: url("/assets/fonts/FiraCode-Regular.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
}
|
||||
152
crates/service/service-assets/css/fontawesome/_animated.scss
vendored
Normal file
152
crates/service/service-assets/css/fontawesome/_animated.scss
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// animating icons
|
||||
// --------------------------
|
||||
|
||||
.#{$fa-css-prefix}-beat {
|
||||
animation-name: #{$fa-css-prefix}-beat;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-bounce {
|
||||
animation-name: #{$fa-css-prefix}-bounce;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(0.280, 0.840, 0.420, 1));
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-fade {
|
||||
animation-name: #{$fa-css-prefix}-fade;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-beat-fade {
|
||||
animation-name: #{$fa-css-prefix}-beat-fade;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip {
|
||||
animation-name: #{$fa-css-prefix}-flip;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-shake {
|
||||
animation-name: #{$fa-css-prefix}-shake;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-spin {
|
||||
animation-name: #{$fa-css-prefix}-spin;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 2s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-spin-reverse {
|
||||
--#{$fa-css-prefix}-animation-direction: reverse;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pulse,
|
||||
.#{$fa-css-prefix}-spin-pulse {
|
||||
animation-name: #{$fa-css-prefix}-spin;
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, steps(8));
|
||||
}
|
||||
|
||||
// if agent or operating system prefers reduced motion, disable animations
|
||||
// see: https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/
|
||||
// see: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.#{$fa-css-prefix}-beat,
|
||||
.#{$fa-css-prefix}-bounce,
|
||||
.#{$fa-css-prefix}-fade,
|
||||
.#{$fa-css-prefix}-beat-fade,
|
||||
.#{$fa-css-prefix}-flip,
|
||||
.#{$fa-css-prefix}-pulse,
|
||||
.#{$fa-css-prefix}-shake,
|
||||
.#{$fa-css-prefix}-spin,
|
||||
.#{$fa-css-prefix}-spin-pulse {
|
||||
animation-delay: -1ms;
|
||||
animation-duration: 1ms;
|
||||
animation-iteration-count: 1;
|
||||
transition-delay: 0s;
|
||||
transition-duration: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-beat {
|
||||
0%, 90% { transform: scale(1); }
|
||||
45% { transform: scale(var(--#{$fa-css-prefix}-beat-scale, 1.25)); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-bounce {
|
||||
0% { transform: scale(1,1) translateY(0); }
|
||||
10% { transform: scale(var(--#{$fa-css-prefix}-bounce-start-scale-x, 1.1),var(--#{$fa-css-prefix}-bounce-start-scale-y, 0.9)) translateY(0); }
|
||||
30% { transform: scale(var(--#{$fa-css-prefix}-bounce-jump-scale-x, 0.9),var(--#{$fa-css-prefix}-bounce-jump-scale-y, 1.1)) translateY(var(--#{$fa-css-prefix}-bounce-height, -0.5em)); }
|
||||
50% { transform: scale(var(--#{$fa-css-prefix}-bounce-land-scale-x, 1.05),var(--#{$fa-css-prefix}-bounce-land-scale-y, 0.95)) translateY(0); }
|
||||
57% { transform: scale(1,1) translateY(var(--#{$fa-css-prefix}-bounce-rebound, -0.125em)); }
|
||||
64% { transform: scale(1,1) translateY(0); }
|
||||
100% { transform: scale(1,1) translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-fade {
|
||||
50% { opacity: var(--#{$fa-css-prefix}-fade-opacity, 0.4); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--#{$fa-css-prefix}-beat-fade-opacity, 0.4);
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(var(--#{$fa-css-prefix}-beat-fade-scale, 1.125));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-flip {
|
||||
50% {
|
||||
transform: rotate3d(var(--#{$fa-css-prefix}-flip-x, 0), var(--#{$fa-css-prefix}-flip-y, 1), var(--#{$fa-css-prefix}-flip-z, 0), var(--#{$fa-css-prefix}-flip-angle, -180deg));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-shake {
|
||||
0% { transform: rotate(-15deg); }
|
||||
4% { transform: rotate(15deg); }
|
||||
8%, 24% { transform: rotate(-18deg); }
|
||||
12%, 28% { transform: rotate(18deg); }
|
||||
16% { transform: rotate(-22deg); }
|
||||
20% { transform: rotate(22deg); }
|
||||
32% { transform: rotate(-12deg); }
|
||||
36% { transform: rotate(12deg); }
|
||||
40%, 100% { transform: rotate(0deg); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
20
crates/service/service-assets/css/fontawesome/_bordered-pulled.scss
vendored
Normal file
20
crates/service/service-assets/css/fontawesome/_bordered-pulled.scss
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// bordered + pulled icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-border {
|
||||
border-color: var(--#{$fa-css-prefix}-border-color, #{$fa-border-color});
|
||||
border-radius: var(--#{$fa-css-prefix}-border-radius, #{$fa-border-radius});
|
||||
border-style: var(--#{$fa-css-prefix}-border-style, #{$fa-border-style});
|
||||
border-width: var(--#{$fa-css-prefix}-border-width, #{$fa-border-width});
|
||||
padding: var(--#{$fa-css-prefix}-border-padding, #{$fa-border-padding});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pull-left {
|
||||
float: left;
|
||||
margin-right: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pull-right {
|
||||
float: right;
|
||||
margin-left: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin});
|
||||
}
|
||||
43
crates/service/service-assets/css/fontawesome/_core.scss
vendored
Normal file
43
crates/service/service-assets/css/fontawesome/_core.scss
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// base icon class definition
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix} {
|
||||
font-family: var(--#{$fa-css-prefix}-style-family, '#{$fa-style-family}');
|
||||
font-weight: var(--#{$fa-css-prefix}-style, #{$fa-style});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix},
|
||||
.#{$fa-css-prefix}-classic,
|
||||
.#{$fa-css-prefix}-sharp,
|
||||
.fas,
|
||||
.#{$fa-css-prefix}-solid,
|
||||
.far,
|
||||
.#{$fa-css-prefix}-regular,
|
||||
.fab,
|
||||
.#{$fa-css-prefix}-brands {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: var(--#{$fa-css-prefix}-display, #{$fa-display});
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
line-height: 1;
|
||||
text-rendering: auto;
|
||||
}
|
||||
|
||||
.fas,
|
||||
.#{$fa-css-prefix}-classic,
|
||||
.#{$fa-css-prefix}-solid,
|
||||
.far,
|
||||
.#{$fa-css-prefix}-regular {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
}
|
||||
|
||||
.fab,
|
||||
.#{$fa-css-prefix}-brands {
|
||||
font-family: 'Font Awesome 6 Brands';
|
||||
}
|
||||
|
||||
|
||||
%fa-icon {
|
||||
@include fa-icon;
|
||||
}
|
||||
7
crates/service/service-assets/css/fontawesome/_fixed-width.scss
vendored
Normal file
7
crates/service/service-assets/css/fontawesome/_fixed-width.scss
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// fixed-width icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-fw {
|
||||
text-align: center;
|
||||
width: $fa-fw-width;
|
||||
}
|
||||
57
crates/service/service-assets/css/fontawesome/_functions.scss
vendored
Normal file
57
crates/service/service-assets/css/fontawesome/_functions.scss
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// functions
|
||||
// --------------------------
|
||||
|
||||
// fa-content: convenience function used to set content property
|
||||
@function fa-content($fa-var) {
|
||||
@return unquote("\"#{ $fa-var }\"");
|
||||
}
|
||||
|
||||
// fa-divide: Originally obtained from the Bootstrap https://github.com/twbs/bootstrap
|
||||
//
|
||||
// Licensed under: The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2011-2021 Twitter, Inc.
|
||||
// Copyright (c) 2011-2021 The Bootstrap Authors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
@function fa-divide($dividend, $divisor, $precision: 10) {
|
||||
$sign: if($dividend > 0 and $divisor > 0, 1, -1);
|
||||
$dividend: abs($dividend);
|
||||
$divisor: abs($divisor);
|
||||
$quotient: 0;
|
||||
$remainder: $dividend;
|
||||
@if $dividend == 0 {
|
||||
@return 0;
|
||||
}
|
||||
@if $divisor == 0 {
|
||||
@error "Cannot divide by 0";
|
||||
}
|
||||
@if $divisor == 1 {
|
||||
@return $dividend;
|
||||
}
|
||||
@while $remainder >= $divisor {
|
||||
$quotient: $quotient + 1;
|
||||
$remainder: $remainder - $divisor;
|
||||
}
|
||||
@if $remainder > 0 and $precision > 0 {
|
||||
$remainder: fa-divide($remainder * 10, $divisor, $precision - 1) * .1;
|
||||
}
|
||||
@return ($quotient + $remainder) * $sign;
|
||||
}
|
||||
10
crates/service/service-assets/css/fontawesome/_icons.scss
vendored
Normal file
10
crates/service/service-assets/css/fontawesome/_icons.scss
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// specific icon class definition
|
||||
// -------------------------
|
||||
|
||||
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
|
||||
readers do not read off random characters that represent icons */
|
||||
|
||||
@each $name, $icon in $fa-icons {
|
||||
.#{$fa-css-prefix}-#{$name}::before { content: unquote("\"#{ $icon }\""); }
|
||||
}
|
||||
|
||||
18
crates/service/service-assets/css/fontawesome/_list.scss
vendored
Normal file
18
crates/service/service-assets/css/fontawesome/_list.scss
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// icons in a list
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-ul {
|
||||
list-style-type: none;
|
||||
margin-left: var(--#{$fa-css-prefix}-li-margin, #{$fa-li-margin});
|
||||
padding-left: 0;
|
||||
|
||||
> li { position: relative; }
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-li {
|
||||
left: calc(var(--#{$fa-css-prefix}-li-width, #{$fa-li-width}) * -1);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: var(--#{$fa-css-prefix}-li-width, #{$fa-li-width});
|
||||
line-height: inherit;
|
||||
}
|
||||
72
crates/service/service-assets/css/fontawesome/_mixins.scss
vendored
Normal file
72
crates/service/service-assets/css/fontawesome/_mixins.scss
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// mixins
|
||||
// --------------------------
|
||||
|
||||
// base rendering for an icon
|
||||
@mixin fa-icon {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
// sets relative font-sizing and alignment (in _sizing)
|
||||
@mixin fa-size ($font-size) {
|
||||
font-size: fa-divide($font-size, $fa-size-scale-base) * 1em; // converts step in sizing scale into an em-based value that's relative to the scale's base
|
||||
line-height: fa-divide(1, $font-size) * 1em; // sets the line-height of the icon back to that of it's parent
|
||||
vertical-align: (fa-divide(6, $font-size) - fa-divide(3, 8)) * 1em; // vertically centers the icon taking into account the surrounding text's descender
|
||||
}
|
||||
|
||||
// only display content to screen readers
|
||||
// see: https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/
|
||||
// see: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/
|
||||
@mixin fa-sr-only() {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
// use in conjunction with .sr-only to only display content when it's focused
|
||||
@mixin fa-sr-only-focusable() {
|
||||
&:not(:focus) {
|
||||
@include fa-sr-only();
|
||||
}
|
||||
}
|
||||
|
||||
// sets a specific icon family to use alongside style + icon mixins
|
||||
|
||||
// convenience mixins for declaring pseudo-elements by CSS variable,
|
||||
// including all style-specific font properties, and both the ::before
|
||||
// and ::after elements in the duotone case.
|
||||
@mixin fa-icon-solid($fa-var) {
|
||||
@extend %fa-icon;
|
||||
@extend .fa-solid;
|
||||
|
||||
&::before {
|
||||
content: unquote("\"#{ $fa-var }\"");
|
||||
}
|
||||
}
|
||||
@mixin fa-icon-regular($fa-var) {
|
||||
@extend %fa-icon;
|
||||
@extend .fa-regular;
|
||||
|
||||
&::before {
|
||||
content: unquote("\"#{ $fa-var }\"");
|
||||
}
|
||||
}
|
||||
@mixin fa-icon-brands($fa-var) {
|
||||
@extend %fa-icon;
|
||||
@extend .fa-brands;
|
||||
|
||||
&::before {
|
||||
content: unquote("\"#{ $fa-var }\"");
|
||||
}
|
||||
}
|
||||
31
crates/service/service-assets/css/fontawesome/_rotated-flipped.scss
vendored
Normal file
31
crates/service/service-assets/css/fontawesome/_rotated-flipped.scss
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// rotating + flipping icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-rotate-90 {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-rotate-180 {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-rotate-270 {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip-horizontal {
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip-vertical {
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip-both,
|
||||
.#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical {
|
||||
transform: scale(-1, -1);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-rotate-by {
|
||||
transform: rotate(var(--#{$fa-css-prefix}-rotate-angle, 0));
|
||||
}
|
||||
14
crates/service/service-assets/css/fontawesome/_screen-reader.scss
vendored
Normal file
14
crates/service/service-assets/css/fontawesome/_screen-reader.scss
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// screen-reader utilities
|
||||
// -------------------------
|
||||
|
||||
// only display content to screen readers
|
||||
.sr-only,
|
||||
.#{$fa-css-prefix}-sr-only {
|
||||
@include fa-sr-only;
|
||||
}
|
||||
|
||||
// use in conjunction with .sr-only to only display content when it's focused
|
||||
.sr-only-focusable,
|
||||
.#{$fa-css-prefix}-sr-only-focusable {
|
||||
@include fa-sr-only-focusable;
|
||||
}
|
||||
1578
crates/service/service-assets/css/fontawesome/_shims.scss
vendored
Normal file
1578
crates/service/service-assets/css/fontawesome/_shims.scss
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
crates/service/service-assets/css/fontawesome/_sizing.scss
vendored
Normal file
16
crates/service/service-assets/css/fontawesome/_sizing.scss
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// sizing icons
|
||||
// -------------------------
|
||||
|
||||
// literal magnification scale
|
||||
@for $i from 1 through 10 {
|
||||
.#{$fa-css-prefix}-#{$i}x {
|
||||
font-size: $i * 1em;
|
||||
}
|
||||
}
|
||||
|
||||
// step-based scale (with alignment)
|
||||
@each $size, $value in $fa-sizes {
|
||||
.#{$fa-css-prefix}-#{$size} {
|
||||
@include fa-size($value);
|
||||
}
|
||||
}
|
||||
32
crates/service/service-assets/css/fontawesome/_stacked.scss
vendored
Normal file
32
crates/service/service-assets/css/fontawesome/_stacked.scss
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// stacking icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-stack {
|
||||
display: inline-block;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
position: relative;
|
||||
vertical-align: $fa-stack-vertical-align;
|
||||
width: $fa-stack-width;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-stack-1x,
|
||||
.#{$fa-css-prefix}-stack-2x {
|
||||
left: 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
z-index: var(--#{$fa-css-prefix}-stack-z-index, #{$fa-stack-z-index});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-stack-1x {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-stack-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-inverse {
|
||||
color: var(--#{$fa-css-prefix}-inverse, #{$fa-inverse});
|
||||
}
|
||||
5015
crates/service/service-assets/css/fontawesome/_variables.scss
vendored
Normal file
5015
crates/service/service-assets/css/fontawesome/_variables.scss
vendored
Normal file
File diff suppressed because it is too large
Load Diff
30
crates/service/service-assets/css/fontawesome/brands.scss
vendored
Normal file
30
crates/service/service-assets/css/fontawesome/brands.scss
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
|
||||
:root, :host {
|
||||
--#{$fa-css-prefix}-style-family-brands: 'Font Awesome 6 Brands';
|
||||
--#{$fa-css-prefix}-font-brands: normal 400 1em/1 'Font Awesome 6 Brands';
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Brands';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: $fa-font-display;
|
||||
src: url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'),
|
||||
url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.fab,
|
||||
.#{$fa-css-prefix}-brands {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@each $name, $icon in $fa-brand-icons {
|
||||
.#{$fa-css-prefix}-#{$name}:before { content: unquote("\"#{ $icon }\""); }
|
||||
}
|
||||
21
crates/service/service-assets/css/fontawesome/fontawesome.scss
vendored
Normal file
21
crates/service/service-assets/css/fontawesome/fontawesome.scss
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
// Font Awesome core compile (Web Fonts-based)
|
||||
// -------------------------
|
||||
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
@import 'mixins';
|
||||
@import 'core';
|
||||
@import 'sizing';
|
||||
@import 'fixed-width';
|
||||
@import 'list';
|
||||
@import 'bordered-pulled';
|
||||
@import 'animated';
|
||||
@import 'rotated-flipped';
|
||||
@import 'stacked';
|
||||
@import 'icons';
|
||||
@import 'screen-reader';
|
||||
26
crates/service/service-assets/css/fontawesome/regular.scss
vendored
Normal file
26
crates/service/service-assets/css/fontawesome/regular.scss
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
|
||||
:root, :host {
|
||||
--#{$fa-css-prefix}-style-family-classic: '#{ $fa-style-family }';
|
||||
--#{$fa-css-prefix}-font-regular: normal 400 1em/1 '#{ $fa-style-family }';
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: $fa-font-display;
|
||||
src: url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
|
||||
url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.far,
|
||||
.#{$fa-css-prefix}-regular {
|
||||
font-weight: 400;
|
||||
}
|
||||
26
crates/service/service-assets/css/fontawesome/solid.scss
vendored
Normal file
26
crates/service/service-assets/css/fontawesome/solid.scss
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
|
||||
:root, :host {
|
||||
--#{$fa-css-prefix}-style-family-classic: '#{ $fa-style-family }';
|
||||
--#{$fa-css-prefix}-font-solid: normal 900 1em/1 '#{ $fa-style-family }';
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: $fa-font-display;
|
||||
src: url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),
|
||||
url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.fas,
|
||||
.#{$fa-css-prefix}-solid {
|
||||
font-weight: 900;
|
||||
}
|
||||
11
crates/service/service-assets/css/fontawesome/v4-shims.scss
vendored
Normal file
11
crates/service/service-assets/css/fontawesome/v4-shims.scss
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2024 Fonticons, Inc.
|
||||
*/
|
||||
// V4 shims compile (Web Fonts-based)
|
||||
// -------------------------
|
||||
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
@import 'shims';
|
||||
55
crates/service/service-assets/src/assets/firacode.rs
Normal file
55
crates/service/service-assets/src/assets/firacode.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use servable::{ServableWithRoute, StaticAsset};
|
||||
|
||||
pub static FONT_FIRACODE_BOLD: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/FiraCode-Bold.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fira/FiraCode-Bold.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static FONT_FIRACODE_LIGHT: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/FiraCode-Light.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fira/FiraCode-Light.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static FONT_FIRACODE_MEDIUM: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/FiraCode-Medium.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fira/FiraCode-Medium.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static FONT_FIRACODE_REGULAR: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/FiraCode-Regular.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fira/FiraCode-Regular.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static FONT_FIRACODE_SEMIBOLD: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/FiraCode-SemiBold.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fira/FiraCode-SemiBold.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static FONT_FIRACODE_VF: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/FiraCode-VF.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fira/FiraCode-VF.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
68
crates/service/service-assets/src/assets/fontawesome.rs
Normal file
68
crates/service/service-assets/src/assets/fontawesome.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use std::str::FromStr;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use mime::Mime;
|
||||
use servable::{ServableWithRoute, StaticAsset};
|
||||
|
||||
pub static FONT_FA_BRANDS_WOFF2: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/fa/fa-brands-400.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fa/fa-brands-400.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static FONT_FA_REGULAR_WOFF2: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/fa/fa-regular-400.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fa/fa-regular-400.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static FONT_FA_SOLID_WOFF2: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/fonts/fa/fa-solid-900.woff2".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fa/fa-solid-900.woff2"),
|
||||
mime: mime::FONT_WOFF2,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
#[expect(clippy::unwrap_used)]
|
||||
pub static FONT_FA_BRANDS_TTF: LazyLock<ServableWithRoute<StaticAsset>> = LazyLock::new(|| {
|
||||
ServableWithRoute::new(
|
||||
|| "/fonts/fa/fa-brands-400.ttf".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fa/fa-brands-400.ttf"),
|
||||
mime: Mime::from_str("font/ttf").unwrap(),
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
#[expect(clippy::unwrap_used)]
|
||||
pub static FONT_FA_REGULAR_TTF: LazyLock<ServableWithRoute<StaticAsset>> = LazyLock::new(|| {
|
||||
ServableWithRoute::new(
|
||||
|| "/fonts/fa/fa-regular-400.ttf".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fa/fa-regular-400.ttf"),
|
||||
mime: Mime::from_str("font/ttf").unwrap(),
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
#[expect(clippy::unwrap_used)]
|
||||
pub static FONT_FA_SOLID_TTF: LazyLock<ServableWithRoute<StaticAsset>> = LazyLock::new(|| {
|
||||
ServableWithRoute::new(
|
||||
|| "/fonts/fa/fa-solid-900.ttf".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/fonts/fa/fa-solid-900.ttf"),
|
||||
mime: Mime::from_str("font/ttf").unwrap(),
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
)
|
||||
});
|
||||
44
crates/service/service-assets/src/assets/mod.rs
Normal file
44
crates/service/service-assets/src/assets/mod.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
use servable::{CACHE_BUST_STR, ServableWithRoute, StaticAsset};
|
||||
|
||||
mod firacode;
|
||||
pub use firacode::*;
|
||||
|
||||
mod fontawesome;
|
||||
pub use fontawesome::*;
|
||||
|
||||
pub static HTMX: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/htmx-2.0.8.js".into(),
|
||||
servable::HTMX_2_0_8.with_ttl(None),
|
||||
);
|
||||
|
||||
pub static HTMX_JSON: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/htmx-json-1.19.12.js".into(),
|
||||
servable::EXT_JSON_1_19_12,
|
||||
);
|
||||
|
||||
pub static IMG_ICON: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| "/img/icon.png".into(),
|
||||
StaticAsset {
|
||||
bytes: include_bytes!("../../assets/icon.png"),
|
||||
mime: mime::IMAGE_PNG,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static CSS_FIRA: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| format!("/css/{}/fira.css", *CACHE_BUST_STR),
|
||||
StaticAsset {
|
||||
bytes: grass::include!("crates/service/service-assets/css/fira.scss").as_bytes(),
|
||||
mime: mime::TEXT_CSS,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
|
||||
pub static CSS_FONTAWESOME: ServableWithRoute<StaticAsset> = ServableWithRoute::new(
|
||||
|| format!("/css/{}/fontawesome.css", *CACHE_BUST_STR),
|
||||
StaticAsset {
|
||||
bytes: grass::include!("crates/service/service-assets/css/fontawesome.scss").as_bytes(),
|
||||
mime: mime::TEXT_CSS,
|
||||
ttl: StaticAsset::DEFAULT_TTL,
|
||||
},
|
||||
);
|
||||
57
crates/service/service-assets/src/components/fa.rs
Normal file
57
crates/service/service-assets/src/components/fa.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use maud::{Markup, Render, html};
|
||||
use strum::{Display, EnumString};
|
||||
|
||||
#[derive(Debug, Clone, Copy, EnumString, Display)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum FAIcon {
|
||||
Github,
|
||||
Git,
|
||||
Python,
|
||||
Rust,
|
||||
Discord,
|
||||
Instagram,
|
||||
|
||||
Link,
|
||||
Envelope,
|
||||
At,
|
||||
Key,
|
||||
SStar,
|
||||
RStar,
|
||||
Leaf,
|
||||
|
||||
Lock,
|
||||
Fire,
|
||||
Pen,
|
||||
Pencil,
|
||||
}
|
||||
|
||||
impl Render for FAIcon {
|
||||
fn render(&self) -> Markup {
|
||||
let classes = match self {
|
||||
Self::Github => "fa-brands fa-github",
|
||||
Self::Git => "fa-brands fa-git-alt",
|
||||
Self::Python => "fa-brands fa-python",
|
||||
Self::Rust => "fa-brands fa-rust",
|
||||
Self::Discord => "fa-brands fa-discord",
|
||||
Self::Instagram => "fa-brands fa-instagram",
|
||||
Self::Link => "fa-solid fa-link",
|
||||
Self::Envelope => "fa-solid fa-envelope",
|
||||
Self::At => "fa-solid fa-at",
|
||||
Self::Key => "fa-solid fa-key",
|
||||
Self::SStar => "fa-solid fa-star",
|
||||
Self::RStar => "fa-regular fa-star",
|
||||
Self::Leaf => "fa-regular fa-leaf",
|
||||
Self::Lock => "fa-solid fa-lock",
|
||||
Self::Fire => "fa-solid fa-fire",
|
||||
Self::Pen => "fa-solid fa-pen-nib",
|
||||
Self::Pencil => "fa-solid fa-pencil",
|
||||
};
|
||||
|
||||
html!(
|
||||
i
|
||||
class=(classes)
|
||||
style="margin-right:5pt" // TODO: configure, color
|
||||
{}
|
||||
)
|
||||
}
|
||||
}
|
||||
17
crates/service/service-assets/src/components/misc.rs
Normal file
17
crates/service/service-assets/src/components/misc.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use maud::{Markup, Render, html};
|
||||
|
||||
/// Shorthand for an `<a>` link that opens a new tab
|
||||
/// Values are (url, text)
|
||||
pub struct FarLink<'a, T: Render>(pub &'a str, pub T);
|
||||
|
||||
impl<T: Render> Render for FarLink<'_, T> {
|
||||
fn render(&self) -> Markup {
|
||||
html!(
|
||||
a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href=(self.0)
|
||||
{ (self.1) }
|
||||
)
|
||||
}
|
||||
}
|
||||
20
crates/service/service-assets/src/components/mod.rs
Normal file
20
crates/service/service-assets/src/components/mod.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
pub mod fa;
|
||||
pub mod misc;
|
||||
|
||||
pub const LAZY_IMAGE_JS: &str = "
|
||||
window.onload = function() {
|
||||
var imgs = document.querySelectorAll('.img-placeholder');
|
||||
|
||||
imgs.forEach(img => {
|
||||
img.style.border = 'none';
|
||||
img.style.filter = 'blur(10px)';
|
||||
img.style.transition = 'filter 0.3s';
|
||||
|
||||
var lg = new Image();
|
||||
lg.src = img.dataset.large;
|
||||
lg.onload = function () {
|
||||
img.src = img.dataset.large;
|
||||
img.style.filter = 'blur(0px)';
|
||||
};
|
||||
})
|
||||
}";
|
||||
71
crates/service/service-assets/src/lib.rs
Normal file
71
crates/service/service-assets/src/lib.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use axum::Router;
|
||||
use libservice::ToService;
|
||||
use servable::ServableRouter;
|
||||
use tower_http::compression::{CompressionLayer, DefaultPredicate};
|
||||
|
||||
pub mod assets;
|
||||
pub mod components;
|
||||
|
||||
pub struct AssetService {}
|
||||
|
||||
impl AssetService {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToService for AssetService {
|
||||
#[inline]
|
||||
fn make_router(&self) -> Option<Router<()>> {
|
||||
use assets::*;
|
||||
let router = ServableRouter::new()
|
||||
.add_page_with_route(&HTMX)
|
||||
.add_page_with_route(&HTMX_JSON)
|
||||
.add_page_with_route(&IMG_ICON)
|
||||
// fira
|
||||
.add_page_with_route(&CSS_FIRA)
|
||||
.add_page_with_route(&FONT_FIRACODE_BOLD)
|
||||
.add_page_with_route(&FONT_FIRACODE_LIGHT)
|
||||
.add_page_with_route(&FONT_FIRACODE_MEDIUM)
|
||||
.add_page_with_route(&FONT_FIRACODE_REGULAR)
|
||||
.add_page_with_route(&FONT_FIRACODE_SEMIBOLD)
|
||||
.add_page_with_route(&FONT_FIRACODE_VF)
|
||||
// fa
|
||||
.add_page_with_route(&CSS_FONTAWESOME)
|
||||
.add_page_with_route(&FONT_FA_BRANDS_WOFF2)
|
||||
.add_page_with_route(&FONT_FA_REGULAR_WOFF2)
|
||||
.add_page_with_route(&FONT_FA_SOLID_WOFF2)
|
||||
.add_page_with_route(&*FONT_FA_BRANDS_TTF)
|
||||
.add_page_with_route(&*FONT_FA_REGULAR_TTF)
|
||||
.add_page_with_route(&*FONT_FA_SOLID_TTF)
|
||||
.into_router();
|
||||
|
||||
let compression: CompressionLayer = CompressionLayer::new()
|
||||
.br(true)
|
||||
.deflate(true)
|
||||
.gzip(true)
|
||||
.zstd(true)
|
||||
.compress_when(DefaultPredicate::new());
|
||||
|
||||
Some(router.layer(compression))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn service_name(&self) -> Option<String> {
|
||||
Some("assets".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[expect(clippy::unwrap_used)]
|
||||
fn server_builds_without_panic() {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let router = AssetService {}.make_router();
|
||||
assert!(router.is_some())
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user