mirror of
https://github.com/thiloho/archtika.git
synced 2025-11-22 02:41:35 +01:00
Share styles and update props
This commit is contained in:
@@ -56,8 +56,6 @@
|
|||||||
program = "${pkgs.writeShellScriptBin "api-setup" ''
|
program = "${pkgs.writeShellScriptBin "api-setup" ''
|
||||||
${pkgs.postgresql_16}/bin/psql postgres://postgres@localhost:15432/archtika -c "ALTER DATABASE archtika SET \"app.jwt_secret\" TO 'a42kVyAhTImYxZeebZkApoAZLmf0VtDA'"
|
${pkgs.postgresql_16}/bin/psql postgres://postgres@localhost:15432/archtika -c "ALTER DATABASE archtika SET \"app.jwt_secret\" TO 'a42kVyAhTImYxZeebZkApoAZLmf0VtDA'"
|
||||||
|
|
||||||
echo "OUT PATH: ${self.outPath}"
|
|
||||||
|
|
||||||
${pkgs.dbmate}/bin/dbmate --url postgres://postgres@localhost:15432/archtika?sslmode=disable --migrations-dir ${self.outPath}/rest-api/db/migrations up
|
${pkgs.dbmate}/bin/dbmate --url postgres://postgres@localhost:15432/archtika?sslmode=disable --migrations-dir ${self.outPath}/rest-api/db/migrations up
|
||||||
|
|
||||||
PGRST_DB_SCHEMAS="api" PGRST_DB_ANON_ROLE="anon" PGRST_OPENAPI_MODE="ignore-privileges" PGRST_DB_URI="postgres://authenticator@localhost:15432/archtika" PGRST_JWT_SECRET="a42kVyAhTImYxZeebZkApoAZLmf0VtDA" ${pkgs.postgrest}/bin/postgrest
|
PGRST_DB_SCHEMAS="api" PGRST_DB_ANON_ROLE="anon" PGRST_OPENAPI_MODE="ignore-privileges" PGRST_DB_URI="postgres://authenticator@localhost:15432/archtika" PGRST_JWT_SECRET="a42kVyAhTImYxZeebZkApoAZLmf0VtDA" ${pkgs.postgrest}/bin/postgrest
|
||||||
|
|||||||
@@ -1,93 +1,3 @@
|
|||||||
:root {
|
|
||||||
--bg-primary: white;
|
|
||||||
--bg-secondary: hsl(0 0% 95%);
|
|
||||||
--bg-tertiary: hsl(0 0% 90%);
|
|
||||||
|
|
||||||
--color-text: black;
|
|
||||||
--color-text-invert: white;
|
|
||||||
--color-accent: hsl(210, 100%, 30%);
|
|
||||||
--color-success: hsl(105, 100%, 30%);
|
|
||||||
--color-error: hsl(0, 100%, 30%);
|
|
||||||
|
|
||||||
--border-primary: 0.0625rem solid var(--bg-tertiary);
|
|
||||||
--border-radius: 0.125rem;
|
|
||||||
|
|
||||||
/* Step -1: 14.9953px → 14.2222px */
|
|
||||||
--font-size--1: clamp(0.8889rem, 0.9592rem + -0.1098cqi, 0.9372rem);
|
|
||||||
/* Step 0: 16px → 16px */
|
|
||||||
--font-size-0: clamp(1rem, 1rem + 0cqi, 1rem);
|
|
||||||
/* Step 1: 17.072px → 18px */
|
|
||||||
--font-size-1: clamp(1.067rem, 1.0406rem + 0.1318cqi, 1.125rem);
|
|
||||||
/* Step 2: 18.2158px → 20.25px */
|
|
||||||
--font-size-2: clamp(1.1385rem, 1.0807rem + 0.2889cqi, 1.2656rem);
|
|
||||||
/* Step 3: 19.4363px → 22.7813px */
|
|
||||||
--font-size-3: clamp(1.2148rem, 1.1197rem + 0.4751cqi, 1.4238rem);
|
|
||||||
/* Step 4: 20.7385px → 25.6289px */
|
|
||||||
--font-size-4: clamp(1.2962rem, 1.1572rem + 0.6947cqi, 1.6018rem);
|
|
||||||
/* Step 5: 22.128px → 28.8325px */
|
|
||||||
--font-size-5: clamp(1.383rem, 1.1925rem + 0.9523cqi, 1.802rem);
|
|
||||||
|
|
||||||
/* Space 3xs: 4px → 5px */
|
|
||||||
--space-3xs: clamp(0.25rem, 0.2336rem + 0.0822cqi, 0.3125rem);
|
|
||||||
/* Space 2xs: 8px → 10px */
|
|
||||||
--space-2xs: clamp(0.5rem, 0.4671rem + 0.1645cqi, 0.625rem);
|
|
||||||
/* Space xs: 12px → 15px */
|
|
||||||
--space-xs: clamp(0.75rem, 0.7007rem + 0.2467cqi, 0.9375rem);
|
|
||||||
/* Space s: 16px → 20px */
|
|
||||||
--space-s: clamp(1rem, 0.9342rem + 0.3289cqi, 1.25rem);
|
|
||||||
/* Space m: 24px → 30px */
|
|
||||||
--space-m: clamp(1.5rem, 1.4013rem + 0.4934cqi, 1.875rem);
|
|
||||||
/* Space l: 32px → 40px */
|
|
||||||
--space-l: clamp(2rem, 1.8684rem + 0.6579cqi, 2.5rem);
|
|
||||||
/* Space xl: 48px → 60px */
|
|
||||||
--space-xl: clamp(3rem, 2.8026rem + 0.9868cqi, 3.75rem);
|
|
||||||
/* Space 2xl: 64px → 80px */
|
|
||||||
--space-2xl: clamp(4rem, 3.7368rem + 1.3158cqi, 5rem);
|
|
||||||
/* Space 3xl: 96px → 120px */
|
|
||||||
--space-3xl: clamp(6rem, 5.6053rem + 1.9737cqi, 7.5rem);
|
|
||||||
|
|
||||||
color-scheme: light;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--bg-primary: hsl(0 0% 15%);
|
|
||||||
--bg-secondary: hsl(0 0% 20%);
|
|
||||||
--bg-tertiary: hsl(0 0% 25%);
|
|
||||||
|
|
||||||
--color-text: white;
|
|
||||||
--color-text-invert: black;
|
|
||||||
--color-accent: hsl(210, 100%, 80%);
|
|
||||||
--color-success: hsl(105, 100%, 80%);
|
|
||||||
--color-error: hsl(0, 100%, 80%);
|
|
||||||
|
|
||||||
color-scheme: dark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
line-height: 1.5;
|
|
||||||
font-family: system-ui, sans-serif;
|
|
||||||
background-color: var(--bg-primary);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-block-size: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--space-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
section + section {
|
section + section {
|
||||||
margin-block-start: var(--space-l);
|
margin-block-start: var(--space-l);
|
||||||
}
|
}
|
||||||
@@ -135,10 +45,6 @@ input[type="color"] {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
a[role="button"] {
|
a[role="button"] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-inline-size: fit-content;
|
max-inline-size: fit-content;
|
||||||
@@ -149,10 +55,6 @@ summary {
|
|||||||
max-inline-size: fit-content;
|
max-inline-size: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
details[open] summary {
|
|
||||||
margin-block-end: var(--space-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
button,
|
||||||
a[role="button"],
|
a[role="button"],
|
||||||
label[for="toggle-mobile-preview"],
|
label[for="toggle-mobile-preview"],
|
||||||
@@ -170,48 +72,11 @@ summary {
|
|||||||
outline-offset: 0.25rem;
|
outline-offset: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
img,
|
|
||||||
picture,
|
|
||||||
svg,
|
|
||||||
video {
|
|
||||||
max-inline-size: 100%;
|
|
||||||
block-size: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
p,
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: var(--font-size-0);
|
|
||||||
}
|
|
||||||
h5 {
|
|
||||||
font-size: var(--font-size-1);
|
|
||||||
}
|
|
||||||
h4 {
|
|
||||||
font-size: var(--font-size-2);
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
font-size: var(--font-size-3);
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
font-size: var(--font-size-4);
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: var(--font-size-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -4,22 +4,6 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.svg" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
media="(prefers-color-scheme: light)"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
|
||||||
integrity="sha512-0aPQyyeZrWj9sCA46UlmWgKOP0mUipLQ6OZXu8l4IcAmD2u31EPEy9VcIMvl7SoAaKe8bLXZhYoMaE/in+gcgA=="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
media="(prefers-color-scheme: dark)"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
|
||||||
integrity="sha512-rO+olRTkcf304DQBxSWxln8JXCzTHlKnIdnMUwYvQa9/Jd4cQaNkItIUj6Z4nvW1dqK0SKXLbn9h4KwZTNtAyw=="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
/>
|
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover">
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
const { date } = $props<{ date: string }>();
|
const { date }: { date: string } = $props();
|
||||||
|
|
||||||
const options: Intl.DateTimeFormatOptions = {
|
const options: Intl.DateTimeFormatOptions = {
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Snippet } from "svelte";
|
import type { Snippet } from "svelte";
|
||||||
|
|
||||||
const { children, id, text } = $props<{ children: Snippet; id: string; text: string }>();
|
const { children, id, text }: { children: Snippet; id: string; text: string } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a href={`#${id}`} role="button">{text}</a>
|
<a href={`#${id}`} role="button">{text}</a>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
const { success, message } = $props<{
|
const { success, message }: { success: boolean | undefined; message: string | undefined } =
|
||||||
success: boolean | undefined;
|
$props();
|
||||||
message: string;
|
|
||||||
}>();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if success}
|
{#if success}
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
fullPreview = false,
|
fullPreview = false,
|
||||||
previewContent,
|
previewContent,
|
||||||
previewScrollTop = 0
|
previewScrollTop = 0
|
||||||
} = $props<{
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
children: Snippet;
|
children: Snippet;
|
||||||
fullPreview?: boolean;
|
fullPreview?: boolean;
|
||||||
previewContent: string;
|
previewContent: string;
|
||||||
previewScrollTop?: number;
|
previewScrollTop?: number;
|
||||||
}>();
|
} = $props();
|
||||||
|
|
||||||
let previewElement: HTMLDivElement;
|
let previewElement: HTMLDivElement;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
const { title, logoType, logo, mainContent, coverImage, publicationDate, footerAdditionalText } =
|
import BlogHead from "./common/BlogHead.svelte";
|
||||||
$props<{
|
import BlogNav from "./common/BlogNav.svelte";
|
||||||
|
import BlogFooter from "./common/BlogFooter.svelte";
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
logoType,
|
||||||
|
logo,
|
||||||
|
mainContent,
|
||||||
|
coverImage,
|
||||||
|
publicationDate,
|
||||||
|
footerAdditionalText
|
||||||
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
logoType: "text" | "image";
|
logoType: "text" | "image";
|
||||||
logo: string;
|
logo: string;
|
||||||
@@ -8,47 +19,12 @@
|
|||||||
coverImage: string;
|
coverImage: string;
|
||||||
publicationDate: string;
|
publicationDate: string;
|
||||||
footerAdditionalText: string;
|
footerAdditionalText: string;
|
||||||
}>();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<BlogHead {title} nestingLevel={1} />
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
media="(prefers-color-scheme: light)"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
|
||||||
integrity="sha512-0aPQyyeZrWj9sCA46UlmWgKOP0mUipLQ6OZXu8l4IcAmD2u31EPEy9VcIMvl7SoAaKe8bLXZhYoMaE/in+gcgA=="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
media="(prefers-color-scheme: dark)"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
|
||||||
integrity="sha512-rO+olRTkcf304DQBxSWxln8JXCzTHlKnIdnMUwYvQa9/Jd4cQaNkItIUj6Z4nvW1dqK0SKXLbn9h4KwZTNtAyw=="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
/>
|
|
||||||
<title>{title}</title>
|
|
||||||
<link rel="stylesheet" href="../styles.css" />
|
|
||||||
</head>
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
<nav>
|
<BlogNav {logoType} {logo} />
|
||||||
<div class="container">
|
|
||||||
<a href="../">
|
|
||||||
{#if logoType === "text"}
|
|
||||||
<p>
|
|
||||||
<strong>{logo}</strong>
|
|
||||||
</p>
|
|
||||||
{:else}
|
|
||||||
<img src={logo} alt="" />
|
|
||||||
{/if}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -62,14 +38,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
{#if mainContent}
|
||||||
|
<main>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{@html mainContent}
|
{@html mainContent}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<footer>
|
<BlogFooter text={footerAdditionalText} />
|
||||||
<div class="container">
|
|
||||||
{footerAdditionalText}
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|||||||
@@ -1,52 +1,28 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
const { title, logoType, logo, mainContent, articles, footerAdditionalText } = $props<{
|
import BlogHead from "./common/BlogHead.svelte";
|
||||||
|
import BlogNav from "./common/BlogNav.svelte";
|
||||||
|
import BlogFooter from "./common/BlogFooter.svelte";
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
logoType,
|
||||||
|
logo,
|
||||||
|
mainContent,
|
||||||
|
articles,
|
||||||
|
footerAdditionalText
|
||||||
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
logoType: "text" | "image";
|
logoType: "text" | "image";
|
||||||
logo: string;
|
logo: string;
|
||||||
mainContent: string;
|
mainContent: string;
|
||||||
articles: any[];
|
articles: { title: string; publication_date: string; meta_description: string }[];
|
||||||
footerAdditionalText: string;
|
footerAdditionalText: string;
|
||||||
}>();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<BlogHead {title} />
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
media="(prefers-color-scheme: light)"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
|
||||||
integrity="sha512-0aPQyyeZrWj9sCA46UlmWgKOP0mUipLQ6OZXu8l4IcAmD2u31EPEy9VcIMvl7SoAaKe8bLXZhYoMaE/in+gcgA=="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
media="(prefers-color-scheme: dark)"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
|
||||||
integrity="sha512-rO+olRTkcf304DQBxSWxln8JXCzTHlKnIdnMUwYvQa9/Jd4cQaNkItIUj6Z4nvW1dqK0SKXLbn9h4KwZTNtAyw=="
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
/>
|
|
||||||
<title>{title}</title>
|
|
||||||
<link rel="stylesheet" href="./styles.css" />
|
|
||||||
</head>
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
<nav>
|
<BlogNav {logoType} {logo} />
|
||||||
<div class="container">
|
|
||||||
<a href="../">
|
|
||||||
{#if logoType === "text"}
|
|
||||||
<p>
|
|
||||||
<strong>{logo}</strong>
|
|
||||||
</p>
|
|
||||||
{:else}
|
|
||||||
<img src={logo} alt="" />
|
|
||||||
{/if}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -66,9 +42,11 @@
|
|||||||
{@const articleFileName = article.title.toLowerCase().split(" ").join("-")}
|
{@const articleFileName = article.title.toLowerCase().split(" ").join("-")}
|
||||||
<li>
|
<li>
|
||||||
<p>{article.publication_date}</p>
|
<p>{article.publication_date}</p>
|
||||||
<h3>
|
<p>
|
||||||
|
<strong>
|
||||||
<a href="./articles/{articleFileName}.html">{article.title}</a>
|
<a href="./articles/{articleFileName}.html">{article.title}</a>
|
||||||
</h3>
|
</strong>
|
||||||
|
</p>
|
||||||
{#if article.meta_description}
|
{#if article.meta_description}
|
||||||
<p>{article.meta_description}</p>
|
<p>{article.meta_description}</p>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -80,8 +58,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<BlogFooter text={footerAdditionalText} />
|
||||||
<div class="container">
|
|
||||||
{footerAdditionalText}
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|||||||
11
web-app/src/lib/templates/blog/common/BlogFooter.svelte
Normal file
11
web-app/src/lib/templates/blog/common/BlogFooter.svelte
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
const { text }: { text: string } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="container">
|
||||||
|
<small>
|
||||||
|
{text}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
12
web-app/src/lib/templates/blog/common/BlogHead.svelte
Normal file
12
web-app/src/lib/templates/blog/common/BlogHead.svelte
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
const { title, nestingLevel = 0 }: { title: string; nestingLevel?: number } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>{title}</title>
|
||||||
|
<link rel="stylesheet" href={`${"../".repeat(nestingLevel)}styles.css`} />
|
||||||
|
</head>
|
||||||
|
</svelte:head>
|
||||||
17
web-app/src/lib/templates/blog/common/BlogNav.svelte
Normal file
17
web-app/src/lib/templates/blog/common/BlogNav.svelte
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
const { logoType, logo }: { logoType: "text" | "image"; logo: string } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<div class="container">
|
||||||
|
<a href="../">
|
||||||
|
{#if logoType === "text"}
|
||||||
|
<p>
|
||||||
|
<strong>{logo}</strong>
|
||||||
|
</p>
|
||||||
|
{:else}
|
||||||
|
<img src={logo} alt="" />
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
const { title, logoType, logo, mainContent, coverImage, publicationDate, footerAdditionalText } =
|
const {
|
||||||
$props<{
|
title,
|
||||||
|
logoType,
|
||||||
|
logo,
|
||||||
|
mainContent,
|
||||||
|
coverImage,
|
||||||
|
publicationDate,
|
||||||
|
footerAdditionalText
|
||||||
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
logoType: "text" | "image";
|
logoType: "text" | "image";
|
||||||
logo: string;
|
logo: string;
|
||||||
@@ -8,7 +15,7 @@
|
|||||||
coverImage: string;
|
coverImage: string;
|
||||||
publicationDate: string;
|
publicationDate: string;
|
||||||
footerAdditionalText: string;
|
footerAdditionalText: string;
|
||||||
}>();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
const { title, logoType, logo, mainContent, articles, footerAdditionalText } = $props<{
|
const {
|
||||||
|
title,
|
||||||
|
logoType,
|
||||||
|
logo,
|
||||||
|
mainContent,
|
||||||
|
articles,
|
||||||
|
footerAdditionalText
|
||||||
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
logoType: "text" | "image";
|
logoType: "text" | "image";
|
||||||
logo: string;
|
logo: string;
|
||||||
mainContent: string;
|
mainContent: string;
|
||||||
articles: any[];
|
articles: { title: string; publication_date: string; meta_description: string }[];
|
||||||
footerAdditionalText: string;
|
footerAdditionalText: string;
|
||||||
}>();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import markdownit from "markdown-it";
|
import markdownit from "markdown-it";
|
||||||
import hljs from "highlight.js";
|
import hljs from "highlight.js";
|
||||||
import type { StateCore } from "markdown-it/index.js";
|
import type { StateCore } from "markdown-it/index.js";
|
||||||
import { dev } from "$app/environment";
|
|
||||||
|
|
||||||
export const sortOptions = [
|
export const sortOptions = [
|
||||||
{ value: "creation-time", text: "Creation time" },
|
{ value: "creation-time", text: "Creation time" },
|
||||||
@@ -117,7 +116,7 @@ export const handleImagePaste = async (event: ClipboardEvent, API_BASE_PREFIX: s
|
|||||||
const clipboardItems = Array.from(event.clipboardData?.items || []);
|
const clipboardItems = Array.from(event.clipboardData?.items || []);
|
||||||
const file = clipboardItems.find((item) => item.type.startsWith("image/"));
|
const file = clipboardItems.find((item) => item.type.startsWith("image/"));
|
||||||
|
|
||||||
if (!file) return;
|
if (!file) return null;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
||||||
import type { ActionData } from "./$types";
|
import type { ActionData } from "./$types";
|
||||||
|
|
||||||
const { form } = $props<{ form: ActionData }>();
|
const { form }: { form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SuccessOrError success={form?.success} message={form?.message} />
|
<SuccessOrError success={form?.success} message={form?.message} />
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
||||||
import type { ActionData } from "./$types";
|
import type { ActionData } from "./$types";
|
||||||
|
|
||||||
const { form } = $props<{ form: ActionData }>();
|
const { form }: { form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SuccessOrError success={form?.success} message={form?.message} />
|
<SuccessOrError success={form?.success} message={form?.message} />
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
||||||
import type { ActionData, PageServerData } from "./$types";
|
import type { ActionData, PageServerData } from "./$types";
|
||||||
|
|
||||||
const { form, data } = $props<{ form: ActionData; data: PageServerData }>();
|
const { form, data }: { form: ActionData; data: PageServerData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SuccessOrError success={form?.success} message={form?.message} />
|
<SuccessOrError success={form?.success} message={form?.message} />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
||||||
import type { ActionData, PageServerData } from "./$types";
|
import type { ActionData, PageServerData } from "./$types";
|
||||||
|
|
||||||
const { data, form } = $props<{ data: PageServerData; form: ActionData }>();
|
const { data, form }: { data: PageServerData; form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SuccessOrError success={form?.success} message={form?.message} />
|
<SuccessOrError success={form?.success} message={form?.message} />
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
import WebsiteEditor from "$lib/components/WebsiteEditor.svelte";
|
import WebsiteEditor from "$lib/components/WebsiteEditor.svelte";
|
||||||
import { ALLOWED_MIME_TYPES, handleImagePaste } from "$lib/utils";
|
import { ALLOWED_MIME_TYPES, handleImagePaste } from "$lib/utils";
|
||||||
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
||||||
import type { ActionData, PageServerData } from "./$types";
|
import type { ActionData, LayoutServerData, PageServerData } from "./$types";
|
||||||
import Modal from "$lib/components/Modal.svelte";
|
import Modal from "$lib/components/Modal.svelte";
|
||||||
|
|
||||||
const { data, form } = $props<{ data: PageServerData; form: ActionData }>();
|
const { data, form }: { data: PageServerData & LayoutServerData; form: ActionData } = $props();
|
||||||
|
|
||||||
let previewContent = $state(data.home.main_content);
|
let previewContent = $state(data.home.main_content);
|
||||||
let mainContentTextarea: HTMLTextAreaElement;
|
let mainContentTextarea: HTMLTextAreaElement;
|
||||||
@@ -19,7 +19,10 @@
|
|||||||
|
|
||||||
const handlePaste = async (event: ClipboardEvent) => {
|
const handlePaste = async (event: ClipboardEvent) => {
|
||||||
const newContent = await handleImagePaste(event, data.API_BASE_PREFIX);
|
const newContent = await handleImagePaste(event, data.API_BASE_PREFIX);
|
||||||
|
|
||||||
|
if (newContent) {
|
||||||
previewContent = newContent;
|
previewContent = newContent;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
||||||
import type { ActionData, PageServerData } from "./$types";
|
import type { ActionData, PageServerData } from "./$types";
|
||||||
|
|
||||||
const { data, form } = $props<{ data: PageServerData; form: ActionData }>();
|
const { data, form }: { data: PageServerData; form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SuccessOrError success={form?.success} message={form?.message} />
|
<SuccessOrError success={form?.success} message={form?.message} />
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import Modal from "$lib/components/Modal.svelte";
|
import Modal from "$lib/components/Modal.svelte";
|
||||||
import { handleImagePaste } from "$lib/utils";
|
import { handleImagePaste } from "$lib/utils";
|
||||||
|
|
||||||
const { data, form } = $props<{ data: PageServerData; form: ActionData }>();
|
const { data, form }: { data: PageServerData; form: ActionData } = $props();
|
||||||
|
|
||||||
let previewContent = $state(data.article.main_content);
|
let previewContent = $state(data.article.main_content);
|
||||||
let mainContentTextarea: HTMLTextAreaElement;
|
let mainContentTextarea: HTMLTextAreaElement;
|
||||||
@@ -20,7 +20,9 @@
|
|||||||
|
|
||||||
const handlePaste = async (event: ClipboardEvent) => {
|
const handlePaste = async (event: ClipboardEvent) => {
|
||||||
const newContent = await handleImagePaste(event, data.API_BASE_PREFIX);
|
const newContent = await handleImagePaste(event, data.API_BASE_PREFIX);
|
||||||
|
if (newContent) {
|
||||||
previewContent = newContent;
|
previewContent = newContent;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import Modal from "$lib/components/Modal.svelte";
|
import Modal from "$lib/components/Modal.svelte";
|
||||||
import type { ActionData, PageServerData } from "./$types";
|
import type { ActionData, PageServerData } from "./$types";
|
||||||
|
|
||||||
const { data, form } = $props<{ data: PageServerData; form: ActionData }>();
|
const { data, form }: { data: PageServerData; form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SuccessOrError success={form?.success} message={form?.message} />
|
<SuccessOrError success={form?.success} message={form?.message} />
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import DocsIndex from "$lib/templates/docs/DocsIndex.svelte";
|
|||||||
import DocsEntry from "$lib/templates/docs/DocsEntry.svelte";
|
import DocsEntry from "$lib/templates/docs/DocsEntry.svelte";
|
||||||
import { dev } from "$app/environment";
|
import { dev } from "$app/environment";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, fetch, cookies }) => {
|
export const load: PageServerLoad = async ({ params, fetch, cookies, parent }) => {
|
||||||
const websiteOverviewData = await fetch(
|
const websiteOverviewData = await fetch(
|
||||||
`${API_BASE_PREFIX}/website_overview?id=eq.${params.websiteId}`,
|
`${API_BASE_PREFIX}/website_overview?id=eq.${params.websiteId}`,
|
||||||
{
|
{
|
||||||
@@ -24,6 +24,7 @@ export const load: PageServerLoad = async ({ params, fetch, cookies }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const websiteOverview = await websiteOverviewData.json();
|
const websiteOverview = await websiteOverviewData.json();
|
||||||
|
const { website } = await parent();
|
||||||
|
|
||||||
generateStaticFiles(websiteOverview);
|
generateStaticFiles(websiteOverview);
|
||||||
|
|
||||||
@@ -31,7 +32,8 @@ export const load: PageServerLoad = async ({ params, fetch, cookies }) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
websitePreviewUrl
|
websitePreviewUrl,
|
||||||
|
website
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,8 +154,11 @@ const generateStaticFiles = async (websiteData: any, isPreview: boolean = true)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = await readFile(`${process.cwd()}/template-styles/blog-styles.css`, {
|
const commonStyles = await readFile(`${process.cwd()}/template-styles/common-styles.css`, {
|
||||||
encoding: "utf-8"
|
encoding: "utf-8"
|
||||||
});
|
});
|
||||||
await writeFile(join(uploadDir, "styles.css"), styles);
|
const specificStyles = await readFile(`${process.cwd()}/template-styles/blog-styles.css`, {
|
||||||
|
encoding: "utf-8"
|
||||||
|
});
|
||||||
|
await writeFile(join(uploadDir, "styles.css"), commonStyles.concat(specificStyles));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
||||||
import type { ActionData, PageServerData } from "./$types";
|
import type { ActionData, PageServerData } from "./$types";
|
||||||
|
|
||||||
const { data, form } = $props<{ data: PageServerData; form: ActionData }>();
|
const { data, form }: { data: PageServerData; form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SuccessOrError success={form?.success} message={form?.message} />
|
<SuccessOrError success={form?.success} message={form?.message} />
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import "../app.css";
|
import "../app.css";
|
||||||
|
import "../../template-styles/common-styles.css";
|
||||||
import { page } from "$app/stores";
|
import { page } from "$app/stores";
|
||||||
import type { LayoutServerData } from "./$types";
|
import type { LayoutServerData } from "./$types";
|
||||||
import type { Snippet } from "svelte";
|
import type { Snippet } from "svelte";
|
||||||
|
|
||||||
const { data, children } = $props<{ data: LayoutServerData; children: Snippet }>();
|
const { data, children }: { data: LayoutServerData; children: Snippet } = $props();
|
||||||
|
|
||||||
const isProjectRoute = $derived($page.url.pathname.startsWith("/website") && !$page.error);
|
const isProjectRoute = $derived($page.url.pathname.startsWith("/website") && !$page.error);
|
||||||
const routeName = $derived(
|
const routeName = $derived(
|
||||||
|
|||||||
@@ -1,43 +1,3 @@
|
|||||||
@font-face {
|
|
||||||
font-family: "JetBrains Mono";
|
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
|
||||||
font-weight: 400;
|
|
||||||
src:
|
|
||||||
url(https://cdn.jsdelivr.net/fontsource/fonts/jetbrains-mono@latest/latin-400-normal.woff2)
|
|
||||||
format("woff2"),
|
|
||||||
url(https://cdn.jsdelivr.net/fontsource/fonts/jetbrains-mono@latest/latin-400-normal.woff)
|
|
||||||
format("woff");
|
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
|
|
||||||
U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
|
|
||||||
U+FFFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
color-scheme: light dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
line-height: 1.5;
|
|
||||||
font-family: system-ui, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
img,
|
|
||||||
picture,
|
|
||||||
svg,
|
|
||||||
video {
|
|
||||||
max-inline-size: 100%;
|
|
||||||
block-size: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
list-style: inside;
|
list-style: inside;
|
||||||
@@ -45,60 +5,37 @@ ol {
|
|||||||
|
|
||||||
.container {
|
.container {
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
inline-size: min(100% - 2rem, 75ch);
|
inline-size: min(100% - var(--space-m), 75ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
header > .container {
|
header > .container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
nav,
|
nav,
|
||||||
header,
|
header,
|
||||||
main,
|
main,
|
||||||
footer {
|
footer {
|
||||||
padding-block: 1rem;
|
padding-block: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
section:has(> h2) + section:has(> h2) {
|
section:has(> h2) + section:has(> h2) {
|
||||||
margin-block-start: 2rem;
|
margin-block-start: var(--space-l);
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.articles ul {
|
.articles ul {
|
||||||
display: grid;
|
display: grid;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
gap: 1rem;
|
gap: var(--space-s);
|
||||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 30ch), 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(min(100%, 30ch), 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.articles li {
|
.articles li {
|
||||||
border: 1px solid hsl(0 0% 50%);
|
border: 1px solid hsl(0 0% 50%);
|
||||||
padding: 1rem;
|
padding: var(--space-s);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: var(--space-xs);
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
border: 1px solid hsl(0 0% 50%);
|
|
||||||
padding: 1rem;
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-family: "JetBrains Mono", monospace;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
:not(pre) > code {
|
|
||||||
background-color: hsl(0 0% 25%);
|
|
||||||
padding-inline: 0.25rem;
|
|
||||||
padding-block: 0.125rem;
|
|
||||||
}
|
}
|
||||||
|
|||||||
175
web-app/template-styles/common-styles.css
Normal file
175
web-app/template-styles/common-styles.css
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
@import url("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css")
|
||||||
|
screen and (prefers-color-scheme: light);
|
||||||
|
@import url("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css")
|
||||||
|
screen and (prefers-color-scheme: dark);
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "JetBrains Mono";
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
font-weight: 400;
|
||||||
|
src:
|
||||||
|
url(https://cdn.jsdelivr.net/fontsource/fonts/jetbrains-mono@latest/latin-400-normal.woff2)
|
||||||
|
format("woff2"),
|
||||||
|
url(https://cdn.jsdelivr.net/fontsource/fonts/jetbrains-mono@latest/latin-400-normal.woff)
|
||||||
|
format("woff");
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
|
||||||
|
U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
|
||||||
|
U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--bg-primary: white;
|
||||||
|
--bg-secondary: hsl(0 0% 95%);
|
||||||
|
--bg-tertiary: hsl(0 0% 90%);
|
||||||
|
|
||||||
|
--color-text: black;
|
||||||
|
--color-text-invert: white;
|
||||||
|
--color-accent: hsl(210, 100%, 30%);
|
||||||
|
--color-success: hsl(105, 100%, 30%);
|
||||||
|
--color-error: hsl(0, 100%, 30%);
|
||||||
|
|
||||||
|
--border-primary: 0.0625rem solid var(--bg-tertiary);
|
||||||
|
--border-radius: 0.125rem;
|
||||||
|
|
||||||
|
/* Step -1: 14.9953px → 14.2222px */
|
||||||
|
--font-size--1: clamp(0.8889rem, 0.9592rem + -0.1098cqi, 0.9372rem);
|
||||||
|
/* Step 0: 16px → 16px */
|
||||||
|
--font-size-0: clamp(1rem, 1rem + 0cqi, 1rem);
|
||||||
|
/* Step 1: 17.072px → 18px */
|
||||||
|
--font-size-1: clamp(1.067rem, 1.0406rem + 0.1318cqi, 1.125rem);
|
||||||
|
/* Step 2: 18.2158px → 20.25px */
|
||||||
|
--font-size-2: clamp(1.1385rem, 1.0807rem + 0.2889cqi, 1.2656rem);
|
||||||
|
/* Step 3: 19.4363px → 22.7813px */
|
||||||
|
--font-size-3: clamp(1.2148rem, 1.1197rem + 0.4751cqi, 1.4238rem);
|
||||||
|
/* Step 4: 20.7385px → 25.6289px */
|
||||||
|
--font-size-4: clamp(1.2962rem, 1.1572rem + 0.6947cqi, 1.6018rem);
|
||||||
|
/* Step 5: 22.128px → 28.8325px */
|
||||||
|
--font-size-5: clamp(1.383rem, 1.1925rem + 0.9523cqi, 1.802rem);
|
||||||
|
|
||||||
|
/* Space 3xs: 4px → 5px */
|
||||||
|
--space-3xs: clamp(0.25rem, 0.2336rem + 0.0822cqi, 0.3125rem);
|
||||||
|
/* Space 2xs: 8px → 10px */
|
||||||
|
--space-2xs: clamp(0.5rem, 0.4671rem + 0.1645cqi, 0.625rem);
|
||||||
|
/* Space xs: 12px → 15px */
|
||||||
|
--space-xs: clamp(0.75rem, 0.7007rem + 0.2467cqi, 0.9375rem);
|
||||||
|
/* Space s: 16px → 20px */
|
||||||
|
--space-s: clamp(1rem, 0.9342rem + 0.3289cqi, 1.25rem);
|
||||||
|
/* Space m: 24px → 30px */
|
||||||
|
--space-m: clamp(1.5rem, 1.4013rem + 0.4934cqi, 1.875rem);
|
||||||
|
/* Space l: 32px → 40px */
|
||||||
|
--space-l: clamp(2rem, 1.8684rem + 0.6579cqi, 2.5rem);
|
||||||
|
/* Space xl: 48px → 60px */
|
||||||
|
--space-xl: clamp(3rem, 2.8026rem + 0.9868cqi, 3.75rem);
|
||||||
|
/* Space 2xl: 64px → 80px */
|
||||||
|
--space-2xl: clamp(4rem, 3.7368rem + 1.3158cqi, 5rem);
|
||||||
|
/* Space 3xl: 96px → 120px */
|
||||||
|
--space-3xl: clamp(6rem, 5.6053rem + 1.9737cqi, 7.5rem);
|
||||||
|
|
||||||
|
color-scheme: light;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--bg-primary: hsl(0 0% 15%);
|
||||||
|
--bg-secondary: hsl(0 0% 20%);
|
||||||
|
--bg-tertiary: hsl(0 0% 25%);
|
||||||
|
|
||||||
|
--color-text: white;
|
||||||
|
--color-text-invert: black;
|
||||||
|
--color-accent: hsl(210, 100%, 80%);
|
||||||
|
--color-success: hsl(105, 100%, 80%);
|
||||||
|
--color-error: hsl(0, 100%, 80%);
|
||||||
|
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
line-height: 1.5;
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
background-color: var(--bg-primary);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-block-size: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--space-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
details[open] summary {
|
||||||
|
margin-block-end: var(--space-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
img,
|
||||||
|
picture,
|
||||||
|
svg,
|
||||||
|
video {
|
||||||
|
max-inline-size: 100%;
|
||||||
|
block-size: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: var(--font-size-0);
|
||||||
|
}
|
||||||
|
h5 {
|
||||||
|
font-size: var(--font-size-1);
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
font-size: var(--font-size-2);
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: var(--font-size-3);
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: var(--font-size-4);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: var(--font-size-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: var(--font-size--1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
border: var(--border-primary);
|
||||||
|
padding: var(--space-s);
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: var(--font-size--1);
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code {
|
||||||
|
background-color: var(--bg-secondary);
|
||||||
|
border: var(--border-primary);
|
||||||
|
padding-inline: var(--space-3xs);
|
||||||
|
}
|
||||||
@@ -2,5 +2,10 @@ import { sveltekit } from "@sveltejs/kit/vite";
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [sveltekit()]
|
plugins: [sveltekit()],
|
||||||
|
server: {
|
||||||
|
fs: {
|
||||||
|
allow: ["."]
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user