4 Commits

Author SHA1 Message Date
jaandrle e4e41197b9 🐛 fixes routing 2026-05-20 14:40:47 +02:00
jaandrle 7d6240e28a 🐛 📺 fixes dev server 2026-05-20 14:40:00 +02:00
jaandrle 139b1590ce Uses original router
- it has benefits to use hash properly
2026-04-29 13:40:40 +02:00
jaandrle 3cc11b68de 🎉 2026-04-28 17:16:00 +02:00
20 changed files with 216 additions and 185 deletions
+2
View File
@@ -5,6 +5,7 @@ set -eo pipefail # this can be harmful, see https://www.youtube.com/watch?v=4Jo3
exit 1;
}
# depends on
declare -r lint='bs/lint'
declare -r rollup='node_modules/.bin/rollup'
declare -r analyze='bs/analyze'
declare -r config='rollup.config.js'
@@ -20,6 +21,7 @@ help(){
main(){
help "${@}"
$lint
rm -rf "$dist"
$rollup -c $config "${@}"
$analyze --exclude "$dist"
+7 -5
View File
@@ -9,15 +9,17 @@ set -eo pipefail # this can be harmful, see https://www.youtube.com/watch?v=4Jo3
# depends on
declare -r server='node_modules/.bin/web-dev-server'
declare -r lint='bs/lint'
declare -r index='index.html'
declare -r server_config='web-dev-server.config.js'
help(){
if ! isHelp "${@}"; then return 0; fi
echoReadmeInfo
cat <<-EOF
Options:
./src Starts the development server (default)
./dist Starts the production server
Defaults:
See server config file: '$server_config'
EOF
$server --help
exit 0
@@ -26,12 +28,12 @@ main(){
help "${@}"
local -r target="${1:-./src}" # ./src or ./dist
if [[ "$target" == './dist' ]]; then
if [[ "$target" =~ 'dist' ]]; then
# console warns because of config file, use npx serve?
$server --root-dir "$target" --app-index $index --open
$server "${@}"
else
$lint --watch --preserveWatchOutput &
$server &
$server "${@}" &
wait
fi
}
+2 -1
View File
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<opml version="1.0">
<head>
<dateCreated>Tue, 21 Apr 2026 11:06:35 GMT</dateCreated>
<dateCreated>Fri, 24 Apr 2026 13:48:25 GMT</dateCreated>
<title>jaa-podcasty subscriptions in CommaFeed</title>
</head>
<body>
<outline text="Epizody z vypršených odběrů" type="rss" title="Epizody z vypršených odběrů" xmlUrl="https://jaandrle.cz/p/2026-04-07.xml" htmlUrl="https://jaandrle.cz/podcasts/" />
<outline text="Playlist: Čestmír &amp; Daniela - YouTube" type="rss" title="Playlist: Čestmír &amp; Daniela - YouTube" xmlUrl="http://rss-bridge.jaandrle.cz/?action=display&amp;bridge=YoutubeBridge&amp;token=Chief*Snowplow1*Drastic&amp;context=By+playlist+Id&amp;p=PLPK5bz7v9zh1BFEHQrNri-iCeugTjq1Jj&amp;duration_min=&amp;duration_max=&amp;format=Atom" htmlUrl="http://rss-bridge.jaandrle.cz/?action=display&amp;bridge=YoutubeBridge&amp;token=Chief*Snowplow1*Drastic&amp;context=By+playlist+Id&amp;p=PLPK5bz7v9zh1BFEHQrNri-iCeugTjq1Jj&amp;duration_min=&amp;duration_max=&amp;format=Atom" />
<outline text="5:59" type="rss" title="5:59" xmlUrl="https://feeds.transistor.fm/5-59" htmlUrl="https://www.seznamzpravy.cz/" />
<outline text="Redneck &amp; Beneš" type="rss" title="Redneck &amp; Beneš" xmlUrl="https://www.voxpot.cz/pod/rss/844dd837-6063-4b77-99c5-5adf7c7622f5/redneck-benes.xml" htmlUrl="https://www.voxpot.cz/muj-ucet" />
<outline text="Pinepods News Podcast" type="rss" title="Pinepods News Podcast" xmlUrl="https://news.pinepods.online/feed.xml" htmlUrl="https://news.pinepods.online" />
<outline text="Český rozhlas - Věda" type="rss" title="Český rozhlas - Věda" xmlUrl="https://api.mujrozhlas.cz/rss/topic/8c432621-a9a9-4c0a-8376-ea4ae5707fbb.rss" htmlUrl="https://www.mujrozhlas.cz/topic/view/8c432621-a9a9-4c0a-8376-ea4ae5707fbb" />
<outline text="Bilance" type="rss" title="Bilance" xmlUrl="https://feeds.transistor.fm/bilance" htmlUrl="https://www.ceskatelevize.cz/porady/14021364946-bilance/" />
+1 -1
View File
@@ -23,7 +23,7 @@
<body>
<app-cfpodcasts></app-cfpodcasts>
<script type="module" src="./out-tsc/src/app-index.js"></script>
<script type="module" src="./out-tsc/src/index.js"></script>
</body>
</html>
+10 -75
View File
@@ -9,6 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"dependencies": {
"@lit-labs/router": "^0.1.4",
"lit": "~3.3"
},
"devDependencies": {
@@ -2201,6 +2202,15 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@lit-labs/router": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/@lit-labs/router/-/router-0.1.4.tgz",
"integrity": "sha512-xURH6fOPE0MYfXa1nyl+qTIhZRVWkFa2oggTRodKAI2q/HjA2Va7HEKe7fMm8DdnFE+zEI2aUGnStawKpVh3lQ==",
"license": "BSD-3-Clause",
"dependencies": {
"lit": "^2.0.0 || ^3.0.0"
}
},
"node_modules/@lit-labs/ssr-dom-shim": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz",
@@ -2435,9 +2445,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2452,9 +2459,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2469,9 +2473,6 @@
"ppc64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2486,9 +2487,6 @@
"riscv64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2503,9 +2501,6 @@
"riscv64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2520,9 +2515,6 @@
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2537,9 +2529,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2554,9 +2543,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2897,9 +2883,6 @@
"arm"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2914,9 +2897,6 @@
"arm"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2931,9 +2911,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2948,9 +2925,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2965,9 +2939,6 @@
"loong64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2982,9 +2953,6 @@
"loong64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2999,9 +2967,6 @@
"ppc64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -3016,9 +2981,6 @@
"ppc64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -3033,9 +2995,6 @@
"riscv64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -3050,9 +3009,6 @@
"riscv64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -3067,9 +3023,6 @@
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -3084,9 +3037,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -3101,9 +3051,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -7961,9 +7908,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7985,9 +7929,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -8009,9 +7950,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -8033,9 +7971,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0",
"optional": true,
"os": [
+1
View File
@@ -11,6 +11,7 @@
"start": "bs/start"
},
"dependencies": {
"@lit-labs/router": "^0.1.4",
"lit": "~3.3"
},
"devDependencies": {
+9
View File
@@ -0,0 +1,9 @@
import { css } from "lit";
export const styles = css`
:host {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
}
`;
+14
View File
@@ -0,0 +1,14 @@
import { LitElement, html } from "lit";
import { property, customElement } from "lit/decorators.js";
import { styles } from "./index.css.js";
@customElement("app-episode")
export class AppEpisode extends LitElement {
static override styles = styles;
@property({ type: String }) override id = "";
override render() {
return html`
Episode ${this.id}
`;
}
}
+16
View File
@@ -0,0 +1,16 @@
import { route } from "../../core/route.js";
import { html } from "lit";
export const path = "/episodes" as const;
export const routes = route(
{
path: "/episodes/:id",
async enter() {
await import("./index.js");
return true;
},
render({ id }){
return html`<app-episode id=${id}></app-episode>`;
},
},
);
+9
View File
@@ -0,0 +1,9 @@
import { css } from "lit";
export const styles = css`
:host {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
}
`;
+16
View File
@@ -0,0 +1,16 @@
import { LitElement, html } from "lit";
import { customElement } from "lit/decorators.js";
import { styles } from "./index.css.js";
const logo = new URL("../../../assets/logo.svg", import.meta.url);
@customElement("app-episodes")
export class AppEpisodes extends LitElement {
static override styles = styles;
override render() {
return html`
<div class="logo"><img alt="open-wc logo" src=${logo} /></div>
<a href="/episodes/1">Episode 1</a>
`;
}
}
+18
View File
@@ -0,0 +1,18 @@
import { route } from "../core/route.js";
import { routes as routeEpisode } from "./:id/routes.js";
import { html } from "lit";
export const path = "/episodes" as const;
export const routes = route(
{
path,
async enter() {
await import("./index.js");
return true;
},
render(){
return html`<app-episodes></app-episodes>`;
},
},
routeEpisode,
);
-33
View File
@@ -1,33 +0,0 @@
import { css } from "lit";
export const styles = css`
:host {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
font-size: calc(10px + 2vmin);
color: #1a2b42;
max-width: 960px;
margin: 0 auto;
text-align: center;
background-color: var(--app-cfpodcasts-background-color);
}
main {
flex-grow: 1;
}
.logo {
margin-top: 36px;
}
.app-footer {
font-size: calc(12px + 0.5vmin);
align-items: center;
}
.app-footer a {
margin-left: 5px;
}
`;
-39
View File
@@ -1,39 +0,0 @@
import { LitElement, html } from "lit";
import { property, customElement } from "lit/decorators.js";
import { styles } from "./app-index.css.js";
const logo = import.meta.resolve("../../assets/logo.svg");
@customElement("app-cfpodcasts")
export class AppCfpodcasts extends LitElement {
@property({ type: String }) header = "My app";
static styles = styles;
render() {
return html`
<main>
<div class="logo"><img alt="open-wc logo" src=${logo} /></div>
<h1>${this.header}</h1>
<p>Edit <code>src/AppCfpodcasts.ts</code> and save to reload.</p>
<a
class="app-link"
href="https://open-wc.org/guides/developing-components/code-examples"
target="_blank"
rel="noopener noreferrer"
>
Code examples
</a>
</main>
<p class="app-footer">
🚽 Made with love by
<a
target="_blank"
rel="noopener noreferrer"
href="https://github.com/open-wc"
>open-wc</a
>.
</p>
`;
}
}
+13
View File
@@ -0,0 +1,13 @@
import type { PathRouteConfig } from "@lit-labs/router";
export function route(...routes: (PathRouteConfig|PathRouteConfig[])[]): PathRouteConfig[] {
return routes.flatMap(function process(route){
if (Array.isArray(route)) // already processed
return route;
const { path, ...rest }= route;
return [
{ path, ...rest },
{ path: path + "/", rest },
];
});
}
+20
View File
@@ -0,0 +1,20 @@
import { css } from "lit";
export const styles = css`
:host {
height: 100vh;
height: 100dvh;
display: grid;
grid-template-areas:
"main"
"footer";
grid-template-rows: auto 2.5ch;
}
main {
grid-area: main;
}
nav {
grid-area: footer;
}
`;
+24
View File
@@ -0,0 +1,24 @@
import { LitElement, html } from "lit";
import { customElement } from "lit/decorators.js";
import { styles } from "./index.css.js";
import { Router } from "@lit-labs/router";
import * as routeEpisodes from "./app-episodes/routes.js";
@customElement("app-cfpodcasts")
export class AppCfpodcasts extends LitElement {
static override styles = styles;
private _routes = new Router(this, [
{ path: "/", render: () => html`Hello world` },
...routeEpisodes.routes,
]);
override render() {
console.log(this._routes);
return html`
<main>${this._routes.outlet()}</main>
<nav>
<a href="${this._routes.link("/")}">Home</a>
<a href="${this._routes.link(routeEpisodes.path)}">Episodes</a>
</nav>
`;
}
}
+2 -2
View File
@@ -1,8 +1,8 @@
import { html } from 'lit';
import { fixture, expect } from '@open-wc/testing';
import type { AppCfpodcasts } from '../src/app-index.js';
import '../src/app-cfpodcasts.js';
import type { AppCfpodcasts } from '../src/index.js';
import '../src/index.js';
describe('AppCfpodcasts', () => {
let element: AppCfpodcasts;
+21 -4
View File
@@ -1,21 +1,38 @@
{
"compilerOptions": {
"verbatimModuleSyntax": true,
"noEmitOnError": true,
"target": "es2021",
"skipLibCheck": true,
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noEmitOnError": true,
"lib": ["es2021", "dom", "DOM.Iterable"],
"isolatedModules": true,
"strict": true,
"esModuleInterop": false,
"strictBindCallApply": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noUncheckedSideEffectImports": true,
"allowUnreachableCode": false,
"noUncheckedIndexedAccess": true,
"noPropertyAccessFromIndexSignature": true,
"erasableSyntaxOnly": true,
"noImplicitOverride": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"useDefineForClassFields": false,
"experimentalDecorators": true,
"importHelpers": true,
"noErrorTruncation": false,
"outDir": "out-tsc",
"sourceMap": true,
"inlineSources": true,
"rootDir": "./",
"incremental": true,
"skipLibCheck": true
"types": ["mocha"],
"lib": ["es2021", "dom", "DOM.Iterable"]
},
"include": ["**/*.ts"]
}
+16 -10
View File
@@ -1,21 +1,27 @@
// import { hmrPlugin, presets } from "@open-wc/dev-server-hmr";
/** Use Hot Module replacement by adding --hmr to the start command */
const hmr = process.argv.includes("--hmr");
/** Use Hot Module replacement by adding --watch to the start command */
//const hmr = process.argv.includes("--watch");
const [ mode ] = process.argv.slice(2);
const target = mode === "src" // OR "dist"
? {
rootDir: ".",
appIndex: "./index.html",
}
: {
rootDir: "./dist",
appIndex: "./dist/index.html",
};
export default /** @type {import("@web/dev-server").DevServerConfig} */ ({
open: "/",
watch: !hmr,
/** Resolve bare module imports */
nodeResolve: {
open: "/", // SPA routing
nodeResolve: { // Resolve bare module imports
exportConditions: ["browser", "development"],
},
/** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
// esbuildTarget: "auto"
// esbuildTarget: "auto" // Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
/** Set appIndex to enable SPA routing */
appIndex: "./index.html",
...target,
plugins: [
/** Use Hot Module Replacement by uncommenting. Requires @open-wc/dev-server-hmr plugin */