create-bascik 1.0.0-rc.2 → 1.0.0-rc.3
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.
- package/assets/SKILL.md +136 -18
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/scaffold.d.ts +2 -2
- package/dist/scaffold.js +8 -8
- package/dist/scaffold.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +3 -1
- package/src/index.ts +2 -2
- package/src/scaffold.test.ts +14 -2
- package/src/scaffold.ts +8 -8
package/assets/SKILL.md
CHANGED
|
@@ -286,7 +286,7 @@ Scoped CSS can live in a paired `.css` file or one or more inline `<style>` tags
|
|
|
286
286
|
At build time, Bascik extracts all inline `<style>` blocks, combines them with any companion `.css` file, scopes them, and injects them into the document `<head>`. Using multiple `<style>` tags (or mixing them with a companion `.css` file) is supported but not recommended for readability and maintainability. Choose a single stylesheet pattern per component.
|
|
287
287
|
|
|
288
288
|
### Global Class Passthrough
|
|
289
|
-
Bascik checks whether a class name in a component template is defined in the component's CSS (paired `.css` or inline `<style>`). Only class names defined in the component's stylesheet are scoped (prefixed/hashed). Classes in component HTML that are NOT defined in the component's stylesheet (such as global utility classes like `skip-link`, `flex`, `hidden`, or design system classes) pass through as unscoped global classes so global stylesheets continue to match them.
|
|
289
|
+
Bascik checks whether a class name in a component template is defined in the component's CSS (paired `.css` or inline `<style>`). Only class names defined in the component's stylesheet are scoped (prefixed/hashed). Classes in component HTML that are NOT defined in the component's stylesheet (such as global utility classes like `skip-link`, `flex`, `hidden`, or design system classes) pass through as unscoped global classes so global stylesheets continue to match them. This includes a component with no stylesheet at all, such as a header or footer styled entirely by a global stylesheet: none of its classes are scoped, so it needs no `.css` file or placeholder comment. It also means such a component has no class isolation, so a script querying `.item` in it matches every `.item` on the page; define the class in a stylesheet to scope it.
|
|
290
290
|
|
|
291
291
|
Pair a `.css` file alongside the HTML in a same-named directory:
|
|
292
292
|
|
|
@@ -406,7 +406,7 @@ Define your design tokens once in a global stylesheet, then consume them inside
|
|
|
406
406
|
* `@import`: local file imports (`@import "./file.css"`) are inlined recursively and scoped to the component; remote URLs (`@import "https://..."`) are preserved and hoisted to the top of the compiled stylesheet
|
|
407
407
|
* Standalone attribute selectors (e.g. `[data-state]`): not scoped and can leak globally; anchor with a scoped class: `.card[data-state]`
|
|
408
408
|
* `[id]` selectors: `[id]` and `[id="..."]` attribute selectors in CSS are stripped at compile time because they cannot be scoped without DOM wrapping
|
|
409
|
-
* Compound element selectors:
|
|
409
|
+
* Compound element selectors: every element name in a chain is converted to a scoped class and injected on matching elements in the component's own template, with or without a class anchor (`.card p {}`, `div p {}`, `p + p {}`, `nav a {}`, `ul li * {}` all work); they never reach page markup or a child component's root
|
|
410
410
|
* Element names inside `:is()`, `:where()`, and `:has()` are not converted; use class selectors inside those pseudo-classes instead
|
|
411
411
|
|
|
412
412
|
---
|
|
@@ -737,12 +737,28 @@ If a component template contains multiple root elements, inherited attributes ar
|
|
|
737
737
|
|
|
738
738
|
Inherited class names are not scoped, they are treated as global page-level classes. To disable inheritance, set `scoping.inheritAttributes` to `false` in `bascik.config.ts`.
|
|
739
739
|
|
|
740
|
+
### Styling a Child Component from Its Parent
|
|
741
|
+
A component's CSS applies only to markup written in its own template. A parent's element selector such as `nav a { }` never matches the root element of a child component, so components stay isolated. To style a child's root from the parent, put a class on the child's usage tag and define that class in the parent's CSS. Bascik scopes it to the parent and merges it onto the child root. A class not defined in the parent's CSS passes through unscoped.
|
|
742
|
+
|
|
743
|
+
```html
|
|
744
|
+
<!-- illustrative: site-nav.html (parent) -->
|
|
745
|
+
<nav>
|
|
746
|
+
<nav-link class="item" href="/">Home</nav-link>
|
|
747
|
+
</nav>
|
|
748
|
+
<!-- site-nav.css: .item { padding: 1em 0.5em; } -->
|
|
749
|
+
<!-- nav-link.html (child, root is an anchor): <a><span data-bascik-slot></span></a> -->
|
|
750
|
+
<!-- output: <a class="bascik__site-nav__item" href="/">Home</a> -->
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
The same applies to markup that a build script or slot produces: put the class on each child usage tag.
|
|
754
|
+
|
|
740
755
|
### Internal Masking vs. Preserving Element Contents
|
|
741
756
|
|
|
742
757
|
These two mechanisms serve distinct purposes:
|
|
743
758
|
|
|
744
759
|
* **Internal scanning mask (internal, hardcoded, not configurable):** Bascik temporarily blanks the contents of `<script>`, `<style>`, `<textarea>`, and HTML comments while scanning with regular expressions, so a component tag inside a JavaScript string, style block, or comment is not mistaken for real markup. The mask is discarded immediately after scanning. Authors never interact with or configure this behavior.
|
|
745
|
-
* **Preserve scoping (authoring choice):** Keep scoping enabled by default. Use `scoping.preserve` (default `['code']`) when every matching tag and subtree must keep literal `id`, `name`, and `class` values. Entries are exact tag names or `*` wildcard patterns (for example `vendor-*` preserves every tag whose name starts with `vendor-`); both use the same semantics. Use bare `data-bascik-preserve` for one element and subtree, or list selected attributes such as `data-bascik-preserve="name"`. Nesting only widens. Preserving `name` gives up per-instance radio-group isolation, so reserve it for external form endpoints that require literal field names.
|
|
760
|
+
* **Preserve scoping (authoring choice):** Keep scoping enabled by default. Use `scoping.preserve` (default `['code']`) when every matching tag and subtree must keep literal `id`, `name`, and `class` values. Entries are exact tag names or `*` wildcard patterns (for example `vendor-*` preserves every tag whose name starts with `vendor-`); both use the same semantics. Use bare `data-bascik-preserve` for one element and subtree, or list selected attributes such as `data-bascik-preserve="name"`. Nesting only widens. Preserving `name` gives up per-instance radio-group isolation, so reserve it for external form endpoints that require literal field names. Preserving an `id` also stops reference rewriting inside the preserved region: a link inside a preserved subtree stays literal even if its target is scoped, so a link and its target must be both preserved or both scoped (a scoped link to a preserved target works). Never preserve a skip link to "keep it working"; put the target `id` on the page shell. Preserve does not silence unresolved-tag warnings.
|
|
761
|
+
* **External custom elements (`components.external`):** Hyphenated tags that belong to a browser custom element or library (for example `heading-anchors`) print `Unresolved component tag` on every page and appear in `bascik --check`. List them in `components: { external: ['heading-anchors', 'vendor-*'] }` (exact names or `*` wildcards, case-insensitive) to remove both. It changes diagnostics only: a real component of the same name still expands, scoping is unaffected, and typos stay reported. To use an npm custom element, copy its ready-to-use module into `dist/` with a `phase: 'pre'` exec script (files in `node_modules` are never copied, and bare specifiers in client scripts are not rewritten), load it with `<script type="module" src="/assets/vendor/name.js">`, and declare the tag here. Bundle it with esbuild instead if it imports other packages.
|
|
746
762
|
|
|
747
763
|
### Self-Closing Tags
|
|
748
764
|
Components that do not contain inner slot content should always use self-closing void syntax:
|
|
@@ -812,6 +828,10 @@ Build scripts receive these `process.env` variables:
|
|
|
812
828
|
|
|
813
829
|
These are critical for scripts that generate per-page output. A script using `BASCIK_SOURCE_FILE`, `BASCIK_PAGE_FILE`, or `BASCIK_PAGE_PATH` gets a separate cache entry per page automatically.
|
|
814
830
|
|
|
831
|
+
`BASCIK_ROUTE` may be any size: over 32 KB it is delivered through a temporary file and set before the script runs, so reading `process.env.BASCIK_ROUTE` is unchanged.
|
|
832
|
+
|
|
833
|
+
**Printed directives never run.** Build script output is transpiled again (component tags expand, client scripts run in the browser), but any `data-bascik-build`, `data-bascik-server`, `data-bascik-stream`, or `data-bascik-routes` script in the output is removed with a warning. Write directives only in source files. This is not a sanitizer: HTML from a CMS or API must still go through an allowlist before printing, because its ordinary scripts, handlers, and component tags are kept.
|
|
834
|
+
|
|
815
835
|
### The Fetch-Once Pattern
|
|
816
836
|
|
|
817
837
|
When a data-driven page needs the same data in several places, read or fetch it **once at page level** in a single `data-bascik-build` script, then apply it everywhere on the page. Not once per component instance. The same data object can feed a second script, a JSON payload for client JavaScript, or a component prop, without a second network round trip or file read.
|
|
@@ -901,14 +921,14 @@ Markdown stays comfortable for authors, while the published page stays **vanilla
|
|
|
901
921
|
|
|
902
922
|
The parser emits ordinary HTML, so it can be styled by a global stylesheet or wrapped in a Bascik component. For reusable scoped styles, have the script emit `<markdown-content>${marked(md)}</markdown-content>` and give that component a default slot.
|
|
903
923
|
|
|
904
|
-
Use wrapper
|
|
924
|
+
Use the wrapper class plus `:is()` around element names for generated slot content:
|
|
905
925
|
|
|
906
926
|
```css
|
|
907
|
-
.markdown-content h2 { margin-block: 2.5rem 0.75rem; }
|
|
908
|
-
.markdown-content blockquote { border-left: 4px solid currentColor; }
|
|
927
|
+
.markdown-content :is(h2) { margin-block: 2.5rem 0.75rem; }
|
|
928
|
+
.markdown-content :is(blockquote) { border-left: 4px solid currentColor; }
|
|
909
929
|
```
|
|
910
930
|
|
|
911
|
-
Do not
|
|
931
|
+
Do not write `h2 {}` or `.markdown-content h2 {}` for Markdown passed through a slot. Bascik scopes an element name by adding a class to the matching elements in the component's own template, also after a wrapper class, so slotted headings (plain tags) never match. Names inside `:is()` are left as written; the wrapper class stays scoped and specificity is unchanged.
|
|
912
932
|
|
|
913
933
|
### Page-Aware Scripts
|
|
914
934
|
|
|
@@ -1157,6 +1177,9 @@ export default defineConfig({
|
|
|
1157
1177
|
out: 'dist',
|
|
1158
1178
|
api: 'src/api',
|
|
1159
1179
|
},
|
|
1180
|
+
components: {
|
|
1181
|
+
external: [],
|
|
1182
|
+
},
|
|
1160
1183
|
scoping: {
|
|
1161
1184
|
scriptBlocks: true,
|
|
1162
1185
|
inheritAttributes: true,
|
|
@@ -1189,6 +1212,7 @@ export default defineConfig({
|
|
|
1189
1212
|
watchPaths: [],
|
|
1190
1213
|
exec: [],
|
|
1191
1214
|
workers: false,
|
|
1215
|
+
onExecError: 'warn', // 'warn' | 'error'. Default: 'warn' in dev, 'error' for --build
|
|
1192
1216
|
},
|
|
1193
1217
|
scripts: {
|
|
1194
1218
|
cache: { enabled: true },
|
|
@@ -1246,6 +1270,7 @@ When creating or modifying `bascik.config.ts`:
|
|
|
1246
1270
|
* **Do NOT invent non-existent `pipeline.exec` scripts:** `pipeline.exec` is only for executing existing custom lifecycle script files. If no custom script file exists in the workspace, omit it.
|
|
1247
1271
|
* **Array Replacement in `build`:** Array properties like `pipeline.exec`, `pipeline.watchPaths`, and `assets.inlineStyles` are replaced as atomic values (not concatenated) when specified in `export const build`. When defining `build.pipeline.exec`, include all scripts that should run in production builds.
|
|
1248
1272
|
* **Write artifacts to `dist/`:** Lifecycle scripts must write generated artifacts only to the output directory, never source files or watched paths. Never configure `pipeline.watchPaths` or `pipeline.exec[].watch` for generated outputs. There is no `outputs` option. Exec receives `BASCIK_BUILD`, `BASCIK_PAGES_DIR`, `BASCIK_OUT_DIR`, `BASCIK_BASE`, and `BASCIK_SITE_URL`. Use `pre` for required generated dependencies, not `parallel`.
|
|
1273
|
+
* **Exec failures (`pipeline.onExecError`):** `'warn'` reports a failing script (terminal and browser overlay) and keeps going; `'error'` stops and exits 1. Applies to pre, parallel, and post, at startup and on edits. Default is `'warn'` for the dev server (a typo must not end the session) and `'error'` for `--build` (a failed script must never produce a build that looks successful). Set it explicitly to flip either mode. Page compile errors are unaffected.
|
|
1249
1274
|
* **Source-owned exec phases:** `pipeline.exec[].watch` selects matching scripts after a source edit. One cycle coalesces overlap with pages, components, and `pipeline.watchPaths`: pre finishes before compilation, parallel starts alongside it, post starts after compilation and disk writes. Known source dependents rebuild once; unknown external dependencies conservatively rebuild all pages without rerunning unmatched scripts. Exec-only inputs need no duplicate `pipeline.watchPaths`. Completion never queues another compile or reload. Edits during work are retained; failed paths retry on the next source edit. Pre/compile/post failures discard success reloads. Dev parallel stays nonblocking and reports every failure; build joins parallel and compilation/post before success. Never suppress watched script edits as presumed self-writes. Bascik cannot safely identify source-writing loops. `scripts.importRoot` and `assets.inlineStyles` do not add compilation watches.
|
|
1250
1275
|
* **Stick to recommended defaults without restating them:** Preserve `scoping.deduplicateCss: true`, `scoping.scriptBlocks: true`, and `scoping.inheritAttributes: true` unless specifically instructed otherwise or integrating global utility frameworks like Tailwind CSS. Do not write these values into a config just to preserve them.
|
|
1251
1276
|
* **Set `BASCIK_SITE_URL` for production features:** Provide the site URL via the environment (e.g. `BASCIK_SITE_URL=https://example.com bascik --build`) when page-aware canonical scripts, sitemaps, or `robots.txt` generation are enabled. Never put `siteUrl` in `bascik.config.ts`.
|
|
@@ -1457,7 +1482,7 @@ While the dev server is active, Bascik watches your file system and incrementall
|
|
|
1457
1482
|
#### 3. Transpilation & Build Errors
|
|
1458
1483
|
Development and production builds handle page failures differently. The dev server logs a failed page, completes boot, continues serving healthy pages, and retries the failed page on the next save. A production `bascik --build` waits for every page job, reports all failures together, and exits nonzero rather than reporting success with missing output.
|
|
1459
1484
|
|
|
1460
|
-
Hard build failures include a missing or unreadable configured pages directory, a page without a non-empty `<body>`, runaway component expansion, output directory creation failure, and page write failure. `ENOENT` write errors are not ignored.
|
|
1485
|
+
Hard build failures include a missing or unreadable configured pages directory, a missing or unreadable components root listed in `directory.components`, a page without a non-empty `<body>`, runaway component expansion, output directory creation failure, and page write failure. `ENOENT` write errors are not ignored. A missing default `src/components/` is not an error: the project has no components until the directory is created.
|
|
1461
1486
|
|
|
1462
1487
|
```terminal
|
|
1463
1488
|
Build failed with 2 page errors:
|
|
@@ -1482,7 +1507,7 @@ Build failed with 2 page errors:
|
|
|
1482
1507
|
```terminal
|
|
1483
1508
|
[bascik] Unresolved component tag in "pages/about.html": <my-mistyped> - no matching component file found. Run `bascik --check` for a full report.
|
|
1484
1509
|
```
|
|
1485
|
-
Use `bascik --check` (or `bascik --check --strict`) as the CI gate for project references and diagnostics.
|
|
1510
|
+
Use `bascik --check` (or `bascik --check --strict`) as the CI gate for project references and diagnostics. Tags that belong to a custom element or library can be declared in `components.external` so neither the warning nor `--check` reports them.
|
|
1486
1511
|
|
|
1487
1512
|
#### 4. Static Analysis (`bascik --check`)
|
|
1488
1513
|
Run `bascik --check` from your project root to validate pages, component files, config, and API route files without starting the dev server or writing any output:
|
|
@@ -1827,7 +1852,7 @@ async function walk(dir: string, ext: string): Promise<string[]> {
|
|
|
1827
1852
|
return out;
|
|
1828
1853
|
}
|
|
1829
1854
|
|
|
1830
|
-
describe('dist HTML
|
|
1855
|
+
describe('dist HTML: WHATWG spec compliance', () => {
|
|
1831
1856
|
it('every page is free of parse errors', async () => {
|
|
1832
1857
|
const files = await walk(DIST_DIR, '.html');
|
|
1833
1858
|
const failures: string[] = [];
|
|
@@ -1844,7 +1869,7 @@ describe('dist HTML — WHATWG spec compliance', () => {
|
|
|
1844
1869
|
});
|
|
1845
1870
|
```
|
|
1846
1871
|
|
|
1847
|
-
Run after `bascik --build`. Catches corrupted script bodies, mismatched tags, and unreplaced internal tokens that string-based assertions miss. Bascik is a build tool
|
|
1872
|
+
Run after `bascik --build`. Catches corrupted script bodies, mismatched tags, and unreplaced internal tokens that string-based assertions miss. Bascik is a build tool, so hold output to the full spec, not browser recovery behavior.
|
|
1848
1873
|
|
|
1849
1874
|
### Testing Site Logic in a Bascik Project
|
|
1850
1875
|
|
|
@@ -1949,8 +1974,66 @@ Detailed per-framework migration guides live at `/switch/*`. Key patterns that a
|
|
|
1949
1974
|
- **Slots:** `<slot />` / `children` → `data-bascik-slot` (no value) for default, `data-bascik-slot="name"` for named slots.
|
|
1950
1975
|
- **Props:** `defineProps` / component props → `data-bascik-prop-*` attributes (text only).
|
|
1951
1976
|
- **Reactive state:** `ref`, `useState`, etc. → plain `<script>` with vanilla JS. Bascik scopes `id` values so multiple instances stay independent.
|
|
1952
|
-
- **Routing:** Client-side router → one `.html` file per URL in `src/pages/`.
|
|
1977
|
+
- **Routing:** Client-side router → one `.html` file per URL in `src/pages/`. For parameterized routes (`[slug].astro`, `getStaticPaths`, Eleventy pagination), use a dynamic route template such as `src/pages/blog/[slug]/index.html` (trailing-slash URLs) with a `<script data-bascik-routes>` block. Do not generate page files into `src/pages/`. A route param cannot contain `/`; use one template per depth.
|
|
1953
1978
|
- **Build-time data:** `onMounted` / `getStaticProps` / frontmatter → `<script data-bascik-build>` (Node.js ESM, stdout injected).
|
|
1979
|
+
- **Content collections (Astro `getCollection`, Eleventy `collections`):** No built-in equivalent. Write a `src/lib/posts.ts` helper that reads `content/` with `fs`, parses front matter with `gray-matter`, validates with `zod`, and sorts by the parsed date (not the file name). Escape every interpolated value. Drafts: skip them when `process.env.BASCIK_BUILD === '1'`. Exclude scripts that read `content/` from `scripts.cache` and add `content/` to `pipeline.watchPaths`.
|
|
1980
|
+
- **Template logic (Nunjucks/Liquid loops, filters, includes with variables):** Becomes TypeScript helpers in `src/lib/` that return HTML. Only static includes become components. Pages keep `<html>`/`<head>`/`<body>`; a component cannot own them.
|
|
1981
|
+
- **Feeds, sitemaps, images:** RSS/Atom is a `pipeline.exec` script (`phase: 'post'`) writing to `BASCIK_OUT_DIR`. Sitemap and robots are built in. No image optimization or syntax highlighting built in; do it in your own build step.
|
|
1982
|
+
- **Component scripts that print styled markup:** Output of a component build script, page-aware or not, is scoped like the template, including markup returned by imported helpers. Classes the component stylesheet does not define stay global.
|
|
1983
|
+
|
|
1984
|
+
### From React
|
|
1985
|
+
|
|
1986
|
+
Full guide: `/switch/from-react`. Key React-specific mappings:
|
|
1987
|
+
|
|
1988
|
+
| React | Bascik |
|
|
1989
|
+
|-------|--------|
|
|
1990
|
+
| Function component | `.html` file in `src/components/<name>/`, folder name is the hyphenated tag |
|
|
1991
|
+
| `children` | `data-bascik-slot` (no value), fallback inside it |
|
|
1992
|
+
| Render prop / named children | `<div data-bascik-slot="x">` wrapper at the usage site and in the component |
|
|
1993
|
+
| `props.x` | `data-bascik-prop-x` (text only; booleans and numbers arrive as strings) |
|
|
1994
|
+
| Prop used as an attribute | `data-bascik-attr-<attribute>="propName"` |
|
|
1995
|
+
| Object, array, or function prop | Not possible. Print one component per item from a build script; use a bubbling `CustomEvent` instead of a callback |
|
|
1996
|
+
| `useState` in the common parent | Variables in the parent component's `<script>`; a function applies them to the DOM |
|
|
1997
|
+
| `onChange` callback prop | Child dispatches `new CustomEvent('x', { bubbles: true, detail })` from its own element; the parent listens on its root |
|
|
1998
|
+
| Re-render of a filtered list | One function sets `hidden` on existing rows; there is no diff, so write every place a value shows |
|
|
1999
|
+
| `.map()` over data | `<script data-bascik-build>` that prints component tags with escaped props |
|
|
2000
|
+
| Conditional style | A `data-` attribute and a CSS selector, in the component's own CSS |
|
|
2001
|
+
| React Router `/blog/:slug` | `src/pages/blog/[slug]/index.html` with `<script data-bascik-routes>` |
|
|
2002
|
+
|
|
2003
|
+
React-specific gotchas:
|
|
2004
|
+
|
|
2005
|
+
- **Escape every interpolated value in a build script.** JSX does it for you; a template string does not.
|
|
2006
|
+
- **Forwarding `children` to an inner component:** write a default slot marker between the inner component's tags, `<inner-box><div data-bascik-slot>fallback</div></inner-box>`. It receives the outer usage's default content. Named wrappers between the inner tags fill the inner component's named slots.
|
|
2007
|
+
- **Plain inputs can disagree with state after Back or reload.** Report the fields again on `pageshow`. A form with one text box submits on Enter; call `preventDefault()` in a `submit` listener when a script drives the form.
|
|
2008
|
+
- **Component scripts run once and are moved in production.** Minified production HTML moves them to the end of the document; the dev server leaves them in place. Look up elements inside handlers or after `DOMContentLoaded`.
|
|
2009
|
+
- **`bascik --check` cannot see a component that only a build script prints** and reports it as unused.
|
|
2010
|
+
- **Tag names need a hyphen.** `Card.jsx` becomes `info-card`.
|
|
2011
|
+
|
|
2012
|
+
### From Next.js
|
|
2013
|
+
|
|
2014
|
+
Full guide: `/switch/from-next`. Key Next.js-specific mappings:
|
|
2015
|
+
|
|
2016
|
+
| Next.js | Bascik |
|
|
2017
|
+
|---------|--------|
|
|
2018
|
+
| `app/page.tsx`, `app/posts/[slug]/page.tsx` | `src/pages/index.html`, `src/pages/posts/[slug].html` (`/posts/<slug>`, also served with a trailing slash) |
|
|
2019
|
+
| `generateStaticParams` | `<script data-bascik-routes>` printing `[{ "params": { "slug": "..." } }]` |
|
|
2020
|
+
| `generateMetadata` / `metadata` export | A build script in `<head>` that prints `<title>` and `<meta>` from a `src/lib` helper; absolute URLs from `BASCIK_SITE_URL` |
|
|
2021
|
+
| `app/layout.tsx` | Pages keep `<html>`/`<head>`/`<body>`; a head component plus header/footer components |
|
|
2022
|
+
| Server component that maps data to JSX | A `src/lib` helper returning escaped HTML strings, printed by a build script |
|
|
2023
|
+
| `"use client"` component with `useState`/`useEffect` | A component with a plain `<script>`; persistent state lives in the DOM or `localStorage` |
|
|
2024
|
+
| `next/link`, `next/image`, `next/font` | `<a>`, `<img>` with `width`/`height`, a self-hosted `@font-face` plus `<link rel="preload">` |
|
|
2025
|
+
| CSS Modules (`styles.x`) | Paired component `.css`; a class written in the template is scoped |
|
|
2026
|
+
| Tailwind via PostCSS | A `pipeline.exec` `pre` script running PostCSS + Tailwind into `BASCIK_OUT_DIR`; Tailwind `content` lists `src/**/*.html` and `src/lib/**/*.ts` |
|
|
2027
|
+
| `app/api/x/route.ts` | `src/api/x.ts` exporting `GET`/`POST`; `context.params` is a plain object, not a promise; `bascik --server` only |
|
|
2028
|
+
|
|
2029
|
+
Next.js-specific gotchas:
|
|
2030
|
+
|
|
2031
|
+
- **`@/` in a helper that imports a helper fails.** tsconfig `paths` do not apply; Node runs `src/lib/*.ts` directly. Inside helpers use relative paths with the `.ts` extension, and `import type` for type-only imports.
|
|
2032
|
+
- **Tailwind `@apply` in component CSS is not processed.** Write the CSS out, or keep `@apply` in the global Tailwind input file.
|
|
2033
|
+
- **Tailwind's `dark` class works unscoped** when it is toggled on `<html>` and the component's own CSS does not define it.
|
|
2034
|
+
- **A pre-paint script (theme, FOUC) goes in `<head>`.** Production HTML minification moves body scripts to the end of the body; head scripts stay put.
|
|
2035
|
+
- **Style slotted Markdown with `.wrapper :is(h2)`**, not `.wrapper h2` (see Markdown above).
|
|
2036
|
+
- **Unknown slugs return 404.** The upstream example answers 500 for them, because `getPostBySlug` throws before `notFound()`.
|
|
1954
2037
|
|
|
1955
2038
|
### From Svelte
|
|
1956
2039
|
|
|
@@ -1977,12 +2060,47 @@ Full guide: `/switch/from-vue`. Key Vue-specific mappings:
|
|
|
1977
2060
|
|-----|--------|
|
|
1978
2061
|
| `<template>` + `<style scoped>` | `.html` + `.css` paired files |
|
|
1979
2062
|
| `<slot />` | `data-bascik-slot` (no value) |
|
|
1980
|
-
| `<slot name="x" />` |
|
|
1981
|
-
| `defineProps` | `data-bascik-prop-*` attributes |
|
|
1982
|
-
|
|
|
1983
|
-
|
|
|
1984
|
-
| `
|
|
1985
|
-
| `
|
|
2063
|
+
| `<slot name="x" />` / `<template #x>` | `<div data-bascik-slot="x">` wrapper around the content, in the component and at the usage site |
|
|
2064
|
+
| `defineProps` | `data-bascik-prop-*` attributes (text only) |
|
|
2065
|
+
| Array or object prop (`:data="rows"`) | JSON in a `<script type="application/json">` that fills the default slot; a build script prints it from a `src/lib` helper, and `<` is escaped as `\u003c` |
|
|
2066
|
+
| `$emit`, `v-model` | DOM events: `dispatchEvent(new CustomEvent(...))` and `addEventListener` |
|
|
2067
|
+
| `ref` / `reactive` | Vanilla JS `<script>`; the script updates the DOM itself |
|
|
2068
|
+
| `v-if` / `v-show` | Build-time: a build script prints one branch. Runtime: toggle the `hidden` attribute |
|
|
2069
|
+
| `v-for` | Build-time loop in a build script, or clone a `<template>` from a script |
|
|
2070
|
+
| `vue-router` | One `.html` per route in `src/pages/`; parameterized routes use `src/pages/blog/[slug].html` with `<script data-bascik-routes>` |
|
|
2071
|
+
| `onMounted` data fetch | `<script data-bascik-build>` for data that is the same for everyone, `fetch()` in a component script otherwise |
|
|
2072
|
+
|
|
2073
|
+
Vue-specific gotchas:
|
|
2074
|
+
|
|
2075
|
+
- **Named-slot wrappers are removed.** `<h1 data-bascik-slot="header">Title</h1>` at the usage site produces `Title` with no `<h1>` (an `<a>` loses its `href` too). Write `<div data-bascik-slot="header"><h1>Title</h1></div>`.
|
|
2076
|
+
- **Component tag names need a hyphen.** `Card.vue` becomes `info-card`; a tag named `card` warns.
|
|
2077
|
+
- **Script-created elements get no element-selector styles.** CSS such as `td { }` applies to template markup. Put the markup in a `<template>` inside the component and clone it, instead of `document.createElement('td')`.
|
|
2078
|
+
- **Script placement differs between modes.** Production HTML minification moves component scripts to the end of the document; the development server and `minify.html: false` leave them in place. Never rely on a later element existing when the script starts: look it up inside an event handler or after `DOMContentLoaded`. Use `pageshow` to resync a form value the browser restored on Back.
|
|
2079
|
+
- **`bascik --check` cannot see a component that only a build script prints** and reports it as unused.
|
|
2080
|
+
|
|
2081
|
+
### From WordPress
|
|
2082
|
+
|
|
2083
|
+
Full guide: `/switch/from-wordpress`. Key WordPress-specific mappings:
|
|
2084
|
+
|
|
2085
|
+
| WordPress | Bascik |
|
|
2086
|
+
|-----------|--------|
|
|
2087
|
+
| The Loop, `WP_Query` | A `src/lib` helper returning escaped HTML, printed by a build script |
|
|
2088
|
+
| `single.php` at `/%year%/%monthnum%/%day%/%postname%/` | `src/pages/[year]/[month]/[day]/[slug]/index.html` (one bracket per segment; a param cannot contain `/`) |
|
|
2089
|
+
| Pages and child pages | `src/pages/[pageslug]/index.html` and `src/pages/[parent]/[child]/index.html` |
|
|
2090
|
+
| Category, tag, and `/page/2/` archives | `category/[term]/`, `tag/[term]/`, `page/[page]/` templates, each paged archive its own template |
|
|
2091
|
+
| REST API (`/wp-json/wp/v2/`) | One `pre` exec script fetches everything (follow `X-WP-TotalPages`; `per_page` above 100 is a 400), sanitizes it, downloads media into `BASCIK_OUT_DIR`, and writes a JSON snapshot pages read |
|
|
2092
|
+
| Tools > Export (WXR) | `wordpress-export-to-markdown`, then restore page parents, menu order, term names, and image alt text by hand |
|
|
2093
|
+
| `wp-content/uploads/` | Same path under `dist/`, so content URLs keep working |
|
|
2094
|
+
| `/feed/` | A `post` exec script writing `/feed.xml`; redirect `/feed/` on the host |
|
|
2095
|
+
|
|
2096
|
+
WordPress-specific gotchas:
|
|
2097
|
+
|
|
2098
|
+
- **Sanitize every post body before printing it.** `content.rendered` can hold `<script>`, `on*` handlers, and `javascript:` links; administrators may save any markup. Use an allowlist such as `sanitize-html`, which also drops custom elements so content cannot place a component tag. Bascik itself only removes printed directive scripts.
|
|
2099
|
+
- **Exclude pages that read fetched data from the script cache** (`scripts.cache.exclude`). Network responses are not part of the cache key, so a rebuild after an edit in WordPress otherwise reuses old output.
|
|
2100
|
+
- **Keep page helpers light.** Every build script is its own Node process; import `zod` and `sanitize-html` in the sync step, not in helpers every page loads.
|
|
2101
|
+
- **Raise the exec `timeout` for media downloads.** The default is 60 seconds.
|
|
2102
|
+
- **Titles are HTML over REST** (`&`, curly quotes); convert to text, then escape. WXR titles are the raw text.
|
|
2103
|
+
- **No comments, search, or date and author archives** in a static build; use services or add templates.
|
|
1986
2104
|
|
|
1987
2105
|
### Migrating Existing Sitemap & Robots Files
|
|
1988
2106
|
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,eAAe,CAAC,IAAc;IAC5C,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QACtD,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QACpC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;KAC7C,CAAC;AACJ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { join } from "node:path";
|
|
|
5
5
|
import { parseCliOptions } from "./cli.js";
|
|
6
6
|
import { scaffold, validateProjectName } from "./scaffold.js";
|
|
7
7
|
const args = process.argv.slice(2);
|
|
8
|
-
const { yesFlag, noDevFlag } = parseCliOptions(args);
|
|
8
|
+
const { yesFlag, noDevFlag, noInstallFlag } = parseCliOptions(args);
|
|
9
9
|
const nameArg = args.find((a) => !a.startsWith("-"));
|
|
10
10
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
11
11
|
let projectName;
|
|
@@ -28,7 +28,7 @@ console.log(`✓ Scaffolded ${projectName}/\n`);
|
|
|
28
28
|
let shouldInstall;
|
|
29
29
|
let shouldDev;
|
|
30
30
|
if (yesFlag) {
|
|
31
|
-
shouldInstall =
|
|
31
|
+
shouldInstall = !noInstallFlag;
|
|
32
32
|
shouldDev = !noDevFlag;
|
|
33
33
|
}
|
|
34
34
|
else {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/scaffold.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare const FAVICON_SVG = "<svg viewBox=\"0 0 32 32\" width=\"32\" heig
|
|
|
16
16
|
export declare const FAVICON_ICO_B64 = "AAABAAMAEBAAAAEAIADIAAAANgAAACAgAAABACAACAEAAP4AAAAwMAAAAQAgAGcBAAAGAgAiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeklEQVQ4jWNgoDa4/L93/uX/vf8J4577OAzouU+cAb3zMTSf/9+vQKTm/xf/9yRgGHDxf08CsqINV8vBGJsBIMsI+r+g3Q+MyfZ/AU4DiPR/AQ4DiPL/ZTwGEOX/yzgNICH+C7C7gPj434AlGon2/2UcmGj/0y/9UwoAAEX+8tkvEHwAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAAJcEhZcwAACxMAAAsTAQCanBgAAAC6SURBVFiF7ZbRDYMwDEQzwcEIDFC6QJXf0jEYKBEjMBJCGYBRXNEFepZshaqx5O+8+HQ+h9DqS22yDEWy2HY6Alu7pNkeIK80QJG8WgOcn1IApMMa4JSVenxr+svF9X88bxKnsZ7+6PpPV/M/1ADG/ocSwNz/UAKY+x8qAIf9D90E7Pc/FAAu+x8KAJf9DxrAKf/BT8An/0ECuOU/SAC3/I/TKPF1r6N/4bvdf4OL/oXqpn/6kfv/r+sNLlrC+A4T1ksAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAMAAAADAIBgAAAFcC+YcAAAAJcEhZcwAACxMAAAsTAQCanBgAAAEZSURBVGiB7ZjBDcJADARTAVBCKKKGSwfpgo+PlHDfQDOWSQGpBIwuD/7EVpYIr2Qpr+hGXln2Nk0otL0mzWXSrJii2QGAZhxALqbHsw4t8PEqSskEUH+ABGAdWhNA+F/D/+sV/teY/9vNf3mS0piWerxof/OfxqSH42mpfOv2N//7y/kDUL935//eFSBvv/94Aghi//EEYMT+4wdAmP3fsQMFsv97AQhq//cCYNT+7wNAuPvXqQMFdv96AAjy/vUAYOT9awcgAANi40iAAAn3/00EAB2U7f56m/2eQf30E14yR/0AAAABJRU5ErkJggg==";
|
|
17
17
|
export declare const FAVICON_32_PNG_B64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAuklEQVRYhe2W0Q2DMAxEM8HBCAxQukCV39IxGCgRIzASQhmAUVzRBXqWbIWqseTvvPh0PofQ6kttsgxFsth2OgJbu6TZHiCvNECRvFoDnJ9SAKTDGuCUlXp8a/rLxfV/PG8Sp7Ge/uj6T1fzP9QAxv6HEsDc/1ACmPsfKgCH/Q/dBOz3PxQALvsfCgCX/Q8awCn/wU/AJ/9BArjlP0gAt/yP0yjxda+jf+G73X+Di/6F6qZ/+pH7/6/rDS5awvgOE9ZLAAAAAElFTkSuQmCC";
|
|
18
18
|
export declare const APPLE_TOUCH_ICON_PNG_B64 = "iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGKUlEQVR4nO2bzWqdVRSGN72AtqO0WicWJ1KtoTi0dGjTK8gFGGtnH1ghJpXOw1l0kHoTUvlIU6rQa9Dg2R9W8OcK2guwky0nkIGU0kTfsvZZ63nhnWWwz7ufnTwcSCmEEEIIIYQQQgghhBBCCCGEEEII6SG12Xptsyd0Fm2DrZIxtdlYmzVq0TYYSra0dvfUvM2edTA+bdoNpnZvtWTL4kMDU7zHNG+z54tfViVbFn+WvMen9iY2GEvG4M9hH9RQsgV/jtsJf/a/BGqSDfBnYGrBNsCfO7gE2mQb4M8AZWE2wJ87uARqkg3wZ2CK9pjGkjF8/xy2Q8kWvn+O24nvn/0vgZpkA/wZmKI9prFkDP4ctkPJFvw5bif82f8SqEk2wJ+BKdpjGkvG4M9hO5RswZ/jdsKf/S+BmmQD/BmYoj2msWQM/hy2Q8kW/DluJ/zZ/xKoSTbAn4Ep2mMaS8bgz2E7lGzBn+N2wp/9L4GaZAP8GZiiPaaxZAz+HLZDyRb8OW4n/Nn/EqhJNsCfgSnaYxpLxuDPYTuUbMGf43bCn5evj3/farsPNw77+I9t9/PUToo/L1n3ft1sn3z6YTt95uy/evX65bb3dNP9fNW/+POy9Lufvmzn3l55Ceajnr+w0h4c3HY/Z/Ut/rwM/fnvnfb+6ruvhPmol65cbAcvdtzPW52KPy9Jd/c+ey3MR72/v+F+3upQ/HmJenN77dhAf3Fnzf281af487J0/da1YwO9+Fnv81af4s8dXAJAN81G+HMHoAK0SfbBnzuAFKBNuRH+7A0pQJtyI/zZG1KANtk++HMHkAK0SbbBnzsAFKBNuQ/+7A0oQJtyH/zZG1CANtk2+HMHgAK0SXbBnzuAE6BNuQ3+7A0nQJtyG/zZG04ANtku+HMHcAK0STbBnzsAE6BNuQv+7A0mQJtyF/zZG0yANtkm+HMHYAK0SfbAnzuAEqBNuQn+7A0lQJtyE/zZG0qANtke+HMHUAK0SbbAnzsAEgBNuQf+7A0kQJtyD/zZG0iANtkW+HMHQAK0SXbAnzuAEaBNuQX+7A0jQJtyC/zZG0aANtkO+HMHMAK0STbAnzsAEQBNuQP+7A0iQJtyB/zZG0SANtkG+HMHIAK0ZgP8uQMIAdqUG+DP3hACtCk3wJ+9IQRok22AP3cAIUCbZAP8uQMAAdqUG+DP3gACtCk3wJ+9AQRok22AP3cAIECbZAP8uQP4ANqUG+DP3vABtCk3wJ+94QNok22AP3cAH0CbZAP8uQPwANqUG+DP3uABtCk3wJ+9wQNok22AP3cAHkCbZAP8uQPoANqUG+DP3tABtCk3wJ+9oQNok22AP3cAHUCbZAP8uQPgANqUG+DP3sABtCk3wJ+9gQNok22AP3cAHECbZAP8uQPYANqUG+DP3rABtCk3wJ+9YQNok22AP3cAG0CbZAP8uQPQANqUG+DP3qABtCk3wJ+9QQNok22AP3cAGkCbZAP8uQPIANqUG+DPmXpze62dPnP2WL31zQ3389aTF3/O1N2HG8cG+ttHn7uft56w+HOyHrzYaZeuXHwtzB98/N7hz3qft56g+HPSPji43c5fWHklzG+9c659/8tX7uesJy/+nLV7Tzfb1euXX4L52o2P2v5vX7ufr/634s/Z+8Of2+3+/sZhf/zrjvt56v8o/tzBJVCTbIA/A1O0xzSWjFl88A7Gp02+Af4MWHEe1tTurZZsWXxo7+GpyTfAnwEr2sMaS8bgz2E7lGxp7e6peZs962B82rQb4M9AFeZRzdvs+eKXVcmWxZ8l7/GpvYnW/d2iwC0CBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIEC";
|
|
19
|
-
/** Head component
|
|
19
|
+
/** Head component: charset, viewport, favicon, CSS link. */
|
|
20
20
|
export declare const SITE_META_HTML = "<meta charset=\"UTF-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<meta name=\"description\" content=\"A fast, modern website built with Bascik.\" />\n<link rel=\"icon\" href=\"/favicon.ico\" sizes=\"any\" />\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/assets/favicon-32x32.png\" />\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"/assets/favicon.svg\" />\n<link rel=\"apple-touch-icon\" href=\"/assets/apple-touch-icon.png\" />\n<link rel=\"stylesheet\" href=\"/css/styles.css\" />\n";
|
|
21
21
|
export declare const SITE_HEADER_CSS = ".header {\n position: sticky;\n top: 0;\n z-index: 100;\n background: rgba(24, 25, 27, 0.9);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border-bottom: 1px solid var(--border);\n}\n\n.container { max-width: 1140px; margin: 0 auto; padding: 0 28px; }\n\n.nav {\n display: flex;\n align-items: center;\n height: 60px;\n gap: 24px;\n}\n\n.logo {\n font-weight: 700;\n font-size: 1rem;\n color: var(--text);\n letter-spacing: -0.01em;\n flex-shrink: 0;\n}\n.logo:hover { opacity: 0.8; }\n\n.nav-menu {\n list-style: none;\n margin: 0 0 0 auto;\n padding: 0;\n display: flex;\n gap: 4px;\n}\n.nav-menu a {\n display: block;\n padding: 6px 12px;\n font-size: 0.9rem;\n color: var(--text-muted);\n border-radius: var(--r-sm);\n transition: color .15s, background .15s;\n}\n.nav-menu a:hover { color: var(--text); background: var(--elevated); opacity: 1; }\n\n.nav-toggle {\n display: none;\n flex-direction: column;\n justify-content: center;\n gap: 5px;\n width: 36px;\n height: 36px;\n background: none;\n border: none;\n cursor: pointer;\n padding: 6px;\n margin-left: auto;\n border-radius: var(--r-sm);\n}\n.nav-toggle span {\n display: block;\n height: 2px;\n background: var(--text);\n border-radius: 2px;\n}\n\n@media (max-width: 640px) {\n .nav-toggle { display: flex; }\n\n .nav-menu {\n display: none;\n position: absolute;\n top: 60px;\n left: 0;\n right: 0;\n flex-direction: column;\n gap: 0;\n background: var(--surface);\n border-bottom: 1px solid var(--border);\n padding: 8px 16px;\n }\n .nav-menu.is-open { display: flex; }\n .nav-menu li { width: 100%; }\n .nav-menu a { padding: 10px 4px; }\n}\n";
|
|
22
22
|
/** Sticky top nav with logo (brand prop) and mobile hamburger. */
|
|
@@ -31,7 +31,7 @@ export declare const FEAT_CARD_CSS = ".fcard {\n background: var(--elevated);\n
|
|
|
31
31
|
*/
|
|
32
32
|
export declare const FEAT_CARD_HTML = "<style>\n.fcard {\n background: var(--elevated);\n border: 1px solid var(--border);\n border-radius: var(--r);\n padding: 24px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n transition: border-color .2s, box-shadow .2s, transform .2s;\n}\n.fcard:hover {\n border-color: var(--border-hover);\n box-shadow: 0 0 0 1px var(--accent-dim), 0 8px 32px rgba(0,0,0,0.3);\n transform: translateY(-2px);\n}\n\n.fcard-header {\n font-size: 0.7rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: .1em;\n color: var(--accent);\n}\n.fcard-header:empty { display: none; }\n\n.fcard-body { flex: 1; }\n.fcard-body h3 { margin: 0 0 6px; font-size: 1rem; color: var(--text); }\n.fcard-body p { margin: 0; font-size: 0.88rem; color: var(--text-muted); }\n\n.fcard-footer {\n padding-top: 12px;\n border-top: 1px solid var(--border);\n margin-top: auto;\n}\n.fcard-footer:empty { display: none; }\n</style>\n<article class=\"fcard\">\n <div class=\"fcard-header\" data-bascik-slot=\"header\"></div>\n <div class=\"fcard-body\" data-bascik-slot></div>\n <div class=\"fcard-footer\" data-bascik-slot=\"footer\"></div>\n</article>\n";
|
|
33
33
|
export declare const MY_COUNTER_CSS = ".counter {\n display: inline-flex;\n align-items: center;\n gap: 16px;\n font-size: 1.25rem;\n}\n\n.count-val {\n font-family: var(--mono);\n font-size: 1.5rem;\n min-width: 2ch;\n text-align: center;\n color: var(--accent);\n}\n\n.btn {\n display: inline-flex; align-items: center; gap: 8px;\n padding: 10px 22px; border: none; border-radius: var(--r-sm);\n font-size: 0.9rem; font-weight: 600; cursor: pointer;\n text-decoration: none; transition: filter .15s, opacity .15s; line-height: 1;\n}\n.btn-primary { background: var(--accent); color: #18191b; }\n.btn-ghost { background: transparent; color: var(--text); border: 1px solid var(--border); }\n@media (hover: hover) {\n .btn-primary:hover { filter: brightness(0.88); opacity: 1; }\n .btn-ghost:hover { border-color: var(--accent); color: var(--accent); opacity: 1; }\n}\n";
|
|
34
|
-
/** Interactive counter
|
|
34
|
+
/** Interactive counter: two instances on a page stay fully independent. */
|
|
35
35
|
export declare const MY_COUNTER_HTML = "<style>\n.counter {\n display: inline-flex;\n align-items: center;\n gap: 16px;\n font-size: 1.25rem;\n}\n\n.count-val {\n font-family: var(--mono);\n font-size: 1.5rem;\n min-width: 2ch;\n text-align: center;\n color: var(--accent);\n}\n\n.btn {\n display: inline-flex; align-items: center; gap: 8px;\n padding: 10px 22px; border: none; border-radius: var(--r-sm);\n font-size: 0.9rem; font-weight: 600; cursor: pointer;\n text-decoration: none; transition: filter .15s, opacity .15s; line-height: 1;\n}\n.btn-primary { background: var(--accent); color: #18191b; }\n.btn-ghost { background: transparent; color: var(--text); border: 1px solid var(--border); }\n@media (hover: hover) {\n .btn-primary:hover { filter: brightness(0.88); opacity: 1; }\n .btn-ghost:hover { border-color: var(--accent); color: var(--accent); opacity: 1; }\n}\n</style>\n<div class=\"counter\">\n <button id=\"btn-dec\" class=\"btn btn-ghost\" data-testid=\"counter-dec\">\u2212</button>\n <span id=\"count-val\" class=\"count-val\" data-testid=\"counter-val\">0</span>\n <button id=\"btn-inc\" class=\"btn btn-primary\" data-testid=\"counter-inc\">+</button>\n</div>\n<script>\n (function () {\n var count = 0;\n var val = document.getElementById('count-val');\n document.getElementById('btn-dec').addEventListener('click', function () {\n val.textContent = --count;\n });\n document.getElementById('btn-inc').addEventListener('click', function () {\n val.textContent = ++count;\n });\n }());\n</script>\n";
|
|
36
36
|
export declare const SITE_META_TEST = "import { describe, it, expect } from 'vitest';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\ndescribe('site-meta component', () => {\n const path = join(process.cwd(), 'src/components/site-meta/site-meta.html');\n\n it('contains charset, viewport, favicon, and stylesheet link tags', async () => {\n const html = await readFile(path, 'utf8');\n expect(html).toContain('charset=\"UTF-8\"');\n expect(html).toContain('name=\"viewport\"');\n expect(html).toContain('name=\"description\"');\n expect(html).toContain('favicon.ico');\n expect(html).toContain('favicon-32x32.png');\n expect(html).toContain('favicon.svg');\n expect(html).toContain('apple-touch-icon.png');\n expect(html).toContain('styles.css');\n });\n});\n";
|
|
37
37
|
export declare const SITE_HEADER_TEST = "import { describe, it, expect } from 'vitest';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\ndescribe('site-header component', () => {\n const path = join(process.cwd(), 'src/components/site-header/site-header.html');\n\n it('renders brand prop placeholder and navigation links', async () => {\n const html = await readFile(path, 'utf8');\n expect(html).toContain('data-bascik-prop-brand');\n expect(html).toContain('href=\"/\"');\n expect(html).toContain('href=\"/about\"');\n expect(html).toContain('href=\"/contact\"');\n expect(html).toContain('id=\"nav-toggle\"');\n });\n});\n";
|
package/dist/scaffold.js
CHANGED
|
@@ -26,7 +26,7 @@ export const PACKAGE_JSON = (name) => JSON.stringify({
|
|
|
26
26
|
e2e: "playwright test --config e2e/playwright.config.ts",
|
|
27
27
|
},
|
|
28
28
|
dependencies: {
|
|
29
|
-
"@bascik/bascik": "^1.0.0-rc.
|
|
29
|
+
"@bascik/bascik": "^1.0.0-rc.3",
|
|
30
30
|
},
|
|
31
31
|
devDependencies: {
|
|
32
32
|
"@bascik/language-server": "^0.1.0-rc.1",
|
|
@@ -294,7 +294,7 @@ export const FAVICON_SVG = `<svg viewBox="0 0 32 32" width="32" height="32" xmln
|
|
|
294
294
|
export const FAVICON_ICO_B64 = `AAABAAMAEBAAAAEAIADIAAAANgAAACAgAAABACAACAEAAP4AAAAwMAAAAQAgAGcBAAAGAgAiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeklEQVQ4jWNgoDa4/L93/uX/vf8J4577OAzouU+cAb3zMTSf/9+vQKTm/xf/9yRgGHDxf08CsqINV8vBGJsBIMsI+r+g3Q+MyfZ/AU4DiPR/AQ4DiPL/ZTwGEOX/yzgNICH+C7C7gPj434AlGon2/2UcmGj/0y/9UwoAAEX+8tkvEHwAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAAJcEhZcwAACxMAAAsTAQCanBgAAAC6SURBVFiF7ZbRDYMwDEQzwcEIDFC6QJXf0jEYKBEjMBJCGYBRXNEFepZshaqx5O+8+HQ+h9DqS22yDEWy2HY6Alu7pNkeIK80QJG8WgOcn1IApMMa4JSVenxr+svF9X88bxKnsZ7+6PpPV/M/1ADG/ocSwNz/UAKY+x8qAIf9D90E7Pc/FAAu+x8KAJf9DxrAKf/BT8An/0ECuOU/SAC3/I/TKPF1r6N/4bvdf4OL/oXqpn/6kfv/r+sNLlrC+A4T1ksAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAMAAAADAIBgAAAFcC+YcAAAAJcEhZcwAACxMAAAsTAQCanBgAAAEZSURBVGiB7ZjBDcJADARTAVBCKKKGSwfpgo+PlHDfQDOWSQGpBIwuD/7EVpYIr2Qpr+hGXln2Nk0otL0mzWXSrJii2QGAZhxALqbHsw4t8PEqSskEUH+ABGAdWhNA+F/D/+sV/teY/9vNf3mS0piWerxof/OfxqSH42mpfOv2N//7y/kDUL935//eFSBvv/94Aghi//EEYMT+4wdAmP3fsQMFsv97AQhq//cCYNT+7wNAuPvXqQMFdv96AAjy/vUAYOT9awcgAANi40iAAAn3/00EAB2U7f56m/2eQf30E14yR/0AAAABJRU5ErkJggg==`;
|
|
295
295
|
export const FAVICON_32_PNG_B64 = `iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAuklEQVRYhe2W0Q2DMAxEM8HBCAxQukCV39IxGCgRIzASQhmAUVzRBXqWbIWqseTvvPh0PofQ6kttsgxFsth2OgJbu6TZHiCvNECRvFoDnJ9SAKTDGuCUlXp8a/rLxfV/PG8Sp7Ge/uj6T1fzP9QAxv6HEsDc/1ACmPsfKgCH/Q/dBOz3PxQALvsfCgCX/Q8awCn/wU/AJ/9BArjlP0gAt/yP0yjxda+jf+G73X+Di/6F6qZ/+pH7/6/rDS5awvgOE9ZLAAAAAElFTkSuQmCC`;
|
|
296
296
|
export const APPLE_TOUCH_ICON_PNG_B64 = `iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGKUlEQVR4nO2bzWqdVRSGN72AtqO0WicWJ1KtoTi0dGjTK8gFGGtnH1ghJpXOw1l0kHoTUvlIU6rQa9Dg2R9W8OcK2guwky0nkIGU0kTfsvZZ63nhnWWwz7ufnTwcSCmEEEIIIYQQQgghhBBCCCGEEEII6SG12Xptsyd0Fm2DrZIxtdlYmzVq0TYYSra0dvfUvM2edTA+bdoNpnZvtWTL4kMDU7zHNG+z54tfViVbFn+WvMen9iY2GEvG4M9hH9RQsgV/jtsJf/a/BGqSDfBnYGrBNsCfO7gE2mQb4M8AZWE2wJ87uARqkg3wZ2CK9pjGkjF8/xy2Q8kWvn+O24nvn/0vgZpkA/wZmKI9prFkDP4ctkPJFvw5bif82f8SqEk2wJ+BKdpjGkvG4M9hO5RswZ/jdsKf/S+BmmQD/BmYoj2msWQM/hy2Q8kW/DluJ/zZ/xKoSTbAn4Ep2mMaS8bgz2E7lGzBn+N2wp/9L4GaZAP8GZiiPaaxZAz+HLZDyRb8OW4n/Nn/EqhJNsCfgSnaYxpLxuDPYTuUbMGf43bCn5evj3/farsPNw77+I9t9/PUToo/L1n3ft1sn3z6YTt95uy/evX65bb3dNP9fNW/+POy9Lufvmzn3l55Ceajnr+w0h4c3HY/Z/Ut/rwM/fnvnfb+6ruvhPmol65cbAcvdtzPW52KPy9Jd/c+ey3MR72/v+F+3upQ/HmJenN77dhAf3Fnzf281af487J0/da1YwO9+Fnv81af4s8dXAJAN81G+HMHoAK0SfbBnzuAFKBNuRH+7A0pQJtyI/zZG1KANtk++HMHkAK0SbbBnzsAFKBNuQ/+7A0oQJtyH/zZG1CANtk2+HMHgAK0SXbBnzuAE6BNuQ3+7A0nQJtyG/zZG04ANtku+HMHcAK0STbBnzsAE6BNuQv+7A0mQJtyF/zZG0yANtkm+HMHYAK0SfbAnzuAEqBNuQn+7A0lQJtyE/zZG0qANtke+HMHUAK0SbbAnzsAEgBNuQf+7A0kQJtyD/zZG0iANtkW+HMHQAK0SXbAnzuAEaBNuQX+7A0jQJtyC/zZG0aANtkO+HMHMAK0STbAnzsAEQBNuQP+7A0iQJtyB/zZG0SANtkG+HMHIAK0ZgP8uQMIAdqUG+DP3hACtCk3wJ+9IQRok22AP3cAIUCbZAP8uQMAAdqUG+DP3gACtCk3wJ+9AQRok22AP3cAIECbZAP8uQP4ANqUG+DP3vABtCk3wJ+94QNok22AP3cAH0CbZAP8uQPwANqUG+DP3uABtCk3wJ+9wQNok22AP3cAHkCbZAP8uQPoANqUG+DP3tABtCk3wJ+9oQNok22AP3cAHUCbZAP8uQPgANqUG+DP3sABtCk3wJ+9gQNok22AP3cAHECbZAP8uQPYANqUG+DP3rABtCk3wJ+9YQNok22AP3cAG0CbZAP8uQPQANqUG+DP3qABtCk3wJ+9QQNok22AP3cAGkCbZAP8uQPIANqUG+DPmXpze62dPnP2WL31zQ3389aTF3/O1N2HG8cG+ttHn7uft56w+HOyHrzYaZeuXHwtzB98/N7hz3qft56g+HPSPji43c5fWHklzG+9c659/8tX7uesJy/+nLV7Tzfb1euXX4L52o2P2v5vX7ufr/634s/Z+8Of2+3+/sZhf/zrjvt56v8o/tzBJVCTbIA/A1O0xzSWjFl88A7Gp02+Af4MWHEe1tTurZZsWXxo7+GpyTfAnwEr2sMaS8bgz2E7lGxp7e6peZs962B82rQb4M9AFeZRzdvs+eKXVcmWxZ8l7/GpvYnW/d2iwC0CBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIEC`;
|
|
297
|
-
/** Head component
|
|
297
|
+
/** Head component: charset, viewport, favicon, CSS link. */
|
|
298
298
|
export const SITE_META_HTML = `<meta charset="UTF-8" />
|
|
299
299
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
300
300
|
<meta name="description" content="A fast, modern website built with Bascik." />
|
|
@@ -544,7 +544,7 @@ export const MY_COUNTER_CSS = `.counter {
|
|
|
544
544
|
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); opacity: 1; }
|
|
545
545
|
}
|
|
546
546
|
`;
|
|
547
|
-
/** Interactive counter
|
|
547
|
+
/** Interactive counter: two instances on a page stay fully independent. */
|
|
548
548
|
export const MY_COUNTER_HTML = `<style>
|
|
549
549
|
${MY_COUNTER_CSS}</style>
|
|
550
550
|
<div class="counter">
|
|
@@ -665,7 +665,7 @@ ${body}
|
|
|
665
665
|
</body>
|
|
666
666
|
</html>
|
|
667
667
|
`;
|
|
668
|
-
export const indexPage = (brand) => pageShell(`Home
|
|
668
|
+
export const indexPage = (brand) => pageShell(`Home - ${brand}`, brand, ` <section class="hero">
|
|
669
669
|
<div class="container">
|
|
670
670
|
<p class="section-label">Welcome</p>
|
|
671
671
|
<h1>Build fast with <span>${brand}</span></h1>
|
|
@@ -709,14 +709,14 @@ export const indexPage = (brand) => pageShell(`Home — ${brand}`, brand, ` <
|
|
|
709
709
|
<div class="container">
|
|
710
710
|
<p class="section-label">Interactive</p>
|
|
711
711
|
<h2>Counter component</h2>
|
|
712
|
-
<p>Each instance holds its own state. Place the same component twice
|
|
712
|
+
<p>Each instance holds its own state. Place the same component twice, and they stay independent.</p>
|
|
713
713
|
<div style="display:flex;gap:48px;flex-wrap:wrap;margin-top:24px;">
|
|
714
714
|
<my-counter />
|
|
715
715
|
<my-counter />
|
|
716
716
|
</div>
|
|
717
717
|
</div>
|
|
718
718
|
</section>`);
|
|
719
|
-
export const aboutPage = (brand) => pageShell(`About
|
|
719
|
+
export const aboutPage = (brand) => pageShell(`About - ${brand}`, brand, ` <div class="container">
|
|
720
720
|
<section class="section">
|
|
721
721
|
<p class="section-label">About</p>
|
|
722
722
|
<h1>About us</h1>
|
|
@@ -738,7 +738,7 @@ export const aboutPage = (brand) => pageShell(`About — ${brand}`, brand, `
|
|
|
738
738
|
</div>
|
|
739
739
|
</section>
|
|
740
740
|
</div>`);
|
|
741
|
-
export const contactPage = (brand) => pageShell(`Contact
|
|
741
|
+
export const contactPage = (brand) => pageShell(`Contact - ${brand}`, brand, ` <div class="container">
|
|
742
742
|
<section class="section">
|
|
743
743
|
<p class="section-label">Contact</p>
|
|
744
744
|
<h1>Get in touch</h1>
|
|
@@ -761,7 +761,7 @@ export const contactPage = (brand) => pageShell(`Contact — ${brand}`, brand, `
|
|
|
761
761
|
</form>
|
|
762
762
|
</section>
|
|
763
763
|
</div>`);
|
|
764
|
-
export const notFoundPage = (brand) => pageShell(`404
|
|
764
|
+
export const notFoundPage = (brand) => pageShell(`404 - ${brand}`, brand, ` <div class="container">
|
|
765
765
|
<section class="section" style="text-align:center;">
|
|
766
766
|
<p class="section-label">Error</p>
|
|
767
767
|
<h1 style="font-size:clamp(4rem,12vw,8rem);color:var(--accent);margin-bottom:8px;">404</h1>
|
package/dist/scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export interface CliOptions {
|
|
2
2
|
yesFlag: boolean;
|
|
3
3
|
noDevFlag: boolean;
|
|
4
|
+
noInstallFlag: boolean;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
export function parseCliOptions(args: string[]): CliOptions {
|
|
7
8
|
return {
|
|
8
9
|
yesFlag: args.includes("-y") || args.includes("--yes"),
|
|
9
10
|
noDevFlag: args.includes("--no-dev"),
|
|
11
|
+
noInstallFlag: args.includes("--no-install"),
|
|
10
12
|
};
|
|
11
|
-
}
|
|
13
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { parseCliOptions } from "./cli.js";
|
|
|
6
6
|
import { scaffold, validateProjectName } from "./scaffold.js";
|
|
7
7
|
|
|
8
8
|
const args = process.argv.slice(2);
|
|
9
|
-
const { yesFlag, noDevFlag } = parseCliOptions(args);
|
|
9
|
+
const { yesFlag, noDevFlag, noInstallFlag } = parseCliOptions(args);
|
|
10
10
|
const nameArg = args.find((a) => !a.startsWith("-"));
|
|
11
11
|
|
|
12
12
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -35,7 +35,7 @@ let shouldInstall: boolean;
|
|
|
35
35
|
let shouldDev: boolean;
|
|
36
36
|
|
|
37
37
|
if (yesFlag) {
|
|
38
|
-
shouldInstall =
|
|
38
|
+
shouldInstall = !noInstallFlag;
|
|
39
39
|
shouldDev = !noDevFlag;
|
|
40
40
|
} else {
|
|
41
41
|
const installAnswer = await rl.question("Install dependencies now? (Y/n) ");
|
package/src/scaffold.test.ts
CHANGED
|
@@ -60,6 +60,7 @@ describe("parseCliOptions", () => {
|
|
|
60
60
|
expect(parseCliOptions(["my-site", "-y"])).toEqual({
|
|
61
61
|
yesFlag: true,
|
|
62
62
|
noDevFlag: false,
|
|
63
|
+
noInstallFlag: false,
|
|
63
64
|
});
|
|
64
65
|
});
|
|
65
66
|
|
|
@@ -67,6 +68,17 @@ describe("parseCliOptions", () => {
|
|
|
67
68
|
expect(parseCliOptions(["my-site", "--yes", "--no-dev"])).toEqual({
|
|
68
69
|
yesFlag: true,
|
|
69
70
|
noDevFlag: true,
|
|
71
|
+
noInstallFlag: false,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("supports skipping install with --no-install", () => {
|
|
76
|
+
expect(
|
|
77
|
+
parseCliOptions(["my-site", "-y", "--no-install", "--no-dev"]),
|
|
78
|
+
).toEqual({
|
|
79
|
+
yesFlag: true,
|
|
80
|
+
noDevFlag: true,
|
|
81
|
+
noInstallFlag: true,
|
|
70
82
|
});
|
|
71
83
|
});
|
|
72
84
|
});
|
|
@@ -120,9 +132,9 @@ describe("PACKAGE_JSON", () => {
|
|
|
120
132
|
expect(pkg.devDependencies["@playwright/test"]).toBeDefined();
|
|
121
133
|
});
|
|
122
134
|
|
|
123
|
-
it("
|
|
135
|
+
it("uses the current Bascik prerelease dependency", () => {
|
|
124
136
|
const pkg = JSON.parse(PACKAGE_JSON("my-app"));
|
|
125
|
-
expect(pkg.dependencies["@bascik/bascik"]).
|
|
137
|
+
expect(pkg.dependencies["@bascik/bascik"]).toBe("^1.0.0-rc.3");
|
|
126
138
|
});
|
|
127
139
|
|
|
128
140
|
it("uses the supplied name", () => {
|
package/src/scaffold.ts
CHANGED
|
@@ -32,7 +32,7 @@ export const PACKAGE_JSON = (name: string): string =>
|
|
|
32
32
|
e2e: "playwright test --config e2e/playwright.config.ts",
|
|
33
33
|
},
|
|
34
34
|
dependencies: {
|
|
35
|
-
"@bascik/bascik": "^1.0.0-rc.
|
|
35
|
+
"@bascik/bascik": "^1.0.0-rc.3",
|
|
36
36
|
},
|
|
37
37
|
devDependencies: {
|
|
38
38
|
"@bascik/language-server": "^0.1.0-rc.1",
|
|
@@ -325,7 +325,7 @@ export const FAVICON_32_PNG_B64 = `iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0A
|
|
|
325
325
|
|
|
326
326
|
export const APPLE_TOUCH_ICON_PNG_B64 = `iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGKUlEQVR4nO2bzWqdVRSGN72AtqO0WicWJ1KtoTi0dGjTK8gFGGtnH1ghJpXOw1l0kHoTUvlIU6rQa9Dg2R9W8OcK2guwky0nkIGU0kTfsvZZ63nhnWWwz7ufnTwcSCmEEEIIIYQQQgghhBBCCCGEEEII6SG12Xptsyd0Fm2DrZIxtdlYmzVq0TYYSra0dvfUvM2edTA+bdoNpnZvtWTL4kMDU7zHNG+z54tfViVbFn+WvMen9iY2GEvG4M9hH9RQsgV/jtsJf/a/BGqSDfBnYGrBNsCfO7gE2mQb4M8AZWE2wJ87uARqkg3wZ2CK9pjGkjF8/xy2Q8kWvn+O24nvn/0vgZpkA/wZmKI9prFkDP4ctkPJFvw5bif82f8SqEk2wJ+BKdpjGkvG4M9hO5RswZ/jdsKf/S+BmmQD/BmYoj2msWQM/hy2Q8kW/DluJ/zZ/xKoSTbAn4Ep2mMaS8bgz2E7lGzBn+N2wp/9L4GaZAP8GZiiPaaxZAz+HLZDyRb8OW4n/Nn/EqhJNsCfgSnaYxpLxuDPYTuUbMGf43bCn5evj3/farsPNw77+I9t9/PUToo/L1n3ft1sn3z6YTt95uy/evX65bb3dNP9fNW/+POy9Lufvmzn3l55Ceajnr+w0h4c3HY/Z/Ut/rwM/fnvnfb+6ruvhPmol65cbAcvdtzPW52KPy9Jd/c+ey3MR72/v+F+3upQ/HmJenN77dhAf3Fnzf281af487J0/da1YwO9+Fnv81af4s8dXAJAN81G+HMHoAK0SfbBnzuAFKBNuRH+7A0pQJtyI/zZG1KANtk++HMHkAK0SbbBnzsAFKBNuQ/+7A0oQJtyH/zZG1CANtk2+HMHgAK0SXbBnzuAE6BNuQ3+7A0nQJtyG/zZG04ANtku+HMHcAK0STbBnzsAE6BNuQv+7A0mQJtyF/zZG0yANtkm+HMHYAK0SfbAnzuAEqBNuQn+7A0lQJtyE/zZG0qANtke+HMHUAK0SbbAnzsAEgBNuQf+7A0kQJtyD/zZG0iANtkW+HMHQAK0SXbAnzuAEaBNuQX+7A0jQJtyC/zZG0aANtkO+HMHMAK0STbAnzsAEQBNuQP+7A0iQJtyB/zZG0SANtkG+HMHIAK0ZgP8uQMIAdqUG+DP3hACtCk3wJ+9IQRok22AP3cAIUCbZAP8uQMAAdqUG+DP3gACtCk3wJ+9AQRok22AP3cAIECbZAP8uQP4ANqUG+DP3vABtCk3wJ+94QNok22AP3cAH0CbZAP8uQPwANqUG+DP3uABtCk3wJ+9wQNok22AP3cAHkCbZAP8uQPoANqUG+DP3tABtCk3wJ+9oQNok22AP3cAHUCbZAP8uQPgANqUG+DP3sABtCk3wJ+9gQNok22AP3cAHECbZAP8uQPYANqUG+DP3rABtCk3wJ+9YQNok22AP3cAG0CbZAP8uQPQANqUG+DP3qABtCk3wJ+9QQNok22AP3cAGkCbZAP8uQPIANqUG+DPmXpze62dPnP2WL31zQ3389aTF3/O1N2HG8cG+ttHn7uft56w+HOyHrzYaZeuXHwtzB98/N7hz3qft56g+HPSPji43c5fWHklzG+9c659/8tX7uesJy/+nLV7Tzfb1euXX4L52o2P2v5vX7ufr/634s/Z+8Of2+3+/sZhf/zrjvt56v8o/tzBJVCTbIA/A1O0xzSWjFl88A7Gp02+Af4MWHEe1tTurZZsWXxo7+GpyTfAnwEr2sMaS8bgz2E7lGxp7e6peZs962B82rQb4M9AFeZRzdvs+eKXVcmWxZ8l7/GpvYnW/d2iwC0CBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIECBAgAIAAAAAAAAgAAAAAAQIEC`;
|
|
327
327
|
|
|
328
|
-
/** Head component
|
|
328
|
+
/** Head component: charset, viewport, favicon, CSS link. */
|
|
329
329
|
export const SITE_META_HTML = `<meta charset="UTF-8" />
|
|
330
330
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
331
331
|
<meta name="description" content="A fast, modern website built with Bascik." />
|
|
@@ -583,7 +583,7 @@ export const MY_COUNTER_CSS = `.counter {
|
|
|
583
583
|
}
|
|
584
584
|
`;
|
|
585
585
|
|
|
586
|
-
/** Interactive counter
|
|
586
|
+
/** Interactive counter: two instances on a page stay fully independent. */
|
|
587
587
|
export const MY_COUNTER_HTML = `<style>
|
|
588
588
|
${MY_COUNTER_CSS}</style>
|
|
589
589
|
<div class="counter">
|
|
@@ -718,7 +718,7 @@ ${body}
|
|
|
718
718
|
`;
|
|
719
719
|
|
|
720
720
|
export const indexPage = (brand: string): string =>
|
|
721
|
-
pageShell(`Home
|
|
721
|
+
pageShell(`Home - ${brand}`, brand, ` <section class="hero">
|
|
722
722
|
<div class="container">
|
|
723
723
|
<p class="section-label">Welcome</p>
|
|
724
724
|
<h1>Build fast with <span>${brand}</span></h1>
|
|
@@ -762,7 +762,7 @@ export const indexPage = (brand: string): string =>
|
|
|
762
762
|
<div class="container">
|
|
763
763
|
<p class="section-label">Interactive</p>
|
|
764
764
|
<h2>Counter component</h2>
|
|
765
|
-
<p>Each instance holds its own state. Place the same component twice
|
|
765
|
+
<p>Each instance holds its own state. Place the same component twice, and they stay independent.</p>
|
|
766
766
|
<div style="display:flex;gap:48px;flex-wrap:wrap;margin-top:24px;">
|
|
767
767
|
<my-counter />
|
|
768
768
|
<my-counter />
|
|
@@ -771,7 +771,7 @@ export const indexPage = (brand: string): string =>
|
|
|
771
771
|
</section>`);
|
|
772
772
|
|
|
773
773
|
export const aboutPage = (brand: string): string =>
|
|
774
|
-
pageShell(`About
|
|
774
|
+
pageShell(`About - ${brand}`, brand, ` <div class="container">
|
|
775
775
|
<section class="section">
|
|
776
776
|
<p class="section-label">About</p>
|
|
777
777
|
<h1>About us</h1>
|
|
@@ -795,7 +795,7 @@ export const aboutPage = (brand: string): string =>
|
|
|
795
795
|
</div>`);
|
|
796
796
|
|
|
797
797
|
export const contactPage = (brand: string): string =>
|
|
798
|
-
pageShell(`Contact
|
|
798
|
+
pageShell(`Contact - ${brand}`, brand, ` <div class="container">
|
|
799
799
|
<section class="section">
|
|
800
800
|
<p class="section-label">Contact</p>
|
|
801
801
|
<h1>Get in touch</h1>
|
|
@@ -820,7 +820,7 @@ export const contactPage = (brand: string): string =>
|
|
|
820
820
|
</div>`);
|
|
821
821
|
|
|
822
822
|
export const notFoundPage = (brand: string): string =>
|
|
823
|
-
pageShell(`404
|
|
823
|
+
pageShell(`404 - ${brand}`, brand, ` <div class="container">
|
|
824
824
|
<section class="section" style="text-align:center;">
|
|
825
825
|
<p class="section-label">Error</p>
|
|
826
826
|
<h1 style="font-size:clamp(4rem,12vw,8rem);color:var(--accent);margin-bottom:8px;">404</h1>
|