Skip to content

Commit

Permalink
fix(tutorials): read notes
Browse files Browse the repository at this point in the history
- Added the extremely fast flexsearch to the project and is now in going to be beta tested in the tutorials page.
- Some visual tweaks to fix some issues with tutorials
- Tutorials now list authors and coauthors
  • Loading branch information
Torwent committed Oct 29, 2024
1 parent 8d80a83 commit 307a6dc
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 119 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@supabase/ssr": "^0.4.1",
"@supabase/supabase-js": "^2.45.4",
"file-saver": "^2.0.5",
"flexsearch": "^0.7.43",
"highlight.js": "11.10.0",
"jszip": "^3.10.1",
"lucide-svelte": "^0.428.0",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion src/lib/server/utils.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ export async function getTutorials() {
export const tutorialsPromise = getTutorials()

export async function getFullTutorials() {
console.log("LOADING FULL")
let tutorials: Tutorial[] = []

const paths = import.meta.glob("/src/wasp-info/tutorials/*.md", { eager: true })
Expand Down
23 changes: 23 additions & 0 deletions src/lib/tutorials.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import FlexSearch from "flexsearch"
import type { Tutorial } from "./types/collection"
import { tutorialsPromise } from "./server/utils.server"

let tutorialsIndex: FlexSearch.Index
let tutorials: Tutorial[]

export function createTutorialsIndex(data: Tutorial[]) {
tutorialsIndex = new FlexSearch.Index({ tokenize: "forward" })

data.forEach((tutorial, i) => {
const item = `${tutorial.title} ${tutorial.description} ${tutorial.content}`
tutorialsIndex.add(i, item)
})

tutorials = data
}

export function searchTutorialsIndex(searchTerm: string) {
const match = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") //escape special regex characters
const results = tutorialsIndex.search(match)
return results.map((index) => tutorials[index as number])
}
32 changes: 3 additions & 29 deletions src/routes/api/tutorials/+server.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,9 @@
import { getUsername } from "$lib/server/supabase.server"
import type { Tutorial } from "$lib/types/collection"
import { encodeSEO } from "$lib/utils"
import { getFullTutorials, tutorialsPromise } from "$lib/server/utils.server"
import { json } from "@sveltejs/kit"

async function getPosts() {
let tutorials: Tutorial[] = []

const paths = import.meta.glob("/src/wasp-info/tutorials/*.md", { eager: true })

for (const path in paths) {
const file = paths[path]
const order = path.split("/").at(-1)?.replace(".md", "")

if (file && typeof file === "object" && "metadata" in file && order) {
const metadata = file.metadata as Omit<Tutorial, "slug">
const username = await getUsername(metadata.author)
if (!username) continue

const url = encodeSEO(metadata.title + " by " + username)

const tutorial = { ...metadata, username, order: parseInt(order), url } satisfies Tutorial
tutorial.published && tutorials.push(tutorial)
}
}

tutorials = tutorials.sort((first, second) => first.order - second.order)

return tutorials
}
export const prerender = true

export async function GET() {
const tutorials = await getPosts()
const tutorials = await getFullTutorials()
return json(tutorials)
}
29 changes: 3 additions & 26 deletions src/routes/api/tutorials/[slug]/+server.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,8 @@
import { getUsername } from "$lib/server/supabase.server"
import type { Tutorial } from "$lib/types/collection"
import { encodeSEO } from "$lib/utils"
import { getTutorial } from "$lib/server/utils.server"
import { error, json } from "@sveltejs/kit"

async function getPosts(slug: string) {
const paths = import.meta.glob("/src/wasp-info/tutorials/*.md", { eager: true })

for (const path in paths) {
const file = paths[path]

const order = path.split("/").at(-1)?.replace(".md", "")
if (file && typeof file === "object" && "metadata" in file && order) {
const metadata = file.metadata as Omit<Tutorial, "slug">
const username = await getUsername(metadata.author)
if (!username) continue

const url = encodeSEO(metadata.title + " by " + username)

if (slug === order || slug === url)
return { ...metadata, order: parseInt(order), url } satisfies Tutorial
}
}

error(404, "Couldn't find " + slug)
}

export async function GET({ params: { slug } }) {
const tutorial = await getPosts(slug)
const tutorial = await getTutorial(slug)
if (!tutorial) error(404, "Can't find " + slug)
return json(tutorial)
}
60 changes: 20 additions & 40 deletions src/routes/tutorials/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,23 @@
import { getUsername } from "$lib/server/supabase.server"
import { tutorialsPromise } from "$lib/server/utils.server"
import { createTutorialsIndex, searchTutorialsIndex } from "$lib/tutorials.server"
import type { Tutorial } from "$lib/types/collection"
import { encodeSEO } from "$lib/utils"

async function getTutorials() {
console.log("LOADING TUTORIALS!")
let tutorials: Tutorial[] = []

const paths = import.meta.glob("/src/wasp-info/tutorials/*.md", { eager: true })

for (const path in paths) {
const file = paths[path]
const order = path.split("/").at(-1)?.replace(".md", "")

if (file && typeof file === "object" && "metadata" in file && order) {
const metadata = file.metadata as Omit<Tutorial, "slug">
const username = await getUsername(metadata.author)
if (!username) continue

const url = encodeSEO(metadata.title + " by " + username)

const tutorial = { ...metadata, username, order: parseInt(order), url } satisfies Tutorial
tutorials.push(tutorial)
}
}

return tutorials.sort((first, second) => first.order - second.order)
}

const tutorialsPromise = getTutorials()

async function getPublishedTutorials() {
const tutorials = await tutorialsPromise
return tutorials.filter((tutorial) => tutorial.published)
const filtered = tutorials.filter((tutorial) => tutorial.published)
createTutorialsIndex(filtered)
return filtered
}

const publishedTutorialPromise = getTutorials()
const publishedTutorialPromise = getPublishedTutorials()

async function getTutorialLevels(level: number) {
const tutorials = await publishedTutorialPromise
return tutorials.filter((tutorial) => tutorial.level === level)
const filtered = tutorials.filter((tutorial) => tutorial.level === level)
return filtered
}

const tutorialLevels: Promise<Tutorial[]>[] = [
getTutorialLevels(0),
getTutorialLevels(1),
getTutorialLevels(2)
]
const tutorialLevelsPromises = [getTutorialLevels(0), getTutorialLevels(1), getTutorialLevels(2)]

export async function load({ depends, url }) {
depends("wasp:tutorials")
Expand All @@ -64,10 +36,18 @@ export async function load({ depends, url }) {
const finish = start + amount - 1

let tutorials: Tutorial[]
if (level != -1) {
tutorials = await tutorialLevels[level]

if (search !== "") {
tutorials = searchTutorialsIndex(search)
if (level != -1) {
tutorials = tutorials.filter((t) => t.level === level)
}
} else {
tutorials = await publishedTutorialPromise
if (level != -1) {
tutorials = await tutorialLevelsPromises[level]
} else {
tutorials = await publishedTutorialPromise
}
}

const filteredTutorials = tutorials.slice(
Expand Down
16 changes: 1 addition & 15 deletions src/routes/tutorials/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,19 @@
import { page } from "$app/stores"
import TutorialCard from "./TutorialCard.svelte"
import Paginator from "$lib/components/Paginator.svelte"
import { ArrowDownAZ, ArrowUpZA } from "lucide-svelte"
import { replaceQuery } from "$lib/client/utils"
import type { Tutorial } from "$lib/types/collection"
export let data
let { tutorials, amount, count } = data
let { searchParams } = $page.url
$: ({ user, roles, tutorials, amount, count } = data)
$: ({ tutorials, amount, count } = data)
$: ({ searchParams } = $page.url)
const pageStr = searchParams.get("page") || "-1"
let currentPage = Number(pageStr) < 0 || Number.isNaN(Number(pageStr)) ? 0 : Number(pageStr)
let search = decodeURIComponent(searchParams.get("search") || "").trim()
const ascendingStr = searchParams.get("ascending")
let ascending = ascendingStr ? ascendingStr.toLowerCase() === "true" : true
const parsedLevel = Number(searchParams.get("level") ?? "-1")
Expand All @@ -27,16 +23,6 @@
const levelColors = ["sky", "orange", "red"]
const levelNames = ["Basic", "Intermidiate", "Advanced"]
async function sort() {
search = ""
ascending = !ascending
await replaceQuery($page.url, {
page: "1",
search: search,
ascending: ascending ? "true" : "false"
})
}
const headTitle = "Tutorials - WaspScripts"
const headDescription =
"Guides and tutorials to bot and develop scripts for OldSchool RuneScape. Find the large collection of Simba tutorials available and unleach the power of Simba and max on osrs."
Expand Down
5 changes: 3 additions & 2 deletions src/routes/tutorials/TutorialCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

{#if tutorial}
<div
class="rounded-md variant-ghost-surface m-4 shadow-none hover:shadow-sm {tutorial.level === 0
class="w-[40rem] rounded-md variant-ghost-surface m-4 shadow-none hover:shadow-sm {tutorial.level ===
0
? 'ring-sky-400 dark:ring-sky-500 shadow-sky-500'
: tutorial.level === 1
? 'ring-orange-400 dark:ring-orange-500 shadow-orange-500'
Expand Down Expand Up @@ -46,7 +47,7 @@
</div>
{:else}
<div
class="rounded-md variant-ghost-surface m-4 shadow-none hover:shadow-sm ring-surface-400 dark:ring-surface-500 shadow-surface-500 animate-pulse"
class="w-[40rem] rounded-md variant-ghost-surface m-4 shadow-none hover:shadow-sm ring-surface-400 dark:ring-surface-500 shadow-surface-500 animate-pulse"
>
<a href={link}>
<div class="flex flex-col p-3">
Expand Down
43 changes: 38 additions & 5 deletions src/routes/tutorials/[slug]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
<script lang="ts">
import { page } from "$app/stores"
export let data
const { content, meta } = data
const { content, meta, supabaseClient } = data
const headImage = "/multi-color-logo.png"
async function getUsername(id: string) {
const { data, error: err } = await supabaseClient
.schema("profiles")
.from("profiles")
.select("username")
.eq("id", id)
.single()
if (err) {
console.error(err)
return "Error"
}
return data.username
}
console.log(meta.coauthors)
</script>

<svelte:head>
Expand Down Expand Up @@ -41,11 +59,26 @@
Found something wrong? Edit on GitHub!
</a>
</div>
<h2 class="text-center mb-4 font-bold text-3xl">{meta.title}</h2>
<h3 class="text-center font-semibold leading-normal mb-4">{meta.description}</h3>

<h2 class="text-center my-4 font-bold text-3xl">{meta.title}</h2>
<h3 class="text-center font-semibold leading-normal my-4">{meta.description}</h3>
<h4 class="text-center">
By {#await getUsername(meta.author)} Loading... {:then author} {author} {/await}
</h4>
{#if meta.coauthors}
<h5 class="text-center">
With contributions from
{#each meta.coauthors as coauthor, i}
{#await getUsername(coauthor)}
Loading
{:then author}
{author}{#if i < meta.coauthors.length - 2},{:else if i === meta.coauthors.length - 2}
<wbr />&nbsp;and{/if}
{/await}
{/each}
</h5>
{/if}
<article
class="mx-auto prose dark:prose-invert py-6 border-t-2 border-surface-300 dark:border-surface-800"
class="mx-auto my-8 prose dark:prose-invert py-6 border-t-2 border-surface-300 dark:border-surface-800"
>
<div>
<svelte:component this={content} />
Expand Down
2 changes: 1 addition & 1 deletion src/wasp-info
Submodule wasp-info updated 2 files
+2 −1 tutorials/1.md
+130 −97 tutorials/23.md

0 comments on commit 307a6dc

Please sign in to comment.