diff --git a/svelte-app/.eslintrc b/svelte-app/.eslintrc
index 7a2961009..fd86f5bfa 100644
--- a/svelte-app/.eslintrc
+++ b/svelte-app/.eslintrc
@@ -11,6 +11,7 @@
"es2017": true
},
"extends": [
+ "prettier",
"eslint:recommended",
"plugin:svelte/recommended",
"plugin:@typescript-eslint/recommended"
@@ -26,6 +27,10 @@
"@typescript-eslint/no-namespace": ["off"],
"@typescript-eslint/restrict-template-expressions": ["off"],
"@typescript-eslint/no-unused-vars": ["off"],
+ "@typescript-eslint/no-duplicate-imports": ["error"],
+ "@typescript-eslint/ban-ts-comment": ["error", {
+ "ts-expect-error": "allow-with-description"
+ }],
"array-bracket-spacing": ["error", "never"],
"arrow-spacing": ["error"],
"block-scoped-var": ["error"],
@@ -42,7 +47,7 @@
"keyword-spacing": ["error"],
"linebreak-style": ["error"],
"no-confusing-arrow": ["error"],
- "no-duplicate-imports": ["error"],
+ "no-duplicate-imports": ["off"],
"no-trailing-spaces": ["error"],
"no-var": ["error"],
"no-eval": ["error"],
@@ -58,7 +63,14 @@
"no-unused-vars": ["off"],
"object-shorthand": ["error"],
"one-var-declaration-per-line": ["error"],
- "prettier/prettier": ["error"],
+ "prettier/prettier": ["error", {
+ "bracketSpacing": true,
+ "svelteBracketNewLine": true
+ }, {
+ "usePrettierrc": true
+ }],
+ "arrow-body-style": ["off"],
+ "prefer-arrow-callback": ["off"],
"quotes": ["error", "single", { "avoidEscape": true }],
"quote-props": ["error", "as-needed"],
"semi": ["error", "always"],
diff --git a/svelte-app/.prettierrc.json b/svelte-app/.prettierrc.json
index 5f91cbfb8..b7faff4e4 100644
--- a/svelte-app/.prettierrc.json
+++ b/svelte-app/.prettierrc.json
@@ -6,6 +6,8 @@
"singleQuote": true,
"trailingComma": "none",
"printWidth": 90,
+ "svelteBracketNewLine": true,
+ "bracketSpacing": true,
"plugins": [
"./node_modules/prettier-plugin-svelte",
"./node_modules/prettier-plugin-tailwindcss"
diff --git a/svelte-app/src/components/code-block.svelte b/svelte-app/src/components/code-block.svelte
index ae9914a0b..1f6f58fc4 100644
--- a/svelte-app/src/components/code-block.svelte
+++ b/svelte-app/src/components/code-block.svelte
@@ -1,24 +1,20 @@
- {#if hlStyles}
+ {#if HighlightStyles}
- {@html hlStyles}
+ {@html HighlightStyles}
{/if}
@@ -122,7 +114,6 @@
role="group"
aria-label={$t('Code block')}
aria-labelledby={filename ? `${id}-filename` : undefined}
- bind:this={container}
>
{#if filename}
{/if}
-
-
- {#key copied}
-
- {/key}
-
-
+
+ {#key copied}
+
+ {/key}
+
{/if}
- {#if !lang}
-
- {:else}
- {#await hlLang then resolvedLang}
+
+ {#await Promise.all([HighlightSvelte, Highlight, LanguageType, LineNumbers]) then [resolvedHighlightSvelte, resolvedHighlight, resolvedLang, resolvedLineNumbers]}
+
{#if showLineNumbers === true}
-
-
- {:else}
-
+ this={resolvedLineNumbers}
+ {highlighted}
+ hideBorder
+ wrapLines
+ />
{/if}
- {:catch error}
- Error loading: {error.message}
- {/await}
- {/if}
+
+ {:catch error}
+
Error loading: {error.message}
+ {/await}
diff --git a/svelte-app/src/components/code-block/imports.ts b/svelte-app/src/components/code-block/imports.ts
new file mode 100644
index 000000000..574da28c1
--- /dev/null
+++ b/svelte-app/src/components/code-block/imports.ts
@@ -0,0 +1,81 @@
+import { SvelteComponent } from 'svelte';
+import { derived, readable, writable } from 'svelte/store';
+
+import type { ComponentType } from 'svelte';
+import type {
+ HighlightEvents,
+ HighlightProps,
+ HighlightSlots
+} from 'svelte-highlight/Highlight.svelte';
+import type {
+ HighlightSvelteEvents,
+ HighlightSvelteProps,
+ HighlightSvelteSlots
+} from 'svelte-highlight/HighlightSvelte.svelte';
+import type {
+ LineNumbersEvents,
+ LineNumbersProps,
+ LineNumbersSlots
+} from 'svelte-highlight/LineNumbers.svelte';
+
+class _LineNumbers extends SvelteComponent<
+ LineNumbersProps,
+ LineNumbersEvents,
+ LineNumbersSlots
+> {}
+class _HighlightSvelte extends SvelteComponent<
+ HighlightSvelteProps,
+ HighlightSvelteEvents,
+ HighlightSvelteSlots
+> {}
+class _Highlight extends SvelteComponent<
+ HighlightProps,
+ HighlightEvents,
+ HighlightSlots
+> {}
+
+export type LineNumbers = ComponentType<_LineNumbers>;
+export type HighlightSvelte = ComponentType<_HighlightSvelte>;
+export type Highlight = ComponentType<_Highlight>;
+
+const stores = {
+ LineNumbers: writable | undefined>(undefined),
+ HighlightSvelte: writable | undefined>(undefined),
+ Highlight: writable | undefined>(undefined)
+} as const;
+
+const genericDerivedAsyncImport = (
+ name: K,
+ target: (typeof stores)[K]
+ ) =>
+ derived(target, (value: Parameters<(typeof target)['set']>[0]) => {
+ if (value === undefined) {
+ const promise = import(
+ `../../../node_modules/svelte-highlight/${name}.svelte`
+ ).then((module) => module.default) as unknown as NonNullable;
+ // @ts-expect-error - TS infers target['set'] here as an Intersection of Writable ReturnTypes rather than Unions
+ target.set(promise);
+ return promise;
+ }
+ return value;
+ }),
+ empty = () =>
+ readable>(new Promise((resolve) => resolve(undefined)));
+
+const lineNumbers = (useLineNumbers: boolean) => {
+ return useLineNumbers
+ ? genericDerivedAsyncImport('LineNumbers', stores.LineNumbers)
+ : empty();
+ },
+ highlightSvelte = (useHlSvelte: boolean) => {
+ return useHlSvelte
+ ? genericDerivedAsyncImport('HighlightSvelte', stores.HighlightSvelte)
+ : empty();
+ },
+ highlight = () => genericDerivedAsyncImport('Highlight', stores.Highlight);
+
+export {
+ highlight as Highlight,
+ highlightSvelte as HighlightSvelte,
+ lineNumbers as LineNumbers
+};
diff --git a/svelte-app/src/components/icon.svelte b/svelte-app/src/components/icon.svelte
index 8b3ee6e9e..10ea93093 100644
--- a/svelte-app/src/components/icon.svelte
+++ b/svelte-app/src/components/icon.svelte
@@ -8,17 +8,18 @@
width = 20,
height = width,
style = '';
+
+ const svg = icons.get(icon);
- {#await icons.get(icon) then svg}
-
- {/await}
+
diff --git a/svelte-app/src/components/portable-text/portable-text.svelte b/svelte-app/src/components/portable-text/portable-text.svelte
index d1acab650..2abf9eb49 100644
--- a/svelte-app/src/components/portable-text/portable-text.svelte
+++ b/svelte-app/src/components/portable-text/portable-text.svelte
@@ -6,6 +6,7 @@
import Logger from '$lib/logger';
import Icon from '$components/icon.svelte';
+ import Link from '$components/link.svelte';
import { PortableText } from '@portabletext/svelte';
@@ -138,20 +139,15 @@
{#each footnotes as note}
-
-
-
+
- customScrollTo(e, `src-${note._key}`)}
- on:keydown={(e) => {
- if (e.code === 'Space' || e.code === 'Enter') {
- customScrollTo(e, `src-${note._key}`);
- }
- }}> customScrollTo(e, `note-${note._key}`)}
+ >
diff --git a/svelte-app/src/components/portable-text/serializers/custom-heading.svelte b/svelte-app/src/components/portable-text/serializers/custom-heading.svelte
index 385d355d1..9f8585251 100644
--- a/svelte-app/src/components/portable-text/serializers/custom-heading.svelte
+++ b/svelte-app/src/components/portable-text/serializers/custom-heading.svelte
@@ -1,38 +1,44 @@
-
-
+
+
- {#if hovered}
-
- {/if}
-
-
-
-
-
-
+
+
+