spark-html-font 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -6,11 +6,12 @@ sites — configure every font **once**, get the whole loading story: correct
6
6
  face** so the swap doesn't shift the layout. Zero dependencies.
7
7
 
8
8
  ```js
9
- // vite.config.js — bake into every built page
10
- import font from 'spark-html-font/vite';
9
+ // spark.config.js — bake into every built page
10
+ import prerender from 'spark-prerender/bun';
11
+ import font from 'spark-html-font/bun';
11
12
 
12
13
  export default {
13
- plugins: [spark(), prerender(), font({
14
+ pipeline: [prerender(), font({
14
15
  fonts: [
15
16
  { family: 'Inter', src: '/fonts/inter-var.woff2', weight: '100 900' },
16
17
  { family: 'Fira Code', google: true, weights: [400, 700] },
@@ -74,3 +75,29 @@ npm install -D spark-html-font
74
75
 
75
76
  Top-level: `fallback` — generic families appended to every var stack
76
77
  (default `['system-ui', 'sans-serif']`).
78
+
79
+ ## The Spark family
80
+
81
+ Small, single-purpose packages that share one philosophy: no compiler, no
82
+ virtual DOM, no build step required. Add only what you use.
83
+
84
+ | Package | What it does |
85
+ |---|---|
86
+ | [`spark-html`](https://www.npmjs.com/package/spark-html) | The runtime — components, reactivity, stores, forms, scoped styles. 13 kB gzip, 0 deps. |
87
+ | [`spark-html-router`](https://www.npmjs.com/package/spark-html-router) | `<template route>` routing — nested routes/layouts, `route.query`, active links. |
88
+ | [`spark-html-theme`](https://www.npmjs.com/package/spark-html-theme) | Dark/light/system theming in one line — persisted, no flash. |
89
+ | [`spark-html-head`](https://www.npmjs.com/package/spark-html-head) | Reactive `<title>`/`<meta>` per route + a `head` store. |
90
+ | [`spark-html-motion`](https://www.npmjs.com/package/spark-html-motion) | Enter/leave transitions on if/each blocks — `transition="fade|slide|scale"`. |
91
+ | [`spark-html-devtools`](https://www.npmjs.com/package/spark-html-devtools) | In-page devtools — live stores, component tree, patch activity. |
92
+ | [`spark-html-query`](https://www.npmjs.com/package/spark-html-query) | Declarative async data — a self-fetching store (`loading`/`error`/`data`/`refetch`). |
93
+ | [`spark-html-persist`](https://www.npmjs.com/package/spark-html-persist) | Persist stores to localStorage/sessionStorage in one line. |
94
+ | [`spark-html-websocket`](https://www.npmjs.com/package/spark-html-websocket) | A WebSocket as a reactive store — auto-reconnect, JSON, `send()`. |
95
+ | [`spark-prerender`](https://www.npmjs.com/package/spark-prerender) | Build-time SEO prerender + sitemap/robots — no SSR server. |
96
+ | [`spark-html-image`](https://www.npmjs.com/package/spark-html-image) | Build-time image optimization — webp/avif + responsive `srcset`, zero config. |
97
+ | [`spark-html-font`](https://www.npmjs.com/package/spark-html-font) | Font loading optimizer — preload + size-adjusted fallbacks, no FOUT. |
98
+ | [`spark-html-manifest`](https://www.npmjs.com/package/spark-html-manifest) | PWA manifest + icons + head tags (and optional service worker) from one config. |
99
+ | [`spark-html-offline`](https://www.npmjs.com/package/spark-html-offline) | Offline URL imports — a service worker that caches CDN components. |
100
+ | [`spark-html-sri`](https://www.npmjs.com/package/spark-html-sri) | Subresource Integrity — hash + verify assets and remote components. |
101
+ | [`create-spark-html-app`](https://www.npmjs.com/package/create-spark-html-app) | Scaffold a spark-html app in one command. |
102
+ | [`prettier-plugin-spark`](https://www.npmjs.com/package/prettier-plugin-spark) | Prettier for components — formats `<script>`/`<style>`, markup stays byte-for-byte. |
103
+ | [`spark-html-language-server`](https://www.npmjs.com/package/spark-html-language-server) | LSP — diagnostics, go-to-definition, prop autocomplete, hover docs. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spark-html-font",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Font loading optimizer for spark-html sites — @font-face + preload + size-adjusted fallbacks in one config, no FOUT, no layout shift. Zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -11,9 +11,8 @@
11
11
  "types": "./src/index.d.ts",
12
12
  "default": "./src/index.js"
13
13
  },
14
- "./vite": {
15
- "types": "./src/index.d.ts",
16
- "default": "./src/vite.js"
14
+ "./bun": {
15
+ "default": "./src/bun.js"
17
16
  }
18
17
  },
19
18
  "scripts": {
@@ -34,7 +33,7 @@
34
33
  "preload",
35
34
  "cls",
36
35
  "layout-shift",
37
- "vite-plugin"
36
+ "bun"
38
37
  ],
39
38
  "license": "MIT"
40
39
  }
package/src/bun.js ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * spark-html-font/bun — bake the font tags into every built page, as a
3
+ * spark-html-bun pipeline step.
4
+ *
5
+ * Inserts the <link rel="preload">s + inline <style data-spark-font> right
6
+ * before </head> in each page — so the font fetch starts with the HTML and
7
+ * first paint uses the size-adjusted fallback. Component fragments have no
8
+ * <head> and are skipped naturally; pages already carrying data-spark-font
9
+ * are left alone (idempotent). Put it after prerender() in the pipeline so
10
+ * per-route pages are covered.
11
+ *
12
+ * import font from 'spark-html-font/bun';
13
+ * export default { pipeline: [prerender(), font({ fonts: [...] })] };
14
+ */
15
+ import { join, resolve } from 'node:path';
16
+ import { readFile, writeFile, readdir, stat } from 'node:fs/promises';
17
+ import { existsSync } from 'node:fs';
18
+ import { fontHtml } from './index.js';
19
+
20
+ async function htmlFiles(dir) {
21
+ const out = [];
22
+ for (const name of await readdir(dir)) {
23
+ const full = join(dir, name);
24
+ const s = await stat(full);
25
+ if (s.isDirectory()) out.push(...await htmlFiles(full));
26
+ else if (name.endsWith('.html')) out.push(full);
27
+ }
28
+ return out;
29
+ }
30
+
31
+ export default function sparkFont(config = {}) {
32
+ return {
33
+ name: 'spark-html-font',
34
+ async run({ outDir }) {
35
+ const root = resolve(outDir);
36
+ if (!existsSync(root)) return;
37
+ const block = fontHtml(config);
38
+ if (!block) return;
39
+ let pages = 0;
40
+ for (const file of await htmlFiles(root)) {
41
+ const html = await readFile(file, 'utf8');
42
+ if (!/<\/head>/i.test(html)) continue; // fragment (component) — skip
43
+ if (html.includes('data-spark-font')) continue; // already injected
44
+ await writeFile(file, html.replace(/<\/head>/i, `${block}\n</head>`), 'utf8');
45
+ pages++;
46
+ }
47
+ if (pages) console.log(`[spark-html-font] injected font loading into ${pages} page(s)`);
48
+ },
49
+ // Dev: inject the same tags into served pages so fonts load in dev too.
50
+ transformHtml(html, { dev }) {
51
+ if (!dev) return html;
52
+ if (html.includes('data-spark-font') || !/<\/head>/i.test(html)) return html;
53
+ const block = fontHtml(config);
54
+ return block ? html.replace(/<\/head>/i, `${block}\n</head>`) : html;
55
+ },
56
+ };
57
+ }
package/src/index.js CHANGED
@@ -18,8 +18,8 @@
18
18
  * import { fonts } from 'spark-html-font';
19
19
  * fonts({ fonts: [{ family: 'Inter', src: '/fonts/inter-var.woff2', weight: '100 900' }] });
20
20
  *
21
- * // at build (vite.config.js) — bakes the same tags into every built page
22
- * import font from 'spark-html-font/vite';
21
+ * // at build (spark.config.js) — bakes the same tags into every built page
22
+ * import font from 'spark-html-font/bun';
23
23
  * plugins: [spark(), prerender(), font({ fonts: [...] })]
24
24
  *
25
25
  * Zero dependencies; pure string generation plus a little DOM.
@@ -127,7 +127,7 @@ export function fontLinks(config = {}) {
127
127
  return links;
128
128
  }
129
129
 
130
- // Serialize the links + style as an HTML block (used by the vite plugin; the
130
+ // Serialize the links + style as an HTML block (used by the bun build step; the
131
131
  // data-spark-font marker makes injection idempotent).
132
132
  export function fontHtml(config = {}) {
133
133
  const attrs = (l) => Object.entries(l)
package/src/vite.js DELETED
@@ -1,57 +0,0 @@
1
- /**
2
- * spark-html-font/vite — bake the font tags into every built page.
3
- *
4
- * Runs in closeBundle (order post, after spark-prerender has written its
5
- * per-route HTML) and inserts the <link rel="preload">s + inline
6
- * <style data-spark-font> right before </head> in each page — so the font
7
- * fetch starts with the HTML and first paint uses the size-adjusted
8
- * fallback. Component fragments have no <head> and are skipped naturally;
9
- * pages already carrying data-spark-font are left alone (idempotent).
10
- *
11
- * import font from 'spark-html-font/vite';
12
- * plugins: [spark(), prerender(), font({ fonts: [...] })]
13
- */
14
- import { join, resolve } from 'node:path';
15
- import { readFile, writeFile, readdir, stat } from 'node:fs/promises';
16
- import { existsSync } from 'node:fs';
17
- import { fontHtml } from './index.js';
18
-
19
- async function htmlFiles(dir) {
20
- const out = [];
21
- for (const name of await readdir(dir)) {
22
- const full = join(dir, name);
23
- const s = await stat(full);
24
- if (s.isDirectory()) out.push(...await htmlFiles(full));
25
- else if (name.endsWith('.html')) out.push(full);
26
- }
27
- return out;
28
- }
29
-
30
- export default function sparkFont(config = {}) {
31
- let outDir = 'dist';
32
- return {
33
- name: 'spark-html-font',
34
- apply: 'build',
35
- configResolved(viteConfig) {
36
- if (viteConfig && viteConfig.build && viteConfig.build.outDir) outDir = viteConfig.build.outDir;
37
- },
38
- closeBundle: {
39
- order: 'post',
40
- async handler() {
41
- const root = resolve(outDir);
42
- if (!existsSync(root)) return;
43
- const block = fontHtml(config);
44
- if (!block) return;
45
- let pages = 0;
46
- for (const file of await htmlFiles(root)) {
47
- const html = await readFile(file, 'utf8');
48
- if (!/<\/head>/i.test(html)) continue; // fragment (component) — skip
49
- if (html.includes('data-spark-font')) continue; // already injected
50
- await writeFile(file, html.replace(/<\/head>/i, `${block}\n</head>`), 'utf8');
51
- pages++;
52
- }
53
- if (pages) console.log(`[spark-html-font] injected font loading into ${pages} page(s)`);
54
- },
55
- },
56
- };
57
- }