edgepress 2026.9.3 → 2026.9.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 +6 -6
- package/content/pages/quick-start/en.md +11 -5
- package/content/pages/quick-start/zh-cn.md +11 -5
- package/content/posts/2026-09-25-edgepress-release-2026-9-4/en.md +26 -0
- package/content/posts/2026-09-25-edgepress-release-2026-9-4/zh-cn.md +26 -0
- package/content/posts/2026-09-25-edgepress-release-2026-9-5/en.md +17 -0
- package/content/posts/2026-09-25-edgepress-release-2026-9-5/zh-cn.md +17 -0
- package/package.json +1 -2
- package/project-compatibility.json +17 -3
- package/src/cli.js +29 -4
- package/src/page-check.js +20 -58
- package/src/preview.js +1 -1
- package/src/report-visuals.js +50 -56
- package/wrangler.jsonc +1 -1
- package/templates/gitignore +0 -6
- package/templates/site-readme.md +0 -20
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://deploy.workers.cloudflare.com/?url=https://github.com/jsw-teams/edgepress)
|
|
4
4
|
|
|
5
|
-
The button
|
|
5
|
+
The button creates a copy of this repository in your GitHub account and a new Worker in your Cloudflare account. It is for creating a separate site, not updating an existing one. Choose unused destination repository and Worker names during setup. If `edgepress` already exists, choose a different name such as `my-edgepress-site`; to update an existing deployment, use that repository's connected Workers Builds integration instead of clicking the button again.
|
|
6
6
|
|
|
7
7
|
EdgePress builds static websites for Cloudflare Workers. Write posts in Markdown, compose pages from editable rows and elements, choose a shared theme, and build the site into dist/.
|
|
8
8
|
|
|
@@ -48,23 +48,23 @@ Posts under content/posts/ use the Markdown renderer. Themes own shared head, na
|
|
|
48
48
|
- edgepress init: scaffold a new site in a project directory.
|
|
49
49
|
- edgepress new "Article title": create a Markdown post.
|
|
50
50
|
- edgepress build and edgepress generate: run the same generator and write static files to dist/ for Cloudflare Workers or static hosting.
|
|
51
|
-
- edgepress server: start live local preview, rebuild on source changes, and refresh the audit report.
|
|
52
|
-
- edgepress check: build,
|
|
51
|
+
- edgepress server: start live local preview, rebuild on source changes, and refresh the PDF audit report.
|
|
52
|
+
- edgepress check: build, audit accessibility, agent-friendliness, and Markdown rendering, capture post/page desktop and mobile screenshots temporarily, and write only the PDF report under tools/.
|
|
53
53
|
- edgepress doctor: inspect runtime and Worker compatibility.
|
|
54
54
|
- edgepress theme list and edgepress theme use <name>: inspect or select an installed theme.
|
|
55
55
|
- edgepress theme install <npm-package>[@version]: install a theme package from npm without running its install scripts.
|
|
56
56
|
- edgepress theme create <name>: make an empty, accessible HTML theme skeleton with editable partials and a blank stylesheet.
|
|
57
57
|
- edgepress secret put BACKEND_TOKEN: store the backend token in Wrangler.
|
|
58
58
|
- edgepress deploy: build and deploy to Cloudflare Workers.
|
|
59
|
-
- Connect a GitHub repository to Cloudflare Workers Builds to deploy on pushes to main.
|
|
59
|
+
- Connect a GitHub repository to Cloudflare Workers Builds to deploy on pushes to main. Set root directory `/`, build command `npm run build`, deploy command `npx wrangler deploy`, and leave build variables empty. See the [Cloudflare build troubleshooting guide](content/pages/quick-start/) if initialization stalls before commands run.
|
|
60
60
|
- edgepress clean: remove generated site and report files.
|
|
61
61
|
- edgepress iterate: create a report-only maintenance plan.
|
|
62
62
|
- edgepress security: check dependency advisories.
|
|
63
63
|
|
|
64
|
-
The
|
|
64
|
+
The only persisted page-audit report is the accessible PDF at tools/page-check.pdf. Desktop and mobile screenshots are embedded in the PDF and removed from temporary storage afterward. Automated checks do not replace manual accessibility or legal review.
|
|
65
65
|
|
|
66
66
|
The header search page filters Markdown posts from the generated local search index; it does not send search queries to an external service. The first post, “EdgePress and Markdown: a complete writing guide,” documents and verifies the supported Markdown syntax in English and Chinese.
|
|
67
67
|
|
|
68
68
|
Project guides are published from content/pages/: project introduction, quick start, theme development, plugin development, and privacy policy. The privacy policy intentionally reports that the starter site still needs a real site URL, operator name, and privacy contact before publication.
|
|
69
69
|
|
|
70
|
-
Version 2026.9.
|
|
70
|
+
Version 2026.9.5 records the fifth requested release update for September 2026. It is available as the `edgepress` npm package. See the [request 1 notes](content/posts/2026-09-24-edgepress-release-2026-9-1/), [request 2 notes](content/posts/2026-09-25-edgepress-release-2026-9-2/), [request 3 notes](content/posts/2026-09-25-edgepress-release-2026-9-3/), [request 4 notes](content/posts/2026-09-25-edgepress-release-2026-9-4/), and [request 5 notes](content/posts/2026-09-25-edgepress-release-2026-9-5/).
|
|
@@ -10,7 +10,7 @@ blocks:
|
|
|
10
10
|
- type: hero
|
|
11
11
|
eyebrow: Start here
|
|
12
12
|
title: Set up the project and open the live preview.
|
|
13
|
-
text: Use the edgepress command after installing project dependencies. Local preview rebuilds changed source files and refreshes the accessibility and agent-friendliness report.
|
|
13
|
+
text: Use the edgepress command after installing project dependencies. Local preview rebuilds changed source files and refreshes the PDF accessibility and agent-friendliness report.
|
|
14
14
|
- columns: 1
|
|
15
15
|
cells:
|
|
16
16
|
-
|
|
@@ -76,7 +76,7 @@ blocks:
|
|
|
76
76
|
- Edit site title, description, canonical URL, agent SEO, site navigation, footer text, and privacy controller details in config.yml. Theme colors live in theme CSS.
|
|
77
77
|
- Change the selected theme with edgepress theme list and edgepress theme use <theme-name>. Theme paths are stored in edgepress.config.mjs.
|
|
78
78
|
- Install a theme package with edgepress theme install <npm-package> or start with a blank theme using edgepress theme create <name>.
|
|
79
|
-
- edgepress server starts a local Wrangler server, watches source files, rebuilds changed pages, reloads the browser, and
|
|
79
|
+
- edgepress server starts a local Wrangler server, watches source files, rebuilds changed pages, reloads the browser, and refreshes tools/page-check.pdf. Screenshots are embedded in the PDF and temporary files are removed after generation.
|
|
80
80
|
- type: code
|
|
81
81
|
title: Build, inspect, and deploy
|
|
82
82
|
language: sh
|
|
@@ -85,14 +85,16 @@ blocks:
|
|
|
85
85
|
edgepress doctor
|
|
86
86
|
edgepress deploy
|
|
87
87
|
- type: text
|
|
88
|
-
text: Compatibility checks read the Node.js baseline, Worker entry, and compatibility date from project-compatibility.json and wrangler.jsonc.
|
|
88
|
+
text: Compatibility checks read the Node.js baseline, Worker entry, and compatibility date from project-compatibility.json and wrangler.jsonc. Review the PDF report before deploying.
|
|
89
89
|
- type: section
|
|
90
90
|
title: Publish the source on GitHub
|
|
91
91
|
blocks:
|
|
92
92
|
- type: text
|
|
93
93
|
paragraphs:
|
|
94
94
|
- Create an empty repository on GitHub, then push the EdgePress source. In the Cloudflare dashboard, create a Worker and connect that repository with Workers Builds. Choose main as the production branch. Set a unique Worker name in wrangler.jsonc before deployment.
|
|
95
|
-
-
|
|
95
|
+
- For this repository, set Workers Builds root directory to /, build command to npm run build, and deploy command to npx wrangler deploy. No build variables are required. The build command generates dist/ before Wrangler publishes the Worker; dist/ stays out of Git.
|
|
96
|
+
- The Deploy to Cloudflare button in the GitHub README creates a new GitHub repository copy and a new Worker. During setup, choose unused names for both. If a repository or Worker named edgepress already exists, choose a different name. To update an existing Worker, use its existing repository and Workers Builds connection; the button does not attach to or update an existing project.
|
|
97
|
+
- If the log remains at Initializing build environment before cloning the repository or running commands, verify that the Cloudflare Workers and Pages GitHub App still has access to this repository. Reconnect the repository or reinstall and reauthorize the app, then retry. Check that the selected Cloudflare API token is still valid; Workers Builds can create a token automatically, and stale tokens must be replaced in Build settings. This stage runs before the project build command.
|
|
96
98
|
- type: code
|
|
97
99
|
title: Upload the source repository
|
|
98
100
|
language: sh
|
|
@@ -108,10 +110,14 @@ blocks:
|
|
|
108
110
|
- type: link-list
|
|
109
111
|
title: Deployment references
|
|
110
112
|
items:
|
|
111
|
-
- label: Connect
|
|
113
|
+
- label: Connect or reauthorize the GitHub integration
|
|
112
114
|
url: https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/github-integration/
|
|
113
115
|
- label: Configure Workers Builds commands
|
|
114
116
|
url: https://developers.cloudflare.com/workers/ci-cd/builds/configuration/
|
|
117
|
+
- label: Troubleshoot Workers Builds
|
|
118
|
+
url: https://developers.cloudflare.com/workers/ci-cd/builds/troubleshoot/
|
|
119
|
+
- label: Deploy button behavior and setup
|
|
120
|
+
url: https://developers.cloudflare.com/workers/platform/deploy-buttons/
|
|
115
121
|
- type: section
|
|
116
122
|
title: Generate files for OpenResty or Nginx
|
|
117
123
|
blocks:
|
|
@@ -10,7 +10,7 @@ blocks:
|
|
|
10
10
|
- type: hero
|
|
11
11
|
eyebrow: 从这里开始
|
|
12
12
|
title: 配置项目并打开实时预览。
|
|
13
|
-
text: 安装项目依赖后使用 edgepress 命令。本地预览会在源文件变更后自动构建,并刷新无障碍化和 agent
|
|
13
|
+
text: 安装项目依赖后使用 edgepress 命令。本地预览会在源文件变更后自动构建,并刷新无障碍化和 agent 友好度 PDF 报告。
|
|
14
14
|
- columns: 1
|
|
15
15
|
cells:
|
|
16
16
|
-
|
|
@@ -76,7 +76,7 @@ blocks:
|
|
|
76
76
|
- 在 config.yml 中编辑站点标题、简介、规范 URL、agent SEO、导航、页脚文字和隐私运营者信息。主题配色保存在各自主题的 CSS 中。
|
|
77
77
|
- 使用 edgepress theme list 查看主题,使用 edgepress theme use <主题名称> 切换主题。主题路径保存在 edgepress.config.mjs 中。
|
|
78
78
|
- 使用 edgepress theme install <npm-package> 安装主题包,或使用 edgepress theme create <名称> 创建空白主题。
|
|
79
|
-
- edgepress server 会启动本地 Wrangler 服务、监视源文件、重新构建变更页面、刷新浏览器,并更新 tools/page-check.
|
|
79
|
+
- edgepress server 会启动本地 Wrangler 服务、监视源文件、重新构建变更页面、刷新浏览器,并更新 tools/page-check.pdf。截图会嵌入 PDF,生成后会清理临时文件。
|
|
80
80
|
- type: code
|
|
81
81
|
title: 构建、检查和部署
|
|
82
82
|
language: sh
|
|
@@ -85,14 +85,16 @@ blocks:
|
|
|
85
85
|
edgepress doctor
|
|
86
86
|
edgepress deploy
|
|
87
87
|
- type: text
|
|
88
|
-
text: 兼容性检查会读取 project-compatibility.json 和 wrangler.jsonc 中的 Node.js 基线、Worker
|
|
88
|
+
text: 兼容性检查会读取 project-compatibility.json 和 wrangler.jsonc 中的 Node.js 基线、Worker 入口和兼容日期。部署前请查看 PDF 报告。
|
|
89
89
|
- type: section
|
|
90
90
|
title: 将源代码上传到 GitHub
|
|
91
91
|
blocks:
|
|
92
92
|
- type: text
|
|
93
93
|
paragraphs:
|
|
94
94
|
- 在 GitHub 创建空仓库并推送 EdgePress 源代码。然后在 Cloudflare 控制台创建 Worker,并通过 Workers Builds 连接该仓库,选择 main 作为生产分支。部署前请在 wrangler.jsonc 中设置唯一的 Worker 名称。
|
|
95
|
-
- Workers Builds
|
|
95
|
+
- 此仓库的 Workers Builds 设置为:根目录 /、构建命令 npm run build、部署命令 npx wrangler deploy。无需添加构建变量。构建命令会先生成 dist/,再由 Wrangler 发布 Worker;dist/ 不会提交到 Git。
|
|
96
|
+
- GitHub README 中的一键部署按钮会在你的 GitHub 账户创建一份新仓库副本,并在 Cloudflare 创建一个新 Worker。设置时请为目标仓库和 Worker 选择未占用的名称。如果 `edgepress` 已存在,请改用其他名称。要更新已有 Worker,请继续使用它已连接的仓库和 Workers Builds;按钮不会连接或更新已有项目。
|
|
97
|
+
- 如果日志在克隆仓库或运行命令前一直停留在 Initializing build environment,请检查 Cloudflare Workers and Pages GitHub App 是否仍有此仓库的访问权限。重新连接仓库,或重新安装并授权该 App 后再试。还需确认所选 Cloudflare API Token 仍有效;Workers Builds 可以自动创建 Token,如果已选 Token 失效,需要在 Build 设置中替换。此阶段尚未运行项目构建命令。
|
|
96
98
|
- type: code
|
|
97
99
|
title: 推送源代码仓库
|
|
98
100
|
language: sh
|
|
@@ -108,10 +110,14 @@ blocks:
|
|
|
108
110
|
- type: link-list
|
|
109
111
|
title: 部署参考
|
|
110
112
|
items:
|
|
111
|
-
- label:
|
|
113
|
+
- label: 连接或重新授权 GitHub 集成
|
|
112
114
|
url: https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/github-integration/
|
|
113
115
|
- label: 配置 Workers Builds 命令
|
|
114
116
|
url: https://developers.cloudflare.com/workers/ci-cd/builds/configuration/
|
|
117
|
+
- label: 排查 Workers Builds
|
|
118
|
+
url: https://developers.cloudflare.com/workers/ci-cd/builds/troubleshoot/
|
|
119
|
+
- label: 一键部署按钮的工作方式
|
|
120
|
+
url: https://developers.cloudflare.com/workers/platform/deploy-buttons/
|
|
115
121
|
- type: section
|
|
116
122
|
title: 为 OpenResty 或 Nginx 生成静态文件
|
|
117
123
|
blocks:
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "EdgePress September 2026 update: request 4"
|
|
3
|
+
date: 2026-09-25
|
|
4
|
+
lang: en
|
|
5
|
+
slug: edgepress-release-2026-9-4
|
|
6
|
+
tags:
|
|
7
|
+
- release
|
|
8
|
+
- reports
|
|
9
|
+
- cloudflare
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
This is the fourth requested EdgePress update for September 2026.
|
|
13
|
+
|
|
14
|
+
## Keep the audit report in one PDF
|
|
15
|
+
|
|
16
|
+
`edgepress check` and `edgepress server` now persist only `tools/page-check.pdf`. Desktop and mobile screenshots are embedded in the PDF; temporary HTML and screenshot files are removed after generation.
|
|
17
|
+
|
|
18
|
+
## Remove the templates directory
|
|
19
|
+
|
|
20
|
+
`edgepress init` now writes its generated README and `.gitignore` directly from the CLI package. The source and npm package no longer include a `templates/` directory.
|
|
21
|
+
|
|
22
|
+
## Cloudflare Workers Builds setup
|
|
23
|
+
|
|
24
|
+
The quick-start guide records the repository settings: root directory `/`, build command `npm run build`, deploy command `npx wrangler deploy`, and no required build variables. It also explains that a build stuck at `Initializing build environment` has not run the project build command yet; reconnect the GitHub integration or replace a stale Cloudflare build API token before retrying.
|
|
25
|
+
|
|
26
|
+
Wrangler requires `compatibility_date` for this Worker, so the project pins it to the first day of the month: `2026-09-01`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: EdgePress 2026 年 9 月更新:第 4 次需求
|
|
3
|
+
date: 2026-09-25
|
|
4
|
+
lang: zh-CN
|
|
5
|
+
slug: edgepress-release-2026-9-4
|
|
6
|
+
tags:
|
|
7
|
+
- 发布
|
|
8
|
+
- 报告
|
|
9
|
+
- Cloudflare
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
这是 EdgePress 在 2026 年 9 月针对第 4 次需求的更新。
|
|
13
|
+
|
|
14
|
+
## 审核报告只保留 PDF
|
|
15
|
+
|
|
16
|
+
`edgepress check` 和 `edgepress server` 现在只在 `tools/page-check.pdf` 保存报告。桌面和移动端截图会嵌入 PDF,临时 HTML 和截图文件会在生成后清理。
|
|
17
|
+
|
|
18
|
+
## 移除 templates 目录
|
|
19
|
+
|
|
20
|
+
`edgepress init` 现在由 CLI 包直接写入新项目的 README 和 `.gitignore`。源码与 npm 包不再包含 `templates/` 目录。
|
|
21
|
+
|
|
22
|
+
## Cloudflare Workers Builds 设置
|
|
23
|
+
|
|
24
|
+
快速入门指南现已记录本仓库设置:根目录 `/`、构建命令 `npm run build`、部署命令 `npx wrangler deploy`,且无需配置构建变量。指南也说明,构建若停留在 `Initializing build environment`,表示项目构建命令还未运行;应重新连接 GitHub 集成,或替换失效的 Cloudflare 构建 API Token 后再试。
|
|
25
|
+
|
|
26
|
+
Wrangler 要求此 Worker 设置 `compatibility_date`,因此项目将其固定为本月第一天:`2026-09-01`。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "EdgePress September 2026 update: request 5"
|
|
3
|
+
date: 2026-09-25
|
|
4
|
+
lang: en
|
|
5
|
+
slug: edgepress-release-2026-9-5
|
|
6
|
+
tags:
|
|
7
|
+
- release
|
|
8
|
+
- cloudflare
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
This is the fifth requested EdgePress update for September 2026.
|
|
12
|
+
|
|
13
|
+
## Clarify Cloudflare one-click deployment
|
|
14
|
+
|
|
15
|
+
The README and bilingual quick-start guides now explain that Cloudflare's Deploy button creates a new GitHub repository copy and a new Worker. Choose unused names for both during setup. The button does not connect to or update an existing Worker; use the existing repository's Workers Builds connection to publish updates.
|
|
16
|
+
|
|
17
|
+
The release notes and project compatibility history are updated as version `2026.9.5`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: EdgePress 2026 年 9 月更新:第 5 次需求
|
|
3
|
+
date: 2026-09-25
|
|
4
|
+
lang: zh-CN
|
|
5
|
+
slug: edgepress-release-2026-9-5
|
|
6
|
+
tags:
|
|
7
|
+
- 发布
|
|
8
|
+
- Cloudflare
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
这是 EdgePress 在 2026 年 9 月针对第 5 次需求的更新。
|
|
12
|
+
|
|
13
|
+
## 说明 Cloudflare 一键部署的行为
|
|
14
|
+
|
|
15
|
+
README 和中英文快速入门现已说明,Cloudflare 一键部署按钮会创建新的 GitHub 仓库副本和新的 Worker。设置时需要为两者选择未占用的名称。按钮不会连接或更新已有 Worker;更新已有项目应使用原仓库连接的 Workers Builds。
|
|
16
|
+
|
|
17
|
+
发布说明和项目兼容性历史已更新至 `2026.9.5`。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "edgepress",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.5",
|
|
4
4
|
"description": "A static website builder for Cloudflare Workers with editable pages, Markdown posts, local search, themes, and consent-gated integrations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"plugins",
|
|
13
13
|
"src",
|
|
14
14
|
"static",
|
|
15
|
-
"templates",
|
|
16
15
|
"themes",
|
|
17
16
|
"config.yml",
|
|
18
17
|
"edgepress.config.mjs",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"frameworkVersion": "2026.9.
|
|
3
|
+
"frameworkVersion": "2026.9.5",
|
|
4
4
|
"requirements": {
|
|
5
5
|
"nodeMajor": 22,
|
|
6
6
|
"nodeMinimumVersion": "22.12.0",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
{ "name": "Row-based editable pages and reusable layout components", "stage": "experimental", "since": "2026.9.1" },
|
|
16
16
|
{ "name": "Image/video with text and display typography elements", "stage": "experimental", "since": "2026.9.1" },
|
|
17
17
|
{ "name": "i18n locale routes", "stage": "experimental", "since": "2026.9.1" },
|
|
18
|
-
{ "name": "Accessibility and agent-friendliness report with screenshots
|
|
18
|
+
{ "name": "Accessibility and agent-friendliness PDF report with embedded screenshots", "stage": "experimental", "since": "2026.9.1" },
|
|
19
19
|
{ "name": "Consent-gated browser plugins", "stage": "experimental", "since": "2026.9.1" },
|
|
20
20
|
{ "name": "Service binding and URL/token backend proxy", "stage": "experimental", "since": "2026.9.1" },
|
|
21
21
|
{ "name": "Live local preview and theme switching", "stage": "experimental", "since": "2026.9.1" },
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
{ "name": "Local browser search across Markdown posts", "stage": "experimental", "since": "2026.9.2" },
|
|
24
24
|
{ "name": "Markdown syntax verification and responsive post screenshots", "stage": "experimental", "since": "2026.9.2" },
|
|
25
25
|
{ "name": "Compact localized language selector", "stage": "experimental", "since": "2026.9.2" },
|
|
26
|
-
{ "name": "npm theme installation and blank theme scaffolds", "stage": "experimental", "since": "2026.9.3" }
|
|
26
|
+
{ "name": "npm theme installation and blank theme scaffolds", "stage": "experimental", "since": "2026.9.3" },
|
|
27
|
+
{ "name": "PDF-only audit output and temporary screenshot capture", "stage": "experimental", "since": "2026.9.4" },
|
|
28
|
+
{ "name": "Cloudflare one-click deployment guidance for existing and new projects", "stage": "stable", "since": "2026.9.5" }
|
|
27
29
|
],
|
|
28
30
|
"releaseHistory": [
|
|
29
31
|
{
|
|
@@ -43,6 +45,18 @@
|
|
|
43
45
|
"date": "2026-09-25",
|
|
44
46
|
"request": 3,
|
|
45
47
|
"notes": "Published EdgePress for npm installation, added npm theme installation and blank theme packages, documented GitHub and Cloudflare Workers Builds deployment, and added a Cloudflare one-click deployment button."
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"version": "2026.9.4",
|
|
51
|
+
"date": "2026-09-25",
|
|
52
|
+
"request": 4,
|
|
53
|
+
"notes": "Keep audit output as a single accessible PDF with embedded screenshots, remove the templates directory and package archive, document Workers Builds initialization troubleshooting, and pin the Wrangler compatibility date to the first of the month."
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"version": "2026.9.5",
|
|
57
|
+
"date": "2026-09-25",
|
|
58
|
+
"request": 5,
|
|
59
|
+
"notes": "Clarify that the Cloudflare one-click deployment button creates a new repository copy and Worker, explain unique naming and the path for updating existing Workers, and publish the guidance in README and bilingual quick-start pages."
|
|
46
60
|
}
|
|
47
61
|
]
|
|
48
62
|
}
|
package/src/cli.js
CHANGED
|
@@ -10,6 +10,31 @@ import { slugify } from './content.js';
|
|
|
10
10
|
import { checkPages } from './page-check.js';
|
|
11
11
|
import { checkCompatibility, writeIterationPlan } from './maintenance.js';
|
|
12
12
|
|
|
13
|
+
const siteGitignore = ['node_modules/', 'dist/', '.edgepress/', '.wrangler/', '.dev.vars', '*.tgz', ''].join('\n');
|
|
14
|
+
const siteReadme = [
|
|
15
|
+
'# My EdgePress site',
|
|
16
|
+
'',
|
|
17
|
+
'Static site source built with EdgePress. Use Node.js 22.12 or newer.',
|
|
18
|
+
'',
|
|
19
|
+
'## Start locally',
|
|
20
|
+
'',
|
|
21
|
+
' npm install',
|
|
22
|
+
' edgepress server',
|
|
23
|
+
'',
|
|
24
|
+
'Edit localized pages in `content/pages/` and Markdown posts in `content/posts/`. Choose a shared layout with `edgepress theme list` and `edgepress theme use <name>`.',
|
|
25
|
+
'',
|
|
26
|
+
'## Deploy to Cloudflare Workers',
|
|
27
|
+
'',
|
|
28
|
+
'Push this source repository to GitHub, then connect the repository to Cloudflare Workers Builds. The `build` and `deploy` scripts in `package.json` generate the static files and deploy the Worker. Set a unique Worker name in `wrangler.jsonc` first.',
|
|
29
|
+
'',
|
|
30
|
+
'For a local deployment, run `npx wrangler login`, then `edgepress deploy`.',
|
|
31
|
+
'',
|
|
32
|
+
'## Use another static web server',
|
|
33
|
+
'',
|
|
34
|
+
'Run `edgepress generate` and upload the contents of `dist/` to the server document root. OpenResty and Nginx can serve the generated directories as static files. Worker API routes and service bindings need a Worker or an equivalent server-side route.',
|
|
35
|
+
''
|
|
36
|
+
].join('\n');
|
|
37
|
+
|
|
13
38
|
async function initializeProject() {
|
|
14
39
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
15
40
|
const root = process.cwd();
|
|
@@ -61,11 +86,11 @@ async function initializeProject() {
|
|
|
61
86
|
};
|
|
62
87
|
for (const directory of directories) await cp(resolve(packageRoot, directory), resolve(root, directory), { recursive: true, errorOnExist: true });
|
|
63
88
|
for (const file of files) {
|
|
64
|
-
const source = file === '.gitignore' ? resolve(packageRoot, 'templates/gitignore') :
|
|
65
|
-
file === 'README.md' ? resolve(packageRoot, 'templates/site-readme.md') : resolve(packageRoot, file);
|
|
66
89
|
const destination = resolve(root, file);
|
|
67
90
|
await mkdir(dirname(destination), { recursive: true });
|
|
68
|
-
await
|
|
91
|
+
if (file === '.gitignore') await writeFile(destination, siteGitignore, { flag: 'wx' });
|
|
92
|
+
else if (file === 'README.md') await writeFile(destination, siteReadme, { flag: 'wx' });
|
|
93
|
+
else await cp(resolve(packageRoot, file), destination, { errorOnExist: true });
|
|
69
94
|
}
|
|
70
95
|
await mkdir(resolve(root, 'src'), { recursive: true });
|
|
71
96
|
await cp(resolve(packageRoot, 'src/worker.js'), resolve(root, 'src/worker.js'), { errorOnExist: true });
|
|
@@ -324,7 +349,7 @@ try {
|
|
|
324
349
|
await buildSite(config.root);
|
|
325
350
|
const pageReport = await checkPages(config);
|
|
326
351
|
const compatibilityReport = await checkCompatibility(config);
|
|
327
|
-
await showReport('Page check', pageReport, resolve(config.root, 'tools/page-check.
|
|
352
|
+
await showReport('Page check', pageReport, resolve(config.root, 'tools/page-check.pdf'));
|
|
328
353
|
await showReport('Compatibility check', compatibilityReport, resolve(config.resolvedPaths.cache, 'reports/compatibility.md'));
|
|
329
354
|
if (pageReport.errors || compatibilityReport.issues.some((issue) => issue.severity === 'error')) process.exitCode = 1;
|
|
330
355
|
} else if (command === 'doctor') {
|
package/src/page-check.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { access, lstat, mkdir, readFile, readdir, realpath,
|
|
1
|
+
import { access, lstat, mkdir, readFile, readdir, realpath, rm } from 'node:fs/promises';
|
|
2
2
|
import { extname, isAbsolute, relative, resolve, sep } from 'node:path';
|
|
3
3
|
import { addVisualEvidence } from './report-visuals.js';
|
|
4
4
|
|
|
@@ -136,49 +136,6 @@ function auditSummary(checks, findings) {
|
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
function markdownReport(report) {
|
|
140
|
-
const lines = [
|
|
141
|
-
'# EdgePress accessibility and agent-friendliness audit',
|
|
142
|
-
'',
|
|
143
|
-
'Overall status: **' + report.status + '**',
|
|
144
|
-
'',
|
|
145
|
-
'| Audit | Status | Score | Checks | Errors | Warnings |',
|
|
146
|
-
'| --- | --- | ---: | ---: | ---: | ---: |',
|
|
147
|
-
'| Accessibility | ' + report.accessibility.status + ' | ' + report.accessibility.score + '% | ' + report.accessibility.checks + ' | ' + report.accessibility.errors + ' | ' + report.accessibility.warnings + ' |',
|
|
148
|
-
'| Agent friendliness | ' + report.agentFriendliness.status + ' | ' + report.agentFriendliness.score + '% | ' + report.agentFriendliness.checks + ' | ' + report.agentFriendliness.errors + ' | ' + report.agentFriendliness.warnings + ' |',
|
|
149
|
-
'| Markdown rendering | ' + report.markdownRendering.status + ' | ' + Math.floor(report.markdownRendering.passed / Math.max(1, report.markdownRendering.checks) * 100) + '% | ' + report.markdownRendering.checks + ' | ' + (report.markdownRendering.checks - report.markdownRendering.passed) + ' | 0 |',
|
|
150
|
-
'| Report reading structure | ' + (report.visualEvidence?.reportAccessibility?.status || 'pending') + ' | ' +
|
|
151
|
-
Math.floor((report.visualEvidence?.reportAccessibility?.passed || 0) / Math.max(1, report.visualEvidence?.reportAccessibility?.checks || 0) * 100) + '% | ' +
|
|
152
|
-
(report.visualEvidence?.reportAccessibility?.checks || 0) + ' | ' +
|
|
153
|
-
((report.visualEvidence?.reportAccessibility?.checks || 0) - (report.visualEvidence?.reportAccessibility?.passed || 0)) + ' | 0 |',
|
|
154
|
-
'',
|
|
155
|
-
'Generated documents: ' + report.pages + ' | Posts: ' + report.contentSummary.posts + ' | Pages: ' + report.contentSummary.pages +
|
|
156
|
-
' | System routes: ' + report.contentSummary.system + ' | Errors: ' + report.errors + ' | Warnings: ' + report.warnings,
|
|
157
|
-
'HTML bytes: ' + report.metrics.htmlBytes + ' | Stylesheet references: ' + report.metrics.stylesheets +
|
|
158
|
-
' | Potentially render-blocking stylesheets: ' + report.metrics.blockingStylesheets +
|
|
159
|
-
' | Script references: ' + report.metrics.scripts + ' | Blocking scripts: ' + report.metrics.blockingScripts,
|
|
160
|
-
'',
|
|
161
|
-
report.visualEvidence?.status === 'complete'
|
|
162
|
-
? 'Accessible PDF evidence: [page-check.pdf](page-check.pdf) | HTML report: [page-check-visual.html](page-check-visual.html) | Screenshots: ' +
|
|
163
|
-
report.visualEvidence.screenshots.map((item) => '[' + item.title + ' · ' + item.viewport + ' (' + item.viewportWidth + '/' + item.documentWidth + ' px)](' + item.path.replace(/^tools\//, '') + ')').join(' · ')
|
|
164
|
-
: 'Visual evidence: ' + (report.visualEvidence?.reason || 'not generated'),
|
|
165
|
-
'',
|
|
166
|
-
'## Findings',
|
|
167
|
-
''
|
|
168
|
-
];
|
|
169
|
-
if (!report.issues.length) lines.push('No findings.');
|
|
170
|
-
for (const issue of report.issues) lines.push('- **' + issue.severity.toUpperCase() + ' · ' + issue.category + '** ' + issue.page + ' — ' + issue.message);
|
|
171
|
-
lines.push('', '## Markdown rendering', '', 'Verified ' + report.markdownRendering.passed + ' of ' + report.markdownRendering.checks +
|
|
172
|
-
' syntax combinations in the generated tutorial post.');
|
|
173
|
-
for (const document of report.markdownRendering.documents) {
|
|
174
|
-
lines.push('', '### ' + document.path, '', ...document.checks.map((item) => '- [' + (item.passed ? 'x' : ' ') + '] ' + item.feature));
|
|
175
|
-
}
|
|
176
|
-
lines.push('', '## Documents reviewed', '', '| Type | Count |', '| --- | ---: |', '| Posts | ' + report.contentSummary.posts + ' |',
|
|
177
|
-
'| Customizable pages and homepages | ' + report.contentSummary.pages + ' |', '| System routes | ' + report.contentSummary.system + ' |');
|
|
178
|
-
lines.push('', '## Scope', '', ...report.scope.map((item) => '- ' + item), '', 'This report is written outside the public output directory.');
|
|
179
|
-
return lines.join('\n');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
139
|
export async function checkPages(config) {
|
|
183
140
|
const output = config.resolvedPaths.output;
|
|
184
141
|
const files = await htmlFiles(output);
|
|
@@ -380,28 +337,35 @@ export async function checkPages(config) {
|
|
|
380
337
|
const root = await realpath(config.root);
|
|
381
338
|
const directory = await realpath(requestedDirectory);
|
|
382
339
|
if (!isInside(root, directory)) throw new Error('Page-check report directory must stay inside the project root');
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
for (const file of [jsonPath, markdownPath]) {
|
|
340
|
+
for (const name of ['page-check.json', 'page-check.md', 'page-check-visual.html']) {
|
|
341
|
+
const file = resolve(directory, name);
|
|
386
342
|
try {
|
|
387
343
|
const info = await lstat(file);
|
|
388
|
-
if (info.isSymbolicLink() || !info.isFile()) throw new Error('Refusing an unsafe
|
|
344
|
+
if (info.isSymbolicLink() || !info.isFile()) throw new Error('Refusing an unsafe legacy report path: ' + file);
|
|
345
|
+
await rm(file);
|
|
389
346
|
} catch (error) {
|
|
390
347
|
if (error.code !== 'ENOENT') throw error;
|
|
391
348
|
}
|
|
392
349
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
350
|
+
const screenshotsDirectory = resolve(directory, 'page-check-screenshots');
|
|
351
|
+
try {
|
|
352
|
+
const info = await lstat(screenshotsDirectory);
|
|
353
|
+
if (info.isSymbolicLink() || !info.isDirectory()) throw new Error('Refusing an unsafe legacy screenshots path: ' + screenshotsDirectory);
|
|
354
|
+
await rm(screenshotsDirectory, { recursive: true });
|
|
355
|
+
} catch (error) {
|
|
356
|
+
if (error.code !== 'ENOENT') throw error;
|
|
357
|
+
}
|
|
358
|
+
const pdfPath = resolve(directory, 'page-check.pdf');
|
|
359
|
+
try {
|
|
360
|
+
const info = await lstat(pdfPath);
|
|
361
|
+
if (info.isSymbolicLink() || !info.isFile()) throw new Error('Refusing an unsafe PDF report path: ' + pdfPath);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
if (error.code !== 'ENOENT') throw error;
|
|
400
364
|
}
|
|
401
365
|
try {
|
|
402
366
|
report.visualEvidence = await addVisualEvidence(config, report);
|
|
403
367
|
if (report.visualEvidence.status !== 'complete') {
|
|
404
|
-
issues.push({ severity: 'warning', category: 'visual-evidence', page: 'report', message: report.visualEvidence.reason || '
|
|
368
|
+
issues.push({ severity: 'warning', category: 'visual-evidence', page: 'report', message: report.visualEvidence.reason || 'PDF generation failed.' });
|
|
405
369
|
}
|
|
406
370
|
} catch (error) {
|
|
407
371
|
report.visualEvidence = { status: 'failed', reason: error.message };
|
|
@@ -410,7 +374,5 @@ export async function checkPages(config) {
|
|
|
410
374
|
report.errors = issues.filter((issue) => issue.severity === 'error').length;
|
|
411
375
|
report.warnings = issues.filter((issue) => issue.severity === 'warning').length;
|
|
412
376
|
report.status = report.errors ? 'fail' : report.warnings ? 'warning' : 'pass';
|
|
413
|
-
await writeFile(jsonPath, JSON.stringify(report, null, 2), 'utf8');
|
|
414
|
-
await writeFile(markdownPath, markdownReport(report), 'utf8');
|
|
415
377
|
return report;
|
|
416
378
|
}
|
package/src/preview.js
CHANGED
|
@@ -57,7 +57,7 @@ async function main() {
|
|
|
57
57
|
await buildSite(root, { preview: true });
|
|
58
58
|
const currentConfig = await loadConfig(root);
|
|
59
59
|
const report = await checkPages(currentConfig);
|
|
60
|
-
console.log('Accessibility and agent-friendliness report: ' + report.status +
|
|
60
|
+
console.log('Accessibility and agent-friendliness PDF report: ' + report.status +
|
|
61
61
|
' (' + report.accessibility.status + ', ' + report.agentFriendliness.status + ')');
|
|
62
62
|
}
|
|
63
63
|
|
package/src/report-visuals.js
CHANGED
|
@@ -247,7 +247,7 @@ function reportHtml(report, screenshots) {
|
|
|
247
247
|
escapeHtml(String(report.markdownRendering?.checks || 0)) + ' syntax checks passed across the tutorial post locales.</p>' + markdownDetails + '</section>' +
|
|
248
248
|
'<section id="evidence" class="appendix"><h2>Responsive page screenshots</h2><p>Mobile screenshots use a 390 by 844 CSS pixel viewport. Each caption includes the measured document width so horizontal overflow is visible in the report.</p>' +
|
|
249
249
|
screenshotGroups + '</section><section id="scope"><h2>Scope and limits</h2><ul>' + report.scope.map((item) => '<li>' + escapeHtml(item) + '</li>').join('') +
|
|
250
|
-
'</ul></section></main><footer><p>EdgePress local
|
|
250
|
+
'</ul></section></main><footer><p>EdgePress local PDF report. Screenshot details are included as evidence and may be small when printed.</p></footer></body></html>';
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
function checkReportReadingStructure(html) {
|
|
@@ -351,73 +351,67 @@ function siteAddress(relativeFile) {
|
|
|
351
351
|
|
|
352
352
|
export async function addVisualEvidence(config, report) {
|
|
353
353
|
const root = resolve(config.root, 'tools');
|
|
354
|
-
const evidenceDirectory = resolve(root, 'page-check-screenshots');
|
|
355
354
|
const directoryInfo = await lstat(root);
|
|
356
355
|
if (directoryInfo.isSymbolicLink() || !directoryInfo.isDirectory()) throw new Error('Report directory must be a real directory');
|
|
357
|
-
await mkdir(evidenceDirectory, { recursive: true });
|
|
358
|
-
const evidenceInfo = await lstat(evidenceDirectory);
|
|
359
|
-
if (evidenceInfo.isSymbolicLink() || !evidenceInfo.isDirectory()) throw new Error('Screenshot directory must be a real directory');
|
|
360
356
|
const browser = await browserPath();
|
|
361
357
|
if (!browser) {
|
|
362
358
|
return { status: 'unavailable', reason: 'Install Microsoft Edge, Chrome, or Chromium to capture page screenshots and PDF evidence.' };
|
|
363
359
|
}
|
|
364
360
|
|
|
365
|
-
const
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
|
|
361
|
+
const stamp = createHash('sha256').update(report.generatedAt).digest('hex').slice(0, 8);
|
|
362
|
+
const profile = await mkdtemp(resolve(tmpdir(), 'edgepress-report-' + process.pid + '-' + stamp + '-'));
|
|
363
|
+
const evidenceDirectory = resolve(profile, 'page-check-screenshots');
|
|
364
|
+
const htmlPath = resolve(profile, 'report.html');
|
|
365
|
+
const pdfPath = resolve(root, 'page-check.pdf');
|
|
366
|
+
let reportServer;
|
|
367
|
+
let browserSession;
|
|
368
|
+
try {
|
|
369
|
+
await mkdir(evidenceDirectory, { recursive: true });
|
|
370
|
+
const evidenceInfo = await lstat(evidenceDirectory);
|
|
371
|
+
if (evidenceInfo.isSymbolicLink() || !evidenceInfo.isDirectory()) throw new Error('Temporary screenshot directory must be a real directory');
|
|
372
|
+
const documents = new Map((report.documents || []).map((item) => [item.path, item]));
|
|
373
|
+
const candidates = new Set((report.documents || [])
|
|
374
|
+
.filter((item) => ['post', 'page', 'homepage'].includes(item.type))
|
|
375
|
+
.map((item) => item.path));
|
|
376
|
+
for (const locale of config.i18n.locales) {
|
|
377
|
+
const prefix = locale === config.i18n.defaultLocale ? '' : locale + '/';
|
|
378
|
+
candidates.add(prefix + 'index.html');
|
|
379
|
+
candidates.add(prefix + 'privacy-policy/index.html');
|
|
380
|
+
}
|
|
381
|
+
for (const issue of report.issues) {
|
|
382
|
+
if (issue.page && issue.page.toLowerCase().endsWith('.html')) candidates.add(issue.page);
|
|
386
383
|
}
|
|
387
|
-
}
|
|
388
384
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const mobile = { name: 'mobile', width: 390, height: 844 };
|
|
393
|
-
const homePaths = new Set(config.i18n.locales.map((locale) => locale === config.i18n.defaultLocale ? 'index.html' : locale + '/index.html'));
|
|
394
|
-
const privacyPaths = new Set(config.i18n.locales.map((locale) =>
|
|
395
|
-
(locale === config.i18n.defaultLocale ? '' : locale + '/') + 'privacy-policy/index.html'));
|
|
396
|
-
for (const relativeFile of available) {
|
|
397
|
-
const document = documents.get(relativeFile) || { type: 'system', title: relativeFile };
|
|
398
|
-
const viewports = homePaths.has(relativeFile) || privacyPaths.has(relativeFile) || document.type === 'post'
|
|
399
|
-
? [desktop, mobile] : [mobile];
|
|
400
|
-
for (const viewport of viewports) {
|
|
401
|
-
const digest = createHash('sha256').update(relativeFile + ':' + viewport.name).digest('hex').slice(0, 10);
|
|
402
|
-
const file = 'page-' + digest + '.png';
|
|
403
|
-
const target = resolve(evidenceDirectory, file);
|
|
385
|
+
const available = [];
|
|
386
|
+
for (const relativeFile of candidates) {
|
|
387
|
+
const target = resolve(config.resolvedPaths.output, relativeFile);
|
|
404
388
|
try {
|
|
405
|
-
const
|
|
406
|
-
if (
|
|
389
|
+
const info = await lstat(target);
|
|
390
|
+
if (info.isFile() && !info.isSymbolicLink()) available.push(relativeFile);
|
|
407
391
|
} catch (error) {
|
|
408
392
|
if (error.code !== 'ENOENT') throw error;
|
|
409
393
|
}
|
|
410
|
-
screenshots.push({ page: relativeFile, type: document.type, title: document.title, viewport: viewport.name, width: viewport.width,
|
|
411
|
-
height: viewport.height, file, target,
|
|
412
|
-
label: relativeFile + ' · ' + viewport.name + ' (' + viewport.width + '×' + viewport.height + ')' });
|
|
413
394
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
395
|
+
|
|
396
|
+
const screenshots = [];
|
|
397
|
+
const desktop = { name: 'desktop', width: 1440, height: 1100 };
|
|
398
|
+
const mobile = { name: 'mobile', width: 390, height: 844 };
|
|
399
|
+
const homePaths = new Set(config.i18n.locales.map((locale) => locale === config.i18n.defaultLocale ? 'index.html' : locale + '/index.html'));
|
|
400
|
+
const privacyPaths = new Set(config.i18n.locales.map((locale) =>
|
|
401
|
+
(locale === config.i18n.defaultLocale ? '' : locale + '/') + 'privacy-policy/index.html'));
|
|
402
|
+
for (const relativeFile of available) {
|
|
403
|
+
const document = documents.get(relativeFile) || { type: 'system', title: relativeFile };
|
|
404
|
+
const viewports = homePaths.has(relativeFile) || privacyPaths.has(relativeFile) || document.type === 'post'
|
|
405
|
+
? [desktop, mobile] : [mobile];
|
|
406
|
+
for (const viewport of viewports) {
|
|
407
|
+
const digest = createHash('sha256').update(relativeFile + ':' + viewport.name).digest('hex').slice(0, 10);
|
|
408
|
+
const file = 'page-' + digest + '.png';
|
|
409
|
+
const target = resolve(evidenceDirectory, file);
|
|
410
|
+
screenshots.push({ page: relativeFile, type: document.type, title: document.title, viewport: viewport.name, width: viewport.width,
|
|
411
|
+
height: viewport.height, file, target,
|
|
412
|
+
label: relativeFile + ' · ' + viewport.name + ' (' + viewport.width + '×' + viewport.height + ')' });
|
|
413
|
+
}
|
|
414
|
+
}
|
|
421
415
|
reportServer = await startReportServer(config.resolvedPaths.output, evidenceDirectory, htmlPath);
|
|
422
416
|
browserSession = await startHeadlessBrowser(browser, profile);
|
|
423
417
|
for (const screenshot of screenshots) {
|
|
@@ -449,13 +443,13 @@ export async function addVisualEvidence(config, report) {
|
|
|
449
443
|
report.visualEvidence = { status: 'complete', pdf: 'tools/page-check.pdf', screenshots: screenshots.map((item) => ({
|
|
450
444
|
page: item.page, type: item.type, title: item.title, viewport: item.viewport, width: item.width, height: item.height,
|
|
451
445
|
viewportWidth: item.viewportWidth, documentWidth: item.documentWidth,
|
|
452
|
-
|
|
446
|
+
label: item.label
|
|
453
447
|
})) };
|
|
454
448
|
const initialHtml = reportHtml(report, screenshots);
|
|
455
449
|
const reportAccessibility = checkReportReadingStructure(initialHtml);
|
|
456
450
|
report.visualEvidence.reportAccessibility = reportAccessibility;
|
|
457
451
|
for (const check of reportAccessibility.results.filter((item) => !item.passed)) {
|
|
458
|
-
report.issues.push({ severity: 'error', category: 'report-accessibility', page: 'tools/page-check
|
|
452
|
+
report.issues.push({ severity: 'error', category: 'report-accessibility', page: 'tools/page-check.pdf',
|
|
459
453
|
message: 'Report reading requirement failed: ' + check.name + '.' });
|
|
460
454
|
}
|
|
461
455
|
report.errors = report.issues.filter((item) => item.severity === 'error').length;
|
package/wrangler.jsonc
CHANGED
package/templates/gitignore
DELETED
package/templates/site-readme.md
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# My EdgePress site
|
|
2
|
-
|
|
3
|
-
Static site source built with EdgePress. Use Node.js 22.12 or newer.
|
|
4
|
-
|
|
5
|
-
## Start locally
|
|
6
|
-
|
|
7
|
-
npm install
|
|
8
|
-
edgepress server
|
|
9
|
-
|
|
10
|
-
Edit localized pages in `content/pages/` and Markdown posts in `content/posts/`. Choose a shared layout with `edgepress theme list` and `edgepress theme use <name>`.
|
|
11
|
-
|
|
12
|
-
## Deploy to Cloudflare Workers
|
|
13
|
-
|
|
14
|
-
Push this source repository to GitHub, then connect the repository to Cloudflare Workers Builds. The `build` and `deploy` scripts in `package.json` generate the static files and deploy the Worker. Set a unique Worker name in `wrangler.jsonc` first.
|
|
15
|
-
|
|
16
|
-
For a local deployment, run `npx wrangler login`, then `edgepress deploy`.
|
|
17
|
-
|
|
18
|
-
## Use another static web server
|
|
19
|
-
|
|
20
|
-
Run `edgepress generate` and upload the contents of `dist/` to the server document root. OpenResty and Nginx can serve the generated directories as static files. Worker API routes and service bindings need a Worker or an equivalent server-side route.
|