mirror of
https://github.com/thiloho/archtika.git
synced 2025-11-22 10:51:36 +01:00
Add OpenGraph head tags and more tests
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
graphics = false;
|
graphics = false;
|
||||||
memorySize = 2048;
|
memorySize = 2048;
|
||||||
cores = 2;
|
cores = 2;
|
||||||
|
diskSize = 10240;
|
||||||
sharedDirectories = {
|
sharedDirectories = {
|
||||||
websites = {
|
websites = {
|
||||||
source = "/var/www/archtika-websites";
|
source = "/var/www/archtika-websites";
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ CREATE TABLE internal.header (
|
|||||||
CREATE TABLE internal.home (
|
CREATE TABLE internal.home (
|
||||||
website_id UUID PRIMARY KEY REFERENCES internal.website (id) ON DELETE CASCADE,
|
website_id UUID PRIMARY KEY REFERENCES internal.website (id) ON DELETE CASCADE,
|
||||||
main_content TEXT NOT NULL CHECK (TRIM(main_content) != ''),
|
main_content TEXT NOT NULL CHECK (TRIM(main_content) != ''),
|
||||||
|
meta_description VARCHAR(250) CHECK (TRIM(meta_description) != ''),
|
||||||
last_modified_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(),
|
last_modified_at TIMESTAMPTZ NOT NULL DEFAULT CLOCK_TIMESTAMP(),
|
||||||
last_modified_by UUID REFERENCES internal.user (id) ON DELETE SET NULL
|
last_modified_by UUID REFERENCES internal.user (id) ON DELETE SET NULL
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ GRANT SELECT, UPDATE (logo_type, logo_text, logo_image) ON internal.header TO au
|
|||||||
|
|
||||||
GRANT SELECT, UPDATE ON api.header TO authenticated_user;
|
GRANT SELECT, UPDATE ON api.header TO authenticated_user;
|
||||||
|
|
||||||
GRANT SELECT, UPDATE (main_content) ON internal.home TO authenticated_user;
|
GRANT SELECT, UPDATE (main_content, meta_description) ON internal.home TO authenticated_user;
|
||||||
|
|
||||||
GRANT SELECT, UPDATE ON api.home TO authenticated_user;
|
GRANT SELECT, UPDATE ON api.home TO authenticated_user;
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ CREATE POLICY view_websites ON internal.website
|
|||||||
|
|
||||||
CREATE POLICY update_website ON internal.website
|
CREATE POLICY update_website ON internal.website
|
||||||
FOR UPDATE
|
FOR UPDATE
|
||||||
USING (internal.user_has_website_access (id, 20));
|
USING (internal.user_has_website_access (id, 30));
|
||||||
|
|
||||||
CREATE POLICY delete_website ON internal.website
|
CREATE POLICY delete_website ON internal.website
|
||||||
FOR DELETE
|
FOR DELETE
|
||||||
|
|||||||
@@ -13,6 +13,23 @@ CREATE TABLE internal.change_log (
|
|||||||
new_value HSTORE
|
new_value HSTORE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE VIEW api.change_log WITH ( security_invoker = ON
|
||||||
|
) AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
internal.change_log;
|
||||||
|
|
||||||
|
GRANT SELECT ON internal.change_log TO authenticated_user;
|
||||||
|
|
||||||
|
GRANT SELECT ON api.change_log TO authenticated_user;
|
||||||
|
|
||||||
|
ALTER TABLE internal.change_log ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
CREATE POLICY view_change_log ON internal.change_log
|
||||||
|
FOR SELECT
|
||||||
|
USING (internal.user_has_website_access (website_id, 10));
|
||||||
|
|
||||||
CREATE FUNCTION internal.track_changes ()
|
CREATE FUNCTION internal.track_changes ()
|
||||||
RETURNS TRIGGER
|
RETURNS TRIGGER
|
||||||
AS $$
|
AS $$
|
||||||
@@ -109,17 +126,6 @@ CREATE TRIGGER collab_track_changes
|
|||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
EXECUTE FUNCTION internal.track_changes ();
|
EXECUTE FUNCTION internal.track_changes ();
|
||||||
|
|
||||||
CREATE VIEW api.change_log WITH ( security_invoker = ON
|
|
||||||
) AS
|
|
||||||
SELECT
|
|
||||||
*
|
|
||||||
FROM
|
|
||||||
internal.change_log;
|
|
||||||
|
|
||||||
GRANT SELECT ON internal.change_log TO authenticated_user;
|
|
||||||
|
|
||||||
GRANT SELECT ON api.change_log TO authenticated_user;
|
|
||||||
|
|
||||||
-- migrate:down
|
-- migrate:down
|
||||||
DROP TRIGGER website_track_changes ON internal.website;
|
DROP TRIGGER website_track_changes ON internal.website;
|
||||||
|
|
||||||
|
|||||||
@@ -299,18 +299,26 @@ const header = {
|
|||||||
export interface Home {
|
export interface Home {
|
||||||
website_id: string;
|
website_id: string;
|
||||||
main_content: string;
|
main_content: string;
|
||||||
|
meta_description: string | null;
|
||||||
last_modified_at: Date;
|
last_modified_at: Date;
|
||||||
last_modified_by: string | null;
|
last_modified_by: string | null;
|
||||||
}
|
}
|
||||||
export interface HomeInput {
|
export interface HomeInput {
|
||||||
website_id: string;
|
website_id: string;
|
||||||
main_content: string;
|
main_content: string;
|
||||||
|
meta_description?: string | null;
|
||||||
last_modified_at?: Date;
|
last_modified_at?: Date;
|
||||||
last_modified_by?: string | null;
|
last_modified_by?: string | null;
|
||||||
}
|
}
|
||||||
const home = {
|
const home = {
|
||||||
tableName: "home",
|
tableName: "home",
|
||||||
columns: ["website_id", "main_content", "last_modified_at", "last_modified_by"],
|
columns: [
|
||||||
|
"website_id",
|
||||||
|
"main_content",
|
||||||
|
"meta_description",
|
||||||
|
"last_modified_at",
|
||||||
|
"last_modified_by"
|
||||||
|
],
|
||||||
requiredForInsert: ["website_id", "main_content"],
|
requiredForInsert: ["website_id", "main_content"],
|
||||||
primaryKey: "website_id",
|
primaryKey: "website_id",
|
||||||
foreignKeys: {
|
foreignKeys: {
|
||||||
|
|||||||
@@ -8,8 +8,10 @@
|
|||||||
const {
|
const {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
article,
|
article,
|
||||||
apiUrl
|
apiUrl,
|
||||||
}: { websiteOverview: WebsiteOverview; article: Article; apiUrl: string } = $props();
|
websiteUrl
|
||||||
|
}: { websiteOverview: WebsiteOverview; article: Article; apiUrl: string; websiteUrl: string } =
|
||||||
|
$props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Head
|
<Head
|
||||||
@@ -18,6 +20,7 @@
|
|||||||
{apiUrl}
|
{apiUrl}
|
||||||
title={article.title}
|
title={article.title}
|
||||||
metaDescription={article.meta_description}
|
metaDescription={article.meta_description}
|
||||||
|
{websiteUrl}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Nav {websiteOverview} isDocsTemplate={false} isIndexPage={false} {apiUrl} />
|
<Nav {websiteOverview} isDocsTemplate={false} isIndexPage={false} {apiUrl} />
|
||||||
|
|||||||
@@ -7,8 +7,14 @@
|
|||||||
const {
|
const {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
apiUrl,
|
apiUrl,
|
||||||
isLegalPage
|
isLegalPage,
|
||||||
}: { websiteOverview: WebsiteOverview; apiUrl: string; isLegalPage: boolean } = $props();
|
websiteUrl
|
||||||
|
}: {
|
||||||
|
websiteOverview: WebsiteOverview;
|
||||||
|
apiUrl: string;
|
||||||
|
isLegalPage: boolean;
|
||||||
|
websiteUrl: string;
|
||||||
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Head
|
<Head
|
||||||
@@ -16,6 +22,8 @@
|
|||||||
nestingLevel={0}
|
nestingLevel={0}
|
||||||
{apiUrl}
|
{apiUrl}
|
||||||
title={isLegalPage ? "Legal information" : websiteOverview.title}
|
title={isLegalPage ? "Legal information" : websiteOverview.title}
|
||||||
|
metaDescription={websiteOverview.home.meta_description}
|
||||||
|
{websiteUrl}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Nav {websiteOverview} isDocsTemplate={false} isIndexPage={true} {apiUrl} />
|
<Nav {websiteOverview} isDocsTemplate={false} isIndexPage={true} {apiUrl} />
|
||||||
|
|||||||
@@ -1,31 +1,86 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { WebsiteOverview } from "../../utils";
|
import { slugify, type WebsiteOverview } from "../../utils";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
nestingLevel,
|
nestingLevel,
|
||||||
apiUrl,
|
apiUrl,
|
||||||
title,
|
title,
|
||||||
metaDescription
|
metaDescription,
|
||||||
|
websiteUrl
|
||||||
}: {
|
}: {
|
||||||
websiteOverview: WebsiteOverview;
|
websiteOverview: WebsiteOverview;
|
||||||
nestingLevel: number;
|
nestingLevel: number;
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
title: string;
|
title: string;
|
||||||
metaDescription?: string | null;
|
metaDescription?: string | null;
|
||||||
|
websiteUrl: string;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
|
const constructedTitle =
|
||||||
|
websiteOverview.title === title ? title : `${websiteOverview.title} | ${title}`;
|
||||||
|
|
||||||
|
let ogUrl = `${websiteUrl.replace(/\/$/, "")}${nestingLevel === 0 ? (websiteOverview.title === title ? "" : `/${slugify(title)}`) : `/articles/${slugify(title)}`}`;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>{websiteOverview.title === title ? title : `${websiteOverview.title} | ${title}`}</title>
|
<title>{constructedTitle}</title>
|
||||||
<meta name="description" content={metaDescription ?? title} />
|
<meta name="description" content={metaDescription ?? title} />
|
||||||
<link rel="stylesheet" href={`${"../".repeat(nestingLevel)}styles.css`} />
|
<link rel="stylesheet" href={`${"../".repeat(nestingLevel)}variables.css`} />
|
||||||
|
<link rel="stylesheet" href={`${"../".repeat(nestingLevel)}common.css`} />
|
||||||
|
<link rel="stylesheet" href={`${"../".repeat(nestingLevel)}scoped.css`} />
|
||||||
{#if websiteOverview.settings.favicon_image}
|
{#if websiteOverview.settings.favicon_image}
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
href="{apiUrl}/rpc/retrieve_file?id={websiteOverview.settings.favicon_image}"
|
href="{apiUrl}/rpc/retrieve_file?id={websiteOverview.settings.favicon_image}"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
<meta property="og:site_name" content={websiteOverview.title} />
|
||||||
|
<meta property="og:title" content={constructedTitle} />
|
||||||
|
<meta property="og:description" content={metaDescription ?? title} />
|
||||||
|
<meta property="og:type" content="article" />
|
||||||
|
<meta property="og:url" content={ogUrl} />
|
||||||
|
{#if websiteOverview.header.logo_image}
|
||||||
|
<meta
|
||||||
|
property="og:image"
|
||||||
|
content="{apiUrl}/rpc/retrieve_file?id={websiteOverview.header.logo_image}"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
<script>
|
||||||
|
const determineTheme = (skipSetTheme = false) => {
|
||||||
|
const lightMode = window
|
||||||
|
.getComputedStyle(document.documentElement)
|
||||||
|
.getPropertyValue("--display-light");
|
||||||
|
const darkMode = window
|
||||||
|
.getComputedStyle(document.documentElement)
|
||||||
|
.getPropertyValue("--display-dark");
|
||||||
|
|
||||||
|
if (!skipSetTheme && lightMode === "none") {
|
||||||
|
localStorage.setItem("theme", "light");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipSetTheme && darkMode === "none") {
|
||||||
|
localStorage.setItem("theme", "dark");
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentTheme = localStorage.getItem("theme");
|
||||||
|
|
||||||
|
window.addEventListener("DOMContentLoaded", (event) => {
|
||||||
|
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
|
||||||
|
document.querySelector("#toggle-theme").checked =
|
||||||
|
darkMode === "none" ? currentTheme === "light" : currentTheme === "dark";
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
determineTheme(true);
|
||||||
|
|
||||||
|
window.addEventListener("DOMContentLoaded", (event) => {
|
||||||
|
document.querySelector('label[for="toggle-theme"]').addEventListener("click", () => {
|
||||||
|
determineTheme();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
<a href={isIndexPage ? "." : ".."}>
|
<svelte:element this={isIndexPage ? "span" : "a"} href="..">
|
||||||
{#if websiteOverview.header.logo_type === "text"}
|
{#if websiteOverview.header.logo_type === "text"}
|
||||||
<strong>{websiteOverview.header.logo_text}</strong>
|
<strong>{websiteOverview.header.logo_text}</strong>
|
||||||
{:else}
|
{:else}
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</svelte:element>
|
||||||
<label style="margin-inline-start: auto;" for="toggle-theme">
|
<label style="margin-inline-start: auto;" for="toggle-theme">
|
||||||
<input type="checkbox" id="toggle-theme" hidden />
|
<input type="checkbox" id="toggle-theme" hidden />
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -8,8 +8,10 @@
|
|||||||
const {
|
const {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
article,
|
article,
|
||||||
apiUrl
|
apiUrl,
|
||||||
}: { websiteOverview: WebsiteOverview; article: Article; apiUrl: string } = $props();
|
websiteUrl
|
||||||
|
}: { websiteOverview: WebsiteOverview; article: Article; apiUrl: string; websiteUrl: string } =
|
||||||
|
$props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Head
|
<Head
|
||||||
@@ -18,6 +20,7 @@
|
|||||||
{apiUrl}
|
{apiUrl}
|
||||||
title={article.title}
|
title={article.title}
|
||||||
metaDescription={article.meta_description}
|
metaDescription={article.meta_description}
|
||||||
|
{websiteUrl}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Nav {websiteOverview} isDocsTemplate={true} isIndexPage={false} {apiUrl} />
|
<Nav {websiteOverview} isDocsTemplate={true} isIndexPage={false} {apiUrl} />
|
||||||
|
|||||||
@@ -7,8 +7,14 @@
|
|||||||
const {
|
const {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
apiUrl,
|
apiUrl,
|
||||||
isLegalPage
|
isLegalPage,
|
||||||
}: { websiteOverview: WebsiteOverview; apiUrl: string; isLegalPage: boolean } = $props();
|
websiteUrl
|
||||||
|
}: {
|
||||||
|
websiteOverview: WebsiteOverview;
|
||||||
|
apiUrl: string;
|
||||||
|
isLegalPage: boolean;
|
||||||
|
websiteUrl: string;
|
||||||
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Head
|
<Head
|
||||||
@@ -16,6 +22,8 @@
|
|||||||
nestingLevel={0}
|
nestingLevel={0}
|
||||||
{apiUrl}
|
{apiUrl}
|
||||||
title={isLegalPage ? "Legal information" : websiteOverview.title}
|
title={isLegalPage ? "Legal information" : websiteOverview.title}
|
||||||
|
metaDescription={websiteOverview.home.meta_description}
|
||||||
|
{websiteUrl}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Nav {websiteOverview} isDocsTemplate={true} isIndexPage={true} {apiUrl} />
|
<Nav {websiteOverview} isDocsTemplate={true} isIndexPage={true} {apiUrl} />
|
||||||
|
|||||||
@@ -134,7 +134,8 @@ export const actions: Actions = {
|
|||||||
"PATCH",
|
"PATCH",
|
||||||
{
|
{
|
||||||
body: {
|
body: {
|
||||||
main_content: data.get("main-content")
|
main_content: data.get("main-content"),
|
||||||
|
meta_description: data.get("description")
|
||||||
},
|
},
|
||||||
successMessage: "Successfully updated home"
|
successMessage: "Successfully updated home"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,12 @@
|
|||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<form action="?/updateHome" method="POST" use:enhance={enhanceForm({ reset: false })}>
|
<form action="?/updateHome" method="POST" use:enhance={enhanceForm({ reset: false })}>
|
||||||
|
<label>
|
||||||
|
Description:
|
||||||
|
<textarea name="description" rows="5" maxlength="250" required
|
||||||
|
>{data.home.meta_description}</textarea
|
||||||
|
>
|
||||||
|
</label>
|
||||||
<MarkdownEditor
|
<MarkdownEditor
|
||||||
apiPrefix={data.API_BASE_PREFIX}
|
apiPrefix={data.API_BASE_PREFIX}
|
||||||
label="Main content"
|
label="Main content"
|
||||||
|
|||||||
@@ -25,24 +25,7 @@ export const load: PageServerLoad = async ({ params, fetch }) => {
|
|||||||
)
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
generateStaticFiles(websiteOverview);
|
const { websitePreviewUrl, websiteProdUrl } = await generateStaticFiles(websiteOverview);
|
||||||
|
|
||||||
const websitePreviewUrl = `${
|
|
||||||
dev
|
|
||||||
? "http://localhost:18000"
|
|
||||||
: process.env.ORIGIN
|
|
||||||
? process.env.ORIGIN
|
|
||||||
: "http://localhost:18000"
|
|
||||||
}/previews/${websiteOverview.id}/`;
|
|
||||||
|
|
||||||
const websiteProdUrl = dev
|
|
||||||
? `http://localhost:18000/${websiteOverview.domain_prefix?.prefix ?? websiteOverview.id}/`
|
|
||||||
: process.env.ORIGIN
|
|
||||||
? process.env.ORIGIN.replace(
|
|
||||||
"//",
|
|
||||||
`//${websiteOverview.domain_prefix?.prefix ?? websiteOverview.id}.`
|
|
||||||
)
|
|
||||||
: `http://localhost:18000/${websiteOverview.domain_prefix?.prefix ?? websiteOverview.id}/`;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
@@ -67,7 +50,7 @@ export const actions: Actions = {
|
|||||||
)
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
generateStaticFiles(websiteOverview, false);
|
await generateStaticFiles(websiteOverview, false);
|
||||||
|
|
||||||
return await apiRequest(
|
return await apiRequest(
|
||||||
fetch,
|
fetch,
|
||||||
@@ -156,6 +139,23 @@ export const actions: Actions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview = true) => {
|
const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview = true) => {
|
||||||
|
const websitePreviewUrl = `${
|
||||||
|
dev
|
||||||
|
? "http://localhost:18000"
|
||||||
|
: process.env.ORIGIN
|
||||||
|
? process.env.ORIGIN
|
||||||
|
: "http://localhost:18000"
|
||||||
|
}/previews/${websiteData.id}/`;
|
||||||
|
|
||||||
|
const websiteProdUrl = dev
|
||||||
|
? `http://localhost:18000/${websiteData.domain_prefix?.prefix ?? websiteData.id}/`
|
||||||
|
: process.env.ORIGIN
|
||||||
|
? process.env.ORIGIN.replace(
|
||||||
|
"//",
|
||||||
|
`//${websiteData.domain_prefix?.prefix ?? websiteData.id}.`
|
||||||
|
)
|
||||||
|
: `http://localhost:18000/${websiteData.domain_prefix?.prefix ?? websiteData.id}/`;
|
||||||
|
|
||||||
const fileContents = (head: string, body: string) => {
|
const fileContents = (head: string, body: string) => {
|
||||||
return `
|
return `
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -173,7 +173,8 @@ const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview = tru
|
|||||||
props: {
|
props: {
|
||||||
websiteOverview: websiteData,
|
websiteOverview: websiteData,
|
||||||
apiUrl: API_BASE_PREFIX,
|
apiUrl: API_BASE_PREFIX,
|
||||||
isLegalPage: false
|
isLegalPage: false,
|
||||||
|
websiteUrl: isPreview ? websitePreviewUrl : websiteProdUrl
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -202,7 +203,8 @@ const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview = tru
|
|||||||
props: {
|
props: {
|
||||||
websiteOverview: websiteData,
|
websiteOverview: websiteData,
|
||||||
article,
|
article,
|
||||||
apiUrl: API_BASE_PREFIX
|
apiUrl: API_BASE_PREFIX,
|
||||||
|
websiteUrl: isPreview ? websitePreviewUrl : websiteProdUrl
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -217,13 +219,17 @@ const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview = tru
|
|||||||
props: {
|
props: {
|
||||||
websiteOverview: websiteData,
|
websiteOverview: websiteData,
|
||||||
apiUrl: API_BASE_PREFIX,
|
apiUrl: API_BASE_PREFIX,
|
||||||
isLegalPage: true
|
isLegalPage: true,
|
||||||
|
websiteUrl: isPreview ? websitePreviewUrl : websiteProdUrl
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await writeFile(join(uploadDir, "legal-information.html"), fileContents(head, body));
|
await writeFile(join(uploadDir, "legal-information.html"), fileContents(head, body));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const variableStyles = await readFile(`${process.cwd()}/template-styles/variables.css`, {
|
||||||
|
encoding: "utf-8"
|
||||||
|
});
|
||||||
const commonStyles = await readFile(`${process.cwd()}/template-styles/common-styles.css`, {
|
const commonStyles = await readFile(`${process.cwd()}/template-styles/common-styles.css`, {
|
||||||
encoding: "utf-8"
|
encoding: "utf-8"
|
||||||
});
|
});
|
||||||
@@ -246,22 +252,43 @@ const generateStaticFiles = async (websiteData: WebsiteOverview, isPreview = tru
|
|||||||
} = hexToHSL(websiteData.settings.background_color_light_theme);
|
} = hexToHSL(websiteData.settings.background_color_light_theme);
|
||||||
|
|
||||||
await writeFile(
|
await writeFile(
|
||||||
join(uploadDir, "styles.css"),
|
join(uploadDir, "variables.css"),
|
||||||
commonStyles
|
variableStyles
|
||||||
.concat(specificStyles)
|
.replaceAll(
|
||||||
.replace(/(?<=\/\* BACKGROUND_COLOR_DARK_THEME_H \*\/\s*).*(?=;)/, ` ${hDark}`)
|
/\/\* BACKGROUND_COLOR_DARK_THEME_H \*\/\s*.*?;/g,
|
||||||
.replace(/(?<=\/\* BACKGROUND_COLOR_DARK_THEME_S \*\/\s*).*(?=;)/, ` ${sDark}%`)
|
`/* BACKGROUND_COLOR_DARK_THEME_H */ ${hDark};`
|
||||||
.replace(/(?<=\/\* BACKGROUND_COLOR_DARK_THEME_L \*\/\s*).*(?=;)/, ` ${lDark}%`)
|
|
||||||
.replace(/(?<=\/\* BACKGROUND_COLOR_LIGHT_THEME_H \*\/\s*).*(?=;)/, ` ${hLight}`)
|
|
||||||
.replace(/(?<=\/\* BACKGROUND_COLOR_LIGHT_THEME_S \*\/\s*).*(?=;)/, ` ${sLight}%`)
|
|
||||||
.replace(/(?<=\/\* BACKGROUND_COLOR_LIGHT_THEME_L \*\/\s*).*(?=;)/, ` ${lLight}%`)
|
|
||||||
.replace(
|
|
||||||
/(?<=\/\* ACCENT_COLOR_DARK_THEME \*\/\s*).*(?=;)/,
|
|
||||||
` ${websiteData.settings.accent_color_dark_theme}`
|
|
||||||
)
|
)
|
||||||
.replace(
|
.replaceAll(
|
||||||
/(?<=\/\* ACCENT_COLOR_LIGHT_THEME \*\/\s*).*(?=;)/,
|
/\/\* BACKGROUND_COLOR_DARK_THEME_S \*\/\s*.*?;/g,
|
||||||
` ${websiteData.settings.accent_color_light_theme}`
|
`/* BACKGROUND_COLOR_DARK_THEME_S */ ${sDark}%;`
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/\/\* BACKGROUND_COLOR_DARK_THEME_L \*\/\s*.*?;/g,
|
||||||
|
`/* BACKGROUND_COLOR_DARK_THEME_L */ ${lDark}%;`
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/\/\* BACKGROUND_COLOR_LIGHT_THEME_H \*\/\s*.*?;/g,
|
||||||
|
`/* BACKGROUND_COLOR_LIGHT_THEME_H */ ${hLight};`
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/\/\* BACKGROUND_COLOR_LIGHT_THEME_S \*\/\s*.*?;/g,
|
||||||
|
`/* BACKGROUND_COLOR_LIGHT_THEME_S */ ${sLight}%;`
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/\/\* BACKGROUND_COLOR_LIGHT_THEME_L \*\/\s*.*?;/g,
|
||||||
|
`/* BACKGROUND_COLOR_LIGHT_THEME_L */ ${lLight}%;`
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/\/\* ACCENT_COLOR_DARK_THEME \*\/\s*.*?;/g,
|
||||||
|
`/* ACCENT_COLOR_DARK_THEME */ ${websiteData.settings.accent_color_dark_theme};`
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
/\/\* ACCENT_COLOR_LIGHT_THEME \*\/\s*.*?;/g,
|
||||||
|
`/* ACCENT_COLOR_LIGHT_THEME */ ${websiteData.settings.accent_color_light_theme};`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
await writeFile(join(uploadDir, "common.css"), commonStyles);
|
||||||
|
await writeFile(join(uploadDir, "scoped.css"), specificStyles);
|
||||||
|
|
||||||
|
return { websitePreviewUrl, websiteProdUrl };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import "../../template-styles/variables.css";
|
||||||
import "../../template-styles/common-styles.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";
|
||||||
|
|||||||
@@ -1,208 +1,3 @@
|
|||||||
html {
|
|
||||||
--border-primary: 0.0625rem solid var(--color-border);
|
|
||||||
--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);
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
--bg-primary-h: /* BACKGROUND_COLOR_LIGHT_THEME_H */ 0;
|
|
||||||
--bg-primary-s: /* BACKGROUND_COLOR_LIGHT_THEME_S */ 0%;
|
|
||||||
--bg-primary-l: /* BACKGROUND_COLOR_LIGHT_THEME_L */ 100%;
|
|
||||||
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
|
||||||
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 5%));
|
|
||||||
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 10%));
|
|
||||||
--bg-blurred: hsla(
|
|
||||||
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) - 20%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 0%);
|
|
||||||
--color-text-invert: var(--bg-primary);
|
|
||||||
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 50%));
|
|
||||||
--color-accent: /* ACCENT_COLOR_LIGHT_THEME */ hsl(210 100% 30%);
|
|
||||||
--color-success: hsl(105 100% 30%);
|
|
||||||
--color-error: hsl(0 100% 30%);
|
|
||||||
|
|
||||||
--display-light: none;
|
|
||||||
--display-dark: initial;
|
|
||||||
|
|
||||||
--hl-bg: #fff;
|
|
||||||
--hl-color: #24292e;
|
|
||||||
--hl-keyword: #d73a49;
|
|
||||||
--hl-title: #6f42c1;
|
|
||||||
--hl-attr: #005cc5;
|
|
||||||
--hl-string: #032f62;
|
|
||||||
--hl-built-in: #e36209;
|
|
||||||
--hl-comment: #6a737d;
|
|
||||||
--hl-tag: #22863a;
|
|
||||||
--hl-section: #005cc5;
|
|
||||||
--hl-bullet: #735c0f;
|
|
||||||
--hl-emphasis: #24292e;
|
|
||||||
--hl-addition-bg: #f0fff4;
|
|
||||||
--hl-addition-text: #22863a;
|
|
||||||
--hl-deletion-bg: #ffeef0;
|
|
||||||
--hl-deletion-text: #b31d28;
|
|
||||||
|
|
||||||
color-scheme: light;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:has(#toggle-theme:checked) {
|
|
||||||
--bg-primary-h: /* BACKGROUND_COLOR_DARK_THEME_H */ 0;
|
|
||||||
--bg-primary-s: /* BACKGROUND_COLOR_DARK_THEME_S */ 0%;
|
|
||||||
--bg-primary-l: /* BACKGROUND_COLOR_DARK_THEME_L */ 15%;
|
|
||||||
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
|
||||||
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 5%));
|
|
||||||
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 10%));
|
|
||||||
--bg-blurred: hsla(
|
|
||||||
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) + 20%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 100%);
|
|
||||||
--color-text-invert: var(--bg-primary);
|
|
||||||
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 50%));
|
|
||||||
--color-accent: /* ACCENT_COLOR_DARK_THEME */ hsl(210 100% 80%);
|
|
||||||
--color-success: hsl(105 100% 80%);
|
|
||||||
--color-error: hsl(0 100% 80%);
|
|
||||||
|
|
||||||
--display-light: initial;
|
|
||||||
--display-dark: none;
|
|
||||||
|
|
||||||
--hl-bg: #0d1117;
|
|
||||||
--hl-color: #c9d1d9;
|
|
||||||
--hl-keyword: #ff7b72;
|
|
||||||
--hl-title: #d2a8ff;
|
|
||||||
--hl-attr: #79c0ff;
|
|
||||||
--hl-string: #a5d6ff;
|
|
||||||
--hl-built-in: #ffa657;
|
|
||||||
--hl-comment: #8b949e;
|
|
||||||
--hl-tag: #7ee787;
|
|
||||||
--hl-section: #1f6feb;
|
|
||||||
--hl-bullet: #f2cc60;
|
|
||||||
--hl-emphasis: #c9d1d9;
|
|
||||||
--hl-addition-bg: #033a16;
|
|
||||||
--hl-addition-text: #aff5b4;
|
|
||||||
--hl-deletion-bg: #67060c;
|
|
||||||
--hl-deletion-text: #ffdcd7;
|
|
||||||
|
|
||||||
color-scheme: dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
html {
|
|
||||||
--bg-primary-h: /* BACKGROUND_COLOR_DARK_THEME_H */ 0;
|
|
||||||
--bg-primary-s: /* BACKGROUND_COLOR_DARK_THEME_S */ 0%;
|
|
||||||
--bg-primary-l: /* BACKGROUND_COLOR_DARK_THEME_L */ 15%;
|
|
||||||
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
|
||||||
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 5%));
|
|
||||||
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 10%));
|
|
||||||
--bg-blurred: hsla(
|
|
||||||
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) + 20%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 100%);
|
|
||||||
--color-text-invert: var(--bg-primary);
|
|
||||||
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 50%));
|
|
||||||
--color-accent: /* ACCENT_COLOR_DARK_THEME */ hsl(210 100% 80%);
|
|
||||||
--color-success: hsl(105 100% 80%);
|
|
||||||
--color-error: hsl(0 100% 80%);
|
|
||||||
|
|
||||||
--display-light: initial;
|
|
||||||
--display-dark: none;
|
|
||||||
|
|
||||||
--hl-bg: #0d1117;
|
|
||||||
--hl-color: #c9d1d9;
|
|
||||||
--hl-keyword: #ff7b72;
|
|
||||||
--hl-title: #d2a8ff;
|
|
||||||
--hl-attr: #79c0ff;
|
|
||||||
--hl-string: #a5d6ff;
|
|
||||||
--hl-built-in: #ffa657;
|
|
||||||
--hl-comment: #8b949e;
|
|
||||||
--hl-tag: #7ee787;
|
|
||||||
--hl-section: #1f6feb;
|
|
||||||
--hl-bullet: #f2cc60;
|
|
||||||
--hl-emphasis: #c9d1d9;
|
|
||||||
--hl-addition-bg: #033a16;
|
|
||||||
--hl-addition-text: #aff5b4;
|
|
||||||
--hl-deletion-bg: #67060c;
|
|
||||||
--hl-deletion-text: #ffdcd7;
|
|
||||||
|
|
||||||
color-scheme: dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:has(#toggle-theme:checked) {
|
|
||||||
--bg-primary-h: /* BACKGROUND_COLOR_LIGHT_THEME_H */ 0;
|
|
||||||
--bg-primary-s: /* BACKGROUND_COLOR_LIGHT_THEME_S */ 0%;
|
|
||||||
--bg-primary-l: /* BACKGROUND_COLOR_LIGHT_THEME_L */ 100%;
|
|
||||||
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
|
||||||
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 5%));
|
|
||||||
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 10%));
|
|
||||||
--bg-blurred: hsla(
|
|
||||||
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) - 20%)
|
|
||||||
);
|
|
||||||
|
|
||||||
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 0%);
|
|
||||||
--color-text-invert: var(--bg-primary);
|
|
||||||
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 50%));
|
|
||||||
--color-accent: /* ACCENT_COLOR_LIGHT_THEME */ hsl(210 100% 30%);
|
|
||||||
--color-success: hsl(105 100% 30%);
|
|
||||||
--color-error: hsl(0 100% 30%);
|
|
||||||
|
|
||||||
--display-light: none;
|
|
||||||
--display-dark: initial;
|
|
||||||
|
|
||||||
--hl-bg: #fff;
|
|
||||||
--hl-color: #24292e;
|
|
||||||
--hl-keyword: #d73a49;
|
|
||||||
--hl-title: #6f42c1;
|
|
||||||
--hl-attr: #005cc5;
|
|
||||||
--hl-string: #032f62;
|
|
||||||
--hl-built-in: #e36209;
|
|
||||||
--hl-comment: #6a737d;
|
|
||||||
--hl-tag: #22863a;
|
|
||||||
--hl-section: #005cc5;
|
|
||||||
--hl-bullet: #735c0f;
|
|
||||||
--hl-emphasis: #24292e;
|
|
||||||
--hl-addition-bg: #f0fff4;
|
|
||||||
--hl-addition-text: #22863a;
|
|
||||||
--hl-deletion-bg: #ffeef0;
|
|
||||||
--hl-deletion-text: #b31d28;
|
|
||||||
|
|
||||||
color-scheme: light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
*::after {
|
*::after {
|
||||||
|
|||||||
204
web-app/template-styles/variables.css
Normal file
204
web-app/template-styles/variables.css
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
html {
|
||||||
|
--border-primary: 0.0625rem solid var(--color-border);
|
||||||
|
--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);
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
--bg-primary-h: /* BACKGROUND_COLOR_LIGHT_THEME_H */ 0;
|
||||||
|
--bg-primary-s: /* BACKGROUND_COLOR_LIGHT_THEME_S */ 0%;
|
||||||
|
--bg-primary-l: /* BACKGROUND_COLOR_LIGHT_THEME_L */ 100%;
|
||||||
|
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
||||||
|
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 5%));
|
||||||
|
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 10%));
|
||||||
|
--bg-blurred: hsla(
|
||||||
|
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) - 20%)
|
||||||
|
);
|
||||||
|
|
||||||
|
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 0%);
|
||||||
|
--color-text-invert: var(--bg-primary);
|
||||||
|
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 50%));
|
||||||
|
--color-accent: /* ACCENT_COLOR_LIGHT_THEME */ hsl(210 100% 30%);
|
||||||
|
--color-success: hsl(105 100% 30%);
|
||||||
|
--color-error: hsl(0 100% 30%);
|
||||||
|
|
||||||
|
--display-light: none;
|
||||||
|
--display-dark: initial;
|
||||||
|
|
||||||
|
--hl-bg: #fff;
|
||||||
|
--hl-color: #24292e;
|
||||||
|
--hl-keyword: #d73a49;
|
||||||
|
--hl-title: #6f42c1;
|
||||||
|
--hl-attr: #005cc5;
|
||||||
|
--hl-string: #032f62;
|
||||||
|
--hl-built-in: #e36209;
|
||||||
|
--hl-comment: #6a737d;
|
||||||
|
--hl-tag: #22863a;
|
||||||
|
--hl-section: #005cc5;
|
||||||
|
--hl-bullet: #735c0f;
|
||||||
|
--hl-emphasis: #24292e;
|
||||||
|
--hl-addition-bg: #f0fff4;
|
||||||
|
--hl-addition-text: #22863a;
|
||||||
|
--hl-deletion-bg: #ffeef0;
|
||||||
|
--hl-deletion-text: #b31d28;
|
||||||
|
|
||||||
|
color-scheme: light;
|
||||||
|
}
|
||||||
|
|
||||||
|
html:has(#toggle-theme:checked) {
|
||||||
|
--bg-primary-h: /* BACKGROUND_COLOR_DARK_THEME_H */ 0;
|
||||||
|
--bg-primary-s: /* BACKGROUND_COLOR_DARK_THEME_S */ 0%;
|
||||||
|
--bg-primary-l: /* BACKGROUND_COLOR_DARK_THEME_L */ 15%;
|
||||||
|
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
||||||
|
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 5%));
|
||||||
|
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 10%));
|
||||||
|
--bg-blurred: hsla(
|
||||||
|
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) + 20%)
|
||||||
|
);
|
||||||
|
|
||||||
|
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 100%);
|
||||||
|
--color-text-invert: var(--bg-primary);
|
||||||
|
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 50%));
|
||||||
|
--color-accent: /* ACCENT_COLOR_DARK_THEME */ hsl(210 100% 80%);
|
||||||
|
--color-success: hsl(105 100% 80%);
|
||||||
|
--color-error: hsl(0 100% 80%);
|
||||||
|
|
||||||
|
--display-light: initial;
|
||||||
|
--display-dark: none;
|
||||||
|
|
||||||
|
--hl-bg: #0d1117;
|
||||||
|
--hl-color: #c9d1d9;
|
||||||
|
--hl-keyword: #ff7b72;
|
||||||
|
--hl-title: #d2a8ff;
|
||||||
|
--hl-attr: #79c0ff;
|
||||||
|
--hl-string: #a5d6ff;
|
||||||
|
--hl-built-in: #ffa657;
|
||||||
|
--hl-comment: #8b949e;
|
||||||
|
--hl-tag: #7ee787;
|
||||||
|
--hl-section: #1f6feb;
|
||||||
|
--hl-bullet: #f2cc60;
|
||||||
|
--hl-emphasis: #c9d1d9;
|
||||||
|
--hl-addition-bg: #033a16;
|
||||||
|
--hl-addition-text: #aff5b4;
|
||||||
|
--hl-deletion-bg: #67060c;
|
||||||
|
--hl-deletion-text: #ffdcd7;
|
||||||
|
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
html {
|
||||||
|
--bg-primary-h: /* BACKGROUND_COLOR_DARK_THEME_H */ 0;
|
||||||
|
--bg-primary-s: /* BACKGROUND_COLOR_DARK_THEME_S */ 0%;
|
||||||
|
--bg-primary-l: /* BACKGROUND_COLOR_DARK_THEME_L */ 15%;
|
||||||
|
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
||||||
|
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 5%));
|
||||||
|
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 10%));
|
||||||
|
--bg-blurred: hsla(
|
||||||
|
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) + 20%)
|
||||||
|
);
|
||||||
|
|
||||||
|
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 100%);
|
||||||
|
--color-text-invert: var(--bg-primary);
|
||||||
|
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) + 50%));
|
||||||
|
--color-accent: /* ACCENT_COLOR_DARK_THEME */ hsl(210 100% 80%);
|
||||||
|
--color-success: hsl(105 100% 80%);
|
||||||
|
--color-error: hsl(0 100% 80%);
|
||||||
|
|
||||||
|
--display-light: initial;
|
||||||
|
--display-dark: none;
|
||||||
|
|
||||||
|
--hl-bg: #0d1117;
|
||||||
|
--hl-color: #c9d1d9;
|
||||||
|
--hl-keyword: #ff7b72;
|
||||||
|
--hl-title: #d2a8ff;
|
||||||
|
--hl-attr: #79c0ff;
|
||||||
|
--hl-string: #a5d6ff;
|
||||||
|
--hl-built-in: #ffa657;
|
||||||
|
--hl-comment: #8b949e;
|
||||||
|
--hl-tag: #7ee787;
|
||||||
|
--hl-section: #1f6feb;
|
||||||
|
--hl-bullet: #f2cc60;
|
||||||
|
--hl-emphasis: #c9d1d9;
|
||||||
|
--hl-addition-bg: #033a16;
|
||||||
|
--hl-addition-text: #aff5b4;
|
||||||
|
--hl-deletion-bg: #67060c;
|
||||||
|
--hl-deletion-text: #ffdcd7;
|
||||||
|
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
html:has(#toggle-theme:checked) {
|
||||||
|
--bg-primary-h: /* BACKGROUND_COLOR_LIGHT_THEME_H */ 0;
|
||||||
|
--bg-primary-s: /* BACKGROUND_COLOR_LIGHT_THEME_S */ 0%;
|
||||||
|
--bg-primary-l: /* BACKGROUND_COLOR_LIGHT_THEME_L */ 100%;
|
||||||
|
--bg-primary: hsl(var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l));
|
||||||
|
--bg-secondary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 5%));
|
||||||
|
--bg-tertiary: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 10%));
|
||||||
|
--bg-blurred: hsla(
|
||||||
|
var(--bg-primary-h) var(--bg-primary-s) var(--bg-primary-l) / calc(var(--bg-primary-l) - 20%)
|
||||||
|
);
|
||||||
|
|
||||||
|
--color-text: hsl(var(--bg-primary-h) var(--bg-primary-s) 0%);
|
||||||
|
--color-text-invert: var(--bg-primary);
|
||||||
|
--color-border: hsl(var(--bg-primary-h) var(--bg-primary-s) calc(var(--bg-primary-l) - 50%));
|
||||||
|
--color-accent: /* ACCENT_COLOR_LIGHT_THEME */ hsl(210 100% 30%);
|
||||||
|
--color-success: hsl(105 100% 30%);
|
||||||
|
--color-error: hsl(0 100% 30%);
|
||||||
|
|
||||||
|
--display-light: none;
|
||||||
|
--display-dark: initial;
|
||||||
|
|
||||||
|
--hl-bg: #fff;
|
||||||
|
--hl-color: #24292e;
|
||||||
|
--hl-keyword: #d73a49;
|
||||||
|
--hl-title: #6f42c1;
|
||||||
|
--hl-attr: #005cc5;
|
||||||
|
--hl-string: #032f62;
|
||||||
|
--hl-built-in: #e36209;
|
||||||
|
--hl-comment: #6a737d;
|
||||||
|
--hl-tag: #22863a;
|
||||||
|
--hl-section: #005cc5;
|
||||||
|
--hl-bullet: #735c0f;
|
||||||
|
--hl-emphasis: #24292e;
|
||||||
|
--hl-addition-bg: #f0fff4;
|
||||||
|
--hl-addition-text: #22863a;
|
||||||
|
--hl-deletion-bg: #ffeef0;
|
||||||
|
--hl-deletion-text: #b31d28;
|
||||||
|
|
||||||
|
color-scheme: light;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,7 +53,14 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByLabel("Title:").click();
|
await page.getByLabel("Title:").click();
|
||||||
await page.getByLabel("Title:").fill("Blog");
|
await page.getByLabel("Title:").fill("Blog");
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page.getByRole("button", { name: "Publish" }).click();
|
||||||
|
await page.getByLabel("Prefix:").click();
|
||||||
|
await page.getByLabel("Prefix:").fill("setup");
|
||||||
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
|
await page.goto("/");
|
||||||
await page.getByRole("button", { name: "Create website" }).click();
|
await page.getByRole("button", { name: "Create website" }).click();
|
||||||
await page.getByLabel("Type: BlogDocs").selectOption("Docs");
|
await page.getByLabel("Type: BlogDocs").selectOption("Docs");
|
||||||
await page.getByLabel("Title:").click();
|
await page.getByLabel("Title:").click();
|
||||||
@@ -146,7 +153,7 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.locator("li").filter({ hasText: "Blog" }).getByRole("button").first().click();
|
await page.locator("li").filter({ hasText: "Blog" }).getByRole("button").first().click();
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
||||||
} else {
|
} else {
|
||||||
await expect(page.getByText("Successfully updated website")).toBeVisible();
|
await expect(page.getByText("Successfully updated website")).toBeVisible();
|
||||||
@@ -179,6 +186,8 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
});
|
});
|
||||||
test("Update Home", async ({ page }) => {
|
test("Update Home", async ({ page }) => {
|
||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page.getByLabel("Description:").click();
|
||||||
|
await page.getByLabel("Description:").fill("Description");
|
||||||
await page.locator("#home").getByRole("button", { name: "Submit" }).click();
|
await page.locator("#home").getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -440,12 +449,37 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByRole("link", { name: "Publish" }).click();
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
await page.getByRole("button", { name: "Publish" }).click();
|
await page.getByRole("button", { name: "Publish" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
||||||
} else {
|
} else {
|
||||||
await expect(page.getByText("Successfully published website")).toBeVisible();
|
await expect(page.getByText("Successfully published website")).toBeVisible();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
test("Set custom domain prefix", async ({ page }) => {
|
||||||
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page.getByLabel("Prefix:").click();
|
||||||
|
await page.getByLabel("Prefix:").fill("blog");
|
||||||
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
|
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
||||||
|
} else {
|
||||||
|
await expect(page.getByText("Successfully created/updated")).toBeVisible();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
test("Remove custom domain prefix", async ({ page }) => {
|
||||||
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page.getByRole("button", { name: "Delete" }).click();
|
||||||
|
await page.getByRole("button", { name: "Delete domain prefix" }).click();
|
||||||
|
|
||||||
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
|
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
||||||
|
} else {
|
||||||
|
await expect(page.getByText("Successfully deleted domain")).toBeVisible();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ test.describe.serial("Website tests", () => {
|
|||||||
|
|
||||||
test("Home", async ({ authenticatedPage: page }) => {
|
test("Home", async ({ authenticatedPage: page }) => {
|
||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page.getByLabel("Description:").click();
|
||||||
|
await page.getByLabel("Description:").fill("Description");
|
||||||
await page.getByLabel("Main content:").click();
|
await page.getByLabel("Main content:").click();
|
||||||
await page.getByLabel("Main content:").press("Control+a");
|
await page.getByLabel("Main content:").press("Control+a");
|
||||||
await page.getByLabel("Main content:").fill("## Some new content comes here");
|
await page.getByLabel("Main content:").fill("## Some new content comes here");
|
||||||
@@ -347,6 +349,38 @@ test.describe.serial("Website tests", () => {
|
|||||||
await expect(page.getByText("Your website is published at")).toBeVisible();
|
await expect(page.getByText("Your website is published at")).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Set custom domain prefixes", async ({ authenticatedPage: page }) => {
|
||||||
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page.getByLabel("Prefix:").click();
|
||||||
|
await page.getByLabel("Prefix:").fill("blog");
|
||||||
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
await expect(page.getByText("Successfully created/updated")).toBeVisible();
|
||||||
|
|
||||||
|
await page.goto("/");
|
||||||
|
await page.getByRole("link", { name: "Documentation" }).click();
|
||||||
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page.getByLabel("Prefix:").click();
|
||||||
|
await page.getByLabel("Prefix:").fill("docs");
|
||||||
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
await expect(page.getByText("Successfully created/updated")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Remove custom domain prefixes", async ({ authenticatedPage: page }) => {
|
||||||
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page.getByRole("button", { name: "Delete" }).click();
|
||||||
|
await page.getByRole("button", { name: "Delete domain prefix" }).click();
|
||||||
|
await expect(page.getByText("Successfully deleted domain")).toBeVisible();
|
||||||
|
|
||||||
|
await page.goto("/");
|
||||||
|
await page.getByRole("link", { name: "Documentation" }).click();
|
||||||
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page.getByRole("button", { name: "Delete" }).click();
|
||||||
|
await page.getByRole("button", { name: "Delete domain prefix" }).click();
|
||||||
|
await expect(page.getByText("Successfully deleted domain")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
test("Delete websites", async ({ authenticatedPage: page }) => {
|
test("Delete websites", async ({ authenticatedPage: page }) => {
|
||||||
await page.getByRole("button", { name: "Delete" }).nth(1).click();
|
await page.getByRole("button", { name: "Delete" }).nth(1).click();
|
||||||
await page.getByRole("button", { name: "Delete website" }).click();
|
await page.getByRole("button", { name: "Delete website" }).click();
|
||||||
|
|||||||
Reference in New Issue
Block a user