getfilepress 0.1.3 → 0.1.5
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 +9 -7
- package/package.json +100 -102
- package/packages/app/README.md +19 -0
- package/packages/app/localberth-port.ts +32 -0
- package/packages/app/vite.config.ts +6 -3
- package/packages/core/README.md +29 -0
- package/packages/core/src/lib/default-headers.txt +10 -0
- package/packages/core/src/lib/headers.ts +21 -0
- package/packages/core/src/lib/server.ts +1 -0
- package/scripts/copy-path-mounts.mjs +22 -7
- package/scripts/ensure-lease.mjs +24 -0
- package/scripts/filepress.mjs +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> File-based Markdown blogs. No admin UI. No database. Just git.
|
|
4
4
|
|
|
5
|
-
A file-based Markdown blog engine. Posts are plain `.md` files with YAML frontmatter
|
|
5
|
+
A file-based Markdown blog engine. Posts are plain `.md` files with YAML frontmatter. Edit them in the GitHub mobile app, the web editor, or any text editor. There is no admin UI, no database, and no server at runtime: a static build produces HTML you can host anywhere (for example Cloudflare Pages).
|
|
6
6
|
|
|
7
7
|
| | |
|
|
8
8
|
| --- | --- |
|
|
@@ -73,6 +73,8 @@ pnpm build:www # → sites/getfilepress/build/
|
|
|
73
73
|
pnpm ship # build + Wrangler Pages deploy (project: getfilepress)
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
Two `filepress dev` processes share Vite **5173** unless you pin the port. With [LocalBerth](https://www.npmjs.com/package/localberth) 0.2+, `filepress dev` reads a named lease. Claim once; see [docs/LOCALBERTH.md](docs/LOCALBERTH.md).
|
|
77
|
+
|
|
76
78
|
## Site configuration
|
|
77
79
|
|
|
78
80
|
```ts
|
|
@@ -108,7 +110,7 @@ export default defineFilepressConfig({
|
|
|
108
110
|
|
|
109
111
|
### Path mounts
|
|
110
112
|
|
|
111
|
-
Attach a site-owned HTML/CSS/JS tree at a URL prefix. FilePress copies it into `build/` after the Kit build and serves it in `filepress dev`. It does **not** parse Markdown or inject Essay chrome into the mount
|
|
113
|
+
Attach a site-owned HTML/CSS/JS tree at a URL prefix. FilePress copies it into `build/` after the Kit build and serves it in `filepress dev`. It does **not** parse Markdown or inject Essay chrome into the mount. The site owns the shell (for example a docs sidebar).
|
|
112
114
|
|
|
113
115
|
```ts
|
|
114
116
|
paths: [
|
|
@@ -128,8 +130,8 @@ variables and structural classes without forking the app.
|
|
|
128
130
|
|
|
129
131
|
In local `filepress dev` / `pnpm dev`, **Genie Mode** (floating FAB) is a design cockpit:
|
|
130
132
|
steers, Openverse / uploads, live inspire URLs, optional Ollama refine, and
|
|
131
|
-
`lede` / `tagline` / `logo` config patches
|
|
132
|
-
|
|
133
|
+
`lede` / `tagline` / `logo` config patches. Experiments live under `.filepress-genie/`.
|
|
134
|
+
Activate writes `theme.css`, `static/`, and config. Dev-only; absent from
|
|
133
135
|
`preview` and production builds. See [`docs/GENIE_MODE_SPEC.md`](docs/GENIE_MODE_SPEC.md)
|
|
134
136
|
and [getfilepress.com/genie](https://getfilepress.com/genie).
|
|
135
137
|
|
|
@@ -182,7 +184,7 @@ Body content in **Markdown**.
|
|
|
182
184
|
|
|
183
185
|
## Deploy
|
|
184
186
|
|
|
185
|
-
`filepress build` emits a static `build/` folder
|
|
187
|
+
`filepress build` emits a static `build/` folder. No Node server in production.
|
|
186
188
|
|
|
187
189
|
**Happy path: [Cloudflare Pages](https://pages.cloudflare.com/)** (git-connected site repo or Wrangler upload).
|
|
188
190
|
|
|
@@ -192,9 +194,9 @@ Body content in **Markdown**.
|
|
|
192
194
|
| Output directory | `build` |
|
|
193
195
|
| Node | 20+ |
|
|
194
196
|
|
|
195
|
-
Pin the engine in the site `package.json` (`"getfilepress": "^0.1.
|
|
197
|
+
Pin the engine in the site `package.json` (`"getfilepress": "^0.1.3"` or `github:Catalyst-Forge-LLC/filepress#v0.1.3`). Do not use `link:` in CI. Set config `url` to the live origin.
|
|
196
198
|
|
|
197
|
-
Any other static host works the same way: publish `build/` as the web root.
|
|
199
|
+
Any other static host works the same way: publish `build/` as the web root. The build also writes a `_headers` file (HSTS, no framing, no wildcard CORS) for Cloudflare Pages; override it with `static/_headers`.
|
|
198
200
|
|
|
199
201
|
Full notes (including an agent checklist): [`docs/DEPLOY.md`](docs/DEPLOY.md) · product page: [getfilepress.com/deploy](https://getfilepress.com/deploy).
|
|
200
202
|
|
package/package.json
CHANGED
|
@@ -1,103 +1,101 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
}
|
|
2
|
+
"name": "getfilepress",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "FilePress — file-based Markdown blog engine. Link this package from a content-only site (config + posts), then run `filepress build`.",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://getfilepress.com",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/Catalyst-Forge-LLC/filepress.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/Catalyst-Forge-LLC/filepress/issues"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"filepress": "./scripts/filepress.mjs",
|
|
18
|
+
"getfilepress": "./scripts/filepress.mjs"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./packages/core/src/lib/index.ts",
|
|
23
|
+
"svelte": "./packages/core/src/lib/index.ts",
|
|
24
|
+
"default": "./packages/core/src/lib/index.ts"
|
|
25
|
+
},
|
|
26
|
+
"./server": {
|
|
27
|
+
"types": "./packages/core/src/lib/server.ts",
|
|
28
|
+
"default": "./packages/core/src/lib/server.ts"
|
|
29
|
+
},
|
|
30
|
+
"./theme": {
|
|
31
|
+
"default": "./packages/core/src/lib/theme.ts"
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"scripts/filepress.mjs",
|
|
37
|
+
"scripts/copy-path-mounts.mjs",
|
|
38
|
+
"scripts/create-site.mjs",
|
|
39
|
+
"scripts/ensure-lease.mjs",
|
|
40
|
+
"scripts/postinstall.mjs",
|
|
41
|
+
"scripts/link-embedded-packages.mjs",
|
|
42
|
+
"packages/core",
|
|
43
|
+
"packages/app",
|
|
44
|
+
"packages/import",
|
|
45
|
+
"pnpm-workspace.yaml",
|
|
46
|
+
"README.md",
|
|
47
|
+
"LICENSE"
|
|
48
|
+
],
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@fontsource-variable/inter": "^5.2.8",
|
|
51
|
+
"@fontsource-variable/newsreader": "^5.2.10",
|
|
52
|
+
"@sveltejs/adapter-static": "^3.0.10",
|
|
53
|
+
"@sveltejs/kit": "^2.63.0",
|
|
54
|
+
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
55
|
+
"@types/turndown": "^5.0.5",
|
|
56
|
+
"fast-xml-parser": "^5.2.5",
|
|
57
|
+
"gray-matter": "^4.0.3",
|
|
58
|
+
"highlight.js": "^11.11.1",
|
|
59
|
+
"linkedom": "^0.18.12",
|
|
60
|
+
"ollanet": "^0.4.0",
|
|
61
|
+
"rehype-autolink-headings": "^7.1.0",
|
|
62
|
+
"rehype-highlight": "^7.0.2",
|
|
63
|
+
"rehype-raw": "^7.0.0",
|
|
64
|
+
"rehype-slug": "^6.0.0",
|
|
65
|
+
"rehype-stringify": "^10.0.1",
|
|
66
|
+
"remark-gfm": "^4.0.1",
|
|
67
|
+
"remark-parse": "^11.0.0",
|
|
68
|
+
"remark-rehype": "^11.1.2",
|
|
69
|
+
"sirv-cli": "^3.0.1",
|
|
70
|
+
"svelte": "^5.56.1",
|
|
71
|
+
"svelte-check": "^4.6.0",
|
|
72
|
+
"tsx": "^4.20.5",
|
|
73
|
+
"turndown": "^7.2.1",
|
|
74
|
+
"typescript": "^6.0.3",
|
|
75
|
+
"unified": "^11.0.5",
|
|
76
|
+
"vite": "^8.0.16"
|
|
77
|
+
},
|
|
78
|
+
"engines": {
|
|
79
|
+
"node": ">=20"
|
|
80
|
+
},
|
|
81
|
+
"devDependencies": {
|
|
82
|
+
"wrangler": "^4.120.1"
|
|
83
|
+
},
|
|
84
|
+
"scripts": {
|
|
85
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
86
|
+
"filepress": "node scripts/filepress.mjs",
|
|
87
|
+
"test": "pnpm --filter @filepress/core test && pnpm --filter @filepress/import test && pnpm --filter @filepress/app test",
|
|
88
|
+
"check": "pnpm filepress check --site demo",
|
|
89
|
+
"build": "pnpm filepress build --site demo",
|
|
90
|
+
"build:demo": "pnpm filepress build --site demo",
|
|
91
|
+
"build:www": "pnpm filepress build --site getfilepress",
|
|
92
|
+
"ship": "pnpm build:www && wrangler pages deploy sites/getfilepress/build --project-name getfilepress",
|
|
93
|
+
"deploy:www": "pnpm ship",
|
|
94
|
+
"dev": "node scripts/ensure-lease.mjs demo 5179 && pnpm filepress dev --site demo",
|
|
95
|
+
"dev:demo": "node scripts/ensure-lease.mjs demo 5179 && pnpm filepress dev --site demo",
|
|
96
|
+
"dev:www": "node scripts/ensure-lease.mjs getfilepress 5180 && pnpm filepress dev --site getfilepress",
|
|
97
|
+
"create-site": "node scripts/create-site.mjs",
|
|
98
|
+
"import": "node scripts/filepress.mjs import",
|
|
99
|
+
"pack:smoke": "node scripts/pack-smoke.mjs"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @filepress/app
|
|
2
|
+
|
|
3
|
+
The only SvelteKit application in the filepress monorepo. All routes, layouts, and
|
|
4
|
+
Kit wiring live here. Content sites under [`../../sites`](../../sites) provide:
|
|
5
|
+
|
|
6
|
+
- `filepress.config.ts` — identity
|
|
7
|
+
- `posts/` — Markdown
|
|
8
|
+
- `static/` — favicon, images (optional)
|
|
9
|
+
|
|
10
|
+
## Run against a site
|
|
11
|
+
|
|
12
|
+
From the repo root (do not run vite directly without `FILEPRESS_SITE_ROOT`):
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm filepress dev --site demo
|
|
16
|
+
pnpm filepress build --site demo
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Build output is written to `sites/<name>/build/`.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
/** `localberth get <name>` — undefined if the CLI or lease is missing. */
|
|
6
|
+
export function localberthGet(name: string): number | undefined {
|
|
7
|
+
const r = spawnSync('localberth', ['get', name], {
|
|
8
|
+
encoding: 'utf8',
|
|
9
|
+
timeout: 5000,
|
|
10
|
+
windowsHide: true,
|
|
11
|
+
shell: process.platform === 'win32'
|
|
12
|
+
});
|
|
13
|
+
if (r.status !== 0) return undefined;
|
|
14
|
+
const n = Number((r.stdout || '').trim());
|
|
15
|
+
return Number.isInteger(n) && n > 0 && n <= 65535 ? n : undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** FILEPRESS_LEASE, then site package.json name, then the site folder name. */
|
|
19
|
+
export function filepressLeaseName(siteRoot: string): string {
|
|
20
|
+
const fromEnv = process.env.FILEPRESS_LEASE?.trim();
|
|
21
|
+
if (fromEnv) return fromEnv;
|
|
22
|
+
const pkgPath = join(siteRoot, 'package.json');
|
|
23
|
+
if (existsSync(pkgPath)) {
|
|
24
|
+
try {
|
|
25
|
+
const name = JSON.parse(readFileSync(pkgPath, 'utf8')).name;
|
|
26
|
+
if (typeof name === 'string' && name.trim()) return name.trim();
|
|
27
|
+
} catch {
|
|
28
|
+
/* fall through */
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return siteRoot.replace(/[/\\]+$/, '').split(/[/\\]/).pop() || 'filepress';
|
|
32
|
+
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from './vite-plugin-critical-theme.ts';
|
|
11
11
|
import { geniePlugin } from './vite-plugin-genie.ts';
|
|
12
12
|
import { pathMountsPlugin } from './vite-plugin-path-mounts.ts';
|
|
13
|
+
import { filepressLeaseName, localberthGet } from './localberth-port.ts';
|
|
13
14
|
import type { PathMount } from '../core/src/lib/paths-shared.ts';
|
|
14
15
|
|
|
15
16
|
const appRoot = dirname(fileURLToPath(import.meta.url));
|
|
@@ -84,9 +85,11 @@ async function loadPathMounts(): Promise<PathMount[]> {
|
|
|
84
85
|
|
|
85
86
|
function resolvePort(): number | undefined {
|
|
86
87
|
const raw = process.env.FILEPRESS_PORT?.trim();
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
if (raw) {
|
|
89
|
+
const n = Number(raw);
|
|
90
|
+
return Number.isInteger(n) && n > 0 && n <= 65535 ? n : undefined;
|
|
91
|
+
}
|
|
92
|
+
return localberthGet(filepressLeaseName(siteRoot));
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
const fixedPort = resolvePort();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @filepress/core
|
|
2
|
+
|
|
3
|
+
The reusable filepress engine. Sites under [`../../sites`](../../sites) depend on
|
|
4
|
+
it (via `workspace:*` in this monorepo) and provide their own SvelteKit routes,
|
|
5
|
+
content, and `filepress.config.ts`.
|
|
6
|
+
|
|
7
|
+
## Entry points
|
|
8
|
+
|
|
9
|
+
- `@filepress/core` — client-safe: `PostCard`, `PostIndex`, `Newsletter`,
|
|
10
|
+
`SiteHeader`, `SiteFooter`, `defineFilepressConfig`, `absoluteUrl`,
|
|
11
|
+
`formatDate`, and shared types.
|
|
12
|
+
- `@filepress/core/server` — server-only (filesystem access): `createContent`,
|
|
13
|
+
`renderMarkdown`, `buildRssXml` / `buildSitemapXml` / `buildRobotsTxt`, and the
|
|
14
|
+
content-parsing primitives. Import only from `+page.server.ts`, `+server.ts`,
|
|
15
|
+
or `*.server.ts` modules.
|
|
16
|
+
- `@filepress/core/theme` — self-hosted fonts + the Essay theme CSS. Import once
|
|
17
|
+
from a site's root layout.
|
|
18
|
+
|
|
19
|
+
## Why routes live in the site
|
|
20
|
+
|
|
21
|
+
SvelteKit's router is per-project, so each site owns its `src/routes/`. Those
|
|
22
|
+
route files stay thin: they call `createContent(...)` + core builders and render
|
|
23
|
+
core components. `scripts/create-site.mjs` scaffolds them.
|
|
24
|
+
|
|
25
|
+
## Testing
|
|
26
|
+
|
|
27
|
+
`pnpm --filter @filepress/core test` runs the unit tests over the pure parsing
|
|
28
|
+
and figure-transform logic. Type-checking of the whole library happens through
|
|
29
|
+
each site's `svelte-check`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Emitted by FilePress. Override by adding static/_headers in the site.
|
|
2
|
+
# Cloudflare Pages and Netlify read this file; it is not served as a page.
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Strict-Transport-Security: max-age=31536000
|
|
6
|
+
Content-Security-Policy: frame-ancestors 'none'
|
|
7
|
+
X-Frame-Options: DENY
|
|
8
|
+
X-Content-Type-Options: nosniff
|
|
9
|
+
Referrer-Policy: strict-origin-when-cross-origin
|
|
10
|
+
! Access-Control-Allow-Origin
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Cloudflare Pages / Netlify `_headers` for a FilePress build.
|
|
3
|
+
* A site-owned `static/_headers` wins: adapter-static copies it first, and
|
|
4
|
+
* we refuse to overwrite `build/_headers`.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
|
|
10
|
+
const templatePath = join(dirname(fileURLToPath(import.meta.url)), 'default-headers.txt');
|
|
11
|
+
|
|
12
|
+
export function defaultSecurityHeaders(): string {
|
|
13
|
+
return readFileSync(templatePath, 'utf8');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function writeBuildHeaders(buildDir: string): 'wrote' | 'kept' {
|
|
17
|
+
const dest = join(buildDir, '_headers');
|
|
18
|
+
if (existsSync(dest)) return 'kept';
|
|
19
|
+
writeFileSync(dest, defaultSecurityHeaders());
|
|
20
|
+
return 'wrote';
|
|
21
|
+
}
|
|
@@ -1,21 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Post-`vite build` steps for a FilePress site:
|
|
3
|
+
* 1. Write default `build/_headers` unless the site already provided one
|
|
4
|
+
* 2. Copy `paths` mounts (from `.filepress/path-mounts.json`)
|
|
4
5
|
*
|
|
5
6
|
* Usage: node scripts/copy-path-mounts.mjs <siteRoot>
|
|
6
7
|
*/
|
|
7
|
-
import { cpSync, existsSync, mkdirSync, readFileSync, statSync } from 'node:fs';
|
|
8
|
-
import { join, resolve } from 'node:path';
|
|
8
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { dirname, join, resolve } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
9
11
|
|
|
10
12
|
const siteRoot = resolve(process.argv[2] ?? '');
|
|
11
13
|
const buildDir = join(siteRoot, 'build');
|
|
12
14
|
const cachePath = join(siteRoot, '.filepress', 'path-mounts.json');
|
|
15
|
+
const headersTemplate = join(
|
|
16
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
17
|
+
'../packages/core/src/lib/default-headers.txt'
|
|
18
|
+
);
|
|
13
19
|
|
|
14
|
-
if (!existsSync(
|
|
20
|
+
if (!existsSync(buildDir)) {
|
|
21
|
+
console.warn(`filepress: post-build skipped — build dir missing (${buildDir})`);
|
|
15
22
|
process.exit(0);
|
|
16
23
|
}
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
|
|
25
|
+
const headersDest = join(buildDir, '_headers');
|
|
26
|
+
if (existsSync(headersDest)) {
|
|
27
|
+
console.log('filepress: kept site _headers');
|
|
28
|
+
} else if (existsSync(headersTemplate)) {
|
|
29
|
+
writeFileSync(headersDest, readFileSync(headersTemplate, 'utf8'));
|
|
30
|
+
console.log('filepress: wrote default _headers');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!existsSync(cachePath)) {
|
|
19
34
|
process.exit(0);
|
|
20
35
|
}
|
|
21
36
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Idempotent LocalBerth claim for FilePress (and sibling) dev ports.
|
|
4
|
+
* Usage: node scripts/ensure-lease.mjs <name> <port>
|
|
5
|
+
* Missing CLI → one line, exit 0. Existing lease → keep it (do not rewrite).
|
|
6
|
+
*/
|
|
7
|
+
import { spawnSync } from 'node:child_process';
|
|
8
|
+
|
|
9
|
+
const name = process.argv[2];
|
|
10
|
+
const port = process.argv[3];
|
|
11
|
+
if (!name || !port) {
|
|
12
|
+
console.error('usage: node scripts/ensure-lease.mjs <name> <port>');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const opt = { encoding: 'utf8', timeout: 8000, windowsHide: true, shell: process.platform === 'win32' };
|
|
17
|
+
const got = spawnSync('localberth', ['get', name], { ...opt, stdio: ['ignore', 'pipe', 'ignore'] });
|
|
18
|
+
if (got.status === 0 && String(got.stdout || '').trim()) {
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
const claim = spawnSync('localberth', ['claim', name, '--port', port], { ...opt, stdio: 'inherit' });
|
|
22
|
+
if (claim.error || claim.status !== 0) {
|
|
23
|
+
console.warn(`localberth: skip claim ${name} (install the CLI to pin this site to ${port})`);
|
|
24
|
+
}
|
package/scripts/filepress.mjs
CHANGED
|
File without changes
|