Skip to content

Commit

Permalink
✨ feat: initial
Browse files Browse the repository at this point in the history
  • Loading branch information
m1212e committed Jan 3, 2025
0 parents commit 955b4f6
Show file tree
Hide file tree
Showing 21 changed files with 657 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/build_and_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Build client

on:
release:
types: [created]

jobs:
test_and_build:
name: Build client
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v1
- name: Install dependencies
run: bun i
- name: Run build
run: bun run build
env:
REF_NAME: ${{ github.ref_name }}
- name: Set tag
id: tag
run: |
if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then
echo "tag=dev" >> $GITHUB_OUTPUT
elif [[ "${{ github.event.release.prerelease }}" == "false" ]]; then
echo "tag=latest" >> $GITHUB_OUTPUT
fi
- uses: JS-DevTools/npm-publish@v3
with:
token: ${{ secrets.NPM_TOKEN }}
package: ./package.json
tag: ${{ steps.tag.outputs.tag }}
16 changes: 16 additions & 0 deletions .github/workflows/code_quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Code check

on:
push:
pull_request:

jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v1
- name: Install dependencies
run: bun i
- name: Run build
run: bun run check
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
node_modules

# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build
/dist

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock
15 changes: 15 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# sveltekit-breadcrumbs
An easy to use breadcrumb component for sveltekit and svelte 5. Uses the filesystem to extract the current path.

## Usage
Add the dependency to your project:
```
bun add -D sveltekit-breadcrumbs
npm i -D sveltekit-breadcrumbs
```
Then you can use the component like this:
```svelte
<script>
import Breadcrumbs from 'sveltekit-breadcrumbs';
import type { PathSegment } from 'sveltekit-breadcrumbs';
type Parameters = keyof LayoutServerLoadEvent['params'];
</script>
<Breadcrumbs
importObject={import.meta.glob('./**/+page.svelte')}
availableLanguageTags={availableLanguageTags as any as string[]}
delimeterSnippet="disabled"
homePath="/"
>
{#snippet pathSnippet(pathSegment: PathSegment<Parameters, boolean>)}
<a class="breadcrumb-snippet" href={pathSegment.href}>
<i class="icon-for-breadcrumb"></i>
<p class="ml-2">
some label for my breadcrumb segment
</p>
</a>
{/snippet}
</Breadcrumbs>
```
### Properties
The component can be configured via a few props:
#### importObject
Depending on where you place the component in your directory tree (best works in a layout file) the component changes its content. To pass all the relevant info, please pass the value of a `import.meta.glob('./**/+page.svelte')` call to this property. This will, relative to the location of the file calling this function, pass all file paths of reachable pages on this level and below to the component.
#### availableLanguageTags
This is optional and can be used to strip language prefixes from the paths. Set this to an array of language tags which might appear in the urls of you application. E.g. `["en", "de"]`.
#### delimeterSnippet
You can optionally set a delimeter snippet which will get placed between all path segments of the generated breadcrumbs.
#### homePath
Where your index/home link should navigate to.
### Example
To see a real world example please see [this project](https://github.com/DeutscheModelUnitedNations/munify-delegator/blob/173630365765ed7c5ee1b9f3f3812b1b9877dd4d/src/routes/(authenticated)/Breadcrumbs.svelte#L1) or the [example directory](./example/)
Binary file added bun.lockb
Binary file not shown.
34 changes: 34 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import prettier from 'eslint-config-prettier';
import js from '@eslint/js';
import { includeIgnoreFile } from '@eslint/compat';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import { fileURLToPath } from 'node:url';
import ts from 'typescript-eslint';
const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));

export default ts.config(
includeIgnoreFile(gitignorePath),
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs['flat/recommended'],
prettier,
...svelte.configs['flat/prettier'],
{
languageOptions: {
globals: {
...globals.browser,
...globals.node
}
}
},
{
files: ['**/*.svelte'],

languageOptions: {
parserOptions: {
parser: ts.parser
}
}
}
);
169 changes: 169 additions & 0 deletions example/Example.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<script lang="ts">
import Breadcrumbs from 'sveltekit-breadcrumbs';
import type { PathSegment } from 'sveltekit-breadcrumbs';
import { availableLanguageTags } from '$lib/paraglide/runtime';
import * as m from '$lib/paraglide/messages.js';
import { graphql } from '$houdini';
import type { LayoutServerLoadEvent } from './$types';
import { browser } from '$app/environment';
type Parameters = keyof LayoutServerLoadEvent['params'];
const conferenceTitleQuery = graphql(`
query ConferenceTitleQuery($conferenceId: String!) {
findUniqueConference(where: { id: $conferenceId }) {
id
title
}
}
`);
interface LocalizedBreadcrumb {
translation: string;
delayedLabel?: Promise<string>;
icon: string;
}
const breadcrumbs: { [key: string]: LocalizedBreadcrumb } = {
management: {
translation: m.admininstration(),
icon: 'bars-progress'
},
conferenceId: {
translation: m.conference(),
icon: 'flag'
},
delegations: {
translation: m.delegations(),
icon: 'users-viewfinder'
},
dashboard: {
translation: m.dashboard(),
icon: 'chart-pie'
},
registration: {
translation: m.registration(),
icon: 'envelope'
},
stats: {
translation: m.statistics(),
icon: 'chart-simple'
},
'create-delegation': {
translation: m.createDelegation(),
icon: 'plus'
},
'join-delegation': {
translation: m.joinDelegation(),
icon: 'arrow-right-to-arc'
},
individual: {
translation: m.individualApplication(),
icon: 'dice-one'
},
roleId: {
translation: m.role(),
icon: 'gavel'
},
'join-delegation-supervisor': {
translation: m.supervisor(),
icon: 'eye'
},
'my-account': {
translation: m.myAccount(),
icon: 'user'
},
configuration: {
translation: m.settings(),
icon: 'gears'
},
participants: {
translation: m.participants(),
icon: 'users'
},
individuals: {
translation: m.singleParticipants(),
icon: 'user'
},
supervisors: {
translation: m.supervisors(),
icon: 'eye'
},
plausibility: {
translation: m.adminPlausibility(),
icon: 'question'
},
committeeAssignment: {
translation: m.committeeAssignment(),
icon: 'arrows-turn-to-dots'
}
};
function getBreadcrumb(segment: PathSegment<Parameters, boolean>): LocalizedBreadcrumb {
const breadcrumb = breadcrumbs[segment.key];
if (!breadcrumb) {
console.warn(`Breadcrumb not found: ${segment.key}`);
return {
translation: segment.key,
icon: 'question'
};
}
if (segment.isParameter) {
switch (segment.key) {
case 'conferenceId':
breadcrumb.delayedLabel = (async () => {
//TODO we could probably load this data serverside
// although this would prevent computational breadcrumbs which depend on client side data
// it's alright for now I guess
if (browser) {
const r = await conferenceTitleQuery.fetch({
variables: { conferenceId: segment.value }
});
return r.data?.findUniqueConference?.title ?? breadcrumb.translation;
}
return breadcrumb.translation;
})();
break;
case 'roleId':
//TODO
break;
default:
break;
}
}
return breadcrumb;
}
</script>

<!-- ATTENTION: importObject is dir route specific. You cannot move this file without adjusting this
import path via the parameter! -->
<Breadcrumbs
importObject={import.meta.glob('./**/+page.svelte')}
availableLanguageTags={availableLanguageTags as any as string[]}
delimeterSnippet="disabled"
homePath="/"
>
{#snippet pathSnippet(pathSegment: PathSegment<Parameters, boolean>)}
<a class="btn btn-ghost btn-sm" href={pathSegment.href}>
<i class="fa-duotone fa-{getBreadcrumb(pathSegment).icon}"></i>
<p class="ml-2">
{#if getBreadcrumb(pathSegment).delayedLabel}
{#await getBreadcrumb(pathSegment).delayedLabel}
<span>
{getBreadcrumb(pathSegment).translation}
</span>
{:then value}
<span>
{value ?? getBreadcrumb(pathSegment).translation}
</span>
{/await}
{:else}
{getBreadcrumb(pathSegment).translation}
{/if}
</p>
</a>
{/snippet}
</Breadcrumbs>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"sveltekit-breadcrumbs","version":"0.0.1","scripts":{"dev":"vite dev","build":"vite build && npm run package","preview":"vite preview","package":"svelte-kit sync && svelte-package && publint && bun ./post-build.ts","prepublishOnly":"npm run package","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch","format":"prettier --write .","lint":"prettier --check . && eslint ."},"files":["dist","!dist/**/*.test.*","!dist/**/*.spec.*"],"sideEffects":["**/*.css"],"svelte":"./dist/index.js","types":"./dist/index.d.ts","type":"module","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"}},"peerDependencies":{"svelte":"^5.0.0","@sveltejs/kit":"^2.15.0"},"devDependencies":{"@eslint/compat":"^1.2.3","@sveltejs/adapter-auto":"^3.0.0","@sveltejs/package":"^2.0.0","@sveltejs/vite-plugin-svelte":"^4.0.0","eslint":"^9.7.0","eslint-config-prettier":"^9.1.0","eslint-plugin-svelte":"^2.36.0","globals":"^15.0.0","prettier":"^3.3.2","prettier-plugin-svelte":"^3.2.6","publint":"^0.2.0","svelte":"^5.0.0","svelte-check":"^4.0.0","typescript":"^5.0.0","typescript-eslint":"^8.0.0","vite":"^5.4.11"}}
25 changes: 25 additions & 0 deletions post-build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import packagejson from './package.json';

const projectDir = import.meta.dir;

// ==============================
// Create package.json
// ==============================

console.info('Adjusting version in package.json...');
const finalPackageJson = { ...packagejson };

const version = process.env.REF_NAME ?? (packagejson as any).version ?? '0.0.1';
console.log(`Setting version: ${version}`);

(finalPackageJson as any).version = version;

await writeFile(join(projectDir, 'package.json'), JSON.stringify(finalPackageJson), {
encoding: 'utf-8'
});
console.info('Written package.json!');

console.info('Done!');
process.exit(0);
13 changes: 13 additions & 0 deletions src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}

export {};
Loading

0 comments on commit 955b4f6

Please sign in to comment.