Skip to content

Commit c3a78d8

Browse files
committed
fix!: cleanup after migration
1 parent d9fdbfa commit c3a78d8

File tree

9 files changed

+837
-609
lines changed

9 files changed

+837
-609
lines changed

eslint.config.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// eslint.config.js
22
import js from "@eslint/js";
33
import svelte from "eslint-plugin-svelte";
4+
import svelteParser from "svelte-eslint-parser";
5+
import tsParser from "@typescript-eslint/parser";
46
import globals from "globals";
57
import svelteConfig from "./svelte.config.js";
68

@@ -32,10 +34,17 @@ export default [
3234
},
3335
},
3436
{
35-
files: ["**/*.svelte", "**/*.svelte.js"],
37+
files: ["**/*.svelte"],
3638
languageOptions: {
39+
parser: svelteParser,
3740
parserOptions: {
41+
parser: {
42+
ts: tsParser,
43+
typescript: tsParser,
44+
},
3845
svelteConfig,
46+
ecmaVersion: "latest",
47+
sourceType: "module",
3948
},
4049
},
4150
rules: {

package-lock.json

Lines changed: 761 additions & 496 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@sveltejs/adapter-auto": "^6.1.0",
2525
"@sveltejs/kit": "^2.36.1",
2626
"@sveltejs/package": "2.5.0",
27+
"@typescript-eslint/parser": "^8.46.3",
2728
"eslint": "^9.33.0",
2829
"eslint-config-prettier": "^10.1.8",
2930
"eslint-plugin-svelte": "^3.11.0",

src/lib/index.svelte

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<script lang="ts">
22
import type { SvelteSeo } from './types';
3+
import transformKey from "../utils/transform-key";
4+
import OpenGraphComponent from "./open-graph.svelte";
35
46
interface Props extends SvelteSeo {}
57
@@ -24,8 +26,6 @@
2426
jsonLd,
2527
children
2628
}: Props = $props();
27-
28-
import OpenGraphComponent from "./open-graph.svelte";
2929
</script>
3030

3131
<svelte:head>
@@ -75,18 +75,8 @@
7575
<meta property="fb:app_id" content={facebook.appId} />
7676
{/if}
7777

78-
<meta
79-
name="robots"
80-
content={`${noindex ? "noindex" : "index"},${
81-
nofollow ? "nofollow" : "follow"
82-
}`}
83-
/>
84-
<meta
85-
name="googlebot"
86-
content={`${noindex ? "noindex" : "index"},${
87-
nofollow ? "nofollow" : "follow"
88-
}`}
89-
/>
78+
<meta name="robots" content={`${noindex ? "noindex" : "index"},${nofollow ? "nofollow" : "follow"}`} />
79+
<meta name="googlebot" content={`${noindex ? "noindex" : "index"},${nofollow ? "nofollow" : "follow"}`} />
9080

9181
{#if nositelinkssearchbox}
9282
<meta name="google" content="nositelinkssearchbox" />
@@ -98,12 +88,7 @@
9888

9989
{#if twitter}
10090
{#each Object.entries(twitter) as [key, value] (key)}
101-
{@const transformed = key
102-
.replace(/([a-z])([A-Z])/g, "$1:$2")
103-
.toLowerCase()}
104-
<!-- The `transformed` variable changes eg, twitter.title into twitter:title
105-
It loops over all the properties and changes the '.' into ':'
106-
-->
91+
{@const transformed = transformKey(key)}
10792
<meta name="twitter:{transformed}" content={value} />
10893
{/each}
10994
{/if}

src/lib/open-graph.svelte

Lines changed: 44 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,61 @@
11
<script lang="ts">
2-
import type { OpenGraph } from './types';
2+
import type { OpenGraph as OpenGraphType } from './types';
3+
import transformKey from "../utils/transform-key";
34
45
interface Props {
5-
openGraph: OpenGraph;
6+
openGraph: OpenGraphType;
67
}
78
89
const { openGraph }: Props = $props();
910
</script>
1011

1112
{#if openGraph}
1213
{#each Object.entries(openGraph) as [key, value] (key)}
13-
<!-- For openGraph, some of the keys have values as objects so we need to check
14-
before.
15-
-->
16-
{@const _type = typeof value}
17-
{#if _type !== "object"}
18-
{@const transform = key.replace(/([a-z])([A-Z])/g, "$1:$2").toLowerCase()}
19-
<meta property="og:{transform}" content={value} />
20-
{/if}
21-
{#if _type === "object"}
22-
{#if key === "images"}
23-
{#each openGraph.images ?? [] as image (image)}
24-
{#each Object.entries(image) as [key, value] (key)}
25-
<meta property="og:image:{key}" content={value.toString()} />
26-
{/each}
27-
{/each}
28-
{:else if key === "videos"}
29-
{#each openGraph.videos ?? [] as video (video.url)}
30-
{#each Object.entries(video) as [key, value] (key)}
31-
{#if key === "url"}
32-
<meta property="og:video" content={value.toString()} />
33-
{:else}
34-
<meta property="og:video:{key}" content={value.toString()} />
35-
{/if}
36-
{/each}
37-
{/each}
38-
{:else if key === "localeAlternate"}
39-
{#each openGraph.localeAlternate ?? [] as alternate (alternate)}
40-
<meta property="og:locale:alternate" content={alternate} />
41-
{/each}
42-
{:else if key === "music"}
43-
{#each Object.entries(openGraph.music ?? {}) as [key, value] (key)}
44-
{@const transform = key
45-
.replace(/([a-z])([A-Z])/g, "$1:$2")
46-
.toLowerCase()}
47-
<meta property="music:{transform}" content={value.toString()} />
48-
{/each}
49-
{:else if key === "movie"}
50-
{#each Object.entries(openGraph.movie ?? {}) as [key, value] (key)}
51-
{#if typeof value === "object"}
52-
{#each value as propValue (propValue)}
53-
<meta property="video:{key}" content={propValue} />
54-
{/each}
55-
{:else}
56-
{@const transform = key
57-
.replace(/([a-z])([A-Z])/g, "$1:$2")
58-
.toLowerCase()}
59-
<meta property="video:{transform}" content={value.toString()} />
60-
{/if}
61-
{/each}
62-
{:else if key === "article"}
63-
{#each Object.entries(openGraph.article ?? {}) as [key, value] (key)}
64-
{#if typeof value === "object"}
65-
{#each value as propValue (propValue)}
66-
<meta property="article:{key}" content={propValue} />
67-
{/each}
68-
{:else}
69-
{@const transform = key
70-
.replace(/([a-z])([A-Z])/g, "$1:$2")
71-
.toLowerCase()}
72-
<meta property="article:{transform}" content={value.toString()} />
14+
{#if value === null || value === undefined}
15+
<!-- Skip null/undefined values -->
16+
{:else if typeof value === "string" || typeof value === "number"}
17+
<!-- Simple string/number values -->
18+
{@const transformed = transformKey(key)}
19+
<meta property="og:{transformed}" content={value.toString()} />
20+
{:else if key === "images" && Array.isArray(value)}
21+
<!-- Images array -->
22+
{#each value as image (image)}
23+
{#each Object.entries(image) as [imgKey, imgValue] (imgKey)}
24+
{#if imgValue !== null && imgValue !== undefined}
25+
<meta property="og:image:{imgKey}" content={imgValue.toString()} />
7326
{/if}
7427
{/each}
75-
{:else if key === "book"}
76-
{#each Object.entries(openGraph.book ?? {}) as [key, value] (key)}
77-
{#if typeof value === "object"}
78-
{#each value as propValue (propValue)}
79-
<meta property="book:{key}" content={propValue} />
80-
{/each}
81-
{:else}
82-
{@const transform = key
83-
.replace(/([a-z])([A-Z])/g, "$1:$2")
84-
.toLowerCase()}
85-
<meta property="book:{transform}" content={value.toString()} />
28+
{/each}
29+
{:else if key === "videos" && Array.isArray(value)}
30+
<!-- Videos array -->
31+
{#each value as video (video.url)}
32+
{#each Object.entries(video) as [vidKey, vidValue] (vidKey)}
33+
{#if vidValue !== null && vidValue !== undefined}
34+
{@const prop = vidKey === "url" ? "og:video" : `og:video:${vidKey}`}
35+
<meta property={prop} content={vidValue.toString()} />
8636
{/if}
8737
{/each}
88-
{:else if key === "profile"}
89-
{#each Object.entries(openGraph.profile ?? {}) as [key, value] (key)}
90-
{@const transform = key
91-
.replace(/([a-z])([A-Z])/g, "$1:$2")
92-
.toLowerCase()}
93-
<meta property="profile:{transform}" content={value} />
94-
{/each}
95-
{/if}
38+
{/each}
39+
{:else if key === "localeAlternate" && Array.isArray(value)}
40+
<!-- Locale alternates -->
41+
{#each value as alternate (alternate)}
42+
<meta property="og:locale:alternate" content={alternate} />
43+
{/each}
44+
{:else if typeof value === "object" && value !== null}
45+
<!-- Complex objects (music, movie, article, book, profile) -->
46+
{@const prefix = key === "movie" ? "video" : key}
47+
{#each Object.entries(value) as [objKey, objValue] (objKey)}
48+
{#if Array.isArray(objValue)}
49+
<!-- Handle arrays (actors, authors, tags, etc.) -->
50+
{#each objValue as item (item)}
51+
<meta property="{prefix}:{objKey}" content={item} />
52+
{/each}
53+
{:else if objValue !== null && objValue !== undefined}
54+
<!-- Handle simple values -->
55+
{@const transformed = transformKey(objKey)}
56+
<meta property="{prefix}:{transformed}" content={objValue.toString()} />
57+
{/if}
58+
{/each}
9659
{/if}
9760
{/each}
9861
{/if}

src/lib/types.d.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ export interface SvelteSeo {
1010
themeColor?: string;
1111
nofollow?: boolean;
1212
noindex?: boolean;
13-
nositelinkssearchbox: boolean;
14-
notranslate: boolean;
13+
nositelinkssearchbox?: boolean;
14+
notranslate?: boolean;
1515
canonical?: string;
1616
amp?: string;
1717
manifest?: string;
@@ -23,11 +23,11 @@ export interface SvelteSeo {
2323
children?: Snippet<[]>;
2424
}
2525

26-
declare interface Facebook {
26+
export interface Facebook {
2727
appId: string;
2828
}
2929

30-
declare interface Twitter {
30+
export interface Twitter {
3131
title?: string;
3232
description?: string;
3333
image?: string;
@@ -49,7 +49,7 @@ declare interface Twitter {
4949
appUrlGoogleplay?: string;
5050
}
5151

52-
declare interface OpenGraph {
52+
export interface OpenGraph {
5353
title?: string;
5454
type?: string;
5555
url?: string;
@@ -84,7 +84,7 @@ declare interface OpenGraph {
8484
profile?: OpenGraphProfile;
8585
}
8686

87-
declare interface OpenGraphMusic {
87+
export interface OpenGraphMusic {
8888
duration?: number | string;
8989
album?: string;
9090
albumDisc?: number;
@@ -97,7 +97,7 @@ declare interface OpenGraphMusic {
9797
release_date?: string;
9898
}
9999

100-
declare interface OpenGraphVideo {
100+
export interface OpenGraphVideo {
101101
actor?: string[];
102102
actorRole?: string;
103103
director?: string[];
@@ -108,7 +108,7 @@ declare interface OpenGraphVideo {
108108
series?: string;
109109
}
110110

111-
declare interface OpenGraphArticle {
111+
export interface OpenGraphArticle {
112112
published_time?: string;
113113
modified_time?: string;
114114
expiration_time?: string;
@@ -117,14 +117,14 @@ declare interface OpenGraphArticle {
117117
tag?: string[];
118118
}
119119

120-
declare interface OpenGraphBook {
120+
export interface OpenGraphBook {
121121
author?: string[];
122122
isbn?: string | number;
123123
release_date?: string;
124124
tag?: string[];
125125
}
126126

127-
declare interface OpenGraphProfile {
127+
export interface OpenGraphProfile {
128128
first_name?: string;
129129
last_name?: string;
130130
username?: string;

src/tests/seo.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ test.describe("Testing SEO and meta tags", () => {
2424
test("Loads the keywords tag correctly", async ({ page }) => {
2525
const element = page.locator("meta[name='keywords']");
2626
const keywords = await element.getAttribute("content");
27-
expect(keywords, "Must render keywords tag").toBe("svelte,sveltekit,web");
27+
expect(keywords, "Must render keywords tag").toBe("svelte, sveltekit, web");
2828
expect(
2929
keywords?.split(",").length,
3030
"Loads the right number of keywords",

src/utils/transform-key.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default function transformKey(key: string): string;

src/utils/transform-key.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Helper function to change eg, twitter.title into twitter:title
2+
export default function transformKey(key: string): string {
3+
return key.replace(/([a-z])([A-Z])/g, "$1:$2").toLowerCase();
4+
}

0 commit comments

Comments
 (0)