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
+5
View File
@@ -0,0 +1,5 @@
---
'svelte-podcast': minor
---
Updates dependencies
+4
View File
@@ -14,3 +14,7 @@ package-lock.json
yarn.lock
**/components/_*
*.config.ts
*.config.js
*.config.cjs
+18 -3
View File
@@ -1,8 +1,13 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['svelte3', '@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
'prettier',
],
plugins: ['svelte3', '@typescript-eslint', 'unused-imports'],
ignorePatterns: ['*.cjs'],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
settings: {
@@ -11,6 +16,7 @@ module.exports = {
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
project: ['./tsconfig.json'],
},
env: {
browser: true,
@@ -18,6 +24,15 @@ module.exports = {
node: true,
},
rules: {
'no-restricted-imports': ['error', { patterns: ['$lib', '$lib/*'] }],
// '@typescript-eslint/no-inferrable-types': 'off',
// '@typescript-eslint/no-unsafe-argument': 'off',
// '@typescript-eslint/no-unsafe-assignment': 'off',
'logical-assignment-operators': ['error', 'always'],
// "no-unused-vars": "off",
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'warn',
{ vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' },
],
},
};
+110 -13
View File
@@ -5,10 +5,6 @@ on:
- main
pull_request:
env:
# we call `pnpm playwright install` instead
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
# cancel in-progress runs on new commits to same PR (gitub.event.number)
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
@@ -18,15 +14,116 @@ permissions:
contents: read # to fetch code (actions/checkout)
jobs:
Lint:
setup:
name: Setup Enviroment
timeout-minutes: 4
runs-on: ubuntu-latest
outputs:
cache_name: ${{ steps.cache.outputs.name }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set Node to v18.13.0
uses: actions/setup-node@v3
with:
node-version: v18.13.0
- name: Get Node version
id: node
run: echo "version=$(node -v)" >> $GITHUB_OUTPUT
#run: echo "::set-output name=version::$(node --v)"
- name: Get Cache Name
id: cache
run: echo "name=${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }}-${{ steps.node.outputs.version }}" >> $GITHUB_OUTPUT
- name: Get node_modules cache
uses: actions/cache@v3
id: node_modules
with:
path: |
**/node_modules
**/.svelte-kit
key: ${{ steps.cache.outputs.name }}
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Sync generated typings
run: yarn run sync
linting:
name: Linting Checks
needs: setup
timeout-minutes: 4
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.4
- uses: actions/setup-node@v3
- name: Checkout code
uses: actions/checkout@v3
- name: Get node_modules cache
uses: actions/cache/restore@v3
id: cache
with:
node-version: '16.x'
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run lint
- run: pnpm run check
path: |
**/node_modules
**/.svelte-kit
key: ${{ needs.setup.outputs.cache_name }}
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Lint prettier
run: yarn run lint:prettier
- name: Lint eslint
run: yarn run lint:eslint
type_check:
name: Typescript Checks
needs: setup
timeout-minutes: 4
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Get node_modules cache
uses: actions/cache/restore@v3
id: cache
with:
path: |
**/node_modules
**/.svelte-kit
key: ${{ needs.setup.outputs.cache_name }}
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Check for type errors
run: yarn run ts
# svelte_check:
# name: Svelte Checks
# needs: setup
# timeout-minutes: 4
# runs-on: ubuntu-latest
# steps:
# - name: Checkout code
# uses: actions/checkout@v3
#
# - name: Get node_modules cache
# uses: actions/cache/restore@v3
# id: cache
# with:
# path: |
# **/node_modules
# **/.svelte-kit
# key: ${{ needs.setup.outputs.cache_name }}
#
# - name: Install dependencies
# run: yarn install --frozen-lockfile
#
# - name: Check for best practices
# run: yarn run check
+57 -12
View File
@@ -7,35 +7,80 @@ on:
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
setup:
name: Setup Enviroment
timeout-minutes: 4
runs-on: ubuntu-latest
outputs:
cache_name: ${{ steps.cache.outputs.name }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set Node to v18.13.0
uses: actions/setup-node@v3
with:
node-version: v18.13.0
- name: Get Node version
id: node
run: echo "version=$(node -v)" >> $GITHUB_OUTPUT
#run: echo "::set-output name=version::$(node --v)"
- name: Get Cache Name
id: cache
run: echo "name=${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }}-${{ steps.node.outputs.version }}" >> $GITHUB_OUTPUT
- name: Get node_modules cache
uses: actions/cache@v3
id: node_modules
with:
path: |
**/node_modules
**/.svelte-kit
key: ${{ steps.cache.outputs.name }}
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Sync generated typings
run: yarn run sync
release:
# prevents this action from running on forks
if: github.repository == 'OllieJT/svelte-podcast'
name: Release
needs: setup
timeout-minutes: 5
runs-on: ubuntu-latest
# prevents this action from running on forks
permissions:
contents: write # to create release (changesets/action)
pull-requests: write # to create pull request (changesets/action)
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
- name: Checkout code
uses: actions/checkout@v3
with:
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
fetch-depth: 0
- uses: pnpm/action-setup@v2.2.4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Get node_modules cache
uses: actions/cache/restore@v3
id: cache
with:
path: |
**/node_modules
**/.svelte-kit
key: ${{ needs.setup.outputs.cache_name }}
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
# This expects you to have a script called release which does a build for your packages and calls changeset publish
publish: pnpm release
publish: yarn release
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
-123
View File
@@ -1,123 +0,0 @@
name: 'CI'
on:
push:
branches:
- todo
env:
# we call `pnpm playwright install` instead
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
# cancel in-progress runs on new commits to same PR (gitub.event.number)
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
cancel-in-progress: true
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
Lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.4
- uses: actions/setup-node@v3
with:
node-version: '16.x'
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run lint
- run: pnpm run check
Tests:
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- node-version: 16
os: ubuntu-latest
e2e-browser: 'chromium'
- node-version: 18
os: ubuntu-latest
e2e-browser: 'chromium'
env:
KIT_E2E_BROWSER: ${{matrix.e2e-browser}}
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.4
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm playwright install ${{ matrix.e2e-browser }}
- run: pnpm test
- name: Archive test results
if: failure()
shell: bash
run: find packages -type d -name test-results -not -empty | tar -czf test-results.tar.gz --files-from=-
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v3
with:
retention-days: 3
name: test-failure-${{ github.run_id }}-${{ matrix.os }}-${{ matrix.node-version }}-${{ matrix.e2e-browser }}
path: test-results.tar.gz
Cross-browser-test:
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- node-version: 16
os: windows-2019 # slowness reported on newer versions https://github.com/actions/runner-images/issues/5166
e2e-browser: 'chromium'
mode: 'dev'
- node-version: 16
os: ubuntu-latest
e2e-browser: 'firefox'
mode: 'dev'
- node-version: 16
os: macOS-latest
e2e-browser: 'webkit'
mode: 'dev'
- node-version: 16
os: windows-2019 # slowness reported on newer versions https://github.com/actions/runner-images/issues/5166
e2e-browser: 'chromium'
mode: 'build'
- node-version: 16
os: ubuntu-latest
e2e-browser: 'firefox'
mode: 'build'
- node-version: 16
os: macOS-latest
e2e-browser: 'webkit'
mode: 'build'
env:
KIT_E2E_BROWSER: ${{matrix.e2e-browser}}
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.4
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm playwright install ${{ matrix.e2e-browser }}
- run: pnpm test:cross-platform:${{ matrix.mode }}
- name: Archive test results
if: failure()
shell: bash
run: find packages -type d -name test-results -not -empty | tar -czf test-results-cross-platform-${{ matrix.mode }}.tar.gz --files-from=-
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v3
with:
retention-days: 3
name: test-failure-cross-platform-${{ matrix.mode }}-${{ github.run_id }}-${{ matrix.os }}-${{ matrix.node-version }}-${{ matrix.e2e-browser }}
path: test-results-cross-platform-${{ matrix.mode }}.tar.gz
+14 -8
View File
@@ -1,12 +1,18 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"svelteSortOrder": "options-scripts-styles-markup",
"svelteBracketNewLine": true,
"svelteIndentScriptAndStyle": true,
"pluginSearchDirs": ["."],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
"arrowParens": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"semi": true,
"singleQuote": true,
"useTabs": true,
"tabWidth": 3,
"trailingComma": "all",
"overrides": [
{
"files": "*.svelte",
"options": { "parser": "svelte" }
}
]
}
+20 -11
View File
@@ -1,18 +1,31 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnType": false,
"editor.formatOnSave": true,
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": true
}
},
"eslint.packageManager": "pnpm",
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "svelte"],
"[typescript]": {
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }],
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnType": false,
"files.exclude": {
"**/.cache": true,
"**/.DS_Store": true,
"**/.gitattributes": true,
"**/.svelte-kit": true,
"**/*-lock.*": true,
"**/*.Identifier": true,
"**/*.map": true,
"**/.turbo": true,
"**/.vercel": true,
"**/dist": true,
"**/node_modules": true,
"**/tsconfig.tsbuildinfo": true,
"**/.npmrc": true
@@ -21,9 +34,5 @@
"**/node_modules": true,
"**/.svelte-kit": true
},
"problems.sortOrder": "severity",
"todo-tree.tree.scanMode": "workspace only",
"javascript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.importModuleSpecifier": "relative",
"files.associations": { ".env*": "dotenv", "*.svx": "mdx", "*.md": "mdx" }
"problems.sortOrder": "severity"
}
+33 -37
View File
@@ -13,17 +13,17 @@
},
"scripts": {
"dev": "vite dev",
"build": "vite build && pnpm package",
"build": "vite build && yarn package",
"preview": "vite preview",
"package": "svelte-kit sync && svelte-package && publint",
"test": "playwright test",
"sync": "svelte-kit sync",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint:prettier": "prettier --check --plugin-search-dir=. .",
"lint:eslint": "TIMING=1 eslint . --ext .ts,.tsx,.svelte --cache",
"lint": "pnpm lint:prettier && pnpm lint:eslint",
"lint": "yarn lint:prettier && yarn lint:eslint",
"format": "prettier --write --plugin-search-dir=. .",
"release": "pnpm package && changeset publish",
"release": "yarn package && changeset publish",
"ts": "tsc --pretty --noImplicitAny --noEmit"
},
"exports": {
@@ -36,63 +36,59 @@
"dist"
],
"peerDependencies": {
"svelte": "^3.55.1"
"svelte": ">=3.00.0"
},
"dependencies": {
"@inqling/svelte-icons": "^3.1.0",
"@inqling/svelte-icons": "^3.3.2",
"clsx": "^1.2.1",
"just-clamp": "^4.2.0",
"svelte-local-storage-store": "^0.4.0"
"svelte-local-storage-store": "^0.5.0"
},
"devDependencies": {
"@changesets/cli": "^2.26.0",
"@playwright/test": "^1.31.2",
"@sveltejs/adapter-static": "^2.0.1",
"@sveltejs/kit": "^1.11.0",
"@sveltejs/package": "^2.0.2",
"@changesets/cli": "^2.26.2",
"@sveltejs/adapter-static": "^2.0.2",
"@sveltejs/kit": "^1.22.1",
"@sveltejs/package": "^2.1.0",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.2",
"@tailwindcss/line-clamp": "^0.4.4",
"@tailwindcss/typography": "^0.5.9",
"@typescript-eslint/eslint-plugin": "^5.54.1",
"@typescript-eslint/parser": "^5.54.1",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"autoprefixer": "^10.4.14",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.7.0",
"eslint": "^8.44.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-svelte3": "^4.0.0",
"highlight.js": "^11.7.0",
"postcss": "^8.4.21",
"eslint-plugin-unused-imports": "^2.0.0",
"highlight.js": "^11.8.0",
"postcss": "^8.4.25",
"postcss-load-config": "^4.0.1",
"prettier": "^2.8.4",
"prettier-plugin-svelte": "^2.9.0",
"prettier-plugin-tailwindcss": "^0.2.4",
"publint": "^0.1.10",
"prettier": "^2.8.8",
"prettier-plugin-svelte": "^2.10.1",
"prettier-plugin-tailwindcss": "^0.3.0",
"publint": "^0.1.16",
"rehype-add-classes": "^1.0.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-external-links": "^2.0.1",
"rehype-external-links": "^2.1.0",
"rehype-highlight": "^6.0.0",
"rehype-sanitize": "^5.0.1",
"rehype-slug": "^5.1.0",
"rehype-stringify": "^9.0.3",
"remark-gfm": "^3.0.1",
"remark-github": "^11.2.4",
"remark-parse": "^10.0.1",
"remark-parse": "^10.0.2",
"remark-rehype": "^10.1.0",
"remark-toc": "^8.0.1",
"svelte": "^3.56.0",
"svelte-check": "^3.1.2",
"svelte-preprocess": "^4.10.7",
"svelte": "^4.0.5",
"svelte-check": "^3.4.5",
"svelte-preprocess": "^5.0.4",
"svhighlight": "^0.7.1",
"tailwindcss": "^3.2.7",
"tslib": "^2.5.0",
"typescript": "^4.9.5",
"tailwindcss": "^3.3.2",
"tslib": "^2.6.0",
"typescript": "^5.1.6",
"unified": "^10.1.2",
"vite": "^4.1.4"
"vite": "^4.4.2"
},
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
"packageManager": "pnpm@7.28.0",
"engines": {
"pnpm": "^7.0.0"
}
"type": "module"
}
-11
View File
@@ -1,11 +0,0 @@
import type { PlaywrightTestConfig } from '@playwright/test';
const config: PlaywrightTestConfig = {
webServer: {
command: 'npm run build && npm run preview',
port: 4173,
},
testDir: 'tests',
};
export default config;
-4867
View File
File diff suppressed because it is too large Load Diff
+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,
+1 -1
View File
@@ -14,7 +14,7 @@ const config = {
adapter: adapter(),
alias: {
'svelte-podcast': 'src/lib',
$content: 'src/content/',
$src: 'src',
},
paths: {
-6
View File
@@ -1,6 +0,0 @@
import { expect, test } from '@playwright/test';
test('index page has expected h1', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible();
});
+4649
View File
File diff suppressed because it is too large Load Diff