npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

svelte-breadcrumbs

v2.0.0

Published

- [Usage](#usage) - [Install](#install) - [Setting up the `Breadcrumb` component](#setting-up-the-breadcrumb-component) - [Customizing route titles](#customizing-route-titles) - [Component Docs](#full-component-docs)

Downloads

337

Readme

Svelte-Breadcrumbs

Svelte-Breadcrumbs makes it easy to generate meaningful breadcrumbs by leveraging Svelte's directory structure and Module Context Exports.

For example, when navigating to a route such as /todos/[id]/edit with the URL Pathname being /todos/1/edit you can immediately generate the breadcrumb todos > 1 > edit.

Replacing the id 1 with meaningful data such as the todo's name proves to be slightly more difficulty. The crux of this issue lies in the fact that we are currently on the /todos/[id]/editpage, so any breadcrumb ui elements generated in/todos/[id]/+page.svelteor breadcrumb data returned in/todos/[id]/+page.server.ts will not be immediately available.

With Svelte-Breadcrumbs, the route id is first split (e.g. /todos/[id]/edit -> ['todos', '[id]', 'edit']) giving us the directory for each route. We then import the +page.svelte file from the corresponding directory and access a constant string pageTitle or getter function getPageTitle that was exported. The getter function is called with the current page's data passed in as a parameter.

The title is then generated with the following priority, each one acting as a fallback for it's greater:

  1. Page data crumbs property which overrides the entire crumbs array
  2. pageTitle: string variable in the svelte page's module context
  3. getPageTitle(data: any) -> string function in the svelte page's module context
  4. The value in the original URL route path

Breadcrumb title definition can now exist within the view itself!

The biggest drawback of this solution is that getter functions have no way of knowing the data that will be provided to them at compile time which can make development a bit tricky. It can be hard to know if a page has the data the getter will need, but this is why the fallbacks exist.

Another drawback I see is that the glob import in Breadcrumbs.svelte may be inefficient, specifically may be storing extra data in memory. This hasn't proven to be an issue for my project, but I'm not completely sure how it would fare in larger projects with more Svelte files...

Usage

Install

$ npm i svelte-breadcrumbs

Setting up the Breadcrumb component

In +layout.svelte:

<!--
Add the `Breadcrumbs` component and feed in the current page url
and the route id.
-->
<Breadcrumbs url={$page.url} routeId={$page.route.id}>
  {#snippet children({ crumbs })}
    <div>
      <span><a href="/">Home</a></span>
      <!--
      Loop over the generated crumbs array
      -->
      {#each crumbs as c}
        <span>/</span>
        <span>
          <a href={c.url}>
            {c.title}
          </a>
        </span>
      {/each}
    </div>
  {/snippet}
</Breadcrumbs>

In the example above, Breadcrumbs.svelte will handle grabbing all of the modules itself under the assumption that all Svelte files exist in /src/routes/. If your directory structure is different, you can implement this yourself. If you pass a value in the routeModules prop the Breadcrumbs component will not try to populate it. You will also need to update the path prefix for your Svelte directory.

<script lang="ts">
  let routeModules = $state({} as Record<string, ModuleData>);

  onMount(async () => {
    // Note: that the path prefix here is now /src/svelte/
    // Note: eager is required
    routeModules = import.meta.glob("/src/svelte/**/*.svelte", {eager: true});
  })
</script>

<!-- Note: routeModules and globImportPrefix passed through -->
<Breadcrumbs
  url={$page.url}
  routeId={$page.route.id}
  {routeModules}
  globImportPrefix={'/src/svelte/'}
  let:crumbs
>
  <!-- ...-->
</Breadcrumbs>

Customizing route titles

The Breadcrumbs component will have access to your Svelte components based on the route id and will be looking for the following exported variables in the Module Context:

  • pageTitle: string
  • getPageTitle: (data: any) -> string

getPageTitle will receive the value of $page.data passed through in the Breadcrumbs prop. (see the Breadcrumbs usage above).

Here is an example:

<script module lang="ts">
  // Getter function
  export function getPageTitle(data: any) {
    // When this is undefined it will fall back to the value in the route (in this case the todo id for the route /todos/1/edit)
    return data.todo?.name;
  }
  // Or a constant
  export const pageTitle = 'Random Todo';
</script>

Types

export type Crumb = {
  title?: string; // The default title being the sanitized page inferred from the URL (e.g. Edit)
  url?: string; // The URL of this page (e.g. /todos/1/edit)
  metadata?: any; // Any metadata you want passed through to the Breadcrumbs component
};

// The data we will be grabbing from each +page.svelte file
export type ModuleData = {
  pageTitle?: string;
  getPageTitle?: (data: any) => string;
};

Full Component Docs

Breadcrumbs

This component will provide an array of Crumbs to a single slot. The final Crumb will never have a URL as it is the current page.

Props

routeModules: Record<string, ModuleData>

Optional

The exported data for each module. If not provided it will be populated on mount with an eager glob import of "/src/routes/**/*.svelte" which is SvelteKit specific.

Completely disable this feature by passing in an empty value as shown below.

<Breadcrumbs routeModules={{}}>
  <!-- ...-->
</Breadcrumbs>

relPathToRoutes: string

Optional

Default Value: '/src/routes/'

The path to the directory where your Svelte files live. In SvelteKit, if we are on a route /todo/[id]/ and we have imported the svelte files like so:

import.meta.glob("/src/routes/**/*.svelte")

it will produce an object with the following:

{
  '/src/routes/todo/[id]/+page.svelte': ...Promise obj...
}

Thus in order to match that file we need to specify the prefix /src/routes/. Breadcrumbs.svelte will essentially do the following to generate a path to the +page.svelte file:

relPathToRoutes + routeId + "/+page.svelte";

routeId: string | null | undefined

Optional

Route id for the current page. In Sveltekit this is $page.route.id.

url: string

Required

URL for the current page. Used to generate the url that each breadcrumb should link to when clicked on. In SvelteKit this is $page.url.

pageData: any

Optional

Page Data to pass through to the getPageTitle function living in a route's page.svelte file

crumbs: Crumb[]

Optional

A list of Crumbs that will override/bypass any breadcrumb generation via routes. In SvelteKit if you pass $page.data.crumbs or something similar you will be able to override any bread crumbs via page loads.

titleSanitizer(title: string) -> string

Optional

Default Value: (title) => title.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());

Each title of the generated Crumb items will pass through this function. By default it will add spaces and capitalize (e.g. myTodos -> My Todos).