@inkandswitch/patchwork 0.7.1 → 0.7.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/CHANGELOG.md +28 -0
- package/dist/site-kit/html.js +13 -3
- package/dist/site-kit/options.d.ts +9 -1
- package/dist/vite/build-info-plugin.d.ts +1 -1
- package/dist/vite/build-info-plugin.js +1 -1
- package/dist/vite/config-plugin.d.ts +1 -1
- package/dist/vite/config-plugin.js +1 -1
- package/dist/vite/dev-plugin.d.ts +1 -1
- package/dist/vite/dev-plugin.js +1 -1
- package/dist/vite/html-plugin.d.ts +1 -1
- package/dist/vite/html-plugin.js +1 -1
- package/dist/vite/icons.d.ts +1 -1
- package/dist/vite/icons.js +1 -1
- package/dist/vite/manifest-plugin.d.ts +1 -1
- package/dist/vite/manifest-plugin.js +1 -1
- package/dist/vite/netlify-plugin.d.ts +1 -1
- package/dist/vite/netlify-plugin.js +1 -1
- package/dist/vite/patchwork-plugin.d.ts +10 -0
- package/dist/vite/patchwork-plugin.js +26 -16
- package/dist/vite/static-plugin.d.ts +3 -2
- package/dist/vite/static-plugin.js +15 -4
- package/package.json +45 -5
- package/src/site-kit/html.ts +17 -3
- package/src/site-kit/options.ts +9 -1
- package/src/vite/build-info-plugin.ts +1 -1
- package/src/vite/config-plugin.ts +1 -1
- package/src/vite/dev-plugin.ts +1 -1
- package/src/vite/html-plugin.ts +1 -1
- package/src/vite/icons.ts +1 -1
- package/src/vite/manifest-plugin.ts +1 -1
- package/src/vite/netlify-plugin.ts +1 -1
- package/src/vite/patchwork-plugin.ts +27 -16
- package/src/vite/static-plugin.ts +23 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @inkandswitch/patchwork
|
|
2
2
|
|
|
3
|
+
## 0.7.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8742cd2: Expose the individual vite plugins that `patchwork()` composes. Each one now has its own subpath — `@inkandswitch/patchwork/vite/importmap`, `/vite/service-worker`, `/vite/config`, `/vite/dev`, `/vite/icons`, `/vite/html`, `/vite/manifest`, `/vite/netlify`, `/vite/static`, `/vite/build-info` — and they are also re-exported from `@inkandswitch/patchwork/vite` as `importmap`, `serviceworker`, `config`, `dev`, `icons`, `html`, `manifest`, `netlify`, `statics` and `buildInfo`, so a site that wants its own composition can pick the pieces it needs instead of the whole default plugin array.
|
|
8
|
+
- Updated dependencies [94f6299]
|
|
9
|
+
- Updated dependencies [a96f250]
|
|
10
|
+
- @inkandswitch/patchwork-elements@6.0.1
|
|
11
|
+
- @inkandswitch/patchwork-plugins@1.2.1
|
|
12
|
+
- @inkandswitch/patchwork-filesystem@0.2.6
|
|
13
|
+
|
|
14
|
+
## 0.7.2
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- e1374ad: Serve the `/packages/…` builtin URLs in dev. Import maps don't apply to worker
|
|
19
|
+
scripts, so code that starts one — `@automerge/automerge-repo`'s shared
|
|
20
|
+
subduction websocket worker, for instance — asks for the `/packages/…` path the
|
|
21
|
+
build emits. Nothing served those in dev, and the worker failed to fetch; the
|
|
22
|
+
dev server now redirects them to the same optimized dep the page's import map
|
|
23
|
+
points at.
|
|
24
|
+
- e1374ad: Say what's actually wrong when a `static` package declares a directory that
|
|
25
|
+
isn't there. The package resolved fine — its `"patchwork": {"static": …}` field
|
|
26
|
+
is what's wrong — and "static source not found" named neither the field nor the
|
|
27
|
+
path it pointed at. The error now quotes the declaration, gives the full path
|
|
28
|
+
that's missing, and says that a package publishing its static tree as the root
|
|
29
|
+
of its own tarball shouldn't set the field at all.
|
|
30
|
+
|
|
3
31
|
## 0.7.1
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/dist/site-kit/html.js
CHANGED
|
@@ -15,6 +15,10 @@ export function escapeHtml(value) {
|
|
|
15
15
|
export function buildHtml(options) {
|
|
16
16
|
const title = options.title ?? DEFAULT_TITLE;
|
|
17
17
|
const lang = (options.html && options.html.lang) || "en";
|
|
18
|
+
const attributes = Object.entries((options.html && options.html.attributes) || {})
|
|
19
|
+
.filter(([name]) => name !== "lang" && /^[a-z][a-z0-9-]*$/i.test(name))
|
|
20
|
+
.map(([name, value]) => ` ${name}="${escapeHtml(value)}"`)
|
|
21
|
+
.join("");
|
|
18
22
|
const entry = options.entry ?? "/src/main.ts";
|
|
19
23
|
const syncServers = resolveSyncServers(options);
|
|
20
24
|
const head = [
|
|
@@ -61,11 +65,17 @@ export function buildHtml(options) {
|
|
|
61
65
|
if (options.html && options.html.extraHead) {
|
|
62
66
|
head.push(options.html.extraHead);
|
|
63
67
|
}
|
|
68
|
+
const body = [
|
|
69
|
+
`<repo-provider><patchwork-view id="root"></patchwork-view></repo-provider>`,
|
|
70
|
+
`<script type="module" src="${entry}"></script>`,
|
|
71
|
+
];
|
|
72
|
+
if (options.html && options.html.extraBody) {
|
|
73
|
+
body.push(options.html.extraBody);
|
|
74
|
+
}
|
|
64
75
|
return `<!doctype html>
|
|
65
|
-
<html lang="${lang}">
|
|
76
|
+
<html lang="${lang}"${attributes}>
|
|
66
77
|
${head.join("\n")}
|
|
67
|
-
|
|
68
|
-
<script type="module" src="${entry}"></script>
|
|
78
|
+
${body.join("\n")}
|
|
69
79
|
</html>
|
|
70
80
|
`;
|
|
71
81
|
}
|
|
@@ -16,8 +16,16 @@ export interface PatchworkIconsOptions {
|
|
|
16
16
|
}
|
|
17
17
|
export interface PatchworkHtmlOptions {
|
|
18
18
|
lang?: string;
|
|
19
|
-
/** Raw HTML appended
|
|
19
|
+
/** Raw HTML appended after the generated head — e.g. extra <link>/<meta> tags. */
|
|
20
20
|
extraHead?: string;
|
|
21
|
+
/** Raw HTML appended after the app root and entry script. */
|
|
22
|
+
extraBody?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Attributes set on the root `<html>` element. How a site states its own
|
|
25
|
+
* configuration to the packages it loads: a package reads the attribute
|
|
26
|
+
* instead of guessing from load order. `lang` stays its own option.
|
|
27
|
+
*/
|
|
28
|
+
attributes?: Record<string, string>;
|
|
21
29
|
}
|
|
22
30
|
export interface PatchworkNetlifyOptions {
|
|
23
31
|
/** Cache-Control: immutable on /assets/*. Default true. */
|
|
@@ -5,4 +5,4 @@ import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
|
5
5
|
* revision, the version of patchwork that built it, and every `static` source,
|
|
6
6
|
* plus whatever extra fields the site passes as the option value.
|
|
7
7
|
*/
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function buildInfo(options?: PatchworkVitePluginOptions): Plugin | null;
|
|
@@ -37,7 +37,7 @@ function describe(directory) {
|
|
|
37
37
|
* revision, the version of patchwork that built it, and every `static` source,
|
|
38
38
|
* plus whatever extra fields the site passes as the option value.
|
|
39
39
|
*/
|
|
40
|
-
export function
|
|
40
|
+
export function buildInfo(options = {}) {
|
|
41
41
|
if (!options.buildInfo)
|
|
42
42
|
return null;
|
|
43
43
|
let root;
|
|
@@ -15,5 +15,5 @@ export declare function buildDefines(options?: PatchworkVitePluginOptions): Reco
|
|
|
15
15
|
* used to hand-write in its own vite.config.ts. Each is switched off
|
|
16
16
|
* individually via the matching `false` option.
|
|
17
17
|
*/
|
|
18
|
-
export declare function
|
|
18
|
+
export declare function config(options?: PatchworkVitePluginOptions): Plugin;
|
|
19
19
|
export { wasm };
|
|
@@ -27,7 +27,7 @@ export function buildDefines(options = {}) {
|
|
|
27
27
|
* used to hand-write in its own vite.config.ts. Each is switched off
|
|
28
28
|
* individually via the matching `false` option.
|
|
29
29
|
*/
|
|
30
|
-
export function
|
|
30
|
+
export function config(options = {}) {
|
|
31
31
|
return {
|
|
32
32
|
name: "@patchwork/config",
|
|
33
33
|
config() {
|
package/dist/vite/dev-plugin.js
CHANGED
|
@@ -53,7 +53,7 @@ function workerContexts(options) {
|
|
|
53
53
|
}
|
|
54
54
|
return contexts;
|
|
55
55
|
}
|
|
56
|
-
export function
|
|
56
|
+
export function dev(options = {}) {
|
|
57
57
|
let serve = false;
|
|
58
58
|
let contexts;
|
|
59
59
|
const wasm = new Map(wasmAssets().map(({ fileName, path }) => [`/${fileName}`, path]));
|
|
@@ -8,4 +8,4 @@ import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
|
8
8
|
* virtual module: `resolveId` claims the one id we care about, `load`
|
|
9
9
|
* returns the generated string — nothing ever touches disk.
|
|
10
10
|
*/
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function html(options?: PatchworkVitePluginOptions): Plugin | null;
|
package/dist/vite/html-plugin.js
CHANGED
|
@@ -9,7 +9,7 @@ const GENERATED_PATH = "index.html";
|
|
|
9
9
|
* virtual module: `resolveId` claims the one id we care about, `load`
|
|
10
10
|
* returns the generated string — nothing ever touches disk.
|
|
11
11
|
*/
|
|
12
|
-
export function
|
|
12
|
+
export function html(options = {}) {
|
|
13
13
|
if (options.html === false)
|
|
14
14
|
return null;
|
|
15
15
|
const html = buildHtml(options);
|
package/dist/vite/icons.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
3
3
|
/** Emits the rendered icon PNGs for build, and serves the same buffers for dev. */
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function icons(options?: PatchworkVitePluginOptions): Plugin | null;
|
package/dist/vite/icons.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import { getIcons } from "../site-kit/icons.js";
|
|
3
3
|
/** Emits the rendered icon PNGs for build, and serves the same buffers for dev. */
|
|
4
|
-
export function
|
|
4
|
+
export function icons(options = {}) {
|
|
5
5
|
if (!options.icons)
|
|
6
6
|
return null;
|
|
7
7
|
const { source } = options.icons;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
3
3
|
/** Emits manifest.webmanifest for build and serves it for dev, from the same generated object. */
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function manifest(options?: PatchworkVitePluginOptions): Plugin | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { buildManifest } from "../site-kit/manifest.js";
|
|
2
2
|
/** Emits manifest.webmanifest for build and serves it for dev, from the same generated object. */
|
|
3
|
-
export function
|
|
3
|
+
export function manifest(options = {}) {
|
|
4
4
|
if (options.manifest === false)
|
|
5
5
|
return null;
|
|
6
6
|
const manifest = buildManifest(options);
|
|
@@ -6,4 +6,4 @@ import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
|
6
6
|
* The Link header shares its sync-server/wasm-asset lists with html-plugin
|
|
7
7
|
* so the two never drift out of sync with each other.
|
|
8
8
|
*/
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function netlify(options?: PatchworkVitePluginOptions): Plugin | null;
|
|
@@ -5,7 +5,7 @@ import { buildHeaders, REDIRECTS } from "../site-kit/netlify.js";
|
|
|
5
5
|
* The Link header shares its sync-server/wasm-asset lists with html-plugin
|
|
6
6
|
* so the two never drift out of sync with each other.
|
|
7
7
|
*/
|
|
8
|
-
export function
|
|
8
|
+
export function netlify(options = {}) {
|
|
9
9
|
if (options.netlify === false)
|
|
10
10
|
return null;
|
|
11
11
|
const headers = buildHeaders(options);
|
|
@@ -23,6 +23,16 @@ import type { PatchworkSiteOptions } from "../site-kit/options.js";
|
|
|
23
23
|
* a different bundler adapter.
|
|
24
24
|
*/
|
|
25
25
|
export default function patchwork(options?: PatchworkVitePluginOptions): Plugin<any>[];
|
|
26
|
+
export { importmap, builtins, devDependencyId } from "./importmap-plugin.js";
|
|
27
|
+
export { serviceworker, workers } from "./service-worker-plugin.js";
|
|
28
|
+
export { config, buildDefines, wasm } from "./config-plugin.js";
|
|
29
|
+
export { dev } from "./dev-plugin.js";
|
|
30
|
+
export { icons } from "./icons.js";
|
|
31
|
+
export { html } from "./html-plugin.js";
|
|
32
|
+
export { manifest } from "./manifest-plugin.js";
|
|
33
|
+
export { netlify } from "./netlify-plugin.js";
|
|
34
|
+
export { statics, resolveStatic } from "./static-plugin.js";
|
|
35
|
+
export { buildInfo } from "./build-info-plugin.js";
|
|
26
36
|
type Imports = {
|
|
27
37
|
[name: string]: string;
|
|
28
38
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { importmap } from "./importmap-plugin.js";
|
|
2
2
|
import { serviceworker } from "./service-worker-plugin.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
3
|
+
import { config, wasm } from "./config-plugin.js";
|
|
4
|
+
import { dev } from "./dev-plugin.js";
|
|
5
|
+
import { icons } from "./icons.js";
|
|
6
|
+
import { html } from "./html-plugin.js";
|
|
7
|
+
import { manifest } from "./manifest-plugin.js";
|
|
8
|
+
import { netlify } from "./netlify-plugin.js";
|
|
9
|
+
import { statics } from "./static-plugin.js";
|
|
10
|
+
import { buildInfo } from "./build-info-plugin.js";
|
|
11
11
|
/**
|
|
12
12
|
* The patchwork vite plugin. A site's vite.config.ts can shrink down to
|
|
13
13
|
* `plugins: [patchwork({...})]` plus a single source icon file — this plugin
|
|
@@ -32,15 +32,25 @@ import { buildInfoPlugin } from "./build-info-plugin.js";
|
|
|
32
32
|
export default function patchwork(options) {
|
|
33
33
|
return [
|
|
34
34
|
wasm(),
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
config(options),
|
|
36
|
+
icons(options),
|
|
37
|
+
html(options),
|
|
38
|
+
manifest(options),
|
|
39
|
+
netlify(options),
|
|
40
40
|
importmap(options),
|
|
41
41
|
serviceworker(),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
dev(options),
|
|
43
|
+
statics(options),
|
|
44
|
+
buildInfo(options),
|
|
45
45
|
].filter((plugin) => plugin != null);
|
|
46
46
|
}
|
|
47
|
+
export { importmap, builtins, devDependencyId } from "./importmap-plugin.js";
|
|
48
|
+
export { serviceworker, workers } from "./service-worker-plugin.js";
|
|
49
|
+
export { config, buildDefines, wasm } from "./config-plugin.js";
|
|
50
|
+
export { dev } from "./dev-plugin.js";
|
|
51
|
+
export { icons } from "./icons.js";
|
|
52
|
+
export { html } from "./html-plugin.js";
|
|
53
|
+
export { manifest } from "./manifest-plugin.js";
|
|
54
|
+
export { netlify } from "./netlify-plugin.js";
|
|
55
|
+
export { statics, resolveStatic } from "./static-plugin.js";
|
|
56
|
+
export { buildInfo } from "./build-info-plugin.js";
|
|
@@ -7,7 +7,8 @@ import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
|
7
7
|
* `from` is either a package specifier or a path relative to the site root. A
|
|
8
8
|
* package says where its static tree lives with a `"patchwork": {"static":
|
|
9
9
|
* "static-dist"}` field in its own package.json; without one, the whole
|
|
10
|
-
* package directory is mounted
|
|
10
|
+
* package directory is mounted — which is what a package that publishes its
|
|
11
|
+
* static tree as the root of its own tarball wants.
|
|
11
12
|
*/
|
|
12
13
|
export interface PatchworkStaticSource {
|
|
13
14
|
from: string;
|
|
@@ -43,4 +44,4 @@ export declare function resolveStatic(options: PatchworkVitePluginOptions, root:
|
|
|
43
44
|
* order, and a site keeps its own `modules.json` by listing it before the
|
|
44
45
|
* package it borrows the rest of the packages from.
|
|
45
46
|
*/
|
|
46
|
-
export declare function
|
|
47
|
+
export declare function statics(options?: PatchworkVitePluginOptions): Plugin | null;
|
|
@@ -34,17 +34,28 @@ function packageDirectory(name, root) {
|
|
|
34
34
|
throw new Error(`[patchwork] can't find the package "${name}" — a static source has to be a dependency of the site`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
/** A package's static tree: the directory it declares, or its root. */
|
|
38
|
+
function staticDirectory(name, directory) {
|
|
39
|
+
const declared = JSON.parse(readFileSync(join(directory, "package.json"), "utf8")).patchwork?.static;
|
|
40
|
+
if (!declared)
|
|
41
|
+
return directory;
|
|
42
|
+
const path = join(directory, declared);
|
|
43
|
+
if (!existsSync(path)) {
|
|
44
|
+
throw new Error(`[patchwork] ${name} declares "patchwork": {"static": ${JSON.stringify(declared)}}, but ${path} doesn't exist. ` +
|
|
45
|
+
`The field is a path inside the installed package — a package that publishes its static tree as the tarball's own root shouldn't set it at all.`);
|
|
46
|
+
}
|
|
47
|
+
return path;
|
|
48
|
+
}
|
|
37
49
|
export function resolveStatic(options, root) {
|
|
38
50
|
return (options.static ?? []).map((source) => {
|
|
39
51
|
const entry = typeof source === "string" ? { from: source } : source;
|
|
40
52
|
const isPath = entry.from.startsWith(".") || isAbsolute(entry.from);
|
|
41
53
|
const directory = isPath ? undefined : packageDirectory(entry.from, root);
|
|
42
54
|
const path = directory
|
|
43
|
-
?
|
|
44
|
-
.patchwork?.static ?? ".")
|
|
55
|
+
? staticDirectory(entry.from, directory)
|
|
45
56
|
: resolve(root, entry.from);
|
|
46
57
|
if (!existsSync(path)) {
|
|
47
|
-
throw new Error(`[patchwork] static source not found: ${entry.from}`);
|
|
58
|
+
throw new Error(`[patchwork] static source not found: ${entry.from} (${path})`);
|
|
48
59
|
}
|
|
49
60
|
const file = statSync(path).isFile();
|
|
50
61
|
const to = entry.to ?? "/";
|
|
@@ -105,7 +116,7 @@ async function files(source, directory = source) {
|
|
|
105
116
|
* order, and a site keeps its own `modules.json` by listing it before the
|
|
106
117
|
* package it borrows the rest of the packages from.
|
|
107
118
|
*/
|
|
108
|
-
export function
|
|
119
|
+
export function statics(options = {}) {
|
|
109
120
|
if (!options.static?.length)
|
|
110
121
|
return null;
|
|
111
122
|
let sources = [];
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"url": "git+https://github.com/inkandswitch/patchwork-system.git",
|
|
6
6
|
"directory": "core/patchwork"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.7.
|
|
8
|
+
"version": "0.7.3",
|
|
9
9
|
"author": "Ink & Switch",
|
|
10
10
|
"type": "module",
|
|
11
11
|
"license": "MIT",
|
|
@@ -19,6 +19,46 @@
|
|
|
19
19
|
"import": "./dist/vite/patchwork-plugin.js",
|
|
20
20
|
"types": "./dist/vite/patchwork-plugin.d.ts"
|
|
21
21
|
},
|
|
22
|
+
"./vite/build-info": {
|
|
23
|
+
"import": "./dist/vite/build-info-plugin.js",
|
|
24
|
+
"types": "./dist/vite/build-info-plugin.d.ts"
|
|
25
|
+
},
|
|
26
|
+
"./vite/config": {
|
|
27
|
+
"import": "./dist/vite/config-plugin.js",
|
|
28
|
+
"types": "./dist/vite/config-plugin.d.ts"
|
|
29
|
+
},
|
|
30
|
+
"./vite/dev": {
|
|
31
|
+
"import": "./dist/vite/dev-plugin.js",
|
|
32
|
+
"types": "./dist/vite/dev-plugin.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./vite/html": {
|
|
35
|
+
"import": "./dist/vite/html-plugin.js",
|
|
36
|
+
"types": "./dist/vite/html-plugin.d.ts"
|
|
37
|
+
},
|
|
38
|
+
"./vite/icons": {
|
|
39
|
+
"import": "./dist/vite/icons.js",
|
|
40
|
+
"types": "./dist/vite/icons.d.ts"
|
|
41
|
+
},
|
|
42
|
+
"./vite/importmap": {
|
|
43
|
+
"import": "./dist/vite/importmap-plugin.js",
|
|
44
|
+
"types": "./dist/vite/importmap-plugin.d.ts"
|
|
45
|
+
},
|
|
46
|
+
"./vite/manifest": {
|
|
47
|
+
"import": "./dist/vite/manifest-plugin.js",
|
|
48
|
+
"types": "./dist/vite/manifest-plugin.d.ts"
|
|
49
|
+
},
|
|
50
|
+
"./vite/netlify": {
|
|
51
|
+
"import": "./dist/vite/netlify-plugin.js",
|
|
52
|
+
"types": "./dist/vite/netlify-plugin.d.ts"
|
|
53
|
+
},
|
|
54
|
+
"./vite/service-worker": {
|
|
55
|
+
"import": "./dist/vite/service-worker-plugin.js",
|
|
56
|
+
"types": "./dist/vite/service-worker-plugin.d.ts"
|
|
57
|
+
},
|
|
58
|
+
"./vite/static": {
|
|
59
|
+
"import": "./dist/vite/static-plugin.js",
|
|
60
|
+
"types": "./dist/vite/static-plugin.d.ts"
|
|
61
|
+
},
|
|
22
62
|
"./head": {
|
|
23
63
|
"import": "./dist/head.js"
|
|
24
64
|
},
|
|
@@ -44,10 +84,10 @@
|
|
|
44
84
|
"sharp": "^0.35.3",
|
|
45
85
|
"vite-plugin-wasm": "^3.6.0",
|
|
46
86
|
"@inkandswitch/patchwork-bootloader": "^0.6.2",
|
|
47
|
-
"@inkandswitch/patchwork-
|
|
48
|
-
"@inkandswitch/patchwork-
|
|
49
|
-
"@inkandswitch/patchwork-plugins": "^1.2.
|
|
50
|
-
"@inkandswitch/patchwork-
|
|
87
|
+
"@inkandswitch/patchwork-elements": "^6.0.1",
|
|
88
|
+
"@inkandswitch/patchwork-filesystem": "^0.2.6",
|
|
89
|
+
"@inkandswitch/patchwork-plugins": "^1.2.1",
|
|
90
|
+
"@inkandswitch/patchwork-providers": "^0.5.0"
|
|
51
91
|
},
|
|
52
92
|
"devDependencies": {
|
|
53
93
|
"rollup": "^4.61.1",
|
package/src/site-kit/html.ts
CHANGED
|
@@ -18,6 +18,12 @@ export function escapeHtml(value: string): string {
|
|
|
18
18
|
export function buildHtml(options: PatchworkSiteOptions): string {
|
|
19
19
|
const title = options.title ?? DEFAULT_TITLE;
|
|
20
20
|
const lang = (options.html && options.html.lang) || "en";
|
|
21
|
+
const attributes = Object.entries(
|
|
22
|
+
(options.html && options.html.attributes) || {}
|
|
23
|
+
)
|
|
24
|
+
.filter(([name]) => name !== "lang" && /^[a-z][a-z0-9-]*$/i.test(name))
|
|
25
|
+
.map(([name, value]) => ` ${name}="${escapeHtml(value)}"`)
|
|
26
|
+
.join("");
|
|
21
27
|
const entry = options.entry ?? "/src/main.ts";
|
|
22
28
|
const syncServers = resolveSyncServers(options);
|
|
23
29
|
|
|
@@ -90,11 +96,19 @@ export function buildHtml(options: PatchworkSiteOptions): string {
|
|
|
90
96
|
head.push(options.html.extraHead);
|
|
91
97
|
}
|
|
92
98
|
|
|
99
|
+
const body = [
|
|
100
|
+
`<repo-provider><patchwork-view id="root"></patchwork-view></repo-provider>`,
|
|
101
|
+
`<script type="module" src="${entry}"></script>`,
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
if (options.html && options.html.extraBody) {
|
|
105
|
+
body.push(options.html.extraBody);
|
|
106
|
+
}
|
|
107
|
+
|
|
93
108
|
return `<!doctype html>
|
|
94
|
-
<html lang="${lang}">
|
|
109
|
+
<html lang="${lang}"${attributes}>
|
|
95
110
|
${head.join("\n")}
|
|
96
|
-
|
|
97
|
-
<script type="module" src="${entry}"></script>
|
|
111
|
+
${body.join("\n")}
|
|
98
112
|
</html>
|
|
99
113
|
`;
|
|
100
114
|
}
|
package/src/site-kit/options.ts
CHANGED
|
@@ -19,8 +19,16 @@ export interface PatchworkIconsOptions {
|
|
|
19
19
|
|
|
20
20
|
export interface PatchworkHtmlOptions {
|
|
21
21
|
lang?: string;
|
|
22
|
-
/** Raw HTML appended
|
|
22
|
+
/** Raw HTML appended after the generated head — e.g. extra <link>/<meta> tags. */
|
|
23
23
|
extraHead?: string;
|
|
24
|
+
/** Raw HTML appended after the app root and entry script. */
|
|
25
|
+
extraBody?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Attributes set on the root `<html>` element. How a site states its own
|
|
28
|
+
* configuration to the packages it loads: a package reads the attribute
|
|
29
|
+
* instead of guessing from load order. `lang` stays its own option.
|
|
30
|
+
*/
|
|
31
|
+
attributes?: Record<string, string>;
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
export interface PatchworkNetlifyOptions {
|
|
@@ -43,7 +43,7 @@ function describe(directory: string) {
|
|
|
43
43
|
* revision, the version of patchwork that built it, and every `static` source,
|
|
44
44
|
* plus whatever extra fields the site passes as the option value.
|
|
45
45
|
*/
|
|
46
|
-
export function
|
|
46
|
+
export function buildInfo(
|
|
47
47
|
options: PatchworkVitePluginOptions = {}
|
|
48
48
|
): Plugin | null {
|
|
49
49
|
if (!options.buildInfo) return null;
|
|
@@ -40,7 +40,7 @@ export function buildDefines(
|
|
|
40
40
|
* used to hand-write in its own vite.config.ts. Each is switched off
|
|
41
41
|
* individually via the matching `false` option.
|
|
42
42
|
*/
|
|
43
|
-
export function
|
|
43
|
+
export function config(
|
|
44
44
|
options: PatchworkVitePluginOptions = {}
|
|
45
45
|
): Plugin {
|
|
46
46
|
return {
|
package/src/vite/dev-plugin.ts
CHANGED
|
@@ -71,7 +71,7 @@ function workerContexts(
|
|
|
71
71
|
return contexts;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
export function
|
|
74
|
+
export function dev(options: PatchworkVitePluginOptions = {}): Plugin {
|
|
75
75
|
let serve = false;
|
|
76
76
|
let contexts: Map<string, Promise<esbuild.BuildContext>> | undefined;
|
|
77
77
|
const wasm = new Map(
|
package/src/vite/html-plugin.ts
CHANGED
|
@@ -13,7 +13,7 @@ const GENERATED_PATH = "index.html";
|
|
|
13
13
|
* virtual module: `resolveId` claims the one id we care about, `load`
|
|
14
14
|
* returns the generated string — nothing ever touches disk.
|
|
15
15
|
*/
|
|
16
|
-
export function
|
|
16
|
+
export function html(
|
|
17
17
|
options: PatchworkVitePluginOptions = {}
|
|
18
18
|
): Plugin | null {
|
|
19
19
|
if (options.html === false) return null;
|
package/src/vite/icons.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
|
4
4
|
import { getIcons } from "../site-kit/icons.js";
|
|
5
5
|
|
|
6
6
|
/** Emits the rendered icon PNGs for build, and serves the same buffers for dev. */
|
|
7
|
-
export function
|
|
7
|
+
export function icons(
|
|
8
8
|
options: PatchworkVitePluginOptions = {}
|
|
9
9
|
): Plugin | null {
|
|
10
10
|
if (!options.icons) return null;
|
|
@@ -3,7 +3,7 @@ import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
|
3
3
|
import { buildManifest } from "../site-kit/manifest.js";
|
|
4
4
|
|
|
5
5
|
/** Emits manifest.webmanifest for build and serves it for dev, from the same generated object. */
|
|
6
|
-
export function
|
|
6
|
+
export function manifest(
|
|
7
7
|
options: PatchworkVitePluginOptions = {}
|
|
8
8
|
): Plugin | null {
|
|
9
9
|
if (options.manifest === false) return null;
|
|
@@ -8,7 +8,7 @@ import { buildHeaders, REDIRECTS } from "../site-kit/netlify.js";
|
|
|
8
8
|
* The Link header shares its sync-server/wasm-asset lists with html-plugin
|
|
9
9
|
* so the two never drift out of sync with each other.
|
|
10
10
|
*/
|
|
11
|
-
export function
|
|
11
|
+
export function netlify(
|
|
12
12
|
options: PatchworkVitePluginOptions = {}
|
|
13
13
|
): Plugin | null {
|
|
14
14
|
if (options.netlify === false) return null;
|
|
@@ -2,14 +2,14 @@ import type { Plugin, ServerOptions, PreviewOptions, BuildOptions } from "vite";
|
|
|
2
2
|
|
|
3
3
|
import { importmap } from "./importmap-plugin.js";
|
|
4
4
|
import { serviceworker } from "./service-worker-plugin.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
5
|
+
import { config, wasm } from "./config-plugin.js";
|
|
6
|
+
import { dev } from "./dev-plugin.js";
|
|
7
|
+
import { icons } from "./icons.js";
|
|
8
|
+
import { html } from "./html-plugin.js";
|
|
9
|
+
import { manifest } from "./manifest-plugin.js";
|
|
10
|
+
import { netlify } from "./netlify-plugin.js";
|
|
11
|
+
import { statics, type PatchworkStaticSource } from "./static-plugin.js";
|
|
12
|
+
import { buildInfo } from "./build-info-plugin.js";
|
|
13
13
|
import type { PatchworkSiteOptions } from "../site-kit/options.js";
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -36,19 +36,30 @@ import type { PatchworkSiteOptions } from "../site-kit/options.js";
|
|
|
36
36
|
export default function patchwork(options?: PatchworkVitePluginOptions) {
|
|
37
37
|
return [
|
|
38
38
|
wasm(),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
config(options),
|
|
40
|
+
icons(options),
|
|
41
|
+
html(options),
|
|
42
|
+
manifest(options),
|
|
43
|
+
netlify(options),
|
|
44
44
|
importmap(options),
|
|
45
45
|
serviceworker(),
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
dev(options),
|
|
47
|
+
statics(options),
|
|
48
|
+
buildInfo(options),
|
|
49
49
|
].filter((plugin): plugin is Plugin => plugin != null);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
export { importmap, builtins, devDependencyId } from "./importmap-plugin.js";
|
|
53
|
+
export { serviceworker, workers } from "./service-worker-plugin.js";
|
|
54
|
+
export { config, buildDefines, wasm } from "./config-plugin.js";
|
|
55
|
+
export { dev } from "./dev-plugin.js";
|
|
56
|
+
export { icons } from "./icons.js";
|
|
57
|
+
export { html } from "./html-plugin.js";
|
|
58
|
+
export { manifest } from "./manifest-plugin.js";
|
|
59
|
+
export { netlify } from "./netlify-plugin.js";
|
|
60
|
+
export { statics, resolveStatic } from "./static-plugin.js";
|
|
61
|
+
export { buildInfo } from "./build-info-plugin.js";
|
|
62
|
+
|
|
52
63
|
type Imports = { [name: string]: string };
|
|
53
64
|
export type ImportMap = {
|
|
54
65
|
imports: Imports;
|
|
@@ -22,7 +22,8 @@ import type { PatchworkVitePluginOptions } from "./patchwork-plugin.js";
|
|
|
22
22
|
* `from` is either a package specifier or a path relative to the site root. A
|
|
23
23
|
* package says where its static tree lives with a `"patchwork": {"static":
|
|
24
24
|
* "static-dist"}` field in its own package.json; without one, the whole
|
|
25
|
-
* package directory is mounted
|
|
25
|
+
* package directory is mounted — which is what a package that publishes its
|
|
26
|
+
* static tree as the root of its own tarball wants.
|
|
26
27
|
*/
|
|
27
28
|
export interface PatchworkStaticSource {
|
|
28
29
|
from: string;
|
|
@@ -87,6 +88,22 @@ function packageDirectory(name: string, root: string) {
|
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
/** A package's static tree: the directory it declares, or its root. */
|
|
92
|
+
function staticDirectory(name: string, directory: string) {
|
|
93
|
+
const declared = JSON.parse(
|
|
94
|
+
readFileSync(join(directory, "package.json"), "utf8")
|
|
95
|
+
).patchwork?.static;
|
|
96
|
+
if (!declared) return directory;
|
|
97
|
+
const path = join(directory, declared);
|
|
98
|
+
if (!existsSync(path)) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`[patchwork] ${name} declares "patchwork": {"static": ${JSON.stringify(declared)}}, but ${path} doesn't exist. ` +
|
|
101
|
+
`The field is a path inside the installed package — a package that publishes its static tree as the tarball's own root shouldn't set it at all.`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return path;
|
|
105
|
+
}
|
|
106
|
+
|
|
90
107
|
export function resolveStatic(
|
|
91
108
|
options: PatchworkVitePluginOptions,
|
|
92
109
|
root: string
|
|
@@ -96,14 +113,12 @@ export function resolveStatic(
|
|
|
96
113
|
const isPath = entry.from.startsWith(".") || isAbsolute(entry.from);
|
|
97
114
|
const directory = isPath ? undefined : packageDirectory(entry.from, root);
|
|
98
115
|
const path = directory
|
|
99
|
-
?
|
|
100
|
-
directory,
|
|
101
|
-
JSON.parse(readFileSync(join(directory, "package.json"), "utf8"))
|
|
102
|
-
.patchwork?.static ?? "."
|
|
103
|
-
)
|
|
116
|
+
? staticDirectory(entry.from, directory)
|
|
104
117
|
: resolve(root, entry.from);
|
|
105
118
|
if (!existsSync(path)) {
|
|
106
|
-
throw new Error(
|
|
119
|
+
throw new Error(
|
|
120
|
+
`[patchwork] static source not found: ${entry.from} (${path})`
|
|
121
|
+
);
|
|
107
122
|
}
|
|
108
123
|
const file = statSync(path).isFile();
|
|
109
124
|
const to = entry.to ?? "/";
|
|
@@ -162,7 +177,7 @@ async function files(source: string, directory = source): Promise<string[]> {
|
|
|
162
177
|
* order, and a site keeps its own `modules.json` by listing it before the
|
|
163
178
|
* package it borrows the rest of the packages from.
|
|
164
179
|
*/
|
|
165
|
-
export function
|
|
180
|
+
export function statics(
|
|
166
181
|
options: PatchworkVitePluginOptions = {}
|
|
167
182
|
): Plugin | null {
|
|
168
183
|
if (!options.static?.length) return null;
|