@forumulate/cli 0.8.0 → 0.10.0

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 (286) hide show
  1. package/README.md +11 -3
  2. package/dist/api/args.d.ts.map +1 -1
  3. package/dist/api/args.js +1 -0
  4. package/dist/api/args.js.map +1 -1
  5. package/dist/api/command.d.ts +1 -1
  6. package/dist/api/command.d.ts.map +1 -1
  7. package/dist/api/command.js +86 -11
  8. package/dist/api/command.js.map +1 -1
  9. package/dist/api/http.d.ts +8 -0
  10. package/dist/api/http.d.ts.map +1 -1
  11. package/dist/api/http.js +3 -2
  12. package/dist/api/http.js.map +1 -1
  13. package/dist/api/live-spec.d.ts +48 -0
  14. package/dist/api/live-spec.d.ts.map +1 -0
  15. package/dist/api/live-spec.js +72 -0
  16. package/dist/api/live-spec.js.map +1 -0
  17. package/dist/api/operations.json +1 -1
  18. package/dist/api/request.d.ts.map +1 -1
  19. package/dist/api/request.js +25 -1
  20. package/dist/api/request.js.map +1 -1
  21. package/dist/api/send.d.ts +10 -1
  22. package/dist/api/send.d.ts.map +1 -1
  23. package/dist/api/send.js +14 -3
  24. package/dist/api/send.js.map +1 -1
  25. package/dist/api/slim.d.ts +14 -0
  26. package/dist/api/slim.d.ts.map +1 -0
  27. package/dist/api/slim.js +174 -0
  28. package/dist/api/slim.js.map +1 -0
  29. package/dist/cache-command.d.ts +12 -0
  30. package/dist/cache-command.d.ts.map +1 -0
  31. package/dist/cache-command.js +93 -0
  32. package/dist/cache-command.js.map +1 -0
  33. package/dist/check/command.d.ts +48 -0
  34. package/dist/check/command.d.ts.map +1 -0
  35. package/dist/check/command.js +256 -0
  36. package/dist/check/command.js.map +1 -0
  37. package/dist/check/external.d.ts +66 -0
  38. package/dist/check/external.d.ts.map +1 -0
  39. package/dist/check/external.js +177 -0
  40. package/dist/check/external.js.map +1 -0
  41. package/dist/check/markdown-links.d.ts +38 -0
  42. package/dist/check/markdown-links.d.ts.map +1 -0
  43. package/dist/check/markdown-links.js +166 -0
  44. package/dist/check/markdown-links.js.map +1 -0
  45. package/dist/cli.js +42 -7
  46. package/dist/cli.js.map +1 -1
  47. package/dist/commands/completion.d.ts.map +1 -1
  48. package/dist/commands/completion.js +17 -0
  49. package/dist/commands/completion.js.map +1 -1
  50. package/dist/commands/context.d.ts.map +1 -1
  51. package/dist/commands/context.js +6 -2
  52. package/dist/commands/context.js.map +1 -1
  53. package/dist/commands/groups-api.d.ts.map +1 -1
  54. package/dist/commands/groups-api.js +20 -2
  55. package/dist/commands/groups-api.js.map +1 -1
  56. package/dist/commands/groups-docs.d.ts.map +1 -1
  57. package/dist/commands/groups-docs.js +8 -2
  58. package/dist/commands/groups-docs.js.map +1 -1
  59. package/dist/commands/groups-jobs.d.ts +10 -0
  60. package/dist/commands/groups-jobs.d.ts.map +1 -0
  61. package/dist/commands/groups-jobs.js +89 -0
  62. package/dist/commands/groups-jobs.js.map +1 -0
  63. package/dist/commands/groups-org.d.ts.map +1 -1
  64. package/dist/commands/groups-org.js +59 -2
  65. package/dist/commands/groups-org.js.map +1 -1
  66. package/dist/commands/groups-site.d.ts.map +1 -1
  67. package/dist/commands/groups-site.js +47 -10
  68. package/dist/commands/groups-site.js.map +1 -1
  69. package/dist/commands/groups-spaces.d.ts.map +1 -1
  70. package/dist/commands/groups-spaces.js +11 -5
  71. package/dist/commands/groups-spaces.js.map +1 -1
  72. package/dist/commands/groups-types.d.ts.map +1 -1
  73. package/dist/commands/groups-types.js +74 -0
  74. package/dist/commands/groups-types.js.map +1 -1
  75. package/dist/commands/groups.d.ts.map +1 -1
  76. package/dist/commands/groups.js +2 -0
  77. package/dist/commands/groups.js.map +1 -1
  78. package/dist/commands/index.d.ts +9 -0
  79. package/dist/commands/index.d.ts.map +1 -1
  80. package/dist/commands/index.js +18 -3
  81. package/dist/commands/index.js.map +1 -1
  82. package/dist/commands/job-wait.d.ts +64 -0
  83. package/dist/commands/job-wait.d.ts.map +1 -0
  84. package/dist/commands/job-wait.js +91 -0
  85. package/dist/commands/job-wait.js.map +1 -0
  86. package/dist/commands/resource.d.ts +19 -0
  87. package/dist/commands/resource.d.ts.map +1 -1
  88. package/dist/commands/resource.js +65 -3
  89. package/dist/commands/resource.js.map +1 -1
  90. package/dist/content/library.d.ts +8 -0
  91. package/dist/content/library.d.ts.map +1 -1
  92. package/dist/content/library.js +10 -2
  93. package/dist/content/library.js.map +1 -1
  94. package/dist/credentials.d.ts +43 -4
  95. package/dist/credentials.d.ts.map +1 -1
  96. package/dist/credentials.js +67 -4
  97. package/dist/credentials.js.map +1 -1
  98. package/dist/dev/command.d.ts +41 -0
  99. package/dist/dev/command.d.ts.map +1 -0
  100. package/dist/dev/command.js +158 -0
  101. package/dist/dev/command.js.map +1 -0
  102. package/dist/doctor/address-checks.d.ts +56 -0
  103. package/dist/doctor/address-checks.d.ts.map +1 -0
  104. package/dist/doctor/address-checks.js +183 -0
  105. package/dist/doctor/address-checks.js.map +1 -0
  106. package/dist/doctor/boilerplate.d.ts +33 -0
  107. package/dist/doctor/boilerplate.d.ts.map +1 -0
  108. package/dist/doctor/boilerplate.js +78 -0
  109. package/dist/doctor/boilerplate.js.map +1 -0
  110. package/dist/doctor/command.d.ts +18 -0
  111. package/dist/doctor/command.d.ts.map +1 -0
  112. package/dist/doctor/command.js +234 -0
  113. package/dist/doctor/command.js.map +1 -0
  114. package/dist/doctor/crawl.d.ts +49 -0
  115. package/dist/doctor/crawl.d.ts.map +1 -0
  116. package/dist/doctor/crawl.js +210 -0
  117. package/dist/doctor/crawl.js.map +1 -0
  118. package/dist/doctor/extended.d.ts +52 -0
  119. package/dist/doctor/extended.d.ts.map +1 -0
  120. package/dist/doctor/extended.js +150 -0
  121. package/dist/doctor/extended.js.map +1 -0
  122. package/dist/doctor/page-checks.d.ts +42 -0
  123. package/dist/doctor/page-checks.d.ts.map +1 -0
  124. package/dist/doctor/page-checks.js +200 -0
  125. package/dist/doctor/page-checks.js.map +1 -0
  126. package/dist/doctor/probe.d.ts +63 -0
  127. package/dist/doctor/probe.d.ts.map +1 -0
  128. package/dist/doctor/probe.js +170 -0
  129. package/dist/doctor/probe.js.map +1 -0
  130. package/dist/doctor/reader-auth-atlas.d.ts +18 -0
  131. package/dist/doctor/reader-auth-atlas.d.ts.map +1 -0
  132. package/dist/doctor/reader-auth-atlas.js +50 -0
  133. package/dist/doctor/reader-auth-atlas.js.map +1 -0
  134. package/dist/doctor/robots-params.d.ts +36 -0
  135. package/dist/doctor/robots-params.d.ts.map +1 -0
  136. package/dist/doctor/robots-params.js +97 -0
  137. package/dist/doctor/robots-params.js.map +1 -0
  138. package/dist/doctor/site.d.ts +42 -0
  139. package/dist/doctor/site.d.ts.map +1 -0
  140. package/dist/doctor/site.js +82 -0
  141. package/dist/doctor/site.js.map +1 -0
  142. package/dist/doctor.d.ts +21 -0
  143. package/dist/doctor.d.ts.map +1 -1
  144. package/dist/doctor.js +94 -3
  145. package/dist/doctor.js.map +1 -1
  146. package/dist/exit-codes.d.ts +40 -0
  147. package/dist/exit-codes.d.ts.map +1 -0
  148. package/dist/exit-codes.js +66 -0
  149. package/dist/exit-codes.js.map +1 -0
  150. package/dist/help-commands.d.ts +13 -0
  151. package/dist/help-commands.d.ts.map +1 -0
  152. package/dist/help-commands.js +215 -0
  153. package/dist/help-commands.js.map +1 -0
  154. package/dist/help.d.ts +1 -1
  155. package/dist/help.d.ts.map +1 -1
  156. package/dist/help.js +74 -11
  157. package/dist/help.js.map +1 -1
  158. package/dist/io.d.ts +33 -0
  159. package/dist/io.d.ts.map +1 -0
  160. package/dist/io.js +81 -0
  161. package/dist/io.js.map +1 -0
  162. package/dist/preview-comment.d.ts +20 -0
  163. package/dist/preview-comment.d.ts.map +1 -0
  164. package/dist/preview-comment.js +88 -0
  165. package/dist/preview-comment.js.map +1 -0
  166. package/dist/publish/about.d.ts +23 -0
  167. package/dist/publish/about.d.ts.map +1 -0
  168. package/dist/publish/about.js +66 -0
  169. package/dist/publish/about.js.map +1 -0
  170. package/dist/publish/api.d.ts +30 -12
  171. package/dist/publish/api.d.ts.map +1 -1
  172. package/dist/publish/api.js +62 -10
  173. package/dist/publish/api.js.map +1 -1
  174. package/dist/publish/client.d.ts +19 -0
  175. package/dist/publish/client.d.ts.map +1 -0
  176. package/dist/publish/client.js +3 -0
  177. package/dist/publish/client.js.map +1 -0
  178. package/dist/publish/command.d.ts +51 -2
  179. package/dist/publish/command.d.ts.map +1 -1
  180. package/dist/publish/command.js +157 -17
  181. package/dist/publish/command.js.map +1 -1
  182. package/dist/publish/context.d.ts +12 -1
  183. package/dist/publish/context.d.ts.map +1 -1
  184. package/dist/publish/context.js.map +1 -1
  185. package/dist/publish/diff.d.ts +21 -0
  186. package/dist/publish/diff.d.ts.map +1 -0
  187. package/dist/publish/diff.js +96 -0
  188. package/dist/publish/diff.js.map +1 -0
  189. package/dist/publish/docs-apply.d.ts +8 -1
  190. package/dist/publish/docs-apply.d.ts.map +1 -1
  191. package/dist/publish/docs-apply.js +49 -10
  192. package/dist/publish/docs-apply.js.map +1 -1
  193. package/dist/publish/docs-plan.d.ts +16 -3
  194. package/dist/publish/docs-plan.d.ts.map +1 -1
  195. package/dist/publish/docs-plan.js +57 -6
  196. package/dist/publish/docs-plan.js.map +1 -1
  197. package/dist/publish/extras.d.ts +10 -0
  198. package/dist/publish/extras.d.ts.map +1 -1
  199. package/dist/publish/extras.js +54 -2
  200. package/dist/publish/extras.js.map +1 -1
  201. package/dist/publish/frontmatter.d.ts +1 -1
  202. package/dist/publish/frontmatter.d.ts.map +1 -1
  203. package/dist/publish/frontmatter.js +1 -0
  204. package/dist/publish/frontmatter.js.map +1 -1
  205. package/dist/publish/index.d.ts +12 -0
  206. package/dist/publish/index.d.ts.map +1 -0
  207. package/dist/publish/index.js +17 -0
  208. package/dist/publish/index.js.map +1 -0
  209. package/dist/publish/manifest.d.ts.map +1 -1
  210. package/dist/publish/manifest.js +48 -3
  211. package/dist/publish/manifest.js.map +1 -1
  212. package/dist/publish/names.d.ts +28 -0
  213. package/dist/publish/names.d.ts.map +1 -0
  214. package/dist/publish/names.js +80 -0
  215. package/dist/publish/names.js.map +1 -0
  216. package/dist/publish/posts.d.ts.map +1 -1
  217. package/dist/publish/posts.js +46 -13
  218. package/dist/publish/posts.js.map +1 -1
  219. package/dist/publish/preview.d.ts +56 -0
  220. package/dist/publish/preview.d.ts.map +1 -0
  221. package/dist/publish/preview.js +133 -0
  222. package/dist/publish/preview.js.map +1 -0
  223. package/dist/publish/redirects.d.ts +13 -0
  224. package/dist/publish/redirects.d.ts.map +1 -0
  225. package/dist/publish/redirects.js +154 -0
  226. package/dist/publish/redirects.js.map +1 -0
  227. package/dist/publish/reserved.d.ts +49 -0
  228. package/dist/publish/reserved.d.ts.map +1 -0
  229. package/dist/publish/reserved.js +118 -0
  230. package/dist/publish/reserved.js.map +1 -0
  231. package/dist/publish/rewrite.d.ts +12 -0
  232. package/dist/publish/rewrite.d.ts.map +1 -1
  233. package/dist/publish/rewrite.js +22 -0
  234. package/dist/publish/rewrite.js.map +1 -1
  235. package/dist/publish/scan-docs.d.ts +10 -0
  236. package/dist/publish/scan-docs.d.ts.map +1 -0
  237. package/dist/publish/scan-docs.js +160 -0
  238. package/dist/publish/scan-docs.js.map +1 -0
  239. package/dist/publish/scan.d.ts +21 -17
  240. package/dist/publish/scan.d.ts.map +1 -1
  241. package/dist/publish/scan.js +99 -232
  242. package/dist/publish/scan.js.map +1 -1
  243. package/dist/publish/slots.d.ts +39 -0
  244. package/dist/publish/slots.d.ts.map +1 -0
  245. package/dist/publish/slots.js +64 -0
  246. package/dist/publish/slots.js.map +1 -0
  247. package/dist/publish/studio-edits.d.ts +25 -0
  248. package/dist/publish/studio-edits.d.ts.map +1 -0
  249. package/dist/publish/studio-edits.js +53 -0
  250. package/dist/publish/studio-edits.js.map +1 -0
  251. package/dist/publish/tags.d.ts +9 -0
  252. package/dist/publish/tags.d.ts.map +1 -0
  253. package/dist/publish/tags.js +194 -0
  254. package/dist/publish/tags.js.map +1 -0
  255. package/dist/publish/types.d.ts +84 -1
  256. package/dist/publish/types.d.ts.map +1 -1
  257. package/dist/publish/types.js +0 -10
  258. package/dist/publish/types.js.map +1 -1
  259. package/dist/publish-command.d.ts +55 -0
  260. package/dist/publish-command.d.ts.map +1 -0
  261. package/dist/publish-command.js +197 -0
  262. package/dist/publish-command.js.map +1 -0
  263. package/dist/run.d.ts +3 -10
  264. package/dist/run.d.ts.map +1 -1
  265. package/dist/run.js +171 -112
  266. package/dist/run.js.map +1 -1
  267. package/dist/translations/target.d.ts.map +1 -1
  268. package/dist/translations/target.js +2 -2
  269. package/dist/translations/target.js.map +1 -1
  270. package/dist/validate.d.ts +39 -0
  271. package/dist/validate.d.ts.map +1 -0
  272. package/dist/validate.js +166 -0
  273. package/dist/validate.js.map +1 -0
  274. package/dist/version.d.ts +8 -0
  275. package/dist/version.d.ts.map +1 -0
  276. package/dist/version.js +11 -0
  277. package/dist/version.js.map +1 -0
  278. package/dist/whoami.d.ts +41 -0
  279. package/dist/whoami.d.ts.map +1 -0
  280. package/dist/whoami.js +161 -0
  281. package/dist/whoami.js.map +1 -0
  282. package/package.json +2 -2
  283. package/dist/publish-dir.d.ts +0 -54
  284. package/dist/publish-dir.d.ts.map +0 -1
  285. package/dist/publish-dir.js +0 -119
  286. package/dist/publish-dir.js.map +0 -1
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PREVIEW_NAME = void 0;
4
+ exports.ciSource = ciSource;
5
+ exports.sendPreview = sendPreview;
6
+ const api_1 = require("./api");
7
+ const context_1 = require("./context");
8
+ const docs_apply_1 = require("./docs-apply");
9
+ /** The name a preview may have — the API's rule (`pr-123`, `mr-45`, `feature-x`). */
10
+ exports.PREVIEW_NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/i;
11
+ /**
12
+ * The pull request this run is for, from the CI's own variables — GitHub
13
+ * Actions, GitLab CI, Bitbucket Pipelines, Gitea/Forgejo Actions, Azure
14
+ * Pipelines — or `FORUMULATE_PREVIEW_*` for anything else. Every field is
15
+ * optional: a preview made from a laptop simply has no source.
16
+ */
17
+ function ciSource(env) {
18
+ const pick = (...vals) => vals.find((v) => v && v.trim())?.trim();
19
+ if (env.FORUMULATE_PREVIEW_PROVIDER || env.FORUMULATE_PREVIEW_URL)
20
+ return clean({
21
+ provider: env.FORUMULATE_PREVIEW_PROVIDER,
22
+ repository: env.FORUMULATE_PREVIEW_REPOSITORY,
23
+ number: env.FORUMULATE_PREVIEW_NUMBER,
24
+ ref: env.FORUMULATE_PREVIEW_REF,
25
+ sha: env.FORUMULATE_PREVIEW_SHA,
26
+ url: env.FORUMULATE_PREVIEW_URL,
27
+ });
28
+ if (env.GITLAB_CI)
29
+ return clean({
30
+ provider: 'gitlab',
31
+ repository: env.CI_PROJECT_PATH,
32
+ number: env.CI_MERGE_REQUEST_IID,
33
+ ref: pick(env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME, env.CI_COMMIT_REF_NAME),
34
+ sha: env.CI_COMMIT_SHA,
35
+ url: env.CI_PROJECT_URL && env.CI_MERGE_REQUEST_IID
36
+ ? `${env.CI_PROJECT_URL}/-/merge_requests/${env.CI_MERGE_REQUEST_IID}`
37
+ : undefined,
38
+ });
39
+ if (env.BITBUCKET_REPO_FULL_NAME)
40
+ return clean({
41
+ provider: 'bitbucket',
42
+ repository: env.BITBUCKET_REPO_FULL_NAME,
43
+ number: env.BITBUCKET_PR_ID,
44
+ ref: env.BITBUCKET_BRANCH,
45
+ sha: env.BITBUCKET_COMMIT,
46
+ url: env.BITBUCKET_PR_ID
47
+ ? `https://bitbucket.org/${env.BITBUCKET_REPO_FULL_NAME}/pull-requests/${env.BITBUCKET_PR_ID}`
48
+ : undefined,
49
+ });
50
+ if (env.GITHUB_ACTIONS || env.GITEA_ACTIONS) {
51
+ const number = /^refs\/pull\/(\d+)\//.exec(env.GITHUB_REF ?? '')?.[1];
52
+ const server = (env.GITHUB_SERVER_URL ?? 'https://github.com').replace(/\/$/, '');
53
+ return clean({
54
+ provider: env.GITEA_ACTIONS ? 'gitea' : 'github',
55
+ repository: env.GITHUB_REPOSITORY,
56
+ number,
57
+ ref: pick(env.GITHUB_HEAD_REF, env.GITHUB_REF_NAME),
58
+ sha: env.GITHUB_SHA,
59
+ url: number && env.GITHUB_REPOSITORY ? `${server}/${env.GITHUB_REPOSITORY}/pull/${number}` : undefined,
60
+ });
61
+ }
62
+ if (env.TF_BUILD)
63
+ return clean({
64
+ provider: 'azure',
65
+ repository: env.BUILD_REPOSITORY_NAME,
66
+ number: env.SYSTEM_PULLREQUEST_PULLREQUESTID,
67
+ ref: env.SYSTEM_PULLREQUEST_SOURCEBRANCH,
68
+ sha: env.BUILD_SOURCEVERSION,
69
+ });
70
+ return {};
71
+ }
72
+ function clean(s) {
73
+ return Object.fromEntries(Object.entries(s).filter(([, v]) => v));
74
+ }
75
+ /** Bytes per request: comfortably under the API's body limit. */
76
+ const BATCH_BYTES = 3_000_000;
77
+ /** Send this space's planned pages to the preview; returns what the API answered. */
78
+ async function sendPreview(ctx, plan, existingAssets, opts) {
79
+ const sends = [...plan.sends.values()].flat();
80
+ const removed = plan.prunePages.map((p) => p.slug);
81
+ if (!sends.length && !removed.length) {
82
+ ctx.line({ verb: 'same', what: `preview ${opts.name}`, detail: 'nothing differs from what is published' });
83
+ }
84
+ // A preview writes no page, but it does upload the pictures those pages use.
85
+ const writer = new api_1.PublishApi({ ...ctx.api.opts, readOnly: false });
86
+ const wctx = { ...ctx, api: writer };
87
+ const urls = await (0, docs_apply_1.uploadAssetsFor)(wctx, sends.map((s) => s.page.file), existingAssets);
88
+ const pages = sends.map((s) => ({
89
+ slug: s.page.slug,
90
+ title: s.page.title,
91
+ file: s.page.file,
92
+ markdown: (0, docs_apply_1.payloadOf)(wctx, s.page, urls.get(s.page.file) ?? new Map()),
93
+ }));
94
+ const batches = [[]];
95
+ let size = 0;
96
+ for (const p of pages) {
97
+ if (size + p.markdown.length > BATCH_BYTES && batches[batches.length - 1].length) {
98
+ batches.push([]);
99
+ size = 0;
100
+ }
101
+ batches[batches.length - 1].push(p);
102
+ size += p.markdown.length;
103
+ }
104
+ let answer = null;
105
+ for (const [i, batch] of batches.entries()) {
106
+ answer = await writer.post((0, context_1.spacePath)(ctx, '/previews'), {
107
+ name: opts.name,
108
+ pages: batch,
109
+ // Removals ride on the first request; later ones only add pages.
110
+ ...(i === 0 && removed.length ? { removed } : {}),
111
+ ...(i > 0 ? { append: true } : {}),
112
+ ...(Object.keys(opts.source).length ? { source: opts.source } : {}),
113
+ ...(opts.ttlDays ? { ttlDays: opts.ttlDays } : {}),
114
+ });
115
+ }
116
+ if (!answer)
117
+ return null;
118
+ for (const s of sends)
119
+ ctx.line({ verb: 'preview', what: `page ${s.page.slug}`, detail: `${s.why} — in preview ${opts.name}` });
120
+ for (const slug of removed)
121
+ ctx.line({ verb: 'preview', what: `page ${slug}`, detail: `removed — in preview ${opts.name}` });
122
+ return {
123
+ space: ctx.spec.space ?? ctx.spaceId,
124
+ id: answer.preview.id,
125
+ name: answer.preview.name,
126
+ token: answer.token,
127
+ urls: answer.urls,
128
+ expiresAt: answer.preview.expiresAt,
129
+ summary: answer.preview.summary,
130
+ comment: answer.comment,
131
+ };
132
+ }
133
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../src/publish/preview.ts"],"names":[],"mappings":";;;AAkDA,4BAuDC;AAUD,kCAgEC;AAnLD,+BAAmC;AACnC,uCAAqD;AAErD,6CAA0D;AAsC1D,qFAAqF;AACxE,QAAA,YAAY,GAAG,8BAA8B,CAAC;AAE3D;;;;;GAKG;AACH,SAAgB,QAAQ,CAAC,GAAsB;IAC7C,MAAM,IAAI,GAAG,CAAC,GAAG,IAA4B,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;IAC1F,IAAI,GAAG,CAAC,2BAA2B,IAAI,GAAG,CAAC,sBAAsB;QAC/D,OAAO,KAAK,CAAC;YACX,QAAQ,EAAE,GAAG,CAAC,2BAA2B;YACzC,UAAU,EAAE,GAAG,CAAC,6BAA6B;YAC7C,MAAM,EAAE,GAAG,CAAC,yBAAyB;YACrC,GAAG,EAAE,GAAG,CAAC,sBAAsB;YAC/B,GAAG,EAAE,GAAG,CAAC,sBAAsB;YAC/B,GAAG,EAAE,GAAG,CAAC,sBAAsB;SAChC,CAAC,CAAC;IACL,IAAI,GAAG,CAAC,SAAS;QACf,OAAO,KAAK,CAAC;YACX,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,GAAG,CAAC,eAAe;YAC/B,MAAM,EAAE,GAAG,CAAC,oBAAoB;YAChC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,mCAAmC,EAAE,GAAG,CAAC,kBAAkB,CAAC;YAC1E,GAAG,EAAE,GAAG,CAAC,aAAa;YACtB,GAAG,EACD,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,oBAAoB;gBAC5C,CAAC,CAAC,GAAG,GAAG,CAAC,cAAc,qBAAqB,GAAG,CAAC,oBAAoB,EAAE;gBACtE,CAAC,CAAC,SAAS;SAChB,CAAC,CAAC;IACL,IAAI,GAAG,CAAC,wBAAwB;QAC9B,OAAO,KAAK,CAAC;YACX,QAAQ,EAAE,WAAW;YACrB,UAAU,EAAE,GAAG,CAAC,wBAAwB;YACxC,MAAM,EAAE,GAAG,CAAC,eAAe;YAC3B,GAAG,EAAE,GAAG,CAAC,gBAAgB;YACzB,GAAG,EAAE,GAAG,CAAC,gBAAgB;YACzB,GAAG,EAAE,GAAG,CAAC,eAAe;gBACtB,CAAC,CAAC,yBAAyB,GAAG,CAAC,wBAAwB,kBAAkB,GAAG,CAAC,eAAe,EAAE;gBAC9F,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;IACL,IAAI,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,iBAAiB,IAAI,oBAAoB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;YACX,QAAQ,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;YAChD,UAAU,EAAE,GAAG,CAAC,iBAAiB;YACjC,MAAM;YACN,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,GAAG,CAAC,eAAe,CAAC;YACnD,GAAG,EAAE,GAAG,CAAC,UAAU;YACnB,GAAG,EAAE,MAAM,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,iBAAiB,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;SACvG,CAAC,CAAC;IACL,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ;QACd,OAAO,KAAK,CAAC;YACX,QAAQ,EAAE,OAAO;YACjB,UAAU,EAAE,GAAG,CAAC,qBAAqB;YACrC,MAAM,EAAE,GAAG,CAAC,gCAAgC;YAC5C,GAAG,EAAE,GAAG,CAAC,+BAA+B;YACxC,GAAG,EAAE,GAAG,CAAC,mBAAmB;SAC7B,CAAC,CAAC;IACL,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,KAAK,CAAC,CAAgB;IAC7B,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAkB,CAAC;AACrF,CAAC;AAED,iEAAiE;AACjE,MAAM,WAAW,GAAG,SAAS,CAAC;AAE9B,qFAAqF;AAC9E,KAAK,UAAU,WAAW,CAC/B,GAAa,EACb,IAAc,EACd,cAAmC,EACnC,IAA+D;IAE/D,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACrC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC,CAAC;IAC7G,CAAC;IACD,6EAA6E;IAC7E,MAAM,MAAM,GAAG,IAAI,gBAAU,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,MAAM,IAAI,GAAa,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAe,EAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,CAAC;IACxF,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;QACjB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;QACjB,QAAQ,EAAE,IAAA,sBAAS,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;KACtE,CAAC,CAAC,CAAC;IACJ,MAAM,OAAO,GAAqB,CAAC,EAAE,CAAC,CAAC;IACvC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,MAAM,EAAE,CAAC;YAClF,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjB,IAAI,GAAG,CAAC,CAAC;QACX,CAAC;QACD,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC5B,CAAC;IAOD,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,KAAK,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3C,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAS,IAAA,mBAAS,EAAC,GAAG,EAAE,WAAW,CAAC,EAAE;YAC9D,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,KAAK;YACZ,iEAAiE;YACjE,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,KAAK;QACnB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,iBAAiB,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC3G,KAAK,MAAM,IAAI,IAAI,OAAO;QACxB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,EAAE,wBAAwB,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACnG,OAAO;QACL,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO;QACpC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE;QACrB,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;QACzB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;QACnC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type SpaceCtx } from './context';
2
+ import type { ManifestRedirect } from './types';
3
+ /** The rules a CSV file declares, by column name when it has a header. */
4
+ export declare function rulesFromCsv(text: string): ManifestRedirect[];
5
+ /** The rules as CSV in the import's columns — what the API is sent. */
6
+ export declare function rulesToCsv(rules: ManifestRedirect[]): string;
7
+ /** What the manifest declares for this space, read from the list or the file. */
8
+ export declare function declaredRedirects(spec: {
9
+ redirects?: ManifestRedirect[] | string;
10
+ }, manifestFile: string | null, root: string): ManifestRedirect[];
11
+ /** Plan or apply this space's declared redirects. */
12
+ export declare function syncRedirects(ctx: SpaceCtx, apply: boolean, manifestFile: string | null): Promise<void>;
13
+ //# sourceMappingURL=redirects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../src/publish/redirects.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAwDhD,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAqB7D;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAM5D;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAAA;CAAE,EACjD,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,IAAI,EAAE,MAAM,GACX,gBAAgB,EAAE,CAMpB;AAMD,qDAAqD;AACrD,wBAAsB,aAAa,CACjC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAmCf"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rulesFromCsv = rulesFromCsv;
4
+ exports.rulesToCsv = rulesToCsv;
5
+ exports.declaredRedirects = declaredRedirects;
6
+ exports.syncRedirects = syncRedirects;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = require("node:path");
9
+ const context_1 = require("./context");
10
+ /**
11
+ * `redirects:` in forumulate.yaml, applied by `publish` (FMU-F09).
12
+ *
13
+ * A docs repository moves pages, and the redirects that keep the old addresses
14
+ * working belong in the same pull request as the move — not in a console
15
+ * someone has to remember to visit after the merge. So a space in the manifest
16
+ * may list them:
17
+ *
18
+ * redirects:
19
+ * - { from: /getting-started, to: /quickstart }
20
+ * - { from: /v1/*, to: /*, status: 301 }
21
+ *
22
+ * or name a CSV file in the redirect manager's columns
23
+ * (`redirects: redirects.csv`, `from,to,status,type,passQuery`).
24
+ *
25
+ * Merged, never replaced: a rule the file does not name is left alone (the
26
+ * console's rules, the platform's rename rules), so declaring three redirects
27
+ * cannot delete three hundred. The write is the redirect manager's own import
28
+ * (`POST …/redirects/import`, mode `merge`), which validates every rule,
29
+ * refuses loops and duplicates, and keeps the platform's rules — one door,
30
+ * whichever way a rule arrives.
31
+ */
32
+ /** A minimal CSV split — quoted fields and doubled quotes — for a manifest's CSV file. */
33
+ function records(text) {
34
+ const out = [];
35
+ let row = [];
36
+ let cell = '';
37
+ let quoted = false;
38
+ const src = text.replace(/^/, '');
39
+ for (let i = 0; i < src.length; i++) {
40
+ const c = src[i];
41
+ if (quoted) {
42
+ if (c === '"' && src[i + 1] === '"') {
43
+ cell += '"';
44
+ i++;
45
+ }
46
+ else if (c === '"')
47
+ quoted = false;
48
+ else
49
+ cell += c;
50
+ }
51
+ else if (c === '"' && cell === '')
52
+ quoted = true;
53
+ else if (c === ',') {
54
+ row.push(cell);
55
+ cell = '';
56
+ }
57
+ else if (c === '\n' || c === '\r') {
58
+ if (c === '\r' && src[i + 1] === '\n')
59
+ i++;
60
+ row.push(cell);
61
+ out.push(row);
62
+ row = [];
63
+ cell = '';
64
+ }
65
+ else
66
+ cell += c;
67
+ }
68
+ if (cell || row.length)
69
+ out.push([...row, cell]);
70
+ return out.filter((r) => r.some((c) => c.trim()));
71
+ }
72
+ /** The rules a CSV file declares, by column name when it has a header. */
73
+ function rulesFromCsv(text) {
74
+ const rows = records(text);
75
+ let cols = { from: 0, to: 1, status: 2, type: 3, passquery: 4 };
76
+ if (rows[0]?.some((c) => c.trim().toLowerCase() === 'from')) {
77
+ cols = {};
78
+ rows[0].forEach((c, i) => (cols[c.trim().toLowerCase()] = i));
79
+ rows.shift();
80
+ }
81
+ const get = (r, k) => (cols[k] === undefined ? '' : (r[cols[k]] ?? '').trim());
82
+ return rows
83
+ .filter((r) => !r[0].trim().startsWith('#'))
84
+ .map((r) => {
85
+ const rule = { from: get(r, 'from'), to: get(r, 'to') };
86
+ const status = Number(get(r, 'status'));
87
+ if ([301, 302, 307, 308].includes(status))
88
+ rule.status = status;
89
+ const type = get(r, 'type');
90
+ if (type === 'redirect' || type === 'rewrite')
91
+ rule.type = type;
92
+ const pass = get(r, 'passquery').toLowerCase();
93
+ if (pass)
94
+ rule.passQuery = ['true', '1', 'yes'].includes(pass);
95
+ return rule;
96
+ });
97
+ }
98
+ /** The rules as CSV in the import's columns — what the API is sent. */
99
+ function rulesToCsv(rules) {
100
+ const q = (v) => `"${String(v ?? '').replace(/"/g, '""')}"`;
101
+ return [
102
+ 'from,to,status,type,passQuery',
103
+ ...rules.map((r) => [r.from, r.to, r.status ?? '', r.type ?? '', r.passQuery ?? ''].map(q).join(',')),
104
+ ].join('\n');
105
+ }
106
+ /** What the manifest declares for this space, read from the list or the file. */
107
+ function declaredRedirects(spec, manifestFile, root) {
108
+ if (!spec.redirects)
109
+ return [];
110
+ if (Array.isArray(spec.redirects))
111
+ return spec.redirects;
112
+ const file = (0, node_path_1.resolve)(manifestFile ? (0, node_path_1.dirname)(manifestFile) : root, spec.redirects);
113
+ if (!(0, node_fs_1.existsSync)(file))
114
+ throw new Error(`redirects: no file at ${file}`);
115
+ return rulesFromCsv((0, node_fs_1.readFileSync)(file, 'utf8'));
116
+ }
117
+ /** The match key a stored rule and a declared one share (path + query condition). */
118
+ const keyOf = (r) => `${r.from}${r.match?.query && r.match.query !== 'ignore' ? `?${JSON.stringify(r.match.query)}` : ''}`;
119
+ /** Plan or apply this space's declared redirects. */
120
+ async function syncRedirects(ctx, apply, manifestFile) {
121
+ const declared = declaredRedirects(ctx.spec, manifestFile, ctx.root);
122
+ if (!declared.length)
123
+ return;
124
+ const live = await ctx.api
125
+ .get((0, context_1.spacePath)(ctx, '/redirects'))
126
+ .then((r) => r.redirects ?? [])
127
+ .catch(() => []);
128
+ const byKey = new Map(live.map((r) => [keyOf(r), r]));
129
+ const changes = declared.filter((d) => {
130
+ const had = byKey.get(keyOf(d));
131
+ return (!had ||
132
+ had.auto === true ||
133
+ had.to !== d.to ||
134
+ (had.status ?? 308) !== (d.status ?? 308) ||
135
+ (had.type ?? 'redirect') !== (d.type ?? 'redirect'));
136
+ });
137
+ if (!changes.length) {
138
+ ctx.line({ verb: 'same', what: 'redirects', detail: `${declared.length} declared, all in place` });
139
+ return;
140
+ }
141
+ for (const r of changes)
142
+ ctx.line({
143
+ verb: byKey.has(keyOf(r)) ? 'update' : 'create',
144
+ what: `redirect ${r.from}`,
145
+ detail: `→ ${r.to}${r.status ? ` (${r.status})` : ''}`,
146
+ });
147
+ if (!apply)
148
+ return;
149
+ await ctx.api.post((0, context_1.spacePath)(ctx, '/redirects/import'), {
150
+ csv: rulesToCsv(changes),
151
+ mode: 'merge',
152
+ });
153
+ }
154
+ //# sourceMappingURL=redirects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../src/publish/redirects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Names in a content folder that are never content (R-N11).
3
+ *
4
+ * A repository that holds a blog also holds a README that explains the
5
+ * repository, a LICENSE, editor folders and a `_drafts` folder of posts nobody
6
+ * has finished. Every customer publisher we were shown carried its own list of
7
+ * these, and the first version of each list was the one that published the
8
+ * README as a post — readers met "How to run this repo locally" at the top of
9
+ * a newsroom. The list lives here, once, and the guide prints it
10
+ * (docs/guides/content-as-code.md, "Reserved names").
11
+ *
12
+ * Three groups, each for its own reason:
13
+ *
14
+ * - Hidden and private: anything starting with `.` (`.git`, `.github`,
15
+ * `.DS_Store`) or `_` (`_drafts`, `_templates`, and the metadata files this
16
+ * tool reads itself: `_collection.yml`, `_tags.yml`). `node_modules`.
17
+ * - The manifest: `forumulate.yaml`, `.yml`, `.json`.
18
+ * - Repository paperwork, in any case and with any Markdown extension:
19
+ * README, LICENSE/LICENCE, CONTRIBUTING, CODE_OF_CONDUCT, SECURITY,
20
+ * CODEOWNERS, and GitBook's SUMMARY (a table of contents, not a page).
21
+ *
22
+ * README is the one with a second meaning. In a DOCS tree it is GitBook's way
23
+ * of naming a folder's own page, and existing docs repositories rely on that,
24
+ * so a page-backed space keeps it as the folder's index unless its manifest
25
+ * says `readme: skip`. A posts space has no folder pages, so there a README is
26
+ * always paperwork.
27
+ */
28
+ export declare const MANIFEST_NAMES: string[];
29
+ /** Repository paperwork, by file stem (lower-cased, extension dropped). */
30
+ export declare const PAPERWORK: readonly ["readme", "license", "licence", "contributing", "code_of_conduct", "code-of-conduct", "security", "codeowners", "summary"];
31
+ /** Folders that are never content, beyond the `.` and `_` prefixes. */
32
+ export declare const RESERVED_FOLDERS: readonly ["node_modules"];
33
+ /** Is this README-shaped (`README.md`, `readme.mdx`, `Readme.markdown`)? */
34
+ export declare const isReadme: (name: string) => boolean;
35
+ /**
36
+ * Why `name` is skipped, or null when it is content.
37
+ *
38
+ * `readmeIsIndex`: a docs space keeps README as a folder's page (see above).
39
+ */
40
+ export declare function reservedReason(name: string, isDir: boolean, readmeIsIndex: boolean): string | null;
41
+ /**
42
+ * The manifest's `ignore:` patterns, as a matcher over paths relative to the
43
+ * space folder. A small glob: `*` is any run within one segment, `**` any run
44
+ * of segments, `?` one character; a pattern without a `/` matches a name at
45
+ * any depth (`*.draft.md`), one with a `/` matches from the space folder
46
+ * (`archive/**`). A folder that matches is skipped with everything under it.
47
+ */
48
+ export declare function ignoreMatcher(patterns: readonly string[] | undefined): (rel: string) => boolean;
49
+ //# sourceMappingURL=reserved.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reserved.d.ts","sourceRoot":"","sources":["../../src/publish/reserved.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,cAAc,UAA2D,CAAC;AAEvF,2EAA2E;AAC3E,eAAO,MAAM,SAAS,sIAUZ,CAAC;AAEX,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,2BAA4B,CAAC;AAI1D,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,YAA8C,CAAC;AAEpF;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,OAAO,GACrB,MAAM,GAAG,IAAI,CASf;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CA6B/F"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isReadme = exports.RESERVED_FOLDERS = exports.PAPERWORK = exports.MANIFEST_NAMES = void 0;
4
+ exports.reservedReason = reservedReason;
5
+ exports.ignoreMatcher = ignoreMatcher;
6
+ const node_path_1 = require("node:path");
7
+ /**
8
+ * Names in a content folder that are never content (R-N11).
9
+ *
10
+ * A repository that holds a blog also holds a README that explains the
11
+ * repository, a LICENSE, editor folders and a `_drafts` folder of posts nobody
12
+ * has finished. Every customer publisher we were shown carried its own list of
13
+ * these, and the first version of each list was the one that published the
14
+ * README as a post — readers met "How to run this repo locally" at the top of
15
+ * a newsroom. The list lives here, once, and the guide prints it
16
+ * (docs/guides/content-as-code.md, "Reserved names").
17
+ *
18
+ * Three groups, each for its own reason:
19
+ *
20
+ * - Hidden and private: anything starting with `.` (`.git`, `.github`,
21
+ * `.DS_Store`) or `_` (`_drafts`, `_templates`, and the metadata files this
22
+ * tool reads itself: `_collection.yml`, `_tags.yml`). `node_modules`.
23
+ * - The manifest: `forumulate.yaml`, `.yml`, `.json`.
24
+ * - Repository paperwork, in any case and with any Markdown extension:
25
+ * README, LICENSE/LICENCE, CONTRIBUTING, CODE_OF_CONDUCT, SECURITY,
26
+ * CODEOWNERS, and GitBook's SUMMARY (a table of contents, not a page).
27
+ *
28
+ * README is the one with a second meaning. In a DOCS tree it is GitBook's way
29
+ * of naming a folder's own page, and existing docs repositories rely on that,
30
+ * so a page-backed space keeps it as the folder's index unless its manifest
31
+ * says `readme: skip`. A posts space has no folder pages, so there a README is
32
+ * always paperwork.
33
+ */
34
+ exports.MANIFEST_NAMES = ['forumulate.yaml', 'forumulate.yml', 'forumulate.json'];
35
+ /** Repository paperwork, by file stem (lower-cased, extension dropped). */
36
+ exports.PAPERWORK = [
37
+ 'readme',
38
+ 'license',
39
+ 'licence',
40
+ 'contributing',
41
+ 'code_of_conduct',
42
+ 'code-of-conduct',
43
+ 'security',
44
+ 'codeowners',
45
+ 'summary',
46
+ ];
47
+ /** Folders that are never content, beyond the `.` and `_` prefixes. */
48
+ exports.RESERVED_FOLDERS = ['node_modules'];
49
+ const stemOf = (name) => name.replace(/\.[^.]*$/, '').toLowerCase();
50
+ /** Is this README-shaped (`README.md`, `readme.mdx`, `Readme.markdown`)? */
51
+ const isReadme = (name) => /^readme\.(md|mdx|markdown)$/i.test(name);
52
+ exports.isReadme = isReadme;
53
+ /**
54
+ * Why `name` is skipped, or null when it is content.
55
+ *
56
+ * `readmeIsIndex`: a docs space keeps README as a folder's page (see above).
57
+ */
58
+ function reservedReason(name, isDir, readmeIsIndex) {
59
+ if (name.startsWith('.'))
60
+ return 'hidden';
61
+ if (name.startsWith('_'))
62
+ return isDir ? 'private folder' : 'private file';
63
+ if (exports.RESERVED_FOLDERS.includes(name))
64
+ return 'dependency folder';
65
+ if (exports.MANIFEST_NAMES.includes(name))
66
+ return 'the manifest';
67
+ if (isDir)
68
+ return null;
69
+ if ((0, exports.isReadme)(name) && readmeIsIndex)
70
+ return null;
71
+ if (exports.PAPERWORK.includes(stemOf(name)))
72
+ return 'repository paperwork';
73
+ return null;
74
+ }
75
+ /**
76
+ * The manifest's `ignore:` patterns, as a matcher over paths relative to the
77
+ * space folder. A small glob: `*` is any run within one segment, `**` any run
78
+ * of segments, `?` one character; a pattern without a `/` matches a name at
79
+ * any depth (`*.draft.md`), one with a `/` matches from the space folder
80
+ * (`archive/**`). A folder that matches is skipped with everything under it.
81
+ */
82
+ function ignoreMatcher(patterns) {
83
+ const res = (patterns ?? [])
84
+ .map((p) => p.trim().replace(/^\.\//, '').replace(/\/+$/, ''))
85
+ .filter(Boolean)
86
+ .map((p) => {
87
+ const anchored = p.includes('/');
88
+ let src = '';
89
+ for (let i = 0; i < p.length; i++) {
90
+ const c = p[i];
91
+ if (c === '*' && p[i + 1] === '*') {
92
+ // `**/` is "any folders, or none"; a bare `**` is "anything".
93
+ if (p[i + 2] === '/') {
94
+ src += '(?:.*/)?';
95
+ i += 2;
96
+ }
97
+ else {
98
+ src += '.*';
99
+ i += 1;
100
+ }
101
+ }
102
+ else if (c === '*')
103
+ src += '[^/]*';
104
+ else if (c === '?')
105
+ src += '[^/]';
106
+ else
107
+ src += c.replace(/[.+^${}()|[\]\\]/g, '\\$&');
108
+ }
109
+ return new RegExp(anchored ? `^${src}$` : `(?:^|/)${src}$`, 'i');
110
+ });
111
+ if (!res.length)
112
+ return () => false;
113
+ return (rel) => {
114
+ const path = node_path_1.posix.normalize(rel.split('\\').join('/'));
115
+ return res.some((re) => re.test(path));
116
+ };
117
+ }
118
+ //# sourceMappingURL=reserved.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reserved.js","sourceRoot":"","sources":["../../src/publish/reserved.ts"],"names":[],"mappings":"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"}
@@ -17,4 +17,16 @@ export declare function rewriteLinks(source: string, file: string, slugByFile: M
17
17
  export declare function rewriteAssets(source: string, urlByRef: Map<string, string>): string;
18
18
  /** The same substitution over a metadata patch (values that were local paths). */
19
19
  export declare function rewriteValue<T>(value: T, urlByRef: Map<string, string>): T;
20
+ /**
21
+ * Does the live text still point at every picture the file's body uses?
22
+ *
23
+ * The word comparison (`compare.ts`) ignores link and image targets on
24
+ * purpose — the importer rewrites them, so they are never the same string
25
+ * twice. That left one change invisible: an image replaced by a new one under
26
+ * the same name uploads under a new content hash, and the post kept pointing
27
+ * at the old picture because its words had not changed. So the targets are
28
+ * checked here instead, by the URL each reference resolves to: one that is
29
+ * not uploaded yet, or not in the live text, means the body must be sent.
30
+ */
31
+ export declare function mediaChanged(body: string, refs: Map<string, string> | undefined, urls: Map<string, string>, liveText: string): boolean;
20
32
  //# sourceMappingURL=rewrite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rewrite.d.ts","sourceRoot":"","sources":["../../src/publish/rewrite.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,CA0BR;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAcnF;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAQ1E"}
1
+ {"version":3,"file":"rewrite.d.ts","sourceRoot":"","sources":["../../src/publish/rewrite.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,CA0BR;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAcnF;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAQ1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACrC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACzB,QAAQ,EAAE,MAAM,GACf,OAAO,CAOT"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.rewriteLinks = rewriteLinks;
4
4
  exports.rewriteAssets = rewriteAssets;
5
5
  exports.rewriteValue = rewriteValue;
6
+ exports.mediaChanged = mediaChanged;
6
7
  const node_path_1 = require("node:path");
7
8
  /**
8
9
  * What changes between the file on disk and the text the API is sent.
@@ -79,4 +80,25 @@ function rewriteValue(value, urlByRef) {
79
80
  return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, rewriteValue(v, urlByRef)]));
80
81
  return value;
81
82
  }
83
+ /**
84
+ * Does the live text still point at every picture the file's body uses?
85
+ *
86
+ * The word comparison (`compare.ts`) ignores link and image targets on
87
+ * purpose — the importer rewrites them, so they are never the same string
88
+ * twice. That left one change invisible: an image replaced by a new one under
89
+ * the same name uploads under a new content hash, and the post kept pointing
90
+ * at the old picture because its words had not changed. So the targets are
91
+ * checked here instead, by the URL each reference resolves to: one that is
92
+ * not uploaded yet, or not in the live text, means the body must be sent.
93
+ */
94
+ function mediaChanged(body, refs, urls, liveText) {
95
+ for (const ref of refs?.keys() ?? []) {
96
+ if (!body.includes(ref))
97
+ continue; // a front-matter value: compared as a field
98
+ const url = urls.get(ref);
99
+ if (!url || !liveText.includes(url))
100
+ return true;
101
+ }
102
+ return false;
103
+ }
82
104
  //# sourceMappingURL=rewrite.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rewrite.js","sourceRoot":"","sources":["../../src/publish/rewrite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rewrite.js","sourceRoot":"","sources":["../../src/publish/rewrite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { DocsWalk, Reader, ScanResult, SpaceSpec } from './types';
2
+ /**
3
+ * The docs half of reading a folder: one top-level folder per collection,
4
+ * files at the root in the root collection, nested folders as parent pages
5
+ * (the folder's `index.md` — or `README.md`, unless the space says
6
+ * `readme: skip` — is the parent; a folder without one gets a title-only stub
7
+ * so its children still have somewhere to hang).
8
+ */
9
+ export declare function scanDocs(absDir: string, spec: SpaceSpec, out: ScanResult, read: Reader, w: DocsWalk): void;
10
+ //# sourceMappingURL=scan-docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-docs.d.ts","sourceRoot":"","sources":["../../src/publish/scan-docs.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAA8B,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEnG;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,QAAQ,GACV,IAAI,CA8BN"}