Skip to content

Commit 6565e46

Browse files
committed
fix(toc): misc fixes and playground
1 parent 2b84756 commit 6565e46

10 files changed

Lines changed: 226 additions & 22 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"@svelte-put/toc": patch
3+
---
4+
5+
.
6+
7+
- Fixed broken imports from `Toc.svelte`
8+
- Better caching: only return cache when parameters are the same
9+
- Temporarily fix the onMount issue where action doesn't run if page is loaded / navigated to from client side
10+
- Added playground page for `svelte-put/toc`

apps/svelte-kit/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
"author": "Quang Phan",
1414
"license": "MIT",
1515
"devDependencies": {
16+
"@svelte-put/avatar": "workspace:^",
1617
"@svelte-put/clickoutside": "workspace:^",
1718
"@svelte-put/eslint-config": "workspace:^",
1819
"@svelte-put/intersect": "workspace:^",
1920
"@svelte-put/movable": "workspace:^",
2021
"@svelte-put/prettierrc": "workspace:^",
22+
"@svelte-put/toc": "workspace:^",
2123
"@sveltejs/adapter-auto": "next",
2224
"@sveltejs/kit": "1.0.0-next.396",
2325
"cssnano": "^5.1.12",

apps/svelte-kit/src/app.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ declare namespace svelte.JSX {
4040
onintersect?: (event: CustomEvent<import('@svelte-put/intersect').IntersectDetail>) => void;
4141
// on:intersectonce
4242
onintersectonce?: (event: CustomEvent<import('@svelte-put/intersect').IntersectDetail>) => void;
43+
// on:toc
44+
ontoc?: (event: CustomEvent<import('@svelte-put/toc').TocEventDetails>) => void;
4345
}
4446
}
4547

apps/svelte-kit/src/routes/index.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
<script lang="ts">
2-
</script>
3-
41
<title>@svelte-put</title>
52

63
<main class="grid w-full flex-1 place-items-center">
@@ -16,5 +13,8 @@
1613
<li>
1714
<a href="/clickoutside" class="hover:text-primary">@svelte-put/clickoutside</a>
1815
</li>
16+
<li>
17+
<a href="/toc" class="hover:text-primary">@svelte-put/toc</a>
18+
</li>
1919
</ul>
2020
</main>
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<script lang="ts" context="module">
2+
import { toc } from '@svelte-put/toc';
3+
import type { TocEventDetails } from '@svelte-put/toc';
4+
import Toc from '@svelte-put/toc/Toc.svelte';
5+
</script>
6+
7+
<script lang="ts">
8+
function onToc(e: CustomEvent<TocEventDetails>) {
9+
const { items } = e.detail;
10+
}
11+
</script>
12+
13+
<main class="p-20 flex flex-col gap-y-10">
14+
<h1 class="text-center text-6xl">H1. Example Blog</h1>
15+
<p class="text-center italic">Some subtitle / summary / description</p>
16+
<h2>h2.1 Table of Contents</h2>
17+
<Toc on:toc={onToc} />
18+
<h2>h2.2 Lorem ipsum dolor sit, amet consectetur adipisicing elit</h2>
19+
<p>
20+
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Vel necessitatibus maxime, blanditiis
21+
impedit, facere quo rem autem soluta architecto voluptate ea optio nemo sit laborum culpa?
22+
Perspiciatis veritatis maiores earum.
23+
</p>
24+
<h3>h3. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Odit, perferendis!</h3>
25+
<p>
26+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis culpa incidunt sit
27+
necessitatibus, error, dolorem est, optio tenetur veniam repudiandae ea soluta perspiciatis
28+
repellat quis voluptatum hic? Optio deserunt quis sapiente nisi sunt, explicabo totam, in
29+
consequatur quas perferendis corrupti ipsa saepe rerum voluptatibus ad reiciendis laborum cumque
30+
delectus voluptates nemo, atque magnam! Repellat debitis harum placeat tempore, quas ipsam
31+
dolore sit deleniti numquam. Officia officiis, ullam quae odit eligendi doloribus quasi esse
32+
dolorem voluptate eveniet quo recusandae harum mollitia. Sed fuga nihil natus nisi deserunt
33+
cumque, similique odit ut magnam perferendis doloribus ad magni quod ratione quisquam recusandae
34+
eaque enim quam, cupiditate excepturi. Molestiae cum, maiores dolor corrupti expedita aliquam!
35+
Dolor et fugit magnam maxime harum, numquam ipsum commodi. Placeat sunt modi vel recusandae
36+
minus provident optio consequatur nam fuga qui porro ea corrupti, ex voluptatem illum mollitia
37+
nemo. Accusantium dicta explicabo tenetur facilis nemo quis voluptates, iure necessitatibus et,
38+
nulla alias dolore ipsum error consequuntur optio quia assumenda aliquam id similique non unde,
39+
ea rerum. Quasi unde delectus accusantium? Ducimus saepe dolor voluptas odit dicta iusto, vel
40+
ipsum ratione facilis iste. Velit illo, nesciunt minima modi quae autem in quisquam suscipit.
41+
Dignissimos corrupti ad sint natus commodi quisquam?
42+
</p>
43+
<p>
44+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Unde, numquam earum? Molestias nisi,
45+
recusandae tempora explicabo, distinctio error accusamus porro odit maiores mollitia dignissimos
46+
vel asperiores sapiente molestiae quam delectus amet qui ratione et voluptatum fugit adipisci
47+
sint possimus? Repellat similique asperiores odio vero. Voluptatibus alias sapiente sequi
48+
asperiores, libero numquam recusandae vero quibusdam assumenda commodi exercitationem fuga vel
49+
adipisci. Provident blanditiis dignissimos voluptatum vero odio eveniet, neque placeat libero
50+
deserunt dolorem quas veritatis facilis repellat vitae inventore distinctio quasi ea tenetur.
51+
Inventore, expedita, eum odit cupiditate earum cum reprehenderit mollitia eligendi eveniet autem
52+
vitae enim qui atque, nemo architecto.
53+
</p>
54+
<h3>h3 Lorem, ipsum dolor.</h3>
55+
<p>
56+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ducimus voluptates, quisquam
57+
perferendis dolorum debitis fuga suscipit dicta nisi fugit tempore officia aspernatur ut, eius a
58+
magnam architecto dolor laborum possimus aliquid culpa! Dolorum, possimus?
59+
</p>
60+
<p>
61+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellat, laboriosam molestiae
62+
voluptatibus porro temporibus repellendus cumque mollitia modi aliquid ab nulla? Eum, soluta
63+
perspiciatis? Tempora ipsa maxime molestiae minima temporibus deleniti animi? Nesciunt corrupti
64+
dolor dolorum consequatur consectetur amet alias in incidunt doloremque, tenetur, possimus
65+
reprehenderit itaque officiis eius molestias ut fuga, accusamus voluptate unde distinctio.
66+
Architecto, repudiandae. Deserunt aperiam alias accusantium, doloremque repellendus ratione hic
67+
expedita assumenda. Incidunt in laudantium quaerat dignissimos, perferendis accusantium est qui,
68+
libero consectetur necessitatibus asperiores provident! Sequi consequatur doloribus repellat
69+
natus tempora repudiandae eius asperiores blanditiis veniam! Cupiditate, architecto aperiam? Et
70+
ipsa quam autem.
71+
</p>
72+
<h4>
73+
h4. Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus amet soluta voluptatem
74+
quo eum, culpa vitae facilis modi ratione a.
75+
</h4>
76+
<p>
77+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor ipsum deleniti corrupti. Ipsam,
78+
quas cum eligendi iure soluta modi tempora eius, vero vel sit quos distinctio dicta excepturi
79+
reprehenderit. Cumque dolorum modi nobis animi voluptas obcaecati consequuntur quo placeat
80+
nihil, temporibus ex provident, quibusdam quidem asperiores ut qui maiores eius commodi! Non
81+
velit impedit nihil eaque ad magni explicabo tempore fugit veniam qui vel optio architecto omnis
82+
doloribus asperiores odit iure at sunt, nulla voluptas expedita maiores dolorem enim. Libero
83+
atque tenetur vitae autem assumenda nisi enim rerum odit quo suscipit id incidunt sunt adipisci
84+
non, quibusdam quam inventore qui unde fuga, aliquid soluta nostrum natus nihil? Eaque porro
85+
dolorem eos libero dolorum doloribus officia eius magnam deserunt. Mollitia voluptatum, sapiente
86+
pariatur rerum dolorem nemo culpa cupiditate corporis ad? Eveniet non quasi fugiat iste
87+
consequuntur, ea, exercitationem repellendus alias itaque error eos vero molestiae, inventore
88+
earum? Sunt rem praesentium tenetur incidunt qui, atque ut pariatur debitis temporibus veritatis
89+
quisquam odit iure blanditiis, laborum sequi? Dignissimos exercitationem necessitatibus nostrum
90+
id veritatis dolore non suscipit quidem officiis facilis enim, fugiat nemo saepe assumenda?
91+
Excepturi, illo eius dolorum asperiores explicabo, labore nam, eligendi commodi suscipit numquam
92+
aliquam optio provident iusto. Cumque ipsa aliquid explicabo sapiente quod perspiciatis
93+
doloribus, consequatur veritatis corporis ratione, quaerat eaque ducimus temporibus? Nisi rerum
94+
quasi earum repudiandae illo vel quo quaerat beatae dolorem deleniti ipsum, amet tenetur
95+
temporibus voluptatibus ducimus cumque vitae? Dicta id minus iste impedit in harum vel
96+
voluptatem labore? Optio esse quisquam, eaque quis illum nobis fugit labore praesentium quaerat
97+
sit ducimus maxime ex repellendus voluptatibus, maiores inventore numquam. Expedita ducimus
98+
doloremque placeat eveniet dolore quos corporis autem quidem excepturi optio omnis architecto
99+
nihil ipsam laborum a dolorem maxime vel inventore laudantium assumenda ad, rerum esse! Cumque
100+
necessitatibus accusantium blanditiis eos suscipit eligendi eveniet voluptas et!
101+
</p>
102+
<h2>
103+
h2.3 Lorem ipsum dolor sit amet consectetur, adipisicing elit. Facilis natus eum totam quo sed?
104+
</h2>
105+
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, eveniet?</p>
106+
<p>
107+
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Necessitatibus itaque velit nemo
108+
nihil, totam praesentium architecto minima aperiam eligendi tenetur est atque asperiores nobis.
109+
Ullam est modi iusto libero, placeat quod amet quis, minus dicta voluptate expedita sit
110+
exercitationem fugit fuga unde. Et reiciendis iure, asperiores tenetur accusamus repellendus
111+
illum minus hic impedit ratione, accusantium quisquam tempora porro labore doloremque quae aut
112+
suscipit nisi est. Ut delectus temporibus deserunt quos sequi numquam vel itaque laborum facere,
113+
ullam doloribus ea, omnis soluta repellat veniam accusantium odio et magnam illum sed. Beatae
114+
explicabo repellat maxime nulla atque officiis odit deserunt fugiat iusto repudiandae
115+
aspernatur, eos, blanditiis at distinctio consequatur sed dolore ea. Enim adipisci qui, quos
116+
optio dolorum, voluptatibus iusto non soluta, neque sint ducimus! Placeat similique laudantium
117+
fuga magni mollitia porro minus. Amet eos dolorum deserunt atque ea obcaecati? Incidunt deleniti
118+
qui reprehenderit minima enim repellat magni modi in eius quas nisi deserunt pariatur, quod
119+
repudiandae delectus, temporibus reiciendis, animi inventore facere? Minima error, aut dolorum
120+
quisquam repellendus aliquid quas ad tempore id reiciendis nostrum necessitatibus illum fugit
121+
enim quae consequuntur maxime ipsum sint! Quos eius neque quisquam aliquid accusantium voluptas
122+
aspernatur reprehenderit blanditiis asperiores enim, consequatur laboriosam. Iste, maxime harum.
123+
</p>
124+
<p>
125+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Beatae, dolorum unde! Debitis ut,
126+
eveniet nesciunt id, omnis necessitatibus consequatur incidunt, ratione rem totam eligendi
127+
placeat sapiente at. In aperiam architecto repellat et numquam nesciunt soluta excepturi rerum
128+
aliquid molestias ipsum minima quidem unde suscipit nostrum ut dicta, necessitatibus eius vero
129+
voluptate quasi laboriosam? Possimus, perferendis.
130+
</p>
131+
<h2>h2.4 Lorem ipsum dolor sit amet consectetur adipisicing elit. Id, explicabo.</h2>
132+
<p>
133+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ducimus sed aut molestias cum qui quasi
134+
error quos voluptas autem. Veniam quaerat ducimus necessitatibus deserunt, eum fugiat temporibus
135+
exercitationem quod porro odio earum nesciunt maiores amet debitis dolorem officiis in? Magni
136+
deserunt placeat, laboriosam est sapiente ex velit adipisci et similique eum atque cumque!
137+
Officia et neque doloremque nisi dicta perspiciatis sed sunt nostrum officiis molestias
138+
similique, quae numquam facilis nesciunt, error, tempore velit. Atque quos quo eaque nulla
139+
pariatur illum incidunt, exercitationem officiis expedita ex, molestiae rem! Blanditiis, ea!
140+
Molestias fuga molestiae ratione non tempora enim quisquam iure ad vitae?
141+
</p>
142+
</main>
143+
144+
<style lang="postcss">
145+
h2 {
146+
@apply text-2xl;
147+
}
148+
h3 {
149+
@apply text-xl;
150+
}
151+
h4 {
152+
@apply text-lg;
153+
}
154+
h1,
155+
h2,
156+
h3,
157+
h4 {
158+
@apply font-bold;
159+
}
160+
161+
:global(.toc-li:hover) {
162+
@apply text-primary underline;
163+
}
164+
</style>

packages/actions/toc/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
"typesVersions": {
1717
"*": {
1818
"toc": [
19-
"./lib/toc.d.ts"
19+
"./lib/action/index.d.ts"
2020
],
2121
"Toc.svelte": [
22-
"./lib/Toc.svelte.d.ts"
22+
"./lib/component/Toc.svelte.d.ts"
2323
]
2424
}
2525
},

packages/actions/toc/src/lib/action/toc.action.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import { onMount, tick } from 'svelte';
1+
import { tick } from 'svelte';
22

3-
import { resolveParameters, restoreTocItems, transformTocItems } from './toc.operations';
4-
import type { TocParameters, TocEventDetails, TocEventItemDetails } from './toc.types';
3+
import { compareParameters, resolveParameters, restoreTocItems, transformTocItems } from './toc.operations';
4+
import type { TocParameters, TocEventDetails, TocEventItemDetails, ResolvedTocParameters } from './toc.types';
55

6-
const cache: Record<string, TocEventItemDetails[]> = {};
6+
const cache: Record<string, {
7+
parameters: ResolvedTocParameters;
8+
items: TocEventItemDetails[];
9+
}> = {};
710

811
/**
912
* Find matching DOM elements for building table of contents
@@ -29,35 +32,40 @@ const cache: Record<string, TocEventItemDetails[]> = {};
2932
export function toc(node: HTMLElement, parameters: Partial<TocParameters> = {}) {
3033
let resolved = resolveParameters(parameters);
3134

32-
let elements: Element[];
35+
let elements: Element[] = [];
3336

3437
function extract() {
3538
let id = node.getAttribute('data-toc-id') || '';
3639
let items: TocEventItemDetails[];
3740
elements = Array.from(node.querySelectorAll(resolved.selector));
38-
if (id) {
39-
// FIXME: potential problem: parameters might change => need to rerun
40-
// solution: also compare the resolved parameters
41-
items = cache[id];
41+
if (id && cache[id] && compareParameters(cache[id].parameters, resolved)) {
42+
items = cache[id].items;
4243
} else {
4344
id = crypto.randomUUID();
4445
items = transformTocItems(elements as HTMLElement[], resolved);
45-
cache[id] = items;
46+
cache[id] = { items, parameters: resolved };
4647
node.setAttribute('data-toc-id', id);
4748
}
4849

4950
const detail: TocEventDetails = { items, id };
50-
setTimeout(() => {
51-
node.dispatchEvent(new CustomEvent('toc', { detail }));
52-
}, 0);
51+
node.dispatchEvent(new CustomEvent('toc', { detail }));
5352
return detail;
5453
}
5554

5655
function cleanup() {
56+
const id = node.getAttribute('data-toc-id') || '';
57+
if (id) {
58+
delete cache[id];
59+
}
5760
restoreTocItems(elements as HTMLElement[], resolved);
5861
}
5962

60-
onMount(async () => {
63+
// svelte's onMount is more appropriate here instead of setTimeout.
64+
// But currently, due to this bug: https://github.com/sveltejs/svelte/issues/7735
65+
// it is not working as intended, setTimeout here is a temporary solution
66+
// it might not work if a large-contented page takes too long to render?
67+
setTimeout(async () => {
68+
await tick();
6169
const { items } = extract();
6270
if (resolved.stimulateHashNavigation) {
6371
const hash = location.hash?.substring(1);
@@ -74,7 +82,7 @@ export function toc(node: HTMLElement, parameters: Partial<TocParameters> = {})
7482
}
7583
}
7684
}
77-
});
85+
}, 50);
7886

7987
return {
8088
update(update: Partial<TocParameters>) {

packages/actions/toc/src/lib/action/toc.operations.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ import { DEFAULT_TOC_PARAMETERS } from './toc.constants';
22
import type { TocParameters, TocEventItemDetails, ResolvedTocParameters } from './toc.types';
33
import { slugify } from './toc.utils';
44

5+
/**
6+
* Compare two ResolvedTocParameters
7+
* @internal
8+
* @param p1 first parameters object to compare
9+
* @param p2 second parameters object to compare
10+
* @returns whether 2 parameters objects have the same properties
11+
*/
12+
export function compareParameters(p1: ResolvedTocParameters, p2: ResolvedTocParameters) {
13+
return Object.keys(p1).every((key) => {
14+
const typedKey = key as keyof ResolvedTocParameters;
15+
return p1[typedKey] === p2[typedKey];
16+
});
17+
}
18+
519
/**
620
* Resolve the raw {@link TocParameters} object from `toc` input
721
* @internal

packages/actions/toc/src/lib/component/Toc.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script lang="ts">
22
import { createEventDispatcher } from 'svelte';
33
4-
import { toc } from './toc';
5-
import type { TocEventDetails, TocEventItemDetails, TocParameters } from './toc.types';
4+
import { toc } from '../action';
5+
import type { TocEventDetails, TocEventItemDetails, TocParameters } from '../action';
66
77
export let parameters: Partial<TocParameters> = {};
88
export let ulClass = '';

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)