diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.html | 199 | ||||
| -rw-r--r-- | src/components/card-v4.svelte | 15 | ||||
| -rw-r--r-- | src/global.d.ts | 16 | ||||
| -rw-r--r-- | src/hooks.server.ts | 62 | ||||
| -rw-r--r-- | src/i18n/en/index.ts | 8 | ||||
| -rw-r--r-- | src/i18n/formatters.ts | 11 | ||||
| -rw-r--r-- | src/i18n/nb/index.ts | 8 | ||||
| -rw-r--r-- | src/index.test.ts | 6 | ||||
| -rw-r--r-- | src/lib/sanity-client.ts | 14 | ||||
| -rw-r--r-- | src/lib/utils.ts | 32 | ||||
| -rw-r--r-- | src/params/lang.ts | 8 | ||||
| -rw-r--r-- | src/routes/+layout.server.ts | 8 | ||||
| -rw-r--r-- | src/routes/+layout.svelte | 3 | ||||
| -rw-r--r-- | src/routes/+layout.ts | 22 | ||||
| -rw-r--r-- | src/routes/[lang=lang]/+page.server.ts | 54 | ||||
| -rw-r--r-- | src/routes/[lang=lang]/+page.svelte | 2 | ||||
| -rw-r--r-- | src/routes/[lang=lang]/+page.ts | 30 | ||||
| -rw-r--r-- | src/routes/[lang=lang]/sections/products.svelte | 17 |
18 files changed, 265 insertions, 250 deletions
diff --git a/src/app.html b/src/app.html index ef0bfa1..68797f1 100644 --- a/src/app.html +++ b/src/app.html @@ -1,122 +1,121 @@ <!DOCTYPE html> <html lang="%lang%"> -<head> - <meta charset="utf-8" /> - <link rel="icon" href="%sveltekit.assets%/favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style> - /* reset */ - *, - *::after, - *::before { - box-sizing: border-box; - } - - * { - font: inherit; - margin: 0; - padding: 0; - border: 0; - } - - body { - background-color: hsl(0, 0%, 100%); - font-family: system-ui, sans-serif; - color: hsl(230, 7%, 23%); - font-size: 1rem; - } - - h1, - h2, - h3, - h4 { - line-height: 1.2; - color: hsl(230, 13%, 9%); - font-weight: 700; - } - - h1 { - font-size: 2.0736rem; - } - - h2 { - font-size: 1.728rem; - } + <head> + <meta charset="utf-8" /> + <link rel="icon" href="%sveltekit.assets%/favicon.png" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <style> + /* reset */ + *, + *::after, + *::before { + box-sizing: border-box; + } - h3 { - font-size: 1.25rem; - } + * { + font: inherit; + margin: 0; + padding: 0; + border: 0; + } - h4 { - font-size: 1.2rem; - } + body { + background-color: hsl(0, 0%, 100%); + font-family: system-ui, sans-serif; + color: hsl(230, 7%, 23%); + font-size: 1rem; + } - ol, - ul, - menu { - list-style: none; - } + h1, + h2, + h3, + h4 { + line-height: 1.2; + color: hsl(230, 13%, 9%); + font-weight: 700; + } - button, - input, - textarea, - select { - background-color: transparent; - border-radius: 0; - color: inherit; - line-height: inherit; - appearance: none; - } + h1 { + font-size: 2.0736rem; + } - textarea { - resize: vertical; - overflow: auto; - vertical-align: top; - } + h2 { + font-size: 1.728rem; + } - a { - color: hsl(250, 84%, 54%); - } + h3 { + font-size: 1.25rem; + } - table { - border-collapse: collapse; - border-spacing: 0; - } + h4 { + font-size: 1.2rem; + } - img, - video, - svg { - display: block; - max-width: 100%; - } + ol, + ul, + menu { + list-style: none; + } - @media (min-width: 64rem) { - body { - font-size: 1.25rem; + button, + input, + textarea, + select { + background-color: transparent; + border-radius: 0; + color: inherit; + line-height: inherit; + appearance: none; } - h1 { - font-size: 3.051rem; + textarea { + resize: vertical; + overflow: auto; + vertical-align: top; } - h2 { - font-size: 2.44rem; + a { + color: hsl(250, 84%, 54%); } - h3 { - font-size: 1.75rem; + table { + border-collapse: collapse; + border-spacing: 0; } - h4 { - font-size: 1.5625rem; + img, + video, + svg { + display: block; + max-width: 100%; } - } - </style> - %sveltekit.head% -</head> -<body> - <div>%sveltekit.body%</div> -</body> + @media (min-width: 64rem) { + body { + font-size: 1.25rem; + } + + h1 { + font-size: 3.051rem; + } + + h2 { + font-size: 2.44rem; + } + + h3 { + font-size: 1.75rem; + } + + h4 { + font-size: 1.5625rem; + } + } + </style> + %sveltekit.head% + </head> -</html>
\ No newline at end of file + <body> + <div>%sveltekit.body%</div> + </body> +</html> diff --git a/src/components/card-v4.svelte b/src/components/card-v4.svelte index d067357..ff35492 100644 --- a/src/components/card-v4.svelte +++ b/src/components/card-v4.svelte @@ -1,13 +1,20 @@ <script lang="ts"> - export let title; - export let description; + import { PortableText } from "@portabletext/svelte"; + import type { InputValue } from "@portabletext/svelte/ptTypes"; + + export let title: string | undefined; + export let description: string | undefined | InputValue; </script> <div class="card"> <div class="p-6"> - <h3 class="mt-0">I have a dream</h3> + <h3 class="mt-0">{title}</h3> <p class="text-contrast-medium mt-3 mx-0 mb-4"> - Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quia minus culpa commodi. + {#if typeof description === "string"} + {description} + {:else} + <PortableText value={description} /> + {/if} </p> <div class="flex flex-wrap gap-3"> <a href="#0" class="btn btn--subtle">Learn more</a> diff --git a/src/global.d.ts b/src/global.d.ts index e49922a..075c69d 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,13 +1,13 @@ /// <reference types="@sveltejs/kit" /> -type Locales = import('$i18n/i18n-types').Locales -type TranslationFunctions = import('$i18n/i18n-types').TranslationFunctions +type Locales = import("$i18n/i18n-types").Locales; +type TranslationFunctions = import("$i18n/i18n-types").TranslationFunctions; declare namespace App { - interface Locals { - locale: Locales - LL: TranslationFunctions - } + interface Locals { + locale: Locales; + LL: TranslationFunctions; + } - // interface Platform { } -}
\ No newline at end of file + // interface Platform { } +} diff --git a/src/hooks.server.ts b/src/hooks.server.ts index ddd9342..1c8c988 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,43 +1,41 @@ -import { detectLocale, i18n, isLocale } from '$i18n/i18n-util' -import { loadAllLocales } from '$i18n/i18n-util.sync' -import type { Handle, RequestEvent } from '@sveltejs/kit' -import { initAcceptLanguageHeaderDetector } from 'typesafe-i18n/detectors' +import { detectLocale, i18n, isLocale } from "$i18n/i18n-util"; +import { loadAllLocales } from "$i18n/i18n-util.sync"; +import type { Handle, RequestEvent } from "@sveltejs/kit"; +import { initAcceptLanguageHeaderDetector } from "typesafe-i18n/detectors"; -loadAllLocales() -const L = i18n() +loadAllLocales(); +const L = i18n(); export const handle: Handle = async ({ event, resolve }) => { - // read language slug - const [, lang] = event.url.pathname.split('/') + // read language slug + const [, lang] = event.url.pathname.split("/"); - // redirect to base locale if no locale slug was found - if (!lang) { - const locale = getPreferredLocale(event) + // redirect to base locale if no locale slug was found + if (!lang) { + const locale = getPreferredLocale(event); - return new Response(null, { - status: 302, - headers: { Location: `/${locale}` }, - }) - } + return new Response(null, { + status: 302, + headers: { Location: `/${locale}` }, + }); + } - // if slug is not a locale, use base locale (e.g. api endpoints) - const locale = isLocale(lang) ? (lang as Locales) : getPreferredLocale(event) - const LL = L[locale] + // if slug is not a locale, use base locale (e.g. api endpoints) + const locale = isLocale(lang) ? (lang as Locales) : getPreferredLocale(event); + const LL = L[locale]; - // bind locale and translation functions to current request - event.locals.locale = locale - event.locals.LL = LL + // bind locale and translation functions to current request + event.locals.locale = locale; + event.locals.LL = LL; - console.info(LL.log({ fileName: 'hooks.server.ts' })) - - // replace html lang attribute with correct language - return resolve(event, { transformPageChunk: ({ html }) => html.replace('%lang%', locale) }) -} + // replace html lang attribute with correct language + return resolve(event, { transformPageChunk: ({ html }) => html.replace("%lang%", locale) }); +}; const getPreferredLocale = ({ request }: RequestEvent) => { - // detect the preferred language the user has configured in his browser - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language - const acceptLanguageDetector = initAcceptLanguageHeaderDetector(request) + // detect the preferred language the user has configured in his browser + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language + const acceptLanguageDetector = initAcceptLanguageHeaderDetector(request); - return detectLocale(acceptLanguageDetector) -}
\ No newline at end of file + return detectLocale(acceptLanguageDetector); +}; diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index 796f4a5..a6b79c2 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -1,13 +1,13 @@ -import type { BaseTranslation } from '../i18n-types' +import type { BaseTranslation } from "../i18n-types"; const en = { contact: { title: "Contact us", addressTitle: "Address", emailTitle: "Email", - phoneTitle: "Phone" + phoneTitle: "Phone", }, homeTitle: "Home", -} satisfies BaseTranslation +} satisfies BaseTranslation; -export default en +export default en; diff --git a/src/i18n/formatters.ts b/src/i18n/formatters.ts index 78734f9..b1fd5a3 100644 --- a/src/i18n/formatters.ts +++ b/src/i18n/formatters.ts @@ -1,11 +1,10 @@ -import type { FormattersInitializer } from 'typesafe-i18n' -import type { Locales, Formatters } from './i18n-types' +import type { FormattersInitializer } from "typesafe-i18n"; +import type { Locales, Formatters } from "./i18n-types"; export const initFormatters: FormattersInitializer<Locales, Formatters> = (locale: Locales) => { - const formatters: Formatters = { // add your formatter functions here - } + }; - return formatters -} + return formatters; +}; diff --git a/src/i18n/nb/index.ts b/src/i18n/nb/index.ts index 9e13fba..5206b07 100644 --- a/src/i18n/nb/index.ts +++ b/src/i18n/nb/index.ts @@ -1,13 +1,13 @@ -import type { Translation } from '../i18n-types' +import type { Translation } from "../i18n-types"; const nb = { contact: { title: "Kontakt oss", addressTitle: "Adresse", emailTitle: "E-postadresse", - phoneTitle: "Telefon" + phoneTitle: "Telefon", }, homeTitle: "Hjem", -} satisfies Translation +} satisfies Translation; -export default nb +export default nb; diff --git a/src/index.test.ts b/src/index.test.ts index e07cbbd..808401e 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,7 +1,7 @@ -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from "vitest"; -describe('sum test', () => { - it('adds 1 + 2 to equal 3', () => { +describe("sum test", () => { + it("adds 1 + 2 to equal 3", () => { expect(1 + 2).toBe(3); }); }); diff --git a/src/lib/sanity-client.ts b/src/lib/sanity-client.ts index 96253ca..7aa868b 100644 --- a/src/lib/sanity-client.ts +++ b/src/lib/sanity-client.ts @@ -1,9 +1,9 @@ import { env } from "$env/dynamic/private"; -import createSanityClient from "@sanity/client"; +import { createClient } from "@sanity/client"; -export const sanity = createSanityClient({ - projectId: env.SANITY_STUDIO_API_PROJECT_ID, - dataset: env.SANITY_STUDIO_API_DATASET, - apiVersion: "2022-03-24", - useCdn: true, -});
\ No newline at end of file +export const sanity = createClient({ + projectId: env.SANITY_STUDIO_API_PROJECT_ID, + dataset: env.SANITY_STUDIO_API_DATASET, + apiVersion: "2022-03-24", + useCdn: true, +}); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 4ec8b01..f7c040d 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -6,22 +6,22 @@ // Otherwise (default) the URL relative to the base is returned. // e.g. https://mywebsite.com/en/blog/article-1 => /de/blog/article-1 export const replaceLocaleInUrl = (url: URL, locale: string, full = false): string => { - const [, , ...rest] = url.pathname.split('/') - const new_pathname = `/${[locale, ...rest].join('/')}` - if (!full) { - return `${new_pathname}${url.search}` - } - const newUrl = new URL(url.toString()) - newUrl.pathname = new_pathname - return newUrl.toString() -} + const [, , ...rest] = url.pathname.split("/"); + const new_pathname = `/${[locale, ...rest].join("/")}`; + if (!full) { + return `${new_pathname}${url.search}`; + } + const newUrl = new URL(url.toString()); + newUrl.pathname = new_pathname; + return newUrl.toString(); +}; export function fromLocalizedString(localizedString: string | object, locale: Locales) { - if (typeof localizedString === "string") return localizedString; - // @ts-ignore - if (localizedString[locale]) return localizedString[locale]; - // @ts-ignore - if (localizedString["nb"]) return localizedString["nb"]; - // @ts-ignore - if (localizedString["en"]) return localizedString["en"]; + if (typeof localizedString === "string") return localizedString; + // @ts-ignore + if (localizedString[locale]) return localizedString[locale]; + // @ts-ignore + if (localizedString["nb"]) return localizedString["nb"]; + // @ts-ignore + if (localizedString["en"]) return localizedString["en"]; } diff --git a/src/params/lang.ts b/src/params/lang.ts index 5f0b857..5f7e2a2 100644 --- a/src/params/lang.ts +++ b/src/params/lang.ts @@ -1,7 +1,7 @@ -import type { ParamMatcher } from '@sveltejs/kit' -import { isLocale } from '$i18n/i18n-util' +import type { ParamMatcher } from "@sveltejs/kit"; +import { isLocale } from "$i18n/i18n-util"; // only accept valid languages as a segment in the URL export const match: ParamMatcher = (param) => { - return isLocale(param) -}
\ No newline at end of file + return isLocale(param); +}; diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index fc087d8..0eef9d3 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -1,6 +1,6 @@ -import type { LayoutServerLoad } from './$types' +import type { LayoutServerLoad } from "./$types"; export const load: LayoutServerLoad = ({ locals: { locale, LL } }) => { - // pass locale information from "server-context" to "shared server + client context" - return { locale } -} + // pass locale information from "server-context" to "shared server + client context" + return { locale }; +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index af29844..97aa8cf 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,12 +1,9 @@ <script lang="ts"> import { page } from "$app/stores"; import "../app.postcss"; - import type { LayoutData } from "./$types"; import { locales, baseLocale } from "$i18n/i18n-util"; import { replaceLocaleInUrl } from "$lib/utils"; import Header from "./parts/header.svelte"; - - export let data: LayoutData; </script> <svelte:head> diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 5a78ab1..ab3b2cc 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1,14 +1,14 @@ -import type { LayoutLoad } from './$types' -import { loadLocaleAsync } from '$i18n/i18n-util.async' -import { setLocale } from '$i18n/i18n-svelte' +import type { LayoutLoad } from "./$types"; +import { loadLocaleAsync } from "$i18n/i18n-util.async"; +import { setLocale } from "$i18n/i18n-svelte"; export const load = (async ({ data: { locale } }) => { - // load dictionary into memory - await loadLocaleAsync(locale) + // load dictionary into memory + await loadLocaleAsync(locale); - // if you need to output a localized string in a `load` function, - // you always need to call `setLocale` right before you access the `LL` store - setLocale(locale) - // pass locale to the "rendering context" - return { locale } -}) satisfies LayoutLoad<{ locale: Locales }>;
\ No newline at end of file + // if you need to output a localized string in a `load` function, + // you always need to call `setLocale` right before you access the `LL` store + setLocale(locale); + // pass locale to the "rendering context" + return { locale }; +}) satisfies LayoutLoad<{ locale: Locales }>; diff --git a/src/routes/[lang=lang]/+page.server.ts b/src/routes/[lang=lang]/+page.server.ts index a647cfe..c2284ee 100644 --- a/src/routes/[lang=lang]/+page.server.ts +++ b/src/routes/[lang=lang]/+page.server.ts @@ -1,29 +1,31 @@ -import { sanity } from '$lib/sanity-client'; -import type { PageServerLoad } from './$types'; +import { sanity } from "$lib/sanity-client"; +import type { PageServerLoad } from "./$types"; import groq from "groq"; -import type { ContactModel } from './sections/contact.svelte'; -import { fromLocalizedString } from '$lib/utils'; -import type { HeroModel } from './sections/hero.svelte'; -import type { DescriptionModel } from './sections/description.svelte'; +import type { ContactModel } from "./sections/contact.svelte"; +import { fromLocalizedString } from "$lib/utils"; +import type { HeroModel } from "./sections/hero.svelte"; +import type { DescriptionModel } from "./sections/description.svelte"; export const load = (async ({ locals }) => { - const contactSection = await sanity.fetch(groq`*[_type == "contact"][0]`); - const heroSection = await sanity.fetch(groq`*[_type == "hero"][0]`); - const descriptionSection = await sanity.fetch(groq`*[_type == "description"][0]`); - return { - contact: { - phone: fromLocalizedString(contactSection.phone, locals.locale), - email: fromLocalizedString(contactSection.email, locals.locale), - phoneHours: fromLocalizedString(contactSection.phoneHours, locals.locale), - addressLines: contactSection.addressLines.map((el: string | object) => fromLocalizedString(el, locals.locale)), - } as ContactModel, - hero: { - title: heroSection.title, - content: heroSection.content - } as HeroModel, - description: { - title: descriptionSection.title, - content: descriptionSection.content - } as DescriptionModel - }; -}) satisfies PageServerLoad;
\ No newline at end of file + const contactSection = await sanity.fetch(groq`*[_type == "contact"][0]`); + const heroSection = await sanity.fetch(groq`*[_type == "hero"][0]`); + const descriptionSection = await sanity.fetch(groq`*[_type == "description"][0]`); + const products = await sanity.fetch(groq`*[_type == "product"]`); + return { + contact: { + phone: fromLocalizedString(contactSection.phone, locals.locale), + email: fromLocalizedString(contactSection.email, locals.locale), + phoneHours: fromLocalizedString(contactSection.phoneHours, locals.locale), + addressLines: contactSection.addressLines.map((el: string | object) => fromLocalizedString(el, locals.locale)), + } as ContactModel, + hero: { + title: heroSection.title, + content: heroSection.content, + } as HeroModel, + description: { + title: descriptionSection.title, + content: descriptionSection.content, + } as DescriptionModel, + products: products + }; +}) satisfies PageServerLoad; diff --git a/src/routes/[lang=lang]/+page.svelte b/src/routes/[lang=lang]/+page.svelte index 325f085..f2028c6 100644 --- a/src/routes/[lang=lang]/+page.svelte +++ b/src/routes/[lang=lang]/+page.svelte @@ -12,4 +12,4 @@ <Hero model={data.hero} /> <Description model={data.description} /> <Contact model={data.contact} /> -<Products model={data.products} />
\ No newline at end of file +<Products model={data.products} /> diff --git a/src/routes/[lang=lang]/+page.ts b/src/routes/[lang=lang]/+page.ts index 1ef0b57..fa95472 100644 --- a/src/routes/[lang=lang]/+page.ts +++ b/src/routes/[lang=lang]/+page.ts @@ -1,18 +1,18 @@ -import type { PageLoad } from './$types'; -import LL, { setLocale } from '$i18n/i18n-svelte' -import { get } from 'svelte/store' +import type { PageLoad } from "./$types"; +import LL, { setLocale } from "$i18n/i18n-svelte"; +import { get } from "svelte/store"; export const load = (async ({ parent, data }) => { - // wait for `+layout.ts` to load dictionary and pass locale information - const { locale } = await parent() + // wait for `+layout.ts` to load dictionary and pass locale information + const { locale } = await parent(); - // if you need to output a localized string in a `load` function, - // you always need to call `setLocale` right before you access the `LL` store - setLocale(locale) - // get the translation functions value from the store - const $LL = get(LL) - return { - title: $LL.homeTitle(), - ...data - } -}) satisfies PageLoad;
\ No newline at end of file + // if you need to output a localized string in a `load` function, + // you always need to call `setLocale` right before you access the `LL` store + setLocale(locale); + // get the translation functions value from the store + const $LL = get(LL); + return { + title: $LL.homeTitle(), + ...data, + }; +}) satisfies PageLoad; diff --git a/src/routes/[lang=lang]/sections/products.svelte b/src/routes/[lang=lang]/sections/products.svelte index 4e10b6f..816e276 100644 --- a/src/routes/[lang=lang]/sections/products.svelte +++ b/src/routes/[lang=lang]/sections/products.svelte @@ -13,6 +13,8 @@ </script> <script lang="ts"> + import CardV4 from "$components/card-v4.svelte"; + export let model: ProductsModel; let visible = true; @@ -24,5 +26,16 @@ </script> {#if visible} - -{/if}
\ No newline at end of file + <div class="wrapper"> + {#each model.products as product} + <CardV4 description={product.description} title={product.title} /> + {/each} + </div> +{/if} + +<style lang="postcss"> + .wrapper { + display: grid; + grid-template-columns: repeat(50%); + } +</style> |
