janosh / svelte-toc

Sticky responsive table of contents component
https://janosh.github.io/svelte-toc
MIT License
112 stars 6 forks source link

Getting error about resolving `$app/stores` #15

Closed atsepkov closed 2 years ago

atsepkov commented 2 years ago

Hi, I've tried setting up the module as described in the README, but getting the following error when starting the app. I'm using webpack instead of SvelteKit, not sure if the error is due to an incompatibility of some sort:

Module not found: Error: Can't resolve '$app/stores' in '/Users/alex/work/personal/app/node_modules/svelte-toc'
resolve '$app/stores' in '/Users/alex/work/personal/app/node_modules/svelte-toc'
  Parsed request is a module
  using description file: /Users/alex/work/personal/app/node_modules/svelte-toc/package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    resolve as module
...

I did find the relevant line in Toc.svelte, I just don't understand how this $app/stores import works, I don't see it as a library in package.json, so I'm guessing it's some sort of magic that's not properly setup on my project?

Thanks

janosh commented 2 years ago

@atsepkov Thanks for reporting. I've never used SvelteKit with Webpack so I don't what config you might be missing.

But your guess is correct, this import is provided by SvelteKit itself (see the docs) and isn't for instance available in Sapper, making svelte-toc SvelteKit-only. There used to be this line about it in the readme.

I originally started using the page store to detect route changes and re-query the DOM for headings to list so the component stays in sync with the content. But SvelteKit changed a lot since then. Maybe there's a better solution to this. Could you simply comment out the $app/stores import and see if the ToC still stays up to date when navigating between pages? Maybe we can drop it altogether.

atsepkov commented 2 years ago

Commenting out that line as well as the page.subscribe(requery_headings) line making use of that import in the doc did seem to make the timeline mostly work. It no longer automatically updates with sections as headings are added to the document, but I added a work-around by adding use:reload to headings are they're rendered and having reload function that updates the key Toc element listens to.

The only part I'm still struggling with (unrelated to the original issue, but maybe you know of a quick fix) is that the document scrolling seems to break due to Toc rendering unless I put the 2 elements together into a display: flex element, but setting that element to flex seems to in turn break the mobile pop-out menu that my app uses (it also uses aside element - rendered via svelte-materialify library).

janosh commented 2 years ago

It no longer automatically updates with sections as headings are added to the document

I don't think it was doing that before either. It would only update when the page store changes, i.e. on navigation events.

I added a work-around by adding use:reload to headings are they're rendered and having reload function that updates the key Toc element listens to.

Sounds a bit like your loosing encapsulation since the job of ToC is now partially performed by the headings themselves but if it works for you, that's good.

It would still be nice to find a more robust/permanent solution. There's a discussion about getting headings in SSR that's slightly related: https://github.com/sveltejs/kit/discussions/3230. Maybe there's something Kit could offer here to make updating on new DOM heading nodes easier in the future.

The only part I'm still struggling with (unrelated to the original issue, but maybe you know of a quick fix) is that the document scrolling seems to break due to Toc rendering unless I put the 2 elements together into a display: flex element

Have you tried setting keepActiveTocItemInView={false}. If that removes the problem, we know for sure where the issue comes from.

atsepkov commented 2 years ago

Thanks! That setting was exactly what I was looking for. Menu now aligns as expected, I still have a minor problem with it in that the section that gets marked as selected inside ToC element after clicking it seems to be off by 1 (highlighting previous section title instead of current, even though the scrolling location on the page seems to be correct - it shows about 100px of content from the past section but I believe that's due to activeTopOffset). Setting activeTopOffset to a lower value in case the problem was due to that seems to have no effect.

janosh commented 2 years ago

Hard to say what's going wrong without seeing the problem and having dev tools to inspect the page.

janosh commented 2 years ago

@atsepkov Since #19, specifically https://github.com/janosh/svelte-toc/commit/939d5db0a39c2738eb58d20b6cad4f2a7f6c8324, Toc.svelte no longer uses any SvelteKit-specific objects like the page store. Instead it relies solely on browser APIs, namely MutationObserver. I expect this change also fixes your issue. Maybe you want to give it another try?

atsepkov commented 2 years ago

Sorry for the slow response, I've been using the local version with the fix applied and just had a chance to refactor it back to using the official version. Thank you, the change does indeed fix my issue. On a related note, I remember seeing a way to disable certain headers from being picked up by TOC but can't seem to find that in the README anymore. Was that one of the features or am I imagining things?

EDIT: Found it, toc-exclude is the option I was looking for. Once again, thank you for building the component.