Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ declare global {
// interface Locals {}
interface PageData {
pageTitle?: string;
/** Full `<title>` override; takes precedence over `pageTitle`. */
metaTitle?: string;
/** Meta description for the current page. */
metaDescription?: string;
/** Comma separated meta keywords for the current page. */
metaKeywords?: string;
}
// interface PageState {}
// interface Platform {}
Expand Down
17 changes: 14 additions & 3 deletions src/app.html
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
<!doctype html>
<html lang="en">
<html lang="%lang%">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1" />
<meta
name="theme-color"
content="#16a34a" />
<link
rel="icon"
href="/branch.svg"
href="%sveltekit.assets%/branch.svg"
type="image/svg+xml" />
<link
rel="apple-touch-icon"
href="%sveltekit.assets%/branch.svg" />
<link
rel="manifest"
href="%sveltekit.assets%/manifest.webmanifest" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover" class="bg-background">
<body
data-sveltekit-preload-data="hover"
class="bg-background">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
35 changes: 35 additions & 0 deletions src/lib/i18n/translations/cs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,41 @@ const cs: Translation = {
},
},

seo: {
titleDefault: 'Treeline – Interaktivní vizualizace datových struktur a algoritmů',
description:
'Treeline je bezplatný interaktivní nástroj pro výuku datových struktur a třídicích i vyhledávacích algoritmů. Sledujte každý krok binárních vyhledávacích stromů, AVL, červeno-černých a B-stromů, hald, spojových seznamů, zásobníků, front i třídění jako quicksort, merge sort a heap sort.',
keywords:
'datové struktury, algoritmy, vizualizace algoritmů, vizualizace datových struktur, třídicí algoritmy, vyhledávací algoritmy, binární vyhledávací strom, AVL strom, červeno-černý strom, B-strom, halda, spojový seznam, zásobník, fronta, bubble sort, selection sort, insertion sort, merge sort, quicksort, heap sort, binární vyhledávání, lineární vyhledávání, informatika, učit se algoritmy interaktivně',
about: 'Zjistěte více o Treeline – bezplatném open-source nástroji pro interaktivní vizualizaci datových struktur a algoritmů, vytvořeném jako diplomová práce.',
dataStructures: {
'binary-search-tree':
'Vizualizujte binární vyhledávací strom (BST) krok za krokem. Vkládejte, vyhledávejte a odebírejte hodnoty a sledujte, jak se strom mění v reálném čase.',
'avl-tree':
'Interaktivní vizualizace AVL stromu. Sledujte, jak rotace udržují strom vyvážený po každém vložení a odebrání, krok za krokem.',
'red-black-tree':
'Interaktivní vizualizace červeno-černého stromu. Sledujte přebarvování a rotace, které udržují strom vyvážený při vkládání a mazání.',
'b-tree': 'Interaktivní vizualizace B-stromu. Sledujte štěpení uzlů, slučování a posun klíčů při vkládání a odebírání hodnot.',
heap: 'Interaktivní vizualizace binární haldy. Vkládejte hodnoty, odebírejte kořen a sledujte, jak heapify udržuje vlastnost max-haldy.',
'linked-list':
'Interaktivní vizualizace spojového seznamu. Vkládejte na začátek či konec, vyhledávejte a odebírejte uzly a sledujte aktualizaci ukazatelů.',
stack: 'Interaktivní vizualizace zásobníku. Pomocí operací push, pop a peek pochopíte princip LIFO (poslední dovnitř, první ven).',
queue: 'Interaktivní vizualizace fronty. Pomocí operací enqueue, dequeue a peek pochopíte princip FIFO (první dovnitř, první ven).',
},
sorting: {
bubble: 'Vizualizujte bubble sort krok za krokem s ovládáním přehrávání, zvýrazněním pseudokódu a různými rozloženími dat.',
selection:
'Vizualizujte selection sort krok za krokem s ovládáním přehrávání, zvýrazněním pseudokódu a různými rozloženími dat.',
insertion:
'Vizualizujte insertion sort krok za krokem s ovládáním přehrávání, zvýrazněním pseudokódu a různými rozloženími dat.',
merge: 'Vizualizujte merge sort krok za krokem s ovládáním přehrávání, zvýrazněním pseudokódu a různými rozloženími dat.',
quick: 'Vizualizujte quicksort krok za krokem s ovládáním přehrávání, zvýrazněním pseudokódu a různými rozloženími dat.',
heap: 'Vizualizujte heap sort krok za krokem s ovládáním přehrávání, zvýrazněním pseudokódu a různými rozloženími dat.',
searching: 'Vizualizujte lineární a binární vyhledávání krok za krokem s nastavitelným cílem a ovládáním přehrávání.',
comparison: 'Porovnejte třídicí algoritmy vedle sebe na různých datových sadách a zvažte porovnání, výměny i rychlost.',
},
},

description: {
title: 'Popis',
noJs: 'Obsah popisu se načítá dynamicky a JavaScript je momentálně vypnutý.',
Expand Down
36 changes: 36 additions & 0 deletions src/lib/i18n/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,42 @@ const en = {
},
},

seo: {
titleDefault: 'Treeline – Interactive Data Structure & Algorithm Visualizer',
description:
'Treeline is a free, interactive visualizer for learning data structures, sorting, and searching algorithms. Watch every step of binary search trees, AVL, red-black and B-trees, heaps, linked lists, stacks, queues, and sorts like quicksort, merge sort, and heap sort.',
keywords:
'data structures, algorithms, algorithm visualizer, data structure visualization, sorting algorithms, searching algorithms, binary search tree, AVL tree, red-black tree, B-tree, heap, linked list, stack, queue, bubble sort, selection sort, insertion sort, merge sort, quicksort, heap sort, binary search, linear search, computer science, learn algorithms interactively',
about: "Learn about Treeline, a free and open-source interactive tool for visualizing data structures and algorithms, built as a Master's thesis project.",
dataStructures: {
'binary-search-tree':
'Visualize a binary search tree (BST) step by step. Insert, find, and remove values and watch the tree reshape in real time.',
'avl-tree':
'Interactive AVL tree visualization. See how rotations keep the tree height-balanced after every insertion and deletion, one step at a time.',
'red-black-tree':
'Interactive red-black tree visualization. Follow the recoloring and rotations that keep the tree balanced during inserts and deletes.',
'b-tree': 'Interactive B-tree visualization. Watch node splits, merges, and key promotions as you insert and remove values.',
heap: 'Interactive binary heap visualization. Insert values, extract the root, and watch heapify maintain the max-heap property.',
'linked-list':
'Interactive linked list visualization. Insert at the head or tail, find, and remove nodes while pointers update in real time.',
stack: 'Interactive stack visualization. Push, pop, and peek values to understand last-in, first-out (LIFO) behavior.',
queue: 'Interactive queue visualization. Enqueue, dequeue, and peek values to understand first-in, first-out (FIFO) behavior.',
},
sorting: {
bubble: 'Visualize bubble sort step by step with playback controls, pseudocode highlighting, and multiple data distributions.',
selection:
'Visualize selection sort step by step with playback controls, pseudocode highlighting, and multiple data distributions.',
insertion:
'Visualize insertion sort step by step with playback controls, pseudocode highlighting, and multiple data distributions.',
merge: 'Visualize merge sort step by step with playback controls, pseudocode highlighting, and multiple data distributions.',
quick: 'Visualize quicksort step by step with playback controls, pseudocode highlighting, and multiple data distributions.',
heap: 'Visualize heap sort step by step with playback controls, pseudocode highlighting, and multiple data distributions.',
searching: 'Visualize linear search and binary search step by step, with adjustable targets and playback controls.',
comparison:
'Compare sorting algorithms side by side across multiple dataset profiles and weigh comparisons, swaps, and speed together.',
},
},

description: {
title: 'Description',
noJs: 'Description content loads dynamically and JavaScript is currently disabled.',
Expand Down
26 changes: 26 additions & 0 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { goto } from '$app/navigation';

import type { Locale } from '$lib/i18n';
import { SITE_URL } from '$lib/seo/config';

onMount(() => {
let locale: Locale = 'en';
Expand All @@ -22,6 +23,31 @@
});
</script>

<svelte:head>
<title>Treeline – Interactive Data Structure & Algorithm Visualizer</title>
<meta
name="description"
content="Treeline is a free, interactive visualizer for learning data structures, sorting, and searching algorithms step by step." />
<link
rel="canonical"
href={`${SITE_URL}/en`} />
<link
rel="alternate"
hreflang="en"
href={`${SITE_URL}/en`} />
<link
rel="alternate"
hreflang="cs"
href={`${SITE_URL}/cs`} />
<link
rel="alternate"
hreflang="x-default"
href={`${SITE_URL}/en`} />
<meta
http-equiv="refresh"
content="0; url=/en" />
</svelte:head>

<div class="flex h-64 items-center justify-center">
<p class="text-gray-500">Redirecting...</p>
</div>
19 changes: 15 additions & 4 deletions src/routes/[lang]/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@

import Footer from '$lib/components/Footer.svelte';
import Nav from '$lib/components/Nav.svelte';
import { setLocaleContext } from '$lib/i18n';
import Seo from '$lib/components/Seo.svelte';
import { setLocaleContext, translate } from '$lib/i18n';
import { SITE_NAME } from '$lib/seo/config';

let { data, children } = $props();

setLocaleContext(data.lang);

const t = (key: string) => translate(data.lang, key);

const title = $derived(page.data.metaTitle ?? (page.data.pageTitle ? `${page.data.pageTitle} – ${SITE_NAME}` : t('seo.titleDefault')));
const description = $derived(page.data.metaDescription ?? t('seo.description'));
const keywords = $derived(page.data.metaKeywords ?? t('seo.keywords'));
</script>

<svelte:head>
<title>{page.data.pageTitle ? `${page.data.pageTitle} - Treeline` : 'Treeline'}</title>
</svelte:head>
<Seo
{title}
{description}
{keywords}
locale={data.lang}
pathname={page.url.pathname} />

<div class="flex min-h-screen flex-col">
<Nav />
Expand Down
1 change: 1 addition & 0 deletions src/routes/[lang]/about/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export const load: PageServerLoad = async ({ params }) => {
return {
...descriptionData,
pageTitle: translate(locale, 'nav.about'),
metaDescription: translate(locale, 'seo.about'),
};
};
1 change: 1 addition & 0 deletions src/routes/[lang]/data-structures/+layout.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ export const load: LayoutServerLoad = async ({ params, url }) => {
return {
...descriptionData,
pageTitle: translate(locale, titleKey),
metaDescription: translate(locale, `seo.dataStructures.${slug}`),
};
};
1 change: 1 addition & 0 deletions src/routes/[lang]/sorting-algorithms/+layout.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const load: LayoutServerLoad = async ({ params, url }) => {
return {
...descriptionData,
pageTitle: translate(locale, titleKey),
metaDescription: translate(locale, `seo.sorting.${slug}`),
initialDetailedArray: createShuffledArray(16),
};
};
4 changes: 3 additions & 1 deletion static/robots.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# allow crawling everything by default
# Allow crawling everything by default
User-agent: *
Disallow:

Sitemap: https://treeline.kkobari.eu/sitemap.xml
2 changes: 1 addition & 1 deletion svelte.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const config = {
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter(),
prerender: {
entries: ['/', '/en', '/cs'],
entries: ['/', '/en', '/cs', '/sitemap.xml'],
},
},
};
Expand Down