edgepress 2026.10.12 → 2026.10.13

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.
Files changed (57) hide show
  1. package/README.md +12 -2
  2. package/config.yml +171 -171
  3. package/content/assets/edgepress/brand/sources/export-manifest.json +181 -181
  4. package/content/assets/edgepress-markdown-guide.svg +21 -21
  5. package/content/guides/markdown-media.md +38 -0
  6. package/content/guides/product-demos.md +30 -30
  7. package/content/pages/deployment/en.json +1 -1
  8. package/content/posts/2026-09-24-edgepress-release-2026-9-1/en.md +1 -1
  9. package/content/posts/2026-09-24-edgepress-release-2026-9-1/zh-cn.md +1 -1
  10. package/languages/base/en.json +98 -98
  11. package/languages/packs/zh-CN.json +98 -98
  12. package/package.json +90 -90
  13. package/src/assets.js +187 -186
  14. package/src/browser-audit.js +158 -158
  15. package/src/build.js +293 -291
  16. package/src/cli.js +364 -364
  17. package/src/content.js +233 -233
  18. package/src/data-saver.js +3 -3
  19. package/src/generators.js +414 -420
  20. package/src/i18n.js +86 -86
  21. package/src/markdown.js +195 -160
  22. package/src/page-check.js +1 -1
  23. package/src/plugin-api.js +77 -77
  24. package/src/report-visuals.js +642 -642
  25. package/src/revision-cards.js +30 -30
  26. package/src/rss.js +100 -0
  27. package/src/theme.js +4 -4
  28. package/src/video-metadata.js +36 -0
  29. package/static/edgepress/fonts/faces.css +2217 -2217
  30. package/static/edgepress/media-viewer.js +67 -10
  31. package/static/edgepress/project-demo.js +83 -83
  32. package/static/edgepress/search.js +84 -84
  33. package/tests/assets-runtime.test.mjs +26 -26
  34. package/tests/audit.test.mjs +142 -142
  35. package/tests/brand-regression.test.mjs +110 -110
  36. package/tests/document-package.test.mjs +2 -2
  37. package/tests/embed-syntax.test.mjs +68 -68
  38. package/tests/image-viewer.test.mjs +36 -36
  39. package/tests/markdown-media.test.mjs +119 -0
  40. package/tests/oembed-layout.test.mjs +6 -1
  41. package/tests/project-demo.test.mjs +73 -73
  42. package/tests/release-version.test.mjs +28 -0
  43. package/tests/rss.test.mjs +54 -0
  44. package/tests/video-metadata.test.mjs +28 -0
  45. package/tests/writing.test.mjs +83 -83
  46. package/themes/atelier/assets/style.css +340 -340
  47. package/themes/default/assets/style.css +371 -371
  48. package/themes/default/layouts/partials/head.html +1 -1
  49. package/themes/folio/assets/style.css +515 -515
  50. package/themes/folio/theme.json +5 -5
  51. package/themes/signal/assets/style.css +332 -332
  52. package/tools/README.md +10 -10
  53. package/tools/assets/generate-brand-assets.py +160 -160
  54. package/tools/assets/video-preview.mjs +15 -0
  55. package/tools/recordings/demo-workbench.mjs +53 -53
  56. package/tools/recordings/desktop-recording.mjs +70 -70
  57. package/tools/recordings/vm-desktop.mjs +59 -59
@@ -1,181 +1,181 @@
1
- {
2
- "iconCount": 28,
3
- "assets": [
4
- {
5
- "path": "content/assets/edgepress/brand/avatar.png",
6
- "format": "PNG",
7
- "dimensions": [
8
- 512,
9
- 512
10
- ],
11
- "alphaRange": [
12
- 0,
13
- 255
14
- ],
15
- "sha256": "fdbada39980869d7cb02d2082cb6a986cf9714957d332e0b360a49eac577ac66"
16
- },
17
- {
18
- "path": "content/assets/edgepress/brand/home-hero.png",
19
- "format": "PNG",
20
- "dimensions": [
21
- 1536,
22
- 1024
23
- ],
24
- "alphaRange": [
25
- 0,
26
- 254
27
- ],
28
- "sha256": "22a77eb0d9396ca1bbc5e45effcba0fc0ac64ef7cae0f172678a62be21020d10"
29
- },
30
- {
31
- "path": "content/assets/edgepress/brand/mascot.png",
32
- "format": "PNG",
33
- "dimensions": [
34
- 1312,
35
- 1199
36
- ],
37
- "alphaRange": [
38
- 0,
39
- 255
40
- ],
41
- "sha256": "94dba136cdfd0c23c847ca4f3792fa9b75b45dfdc1e6a3bc25c514ff63e93dfe"
42
- },
43
- {
44
- "path": "content/assets/edgepress/brand/og-image.png",
45
- "format": "PNG",
46
- "dimensions": [
47
- 1200,
48
- 630
49
- ],
50
- "alphaRange": null,
51
- "sha256": "0ff7e76c5b90d0285e8ba0d00428298a5ec19bcfd9c1905c1ba3624066651c62"
52
- },
53
- {
54
- "path": "content/assets/edgepress/brand/sources/edgepress-avatar-master.png",
55
- "format": "PNG",
56
- "dimensions": [
57
- 1254,
58
- 1254
59
- ],
60
- "alphaRange": [
61
- 0,
62
- 255
63
- ],
64
- "sha256": "8bb4d9bd2b5277d8802ab84264460fbd6ecbb9fdfcdfa0afaf2f6f95f5374dbc"
65
- },
66
- {
67
- "path": "content/assets/edgepress/brand/home-hero-768.webp",
68
- "format": "WEBP",
69
- "dimensions": [
70
- 768,
71
- 512
72
- ],
73
- "alphaRange": [
74
- 0,
75
- 255
76
- ],
77
- "sha256": "f95fcd52017213df482e4718def2c6e2c0e0c2142773bf71b101dfbacd0e88a0"
78
- },
79
- {
80
- "path": "content/assets/edgepress/brand/home-hero.webp",
81
- "format": "WEBP",
82
- "dimensions": [
83
- 1536,
84
- 1024
85
- ],
86
- "alphaRange": [
87
- 0,
88
- 254
89
- ],
90
- "sha256": "6ea3111a1ccd79cee7e82825ca907216a73151ce462590eb03cfd26e3e725d03"
91
- },
92
- {
93
- "path": "content/assets/edgepress/brand/mascot.webp",
94
- "format": "WEBP",
95
- "dimensions": [
96
- 768,
97
- 702
98
- ],
99
- "alphaRange": [
100
- 0,
101
- 255
102
- ],
103
- "sha256": "d34544362877d1ae10b8af6bdc345d9375aaa777e10b839bb40adf2ecb2663a7"
104
- },
105
- {
106
- "path": "content/assets/edgepress/brand/og-image.webp",
107
- "format": "WEBP",
108
- "dimensions": [
109
- 1200,
110
- 630
111
- ],
112
- "alphaRange": null,
113
- "sha256": "79044ffa13fb407b2fd715befb45f71f70f5b9f003c7986341e5b45cea6f0003"
114
- },
115
- {
116
- "path": "content/assets/edgepress/favicon/apple-touch-icon.png",
117
- "format": "PNG",
118
- "dimensions": [
119
- 180,
120
- 180
121
- ],
122
- "alphaRange": [
123
- 255,
124
- 255
125
- ],
126
- "sha256": "90ca1fd67318ad4aaeffa9fcf7881c3bd93b96f87c77fc8381d832e8c3368ff1"
127
- },
128
- {
129
- "path": "content/assets/edgepress/favicon/favicon-16.png",
130
- "format": "PNG",
131
- "dimensions": [
132
- 16,
133
- 16
134
- ],
135
- "alphaRange": [
136
- 0,
137
- 255
138
- ],
139
- "sha256": "387a744c660732ca6c2fa166a36df40b594484dd51e6f1df84d3947d3352bbce"
140
- },
141
- {
142
- "path": "content/assets/edgepress/favicon/favicon-32.png",
143
- "format": "PNG",
144
- "dimensions": [
145
- 32,
146
- 32
147
- ],
148
- "alphaRange": [
149
- 0,
150
- 255
151
- ],
152
- "sha256": "b1be2f46a9277773b112dbe8c3247243246e1d9426529a1b8b781755c695ab5f"
153
- },
154
- {
155
- "path": "content/assets/edgepress/favicon/favicon-48.png",
156
- "format": "PNG",
157
- "dimensions": [
158
- 48,
159
- 48
160
- ],
161
- "alphaRange": [
162
- 0,
163
- 255
164
- ],
165
- "sha256": "8c1e2491f1026fbd454fda84ae1edb66e3e648dd5e44bd3baaf05704be302c54"
166
- },
167
- {
168
- "path": "content/assets/edgepress/favicon/favicon-64.png",
169
- "format": "PNG",
170
- "dimensions": [
171
- 64,
172
- 64
173
- ],
174
- "alphaRange": [
175
- 0,
176
- 255
177
- ],
178
- "sha256": "4191df3d3f9276cb29983baeadf42b760c015cc5bf1c964cbc31a00348319588"
179
- }
180
- ]
181
- }
1
+ {
2
+ "iconCount": 28,
3
+ "assets": [
4
+ {
5
+ "path": "content/assets/edgepress/brand/avatar.png",
6
+ "format": "PNG",
7
+ "dimensions": [
8
+ 512,
9
+ 512
10
+ ],
11
+ "alphaRange": [
12
+ 0,
13
+ 255
14
+ ],
15
+ "sha256": "fdbada39980869d7cb02d2082cb6a986cf9714957d332e0b360a49eac577ac66"
16
+ },
17
+ {
18
+ "path": "content/assets/edgepress/brand/home-hero.png",
19
+ "format": "PNG",
20
+ "dimensions": [
21
+ 1536,
22
+ 1024
23
+ ],
24
+ "alphaRange": [
25
+ 0,
26
+ 254
27
+ ],
28
+ "sha256": "22a77eb0d9396ca1bbc5e45effcba0fc0ac64ef7cae0f172678a62be21020d10"
29
+ },
30
+ {
31
+ "path": "content/assets/edgepress/brand/mascot.png",
32
+ "format": "PNG",
33
+ "dimensions": [
34
+ 1312,
35
+ 1199
36
+ ],
37
+ "alphaRange": [
38
+ 0,
39
+ 255
40
+ ],
41
+ "sha256": "94dba136cdfd0c23c847ca4f3792fa9b75b45dfdc1e6a3bc25c514ff63e93dfe"
42
+ },
43
+ {
44
+ "path": "content/assets/edgepress/brand/og-image.png",
45
+ "format": "PNG",
46
+ "dimensions": [
47
+ 1200,
48
+ 630
49
+ ],
50
+ "alphaRange": null,
51
+ "sha256": "0ff7e76c5b90d0285e8ba0d00428298a5ec19bcfd9c1905c1ba3624066651c62"
52
+ },
53
+ {
54
+ "path": "content/assets/edgepress/brand/sources/edgepress-avatar-master.png",
55
+ "format": "PNG",
56
+ "dimensions": [
57
+ 1254,
58
+ 1254
59
+ ],
60
+ "alphaRange": [
61
+ 0,
62
+ 255
63
+ ],
64
+ "sha256": "8bb4d9bd2b5277d8802ab84264460fbd6ecbb9fdfcdfa0afaf2f6f95f5374dbc"
65
+ },
66
+ {
67
+ "path": "content/assets/edgepress/brand/home-hero-768.webp",
68
+ "format": "WEBP",
69
+ "dimensions": [
70
+ 768,
71
+ 512
72
+ ],
73
+ "alphaRange": [
74
+ 0,
75
+ 255
76
+ ],
77
+ "sha256": "f95fcd52017213df482e4718def2c6e2c0e0c2142773bf71b101dfbacd0e88a0"
78
+ },
79
+ {
80
+ "path": "content/assets/edgepress/brand/home-hero.webp",
81
+ "format": "WEBP",
82
+ "dimensions": [
83
+ 1536,
84
+ 1024
85
+ ],
86
+ "alphaRange": [
87
+ 0,
88
+ 254
89
+ ],
90
+ "sha256": "6ea3111a1ccd79cee7e82825ca907216a73151ce462590eb03cfd26e3e725d03"
91
+ },
92
+ {
93
+ "path": "content/assets/edgepress/brand/mascot.webp",
94
+ "format": "WEBP",
95
+ "dimensions": [
96
+ 768,
97
+ 702
98
+ ],
99
+ "alphaRange": [
100
+ 0,
101
+ 255
102
+ ],
103
+ "sha256": "d34544362877d1ae10b8af6bdc345d9375aaa777e10b839bb40adf2ecb2663a7"
104
+ },
105
+ {
106
+ "path": "content/assets/edgepress/brand/og-image.webp",
107
+ "format": "WEBP",
108
+ "dimensions": [
109
+ 1200,
110
+ 630
111
+ ],
112
+ "alphaRange": null,
113
+ "sha256": "79044ffa13fb407b2fd715befb45f71f70f5b9f003c7986341e5b45cea6f0003"
114
+ },
115
+ {
116
+ "path": "content/assets/edgepress/favicon/apple-touch-icon.png",
117
+ "format": "PNG",
118
+ "dimensions": [
119
+ 180,
120
+ 180
121
+ ],
122
+ "alphaRange": [
123
+ 255,
124
+ 255
125
+ ],
126
+ "sha256": "90ca1fd67318ad4aaeffa9fcf7881c3bd93b96f87c77fc8381d832e8c3368ff1"
127
+ },
128
+ {
129
+ "path": "content/assets/edgepress/favicon/favicon-16.png",
130
+ "format": "PNG",
131
+ "dimensions": [
132
+ 16,
133
+ 16
134
+ ],
135
+ "alphaRange": [
136
+ 0,
137
+ 255
138
+ ],
139
+ "sha256": "387a744c660732ca6c2fa166a36df40b594484dd51e6f1df84d3947d3352bbce"
140
+ },
141
+ {
142
+ "path": "content/assets/edgepress/favicon/favicon-32.png",
143
+ "format": "PNG",
144
+ "dimensions": [
145
+ 32,
146
+ 32
147
+ ],
148
+ "alphaRange": [
149
+ 0,
150
+ 255
151
+ ],
152
+ "sha256": "b1be2f46a9277773b112dbe8c3247243246e1d9426529a1b8b781755c695ab5f"
153
+ },
154
+ {
155
+ "path": "content/assets/edgepress/favicon/favicon-48.png",
156
+ "format": "PNG",
157
+ "dimensions": [
158
+ 48,
159
+ 48
160
+ ],
161
+ "alphaRange": [
162
+ 0,
163
+ 255
164
+ ],
165
+ "sha256": "8c1e2491f1026fbd454fda84ae1edb66e3e648dd5e44bd3baaf05704be302c54"
166
+ },
167
+ {
168
+ "path": "content/assets/edgepress/favicon/favicon-64.png",
169
+ "format": "PNG",
170
+ "dimensions": [
171
+ 64,
172
+ 64
173
+ ],
174
+ "alphaRange": [
175
+ 0,
176
+ 255
177
+ ],
178
+ "sha256": "4191df3d3f9276cb29983baeadf42b760c015cc5bf1c964cbc31a00348319588"
179
+ }
180
+ ]
181
+ }
@@ -1,21 +1,21 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 320" role="img" aria-labelledby="title desc">
2
- <title id="title">EdgePress Markdown publishing flow</title>
3
- <desc id="desc">Markdown source passes through rendering and HTML sanitization to a published post.</desc>
4
- <rect width="960" height="320" rx="24" fill="#f5f3ee"/>
5
- <g font-family="system-ui, sans-serif" text-anchor="middle" fill="#24352d">
6
- <rect x="44" y="86" width="230" height="148" rx="18" fill="#fff" stroke="#b8c6bc" stroke-width="3"/>
7
- <text x="159" y="139" font-size="23" font-weight="700">Markdown source</text>
8
- <text x="159" y="181" font-size="12">content/posts/&lt;post-id&gt;/en.md</text>
9
- <text x="159" y="209" font-size="17">headings · lists · links</text>
10
- <path d="M292 160h78m-16-16 16 16-16 16" fill="none" stroke="#426b57" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
11
- <rect x="382" y="86" width="230" height="148" rx="18" fill="#e3ece5" stroke="#9db4a4" stroke-width="3"/>
12
- <text x="497" y="139" font-size="23" font-weight="700">EdgePress build</text>
13
- <text x="497" y="181" font-size="17">CommonMark + GFM</text>
14
- <text x="497" y="209" font-size="17">safe HTML output</text>
15
- <path d="M630 160h78m-16-16 16 16-16 16" fill="none" stroke="#426b57" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
16
- <rect x="720" y="86" width="196" height="148" rx="18" fill="#fff" stroke="#b8c6bc" stroke-width="3"/>
17
- <text x="818" y="139" font-size="23" font-weight="700">Published post</text>
18
- <text x="818" y="181" font-size="17">accessible HTML</text>
19
- <text x="818" y="209" font-size="17">static site output</text>
20
- </g>
21
- </svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 320" role="img" aria-labelledby="title desc">
2
+ <title id="title">EdgePress Markdown publishing flow</title>
3
+ <desc id="desc">Markdown source passes through rendering and HTML sanitization to a published post.</desc>
4
+ <rect width="960" height="320" rx="24" fill="#f5f3ee"/>
5
+ <g font-family="system-ui, sans-serif" text-anchor="middle" fill="#24352d">
6
+ <rect x="44" y="86" width="230" height="148" rx="18" fill="#fff" stroke="#b8c6bc" stroke-width="3"/>
7
+ <text x="159" y="139" font-size="23" font-weight="700">Markdown source</text>
8
+ <text x="159" y="181" font-size="12">content/posts/&lt;post-id&gt;/en.md</text>
9
+ <text x="159" y="209" font-size="17">headings · lists · links</text>
10
+ <path d="M292 160h78m-16-16 16 16-16 16" fill="none" stroke="#426b57" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
11
+ <rect x="382" y="86" width="230" height="148" rx="18" fill="#e3ece5" stroke="#9db4a4" stroke-width="3"/>
12
+ <text x="497" y="139" font-size="23" font-weight="700">EdgePress build</text>
13
+ <text x="497" y="181" font-size="17">CommonMark + GFM</text>
14
+ <text x="497" y="209" font-size="17">safe HTML output</text>
15
+ <path d="M630 160h78m-16-16 16 16-16 16" fill="none" stroke="#426b57" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
16
+ <rect x="720" y="86" width="196" height="148" rx="18" fill="#fff" stroke="#b8c6bc" stroke-width="3"/>
17
+ <text x="818" y="139" font-size="23" font-weight="700">Published post</text>
18
+ <text x="818" y="181" font-size="17">accessible HTML</text>
19
+ <text x="818" y="209" font-size="17">static site output</text>
20
+ </g>
21
+ </svg>
@@ -0,0 +1,38 @@
1
+ ---
2
+ title: "Local video and CJK emphasis in Markdown"
3
+ lang: en
4
+ ---
5
+
6
+ Insert a local video with the ordinary image-shaped Markdown syntax:
7
+
8
+ ```md
9
+ ![A character walks around the barrier](/media/bypass.mp4 "Motion test")
10
+ ```
11
+
12
+ EdgePress enhances same-origin MP4, WebM, OGV and OGG files with the shared Multimedia viewer player. It provides themed controls, time, seeking, speed, volume and fullscreen. The file starts loading when the visitor presses Play. Scrolling the player out of view pauses playback and retains its position. Returning does not automatically resume it.
13
+
14
+ The native video element remains the fallback if the enhancement is unavailable. The player engine and styles are bundled locally and fingerprinted with the other site assets. A site with Markdown videos receives these assets even when it has no Pages galleries. In text view, the video and its engine activate only when the visitor requests that media. External embeds retain their own service-consent rules.
15
+
16
+ Use meaningful alternative text and an optional title for the visible caption. Reference-style links are supported too:
17
+
18
+ To show a poster and total duration before Play, generate a local preview once (FFmpeg and FFprobe must be on PATH):
19
+
20
+ ```sh
21
+ node node_modules/edgepress/tools/assets/video-preview.mjs content/assets/media/bypass.mp4
22
+ ```
23
+
24
+ An optional second argument selects the frame time in seconds. Commit the generated `bypass.mp4.poster.jpg` and `bypass.mp4.json` beside the video. The sidecar contains measured `duration`, `width`, `height` and the relative `poster` filename. EdgePress reads these local files during every build and adds the preview attributes to matching video elements, including Markdown videos. Cloud builds need no FFmpeg; visitors load the poster, while the video still waits for Play. After playback begins, the player's actual media duration replaces the supplied value. Regenerate the preview when replacing the video.
25
+
26
+ ```md
27
+ ![An action comparison][comparison]
28
+
29
+ [comparison]: /media/comparison.mp4
30
+ ```
31
+
32
+ CJK prose can place bold text ending in brackets or punctuation directly beside the next word:
33
+
34
+ ```md
35
+ 本次采用**有限动画(背景复用)**制作短片。
36
+ ```
37
+
38
+ The bracketed phrase renders as bold without adding spaces. Code spans, fenced code, escaped delimiters and link destinations retain their normal Markdown behavior.
@@ -1,37 +1,37 @@
1
- # Product demonstrations
2
-
3
- Use a static poster and a local MP4 or WebM for website playback. Visitors start playback manually and can drag the progress bar or use its arrow keys. Touch seeking needs an intentional horizontal drag; scrolling vertically and tapping control spacing keep the playhead. Leaving the viewport pauses playback and returning keeps the same position until Continue is clicked. The final frame remains visible until Replay is chosen.
4
-
5
- ```yaml
6
- - type: media-text
7
- mediaType: image
8
- src: /images/publishing.webp
9
- animationSrc: /images/publishing.mp4
10
- alt: Publishing a photo and video post
11
- title: Publish a story
12
- text: Write a caption, attach media and share the result.
13
- ```
14
-
15
- Put the MP4 metadata at the start of the file (FFmpeg `-movflags +faststart`) and use a hashed filename for immutable caching. The runtime prepares nearby media, streams the native file and preserves its playhead without Blob URLs. Posters reserve the layout. GIF exports remain useful in GitHub documentation.
16
-
1
+ # Product demonstrations
2
+
3
+ Use a static poster and a local MP4 or WebM for website playback. Visitors start playback manually and can drag the progress bar or use its arrow keys. Touch seeking needs an intentional horizontal drag; scrolling vertically and tapping control spacing keep the playhead. Leaving the viewport pauses playback and returning keeps the same position until Continue is clicked. The final frame remains visible until Replay is chosen.
4
+
5
+ ```yaml
6
+ - type: media-text
7
+ mediaType: image
8
+ src: /images/publishing.webp
9
+ animationSrc: /images/publishing.mp4
10
+ alt: Publishing a photo and video post
11
+ title: Publish a story
12
+ text: Write a caption, attach media and share the result.
13
+ ```
14
+
15
+ Put the MP4 metadata at the start of the file (FFmpeg `-movflags +faststart`) and use a hashed filename for immutable caching. The runtime prepares nearby media, streams the native file and preserves its playhead without Blob URLs. Posters reserve the layout. GIF exports remain useful in GitHub documentation.
16
+
17
17
  Record a real project and hold its visible results. For EdgePress, show `edgepress new post 'An afternoon by the water'`, editing the generated Markdown in a code editor, running `edgepress server`, opening the homepage, and clicking the article to read it. The preview uses the actual local server. Do not overlay unrelated slogans or publish test posts to production.
18
-
19
- 中文:网站使用静态封面与本地 MP4/WebM;手动播放,可拖动进度条或用方向键定位;离开视野时暂停,再回来保留原位置,点击继续才播放,结束后停留最后一帧。视频采用 faststart 与内容哈希,接近视野时预载,保留 GIF 给 GitHub 文档。示例必须来自独立写文建站项目:创建文章、代码编辑器修改、运行 `edgepress server`,再从网站首页点击进入文章。录制不需要固定字幕条。
20
-
21
- ## Isolated desktop recordings
22
-
23
- Use a disposable VM and its own display. The current Windows workflow imports a dedicated WSL2 Debian VM and starts Xvfb display :99 with Openbox, xterm, Geany and Chromium. FFmpeg x11grab records that entire guest desktop at 25 fps. Playwright controls only the guest browser through its loopback CDP endpoint; xdotool controls only DISPLAY :99. Host mouse, keyboard, clipboard and browser sessions remain separate.
24
-
25
- Create `/opt/recording/workspace` inside the guest as a link to the mounted canonical workspace. Pack the local EdgePress release with `npm pack` and install the resulting archive under `/opt/recording`, together with its locked Linux dependencies and Wrangler; verify `/opt/recording/node_modules/.bin/edgepress` before capture. Rebuild esbuild in the guest if lifecycle scripts were disabled. When GitHub downloads are unavailable in the guest, transfer the same pinned media-viewer archive from the host and point only the temporary package’s dependency at that archive. Do not fall back to a Windows global CLI.
26
-
18
+
19
+ 中文:网站使用静态封面与本地 MP4/WebM;手动播放,可拖动进度条或用方向键定位;离开视野时暂停,再回来保留原位置,点击继续才播放,结束后停留最后一帧。视频采用 faststart 与内容哈希,接近视野时预载,保留 GIF 给 GitHub 文档。示例必须来自独立写文建站项目:创建文章、代码编辑器修改、运行 `edgepress server`,再从网站首页点击进入文章。录制不需要固定字幕条。
20
+
21
+ ## Isolated desktop recordings
22
+
23
+ Use a disposable VM and its own display. The current Windows workflow imports a dedicated WSL2 Debian VM and starts Xvfb display :99 with Openbox, xterm, Geany and Chromium. FFmpeg x11grab records that entire guest desktop at 25 fps. Playwright controls only the guest browser through its loopback CDP endpoint; xdotool controls only DISPLAY :99. Host mouse, keyboard, clipboard and browser sessions remain separate.
24
+
25
+ Create `/opt/recording/workspace` inside the guest as a link to the mounted canonical workspace. Pack the local EdgePress release with `npm pack` and install the resulting archive under `/opt/recording`, together with its locked Linux dependencies and Wrangler; verify `/opt/recording/node_modules/.bin/edgepress` before capture. Rebuild esbuild in the guest if lifecycle scripts were disabled. When GitHub downloads are unavailable in the guest, transfer the same pinned media-viewer archive from the host and point only the temporary package’s dependency at that archive. Do not fall back to a Windows global CLI.
26
+
27
27
  The reusable helpers live in tools/recordings/. provision-vm.sh installs open-source desktop tools inside the guest; start-vm-desktop.sh starts its private display. demo-workbench.mjs prepares a real standalone writing site, executes edgepress in the guest terminal, saves the actual Markdown through Geany and opens the actual local preview in Chromium. desktop-recording.mjs invokes FFmpeg capture, trim, concat, H.264 faststart and GIF palette filters. It contains no screenshot capture loop or renderer.
28
28
 
29
29
  Run start-vm-desktop.sh with `--keep-alive` during a capture session so the desktop stays available between commands. Browser startup waits for the guest CDP endpoint and disables unsolicited translation prompts. Use the physical browser window for page layout and the guest's actual X11 pointer for visible actions. Retain the application's navigation, quota cards and original styles; scroll controls into view before using them. Select both attachments through the native file chooser and show the publication result. The local video fixture adds gentle motion to the existing repository photograph so playback, pause, seeking and speed changes can be seen.
30
-
30
+
31
31
  For embeddings, paste !embed[ishare](URL) into the body, save, run edgepress server, open the article from the homepage, grant consent and inspect the attachments. Only the uninformative middle of local-preview startup is omitted; retain the command and ready state. Service fixtures are isolated and never publish production test posts.
32
32
 
33
33
  Begin writing captures with the terminal already visible. Hold the saved document and server-ready state, then show the homepage link and rendered article. In an embedding capture, verify the copied share URL, play and pause the embedded video, then switch to the picture. Review the exported timeline at several points in every clip and verify MP4/GIF duration, posters and file hashes before synchronizing references.
34
-
35
- Keep raw masters, temporary sites and manifests in ignored tools/.recordings/. Publish only verified hashed posters, MP4 clips and documentation GIFs under content/assets/. Run `npm run recordings:capture` from `web/js.gripe`; optional `DEMO` and `DEMO_LOCALE` select a project and language. Inspect the exported clips before running `npm run recordings:sync`. Stop the guest desktop after capture. The operator can also use [OBS Studio display capture](https://obsproject.com/kb/display-capture-sources) inside a VM; this automated pipeline uses [FFmpeg x11grab](https://ffmpeg.org/ffmpeg-devices.html#x11grab) and [Playwright CDP](https://playwright.dev/docs/api/class-browsertype#browser-type-connect-over-cdp).
36
-
37
- The builder emits each progressive file's exact Content-Length and Accept-Ranges policy, with immutable caching for content hashes. Generated audit PDFs live only in tools/reports/page-check.pdf and come from edgepress check.
34
+
35
+ Keep raw masters, temporary sites and manifests in ignored tools/.recordings/. Publish only verified hashed posters, MP4 clips and documentation GIFs under content/assets/. Run `npm run recordings:capture` from `web/js.gripe`; optional `DEMO` and `DEMO_LOCALE` select a project and language. Inspect the exported clips before running `npm run recordings:sync`. Stop the guest desktop after capture. The operator can also use [OBS Studio display capture](https://obsproject.com/kb/display-capture-sources) inside a VM; this automated pipeline uses [FFmpeg x11grab](https://ffmpeg.org/ffmpeg-devices.html#x11grab) and [Playwright CDP](https://playwright.dev/docs/api/class-browsertype#browser-type-connect-over-cdp).
36
+
37
+ The builder emits each progressive file's exact Content-Length and Accept-Ranges policy, with immutable caching for content hashes. Generated audit PDFs live only in tools/reports/page-check.pdf and come from edgepress check.
@@ -20,7 +20,7 @@
20
20
  "heading": "Platform configuration",
21
21
  "paragraphs": [
22
22
  "Cloudflare reads wrangler.jsonc and serves static assets without a Worker script. Vercel reads vercel.json. Tencent EdgeOne Pages reads edgeone.json. Alibaba Cloud ESA Pages reads esa.jsonc.",
23
- "Vercel and EdgeOne support repository deployment buttons. ESA uses repository import or the native deployment CLI. Authenticate in your chosen platform and run one deployment command, or use the manual deployment workflow after setting repository Secrets."
23
+ "Vercel and EdgeOne support repository deployment buttons. ESA uses repository import or the native deployment CLI. Authenticate in your chosen platform and run one deployment command locally. GitHub Actions runs dependency security audits only."
24
24
  ]
25
25
  },
26
26
  {
@@ -29,4 +29,4 @@ The guides now cover consent-gated tracking, statistics, advertising, and human-
29
29
 
30
30
  edgepress server watches source files, rebuilds the site, refreshes the browser, and updates the accessibility and agent-friendliness report. edgepress check also captures desktop and mobile screenshots and writes tools/page-check.pdf with Markdown and JSON summaries.
31
31
 
32
- The automated report checks generated markup and metadata. It does not establish legal compliance or replace manual keyboard, contrast, or assistive-technology review.
32
+ The automated report checks generated markup and metadata. It does not establish legal compliance or replace manual keyboard, contrast, or assistive-technology review.
@@ -29,4 +29,4 @@ tags:
29
29
 
30
30
  edgepress server 会监视源文件、重新构建网站、刷新浏览器,并更新无障碍化和 agent 友好度报告。edgepress check 还会捕获桌面与移动页面截图,并生成 tools/page-check.pdf,以及 Markdown 和 JSON 摘要。
31
31
 
32
- 自动报告检查生成的标记和元数据,但不能证明符合特定法律,也不能取代键盘、对比度或辅助技术的人工审核。
32
+ 自动报告检查生成的标记和元数据,但不能证明符合特定法律,也不能取代键盘、对比度或辅助技术的人工审核。