@aglyn/plugins-ai 1.0.0-beta.288 → 1.0.0-beta.290

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 (92) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.d.ts +3 -2
  3. package/src/lib/activity/ai-activity-actions.js +3 -0
  4. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  5. package/src/lib/components/ai-job-requests.d.ts +2 -0
  6. package/src/lib/components/ai-job-requests.js +2 -0
  7. package/src/lib/components/ai-job-requests.js.map +1 -1
  8. package/src/lib/components/ai-site-build-page.component.js +4 -0
  9. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  10. package/src/lib/components/ai-site-import-job.component.d.ts +6 -1
  11. package/src/lib/components/ai-site-import-job.component.js +124 -17
  12. package/src/lib/components/ai-site-import-job.component.js.map +1 -1
  13. package/src/lib/components/ai-site-import-start.component.d.ts +6 -0
  14. package/src/lib/components/ai-site-import-start.component.js +18 -4
  15. package/src/lib/components/ai-site-import-start.component.js.map +1 -1
  16. package/src/lib/components/ai-site-start-card.component.js +2 -1
  17. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  18. package/src/lib/jobs/ai-image-reads.d.ts +20 -2
  19. package/src/lib/jobs/ai-image-reads.js +47 -0
  20. package/src/lib/jobs/ai-image-reads.js.map +1 -1
  21. package/src/lib/jobs/ai-job-import-step.d.ts +53 -3
  22. package/src/lib/jobs/ai-job-import-step.js +386 -64
  23. package/src/lib/jobs/ai-job-import-step.js.map +1 -1
  24. package/src/lib/jobs/ai-job-layout-language.d.ts +33 -0
  25. package/src/lib/jobs/ai-job-layout-language.js +75 -1
  26. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  27. package/src/lib/jobs/ai-job-layout-step.js +8 -3
  28. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  29. package/src/lib/jobs/ai-job-page-language.d.ts +29 -0
  30. package/src/lib/jobs/ai-job-page-language.js +178 -2
  31. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  32. package/src/lib/jobs/ai-job-page-step.js +3 -0
  33. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  34. package/src/lib/jobs/ai-site-import-document.d.ts +117 -0
  35. package/src/lib/jobs/ai-site-import-document.js +710 -0
  36. package/src/lib/jobs/ai-site-import-document.js.map +1 -0
  37. package/src/lib/jobs/ai-site-import-look.d.ts +112 -0
  38. package/src/lib/jobs/ai-site-import-look.js +402 -0
  39. package/src/lib/jobs/ai-site-import-look.js.map +1 -0
  40. package/src/lib/jobs/ai-site-import-publish.d.ts +41 -0
  41. package/src/lib/jobs/ai-site-import-publish.js +92 -0
  42. package/src/lib/jobs/ai-site-import-publish.js.map +1 -0
  43. package/src/lib/jobs/ai-theme-brand-inputs.d.ts +27 -2
  44. package/src/lib/jobs/ai-theme-brand-inputs.js +37 -8
  45. package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -1
  46. package/src/lib/layout-language/ai-layout-frame.d.ts +17 -0
  47. package/src/lib/layout-language/ai-layout-frame.js +73 -2
  48. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  49. package/src/lib/layout-language/ai-layout-language.d.ts +43 -0
  50. package/src/lib/layout-language/ai-layout-language.js +199 -0
  51. package/src/lib/layout-language/ai-layout-language.js.map +1 -1
  52. package/src/lib/model/ai-credit-estimate.d.ts +15 -0
  53. package/src/lib/model/ai-credit-estimate.js +14 -1
  54. package/src/lib/model/ai-credit-estimate.js.map +1 -1
  55. package/src/lib/model/ai-jobs.types.d.ts +13 -1
  56. package/src/lib/model/ai-jobs.types.js.map +1 -1
  57. package/src/lib/model/ai-site-import-view.d.ts +47 -3
  58. package/src/lib/model/ai-site-import-view.js +122 -20
  59. package/src/lib/model/ai-site-import-view.js.map +1 -1
  60. package/src/lib/model/ai-site-import.d.ts +232 -7
  61. package/src/lib/model/ai-site-import.js +365 -35
  62. package/src/lib/model/ai-site-import.js.map +1 -1
  63. package/src/lib/runtime/ai-doctrine-validators.d.ts +18 -0
  64. package/src/lib/runtime/ai-doctrine-validators.js +16 -5
  65. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  66. package/src/lib/runtime/ai-palette.generated.js +31 -0
  67. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  68. package/src/lib/server/ai-image-reads-route.js +24 -1
  69. package/src/lib/server/ai-image-reads-route.js.map +1 -1
  70. package/src/lib/server/ai-jobs-resume.js +7 -1
  71. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  72. package/src/lib/site-import/fixtures/aglyn-com-recordings.d.ts +57 -0
  73. package/src/lib/site-import/fixtures/aglyn-com-recordings.js +172 -0
  74. package/src/lib/site-import/fixtures/aglyn-com-recordings.js.map +1 -0
  75. package/src/lib/site-import/site-import-crawl.d.ts +32 -7
  76. package/src/lib/site-import/site-import-crawl.js +133 -44
  77. package/src/lib/site-import/site-import-crawl.js.map +1 -1
  78. package/src/lib/site-import/site-import-edge-server.d.ts +31 -0
  79. package/src/lib/site-import/site-import-edge-server.js +31 -0
  80. package/src/lib/site-import/site-import-edge-server.js.map +1 -0
  81. package/src/lib/site-import/site-import-edge.d.ts +44 -0
  82. package/src/lib/site-import/site-import-edge.js +108 -0
  83. package/src/lib/site-import/site-import-edge.js.map +1 -0
  84. package/src/lib/site-import/site-import-html.d.ts +73 -3
  85. package/src/lib/site-import/site-import-html.js +332 -45
  86. package/src/lib/site-import/site-import-html.js.map +1 -1
  87. package/src/lib/site-import/site-import-images.d.ts +22 -0
  88. package/src/lib/site-import/site-import-images.js +78 -2
  89. package/src/lib/site-import/site-import-images.js.map +1 -1
  90. package/src/lib/site-import/site-import-page.d.ts +44 -2
  91. package/src/lib/site-import/site-import-page.js +116 -16
  92. package/src/lib/site-import/site-import-page.js.map +1 -1
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /*==========================================
17
+ * AGLYNBOT THROUGH AGLYN'S OWN EDGE (AGL-4085).
18
+ *
19
+ * The tenant deployment's bot protection answers a client that runs no
20
+ * JavaScript with a 429 challenge page, and AglynBot is such a client. So a
21
+ * site we host, aglyn.com included, could not be brought in: on 2026-10-20 the
22
+ * import read 10 of 121 pages, the ten the store-review bypass happens to
23
+ * admit, and no home page.
24
+ *
25
+ * The edge rule "Site import crawler bypass" (declared in
26
+ * `tools/scripts/lib/firewall-posture.mjs`) lifts that challenge, and nothing
27
+ * else, for a request carrying BOTH this header with the secret AND a
28
+ * user agent starting `AglynBot/`. This module is the only place that holds
29
+ * the secret, and it gives it out for one reason: a request to a hostname this
30
+ * platform serves (`isPlatformServedDomain`: our host records, then the hosting
31
+ * platform's live view). A site anywhere else never sees it.
32
+ *
33
+ * - The secret is `SITE_IMPORT_EDGE_TOKEN`, a server variable on the console,
34
+ * where the crawl runs. Read in the bracket form, so Next never substitutes
35
+ * it into a bundle. Unset, or not shaped like a secret, nothing is sent and
36
+ * nothing is read: the crawler is challenged as it was before.
37
+ * - The decision is per hostname and per request: the fetch asks
38
+ * `headersFor(url)` again on every redirect hop, so a hop to another host
39
+ * carries nothing even where the caller would follow it.
40
+ * - Rotation: a new value in the console's env and the same value in the
41
+ * rule, together. See `apps/docs/docs/operations/firewall-posture.md`.
42
+ *=========================================*/ /** The header the edge rule matches. Lowercase, as the rule declares it. */ export const SITE_IMPORT_EDGE_HEADER = 'x-aglyn-import';
43
+ /** A secret shorter than this is treated as unset: `openssl rand -hex 32` makes 64. */ export const SITE_IMPORT_EDGE_TOKEN_MIN_LENGTH = 32;
44
+ /** Header-safe characters only, so the value can neither break a header nor fail the rule's match. */ const TOKEN_PATTERN = /^[A-Za-z0-9_-]+$/;
45
+ /** Sends nothing anywhere. */ export const NO_SITE_IMPORT_HEADERS = ()=>({});
46
+ /** The edge secret, or null when it is unset or not shaped like one. Never logged. */ export function siteImportEdgeToken(env) {
47
+ var _ref;
48
+ // The direct read is spelled out so the self-host env reference guard sees it.
49
+ const token = String((_ref = env ? env['SITE_IMPORT_EDGE_TOKEN'] : process.env['SITE_IMPORT_EDGE_TOKEN']) != null ? _ref : '').trim();
50
+ if (token.length < SITE_IMPORT_EDGE_TOKEN_MIN_LENGTH || token.length > 256) return null;
51
+ return TOKEN_PATTERN.test(token) ? token : null;
52
+ }
53
+ async function defaultServed(hostname) {
54
+ // Loaded only once a secret is configured, so a crawl that has none (every
55
+ // spec, every self-hosted deployment without the rule) never opens Firestore.
56
+ // By relative path: see `site-import-edge-server.ts`.
57
+ const { isPlatformServedDomain } = await import("./site-import-edge-server.js");
58
+ return isPlatformServedDomain(hostname);
59
+ }
60
+ /**
61
+ * The edge header for requests to one hostname: the secret when this platform
62
+ * serves it, else nothing. Never throws.
63
+ */ export async function siteImportEdgeHeaders(hostname, deps = {}) {
64
+ const token = siteImportEdgeToken(deps.env);
65
+ if (!token) return {};
66
+ const name = String(hostname != null ? hostname : '').trim().toLowerCase();
67
+ if (!name) return {};
68
+ try {
69
+ var _deps_served;
70
+ const served = await ((_deps_served = deps.served) != null ? _deps_served : defaultServed)(name);
71
+ return served ? {
72
+ [SITE_IMPORT_EDGE_HEADER]: token
73
+ } : {};
74
+ } catch (error) {
75
+ console.error('[site-import-edge] could not tell whether the platform serves', name, error);
76
+ return {};
77
+ }
78
+ }
79
+ /**
80
+ * Per-request headers for a crawl of these origins: each origin's hostname is
81
+ * decided once, and a request is given the header only when it is https on
82
+ * the default port to an origin decided "served". Anything else, a hop to
83
+ * another host included, gets nothing.
84
+ */ export async function siteImportEdgeHeadersFor(origins, deps = {}) {
85
+ if (!siteImportEdgeToken(deps.env)) return NO_SITE_IMPORT_HEADERS;
86
+ const decided = new Map();
87
+ for (const raw of origins){
88
+ let origin;
89
+ try {
90
+ origin = new URL(raw);
91
+ } catch (unused) {
92
+ continue;
93
+ }
94
+ if (!isPlainHttpsOrigin(origin) || decided.has(origin.origin)) continue;
95
+ const headers = await siteImportEdgeHeaders(origin.hostname, deps);
96
+ if (Object.keys(headers).length) decided.set(origin.origin, headers);
97
+ }
98
+ if (!decided.size) return NO_SITE_IMPORT_HEADERS;
99
+ return (url)=>{
100
+ var _decided_get;
101
+ return isPlainHttpsOrigin(url) ? (_decided_get = decided.get(url.origin)) != null ? _decided_get : {} : {};
102
+ };
103
+ }
104
+ function isPlainHttpsOrigin(url) {
105
+ return url.protocol === 'https:' && (!url.port || url.port === '443') && !url.username && !url.password;
106
+ }
107
+
108
+ //# sourceMappingURL=site-import-edge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/site-import/site-import-edge.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*==========================================\n * AGLYNBOT THROUGH AGLYN'S OWN EDGE (AGL-4085).\n *\n * The tenant deployment's bot protection answers a client that runs no\n * JavaScript with a 429 challenge page, and AglynBot is such a client. So a\n * site we host, aglyn.com included, could not be brought in: on 2026-10-20 the\n * import read 10 of 121 pages, the ten the store-review bypass happens to\n * admit, and no home page.\n *\n * The edge rule \"Site import crawler bypass\" (declared in\n * `tools/scripts/lib/firewall-posture.mjs`) lifts that challenge, and nothing\n * else, for a request carrying BOTH this header with the secret AND a\n * user agent starting `AglynBot/`. This module is the only place that holds\n * the secret, and it gives it out for one reason: a request to a hostname this\n * platform serves (`isPlatformServedDomain`: our host records, then the hosting\n * platform's live view). A site anywhere else never sees it.\n *\n * - The secret is `SITE_IMPORT_EDGE_TOKEN`, a server variable on the console,\n * where the crawl runs. Read in the bracket form, so Next never substitutes\n * it into a bundle. Unset, or not shaped like a secret, nothing is sent and\n * nothing is read: the crawler is challenged as it was before.\n * - The decision is per hostname and per request: the fetch asks\n * `headersFor(url)` again on every redirect hop, so a hop to another host\n * carries nothing even where the caller would follow it.\n * - Rotation: a new value in the console's env and the same value in the\n * rule, together. See `apps/docs/docs/operations/firewall-posture.md`.\n *=========================================*/\n\n/** The header the edge rule matches. Lowercase, as the rule declares it. */\nexport const SITE_IMPORT_EDGE_HEADER = 'x-aglyn-import'\n\n/** A secret shorter than this is treated as unset: `openssl rand -hex 32` makes 64. */\nexport const SITE_IMPORT_EDGE_TOKEN_MIN_LENGTH = 32\n\n/** Header-safe characters only, so the value can neither break a header nor fail the rule's match. */\nconst TOKEN_PATTERN = /^[A-Za-z0-9_-]+$/\n\n/** Extra headers for one request, asked per address. */\nexport type SiteImportHeadersFor = (url: URL) => Readonly<Record<string, string>>\n\n/** Sends nothing anywhere. */\nexport const NO_SITE_IMPORT_HEADERS: SiteImportHeadersFor = () => ({})\n\nexport interface SiteImportEdgeDeps {\n /** Where the secret is read from; `process.env` by default. */\n env?: Readonly<Record<string, string | undefined>>\n /** Whether this platform serves a hostname; `isPlatformServedDomain` by default. */\n served?: (hostname: string) => Promise<boolean>\n}\n\n/** The edge secret, or null when it is unset or not shaped like one. Never logged. */\nexport function siteImportEdgeToken(env?: SiteImportEdgeDeps['env']): string | null {\n // The direct read is spelled out so the self-host env reference guard sees it.\n const token = String((env ? env['SITE_IMPORT_EDGE_TOKEN'] : process.env['SITE_IMPORT_EDGE_TOKEN']) ?? '').trim()\n if (token.length < SITE_IMPORT_EDGE_TOKEN_MIN_LENGTH || token.length > 256) return null\n return TOKEN_PATTERN.test(token) ? token : null\n}\n\nasync function defaultServed(hostname: string): Promise<boolean> {\n // Loaded only once a secret is configured, so a crawl that has none (every\n // spec, every self-hosted deployment without the rule) never opens Firestore.\n // By relative path: see `site-import-edge-server.ts`.\n const { isPlatformServedDomain } = await import('./site-import-edge-server')\n return isPlatformServedDomain(hostname)\n}\n\n/**\n * The edge header for requests to one hostname: the secret when this platform\n * serves it, else nothing. Never throws.\n */\nexport async function siteImportEdgeHeaders(\n hostname: string,\n deps: SiteImportEdgeDeps = {},\n): Promise<Readonly<Record<string, string>>> {\n const token = siteImportEdgeToken(deps.env)\n if (!token) return {}\n const name = String(hostname ?? '').trim().toLowerCase()\n if (!name) return {}\n try {\n const served = await (deps.served ?? defaultServed)(name)\n return served ? { [SITE_IMPORT_EDGE_HEADER]: token } : {}\n } catch (error) {\n console.error('[site-import-edge] could not tell whether the platform serves', name, error)\n return {}\n }\n}\n\n/**\n * Per-request headers for a crawl of these origins: each origin's hostname is\n * decided once, and a request is given the header only when it is https on\n * the default port to an origin decided \"served\". Anything else, a hop to\n * another host included, gets nothing.\n */\nexport async function siteImportEdgeHeadersFor(\n origins: readonly string[],\n deps: SiteImportEdgeDeps = {},\n): Promise<SiteImportHeadersFor> {\n if (!siteImportEdgeToken(deps.env)) return NO_SITE_IMPORT_HEADERS\n const decided = new Map<string, Readonly<Record<string, string>>>()\n for (const raw of origins) {\n let origin: URL\n try {\n origin = new URL(raw)\n } catch {\n continue\n }\n if (!isPlainHttpsOrigin(origin) || decided.has(origin.origin)) continue\n const headers = await siteImportEdgeHeaders(origin.hostname, deps)\n if (Object.keys(headers).length) decided.set(origin.origin, headers)\n }\n if (!decided.size) return NO_SITE_IMPORT_HEADERS\n return (url: URL) => (isPlainHttpsOrigin(url) ? decided.get(url.origin) ?? {} : {})\n}\n\nfunction isPlainHttpsOrigin(url: URL): boolean {\n return url.protocol === 'https:' && (!url.port || url.port === '443') && !url.username && !url.password\n}\n"],"names":["SITE_IMPORT_EDGE_HEADER","SITE_IMPORT_EDGE_TOKEN_MIN_LENGTH","TOKEN_PATTERN","NO_SITE_IMPORT_HEADERS","siteImportEdgeToken","env","token","String","process","trim","length","test","defaultServed","hostname","isPlatformServedDomain","siteImportEdgeHeaders","deps","name","toLowerCase","served","error","console","siteImportEdgeHeadersFor","origins","decided","Map","raw","origin","URL","isPlainHttpsOrigin","has","headers","Object","keys","set","size","url","get","protocol","port","username","password"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;2CA0B2C,GAE3C,0EAA0E,GAC1E,OAAO,MAAMA,0BAA0B,iBAAgB;AAEvD,qFAAqF,GACrF,OAAO,MAAMC,oCAAoC,GAAE;AAEnD,oGAAoG,GACpG,MAAMC,gBAAgB;AAKtB,4BAA4B,GAC5B,OAAO,MAAMC,yBAA+C,IAAO,CAAA,CAAC,CAAA,EAAE;AAStE,oFAAoF,GACpF,OAAO,SAASC,oBAAoBC,GAA+B;QAE3CA;IADtB,+EAA+E;IAC/E,MAAMC,QAAQC,QAAQF,OAAAA,MAAMA,GAAG,CAAC,yBAAyB,GAAGG,QAAQH,GAAG,CAAC,yBAAyB,YAA3EA,OAAgF,IAAII,IAAI;IAC9G,IAAIH,MAAMI,MAAM,GAAGT,qCAAqCK,MAAMI,MAAM,GAAG,KAAK,OAAO;IACnF,OAAOR,cAAcS,IAAI,CAACL,SAASA,QAAQ;AAC7C;AAEA,eAAeM,cAAcC,QAAgB;IAC3C,2EAA2E;IAC3E,8EAA8E;IAC9E,sDAAsD;IACtD,MAAM,EAAEC,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC;IAChD,OAAOA,uBAAuBD;AAChC;AAEA;;;CAGC,GACD,OAAO,eAAeE,sBACpBF,QAAgB,EAChBG,OAA2B,CAAC,CAAC;IAE7B,MAAMV,QAAQF,oBAAoBY,KAAKX,GAAG;IAC1C,IAAI,CAACC,OAAO,OAAO,CAAC;IACpB,MAAMW,OAAOV,OAAOM,mBAAAA,WAAY,IAAIJ,IAAI,GAAGS,WAAW;IACtD,IAAI,CAACD,MAAM,OAAO,CAAC;IACnB,IAAI;YACoBD;QAAtB,MAAMG,SAAS,MAAM,EAACH,eAAAA,KAAKG,MAAM,YAAXH,eAAeJ,eAAeK;QACpD,OAAOE,SAAS;YAAE,CAACnB,wBAAwB,EAAEM;QAAM,IAAI,CAAC;IAC1D,EAAE,OAAOc,OAAO;QACdC,QAAQD,KAAK,CAAC,iEAAiEH,MAAMG;QACrF,OAAO,CAAC;IACV;AACF;AAEA;;;;;CAKC,GACD,OAAO,eAAeE,yBACpBC,OAA0B,EAC1BP,OAA2B,CAAC,CAAC;IAE7B,IAAI,CAACZ,oBAAoBY,KAAKX,GAAG,GAAG,OAAOF;IAC3C,MAAMqB,UAAU,IAAIC;IACpB,KAAK,MAAMC,OAAOH,QAAS;QACzB,IAAII;QACJ,IAAI;YACFA,SAAS,IAAIC,IAAIF;QACnB,EAAE,eAAM;YACN;QACF;QACA,IAAI,CAACG,mBAAmBF,WAAWH,QAAQM,GAAG,CAACH,OAAOA,MAAM,GAAG;QAC/D,MAAMI,UAAU,MAAMhB,sBAAsBY,OAAOd,QAAQ,EAAEG;QAC7D,IAAIgB,OAAOC,IAAI,CAACF,SAASrB,MAAM,EAAEc,QAAQU,GAAG,CAACP,OAAOA,MAAM,EAAEI;IAC9D;IACA,IAAI,CAACP,QAAQW,IAAI,EAAE,OAAOhC;IAC1B,OAAO,CAACiC;YAAwCZ;eAA1BK,mBAAmBO,QAAOZ,eAAAA,QAAQa,GAAG,CAACD,IAAIT,MAAM,aAAtBH,eAA2B,CAAC,IAAI,CAAC;;AACnF;AAEA,SAASK,mBAAmBO,GAAQ;IAClC,OAAOA,IAAIE,QAAQ,KAAK,YAAa,CAAA,CAACF,IAAIG,IAAI,IAAIH,IAAIG,IAAI,KAAK,KAAI,KAAM,CAACH,IAAII,QAAQ,IAAI,CAACJ,IAAIK,QAAQ;AACzG"}
@@ -29,6 +29,19 @@ export type SiteImportBlock = {
29
29
  url: string;
30
30
  alt: string;
31
31
  region: SiteImportRegion;
32
+ }
33
+ /**
34
+ * A link the page shows outside its menus (AGL-4083): `href` is an absolute
35
+ * http(s) address, a `mailto:` or a `tel:`. `inline` when its words are
36
+ * already in the block before it (a link inside a sentence); a link on its
37
+ * own (a button, an email address in a card) is only this block.
38
+ */
39
+ | {
40
+ kind: 'link';
41
+ text: string;
42
+ href: string;
43
+ region: SiteImportRegion;
44
+ inline?: true;
32
45
  };
33
46
  /** Where on the page a block sat: the header and footer carry business details. */
34
47
  export type SiteImportRegion = 'header' | 'main' | 'footer';
@@ -38,6 +51,46 @@ export interface SiteImportImage {
38
51
  alt: string;
39
52
  /** On the site's own origin; otherwise a CDN or a third party. The importer decides. */
40
53
  sameSite: boolean;
54
+ /** Where on the page it sat, its menus included (AGL-4083): a header's picture is often the logo. */
55
+ region: SiteImportRegion;
56
+ }
57
+ /** A `<link rel="icon">` or `apple-touch-icon` of the page's head (AGL-4083). */
58
+ export interface SiteImportIcon {
59
+ url: string;
60
+ rel: 'icon' | 'apple-touch-icon';
61
+ /** The larger side its `sizes` names, or `null` for none or `any`. */
62
+ size: number | null;
63
+ /** Its declared type, as written. */
64
+ type: string | null;
65
+ }
66
+ /**
67
+ * The link to the home page in a page's header (AGL-4083): what its brand is
68
+ * drawn with. `logo` is the first picture inside it; `text` its words, which
69
+ * are the site's name when the header prints one.
70
+ */
71
+ export interface SiteImportBrandMark {
72
+ logo: {
73
+ url: string;
74
+ alt: string;
75
+ } | null;
76
+ text: string;
77
+ region: SiteImportRegion;
78
+ }
79
+ /**
80
+ * The page's Organization (or LocalBusiness) structured data (AGL-4083), as
81
+ * written: the site's own statement of its name, address, phone, email and
82
+ * profiles. Every field is the empty string, or an empty list, when absent.
83
+ */
84
+ export interface SiteImportOrganization {
85
+ name: string;
86
+ description: string;
87
+ url: string;
88
+ logo: string;
89
+ telephone: string;
90
+ email: string;
91
+ /** One line: street, town, region and postal code, country. */
92
+ address: string;
93
+ sameAs: string[];
41
94
  }
42
95
  export interface SiteImportNavLink {
43
96
  text: string;
@@ -55,6 +108,13 @@ export interface SiteImportExtract {
55
108
  description: string;
56
109
  lang: string | null;
57
110
  canonical: string | null;
111
+ /** The share card, `og:image` (or `twitter:image`), as an absolute address (AGL-4083). */
112
+ ogImage: string | null;
113
+ /** The site's own name, `og:site_name` (or `application-name`); empty when absent. */
114
+ siteName: string;
115
+ icons: SiteImportIcon[];
116
+ brand: SiteImportBrandMark | null;
117
+ organization: SiteImportOrganization | null;
58
118
  blocks: SiteImportBlock[];
59
119
  images: SiteImportImage[];
60
120
  navLinks: SiteImportNavLink[];
@@ -69,13 +129,17 @@ export interface SiteImportExtract {
69
129
  }
70
130
  /** Ceilings that keep one odd page from becoming the whole inventory. */
71
131
  export declare const SITE_IMPORT_PAGE_LIMITS: {
72
- readonly blocks: 400;
73
- readonly blockChars: 2000;
132
+ /** A pricing page's plan table runs past 400 (AGL-4083); a wave's read keeps fewer, under its own budget. */
133
+ readonly blocks: 2000;
134
+ /** A legal page's paragraph runs past 2,000 characters. */
135
+ readonly blockChars: 10000;
74
136
  readonly images: 100;
75
137
  readonly links: 300;
76
- readonly navLinks: 60;
138
+ /** A mega-menu's entries and the footer's columns together. */
139
+ readonly navLinks: 150;
77
140
  readonly forms: 10;
78
141
  readonly fieldsPerForm: 30;
142
+ readonly icons: 12;
79
143
  };
80
144
  /** Character references to characters; an unknown name stays as written. */
81
145
  export declare function decodeHtmlEntities(text: string): string;
@@ -85,6 +149,12 @@ export declare function parseAttributes(source: string): Record<string, string>;
85
149
  export declare function readMetaValues(html: string, name: string): string[];
86
150
  /** `raw` against the page, as an absolute http(s) address without a fragment. */
87
151
  export declare function resolveSiteUrl(raw: string | undefined, base: string): URL | null;
152
+ /**
153
+ * Where a link a page shows goes (AGL-4083): an absolute http(s) address
154
+ * without its fragment, a `mailto:` with an address in it, or a `tel:` with
155
+ * a number in it; `null` for anything else (a script, a jump on the page).
156
+ */
157
+ export declare function resolveSiteLink(raw: string | undefined, base: string): string | null;
88
158
  /**
89
159
  * The words, structure, pictures and links of one page.
90
160
  *