@geekity/cms 0.18.0 → 0.20.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 (182) hide show
  1. package/README.md +29 -25
  2. package/admin/components/admin-bar.njk +4 -3
  3. package/admin/components/public-admin-bar.njk +3 -1
  4. package/admin/layouts/shell.njk +1 -0
  5. package/admin/pages/documents/editor.njk +291 -192
  6. package/admin/static/admin.css +123 -13
  7. package/admin/static/location.js +38 -0
  8. package/dist/admin/documents.d.ts +18 -3
  9. package/dist/admin/documents.d.ts.map +1 -1
  10. package/dist/admin/documents.js +150 -21
  11. package/dist/admin/documents.js.map +1 -1
  12. package/dist/admin/editor-layout.d.ts +13 -0
  13. package/dist/admin/editor-layout.d.ts.map +1 -0
  14. package/dist/admin/editor-layout.js +62 -0
  15. package/dist/admin/editor-layout.js.map +1 -0
  16. package/dist/admin/enclosure-field.d.ts +2 -3
  17. package/dist/admin/enclosure-field.d.ts.map +1 -1
  18. package/dist/admin/enclosure-field.js +27 -7
  19. package/dist/admin/enclosure-field.js.map +1 -1
  20. package/dist/admin/headers.d.ts +1 -0
  21. package/dist/admin/headers.d.ts.map +1 -1
  22. package/dist/admin/headers.js +3 -0
  23. package/dist/admin/headers.js.map +1 -1
  24. package/dist/admin/location-field.d.ts +4 -3
  25. package/dist/admin/location-field.d.ts.map +1 -1
  26. package/dist/admin/location-field.js +10 -2
  27. package/dist/admin/location-field.js.map +1 -1
  28. package/dist/admin/media.d.ts.map +1 -1
  29. package/dist/admin/media.js +3 -0
  30. package/dist/admin/media.js.map +1 -1
  31. package/dist/admin/photo-field.d.ts +2 -3
  32. package/dist/admin/photo-field.d.ts.map +1 -1
  33. package/dist/admin/photo-field.js +4 -2
  34. package/dist/admin/photo-field.js.map +1 -1
  35. package/dist/admin/read-field.d.ts +2 -3
  36. package/dist/admin/read-field.d.ts.map +1 -1
  37. package/dist/admin/read-field.js +12 -4
  38. package/dist/admin/read-field.js.map +1 -1
  39. package/dist/config.d.ts +2 -0
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js.map +1 -1
  42. package/dist/content/citation.d.ts +5 -0
  43. package/dist/content/citation.d.ts.map +1 -1
  44. package/dist/content/citation.js +17 -0
  45. package/dist/content/citation.js.map +1 -1
  46. package/dist/content/kept-properties.d.ts +5 -0
  47. package/dist/content/kept-properties.d.ts.map +1 -0
  48. package/dist/content/kept-properties.js +12 -0
  49. package/dist/content/kept-properties.js.map +1 -0
  50. package/dist/content/location.d.ts +4 -0
  51. package/dist/content/location.d.ts.map +1 -1
  52. package/dist/content/location.js +35 -3
  53. package/dist/content/location.js.map +1 -1
  54. package/dist/content/locations.d.ts +2 -5
  55. package/dist/content/locations.d.ts.map +1 -1
  56. package/dist/content/locations.js +2 -77
  57. package/dist/content/locations.js.map +1 -1
  58. package/dist/content/markdown.d.ts +9 -0
  59. package/dist/content/markdown.d.ts.map +1 -1
  60. package/dist/content/markdown.js +37 -1
  61. package/dist/content/markdown.js.map +1 -1
  62. package/dist/content/permalink-file.d.ts +7 -0
  63. package/dist/content/permalink-file.d.ts.map +1 -0
  64. package/dist/content/permalink-file.js +77 -0
  65. package/dist/content/permalink-file.js.map +1 -0
  66. package/dist/content/post-type.d.ts +1 -6
  67. package/dist/content/post-type.d.ts.map +1 -1
  68. package/dist/content/post-type.js +13 -14
  69. package/dist/content/post-type.js.map +1 -1
  70. package/dist/content/slug.d.ts +2 -1
  71. package/dist/content/slug.d.ts.map +1 -1
  72. package/dist/content/slug.js +3 -1
  73. package/dist/content/slug.js.map +1 -1
  74. package/dist/env.d.ts +6 -0
  75. package/dist/env.d.ts.map +1 -1
  76. package/dist/federation/article.d.ts +8 -7
  77. package/dist/federation/article.d.ts.map +1 -1
  78. package/dist/federation/article.js +37 -18
  79. package/dist/federation/article.js.map +1 -1
  80. package/dist/federation/citations.d.ts +7 -6
  81. package/dist/federation/citations.d.ts.map +1 -1
  82. package/dist/federation/citations.js +44 -28
  83. package/dist/federation/citations.js.map +1 -1
  84. package/dist/federation/delivery.d.ts.map +1 -1
  85. package/dist/federation/delivery.js +23 -16
  86. package/dist/federation/delivery.js.map +1 -1
  87. package/dist/index.d.ts +5 -4
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +2 -1
  90. package/dist/index.js.map +1 -1
  91. package/dist/indieauth/bearer.d.ts +10 -6
  92. package/dist/indieauth/bearer.d.ts.map +1 -1
  93. package/dist/indieauth/bearer.js +11 -9
  94. package/dist/indieauth/bearer.js.map +1 -1
  95. package/dist/indieauth/token.js +1 -1
  96. package/dist/indieauth/token.js.map +1 -1
  97. package/dist/micropub/content.d.ts +15 -0
  98. package/dist/micropub/content.d.ts.map +1 -0
  99. package/dist/micropub/content.js +254 -0
  100. package/dist/micropub/content.js.map +1 -0
  101. package/dist/micropub/create.d.ts +7 -3
  102. package/dist/micropub/create.d.ts.map +1 -1
  103. package/dist/micropub/create.js +75 -24
  104. package/dist/micropub/create.js.map +1 -1
  105. package/dist/micropub/endpoint.d.ts +4 -5
  106. package/dist/micropub/endpoint.d.ts.map +1 -1
  107. package/dist/micropub/endpoint.js +33 -12
  108. package/dist/micropub/endpoint.js.map +1 -1
  109. package/dist/micropub/media.d.ts +6 -4
  110. package/dist/micropub/media.d.ts.map +1 -1
  111. package/dist/micropub/media.js +7 -5
  112. package/dist/micropub/media.js.map +1 -1
  113. package/dist/micropub/update.d.ts +7 -1
  114. package/dist/micropub/update.d.ts.map +1 -1
  115. package/dist/micropub/update.js +32 -7
  116. package/dist/micropub/update.js.map +1 -1
  117. package/dist/web/admin-bar.d.ts.map +1 -1
  118. package/dist/web/admin-bar.js +27 -1
  119. package/dist/web/admin-bar.js.map +1 -1
  120. package/dist/web/context.d.ts +10 -3
  121. package/dist/web/context.d.ts.map +1 -1
  122. package/dist/web/context.js +12 -2
  123. package/dist/web/context.js.map +1 -1
  124. package/dist/web/documents.d.ts +21 -6
  125. package/dist/web/documents.d.ts.map +1 -1
  126. package/dist/web/documents.js +23 -12
  127. package/dist/web/documents.js.map +1 -1
  128. package/dist/web/feed-item.d.ts +26 -3
  129. package/dist/web/feed-item.d.ts.map +1 -1
  130. package/dist/web/feed-item.js +63 -6
  131. package/dist/web/feed-item.js.map +1 -1
  132. package/dist/web/feed-rss.js +3 -3
  133. package/dist/web/feed-rss.js.map +1 -1
  134. package/dist/web/feed-source.d.ts +7 -0
  135. package/dist/web/feed-source.d.ts.map +1 -1
  136. package/dist/web/feed-source.js.map +1 -1
  137. package/dist/web/feeds.d.ts.map +1 -1
  138. package/dist/web/feeds.js +7 -1
  139. package/dist/web/feeds.js.map +1 -1
  140. package/dist/web/negotiate.d.ts +4 -0
  141. package/dist/web/negotiate.d.ts.map +1 -1
  142. package/dist/web/negotiate.js +5 -1
  143. package/dist/web/negotiate.js.map +1 -1
  144. package/dist/web/render.d.ts +5 -4
  145. package/dist/web/render.d.ts.map +1 -1
  146. package/dist/web/render.js +34 -12
  147. package/dist/web/render.js.map +1 -1
  148. package/dist/web/routes.d.ts.map +1 -1
  149. package/dist/web/routes.js +16 -4
  150. package/dist/web/routes.js.map +1 -1
  151. package/dist/web/sanitize.d.ts +10 -0
  152. package/dist/web/sanitize.d.ts.map +1 -1
  153. package/dist/web/sanitize.js +180 -0
  154. package/dist/web/sanitize.js.map +1 -1
  155. package/dist/web/templates.d.ts.map +1 -1
  156. package/dist/web/templates.js +2 -0
  157. package/dist/web/templates.js.map +1 -1
  158. package/dist/webmention/cited-picture.d.ts +37 -0
  159. package/dist/webmention/cited-picture.d.ts.map +1 -0
  160. package/dist/webmention/cited-picture.js +121 -0
  161. package/dist/webmention/cited-picture.js.map +1 -0
  162. package/dist/webmention/fetch-public.d.ts +26 -8
  163. package/dist/webmention/fetch-public.d.ts.map +1 -1
  164. package/dist/webmention/fetch-public.js +22 -12
  165. package/dist/webmention/fetch-public.js.map +1 -1
  166. package/dist/webmention/reply-context.d.ts +30 -8
  167. package/dist/webmention/reply-context.d.ts.map +1 -1
  168. package/dist/webmention/reply-context.js +238 -27
  169. package/dist/webmention/reply-context.js.map +1 -1
  170. package/dist/webmention/reply-contexts.d.ts +28 -16
  171. package/dist/webmention/reply-contexts.d.ts.map +1 -1
  172. package/dist/webmention/reply-contexts.js +108 -25
  173. package/dist/webmention/reply-contexts.js.map +1 -1
  174. package/package.json +10 -9
  175. package/themes/default/README.md +83 -9
  176. package/themes/default/layouts/post.njk +7 -7
  177. package/themes/default/partials/citations.njk +25 -4
  178. package/themes/default/partials/cited-page.njk +58 -0
  179. package/themes/default/partials/post-list.njk +8 -5
  180. package/themes/default/partials/reply-context.njk +9 -11
  181. package/themes/default/src/style.css +37 -0
  182. package/themes/default/static/style.css +83 -0
@@ -0,0 +1,121 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, readdir, rm, writeFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import sharp from 'sharp';
5
+ import { citedImageAlt } from '../content/citation.js';
6
+ import { matchesSignature, UPLOAD_MEDIA_TYPES } from '../content/media.js';
7
+ import { stripMetadata } from '../content/metadata/index.js';
8
+ import { generateImageVariants, removeImageVariants } from '../images/variants.js';
9
+ import { UPLOAD_ASSET_PREFIX, UPLOAD_DIRECTORY } from '../web/assets.js';
10
+ import { fetchPublic } from './fetch-public.js';
11
+ export const CITED_PICTURE_DIRECTORY = 'cited';
12
+ export const CITED_PICTURE_PREFIX = `${UPLOAD_ASSET_PREFIX}${CITED_PICTURE_DIRECTORY}/`;
13
+ export const CITED_PICTURE_TIMEOUT_MS = 10_000;
14
+ const IMAGE_EXTENSIONS = ['.png', '.jpg', '.gif', '.webp', '.avif'];
15
+ export async function copyCitedPicture(source, options) {
16
+ const fetched = await fetchPublic(source.url, {
17
+ lookup: options.lookup,
18
+ timeoutMs: options.timeoutMs ?? CITED_PICTURE_TIMEOUT_MS,
19
+ maxBytes: options.config.uploadMaxBytes,
20
+ accept: 'image/avif, image/webp, image/png, image/gif, image/jpeg;q=0.9',
21
+ contentType: { pattern: /^\s*image\//i, name: 'an image' },
22
+ });
23
+ if (!fetched.ok)
24
+ return undefined;
25
+ const extension = IMAGE_EXTENSIONS.find((candidate) => {
26
+ const media = UPLOAD_MEDIA_TYPES.get(candidate);
27
+ return media !== undefined && matchesSignature(media, fetched.body);
28
+ });
29
+ if (extension === undefined)
30
+ return undefined;
31
+ let bytes;
32
+ let size;
33
+ try {
34
+ bytes = stripMetadata(extension, fetched.body).bytes;
35
+ size = await uprightSize(bytes);
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ if (size === undefined)
41
+ return undefined;
42
+ const name = `${createHash('sha256').update(bytes).digest('hex').slice(0, 16)}${extension}`;
43
+ const directory = path.join(options.config.contentDir, UPLOAD_DIRECTORY, CITED_PICTURE_DIRECTORY);
44
+ await mkdir(directory, { recursive: true });
45
+ try {
46
+ await writeFile(path.join(directory, name), bytes, { flag: 'wx' });
47
+ }
48
+ catch (error) {
49
+ if (error.code !== 'EEXIST')
50
+ throw error;
51
+ }
52
+ try {
53
+ await generateImageVariants(options.config, `${CITED_PICTURE_DIRECTORY}/${name}`);
54
+ }
55
+ catch (error) {
56
+ const message = error instanceof Error ? error.message : String(error);
57
+ console.warn(`Copied ${name} but could not derive its variants: ${message}`);
58
+ }
59
+ return {
60
+ src: `${CITED_PICTURE_PREFIX}${name}`,
61
+ ...size,
62
+ kind: source.kind,
63
+ ...(source.video === true ? { video: true } : {}),
64
+ };
65
+ }
66
+ /** The size a reader sees: orientations 5 to 8 turn the picture on its side. */
67
+ async function uprightSize(bytes) {
68
+ const metadata = await sharp(bytes).metadata();
69
+ const width = metadata.width;
70
+ const height = metadata.pageHeight ?? metadata.height;
71
+ if (width === undefined || height === undefined)
72
+ return undefined;
73
+ return (metadata.orientation ?? 1) >= 5 ? { width: height, height: width } : { width, height };
74
+ }
75
+ export async function sweepCitedPictures(config, kept) {
76
+ const directory = path.join(config.contentDir, UPLOAD_DIRECTORY, CITED_PICTURE_DIRECTORY);
77
+ let names;
78
+ try {
79
+ names = await readdir(directory);
80
+ }
81
+ catch {
82
+ return;
83
+ }
84
+ for (const name of names) {
85
+ if (kept.has(`${CITED_PICTURE_PREFIX}${name}`))
86
+ continue;
87
+ const source = `${CITED_PICTURE_DIRECTORY}/${name}`;
88
+ await removeImageVariants(config, source);
89
+ await rm(path.join(directory, name), { force: true });
90
+ }
91
+ }
92
+ export function shownInFull(property, picture) {
93
+ return property === 'repost-of' && picture.kind === 'photo';
94
+ }
95
+ export function citesAnImage(context) {
96
+ return (context.picture?.kind === 'photo' && context.name === undefined && context.author === undefined);
97
+ }
98
+ export function citedPictureAlt(property, context, document) {
99
+ if (context.picture === undefined || !shownInFull(property, context.picture))
100
+ return '';
101
+ return citesAnImage(context) ? citedImageAlt(document) : (context.name ?? '');
102
+ }
103
+ export function parseCitedPicture(value) {
104
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
105
+ return undefined;
106
+ const fields = value;
107
+ const { src, width, height, kind } = fields;
108
+ if (typeof src !== 'string' ||
109
+ !src.startsWith(CITED_PICTURE_PREFIX) ||
110
+ src.slice(CITED_PICTURE_PREFIX.length).includes('/') ||
111
+ !positiveInteger(width) ||
112
+ !positiveInteger(height) ||
113
+ (kind !== 'photo' && kind !== 'thumbnail')) {
114
+ return undefined;
115
+ }
116
+ return { src, width, height, kind, ...(fields['video'] === true ? { video: true } : {}) };
117
+ }
118
+ function positiveInteger(value) {
119
+ return typeof value === 'number' && Number.isInteger(value) && value > 0;
120
+ }
121
+ //# sourceMappingURL=cited-picture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cited-picture.js","sourceRoot":"","sources":["../../src/webmention/cited-picture.ts"],"names":[],"mappings":"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"}
@@ -5,8 +5,9 @@ export interface FetchPublicOptions {
5
5
  readonly lookup: HostLookup;
6
6
  /** How long the whole exchange is given, body included. */
7
7
  readonly timeoutMs: number;
8
- /** The most of a body that is read. A bigger body is not read at all. */
8
+ /** The most of a body that is read. */
9
9
  readonly maxBytes: number;
10
+ readonly overflow?: 'refuse' | 'truncate';
10
11
  /** The `Accept` header sent. */
11
12
  readonly accept: string;
12
13
  /** The content types taken, and what to call anything else when refusing it. */
@@ -14,23 +15,40 @@ export interface FetchPublicOptions {
14
15
  readonly pattern: RegExp;
15
16
  readonly name: string;
16
17
  };
18
+ readonly headersOnly?: RegExp;
17
19
  }
18
- /** What one fetch came to. */
19
- export type PublicFetch = {
20
- readonly ok: true;
21
- /** The URL the body came from, after any redirects. */
20
+ interface PublicResponse {
21
+ /** The URL the response came from, after any redirects. */
22
22
  readonly url: string;
23
23
  /** The response's `Content-Type`. */
24
24
  readonly type: string;
25
25
  /** The response's `Link` header, or `null` when it sent none. */
26
26
  readonly link: string | null;
27
+ }
28
+ export interface PublicBody extends PublicResponse {
29
+ readonly ok: true;
30
+ readonly read: 'body';
27
31
  readonly body: Uint8Array;
28
- } | {
32
+ readonly truncated: boolean;
33
+ }
34
+ export interface PublicHeaders extends PublicResponse {
35
+ readonly ok: true;
36
+ readonly read: 'headers';
37
+ }
38
+ export interface PublicRefusal {
29
39
  readonly ok: false;
30
40
  readonly reason: string;
31
- };
41
+ }
42
+ /** What one fetch came to. */
43
+ export type PublicFetch = PublicBody | PublicHeaders | PublicRefusal;
32
44
  /** Fetch `target` within the limits `options` sets. */
33
- export declare function fetchPublic(target: string, options: FetchPublicOptions): Promise<PublicFetch>;
45
+ export declare function fetchPublic(target: string, options: FetchPublicOptions & {
46
+ readonly headersOnly: RegExp;
47
+ }): Promise<PublicFetch>;
48
+ export declare function fetchPublic(target: string, options: FetchPublicOptions & {
49
+ readonly headersOnly?: undefined;
50
+ }): Promise<PublicBody | PublicRefusal>;
34
51
  /** An http or https URL with a host, or `undefined`. */
35
52
  export declare function webUrl(value: string): URL | undefined;
53
+ export {};
36
54
  //# sourceMappingURL=fetch-public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-public.d.ts","sourceRoot":"","sources":["../../src/webmention/fetch-public.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAetD,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3E;AAED,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GACnB;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,uDAAuD;IACvD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC3B,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,uDAAuD;AACvD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,WAAW,CAAC,CA6CtB;AAED,wDAAwD;AACxD,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CASrD"}
1
+ {"version":3,"file":"fetch-public.d.ts","sourceRoot":"","sources":["../../src/webmention/fetch-public.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAetD,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC1C,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,UAAU,cAAc;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,aAAa,CAAC;AAErE,uDAAuD;AACvD,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,GAAG;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC7D,OAAO,CAAC,WAAW,CAAC,CAAC;AACxB,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,GAAG;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAA;CAAE,GACjE,OAAO,CAAC,UAAU,GAAG,aAAa,CAAC,CAAC;AAwDvC,wDAAwD;AACxD,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CASrD"}
@@ -11,7 +11,6 @@ import { publicHost } from './public-address.js';
11
11
  */
12
12
  /** How many redirects are followed, each one checked like the first. */
13
13
  const MAX_REDIRECTS = 5;
14
- /** Fetch `target` within the limits `options` sets. */
15
14
  export async function fetchPublic(target, options) {
16
15
  const signal = AbortSignal.timeout(options.timeoutMs);
17
16
  let at = target;
@@ -41,14 +40,19 @@ export async function fetchPublic(target, options) {
41
40
  return refuse(`answered ${String(response.status)}`);
42
41
  }
43
42
  const type = response.headers.get('content-type') ?? '';
43
+ const link = response.headers.get('link');
44
+ if (options.headersOnly?.test(type) === true) {
45
+ await response.body?.cancel();
46
+ return { ok: true, read: 'headers', url: url.href, type, link };
47
+ }
44
48
  if (!options.contentType.pattern.test(type)) {
45
49
  await response.body?.cancel();
46
50
  return refuse(`not ${options.contentType.name}`);
47
51
  }
48
- const body = await readWithin(response, options.maxBytes);
49
- if (body === undefined)
52
+ const read = await readWithin(response, options.maxBytes, options.overflow ?? 'refuse');
53
+ if (read === undefined)
50
54
  return refuse(`larger than ${String(options.maxBytes)} bytes`);
51
- return { ok: true, url: url.href, type, link: response.headers.get('link'), body };
55
+ return { ok: true, read: 'body', url: url.href, type, link, ...read };
52
56
  }
53
57
  }
54
58
  catch (thrown) {
@@ -68,16 +72,19 @@ export function webUrl(value) {
68
72
  return undefined;
69
73
  return url.hostname === '' ? undefined : url;
70
74
  }
71
- /** A response body when it is no bigger than the limit, else `undefined`. */
72
- async function readWithin(response, maxBytes) {
75
+ /**
76
+ * A response body no bigger than the limit. A bigger one is `undefined` when
77
+ * refused, or its first `maxBytes` when truncated.
78
+ */
79
+ async function readWithin(response, maxBytes, overflow) {
73
80
  const declared = Number(response.headers.get('content-length') ?? '0');
74
- if (declared > maxBytes) {
81
+ if (declared > maxBytes && overflow === 'refuse') {
75
82
  await response.body?.cancel();
76
83
  return undefined;
77
84
  }
78
85
  const body = response.body;
79
86
  if (body === null)
80
- return new Uint8Array();
87
+ return { body: new Uint8Array(), truncated: false };
81
88
  const reader = body.getReader();
82
89
  const chunks = [];
83
90
  let read = 0;
@@ -86,14 +93,17 @@ async function readWithin(response, maxBytes) {
86
93
  if (chunk.done)
87
94
  break;
88
95
  const value = chunk.value;
89
- read += value.length;
90
- if (read > maxBytes) {
96
+ if (read + value.length > maxBytes) {
91
97
  await reader.cancel();
92
- return undefined;
98
+ if (overflow === 'refuse')
99
+ return undefined;
100
+ chunks.push(value.subarray(0, maxBytes - read));
101
+ return { body: Buffer.concat(chunks), truncated: true };
93
102
  }
103
+ read += value.length;
94
104
  chunks.push(value);
95
105
  }
96
- return Buffer.concat(chunks);
106
+ return { body: Buffer.concat(chunks), truncated: false };
97
107
  }
98
108
  function refuse(reason) {
99
109
  return { ok: false, reason };
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-public.js","sourceRoot":"","sources":["../../src/webmention/fetch-public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;;;;;GAQG;AAEH,wEAAwE;AACxE,MAAM,aAAa,GAAG,CAAC,CAAC;AA8BxB,uDAAuD;AACvD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,OAA2B;IAE3B,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACtD,IAAI,EAAE,GAAG,MAAM,CAAC;IAEhB,IAAI,CAAC;QACH,KAAK,IAAI,GAAG,GAAG,CAAC,GAAI,GAAG,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;YACvB,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC,0BAA0B,CAAC,CAAC;YACjE,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBACtD,OAAO,MAAM,CAAC,sBAAsB,CAAC,CAAC;YACxC,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,qBAAqB,EAAE;gBACxE,QAAQ,EAAE,QAAQ;gBAClB,MAAM;aACP,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACzE,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;gBAC9B,IAAI,GAAG,KAAK,aAAa;oBAAE,OAAO,MAAM,CAAC,oBAAoB,CAAC,CAAC;gBAC/D,EAAE,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC;gBACjC,SAAS;YACX,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;gBAC9B,OAAO,MAAM,CAAC,YAAY,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YACxD,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5C,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;gBAC9B,OAAO,MAAM,CAAC,OAAO,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC1D,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC,eAAe,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEvF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,MAAM,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5E,OAAO,GAAG,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;AAC/C,CAAC;AAED,6EAA6E;AAC7E,KAAK,UAAU,UAAU,CAAC,QAAkB,EAAE,QAAgB;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,CAAC;IACvE,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,UAAU,EAAE,CAAC;IAE3C,MAAM,MAAM,GAAI,IAAmC,CAAC,SAAS,EAAE,CAAC;IAChE,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,SAAS,CAAC;QACR,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,IAAI;YAAE,MAAM;QACtB,MAAM,KAAK,GAAe,KAAK,CAAC,KAAK,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;QACrB,IAAI,IAAI,GAAG,QAAQ,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,MAAM,CAAC,MAAc;IAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC/B,CAAC"}
1
+ {"version":3,"file":"fetch-public.js","sourceRoot":"","sources":["../../src/webmention/fetch-public.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { CitedPicture, PictureSource } from './cited-picture.ts';
1
2
  import type { HostLookup } from './public-address.ts';
2
3
  /**
3
4
  * Reply context: what a reply shows of the post it answers (TASK-123).
@@ -10,7 +11,10 @@ import type { HostLookup } from './public-address.ts';
10
11
  */
11
12
  /** How long a target is given to answer, body included. */
12
13
  export declare const REPLY_CONTEXT_TIMEOUT_MS = 10000;
13
- /** The most of a target page that is read. A bigger page is not read at all. */
14
+ /**
15
+ * The most of a target page that is read. Only the head of a bigger page is
16
+ * read, and an oEmbed answer bigger than this is not read at all.
17
+ */
14
18
  export declare const REPLY_CONTEXT_MAX_BYTES = 1000000;
15
19
  /** What a reply shows of the post it answers. */
16
20
  export interface ReplyContext {
@@ -27,11 +31,15 @@ export interface ReplyContext {
27
31
  };
28
32
  /** When it says it was published, as an ISO 8601 instant. */
29
33
  readonly published?: string;
34
+ /** The site it is on, its `og:site_name`, kept only when it names no author. */
35
+ readonly site?: string;
36
+ /** Its picture, copied into the site's uploads (TASK-252). */
37
+ readonly picture?: CitedPicture;
30
38
  }
31
- /** What fetching one target came to. */
32
39
  export type ReplyContextFetch = {
33
40
  readonly ok: true;
34
41
  readonly context: ReplyContext;
42
+ readonly picture?: PictureSource;
35
43
  } | {
36
44
  readonly ok: false;
37
45
  readonly reason: string;
@@ -46,22 +54,36 @@ export interface FetchReplyContextOptions {
46
54
  readonly maxBytes?: number | undefined;
47
55
  }
48
56
  /**
49
- * Fetch a reply's target and read what it says about itself.
57
+ * Fetch a page a post cites and read what it says about itself. A known
58
+ * provider's oEmbed endpoint is asked first, and the page is read only when
59
+ * that names nothing. Any other page is read, and asked about through the
60
+ * oEmbed endpoint it links when it has no `h-entry`.
50
61
  *
51
62
  * Only http and https, only public hosts (every redirect hop is checked, and a
52
63
  * name is refused when any address it resolves to is private), one timeout
53
- * over the whole exchange, and no page over the byte limit. Nothing throws.
64
+ * over the whole exchange, every oEmbed request included, no more of a page
65
+ * than the byte limit, and no oEmbed answer over it. Nothing throws.
54
66
  */
55
67
  export declare function fetchReplyContext(target: string, options: FetchReplyContextOptions): Promise<ReplyContextFetch>;
68
+ export interface Oembed {
69
+ readonly title?: string;
70
+ readonly author?: {
71
+ readonly name: string;
72
+ readonly url?: string;
73
+ };
74
+ readonly picture?: PictureSource;
75
+ }
56
76
  /**
57
77
  * What a target page says about itself, or `undefined` when it says nothing a
58
78
  * preview could show.
59
79
  *
60
80
  * The first `h-entry` when there is one: its name when it has one of its own
61
81
  * (the test Post Type Discovery uses), an excerpt of its text, its author and
62
- * its date. A page with no `h-entry` is described by its `<title>` and its
63
- * description metadata. Everything comes out as plain text; the theme escapes
64
- * it like any other string.
82
+ * its date. A page with no `h-entry` is described by its oEmbed title and
83
+ * author when `oembed` holds them, then its `og:title`, `<title>` and
84
+ * description metadata, where a title that is only a site suffix is none.
85
+ * Everything comes out as plain text; the theme escapes it like any other
86
+ * string.
65
87
  */
66
- export declare function readReplyContext(html: string, target: string, base?: string): ReplyContext | undefined;
88
+ export declare function readReplyContext(html: string, target: string, base?: string, oembed?: Oembed): ReplyContext | undefined;
67
89
  //# sourceMappingURL=reply-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reply-context.d.ts","sourceRoot":"","sources":["../../src/webmention/reply-context.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;;;GAQG;AAEH,2DAA2D;AAC3D,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAQjD,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wCAAwC;AACxC,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,4CAA4C;AAC5C,MAAM,WAAW,wBAAwB;IACvC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CAY5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,MAAe,GACpB,YAAY,GAAG,SAAS,CA6B1B"}
1
+ {"version":3,"file":"reply-context.d.ts","sourceRoot":"","sources":["../../src/webmention/reply-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;;;GAQG;AAEH,2DAA2D;AAC3D,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAUjD,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;CACjC;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAA;CAAE,GACvF;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,4CAA4C;AAC5C,MAAM,WAAW,wBAAwB;IACvC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CAmD5B;AAkFD,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;CAClC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,MAAe,EACrB,MAAM,CAAC,EAAE,MAAM,GACd,YAAY,GAAG,SAAS,CAG1B"}