Env Chores (#40)

This commit is contained in:
Ollie Taylor
2023-07-09 23:21:21 +01:00
committed by GitHub
parent 9b1238c4a1
commit 1a95ddd387
33 changed files with 5280 additions and 5442 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
@layer components {
.prose code {
@apply inline rounded bg-primary-100 py-1 px-2 font-mono leading-none text-primary-800;
@apply inline rounded bg-primary-100 px-2 py-1 font-mono leading-none text-primary-800;
overflow-wrap: anywhere;
}
.prose code::before,
+4 -3
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { topics } from '$content/utility/anchor-registry';
import { topics } from '$src/content/utility/anchor-registry';
import { Hashtag } from '@inqling/svelte-icons/heroicon-24-outline';
export let value: string;
@@ -8,8 +8,9 @@
</script>
<a href="/#{id}" class="group relative -ml-[1em] hover:text-black">
<Hashtag class="h-[1em] w-[1em] -translate-x-1 text-mono-300 group-hover:text-primary-600" /><span
class="underline decoration-primary-50/0 decoration-4 group-hover:decoration-primary-500"
<Hashtag
class="h-[1em] w-[1em] -translate-x-1 text-mono-300 group-hover:text-primary-600"
/><span class="underline decoration-primary-50/0 decoration-4 group-hover:decoration-primary-500"
>{value}</span
>
<span class="pointer-events-none absolute -top-10 h-px w-px" {id} />
+1 -1
View File
@@ -18,7 +18,7 @@
<dt class="inline font-semibold text-mono-900">
<svelte:component
this={feature.icon}
class="absolute top-1 left-1 h-5 w-5 text-primary-600"
class="absolute left-1 top-1 h-5 w-5 text-primary-600"
/>
{feature.title}
+1
View File
@@ -20,6 +20,7 @@ function slugify(value: string) {
.replace(/\s+/g, '-')
.toLowerCase()
.trim()
// eslint-disable-next-line no-control-regex
.replace(/[^\x00-\x7F]/g, '-')
.replace(/[^a-z0-9-]/g, '-')
.replace(/^-+/, '')
+3 -3
View File
@@ -26,9 +26,9 @@
<svelte:head>
<style>
:root {
--svpod--font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
--svpod--font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--svpod--surface--darker: rgb(0, 0, 0);
--svpod--surface--base: rgb(40, 40, 40);
+16 -16
View File
@@ -19,6 +19,22 @@
}
</script>
<input
class={$$props.class}
style="display:block; width:100%;"
type="range"
data-paused={$episode_audio?.is_paused ? 'true' : 'false'}
min={0}
{step}
max={$episode_audio?.duration || step}
value={$episode_progress.current_time}
on:change={(e) => episode_audio.seek(e.currentTarget.valueAsNumber)}
on:touchstart={() => handle_drag_start('touchstart')}
on:mousedown={() => handle_drag_start('mousedown')}
on:touchend={() => handle_drag_end('touchend')}
on:mouseup={() => handle_drag_end('mouseup')}
/>
<style>
input[type='range'] {
--track--shape--height: calc(var(--svpod--timeline-track--shape--height));
@@ -127,19 +143,3 @@
background: var(--svpod--timeline-track--bg);
}
</style>
<input
class={$$props.class}
style="display:block; width:100%;"
type="range"
data-paused={$episode_audio?.is_paused ? 'true' : 'false'}
min={0}
{step}
max={$episode_audio?.duration || step}
value={$episode_progress.current_time}
on:change={(e) => episode_audio.seek(e.currentTarget.valueAsNumber)}
on:touchstart={() => handle_drag_start('touchstart')}
on:mousedown={() => handle_drag_start('mousedown')}
on:touchend={() => handle_drag_end('touchend')}
on:mouseup={() => handle_drag_end('mouseup')}
/>
+93 -89
View File
@@ -34,6 +34,99 @@
const { class: ClassName, ...rest } = $$restProps;
</script>
<div
class={clsx('svpod--container svpod--reset', ClassName)}
data-loaded={is_loaded ? 'true' : 'false'}
{...rest}
>
<div class="svpod--container--row svpod--row--controls">
<button
on:click={() => options.skip_back && episode_audio.skip(options.skip_back, 'backward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_back} type="backward" />
</button>
<!-- toggle play -->
{#if is_loaded}
<button
on:click={() => is_loaded && episode_audio.play('toggle')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<A11yIcon icon={is_playing ? Pause : Play} label={is_playing ? 'Pause' : 'Play'} />
</button>
{:else}
<div class="svpod--reset svpod--toggle-pause">
<A11yIcon icon={Spinner} label="Waiting for audio..." />
</div>
{/if}
<button
on:click={() =>
options.skip_forward && episode_audio.skip(options.skip_forward, 'forward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_forward} type="forward" />
</button>
</div>
<div class="svpod--artwork svpod--row--artwork">
<span class="svpod--aspect--square" />
<slot>
<div class="svpod--artwork--placeholder">
<span><SpeakerWave style="width:1em; height: 1em;" /></span>
</div>
</slot>
</div>
<div class="svpod--timeline svpod--row--timeline">
<HeadlessTimeline />
</div>
{#if options.timestamps || options.playback_rate}
<div class="svpod--container--row svpod--row--timestamps">
{#if options.timestamps}
<div class="svpod--timestamp">
<Timestamp
value={$episode_progress?.current_time || 0}
force_hours={timestamp_hours}
/>
</div>
<div style="flex-grow: 1" />
<div class="svpod--timestamp">
<Timestamp value={$episode_audio?.duration || 0} />
</div>
{/if}
{#if options.playback_rate}
<select
class="svpod--playback-rate"
value={$user_preferences.playback_rate}
on:change={(e) => {
const value = parseFloat(e.currentTarget.value);
user_preferences.set.playback_rate(value);
}}
>
{#each playback_rate_values as value}
<option {value}>
{#if Number.isInteger(value)}
{value}.0
{:else}
{value}
{/if}
</option>
{/each}
</select>
{/if}
</div>
{/if}
</div>
<style>
.svpod--container {
--fg: var(--svpod--content--base);
@@ -227,92 +320,3 @@
padding-bottom: 100%;
}
</style>
<div
class={clsx('svpod--container svpod--reset', ClassName)}
data-loaded={is_loaded ? 'true' : 'false'}
{...rest}
>
<div class="svpod--container--row svpod--row--controls">
<button
on:click={() => options.skip_back && episode_audio.skip(options.skip_back, 'backward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_back} type="backward" />
</button>
<!-- toggle play -->
{#if is_loaded}
<button
on:click={() => is_loaded && episode_audio.play('toggle')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<A11yIcon icon={is_playing ? Pause : Play} label={is_playing ? 'Pause' : 'Play'} />
</button>
{:else}
<div class="svpod--reset svpod--toggle-pause">
<A11yIcon icon={Spinner} label="Waiting for audio..." />
</div>
{/if}
<button
on:click={() => options.skip_forward && episode_audio.skip(options.skip_forward, 'forward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_forward} type="forward" />
</button>
</div>
<div class="svpod--artwork svpod--row--artwork">
<span class="svpod--aspect--square" />
<slot>
<div class="svpod--artwork--placeholder">
<span><SpeakerWave style="width:1em; height: 1em;" /></span>
</div>
</slot>
</div>
<div class="svpod--timeline svpod--row--timeline">
<HeadlessTimeline />
</div>
{#if options.timestamps || options.playback_rate}
<div class="svpod--container--row svpod--row--timestamps">
{#if options.timestamps}
<div class="svpod--timestamp">
<Timestamp value={$episode_progress?.current_time || 0} force_hours={timestamp_hours} />
</div>
<div style="flex-grow: 1" />
<div class="svpod--timestamp">
<Timestamp value={$episode_audio?.duration || 0} />
</div>
{/if}
{#if options.playback_rate}
<select
class="svpod--playback-rate"
value={$user_preferences.playback_rate}
on:change={(e) => {
const value = parseFloat(e.currentTarget.value);
user_preferences.set.playback_rate(value);
}}
>
{#each playback_rate_values as value}
<option {value}>
{#if Number.isInteger(value)}
{value}.0
{:else}
{value}
{/if}
</option>
{/each}
</select>
{/if}
</div>
{/if}
</div>
+76 -75
View File
@@ -38,6 +38,82 @@
const { class: ClassName, ...rest } = $$restProps;
</script>
<div
class={clsx('svpod--container svpod--reset', ClassName)}
data-loaded={is_loaded ? 'true' : 'false'}
{...rest}
>
{#if options.skip_back}
<button
on:click={() => options.skip_back && episode_audio.skip(options.skip_back, 'backward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_back} type="backward" />
</button>
{/if}
<!-- toggle play -->
{#if is_loaded}
<button
on:click={() => is_loaded && episode_audio.play('toggle')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<A11yIcon icon={is_playing ? Pause : Play} label={is_playing ? 'Pause' : 'Play'} />
</button>
{:else}
<div class="svpod--reset svpod--toggle-pause">
<A11yIcon icon={Spinner} label="Waiting for audio..." />
</div>
{/if}
{#if options.skip_forward}
<button
on:click={() =>
options.skip_forward && episode_audio.skip(options.skip_forward, 'forward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_forward} type="forward" />
</button>
{/if}
{#if current_time !== false}
<div class="svpod--timestamp">
<Timestamp value={current_time} force_hours={timestamp_hours} />
</div>
{/if}
<div class="svpod--timeline">
<HeadlessTimeline />
</div>
{#if duration !== false}
<div class="svpod--timestamp">
<Timestamp value={duration} />
</div>
{/if}
{#if options.playback_rate}
<select
class="svpod--playback-rate"
value={$user_preferences.playback_rate}
on:change={(e) => {
const value = parseFloat(e.currentTarget.value);
user_preferences.set.playback_rate(value);
}}
>
{#each playback_rate_values as value}
<option {value}>
{#if Number.isInteger(value)}
{value}.0
{:else}
{value}
{/if}
</option>
{/each}
</select>
{/if}
</div>
<style>
.svpod--container {
--fg: var(--svpod--content--base);
@@ -157,78 +233,3 @@
color: var(--fg);
}
</style>
<div
class={clsx('svpod--container svpod--reset', ClassName)}
data-loaded={is_loaded ? 'true' : 'false'}
{...rest}
>
{#if options.skip_back}
<button
on:click={() => options.skip_back && episode_audio.skip(options.skip_back, 'backward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_back} type="backward" />
</button>
{/if}
<!-- toggle play -->
{#if is_loaded}
<button
on:click={() => is_loaded && episode_audio.play('toggle')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<A11yIcon icon={is_playing ? Pause : Play} label={is_playing ? 'Pause' : 'Play'} />
</button>
{:else}
<div class="svpod--reset svpod--toggle-pause">
<A11yIcon icon={Spinner} label="Waiting for audio..." />
</div>
{/if}
{#if options.skip_forward}
<button
on:click={() => options.skip_forward && episode_audio.skip(options.skip_forward, 'forward')}
class="svpod--reset svpod--toggle-pause"
type="button"
>
<Skip value={options.skip_forward} type="forward" />
</button>
{/if}
{#if current_time !== false}
<div class="svpod--timestamp">
<Timestamp value={current_time} force_hours={timestamp_hours} />
</div>
{/if}
<div class="svpod--timeline">
<HeadlessTimeline />
</div>
{#if duration !== false}
<div class="svpod--timestamp">
<Timestamp value={duration} />
</div>
{/if}
{#if options.playback_rate}
<select
class="svpod--playback-rate"
value={$user_preferences.playback_rate}
on:change={(e) => {
const value = parseFloat(e.currentTarget.value);
user_preferences.set.playback_rate(value);
}}
>
{#each playback_rate_values as value}
<option {value}>
{#if Number.isInteger(value)}
{value}.0
{:else}
{value}
{/if}
</option>
{/each}
</select>
{/if}
</div>
+56 -56
View File
@@ -4,62 +4,6 @@
export let type: 'forward' | 'backward';
</script>
<style>
div.svpod--skip-container {
display: inline-flex;
position: relative;
align-items: center;
justify-content: center;
width: 1.5em;
height: 1.5em;
}
div.svpod--skip-icon,
span.svpod--skip-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
span.svpod--skip-mask {
z-index: 1;
background: linear-gradient(0deg, var(--bg), transparent);
opacity: 0.5;
}
div.svpod--skip-icon {
z-index: 0;
display: flex;
align-items: center;
justify-content: center;
color: var(--svpod--content--base);
}
span.svpod--skip-label {
position: relative;
z-index: 2;
font-size: 0.5em;
line-height: 1em;
color: var(--svpod--content--lighter);
}
@keyframes Spin {
0%,
100% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
svg {
/* animation: Spin 1s cubic-bezier(0.5, 0.1, 0.1, 0.8) infinite; */
}
</style>
<div class="svpod--skip-container" style="font-size:{size}px">
<span class="svpod--skip-label">
<span class="svpod--a11y-hidden">skip {type}</span>
@@ -153,3 +97,59 @@
{/if}
</div>
</div>
<style>
div.svpod--skip-container {
display: inline-flex;
position: relative;
align-items: center;
justify-content: center;
width: 1.5em;
height: 1.5em;
}
div.svpod--skip-icon,
span.svpod--skip-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
span.svpod--skip-mask {
z-index: 1;
background: linear-gradient(0deg, var(--bg), transparent);
opacity: 0.5;
}
div.svpod--skip-icon {
z-index: 0;
display: flex;
align-items: center;
justify-content: center;
color: var(--svpod--content--base);
}
span.svpod--skip-label {
position: relative;
z-index: 2;
font-size: 0.5em;
line-height: 1em;
color: var(--svpod--content--lighter);
}
@keyframes Spin {
0%,
100% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
svg {
/* animation: Spin 1s cubic-bezier(0.5, 0.1, 0.1, 0.8) infinite; */
}
</style>
+20 -20
View File
@@ -2,6 +2,26 @@
export let size = 24;
</script>
<div class="svpod--spinner-container" style="width:{size}px; height:{size}px">
{#each [0, 0.075, 0.15] as delay}
<div class="svpod--item">
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style="animation-delay: {delay}s;"
>
<path
d="M24 12C24 14.3734 23.2962 16.6935 21.9776 18.6668C20.6591 20.6402 18.7849 22.1783 16.5922 23.0866C14.3995 23.9948 11.9867 24.2324 9.65892 23.7694C7.33114 23.3064 5.19295 22.1635 3.51472 20.4853C1.83649 18.8071 0.693599 16.6689 0.230577 14.3411C-0.232446 12.0133 0.00519403 9.60051 0.913446 7.4078C1.8217 5.21509 3.35977 3.34094 5.33316 2.02236C7.30655 0.703788 9.62662 -2.83022e-08 12 0L12 3C10.22 3 8.47991 3.52784 6.99987 4.51677C5.51983 5.50571 4.36627 6.91131 3.68508 8.55585C3.0039 10.2004 2.82567 12.01 3.17293 13.7558C3.5202 15.5016 4.37737 17.1053 5.63604 18.364C6.89471 19.6226 8.49836 20.4798 10.2442 20.8271C11.99 21.1743 13.7996 20.9961 15.4442 20.3149C17.0887 19.6337 18.4943 18.4802 19.4832 17.0001C20.4722 15.5201 21 13.78 21 12H24Z"
fill="currentColor"
/>
</svg>
</div>
{/each}
</div>
<style>
div.svpod--spinner-container {
display: inline-block;
@@ -40,23 +60,3 @@
animation: Spin 1s cubic-bezier(0.5, 0.1, 0.1, 0.8) infinite;
}
</style>
<div class="svpod--spinner-container" style="width:{size}px; height:{size}px">
{#each [0, 0.075, 0.15] as delay}
<div class="svpod--item">
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style="animation-delay: {delay}s;"
>
<path
d="M24 12C24 14.3734 23.2962 16.6935 21.9776 18.6668C20.6591 20.6402 18.7849 22.1783 16.5922 23.0866C14.3995 23.9948 11.9867 24.2324 9.65892 23.7694C7.33114 23.3064 5.19295 22.1635 3.51472 20.4853C1.83649 18.8071 0.693599 16.6689 0.230577 14.3411C-0.232446 12.0133 0.00519403 9.60051 0.913446 7.4078C1.8217 5.21509 3.35977 3.34094 5.33316 2.02236C7.30655 0.703788 9.62662 -2.83022e-08 12 0L12 3C10.22 3 8.47991 3.52784 6.99987 4.51677C5.51983 5.50571 4.36627 6.91131 3.68508 8.55585C3.0039 10.2004 2.82567 12.01 3.17293 13.7558C3.5202 15.5016 4.37737 17.1053 5.63604 18.364C6.89471 19.6226 8.49836 20.4798 10.2442 20.8271C11.99 21.1743 13.7996 20.9961 15.4442 20.3149C17.0887 19.6337 18.4943 18.4802 19.4832 17.0001C20.4722 15.5201 21 13.78 21 12H24Z"
fill="currentColor"
/>
</svg>
</div>
{/each}
</div>
+2 -2
View File
@@ -7,6 +7,8 @@
$: timestamp = secondsToTimestamp(value, force_hours);
</script>
<span style="width:{timestamp.length}ch">{timestamp}</span>
<style>
span {
letter-spacing: 0.5px;
@@ -15,5 +17,3 @@
width: 8ch;
}
</style>
<span style="width:{timestamp.length}ch">{timestamp}</span>
+1 -1
View File
@@ -17,7 +17,7 @@
class="sticky top-0 z-50 border-b border-mono-100 bg-white text-lg leading-none lg:overflow-y-visible"
id="navigation"
>
<div class="mx-auto max-w-prose px-4 py-1 sm:py-2 sm:px-6 lg:px-8">
<div class="mx-auto max-w-prose px-4 py-1 sm:px-6 sm:py-2 lg:px-8">
<div class="relative grid grid-cols-12 gap-1 text-base md:gap-3">
<div class="col-span-2 flex items-center justify-start leading-none">
<a href="{base}/#navigation" class="flex-shrink-0 py-1">
+1 -1
View File
@@ -1,4 +1,4 @@
import content from '$content/docs.md?raw';
import content from '$src/content/docs.md?raw';
import type { PageServerLoad } from './$types';
import { use_markdown } from './use-markdown';
+7 -6
View File
@@ -1,8 +1,8 @@
<script lang="ts">
import { base } from '$app/paths';
import { Section } from '$content/components';
// import Docs from '$content/docs.md';
import { episodes } from '$content/episodes';
import { Section } from '$src/content/components';
// import Docs from '$src/content/docs.md';
import { episodes } from '$src/content/episodes';
import { onMount } from 'svelte';
import { episode_audio, PlayerWidget } from 'svelte-podcast';
import type { PageServerData } from './$types';
@@ -54,15 +54,16 @@
</span>
</h1>
<p class="mt-6 text-xl leading-8 text-mono-600">
A suite of tools and components to build your own podcast players, and work with RSS
podcast data in SvelteKit.
A suite of tools and components to build your own podcast players, and work with
RSS podcast data in SvelteKit.
<span class="mt-3 block text-base leading-none text-primary-800">
<span
class="inline-block rounded-full bg-primary-50 px-3 py-1.5 text-xs font-medium uppercase tracking-wider text-primary-600"
>
Coming Soon<span class="sr-only">:</span>
</span>
<span class="tracking-wide">SSR utilities for consuming RSS podcast feeds</span>
<span class="tracking-wide">SSR utilities for consuming RSS podcast feeds</span
>
</span>
</p>
<div class="mt-10 flex items-center justify-center gap-x-3">
+11 -3
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { Section } from '$content/components';
import { Section } from '$src/content/components';
import {
episode_audio,
episode_progress,
@@ -62,7 +62,11 @@
</div>
<div>
<label for="pw_playback_rate">playback_rate</label>
<input id="pw_playback_rate" type="checkbox" bind:checked={player_widget.playback_rate} />
<input
id="pw_playback_rate"
type="checkbox"
bind:checked={player_widget.playback_rate}
/>
</div>
<div>
<label for="pw_duration">duration</label>
@@ -87,7 +91,11 @@
<svelte:fragment slot="options">
<div>
<label for="pw_playback_rate">playback_rate</label>
<input id="pw_playback_rate" type="checkbox" bind:checked={player_stack.playback_rate} />
<input
id="pw_playback_rate"
type="checkbox"
bind:checked={player_stack.playback_rate}
/>
</div>
<div>
<label for="pw_timestamps">timestamps</label>
+3
View File
@@ -40,11 +40,14 @@ export function hljsDefineSvelte(hljs: HLJSApi) {
subLanguage: 'javascript',
contains: [
{
// eslint-disable-next-line no-useless-escape
begin: /[\{]/,
// eslint-disable-next-line no-useless-escape
end: /[\}]/,
skip: true,
},
{
// eslint-disable-next-line no-useless-escape
begin: /([#:\/@])(if|else|each|await|then|catch|debug|html)/gm,
className: 'keyword',
relevance: 10,