create-xmlui-app 0.12.28 → 0.12.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/blog/ts/.github/workflows/check.yml +24 -0
  2. package/dist/blog/ts/content/blog/building-a-docs-site-with-xmlui.md +44 -0
  3. package/dist/blog/ts/content/blog/theming-in-xmlui.md +47 -0
  4. package/dist/blog/ts/content/blog/welcome-to-my-blog.md +36 -0
  5. package/dist/blog/ts/gitignore +31 -0
  6. package/dist/blog/ts/index.html +14 -0
  7. package/dist/blog/ts/index.ts +13 -0
  8. package/dist/blog/ts/public/resources/favicon.ico +0 -0
  9. package/dist/blog/ts/public/resources/xmlui-logo-dark.svg +9 -0
  10. package/dist/blog/ts/public/resources/xmlui-logo.svg +8 -0
  11. package/dist/blog/ts/public/serve.json +8 -0
  12. package/dist/blog/ts/src/Main.xmlui +31 -0
  13. package/dist/blog/ts/src/components/PostCard.xmlui +19 -0
  14. package/dist/blog/ts/src/components/PostList.xmlui +7 -0
  15. package/dist/blog/ts/src/components/PostPage.xmlui +44 -0
  16. package/dist/blog/ts/src/components/PostTag.xmlui +12 -0
  17. package/dist/blog/ts/src/config.ts +20 -0
  18. package/dist/blog/ts/src/content.ts +66 -0
  19. package/dist/blog/ts/xmlui.config.json +16 -0
  20. package/dist/default/ts/.github/workflows/check.yml +24 -0
  21. package/dist/default/ts/gitignore +31 -0
  22. package/dist/default/ts/index.html +14 -0
  23. package/dist/default/ts/index.ts +9 -0
  24. package/dist/default/ts/public/mockServiceWorker.js +307 -0
  25. package/dist/default/ts/public/resources/favicon.ico +0 -0
  26. package/dist/default/ts/public/resources/xmlui-logo.svg +9 -0
  27. package/dist/default/ts/public/serve.json +8 -0
  28. package/dist/default/ts/src/Main.xmlui +37 -0
  29. package/dist/default/ts/src/components/ApiAware.xmlui +9 -0
  30. package/dist/default/ts/src/components/Home.xmlui +17 -0
  31. package/dist/default/ts/src/components/IncButton.xmlui +6 -0
  32. package/dist/default/ts/src/components/PagePanel.xmlui +5 -0
  33. package/dist/default/ts/src/config.ts +12 -0
  34. package/dist/default/ts/xmlui.config.json +16 -0
  35. package/dist/docs/ts/.github/workflows/check.yml +24 -0
  36. package/dist/docs/ts/content/docs/api/endpoints.md +128 -0
  37. package/dist/docs/ts/content/docs/api/overview.md +72 -0
  38. package/dist/docs/ts/content/docs/changelog.md +41 -0
  39. package/dist/docs/ts/content/docs/configuration.md +92 -0
  40. package/dist/docs/ts/content/docs/guides/advanced.md +113 -0
  41. package/dist/docs/ts/content/docs/guides/core-concepts.md +95 -0
  42. package/dist/docs/ts/content/docs/installation.md +89 -0
  43. package/dist/docs/ts/content/docs/introduction.md +53 -0
  44. package/dist/docs/ts/content/docs/quick-start.md +47 -0
  45. package/dist/docs/ts/gitignore +31 -0
  46. package/dist/docs/ts/icons/article.svg +18 -0
  47. package/dist/docs/ts/icons/bolt.svg +15 -0
  48. package/dist/docs/ts/icons/braces.svg +4 -0
  49. package/dist/docs/ts/icons/deploy.svg +19 -0
  50. package/dist/docs/ts/icons/file-code.svg +18 -0
  51. package/dist/docs/ts/icons/markup.svg +1 -0
  52. package/dist/docs/ts/icons/refactor.svg +15 -0
  53. package/dist/docs/ts/icons/school.svg +17 -0
  54. package/dist/docs/ts/icons/settings.svg +16 -0
  55. package/dist/docs/ts/index.html +14 -0
  56. package/dist/docs/ts/index.ts +13 -0
  57. package/dist/docs/ts/public/resources/favicon.ico +0 -0
  58. package/dist/docs/ts/public/resources/xmlui-logo-dark.svg +9 -0
  59. package/dist/docs/ts/public/resources/xmlui-logo.svg +8 -0
  60. package/dist/docs/ts/public/serve.json +8 -0
  61. package/dist/docs/ts/src/Main.xmlui +72 -0
  62. package/dist/docs/ts/src/config.ts +34 -0
  63. package/dist/docs/ts/src/content.ts +35 -0
  64. package/dist/docs/ts/xmlui.config.json +16 -0
  65. package/dist/index.js +64 -0
  66. package/dist/minimal/ts/.github/workflows/check.yml +24 -0
  67. package/dist/minimal/ts/gitignore +31 -0
  68. package/dist/minimal/ts/index.html +14 -0
  69. package/dist/minimal/ts/index.ts +9 -0
  70. package/dist/minimal/ts/public/mockServiceWorker.js +307 -0
  71. package/dist/minimal/ts/public/resources/favicon.ico +0 -0
  72. package/dist/minimal/ts/public/resources/xmlui-logo.svg +9 -0
  73. package/dist/minimal/ts/public/serve.json +8 -0
  74. package/dist/minimal/ts/src/Main.xmlui +27 -0
  75. package/dist/minimal/ts/src/config.ts +10 -0
  76. package/dist/minimal/ts/xmlui.config.json +16 -0
  77. package/package.json +1 -1
@@ -0,0 +1,24 @@
1
+ name: XMLUI Check
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ check:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Set up Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version: "20"
18
+ cache: "npm"
19
+
20
+ - name: Install dependencies
21
+ run: npm ci
22
+
23
+ - name: Run xmlui static analyzer
24
+ run: npm run check
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: "Building a Docs Site with XMLUI"
3
+ slug: "building-a-docs-site-with-xmlui"
4
+ description: "A step-by-step walkthrough of the docs template — navigation, TOC, and Markdown rendering."
5
+ author: "Jane Smith"
6
+ date: "2025-03-10"
7
+ tags: ["tutorial", "xmlui"]
8
+ ---
9
+
10
+ ## The Docs Template
11
+
12
+ The `create-xmlui-app` tool ships with a docs template that gives you a complete
13
+ documentation site in minutes:
14
+
15
+ ```bash
16
+ npx create-xmlui-app my-docs --template docs
17
+ cd my-docs && npm start
18
+ ```
19
+
20
+ ## What You Get
21
+
22
+ The template includes:
23
+
24
+ - A **sidebar** built with `NavPanel` and collapsible `NavGroup` sections
25
+ - A **Table of Contents** sidebar that auto-generates from page headings
26
+ - **Full-text search** across all Markdown content
27
+ - **Previous / next** navigation between pages
28
+ - A **dark / light mode** toggle
29
+
30
+ ## How the Layout Works
31
+
32
+ The `vertical-sticky` app layout puts the `NavPanel` on the left and the content area on
33
+ the right. Inside each content page, the `DocumentPage` component (from
34
+ `xmlui-docs-blocks`) renders the Markdown next to a `TableOfContents` and a prev/next
35
+ links section.
36
+
37
+ ## Adding a New Page
38
+
39
+ 1. Drop a new `.md` file into `content/docs/`.
40
+ 2. Add a `NavLink` in the `NavPanel` section of `Main.xmlui`.
41
+ 3. Add a matching `Page` element inside `Pages` that loads the Markdown via
42
+ `appGlobals.docsContent['<filename>']`.
43
+
44
+ That is all it takes.
@@ -0,0 +1,47 @@
1
+ ---
2
+ title: "Theming in XMLUI"
3
+ slug: "theming-in-xmlui"
4
+ description: "How to customise colours, typography, and spacing with XMLUI theme variables."
5
+ author: "Alex Johnson"
6
+ date: "2025-03-20"
7
+ tags: ["theming", "xmlui", "css"]
8
+ ---
9
+
10
+ ## The Theme System
11
+
12
+ XMLUI uses a token-based theming system. Every component exposes a set of CSS-variable-like
13
+ theme variables that you can override at any level of the tree.
14
+
15
+ ## Changing the Primary Color
16
+
17
+ Wrap any subtree in a `Theme` component and set the token you want to override. The
18
+ `color-primary-500` token cascades to buttons, links, and active navigation items
19
+ automatically.
20
+
21
+ ```xml
22
+ <Theme color-primary-500="#6366f1">
23
+ <App>
24
+ ...
25
+ </App>
26
+ </Theme>
27
+ ```
28
+
29
+ ## Typography
30
+
31
+ Use `fontFamily-base`, `fontSize-base`, and `lineHeight-base` theme variables to set the
32
+ global typography for your app.
33
+
34
+ ## Dark Mode
35
+
36
+ Add `autoDetectTone="true"` on the `App` component to follow the system preference. Or
37
+ let users switch manually with the `ToneChangerButton` component in the `AppHeader`.
38
+
39
+ ## Scoped Themes
40
+
41
+ Themes are scoped — they only affect descendants. This lets you apply a different look to
42
+ a single section without touching the rest of the app.
43
+
44
+ ## Finding Token Names
45
+
46
+ Every component's documentation lists its supported theme variables. You can also inspect
47
+ the rendered HTML and look for CSS custom properties prefixed with `--xmlui-`.
@@ -0,0 +1,36 @@
1
+ ---
2
+ title: "Welcome to My Blog"
3
+ slug: "welcome-to-my-blog"
4
+ description: "The first post on this blog — what to expect and how it was built."
5
+ author: "Jane Smith"
6
+ date: "2025-03-01"
7
+ tags: ["news", "meta"]
8
+ ---
9
+
10
+ ## Why I Started This Blog
11
+
12
+ Every developer needs a place to share ideas, document experiments, and connect with others. This blog is mine.
13
+
14
+ I built it with [XMLUI](https://xmlui.org) — a declarative UI framework that lets me write apps in markup without wrestling with component boilerplate.
15
+
16
+ ## What to Expect
17
+
18
+ I plan to write about:
19
+
20
+ - **XMLUI tips and tricks** — patterns I find useful day to day
21
+ - **Project walkthroughs** — building real apps from scratch
22
+ - **Tooling** — the CLI tools, editors, and workflows that make me productive
23
+
24
+ ## How This Site Works
25
+
26
+ The blog is a single XMLUI app with a post listing page and individual post pages. All
27
+ posts live in `content/blog/` as Markdown files with a frontmatter header. To add a new
28
+ post, drop a new `.md` file into that folder — title, slug, date, author, and tags all
29
+ come from the frontmatter.
30
+
31
+ For a larger blog you would swap the local Markdown for an API call — the `PostList` and
32
+ `PostPage` components stay exactly the same.
33
+
34
+ ## Get in Touch
35
+
36
+ Have a question or idea? Open an issue on the repo or reach out directly.
@@ -0,0 +1,31 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+
15
+ # Editor directories and files
16
+ .vscode/*
17
+ !.vscode/extensions.json
18
+ .idea
19
+ .DS_Store
20
+ *.suo
21
+ *.ntvs*
22
+ *.njsproj
23
+ *.sln
24
+ *.sw?
25
+ /test-results/
26
+ /playwright-report/
27
+ /playwright/.cache/
28
+
29
+ .env.local
30
+ .env.production
31
+
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/resources/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <script>window.__PUBLIC_PATH = '/'</script>
8
+ <base href="/">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ <script type="module" src="/index.ts"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,13 @@
1
+ import { startApp } from "xmlui";
2
+ import search from "xmlui-search";
3
+ import docsBlocks from "xmlui-docs-blocks";
4
+
5
+ export const runtime = import.meta.glob(`/src/**`, { eager: true });
6
+ const usedExtensions = [search, docsBlocks];
7
+ startApp(runtime, usedExtensions);
8
+
9
+ if (import.meta.hot) {
10
+ import.meta.hot.accept((newModule) => {
11
+ startApp(newModule?.runtime ?? runtime, usedExtensions);
12
+ });
13
+ }
@@ -0,0 +1,9 @@
1
+ <svg width="312" height="122" viewBox="0 0 312 122" fill="none"
2
+ xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M229.875 98.0763C225.499 98.0763 221.696 97.1076 218.467 95.1703C215.31 93.1613 212.87 90.363 211.148 86.7755C209.426 83.1162 208.565 78.8111 208.565 73.8603V43.6173C208.565 42.8998 208.817 42.2899 209.319 41.7877C209.821 41.2854 210.431 41.0343 211.148 41.0343H220.62C221.409 41.0343 222.019 41.2854 222.449 41.7877C222.951 42.2899 223.203 42.8998 223.203 43.6173V73.2146C223.203 82.1117 227.113 86.5602 234.934 86.5602C238.665 86.5602 241.607 85.3763 243.759 83.0086C245.984 80.6408 247.096 77.3761 247.096 73.2146V43.6173C247.096 42.8998 247.347 42.2899 247.849 41.7877C248.351 41.2854 248.961 41.0343 249.679 41.0343H259.15C259.867 41.0343 260.477 41.2854 260.979 41.7877C261.482 42.2899 261.733 42.8998 261.733 43.6173V94.417C261.733 95.1345 261.482 95.7443 260.979 96.2466C260.477 96.7489 259.867 97 259.15 97H250.432C249.643 97 248.997 96.7489 248.495 96.2466C248.064 95.7443 247.849 95.1345 247.849 94.417V90.0043C245.912 92.5156 243.508 94.4887 240.638 95.9237C237.768 97.3587 234.18 98.0763 229.875 98.0763Z" fill="#3367CC"/>
4
+ <path d="M278.533 97C277.815 97 277.205 96.7489 276.703 96.2466C276.201 95.7443 275.95 95.1345 275.95 94.417V43.6173C275.95 42.8998 276.201 42.2899 276.703 41.7877C277.205 41.2854 277.815 41.0343 278.533 41.0343H287.466C288.255 41.0343 288.865 41.2854 289.295 41.7877C289.798 42.2899 290.049 42.8998 290.049 43.6173V94.417C290.049 95.1345 289.798 95.7443 289.295 96.2466C288.865 96.7489 288.255 97 287.466 97H278.533ZM278.102 31.7784C277.313 31.7784 276.667 31.5632 276.165 31.1327C275.734 30.6304 275.519 29.9847 275.519 29.1954V21.4463C275.519 20.7288 275.734 20.1189 276.165 19.6167C276.667 19.1144 277.313 18.8633 278.102 18.8633H287.896C288.685 18.8633 289.331 19.1144 289.833 19.6167C290.336 20.1189 290.587 20.7288 290.587 21.4463V29.1954C290.587 29.9847 290.336 30.6304 289.833 31.1327C289.331 31.5632 288.685 31.7784 287.896 31.7784H278.102Z" fill="#3367CC"/>
5
+ <path d="M3.73546 97.0006C3.0897 97.0006 2.51569 96.7854 2.01343 96.3549C1.58293 95.8526 1.36768 95.2786 1.36768 94.6329C1.36768 94.4176 1.40355 94.1665 1.4753 93.8795C1.6188 93.5925 1.83406 93.2337 2.12106 92.8032L20.4175 68.2644L3.41258 45.2324C3.19732 44.8736 3.01795 44.5507 2.87444 44.2637C2.80269 43.9767 2.76682 43.6897 2.76682 43.4027C2.76682 42.757 2.98207 42.2188 3.41258 41.7883C3.91483 41.2861 4.48884 41.0349 5.1346 41.0349H14.4981C15.3591 41.0349 16.0049 41.2502 16.4354 41.6807C16.8659 42.1112 17.1887 42.5058 17.404 42.8646L29.5658 59.0085L41.7275 42.8646C42.0146 42.5058 42.3374 42.1112 42.6962 41.6807C43.1267 41.2502 43.7724 41.0349 44.6335 41.0349H53.5664C54.2122 41.0349 54.7503 41.2861 55.1808 41.7883C55.6831 42.2188 55.9342 42.7211 55.9342 43.2951C55.9342 43.6538 55.8625 43.9767 55.719 44.2637C55.6472 44.5507 55.5037 44.8736 55.2885 45.2324L38.0683 68.4797L56.4724 92.8032C56.7594 93.2337 56.9387 93.5925 57.0105 93.8795C57.154 94.1665 57.2257 94.4176 57.2257 94.6329C57.2257 95.2786 56.9746 95.8526 56.4724 96.3549C56.0418 96.7854 55.5037 97.0006 54.858 97.0006H45.064C44.2747 97.0006 43.6648 96.8212 43.2343 96.4625C42.8038 96.032 42.4451 95.6374 42.1581 95.2786L29.2429 78.166L16.1125 95.2786C15.8255 95.6374 15.4667 96.032 15.0362 96.4625C14.6775 96.8212 14.0676 97.0006 13.2066 97.0006H3.73546Z" fill="white"/>
6
+ <path d="M69.4363 97.0006C68.7188 97.0006 68.1089 96.7495 67.6066 96.2472C67.1044 95.745 66.8532 95.1351 66.8532 94.4176V43.618C66.8532 42.9005 67.1044 42.2906 67.6066 41.7883C68.1089 41.2861 68.7188 41.0349 69.4363 41.0349H77.8311C78.5486 41.0349 79.1585 41.2861 79.6608 41.7883C80.163 42.2906 80.4142 42.9005 80.4142 43.618V47.2773C81.9209 45.2682 83.93 43.5821 86.4412 42.2188C89.0243 40.7838 92.0737 40.0304 95.5895 39.9587C103.769 39.8152 109.473 43.0081 112.702 49.5374C114.352 46.6674 116.72 44.3714 119.805 42.6493C122.962 40.8556 126.442 39.9587 130.245 39.9587C133.976 39.9587 137.348 40.8197 140.362 42.5417C143.447 44.2637 145.851 46.8826 147.573 50.3984C149.367 53.8425 150.264 58.2193 150.264 63.5288V94.4176C150.264 95.1351 150.013 95.745 149.51 96.2472C149.008 96.7495 148.398 97.0006 147.681 97.0006H138.855C138.138 97.0006 137.528 96.7495 137.026 96.2472C136.523 95.745 136.272 95.1351 136.272 94.4176V64.3899C136.272 61.1611 135.806 58.6139 134.873 56.7484C133.94 54.8111 132.685 53.4478 131.106 52.6586C129.528 51.8693 127.77 51.4747 125.832 51.4747C124.254 51.4747 122.675 51.8693 121.097 52.6586C119.518 53.4478 118.227 54.8111 117.222 56.7484C116.218 58.6139 115.716 61.1611 115.716 64.3899V94.4176C115.716 95.1351 115.464 95.745 114.962 96.2472C114.46 96.7495 113.85 97.0006 113.133 97.0006H104.307C103.518 97.0006 102.872 96.7495 102.37 96.2472C101.939 95.745 101.724 95.1351 101.724 94.4176V64.3899C101.724 61.1611 101.222 58.6139 100.217 56.7484C99.2129 54.8111 97.9214 53.4478 96.3429 52.6586C94.7643 51.8693 93.0782 51.4747 91.2844 51.4747C89.6342 51.4747 88.0198 51.9052 86.4412 52.7662C84.8627 53.5555 83.5712 54.8829 82.5667 56.7484C81.5622 58.6139 81.0599 61.1611 81.0599 64.3899V94.4176C81.0599 95.1351 80.8088 95.745 80.3065 96.2472C79.8043 96.7495 79.1944 97.0006 78.4769 97.0006H69.4363Z" fill="white"/>
7
+ <path d="M166.66 97.0006C165.942 97.0006 165.332 96.7495 164.83 96.2472C164.328 95.745 164.077 95.1351 164.077 94.4176V23.169C164.077 22.4515 164.328 21.8416 164.83 21.3393C165.332 20.8371 165.942 20.5859 166.66 20.5859H175.593C176.31 20.5859 176.92 20.8371 177.422 21.3393C177.925 21.8416 178.176 22.4515 178.176 23.169V94.4176C178.176 95.1351 177.925 95.745 177.422 96.2472C176.92 96.7495 176.31 97.0006 175.593 97.0006H166.66Z" fill="white"/>
8
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M309 3H193V119H309V3ZM191 1V121H311V1H191Z" fill="#3367CC"/>
9
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="312" height="122" viewBox="0 0 312 122" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M229.875 98.0763C225.499 98.0763 221.696 97.1076 218.467 95.1703C215.31 93.1613 212.87 90.363 211.148 86.7755C209.426 83.1162 208.565 78.8111 208.565 73.8603V43.6173C208.565 42.8998 208.817 42.2899 209.319 41.7877C209.821 41.2854 210.431 41.0343 211.148 41.0343H220.62C221.409 41.0343 222.019 41.2854 222.449 41.7877C222.951 42.2899 223.203 42.8998 223.203 43.6173V73.2146C223.203 82.1117 227.113 86.5602 234.934 86.5602C238.665 86.5602 241.607 85.3763 243.759 83.0086C245.984 80.6408 247.096 77.3761 247.096 73.2146V43.6173C247.096 42.8998 247.347 42.2899 247.849 41.7877C248.351 41.2854 248.961 41.0343 249.679 41.0343H259.15C259.867 41.0343 260.477 41.2854 260.979 41.7877C261.482 42.2899 261.733 42.8998 261.733 43.6173V94.417C261.733 95.1345 261.482 95.7443 260.979 96.2466C260.477 96.7489 259.867 97 259.15 97H250.432C249.643 97 248.997 96.7489 248.495 96.2466C248.064 95.7443 247.849 95.1345 247.849 94.417V90.0043C245.912 92.5156 243.508 94.4887 240.638 95.9237C237.768 97.3587 234.18 98.0763 229.875 98.0763Z" fill="#3367CC"/>
3
+ <path d="M278.533 97C277.815 97 277.205 96.7489 276.703 96.2466C276.201 95.7443 275.95 95.1345 275.95 94.417V43.6173C275.95 42.8998 276.201 42.2899 276.703 41.7877C277.205 41.2854 277.815 41.0343 278.533 41.0343H287.466C288.255 41.0343 288.865 41.2854 289.295 41.7877C289.798 42.2899 290.049 42.8998 290.049 43.6173V94.417C290.049 95.1345 289.798 95.7443 289.295 96.2466C288.865 96.7489 288.255 97 287.466 97H278.533ZM278.102 31.7784C277.313 31.7784 276.667 31.5632 276.165 31.1327C275.734 30.6304 275.519 29.9847 275.519 29.1954V21.4463C275.519 20.7288 275.734 20.1189 276.165 19.6167C276.667 19.1144 277.313 18.8633 278.102 18.8633H287.896C288.685 18.8633 289.331 19.1144 289.833 19.6167C290.336 20.1189 290.587 20.7288 290.587 21.4463V29.1954C290.587 29.9847 290.336 30.6304 289.833 31.1327C289.331 31.5632 288.685 31.7784 287.896 31.7784H278.102Z" fill="#3367CC"/>
4
+ <path d="M3.73546 97.0006C3.0897 97.0006 2.51569 96.7854 2.01343 96.3549C1.58293 95.8526 1.36768 95.2786 1.36768 94.6329C1.36768 94.4176 1.40355 94.1665 1.4753 93.8795C1.6188 93.5925 1.83406 93.2337 2.12106 92.8032L20.4175 68.2644L3.41258 45.2324C3.19732 44.8736 3.01795 44.5507 2.87444 44.2637C2.80269 43.9767 2.76682 43.6897 2.76682 43.4027C2.76682 42.757 2.98207 42.2188 3.41258 41.7883C3.91483 41.2861 4.48884 41.0349 5.1346 41.0349H14.4981C15.3591 41.0349 16.0049 41.2502 16.4354 41.6807C16.8659 42.1112 17.1887 42.5058 17.404 42.8646L29.5658 59.0085L41.7275 42.8646C42.0146 42.5058 42.3374 42.1112 42.6962 41.6807C43.1267 41.2502 43.7724 41.0349 44.6335 41.0349H53.5664C54.2122 41.0349 54.7503 41.2861 55.1808 41.7883C55.6831 42.2188 55.9342 42.7211 55.9342 43.2951C55.9342 43.6538 55.8625 43.9767 55.719 44.2637C55.6472 44.5507 55.5037 44.8736 55.2885 45.2324L38.0683 68.4797L56.4724 92.8032C56.7594 93.2337 56.9387 93.5925 57.0105 93.8795C57.154 94.1665 57.2257 94.4176 57.2257 94.6329C57.2257 95.2786 56.9746 95.8526 56.4724 96.3549C56.0418 96.7854 55.5037 97.0006 54.858 97.0006H45.064C44.2747 97.0006 43.6648 96.8212 43.2343 96.4625C42.8038 96.032 42.4451 95.6374 42.1581 95.2786L29.2429 78.166L16.1125 95.2786C15.8255 95.6374 15.4667 96.032 15.0362 96.4625C14.6775 96.8212 14.0676 97.0006 13.2066 97.0006H3.73546Z" fill="#333366"/>
5
+ <path d="M69.4363 97.0006C68.7188 97.0006 68.1089 96.7495 67.6066 96.2472C67.1044 95.745 66.8532 95.1351 66.8532 94.4176V43.618C66.8532 42.9005 67.1044 42.2906 67.6066 41.7883C68.1089 41.2861 68.7188 41.0349 69.4363 41.0349H77.8311C78.5486 41.0349 79.1585 41.2861 79.6608 41.7883C80.163 42.2906 80.4142 42.9005 80.4142 43.618V47.2773C81.9209 45.2682 83.93 43.5821 86.4412 42.2188C89.0243 40.7838 92.0737 40.0304 95.5895 39.9587C103.769 39.8152 109.473 43.0081 112.702 49.5374C114.352 46.6674 116.72 44.3714 119.805 42.6493C122.962 40.8556 126.442 39.9587 130.245 39.9587C133.976 39.9587 137.348 40.8197 140.362 42.5417C143.447 44.2637 145.851 46.8826 147.573 50.3984C149.367 53.8425 150.264 58.2193 150.264 63.5288V94.4176C150.264 95.1351 150.013 95.745 149.51 96.2472C149.008 96.7495 148.398 97.0006 147.681 97.0006H138.855C138.138 97.0006 137.528 96.7495 137.026 96.2472C136.523 95.745 136.272 95.1351 136.272 94.4176V64.3899C136.272 61.1611 135.806 58.6139 134.873 56.7484C133.94 54.8111 132.685 53.4478 131.106 52.6586C129.528 51.8693 127.77 51.4747 125.832 51.4747C124.254 51.4747 122.675 51.8693 121.097 52.6586C119.518 53.4478 118.227 54.8111 117.222 56.7484C116.218 58.6139 115.716 61.1611 115.716 64.3899V94.4176C115.716 95.1351 115.464 95.745 114.962 96.2472C114.46 96.7495 113.85 97.0006 113.133 97.0006H104.307C103.518 97.0006 102.872 96.7495 102.37 96.2472C101.939 95.745 101.724 95.1351 101.724 94.4176V64.3899C101.724 61.1611 101.222 58.6139 100.217 56.7484C99.2129 54.8111 97.9214 53.4478 96.3429 52.6586C94.7643 51.8693 93.0782 51.4747 91.2844 51.4747C89.6342 51.4747 88.0198 51.9052 86.4412 52.7662C84.8627 53.5555 83.5712 54.8829 82.5667 56.7484C81.5622 58.6139 81.0599 61.1611 81.0599 64.3899V94.4176C81.0599 95.1351 80.8088 95.745 80.3065 96.2472C79.8043 96.7495 79.1944 97.0006 78.4769 97.0006H69.4363Z" fill="#333366"/>
6
+ <path d="M166.66 97.0006C165.942 97.0006 165.332 96.7495 164.83 96.2472C164.328 95.745 164.077 95.1351 164.077 94.4176V23.169C164.077 22.4515 164.328 21.8416 164.83 21.3393C165.332 20.8371 165.942 20.5859 166.66 20.5859H175.593C176.31 20.5859 176.92 20.8371 177.422 21.3393C177.925 21.8416 178.176 22.4515 178.176 23.169V94.4176C178.176 95.1351 177.925 95.745 177.422 96.2472C176.92 96.7495 176.31 97.0006 175.593 97.0006H166.66Z" fill="#333366"/>
7
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M309 3H193V119H309V3ZM191 1V121H311V1H191Z" fill="#3367CC"/>
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ {
2
+ "rewrites": [
3
+ {
4
+ "source": "**",
5
+ "destination": "/index.html"
6
+ }
7
+ ]
8
+ }
@@ -0,0 +1,31 @@
1
+ <App layout="vertical-full-header">
2
+ <AppHeader>
3
+ <property name="logoTemplate">
4
+ <Link to="/" height="100%">
5
+ <Logo height="$space-8" />
6
+ </Link>
7
+ </property>
8
+ <SpaceFiller />
9
+ <Search
10
+ data="{appGlobals.staticSearchData}"
11
+ placeholder="Search posts..."
12
+ noResultsMessage="No posts match your search."
13
+ pageSize="8"
14
+ enableSpellCorrection="true"
15
+ mode="inline"
16
+ collapsible="true"
17
+ />
18
+ <ToneChangerButton />
19
+ </AppHeader>
20
+ <Pages fallbackPath="/">
21
+ <Page url="/">
22
+ <PostList posts="{appGlobals.posts}" />
23
+ </Page>
24
+ <Page url="/post/:slug">
25
+ <PostPage posts="{appGlobals.posts}" />
26
+ </Page>
27
+ </Pages>
28
+ <Footer>
29
+ Powered by XMLUI
30
+ </Footer>
31
+ </App>
@@ -0,0 +1,19 @@
1
+ <Component name="PostCard">
2
+ <Card>
3
+ <VStack gap="0.75rem">
4
+ <Link to="{'/post/' + $props.post.slug}" noIndicator>
5
+ <H3>{$props.post.title}</H3>
6
+ </Link>
7
+ <Text color="$color-surface-500" fontSize="$fontSize-sm">
8
+ {$props.post.author} · {$props.post.date}
9
+ </Text>
10
+ <Text>{$props.post.description}</Text>
11
+ <HStack gap="0.5rem" when="{$props.post.tags && $props.post.tags.length > 0}">
12
+ <Items data="{$props.post.tags}">
13
+ <PostTag>{$item}</PostTag>
14
+ </Items>
15
+ </HStack>
16
+ <Link to="{'/post/' + $props.post.slug}" label="Read more →" />
17
+ </VStack>
18
+ </Card>
19
+ </Component>
@@ -0,0 +1,7 @@
1
+ <Component name="PostList">
2
+ <VStack maxWidth="720px" marginHorizontal="auto" padding="2rem" gap="2rem">
3
+ <Items data="{$props.posts || []}">
4
+ <PostCard post="{$item}" />
5
+ </Items>
6
+ </VStack>
7
+ </Component>
@@ -0,0 +1,44 @@
1
+ <Component name="PostPage">
2
+ <script>
3
+ var post = ($props.posts || []).find(function(p) { return p.slug === $routeParams.slug; });
4
+ function markdownContent() {
5
+ return post ? appGlobals.prefetchedContent['/post/' + post.slug] : '';
6
+ }
7
+ </script>
8
+
9
+ <VStack when="{!post}" padding="2rem" gap="1rem" horizontalAlignment="center">
10
+ <H2>Post not found</H2>
11
+ <Text>The post you are looking for does not exist.</Text>
12
+ <Link to="/" label="← Back to all posts" />
13
+ </VStack>
14
+
15
+ <VStack when="{!!post}" maxWidth="720px" marginHorizontal="auto" padding="2rem" gap="1.5rem">
16
+ <Link to="/" noIndicator>← All posts</Link>
17
+
18
+ <VStack gap="0.5rem">
19
+ <H1 showAnchor="false">{post && post.title}</H1>
20
+ <Text color="$color-surface-500" fontSize="$fontSize-lg">
21
+ {post && post.description}
22
+ </Text>
23
+ </VStack>
24
+
25
+ <HStack gap="1rem" verticalAlignment="center">
26
+ <Text color="$color-surface-500" fontSize="$fontSize-sm">
27
+ {post && post.author} · {post && post.date}
28
+ </Text>
29
+ </HStack>
30
+
31
+ <HStack gap="0.5rem" when="{post && post.tags && post.tags.length > 0}">
32
+ <Items data="{post ? post.tags : []}">
33
+ <PostTag>{$item}</PostTag>
34
+ </Items>
35
+ </HStack>
36
+
37
+ <ContentSeparator />
38
+
39
+ <Markdown content="{markdownContent()}" showHeadingAnchors />
40
+
41
+ <ContentSeparator />
42
+ <Link to="/" label="← Back to all posts" />
43
+ </VStack>
44
+ </Component>
@@ -0,0 +1,12 @@
1
+ <Component name="PostTag">
2
+ <Text
3
+ backgroundColor="$color-surface-100"
4
+ color="$color-surface-500"
5
+ borderRadius="$space-8"
6
+ paddingHorizontal="$space-3"
7
+ paddingVertical="$space-0_5"
8
+ fontSize="$fontSize-sm"
9
+ >
10
+ <Slot />
11
+ </Text>
12
+ </Component>
@@ -0,0 +1,20 @@
1
+ import type { StandaloneAppDescription } from "xmlui";
2
+ import { allPosts, prefetchedContent, staticSearchData } from "./content";
3
+
4
+ const App: StandaloneAppDescription = {
5
+ name: "My Blog",
6
+ version: "0.1.0",
7
+ defaultTheme: "xmlui-web",
8
+ resources: {
9
+ logo: "/resources/xmlui-logo.svg",
10
+ "logo-dark": "/resources/xmlui-logo-dark.svg",
11
+ favicon: "/resources/favicon.ico",
12
+ },
13
+ appGlobals: {
14
+ posts: allPosts,
15
+ prefetchedContent,
16
+ staticSearchData,
17
+ },
18
+ };
19
+
20
+ export default App;
@@ -0,0 +1,66 @@
1
+ import { buildContentFromRuntime } from "xmlui-docs-blocks";
2
+ import { type SearchItemData, SEARCH_CATEGORIES } from "xmlui";
3
+
4
+ const rawBlogContent: Record<string, { default: string }> = import.meta.glob(
5
+ `/content/blog/*.md`,
6
+ {
7
+ eager: true,
8
+ query: "?raw",
9
+ },
10
+ );
11
+
12
+ const {
13
+ content: blogContent,
14
+ plainTextContent: plainTextBlogContent,
15
+ frontmatter: blogFrontmatter,
16
+ } = buildContentFromRuntime(
17
+ rawBlogContent,
18
+ { contentPrefix: "/content/blog/" },
19
+ { urlPrefix: "/post/" },
20
+ ) as unknown as {
21
+ content: Record<string, string>;
22
+ plainTextContent: Record<string, string>;
23
+ frontmatter: Record<string, Record<string, unknown>>;
24
+ };
25
+
26
+ // Build the post list (excluding drafts) sorted by date descending.
27
+ const allPosts = Object.entries(blogFrontmatter)
28
+ .map(([key, fm]) => ({
29
+ title: fm.title,
30
+ slug: fm.slug ?? key.replace("/post/", ""),
31
+ description: fm.description,
32
+ author: fm.author,
33
+ date: fm.date,
34
+ image: fm.image,
35
+ tags: fm.tags,
36
+ draft: !!fm.draft,
37
+ }))
38
+ .filter((p) => !p.draft)
39
+ .sort((a, b) => Date.parse(String(b.date)) - Date.parse(String(a.date)));
40
+
41
+ // Markdown content keyed by `/post/<slug>` for prefetched lookup from PostPage.
42
+ const prefetchedContent: Record<string, string> = {};
43
+ Object.keys(blogContent).forEach((fileName) => {
44
+ prefetchedContent[`/post/${fileName}`] = blogContent[fileName];
45
+ });
46
+
47
+ const staticSearchData: SearchItemData[] = Object.entries(plainTextBlogContent).map(
48
+ ([key, value]) => {
49
+ const fmKey = key;
50
+ const fm = blogFrontmatter[fmKey] || {};
51
+ const fallbackTitle = key
52
+ .replace("/post/", "")
53
+ .split("-")
54
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
55
+ .join(" ");
56
+ const title = fm.title ? String(fm.title) : fallbackTitle;
57
+ return {
58
+ path: key,
59
+ title,
60
+ content: value,
61
+ category: SEARCH_CATEGORIES[1], // "blog"
62
+ };
63
+ },
64
+ );
65
+
66
+ export { allPosts, prefetchedContent, staticSearchData };
@@ -0,0 +1,16 @@
1
+ {
2
+ "analyze": "warn",
3
+ "rules": {
4
+ "id-unknown-component": "warn",
5
+ "id-unknown-prop": "warn",
6
+ "id-unknown-event": "warn",
7
+ "id-unknown-slot": "warn",
8
+ "expr-unbound-identifier": "warn",
9
+ "expr-unused-var": "info",
10
+ "expr-dead-conditional": "info",
11
+ "expr-handler-no-value": "warn",
12
+ "id-undefined-component-ref": "warn",
13
+ "id-undefined-form-ref": "warn",
14
+ "theming-missing-prefix": "warn"
15
+ }
16
+ }
@@ -0,0 +1,24 @@
1
+ name: XMLUI Check
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ check:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Set up Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version: "20"
18
+ cache: "npm"
19
+
20
+ - name: Install dependencies
21
+ run: npm ci
22
+
23
+ - name: Run xmlui static analyzer
24
+ run: npm run check
@@ -0,0 +1,31 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+
15
+ # Editor directories and files
16
+ .vscode/*
17
+ !.vscode/extensions.json
18
+ .idea
19
+ .DS_Store
20
+ *.suo
21
+ *.ntvs*
22
+ *.njsproj
23
+ *.sln
24
+ *.sw?
25
+ /test-results/
26
+ /playwright-report/
27
+ /playwright/.cache/
28
+
29
+ .env.local
30
+ .env.production
31
+
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/resources/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <script>window.__PUBLIC_PATH = '/'</script>
8
+ <base href="/">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ <script type="module" src="/index.ts"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,9 @@
1
+ import { startApp } from "xmlui";
2
+ export const runtime = import.meta.glob(`/src/**`, { eager: true });
3
+ startApp(runtime);
4
+
5
+ if (import.meta.hot) {
6
+ import.meta.hot.accept((newModule) => {
7
+ startApp(newModule?.runtime);
8
+ });
9
+ }