mirror of
https://github.com/youwen5/site.git
synced 2024-11-24 17:33:51 -08:00
feat: add test blog post with katex support
This commit is contained in:
parent
b60fc3d19c
commit
b9affbbb6d
96 changed files with 783 additions and 41 deletions
|
@ -13,6 +13,6 @@ bun install
|
|||
bun dev
|
||||
|
||||
# for production:
|
||||
bun build
|
||||
bun start
|
||||
bun run build
|
||||
bun preview
|
||||
```
|
||||
|
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -45,8 +45,11 @@
|
|||
"@fontsource/geist-sans": "^5.0.2",
|
||||
"bits-ui": "^0.21.2",
|
||||
"clsx": "^2.1.0",
|
||||
"marked": "^12.0.1",
|
||||
"marked-katex-extension": "^5.0.1",
|
||||
"mode-watcher": "^0.3.0",
|
||||
"svelte-radix": "^1.1.0",
|
||||
"svelte-sonner": "^0.3.21",
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"tailwind-variants": "^0.2.1"
|
||||
}
|
||||
|
|
0
src/globals.d.ts
vendored
Normal file
0
src/globals.d.ts
vendored
Normal file
|
@ -1,18 +1,13 @@
|
|||
<script>
|
||||
import { GithubLogo } from 'svelte-radix';
|
||||
import Separator from './ui/separator/separator.svelte';
|
||||
import Socials from './Socials.svelte';
|
||||
</script>
|
||||
|
||||
<footer class="h-24 px-2 mb-4 text-sm md:text-md xl:text-lg">
|
||||
<footer class="h-24 px-2 mb-8 text-sm md:text-md xl:text-lg">
|
||||
<Separator class="mb-4" />
|
||||
<div class="flex justify-center flex-col gap-4">
|
||||
<div class="flex justify-around gap-4">
|
||||
<a
|
||||
href="https://github.com/couscousdude"
|
||||
target="_blank"
|
||||
class="dark:brightness-75 dark:hover:brightness-100"><GithubLogo /></a
|
||||
>
|
||||
</div>
|
||||
<Socials center />
|
||||
<p class="text-zinc-400 dark:text-zinc-700 text-center">
|
||||
© 2024 Youwen Wu | Built with <a
|
||||
href="https://kit.svelte.dev"
|
||||
|
|
57
src/lib/components/Gpg.svelte
Normal file
57
src/lib/components/Gpg.svelte
Normal file
|
@ -0,0 +1,57 @@
|
|||
<script lang="ts">
|
||||
import * as AlertDialog from '$lib/components/ui/alert-dialog';
|
||||
import { onMount } from 'svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import ScrollArea from './ui/scroll-area/scroll-area.svelte';
|
||||
|
||||
let gpg: Promise<string>;
|
||||
|
||||
async function getGpg() {
|
||||
const res = await fetch(`/youwen.gpg`);
|
||||
const text = await res.text();
|
||||
|
||||
if (res.ok) {
|
||||
return text;
|
||||
} else {
|
||||
throw new Error(text);
|
||||
}
|
||||
}
|
||||
async function copyGpg() {
|
||||
try {
|
||||
const text = await gpg;
|
||||
navigator.clipboard.writeText(text);
|
||||
toast('Copied GPG key to clipboard');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toast('Failed to copy GPG key to clipboard');
|
||||
}
|
||||
}
|
||||
onMount(() => {
|
||||
gpg = getGpg();
|
||||
});
|
||||
</script>
|
||||
|
||||
<AlertDialog.Root>
|
||||
<AlertDialog.Trigger><slot /></AlertDialog.Trigger>
|
||||
<AlertDialog.Content>
|
||||
<AlertDialog.Header>
|
||||
<AlertDialog.Title>GPG Key</AlertDialog.Title>
|
||||
<AlertDialog.Description class="flex justify-center">
|
||||
{#await gpg then text}
|
||||
<ScrollArea class="max-h-60 mb-4 max-w-60" orientation="both">
|
||||
<p>{text}</p>
|
||||
</ScrollArea>
|
||||
{:catch}
|
||||
<p class="text-destructive">Couldn't fetch GPG key.</p>
|
||||
{/await}
|
||||
</AlertDialog.Description>
|
||||
</AlertDialog.Header>
|
||||
<AlertDialog.Footer class="gap-1">
|
||||
<a href="/youwen.gpg" download>
|
||||
<AlertDialog.Action>Download</AlertDialog.Action>
|
||||
</a>
|
||||
<AlertDialog.Action on:click={copyGpg}>Copy</AlertDialog.Action>
|
||||
<AlertDialog.Cancel>Close</AlertDialog.Cancel>
|
||||
</AlertDialog.Footer>
|
||||
</AlertDialog.Content>
|
||||
</AlertDialog.Root>
|
|
@ -25,7 +25,7 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<nav class="h-20 bg-background bg-opacity-50 backdrop-blur-md fixed w-full">
|
||||
<nav class="h-20 bg-background bg-opacity-50 backdrop-blur-md fixed w-full z-50">
|
||||
<div class="container mx-auto flex justify-between items-center h-full gap-4">
|
||||
{#if current === 'blog'}
|
||||
<Coredump height="95%" href="/blog" />
|
||||
|
|
63
src/lib/components/Socials.svelte
Normal file
63
src/lib/components/Socials.svelte
Normal file
|
@ -0,0 +1,63 @@
|
|||
<script>
|
||||
import {
|
||||
InstagramLogo,
|
||||
TwitterLogo,
|
||||
GithubLogo,
|
||||
LinkedinLogo,
|
||||
DiscordLogo,
|
||||
EnvelopeClosed
|
||||
} from 'svelte-radix';
|
||||
import * as Popover from '$lib/components/ui/popover';
|
||||
|
||||
export let center = false;
|
||||
|
||||
import Button from './ui/button/button.svelte';
|
||||
import PopoverContent from './ui/popover/popover-content.svelte';
|
||||
</script>
|
||||
|
||||
<div class="flex gap-2 mt-2" class:justify-center={center}>
|
||||
<Button variant="ghost" size="icon" href="https://github.com/couscousdude">
|
||||
<GithubLogo />
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" href="https://www.instagram.com/uncle_uwon/"
|
||||
><InstagramLogo /></Button
|
||||
>
|
||||
<Button variant="ghost" size="icon" href="https://twitter.com/couscousdude"
|
||||
><TwitterLogo /></Button
|
||||
>
|
||||
<Button variant="ghost" size="icon" href="https://www.linkedin.com/in/youwen-wu-306221288/>">
|
||||
<LinkedinLogo />
|
||||
</Button>
|
||||
<Popover.Root>
|
||||
<Popover.Trigger>
|
||||
<Button variant="ghost" size="icon">
|
||||
<DiscordLogo />
|
||||
</Button>
|
||||
</Popover.Trigger>
|
||||
<Popover.Content>
|
||||
Discord (for some reason) doesn't support direct links to profiles. You can find me on discord
|
||||
with my username, <strong>@couscousdude</strong>.
|
||||
</Popover.Content>
|
||||
</Popover.Root>
|
||||
<Popover.Root>
|
||||
<Popover.Trigger>
|
||||
<Button variant="ghost" size="icon">
|
||||
<EnvelopeClosed />
|
||||
</Button>
|
||||
</Popover.Trigger>
|
||||
<Popover.Content>
|
||||
<p>
|
||||
You can reach my Gmail at <a class="text-link" href="mailto:youwenw@gmail.com"
|
||||
>youwenw@gmail.com</a
|
||||
>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
Or, if you prefer, you can securely email me on Protonmail at <a
|
||||
class="text-link"
|
||||
href="mailto:youwenw@protonmail.com">youwenw@protonmail.com</a
|
||||
>
|
||||
</p>
|
||||
</Popover.Content>
|
||||
</Popover.Root>
|
||||
</div>
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
import { buttonVariants } from "$lib/components/ui/button/index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = AlertDialogPrimitive.ActionProps;
|
||||
type $$Events = AlertDialogPrimitive.ActionEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<AlertDialogPrimitive.Action
|
||||
class={cn(buttonVariants(), className)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
let:builder
|
||||
>
|
||||
<slot {builder} />
|
||||
</AlertDialogPrimitive.Action>
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
import { buttonVariants } from "$lib/components/ui/button/index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = AlertDialogPrimitive.CancelProps;
|
||||
type $$Events = AlertDialogPrimitive.CancelEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<AlertDialogPrimitive.Cancel
|
||||
class={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
let:builder
|
||||
>
|
||||
<slot {builder} />
|
||||
</AlertDialogPrimitive.Cancel>
|
|
@ -0,0 +1,27 @@
|
|||
<script lang="ts">
|
||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
import * as AlertDialog from "./index.js";
|
||||
import { cn, flyAndScale } from "$lib/utils.js";
|
||||
|
||||
type $$Props = AlertDialogPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let transition: $$Props["transition"] = flyAndScale;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<AlertDialog.Portal>
|
||||
<AlertDialog.Overlay />
|
||||
<AlertDialogPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg sm:rounded-lg md:w-full",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</AlertDialogPrimitive.Content>
|
||||
</AlertDialog.Portal>
|
|
@ -0,0 +1,16 @@
|
|||
<script lang="ts">
|
||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = AlertDialogPrimitive.DescriptionProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<AlertDialogPrimitive.Description
|
||||
class={cn("text-sm text-muted-foreground", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</AlertDialogPrimitive.Description>
|
|
@ -0,0 +1,16 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div class={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...$$restProps}>
|
||||
<slot />
|
||||
</div>
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
import { fade } from "svelte/transition";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = AlertDialogPrimitive.OverlayProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let transition: $$Props["transition"] = fade;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = {
|
||||
duration: 150,
|
||||
};
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<AlertDialogPrimitive.Overlay
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm", className)}
|
||||
{...$$restProps}
|
||||
/>
|
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
|
||||
type $$Props = AlertDialogPrimitive.PortalProps;
|
||||
</script>
|
||||
|
||||
<AlertDialogPrimitive.Portal {...$$restProps}>
|
||||
<slot />
|
||||
</AlertDialogPrimitive.Portal>
|
14
src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
Normal file
14
src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
Normal file
|
@ -0,0 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = AlertDialogPrimitive.TitleProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let level: $$Props["level"] = "h3";
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<AlertDialogPrimitive.Title class={cn("text-lg font-semibold", className)} {level} {...$$restProps}>
|
||||
<slot />
|
||||
</AlertDialogPrimitive.Title>
|
40
src/lib/components/ui/alert-dialog/index.ts
Normal file
40
src/lib/components/ui/alert-dialog/index.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
|
||||
|
||||
import Title from "./alert-dialog-title.svelte";
|
||||
import Action from "./alert-dialog-action.svelte";
|
||||
import Cancel from "./alert-dialog-cancel.svelte";
|
||||
import Portal from "./alert-dialog-portal.svelte";
|
||||
import Footer from "./alert-dialog-footer.svelte";
|
||||
import Header from "./alert-dialog-header.svelte";
|
||||
import Overlay from "./alert-dialog-overlay.svelte";
|
||||
import Content from "./alert-dialog-content.svelte";
|
||||
import Description from "./alert-dialog-description.svelte";
|
||||
|
||||
const Root = AlertDialogPrimitive.Root;
|
||||
const Trigger = AlertDialogPrimitive.Trigger;
|
||||
|
||||
export {
|
||||
Root,
|
||||
Title,
|
||||
Action,
|
||||
Cancel,
|
||||
Portal,
|
||||
Footer,
|
||||
Header,
|
||||
Trigger,
|
||||
Overlay,
|
||||
Content,
|
||||
Description,
|
||||
//
|
||||
Root as AlertDialog,
|
||||
Title as AlertDialogTitle,
|
||||
Action as AlertDialogAction,
|
||||
Cancel as AlertDialogCancel,
|
||||
Portal as AlertDialogPortal,
|
||||
Footer as AlertDialogFooter,
|
||||
Header as AlertDialogHeader,
|
||||
Trigger as AlertDialogTrigger,
|
||||
Overlay as AlertDialogOverlay,
|
||||
Content as AlertDialogContent,
|
||||
Description as AlertDialogDescription,
|
||||
};
|
18
src/lib/components/ui/badge/badge.svelte
Normal file
18
src/lib/components/ui/badge/badge.svelte
Normal file
|
@ -0,0 +1,18 @@
|
|||
<script lang="ts">
|
||||
import { type Variant, badgeVariants } from "./index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
let className: string | undefined | null = undefined;
|
||||
export let href: string | undefined = undefined;
|
||||
export let variant: Variant = "default";
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<svelte:element
|
||||
this={href ? "a" : "span"}
|
||||
{href}
|
||||
class={cn(badgeVariants({ variant, className }))}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</svelte:element>
|
22
src/lib/components/ui/badge/index.ts
Normal file
22
src/lib/components/ui/badge/index.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { type VariantProps, tv } from "tailwind-variants";
|
||||
|
||||
export { default as Badge } from "./badge.svelte";
|
||||
export const badgeVariants = tv({
|
||||
base: "inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
||||
secondary:
|
||||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
|
||||
outline: "text-foreground",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
});
|
||||
|
||||
export type Variant = VariantProps<typeof badgeVariants>["variant"];
|
17
src/lib/components/ui/popover/index.ts
Normal file
17
src/lib/components/ui/popover/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Popover as PopoverPrimitive } from "bits-ui";
|
||||
import Content from "./popover-content.svelte";
|
||||
const Root = PopoverPrimitive.Root;
|
||||
const Trigger = PopoverPrimitive.Trigger;
|
||||
const Close = PopoverPrimitive.Close;
|
||||
|
||||
export {
|
||||
Root,
|
||||
Content,
|
||||
Trigger,
|
||||
Close,
|
||||
//
|
||||
Root as Popover,
|
||||
Content as PopoverContent,
|
||||
Trigger as PopoverTrigger,
|
||||
Close as PopoverClose,
|
||||
};
|
27
src/lib/components/ui/popover/popover-content.svelte
Normal file
27
src/lib/components/ui/popover/popover-content.svelte
Normal file
|
@ -0,0 +1,27 @@
|
|||
<script lang="ts">
|
||||
import { Popover as PopoverPrimitive } from "bits-ui";
|
||||
import { cn, flyAndScale } from "$lib/utils.js";
|
||||
|
||||
type $$Props = PopoverPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let transition: $$Props["transition"] = flyAndScale;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = undefined;
|
||||
export let align: $$Props["align"] = "center";
|
||||
export let sideOffset: $$Props["sideOffset"] = 4;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<PopoverPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
{align}
|
||||
{sideOffset}
|
||||
{...$$restProps}
|
||||
class={cn(
|
||||
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<slot />
|
||||
</PopoverPrimitive.Content>
|
10
src/lib/components/ui/scroll-area/index.ts
Normal file
10
src/lib/components/ui/scroll-area/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import Scrollbar from "./scroll-area-scrollbar.svelte";
|
||||
import Root from "./scroll-area.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
Scrollbar,
|
||||
//,
|
||||
Root as ScrollArea,
|
||||
Scrollbar as ScrollAreaScrollbar,
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
<script lang="ts">
|
||||
import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ScrollAreaPrimitive.ScrollbarProps & {
|
||||
orientation?: "vertical" | "horizontal";
|
||||
};
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let orientation: $$Props["orientation"] = "vertical";
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ScrollAreaPrimitive.Scrollbar
|
||||
{orientation}
|
||||
class={cn(
|
||||
"flex touch-none select-none transition-colors",
|
||||
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-px",
|
||||
orientation === "horizontal" && "h-2.5 w-full border-t border-t-transparent p-px",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<slot />
|
||||
<ScrollAreaPrimitive.Thumb
|
||||
class={cn("relative rounded-full bg-border", orientation === "vertical" && "flex-1")}
|
||||
/>
|
||||
</ScrollAreaPrimitive.Scrollbar>
|
32
src/lib/components/ui/scroll-area/scroll-area.svelte
Normal file
32
src/lib/components/ui/scroll-area/scroll-area.svelte
Normal file
|
@ -0,0 +1,32 @@
|
|||
<script lang="ts">
|
||||
import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
|
||||
import { Scrollbar } from "./index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ScrollAreaPrimitive.Props & {
|
||||
orientation?: "vertical" | "horizontal" | "both";
|
||||
scrollbarXClasses?: string;
|
||||
scrollbarYClasses?: string;
|
||||
};
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
export let orientation = "vertical";
|
||||
export let scrollbarXClasses: string = "";
|
||||
export let scrollbarYClasses: string = "";
|
||||
</script>
|
||||
|
||||
<ScrollAreaPrimitive.Root {...$$restProps} class={cn("relative overflow-hidden", className)}>
|
||||
<ScrollAreaPrimitive.Viewport class="h-full w-full rounded-[inherit]">
|
||||
<ScrollAreaPrimitive.Content>
|
||||
<slot />
|
||||
</ScrollAreaPrimitive.Content>
|
||||
</ScrollAreaPrimitive.Viewport>
|
||||
{#if orientation === "vertical" || orientation === "both"}
|
||||
<Scrollbar orientation="vertical" class={scrollbarYClasses} />
|
||||
{/if}
|
||||
{#if orientation === "horizontal" || orientation === "both"}
|
||||
<Scrollbar orientation="horizontal" class={scrollbarXClasses} />
|
||||
{/if}
|
||||
<ScrollAreaPrimitive.Corner />
|
||||
</ScrollAreaPrimitive.Root>
|
1
src/lib/components/ui/sonner/index.ts
Normal file
1
src/lib/components/ui/sonner/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export { default as Toaster } from "./sonner.svelte";
|
20
src/lib/components/ui/sonner/sonner.svelte
Normal file
20
src/lib/components/ui/sonner/sonner.svelte
Normal file
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { Toaster as Sonner, type ToasterProps as SonnerProps } from "svelte-sonner";
|
||||
import { mode } from "mode-watcher";
|
||||
|
||||
type $$Props = SonnerProps;
|
||||
</script>
|
||||
|
||||
<Sonner
|
||||
theme={$mode}
|
||||
class="toaster group"
|
||||
toastOptions={{
|
||||
classes: {
|
||||
toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
|
||||
description: "group-[.toast]:text-muted-foreground",
|
||||
actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
||||
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
||||
},
|
||||
}}
|
||||
{...$$restProps}
|
||||
/>
|
1
src/lib/styles/katex.min.css
vendored
Normal file
1
src/lib/styles/katex.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { cubicOut } from "svelte/easing";
|
||||
import type { TransitionConfig } from "svelte/transition";
|
||||
import { type ClassValue, clsx } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
import type { TransitionConfig } from 'svelte/transition';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
|
@ -19,13 +19,9 @@ export const flyAndScale = (
|
|||
params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }
|
||||
): TransitionConfig => {
|
||||
const style = getComputedStyle(node);
|
||||
const transform = style.transform === "none" ? "" : style.transform;
|
||||
const transform = style.transform === 'none' ? '' : style.transform;
|
||||
|
||||
const scaleConversion = (
|
||||
valueA: number,
|
||||
scaleA: [number, number],
|
||||
scaleB: [number, number]
|
||||
) => {
|
||||
const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
|
||||
const [minA, maxA] = scaleA;
|
||||
const [minB, maxB] = scaleB;
|
||||
|
||||
|
@ -35,13 +31,11 @@ export const flyAndScale = (
|
|||
return valueB;
|
||||
};
|
||||
|
||||
const styleToString = (
|
||||
style: Record<string, number | string | undefined>
|
||||
): string => {
|
||||
const styleToString = (style: Record<string, number | string | undefined>): string => {
|
||||
return Object.keys(style).reduce((str, key) => {
|
||||
if (style[key] === undefined) return str;
|
||||
return str + `${key}:${style[key]};`;
|
||||
}, "");
|
||||
}, '');
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
import '@fontsource/geist-sans/latin.css';
|
||||
import '@fontsource/geist-mono/latin.css';
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import { Toaster } from '$lib/components/ui/sonner';
|
||||
</script>
|
||||
|
||||
<Toaster />
|
||||
<ModeWatcher />
|
||||
|
||||
<Navbar />
|
||||
<div class="px-4 pt-24">
|
||||
<div class="pt-20">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
<script lang="ts">
|
||||
import Gpg from '$lib/components/Gpg.svelte';
|
||||
import Socials from '$lib/components/Socials.svelte';
|
||||
import Button from '$lib/components/ui/button/button.svelte';
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import { ArrowRight, GithubLogo } from 'svelte-radix';
|
||||
|
@ -12,9 +13,9 @@
|
|||
<meta name="author" content="Youwen Wu" />
|
||||
</svelte:head>
|
||||
|
||||
<main class="background py-2">
|
||||
<div class="container max-w-3xl mx-auto p-10">
|
||||
<Typewriter mode="scramble" scrambleDuration={500}>
|
||||
<main class="background px-4">
|
||||
<div class="container max-w-4xl 2xl:max-w-5xl mx-auto p-10">
|
||||
<Typewriter mode="scramble" scrambleDuration={750}>
|
||||
<h1 class="text-4xl md:text-6xl font-bold text-center tracking-tight mt-20">
|
||||
👋 Hi, I'm Youwen.
|
||||
</h1>
|
||||
|
@ -29,11 +30,11 @@
|
|||
</Typewriter>
|
||||
<br />
|
||||
<Typewriter mode="scramble" scrambleDuration={1000}>
|
||||
I'm interested in systems programming, web design, data science, and statistics.
|
||||
Interested in systems programming, web design, data science, and statistics.
|
||||
</Typewriter>
|
||||
</div>
|
||||
<span class="flex gap-2 justify-center my-8">
|
||||
<Button href="/about" size="lg" class="text-xl">About Me</Button>
|
||||
<span class="flex gap-2 justify-center my-8 flex-wrap">
|
||||
<Button href="/about" size="lg" class="text-xl">More About Me</Button>
|
||||
<Button
|
||||
href="https://github.com/couscousdude"
|
||||
target="_blank"
|
||||
|
@ -42,8 +43,8 @@
|
|||
class="text-xl"><GithubLogo class="mr-2" />My GitHub</Button
|
||||
>
|
||||
</span>
|
||||
<div class="grid sm:grid-cols-2 gap-4 grid-cols-1">
|
||||
<Card.Root>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<Card.Root class="col-span-2 sm:col-span-1">
|
||||
<Card.Header>
|
||||
<Card.Title>Blog</Card.Title>
|
||||
</Card.Header>
|
||||
|
@ -57,7 +58,7 @@
|
|||
<Button variant="outline" href="/blog">Go<ArrowRight class="ml-2" /></Button>
|
||||
</Card.Footer>
|
||||
</Card.Root>
|
||||
<Card.Root>
|
||||
<Card.Root class="col-span-2 sm:col-span-1">
|
||||
<Card.Header>
|
||||
<Card.Title>Projects</Card.Title>
|
||||
</Card.Header>
|
||||
|
@ -90,6 +91,18 @@
|
|||
</span>
|
||||
</Card.Footer>
|
||||
</Card.Root>
|
||||
<Card.Root class="col-span-2">
|
||||
<Card.Header>
|
||||
<Card.Title>Contact Me</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<h3>Find me on:</h3>
|
||||
<Socials />
|
||||
<Gpg>
|
||||
<Button variant="outline" class="mt-4"><span class="mr-2">🔑</span> My GPG Key</Button>
|
||||
</Gpg>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
|
5
src/routes/blog/+layout.svelte
Normal file
5
src/routes/blog/+layout.svelte
Normal file
|
@ -0,0 +1,5 @@
|
|||
<script lang="ts">
|
||||
import '$lib/styles/katex.min.css';
|
||||
</script>
|
||||
|
||||
<slot />
|
|
@ -1,5 +1,19 @@
|
|||
<script>
|
||||
import UnderConstruction from '$lib/components/UnderConstruction.svelte';
|
||||
<script lang="ts">
|
||||
import ChevronRight from 'svelte-radix/ChevronRight.svelte';
|
||||
import Code from 'svelte-radix/Code.svelte';
|
||||
import type { PageData } from './$types.js';
|
||||
// import { config } from '$lib/stores/index.js';
|
||||
import { cn } from '$lib/utils.js';
|
||||
|
||||
let doc = {
|
||||
title: 'Test Post',
|
||||
description: ''
|
||||
};
|
||||
|
||||
export let data: PageData;
|
||||
$: markdown = data.markdown;
|
||||
// $: doc = data.metadata;
|
||||
// $: componentSource = data.metadata.source?.replace('default', $config.style ?? 'default');
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
@ -8,4 +22,33 @@
|
|||
<meta name="author" content="Youwen Wu" />
|
||||
</svelte:head>
|
||||
|
||||
<UnderConstruction />
|
||||
<main class="container max-w-5xl mx-auto my-8">
|
||||
<div class="mx-auto w-full min-w-0 mb-4">
|
||||
<div class="mb-4 flex items-center space-x-1 text-sm text-muted-foreground">
|
||||
<div class="overflow-hidden text-ellipsis whitespace-nowrap">Docs</div>
|
||||
<ChevronRight class="h-4 w-4" />
|
||||
<div class="font-medium text-foreground">{doc.title}</div>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<h1 class={cn('scroll-m-20 text-4xl font-bold tracking-tight')}>
|
||||
{doc.title}
|
||||
</h1>
|
||||
{#if doc.description}
|
||||
<p class="text-balance text-lg text-muted-foreground">
|
||||
{doc.description}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- <div class="pb-12 pt-8 mx-auto"> -->
|
||||
<!-- </div> -->
|
||||
<!-- <div class="hidden text-sm xl:block">
|
||||
<div class="sticky top-16 -mt-10 h-[calc(100vh-3.5rem)] overflow-hidden pt-4">
|
||||
{#key $page.url.pathname}
|
||||
<TableOfContents />
|
||||
{/key}
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
{@html markdown}
|
||||
</main>
|
||||
|
|
17
src/routes/blog/+page.ts
Normal file
17
src/routes/blog/+page.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import type { PageLoad } from './$types.js';
|
||||
import { marked } from 'marked';
|
||||
import markedKatex from 'marked-katex-extension';
|
||||
|
||||
const options = {
|
||||
throwOnError: false
|
||||
};
|
||||
marked.use(markedKatex(options));
|
||||
|
||||
export const load: PageLoad = async ({ fetch }) => {
|
||||
const data = await fetch('/test.md');
|
||||
const markdown = await marked.parse(await data.text());
|
||||
|
||||
return {
|
||||
markdown
|
||||
};
|
||||
};
|
BIN
static/fonts/KaTeX_AMS-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_AMS-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_AMS-Regular.woff
Normal file
BIN
static/fonts/KaTeX_AMS-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_AMS-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_AMS-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Caligraphic-Bold.ttf
Normal file
BIN
static/fonts/KaTeX_Caligraphic-Bold.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Caligraphic-Bold.woff
Normal file
BIN
static/fonts/KaTeX_Caligraphic-Bold.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Caligraphic-Bold.woff2
Normal file
BIN
static/fonts/KaTeX_Caligraphic-Bold.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Caligraphic-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Caligraphic-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Caligraphic-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Caligraphic-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Caligraphic-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Caligraphic-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Fraktur-Bold.ttf
Normal file
BIN
static/fonts/KaTeX_Fraktur-Bold.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Fraktur-Bold.woff
Normal file
BIN
static/fonts/KaTeX_Fraktur-Bold.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Fraktur-Bold.woff2
Normal file
BIN
static/fonts/KaTeX_Fraktur-Bold.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Fraktur-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Fraktur-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Fraktur-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Fraktur-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Fraktur-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Fraktur-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Bold.ttf
Normal file
BIN
static/fonts/KaTeX_Main-Bold.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Bold.woff
Normal file
BIN
static/fonts/KaTeX_Main-Bold.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Bold.woff2
Normal file
BIN
static/fonts/KaTeX_Main-Bold.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-BoldItalic.ttf
Normal file
BIN
static/fonts/KaTeX_Main-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-BoldItalic.woff
Normal file
BIN
static/fonts/KaTeX_Main-BoldItalic.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-BoldItalic.woff2
Normal file
BIN
static/fonts/KaTeX_Main-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Italic.ttf
Normal file
BIN
static/fonts/KaTeX_Main-Italic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Italic.woff
Normal file
BIN
static/fonts/KaTeX_Main-Italic.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Italic.woff2
Normal file
BIN
static/fonts/KaTeX_Main-Italic.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Main-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Main-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Main-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Main-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Math-BoldItalic.ttf
Normal file
BIN
static/fonts/KaTeX_Math-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Math-BoldItalic.woff
Normal file
BIN
static/fonts/KaTeX_Math-BoldItalic.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Math-BoldItalic.woff2
Normal file
BIN
static/fonts/KaTeX_Math-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Math-Italic.ttf
Normal file
BIN
static/fonts/KaTeX_Math-Italic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Math-Italic.woff
Normal file
BIN
static/fonts/KaTeX_Math-Italic.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Math-Italic.woff2
Normal file
BIN
static/fonts/KaTeX_Math-Italic.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Bold.ttf
Normal file
BIN
static/fonts/KaTeX_SansSerif-Bold.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Bold.woff
Normal file
BIN
static/fonts/KaTeX_SansSerif-Bold.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Bold.woff2
Normal file
BIN
static/fonts/KaTeX_SansSerif-Bold.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Italic.ttf
Normal file
BIN
static/fonts/KaTeX_SansSerif-Italic.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Italic.woff
Normal file
BIN
static/fonts/KaTeX_SansSerif-Italic.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Italic.woff2
Normal file
BIN
static/fonts/KaTeX_SansSerif-Italic.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_SansSerif-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Regular.woff
Normal file
BIN
static/fonts/KaTeX_SansSerif-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_SansSerif-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_SansSerif-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Script-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Script-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Script-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Script-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Script-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Script-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size1-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Size1-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size1-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Size1-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size1-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Size1-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size2-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Size2-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size2-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Size2-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size2-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Size2-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size3-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Size3-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size3-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Size3-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size3-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Size3-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size4-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Size4-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size4-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Size4-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Size4-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Size4-Regular.woff2
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Typewriter-Regular.ttf
Normal file
BIN
static/fonts/KaTeX_Typewriter-Regular.ttf
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Typewriter-Regular.woff
Normal file
BIN
static/fonts/KaTeX_Typewriter-Regular.woff
Normal file
Binary file not shown.
BIN
static/fonts/KaTeX_Typewriter-Regular.woff2
Normal file
BIN
static/fonts/KaTeX_Typewriter-Regular.woff2
Normal file
Binary file not shown.
135
static/test.md
Normal file
135
static/test.md
Normal file
|
@ -0,0 +1,135 @@
|
|||
The following content is a test post for the blog's markdown and $\KaTeX$ rendering capabilities. There's a few errors, and wikilinks aren't supported. This file was copy pasted directly out of my `obsidian.md` notebook, so it contains some weird formatting.
|
||||
|
||||
<br />
|
||||
|
||||
The methods in [[9.8 Power Series]] and [[9.9 Representation of (Rational) Functions by Power Series]] allow us to find power series for rational functions, $\ln$, and $\arctan$. To get power series for other elementary functions, we need a more general method.
|
||||
|
||||
We can approximate some non-polynomial functions by constructing a polynomial with the _same derivatives_ as the function. This is called a _Taylor Polynomial_.
|
||||
|
||||
> [!NOTE]
|
||||
> In general, if $c \neq 0$, it's called a Taylor Polynomial. If $c = 0$, then it's a Maclaurin Polynomial.
|
||||
|
||||
Consider $f(x) = e^x$. Let's find the best cubic approximation $P_3(x)$ for $f(x)$ at $c=0$.
|
||||
|
||||
$$
|
||||
P_3(0) = f(0)
|
||||
$$
|
||||
|
||||
$$
|
||||
f'(x) = e^x,\,P_3'(0)=f'(0)
|
||||
$$
|
||||
|
||||
$$
|
||||
f''(x) = e^x,\,P_3''(0) = f''(0)
|
||||
$$
|
||||
|
||||
$$
|
||||
f'''(x) = e^x,\,P_3'''(0) = f'''(0)
|
||||
$$
|
||||
|
||||
$$
|
||||
f(0) = f'(0) = f''(0) = f'''(0) = 1
|
||||
$$
|
||||
|
||||
We know that $P_3(x)$ will be of the form
|
||||
|
||||
$$
|
||||
P_3(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3
|
||||
$$
|
||||
|
||||
We can differentiate both sides $n$ times to find the values of $a_0$, $a_1$, $\dots$, $a_n$.
|
||||
|
||||
$$
|
||||
P_3(x) = 1 + x + \frac{1}{2} x^2 + \frac{1}{6} x^3
|
||||
$$
|
||||
|
||||
You can confirm that this polynomial has the same first, second, and third derivatives as $e^x$.
|
||||
|
||||
## Generalizing
|
||||
|
||||
Taking repeated derivatives like this leads to a common pattern in all Taylor polynomials.
|
||||
|
||||
> [!NOTE]
|
||||
> We use the notation $P_n(x)$ to denote the $n^{th}$ Taylor polynomial
|
||||
|
||||
Taylor polynomials take the form:
|
||||
|
||||
$$
|
||||
P_n(x) = a_0 + a_1 (x-c) + a_2(x-c)^2 + a_3 (x-c)^3 + \dots + a_n(x-c)^n
|
||||
$$
|
||||
|
||||
where $a_n$ is the coefficient of the $n^{th}$ term (indexed from 0). It turns out that these coefficients are actually common across Taylor polynomials.
|
||||
|
||||
$$
|
||||
P_n(c) = a_0 = f(c)
|
||||
$$
|
||||
|
||||
$$
|
||||
P_n'(c) = a_1 = f'(c)
|
||||
$$
|
||||
|
||||
$$
|
||||
P_n''(c) = 2 a_2 = 2!\,a_2
|
||||
$$
|
||||
|
||||
$$
|
||||
P_n'''(c) = 6a_3 = 3!\,a_3 = f'''(c)
|
||||
$$
|
||||
|
||||
$$
|
||||
P_n^{(n)}(c) = n!\,a_n = f^{(n)}(c)
|
||||
$$
|
||||
|
||||
$$
|
||||
\implies a_n = \frac{f^{(n)}(c)}{n!}
|
||||
$$
|
||||
|
||||
## Tying up loose ends
|
||||
|
||||
We've seen Taylor and Maclaurin polynomials. We will eventually extend them to [[9.10 Taylor and Maclaurin Series|Maclaurin and Taylor series]]. Before this is mathematically valid (at least, valid enough), we need to do some stuff first.
|
||||
|
||||
We can use Maclaurin and Taylor polynomials (or series) to estimate the value of functions by hand.
|
||||
|
||||
### Taylor Remainder
|
||||
|
||||
If you have $f(x)$ and $P_n(x)$ (centered at $c$), then $f(x) = P_n(x) + R_n(x)$, where $R_n$ is
|
||||
|
||||
$$
|
||||
R_n(x) = \frac{f^{(n+1)}(z)}{(n+1)!}\,(x-c)^{n+1}
|
||||
$$
|
||||
|
||||
$$
|
||||
z \in [c,\,x]
|
||||
$$
|
||||
|
||||
> [!TIP]
|
||||
> This is a fancy way of saying that $z$ is between $c$ and $x$.
|
||||
|
||||
$$
|
||||
\text{Error} = \left|R_n(x)\right|
|
||||
$$
|
||||
|
||||
> [!NOTE] > $R_n$ would be the "next term" in $P_n(x)$ except we put $z$ instead of $c$.
|
||||
|
||||
#### Applying to $e^x$
|
||||
|
||||
How many terms of the Maclaurin Polynomial for $f(x) = e^x$ do we need to guarantee that our estimate for $f(1) = e$ is within $\displaystyle\frac{1}{1000000}$?
|
||||
The error is
|
||||
|
||||
$$
|
||||
|R_n(1)| = \frac{|f^{(n+1)}(z)|}{(n+1)!}\,\cancel{|1-0|^{n+1}}
|
||||
$$
|
||||
|
||||
for some $z$ between $c=0$ and $x=1$
|
||||
So we want an $n$ such that
|
||||
|
||||
$$
|
||||
\frac{|e^z|}{(n+1)!} \le \frac{1}{1000000}
|
||||
$$
|
||||
|
||||
The worst case scenario is $z=1$.
|
||||
If $\displaystyle\frac{e}{(n+1)!} \le \frac{1}{1000000}$, we're all set.
|
||||
|
||||
Assume that $e \le 3$, which implies that if $\displaystyle\frac{3}{(n+1)!} \le \frac{1}{1000000}$, we're all set.
|
||||
After trying terms, we find that $n=9$ works.
|
||||
So $P_9(1) = 1 + 1 + \frac{1}{2!} + \frac{1}{3!} + \dots + \frac{1}{9!}$ is within $\frac{1}{1000000}$ of $e$.
|
41
static/youwen.gpg
Normal file
41
static/youwen.gpg
Normal file
|
@ -0,0 +1,41 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
1Aslp42CY3IG
|
||||
=wGsS
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
Loading…
Reference in a new issue