mcp-scraper 0.58.0 → 0.60.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.
- package/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/dist/bin/api-server.cjs +415 -100
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +7 -6
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/{chunk-P32KEY3D.js → chunk-AIA3MFT2.js} +8 -7
- package/dist/chunk-AIA3MFT2.js.map +1 -0
- package/dist/chunk-AQA2ZL4X.js +7 -0
- package/dist/chunk-AQA2ZL4X.js.map +1 -0
- package/dist/editorial-reading-room/assets/app.js +17 -3
- package/dist/{server-J4YGBOTS.js → server-IRKNU6LO.js} +395 -96
- package/dist/server-IRKNU6LO.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-EJ6KU4PC.js +0 -7
- package/dist/chunk-EJ6KU4PC.js.map +0 -1
- package/dist/chunk-P32KEY3D.js.map +0 -1
- package/dist/server-J4YGBOTS.js.map +0 -1
package/dist/bin/api-server.cjs
CHANGED
|
@@ -44650,7 +44650,7 @@ var PACKAGE_VERSION;
|
|
|
44650
44650
|
var init_version = __esm({
|
|
44651
44651
|
"src/version.ts"() {
|
|
44652
44652
|
"use strict";
|
|
44653
|
-
PACKAGE_VERSION = "0.
|
|
44653
|
+
PACKAGE_VERSION = "0.60.0";
|
|
44654
44654
|
}
|
|
44655
44655
|
});
|
|
44656
44656
|
|
|
@@ -46776,6 +46776,7 @@ var init_mcp_tool_schemas = __esm({
|
|
|
46776
46776
|
includeZipGroups: import_zod43.z.boolean().default(true).describe("Include ZIP and county groups from the active hosted ZIP dataset.")
|
|
46777
46777
|
};
|
|
46778
46778
|
CommonsSearchEntitiesInputSchema = {
|
|
46779
|
+
mode: import_zod43.z.enum(["lexical", "semantic", "hybrid"]).optional().describe("Retrieval mode. hybrid (default) fuses meaning-based candidates with exact term matching; lexical matches terms only, which is what you want when the caller quoted an exact name or phrase; semantic ignores term matching entirely."),
|
|
46779
46780
|
query: import_zod43.z.string().trim().max(300).optional().describe("Search text matched against title, description, tags, keywords, JSON-LD, source metadata, citations, media, and article body."),
|
|
46780
46781
|
entityType: import_zod43.z.string().trim().max(120).optional().describe('Optional entity type filter. "Public Article", "PublicArticle", "Article", and "item" normalize to PublicArticle.'),
|
|
46781
46782
|
tag: import_zod43.z.string().trim().max(80).optional().describe("Single canonical tag filter. Use tags for multiple tags."),
|
|
@@ -50422,7 +50423,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50422
50423
|
}, async (input) => formatG2Reviews(await executor.g2Reviews(input), input));
|
|
50423
50424
|
server.registerTool("commons_search_entities", {
|
|
50424
50425
|
title: "Transparent Commons Entity Search",
|
|
50425
|
-
description: "Search the Transparent Commons public wiki graph
|
|
50426
|
+
description: "Search the Transparent Commons public wiki graph. Hybrid by default: meaning-based candidates fused with exact matching over title, description, tags, keywords, JSON-LD, body, citations, media, source metadata, related entities, trails, and saved filters, ranked title-first. Set mode:lexical for a quoted exact name or phrase. Reads published Commons entities only; never a personal Memory vault.",
|
|
50426
50427
|
inputSchema: CommonsSearchEntitiesInputSchema,
|
|
50427
50428
|
outputSchema: recordOutputSchema("commons_search_entities", CommonsGenericOutputSchema),
|
|
50428
50429
|
annotations: {
|
|
@@ -50500,7 +50501,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50500
50501
|
}, async (input) => executor.commonsValidateEntity(input));
|
|
50501
50502
|
server.registerTool("commons_submit_entity", {
|
|
50502
50503
|
title: "Transparent Commons Governed Entity Write",
|
|
50503
|
-
description: "Create or propose an edit to a Transparent Commons public wiki entity through the governed MCP Scraper write plane. A new entity costs 10 Credits; an edit to an existing entity costs 2 Credits. Preparation and validation are free, and idempotent retries are not charged twice. This never edits rendered HTML directly. Normal workflow is commons_prepare_entity, compose, commons_validate_entity, then submit.
|
|
50504
|
+
description: "Create or propose an edit to a Transparent Commons public wiki entity through the governed MCP Scraper write plane. A new entity costs 10 Credits; an edit to an existing entity costs 2 Credits. Preparation and validation are free, and idempotent retries are not charged twice. This never edits rendered HTML directly. Normal workflow is commons_prepare_entity, compose, commons_validate_entity, then submit. commons_prepare_entity returns the entity profile contract and section guidance to compose against. Transparent Commons is an open wiki: any account may edit any entity, and every edit publishes and is recorded on the public contribution ledger. Publishing requires a featured image and body/source evidence. Pass baseRevision when editing so the ledger can show whether the edit was written on top of a newer revision. Requires idempotencyKey.",
|
|
50504
50505
|
inputSchema: CommonsSubmitEntityInputSchema,
|
|
50505
50506
|
outputSchema: recordOutputSchema("commons_submit_entity", CommonsGenericOutputSchema),
|
|
50506
50507
|
annotations: {
|
|
@@ -50526,7 +50527,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50526
50527
|
}, async (input) => executor.commonsGetEntityLedger(input));
|
|
50527
50528
|
server.registerTool("commons_host_image", {
|
|
50528
50529
|
title: "Host a Transparent Commons Image",
|
|
50529
|
-
description: "
|
|
50530
|
+
description: "Host an image from a public https URL or base64 bytes, returning a permanent Commons URL. Commons never serves a third-party image URL \u2014 commons_submit_entity hosts external images automatically, so use this only to host one before or independently of a write. JPEG, PNG, GIF, WebP up to 10 MB; SVG rejected. Identical bytes are stored once.",
|
|
50530
50531
|
inputSchema: CommonsHostImageInputSchema,
|
|
50531
50532
|
outputSchema: recordOutputSchema("commons_host_image", CommonsGenericOutputSchema),
|
|
50532
50533
|
annotations: {
|
|
@@ -50606,7 +50607,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50606
50607
|
}, async (input) => executor.commonsPublishEditorial(input));
|
|
50607
50608
|
server.registerTool("commons_update_editorial_article", {
|
|
50608
50609
|
title: "Edit One Transparent Commons Article",
|
|
50609
|
-
description: "Replace the Markdown of
|
|
50610
|
+
description: "Replace the Markdown of one article in a published edition without resupplying the others: it reads the stored sources, swaps the article you name, and publishes the next revision with the rest byte-identical. Read commons_get_publication with includeArticles first for the current source and revision. commons_publish_editorial is the full-replace path. Requires baseRevision and idempotencyKey.",
|
|
50610
50611
|
inputSchema: CommonsUpdateEditorialArticleInputSchema,
|
|
50611
50612
|
outputSchema: recordOutputSchema("commons_update_editorial_article", CommonsGenericOutputSchema),
|
|
50612
50613
|
annotations: { title: "Edit One Transparent Commons Article", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
@@ -50680,7 +50681,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50680
50681
|
}, async (input) => executor.localSourcebookCapture(input));
|
|
50681
50682
|
server.registerTool("local_sourcebook_submission_status", {
|
|
50682
50683
|
title: "Local Sourcebook Submission Status",
|
|
50683
|
-
description: "Read the
|
|
50684
|
+
description: "Read the caller\u2019s listing draft, enrichment coverage, revision number, publication state, and live LocalSourcebook.com profile and reviews URLs. When status is failed, acquisitionError says why \u2014 read it before retrying, since a refresh repeats the same acquisition. Coverage counters are written only on success, so zeroed counters on a failed listing do not mean the crawl never ran.",
|
|
50684
50685
|
inputSchema: LocalSourcebookSubmissionStatusInputSchema,
|
|
50685
50686
|
outputSchema: recordOutputSchema("local_sourcebook_submission_status", LocalSourcebookOutputSchema),
|
|
50686
50687
|
annotations: localPlanningToolAnnotations("Local Sourcebook Submission Status")
|
|
@@ -64079,9 +64080,7 @@ function socialMeta(input) {
|
|
|
64079
64080
|
];
|
|
64080
64081
|
return tags.join("\n ");
|
|
64081
64082
|
}
|
|
64082
|
-
function
|
|
64083
|
-
const sourceBytes = input.articles.reduce((total, article) => total + Buffer.byteLength(article.markdown), 0);
|
|
64084
|
-
if (sourceBytes > 2e6) throw new Error("Editorial reading-room Markdown must be 2,000,000 bytes or fewer in total.");
|
|
64083
|
+
function buildEditorialArticles(input) {
|
|
64085
64084
|
const seenSlugs = /* @__PURE__ */ new Set();
|
|
64086
64085
|
const seenOrders = /* @__PURE__ */ new Set();
|
|
64087
64086
|
const parser = markdownRenderer();
|
|
@@ -64108,7 +64107,19 @@ function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
|
|
|
64108
64107
|
html: rendered
|
|
64109
64108
|
};
|
|
64110
64109
|
});
|
|
64110
|
+
return { articles, warnings, totalWordCount };
|
|
64111
|
+
}
|
|
64112
|
+
function renderEditorialArticleModels(input) {
|
|
64113
|
+
return buildEditorialArticles(input).articles;
|
|
64114
|
+
}
|
|
64115
|
+
function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
|
|
64116
|
+
const sourceBytes = input.articles.reduce((total, article) => total + Buffer.byteLength(article.markdown), 0);
|
|
64117
|
+
if (sourceBytes > 2e6) throw new Error("Editorial reading-room Markdown must be 2,000,000 bytes or fewer in total.");
|
|
64111
64118
|
const generatedAt = now.toISOString();
|
|
64119
|
+
const built = buildEditorialArticles(input);
|
|
64120
|
+
const articles = built.articles;
|
|
64121
|
+
const warnings = built.warnings;
|
|
64122
|
+
const totalWordCount = built.totalWordCount;
|
|
64112
64123
|
const data = { ...input, generatedAt, articles };
|
|
64113
64124
|
const template = readAsset("index.html");
|
|
64114
64125
|
const html = template.replace("<title>Editorial Reading Room</title>", `<title>${escapeHtml6(input.site.title)}</title>`).replace('content="A mobile-first editorial reading room."', `content="${escapeHtml6(input.deck || input.site.heroTitle)}"`).replace("<!--__READING_ROOM_SOCIAL_META__-->", socialMeta(input)).replace("/*__READING_ROOM_STYLES__*/", readAsset("styles.css")).replace("/*__READING_ROOM_DATA__*/", escapedJsonForHtml(data)).replace("/*__READING_ROOM_SCRIPT__*/", readAsset("app.js"));
|
|
@@ -64589,6 +64600,141 @@ var init_commons_image_store = __esm({
|
|
|
64589
64600
|
}
|
|
64590
64601
|
});
|
|
64591
64602
|
|
|
64603
|
+
// src/api/commons-embeddings.ts
|
|
64604
|
+
function commonsEmbedModel() {
|
|
64605
|
+
return (process.env.JINA_EMBED_MODEL ?? "jina-embeddings-v5-omni-small").trim();
|
|
64606
|
+
}
|
|
64607
|
+
function commonsEmbedDim() {
|
|
64608
|
+
return Number((process.env.JINA_EMBED_DIM ?? "1024").trim());
|
|
64609
|
+
}
|
|
64610
|
+
function commonsSemanticSearchConfigured() {
|
|
64611
|
+
return Boolean(process.env.JINA_API_KEY?.trim() && process.env.MEMORY_DATABASE_URL?.trim());
|
|
64612
|
+
}
|
|
64613
|
+
function vectorSql() {
|
|
64614
|
+
if (_vectorSql) return _vectorSql;
|
|
64615
|
+
const url = process.env.MEMORY_DATABASE_URL?.trim();
|
|
64616
|
+
if (!url) throw new Error("MEMORY_DATABASE_URL is not set; Commons semantic search needs the shared Postgres.");
|
|
64617
|
+
_vectorSql = (0, import_serverless.neon)(url);
|
|
64618
|
+
return _vectorSql;
|
|
64619
|
+
}
|
|
64620
|
+
async function ensureCommonsVectorSchema() {
|
|
64621
|
+
if (vectorSchemaReady) return;
|
|
64622
|
+
const dimension = commonsEmbedDim();
|
|
64623
|
+
await vectorSql().query("CREATE EXTENSION IF NOT EXISTS vector");
|
|
64624
|
+
await vectorSql().query(`
|
|
64625
|
+
CREATE TABLE IF NOT EXISTS commons_index_vectors (
|
|
64626
|
+
document_id TEXT PRIMARY KEY,
|
|
64627
|
+
entity_id TEXT NOT NULL,
|
|
64628
|
+
document_type TEXT NOT NULL,
|
|
64629
|
+
title TEXT NOT NULL,
|
|
64630
|
+
embedding vector(${dimension}) NOT NULL,
|
|
64631
|
+
model TEXT NOT NULL,
|
|
64632
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
64633
|
+
)
|
|
64634
|
+
`);
|
|
64635
|
+
await vectorSql().query("CREATE INDEX IF NOT EXISTS commons_index_vectors_entity ON commons_index_vectors(entity_id)");
|
|
64636
|
+
vectorSchemaReady = true;
|
|
64637
|
+
}
|
|
64638
|
+
async function embedCommonsTexts(texts) {
|
|
64639
|
+
const apiKey = process.env.JINA_API_KEY?.trim();
|
|
64640
|
+
if (!apiKey) throw new Error("JINA_API_KEY is not set; Commons semantic search cannot embed.");
|
|
64641
|
+
if (!texts.length) return [];
|
|
64642
|
+
const response = await fetch("https://api.jina.ai/v1/embeddings", {
|
|
64643
|
+
method: "POST",
|
|
64644
|
+
headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json" },
|
|
64645
|
+
body: JSON.stringify({
|
|
64646
|
+
model: commonsEmbedModel(),
|
|
64647
|
+
dimensions: commonsEmbedDim(),
|
|
64648
|
+
input: texts.map((text2) => ({ text: text2.slice(0, 8e3) }))
|
|
64649
|
+
}),
|
|
64650
|
+
signal: AbortSignal.timeout(6e4)
|
|
64651
|
+
});
|
|
64652
|
+
if (!response.ok) {
|
|
64653
|
+
throw new Error(`Jina embedding request failed with HTTP ${response.status}: ${(await response.text()).slice(0, 200)}`);
|
|
64654
|
+
}
|
|
64655
|
+
const payload = await response.json();
|
|
64656
|
+
const vectors = (payload.data ?? []).map((item) => item.embedding);
|
|
64657
|
+
if (vectors.length !== texts.length) {
|
|
64658
|
+
throw new Error(`Jina returned ${vectors.length} embeddings for ${texts.length} inputs.`);
|
|
64659
|
+
}
|
|
64660
|
+
return vectors;
|
|
64661
|
+
}
|
|
64662
|
+
async function embedQueuedCommonsDocuments(limit = 50) {
|
|
64663
|
+
if (!commonsSemanticSearchConfigured()) return { claimed: 0, embedded: 0, failed: 0, remaining: 0 };
|
|
64664
|
+
await ensureCommonsVectorSchema();
|
|
64665
|
+
const bounded = Math.max(1, Math.min(200, Math.floor(limit)));
|
|
64666
|
+
const queued = await getDb().execute({
|
|
64667
|
+
sql: `SELECT id, entity_id, document_type, title, text FROM commons_index_documents
|
|
64668
|
+
WHERE embedding_status IN ('queued', 'failed') ORDER BY updated_at ASC LIMIT ?`,
|
|
64669
|
+
args: [bounded]
|
|
64670
|
+
});
|
|
64671
|
+
const rows = queued.rows;
|
|
64672
|
+
if (!rows.length) return { claimed: 0, embedded: 0, failed: 0, remaining: await queuedCommonsDocumentCount() };
|
|
64673
|
+
let embedded = 0;
|
|
64674
|
+
let failed = 0;
|
|
64675
|
+
const model = commonsEmbedModel();
|
|
64676
|
+
try {
|
|
64677
|
+
const vectors = await embedCommonsTexts(rows.map((row) => `${row.title}
|
|
64678
|
+
|
|
64679
|
+
${row.text}`));
|
|
64680
|
+
for (const [index, row] of rows.entries()) {
|
|
64681
|
+
const literal = `[${vectors[index].join(",")}]`;
|
|
64682
|
+
await vectorSql().query(
|
|
64683
|
+
`INSERT INTO commons_index_vectors (document_id, entity_id, document_type, title, embedding, model, updated_at)
|
|
64684
|
+
VALUES ($1, $2, $3, $4, $5::vector, $6, now())
|
|
64685
|
+
ON CONFLICT (document_id) DO UPDATE SET entity_id = EXCLUDED.entity_id, document_type = EXCLUDED.document_type,
|
|
64686
|
+
title = EXCLUDED.title, embedding = EXCLUDED.embedding, model = EXCLUDED.model, updated_at = now()`,
|
|
64687
|
+
[row.id, row.entity_id, row.document_type, row.title, literal, model]
|
|
64688
|
+
);
|
|
64689
|
+
await getDb().execute({
|
|
64690
|
+
sql: `UPDATE commons_index_documents SET embedding_status = 'indexed', embedding_provider = ?, embedding_model = ?,
|
|
64691
|
+
vector_ref = ?, indexed_at = ?, error = NULL WHERE id = ?`,
|
|
64692
|
+
args: [COMMONS_EMBED_PROVIDER, model, row.id, (/* @__PURE__ */ new Date()).toISOString(), row.id]
|
|
64693
|
+
});
|
|
64694
|
+
embedded += 1;
|
|
64695
|
+
}
|
|
64696
|
+
} catch (error) {
|
|
64697
|
+
failed = rows.length - embedded;
|
|
64698
|
+
const message = (error instanceof Error ? error.message : String(error)).slice(0, 500);
|
|
64699
|
+
for (const row of rows.slice(embedded)) {
|
|
64700
|
+
await getDb().execute({
|
|
64701
|
+
sql: `UPDATE commons_index_documents SET embedding_status = 'failed', error = ? WHERE id = ?`,
|
|
64702
|
+
args: [message, row.id]
|
|
64703
|
+
}).catch(() => void 0);
|
|
64704
|
+
}
|
|
64705
|
+
}
|
|
64706
|
+
return { claimed: rows.length, embedded, failed, remaining: await queuedCommonsDocumentCount() };
|
|
64707
|
+
}
|
|
64708
|
+
async function queuedCommonsDocumentCount() {
|
|
64709
|
+
const result = await getDb().execute(`SELECT COUNT(*) AS n FROM commons_index_documents WHERE embedding_status IN ('queued', 'failed')`);
|
|
64710
|
+
return Number(result.rows[0]?.n ?? 0);
|
|
64711
|
+
}
|
|
64712
|
+
async function semanticCommonsEntityScores(query, limit = 40) {
|
|
64713
|
+
const scores = /* @__PURE__ */ new Map();
|
|
64714
|
+
if (!commonsSemanticSearchConfigured() || !query.trim()) return scores;
|
|
64715
|
+
await ensureCommonsVectorSchema();
|
|
64716
|
+
const [vector] = await embedCommonsTexts([query]);
|
|
64717
|
+
if (!vector) return scores;
|
|
64718
|
+
const rows = await vectorSql().query(
|
|
64719
|
+
`SELECT entity_id, MAX(1 - (embedding <=> $1::vector)) AS score
|
|
64720
|
+
FROM commons_index_vectors GROUP BY entity_id ORDER BY score DESC LIMIT $2`,
|
|
64721
|
+
[`[${vector.join(",")}]`, Math.max(1, Math.min(100, limit))]
|
|
64722
|
+
);
|
|
64723
|
+
for (const row of rows) scores.set(String(row.entity_id), Number(row.score));
|
|
64724
|
+
return scores;
|
|
64725
|
+
}
|
|
64726
|
+
var import_serverless, COMMONS_EMBED_PROVIDER, _vectorSql, vectorSchemaReady;
|
|
64727
|
+
var init_commons_embeddings = __esm({
|
|
64728
|
+
"src/api/commons-embeddings.ts"() {
|
|
64729
|
+
"use strict";
|
|
64730
|
+
import_serverless = require("@neondatabase/serverless");
|
|
64731
|
+
init_db();
|
|
64732
|
+
COMMONS_EMBED_PROVIDER = "jina";
|
|
64733
|
+
_vectorSql = null;
|
|
64734
|
+
vectorSchemaReady = false;
|
|
64735
|
+
}
|
|
64736
|
+
});
|
|
64737
|
+
|
|
64592
64738
|
// src/api/schema-presence.ts
|
|
64593
64739
|
async function loadSchemaObjects() {
|
|
64594
64740
|
const res = await getDb().execute(
|
|
@@ -65082,17 +65228,35 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
65082
65228
|
args.push(mergedFilters.updatedAfter);
|
|
65083
65229
|
}
|
|
65084
65230
|
const terms = tokenize(mergedFilters.query);
|
|
65085
|
-
|
|
65086
|
-
|
|
65087
|
-
|
|
65088
|
-
|
|
65089
|
-
|
|
65090
|
-
|
|
65091
|
-
|
|
65092
|
-
|
|
65093
|
-
|
|
65094
|
-
|
|
65095
|
-
|
|
65231
|
+
const searchMode = mergedFilters.mode === "lexical" || mergedFilters.mode === "semantic" ? mergedFilters.mode : "hybrid";
|
|
65232
|
+
const semanticScores = !terms.length || searchMode === "lexical" || !commonsSemanticSearchConfigured() ? /* @__PURE__ */ new Map() : await semanticCommonsEntityScores(String(mergedFilters.query ?? ""), SEARCH_CANDIDATE_LIMIT).catch(() => /* @__PURE__ */ new Map());
|
|
65233
|
+
const semanticIds = [...semanticScores.entries()].filter(([, score]) => score >= 0.6).sort((left, right) => right[1] - left[1]).slice(0, 60).map(([id]) => id);
|
|
65234
|
+
if (terms.length) {
|
|
65235
|
+
const termClauses = [];
|
|
65236
|
+
for (const term of terms) {
|
|
65237
|
+
termClauses.push(`(
|
|
65238
|
+
search_text LIKE ?
|
|
65239
|
+
OR EXISTS (
|
|
65240
|
+
SELECT 1 FROM commons_claims
|
|
65241
|
+
WHERE commons_claims.subject_entity_id = commons_entities.id
|
|
65242
|
+
AND (commons_claims.predicate LIKE ? OR commons_claims.predicate_label LIKE ? OR commons_claims.title LIKE ? OR commons_claims.object_url LIKE ?)
|
|
65243
|
+
)
|
|
65244
|
+
)`);
|
|
65245
|
+
const pattern = `%${escapeLike(term)}%`;
|
|
65246
|
+
args.push(pattern, pattern, pattern, pattern, pattern);
|
|
65247
|
+
}
|
|
65248
|
+
const lexicalClause = `(${termClauses.join(" AND ")})`;
|
|
65249
|
+
if (searchMode === "semantic") {
|
|
65250
|
+
if (!semanticIds.length) return { results: [], filters: mergedFilters, limit, offset };
|
|
65251
|
+
args.length -= terms.length * 5;
|
|
65252
|
+
clauses.push(`id IN (${semanticIds.map(() => "?").join(", ")})`);
|
|
65253
|
+
args.push(...semanticIds);
|
|
65254
|
+
} else if (semanticIds.length) {
|
|
65255
|
+
clauses.push(`(${lexicalClause} OR id IN (${semanticIds.map(() => "?").join(", ")}))`);
|
|
65256
|
+
args.push(...semanticIds);
|
|
65257
|
+
} else {
|
|
65258
|
+
clauses.push(lexicalClause);
|
|
65259
|
+
}
|
|
65096
65260
|
}
|
|
65097
65261
|
if (!terms.length) {
|
|
65098
65262
|
args.push(limit, offset);
|
|
@@ -65129,6 +65293,7 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
65129
65293
|
`,
|
|
65130
65294
|
args
|
|
65131
65295
|
});
|
|
65296
|
+
const mode = searchMode;
|
|
65132
65297
|
const ranked = candidates.rows.map((row) => {
|
|
65133
65298
|
const record = row;
|
|
65134
65299
|
const score = relevanceScore(terms, {
|
|
@@ -65139,8 +65304,10 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
65139
65304
|
searchText: String(record.search_text ?? ""),
|
|
65140
65305
|
claimText: String(record.claim_text ?? "")
|
|
65141
65306
|
});
|
|
65142
|
-
|
|
65143
|
-
|
|
65307
|
+
const semantic = semanticScores.get(String(record.id)) ?? 0;
|
|
65308
|
+
const fused = mode === "semantic" ? semantic * 100 : score + semantic * 60;
|
|
65309
|
+
return { id: String(record.id), updatedAt: String(record.updated_at ?? ""), title: String(record.title ?? ""), score: fused, lexical: score, semantic };
|
|
65310
|
+
}).filter((candidate) => mode === "semantic" ? candidate.semantic > 0 : candidate.lexical > 0 || candidate.semantic >= 0.62).sort((left, right) => right.score - left.score || right.updatedAt.localeCompare(left.updatedAt) || left.title.localeCompare(right.title));
|
|
65144
65311
|
const pageIds = ranked.slice(offset, offset + limit).map((candidate) => candidate.id);
|
|
65145
65312
|
if (!pageIds.length) return { results: [], filters: mergedFilters, limit, offset };
|
|
65146
65313
|
const page = await getDb().execute({
|
|
@@ -66626,6 +66793,7 @@ function normalizeRelatedEntities(related) {
|
|
|
66626
66793
|
}
|
|
66627
66794
|
function sanitizeSearchFilters(filters) {
|
|
66628
66795
|
return {
|
|
66796
|
+
mode: filters.mode === "lexical" || filters.mode === "semantic" ? filters.mode : "hybrid",
|
|
66629
66797
|
query: optionalText2(filters.query, 300) ?? void 0,
|
|
66630
66798
|
entityType: filters.entityType ? normalizeEntityType(filters.entityType) : void 0,
|
|
66631
66799
|
tag: optionalText2(filters.tag, 80) ?? void 0,
|
|
@@ -66893,6 +67061,7 @@ var init_commons_repository = __esm({
|
|
|
66893
67061
|
import_node_crypto39 = require("crypto");
|
|
66894
67062
|
init_db();
|
|
66895
67063
|
init_commons_image_store();
|
|
67064
|
+
init_commons_embeddings();
|
|
66896
67065
|
init_schema_presence();
|
|
66897
67066
|
init_rates();
|
|
66898
67067
|
init_commons_linksets();
|
|
@@ -67084,6 +67253,101 @@ var init_commons_repository = __esm({
|
|
|
67084
67253
|
}
|
|
67085
67254
|
});
|
|
67086
67255
|
|
|
67256
|
+
// src/editorial-reading-room/article-page.ts
|
|
67257
|
+
function escapeHtml7(value) {
|
|
67258
|
+
return String(value ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
67259
|
+
}
|
|
67260
|
+
function articlePath(origin, slug4) {
|
|
67261
|
+
return `${origin.replace(/\/+$/, "")}/${encodeURIComponent(slug4)}`;
|
|
67262
|
+
}
|
|
67263
|
+
function renderEditorialArticlePage(input) {
|
|
67264
|
+
const articles = renderEditorialArticleModels(input.edition);
|
|
67265
|
+
const index = articles.findIndex((article2) => article2.slug === input.articleSlug);
|
|
67266
|
+
if (index === -1) return null;
|
|
67267
|
+
const article = articles[index];
|
|
67268
|
+
const previous = index > 0 ? articles[index - 1] : null;
|
|
67269
|
+
const next = index < articles.length - 1 ? articles[index + 1] : null;
|
|
67270
|
+
const canonicalUrl = articlePath(input.origin, article.slug);
|
|
67271
|
+
const site = input.edition.site;
|
|
67272
|
+
const description = article.summary || input.edition.deck || site.title;
|
|
67273
|
+
const jsonLd = JSON.stringify({
|
|
67274
|
+
"@context": "https://schema.org",
|
|
67275
|
+
"@type": "Article",
|
|
67276
|
+
"@id": `${canonicalUrl}#article`,
|
|
67277
|
+
headline: article.title,
|
|
67278
|
+
description,
|
|
67279
|
+
articleSection: article.category,
|
|
67280
|
+
wordCount: article.wordCount,
|
|
67281
|
+
url: canonicalUrl,
|
|
67282
|
+
isPartOf: { "@type": "CollectionPage", "@id": `${input.editionUrl}#collection`, name: site.title, url: input.editionUrl },
|
|
67283
|
+
publisher: { "@type": "Organization", name: input.publicationTitle, url: input.origin }
|
|
67284
|
+
}).replace(/</g, "\\u003c");
|
|
67285
|
+
const jumps = article.toc.length ? `<nav class="article-jumps" aria-label="On this page">${article.toc.map((item) => `<a href="#${escapeHtml7(item.id)}">${escapeHtml7(item.title)}</a>`).join("")}</nav>` : "";
|
|
67286
|
+
const neighbour = (item, label) => item ? `<a class="neighbour" href="${escapeHtml7(articlePath(input.origin, item.slug))}"><span>${label}</span><strong>${escapeHtml7(item.title)}</strong></a>` : "";
|
|
67287
|
+
const html = `<!doctype html>
|
|
67288
|
+
<html lang="en">
|
|
67289
|
+
<head>
|
|
67290
|
+
<meta charset="utf-8">
|
|
67291
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
67292
|
+
<title>${escapeHtml7(article.title)} \u2014 ${escapeHtml7(input.publicationTitle)}</title>
|
|
67293
|
+
<meta name="description" content="${escapeHtml7(description)}">
|
|
67294
|
+
<link rel="canonical" href="${escapeHtml7(canonicalUrl)}">
|
|
67295
|
+
<meta property="og:type" content="article">
|
|
67296
|
+
<meta property="og:title" content="${escapeHtml7(article.title)}">
|
|
67297
|
+
<meta property="og:description" content="${escapeHtml7(description)}">
|
|
67298
|
+
<meta property="og:url" content="${escapeHtml7(canonicalUrl)}">
|
|
67299
|
+
<meta property="og:site_name" content="${escapeHtml7(input.publicationTitle)}">
|
|
67300
|
+
<meta name="twitter:card" content="summary_large_image">
|
|
67301
|
+
<meta name="twitter:title" content="${escapeHtml7(article.title)}">
|
|
67302
|
+
<meta name="twitter:description" content="${escapeHtml7(description)}">
|
|
67303
|
+
<script type="application/ld+json">${jsonLd}</script>
|
|
67304
|
+
<style>
|
|
67305
|
+
:root{color-scheme:light dark;--ink:#12171f;--muted:#5b6672;--rule:#dfe4ea;--bg:#fbfbfa;--accent:#8a6a2f}
|
|
67306
|
+
*{box-sizing:border-box}
|
|
67307
|
+
body{margin:0;background:var(--bg);color:var(--ink);font:17px/1.65 Georgia,"Times New Roman",serif}
|
|
67308
|
+
a{color:inherit}
|
|
67309
|
+
header.masthead{border-bottom:1px solid var(--rule);padding:18px 20px}
|
|
67310
|
+
header.masthead a{font:600 13px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;text-decoration:none;color:var(--muted)}
|
|
67311
|
+
main{max-width:44rem;margin:0 auto;padding:34px 20px 64px}
|
|
67312
|
+
.kicker{font:600 12px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.1em;text-transform:uppercase;color:var(--accent)}
|
|
67313
|
+
h1{font-size:2.1rem;line-height:1.18;margin:12px 0 10px}
|
|
67314
|
+
.summary{color:var(--muted);font-size:1.06rem;margin:0 0 18px}
|
|
67315
|
+
.meta{font:12px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:11px 0;margin-bottom:26px}
|
|
67316
|
+
.article-jumps{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 26px}
|
|
67317
|
+
.article-jumps a{font:13px/1 ui-sans-serif,system-ui,sans-serif;color:var(--muted);text-decoration:none;border:1px solid var(--rule);border-radius:999px;padding:6px 11px}
|
|
67318
|
+
article h2{font-size:1.4rem;margin:32px 0 10px}
|
|
67319
|
+
article h3{font-size:1.15rem;margin:24px 0 8px}
|
|
67320
|
+
article p{margin:0 0 17px}
|
|
67321
|
+
.neighbours{display:grid;gap:12px;margin-top:44px;padding-top:22px;border-top:1px solid var(--rule)}
|
|
67322
|
+
.neighbour{display:block;text-decoration:none;border:1px solid var(--rule);border-radius:10px;padding:13px 15px;background:#fff}
|
|
67323
|
+
.neighbour span{display:block;font:11px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);margin-bottom:5px}
|
|
67324
|
+
footer{border-top:1px solid var(--rule);padding:20px;text-align:center;color:var(--muted);font:13px/1.5 ui-sans-serif,system-ui,sans-serif}
|
|
67325
|
+
@media (prefers-color-scheme:dark){:root{--ink:#eef1f5;--muted:#9aa4b1;--rule:#2b323b;--bg:#12151a}.neighbour{background:#171b21}}
|
|
67326
|
+
</style>
|
|
67327
|
+
</head>
|
|
67328
|
+
<body>
|
|
67329
|
+
<header class="masthead"><a href="${escapeHtml7(input.origin)}">${escapeHtml7(input.publicationTitle)}</a></header>
|
|
67330
|
+
<main>
|
|
67331
|
+
<p class="kicker">${escapeHtml7(article.kicker || article.category)}</p>
|
|
67332
|
+
<h1>${escapeHtml7(article.title)}</h1>
|
|
67333
|
+
<p class="summary">${escapeHtml7(article.summary)}</p>
|
|
67334
|
+
<p class="meta">${escapeHtml7(article.category)} \xB7 ${article.wordCount} words \xB7 ${article.readingMinutes} min \xB7 <a href="${escapeHtml7(input.editionUrl)}">${escapeHtml7(site.title)}</a></p>
|
|
67335
|
+
${jumps}
|
|
67336
|
+
<article>${article.html}</article>
|
|
67337
|
+
<div class="neighbours">${neighbour(previous, "Previous")}${neighbour(next, "Next")}</div>
|
|
67338
|
+
</main>
|
|
67339
|
+
<footer>${escapeHtml7(input.publicationTitle)} \xB7 <a href="${escapeHtml7(input.editionUrl)}">All articles in ${escapeHtml7(site.title)}</a></footer>
|
|
67340
|
+
</body>
|
|
67341
|
+
</html>`;
|
|
67342
|
+
return { html, article, canonicalUrl };
|
|
67343
|
+
}
|
|
67344
|
+
var init_article_page = __esm({
|
|
67345
|
+
"src/editorial-reading-room/article-page.ts"() {
|
|
67346
|
+
"use strict";
|
|
67347
|
+
init_render();
|
|
67348
|
+
}
|
|
67349
|
+
});
|
|
67350
|
+
|
|
67087
67351
|
// src/api/commons-publication-repository.ts
|
|
67088
67352
|
async function prepareCommonsPublication(input, user) {
|
|
67089
67353
|
await ensureCommonsSchema();
|
|
@@ -67382,6 +67646,20 @@ async function listCommonsPublicationEditions(publicationId) {
|
|
|
67382
67646
|
if (!publication) return [];
|
|
67383
67647
|
return result.rows.map((row) => rowToEdition(row, publication.subdomain));
|
|
67384
67648
|
}
|
|
67649
|
+
async function getCommonsPublicationArticleHtml(subdomainInput, articleSlug, editionSlugInput) {
|
|
67650
|
+
const found = await getCommonsPublicationEditionHtml(subdomainInput, editionSlugInput);
|
|
67651
|
+
if (!found) return null;
|
|
67652
|
+
const { publication, edition } = found;
|
|
67653
|
+
const page = renderEditorialArticlePage({
|
|
67654
|
+
edition: { site: edition.site, deck: edition.deck, articles: edition.articles },
|
|
67655
|
+
articleSlug,
|
|
67656
|
+
origin: publicationPublicUrl(publication.subdomain),
|
|
67657
|
+
editionUrl: editionPublicUrl(publication.subdomain, edition.editionSlug),
|
|
67658
|
+
publicationTitle: publication.title
|
|
67659
|
+
});
|
|
67660
|
+
if (!page) return null;
|
|
67661
|
+
return { publication, edition, html: page.html, canonicalUrl: page.canonicalUrl };
|
|
67662
|
+
}
|
|
67385
67663
|
async function getCommonsPublicationEditionHtml(subdomainInput, editionSlugInput) {
|
|
67386
67664
|
const publication = await getCommonsPublicationBySubdomain(subdomainInput);
|
|
67387
67665
|
if (!publication) return null;
|
|
@@ -67530,6 +67808,7 @@ var init_commons_publication_repository = __esm({
|
|
|
67530
67808
|
init_db();
|
|
67531
67809
|
init_commons_repository();
|
|
67532
67810
|
init_render();
|
|
67811
|
+
init_article_page();
|
|
67533
67812
|
PUBLICATION_ROOT_DOMAIN = process.env.COMMONS_PUBLICATION_ROOT_DOMAIN || "transparent-commons.cc";
|
|
67534
67813
|
RESERVED_SUBDOMAINS = /* @__PURE__ */ new Set([
|
|
67535
67814
|
"admin",
|
|
@@ -67569,6 +67848,7 @@ var init_commons_publication_repository = __esm({
|
|
|
67569
67848
|
// src/api/commons-routes.ts
|
|
67570
67849
|
function filtersFromQuery(query) {
|
|
67571
67850
|
return {
|
|
67851
|
+
mode: query.mode === "lexical" || query.mode === "semantic" ? query.mode : void 0,
|
|
67572
67852
|
query: query.query || query.q,
|
|
67573
67853
|
entityType: query.entityType,
|
|
67574
67854
|
tag: query.tag,
|
|
@@ -67643,6 +67923,7 @@ var init_commons_routes = __esm({
|
|
|
67643
67923
|
init_api_auth();
|
|
67644
67924
|
init_commons_repository();
|
|
67645
67925
|
init_commons_image_store();
|
|
67926
|
+
init_commons_embeddings();
|
|
67646
67927
|
init_commons_linksets();
|
|
67647
67928
|
init_listing_write_billing();
|
|
67648
67929
|
init_commons_publication_repository();
|
|
@@ -67650,6 +67931,7 @@ var init_commons_routes = __esm({
|
|
|
67650
67931
|
commonsApp = new import_hono31.Hono();
|
|
67651
67932
|
auth2 = createApiKeyAuth();
|
|
67652
67933
|
SearchBodySchema = import_zod52.z.object({
|
|
67934
|
+
mode: import_zod52.z.enum(["lexical", "semantic", "hybrid"]).optional(),
|
|
67653
67935
|
query: import_zod52.z.string().max(300).optional(),
|
|
67654
67936
|
entityType: import_zod52.z.string().max(120).optional(),
|
|
67655
67937
|
tag: import_zod52.z.string().max(80).optional(),
|
|
@@ -67813,6 +68095,14 @@ var init_commons_routes = __esm({
|
|
|
67813
68095
|
ClaimPublicationSchema = import_zod52.z.object(CommonsClaimPublicationInputSchema).strict();
|
|
67814
68096
|
PublishEditorialSchema = import_zod52.z.object(CommonsPublishEditorialInputSchema).strict();
|
|
67815
68097
|
UpdateEditorialArticleSchema = import_zod52.z.object(CommonsUpdateEditorialArticleInputSchema).strict();
|
|
68098
|
+
commonsApp.post("/index/embed", auth2, async (c) => {
|
|
68099
|
+
const body = await c.req.json().catch(() => ({}));
|
|
68100
|
+
const result = await embedQueuedCommonsDocuments(Number(body.limit) || 50);
|
|
68101
|
+
return c.json({ ok: true, data: result });
|
|
68102
|
+
});
|
|
68103
|
+
commonsApp.get("/index/status", auth2, async (c) => {
|
|
68104
|
+
return c.json({ ok: true, data: { queued: await queuedCommonsDocumentCount(), semanticSearchConfigured: commonsSemanticSearchConfigured() } });
|
|
68105
|
+
});
|
|
67816
68106
|
commonsApp.get("/health", async (c) => {
|
|
67817
68107
|
await ensureCommonsSchema();
|
|
67818
68108
|
return c.json({ ok: true, data: commonsDatabaseReport() });
|
|
@@ -67871,6 +68161,28 @@ var init_commons_routes = __esm({
|
|
|
67871
68161
|
return publicationError(c, error);
|
|
67872
68162
|
}
|
|
67873
68163
|
});
|
|
68164
|
+
commonsApp.get("/publications/:subdomain/articles/:articleSlug/site", async (c) => {
|
|
68165
|
+
try {
|
|
68166
|
+
const result = await getCommonsPublicationArticleHtml(c.req.param("subdomain"), c.req.param("articleSlug"));
|
|
68167
|
+
if (!result) return c.json({ ok: false, error: "article_not_found", message: "No published article matched that publication and slug." }, 404);
|
|
68168
|
+
return c.html(result.html, 200, {
|
|
68169
|
+
"cache-control": "public, max-age=60, s-maxage=300",
|
|
68170
|
+
"x-robots-tag": "index, follow",
|
|
68171
|
+
link: `<${result.canonicalUrl}>; rel="canonical"`
|
|
68172
|
+
});
|
|
68173
|
+
} catch (error) {
|
|
68174
|
+
return publicationError(c, error);
|
|
68175
|
+
}
|
|
68176
|
+
});
|
|
68177
|
+
commonsApp.get("/publications/:subdomain/editions/:editionSlug/articles/:articleSlug/site", async (c) => {
|
|
68178
|
+
try {
|
|
68179
|
+
const result = await getCommonsPublicationArticleHtml(c.req.param("subdomain"), c.req.param("articleSlug"), c.req.param("editionSlug"));
|
|
68180
|
+
if (!result) return c.json({ ok: false, error: "article_not_found", message: "No published article matched that publication, edition, and slug." }, 404);
|
|
68181
|
+
return c.html(result.html, 200, { "cache-control": "public, max-age=60, s-maxage=300", "x-robots-tag": "index, follow" });
|
|
68182
|
+
} catch (error) {
|
|
68183
|
+
return publicationError(c, error);
|
|
68184
|
+
}
|
|
68185
|
+
});
|
|
67874
68186
|
commonsApp.get("/publications/:subdomain/editions/:editionSlug/site", async (c) => {
|
|
67875
68187
|
try {
|
|
67876
68188
|
const result = await getCommonsPublicationEditionHtml(c.req.param("subdomain"), c.req.param("editionSlug"));
|
|
@@ -71439,7 +71751,7 @@ function pixelSnippet(publicId) {
|
|
|
71439
71751
|
function formSnippet(publicId) {
|
|
71440
71752
|
return `<div data-mcp-form="${publicId}"></div><script async src="https://mcpscraper.dev/analytics/v1/form.js?form=${publicId}"></script>`;
|
|
71441
71753
|
}
|
|
71442
|
-
function
|
|
71754
|
+
function escapeHtml8(value) {
|
|
71443
71755
|
return String(value ?? "").replace(
|
|
71444
71756
|
/[&<>"']/g,
|
|
71445
71757
|
(character) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[character]
|
|
@@ -71451,13 +71763,13 @@ function renderPublicForm(form, placementUrl) {
|
|
|
71451
71763
|
const fields = form.fields.map((field) => {
|
|
71452
71764
|
const required = field.required ? " required" : "";
|
|
71453
71765
|
const options = (field.options ?? []).map(
|
|
71454
|
-
(option) => `<option value="${
|
|
71766
|
+
(option) => `<option value="${escapeHtml8(option)}">${escapeHtml8(option)}</option>`
|
|
71455
71767
|
).join("");
|
|
71456
|
-
const control = field.type === "textarea" ? `<textarea id="${
|
|
71457
|
-
return `<label${field.type === "checkbox" ? ' class="check"' : ""}><span>${
|
|
71768
|
+
const control = field.type === "textarea" ? `<textarea id="${escapeHtml8(field.id)}" name="${escapeHtml8(field.id)}"${required}></textarea>` : field.type === "select" ? `<select id="${escapeHtml8(field.id)}" name="${escapeHtml8(field.id)}"${required}><option value="">Choose\u2026</option>${options}</select>` : field.type === "checkbox" ? `<input id="${escapeHtml8(field.id)}" name="${escapeHtml8(field.id)}" type="checkbox" value="true"${required}>` : `<input id="${escapeHtml8(field.id)}" name="${escapeHtml8(field.id)}" type="${escapeHtml8(field.type)}"${required}>`;
|
|
71769
|
+
return `<label${field.type === "checkbox" ? ' class="check"' : ""}><span>${escapeHtml8(field.label)}${field.required ? " *" : ""}</span>${control}</label>`;
|
|
71458
71770
|
}).join("");
|
|
71459
71771
|
const brand = form.brand;
|
|
71460
|
-
return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>:root{font-family:ui-sans-serif,system-ui;color:${
|
|
71772
|
+
return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>:root{font-family:ui-sans-serif,system-ui;color:${escapeHtml8(brand.textColor)};background:${escapeHtml8(brand.backgroundColor)}}*{box-sizing:border-box}body{margin:0;padding:18px}form{display:grid;gap:14px}label{display:grid;gap:6px;font-size:13px;font-weight:650}.check{grid-template-columns:auto 1fr;align-items:center}.check span{grid-column:2}.check input{grid-column:1;grid-row:1}input,textarea,select{width:100%;min-height:44px;padding:10px 12px;border:1px solid #ccd3df;border-radius:${brand.radius}px;background:white;color:inherit;font:inherit}textarea{min-height:110px;resize:vertical}button{min-height:46px;border:0;border-radius:${brand.radius}px;color:white;background:${escapeHtml8(brand.primaryColor)};font:inherit;font-weight:750;cursor:pointer}.consent{margin:0;color:#667085;font-size:11px;line-height:1.45}.notice{display:none;padding:12px;border-radius:${brand.radius}px;background:#edf8f2;color:#17613c}.hp{position:absolute!important;left:-9999px!important}</style></head><body><form id="mcp-form">${fields}<label class="hp">Website<input name="website" autocomplete="off" tabindex="-1"></label>${form.consent_text ? `<p class="consent">${escapeHtml8(form.consent_text)}</p>` : ""}<button>${escapeHtml8(form.submit_label)}</button><div class="notice" role="status"></div></form><script>(()=>{const form=document.querySelector('#mcp-form'),notice=form.querySelector('.notice'),q=new URLSearchParams(location.search);form.addEventListener('submit',async event=>{event.preventDefault();const button=form.querySelector('button');button.disabled=true;const raw=Object.fromEntries(new FormData(form).entries()),website=String(raw.website||''),clickIds={};delete raw.website;for(const k of ['fbclid','gclid','gbraid','wbraid','ttclid','rdt_cid','msclkid']){const v=q.get(k);if(v)clickIds[k]=v}try{const response=await fetch('/analytics/forms/${escapeHtml8(form.public_id)}/submissions',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({data:raw,website,placementUrl:${JSON.stringify(placementUrl)},visitorId:q.get('visitor')||undefined,sessionId:q.get('session')||undefined,source:q.get('source')||undefined,medium:q.get('medium')||undefined,campaign:q.get('campaign')||undefined,clickIds})});if(!response.ok)throw new Error('submit');notice.textContent=${JSON.stringify(form.success_message)};notice.style.display='block';form.reset();${form.redirect_url ? `setTimeout(()=>{top.location.href=${JSON.stringify(form.redirect_url)}},700);` : ""}}catch{notice.textContent='Your response could not be submitted. Please try again.';notice.style.display='block'}finally{button.disabled=false}})})()</script></body></html>`;
|
|
71461
71773
|
}
|
|
71462
71774
|
var import_hono32, import_factory6, import_zod54, import_node_crypto43, import_papaparse4, analyticsApp, auth3, entitlementGuard, ThorbitApiKeySchema, ThorbitCallbackSchema, SiteInputSchema, PixelInputSchema, PixelUpdateSchema, EventSchema, IngestionSchema, ConversionSchema, ExportSchema2, CampaignLinkSchema, FormFieldSchema, FormInputSchema, FormSubmissionSchema, CrmImportSchema, ActivationDestinationSchema, BusinessModelSchema, AdSpendSchema;
|
|
71463
71775
|
var init_analytics_routes = __esm({
|
|
@@ -72943,7 +73255,7 @@ var init_scheduled_run_view_links = __esm({
|
|
|
72943
73255
|
});
|
|
72944
73256
|
|
|
72945
73257
|
// src/personal-authority/render.ts
|
|
72946
|
-
function
|
|
73258
|
+
function escapeHtml9(value) {
|
|
72947
73259
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
72948
73260
|
"&": "&",
|
|
72949
73261
|
"<": "<",
|
|
@@ -72954,13 +73266,13 @@ function escapeHtml8(value) {
|
|
|
72954
73266
|
}
|
|
72955
73267
|
function safeHref(value) {
|
|
72956
73268
|
const trimmed = value.trim();
|
|
72957
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73269
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml9(trimmed) : "#";
|
|
72958
73270
|
}
|
|
72959
73271
|
function initials(name) {
|
|
72960
73272
|
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("") || "PA";
|
|
72961
73273
|
}
|
|
72962
73274
|
function action(action3, secondary = false) {
|
|
72963
|
-
return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref(action3.href)}">${
|
|
73275
|
+
return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref(action3.href)}">${escapeHtml9(action3.label)} <span aria-hidden="true">\u2197</span></a>`;
|
|
72964
73276
|
}
|
|
72965
73277
|
function section(enabled, html) {
|
|
72966
73278
|
return enabled ? html : "";
|
|
@@ -72969,7 +73281,7 @@ function renderPersonalAuthorityV1(input, config, generatedAt) {
|
|
|
72969
73281
|
const flags = config.featureFlags;
|
|
72970
73282
|
const brand = config.brandName || input.name;
|
|
72971
73283
|
const generatedAtIso = generatedAt.toISOString();
|
|
72972
|
-
const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link2) => `<a href="${safeHref(link2.href)}">${
|
|
73284
|
+
const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link2) => `<a href="${safeHref(link2.href)}">${escapeHtml9(link2.label)}</a>`).join("")}</nav>` : "";
|
|
72973
73285
|
const navigation = flags.navigation ? `<button class="menu" type="button" aria-expanded="false" aria-controls="nav">Menu</button><nav id="nav" class="nav" aria-label="Primary navigation"><a href="#about">About</a><a href="#services">Work</a><a href="#proof">Proof</a><a href="#contact">Contact</a></nav>` : "";
|
|
72974
73286
|
const authority = input.authority;
|
|
72975
73287
|
const consultation = input.consultation;
|
|
@@ -72981,21 +73293,21 @@ function renderPersonalAuthorityV1(input, config, generatedAt) {
|
|
|
72981
73293
|
<html lang="en" data-theme="${config.theme}">
|
|
72982
73294
|
<head>
|
|
72983
73295
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
72984
|
-
<meta name="description" content="${
|
|
73296
|
+
<meta name="description" content="${escapeHtml9(input.summary)}"><title>${escapeHtml9(input.name)} \u2014 ${escapeHtml9(input.professionalTitle)}</title>
|
|
72985
73297
|
<style>
|
|
72986
73298
|
:root{--blue:#2f66eb;--blue-soft:#dbe6ff;--ink:#050708;--paper:#f7f8fb;--white:#fff;--gray:#9ca5b5;--line:#27303b;--serif:Georgia,'Times New Roman',serif;--sans:Arial,Helvetica,sans-serif}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--ink);color:var(--white);font-family:var(--sans);line-height:1.55}a{color:inherit}.skip{position:absolute;left:-9999px}.skip:focus{left:16px;top:16px;z-index:9;background:#fff;color:#000;padding:10px}.header{height:88px;display:flex;align-items:center;justify-content:space-between;padding:0 clamp(20px,4vw,72px);border-bottom:1px solid var(--line);position:relative;z-index:3;background:rgba(5,7,8,.96)}.brand{display:flex;align-items:center;gap:12px;text-decoration:none;font-family:var(--serif);font-size:24px}.mark{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;background:var(--blue);font-family:var(--sans);font-weight:700}.nav{display:flex;align-items:center;gap:28px}.nav a{text-decoration:none;color:#c8ced8;font-size:14px}.nav a:hover{color:#fff}.menu{display:none;background:transparent;color:#fff;border:1px solid #5b6471;padding:10px 14px}.hero{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.25fr);min-height:760px;border-bottom:3px solid var(--blue)}.portrait{display:grid;place-items:end center;background:radial-gradient(circle at 50% 38%,#273243 0,#11161d 38%,#060708 70%);overflow:hidden}.portrait-card{width:min(82%,560px);aspect-ratio:4/5;display:grid;place-items:center;align-self:end;border:1px solid #263142;border-bottom:0;background:linear-gradient(145deg,#252d38,#0b0d10 58%);font-family:var(--serif);font-size:clamp(80px,13vw,180px);color:#d9e4ff;text-shadow:0 0 42px rgba(47,102,235,.5)}.hero-copy{padding:clamp(44px,7vw,110px) clamp(24px,6vw,100px);display:flex;flex-direction:column;justify-content:center;background:linear-gradient(135deg,#080a0d,#101318)}h1,h2,h3,p{margin-top:0}.hero h1{font-family:var(--serif);font-size:clamp(58px,8vw,116px);line-height:.92;font-weight:400;color:var(--blue);margin-bottom:24px}.role{font-family:var(--serif);font-size:clamp(28px,3.8vw,52px);line-height:1.05;border-left:5px solid var(--blue);padding-left:22px;max-width:820px}.summary{color:#c6cbd3;font-size:clamp(17px,1.5vw,22px);max-width:760px}.actions{display:flex;gap:12px;flex-wrap:wrap;margin:24px 0}.button{display:inline-flex;align-items:center;justify-content:space-between;gap:28px;min-height:58px;padding:0 26px;background:var(--blue);border:1px solid var(--blue);text-decoration:none;font-weight:700}.button--secondary{background:transparent;border-color:#5c6572}.social{display:flex;gap:10px;flex-wrap:wrap}.social a{border:1px solid #39414d;border-radius:999px;padding:8px 13px;text-decoration:none;color:#d8dce4;font-size:13px}.light{background:var(--paper);color:#111722;padding:clamp(70px,10vw,150px) clamp(20px,6vw,90px)}.light h2,.section h2{font-family:var(--serif);font-size:clamp(42px,6vw,82px);line-height:1.02;font-weight:400;max-width:1080px}.light p{max-width:920px;color:#4e596a;font-size:18px}.section{padding:clamp(70px,9vw,130px) clamp(20px,6vw,90px);border-bottom:1px solid var(--line)}.section-head{max-width:920px;margin-bottom:46px}.eyebrow{text-transform:uppercase;letter-spacing:.18em;font-size:12px;color:#aab2bf}.consult{display:grid;grid-template-columns:1.3fr .7fr;gap:50px;background:linear-gradient(130deg,#060708,#111721)}.accent-card{min-height:360px;border:1px solid #2a3545;background:linear-gradient(145deg,rgba(47,102,235,.22),transparent 55%);display:grid;place-items:center;font-family:var(--serif);font-size:96px;color:var(--blue)}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.card{border:1px solid #323a46;padding:26px;min-height:220px;background:#0b0e12}.card h3{font-family:var(--serif);font-size:30px}.card p{color:#b9c0ca}.learning{background:#020303}.topic-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;background:#29313c;border:1px solid #29313c}.topic{background:#050708;padding:30px}.topic strong{display:block;color:var(--blue);text-transform:uppercase;font-size:11px;letter-spacing:.15em}.topic h3{font-family:var(--serif);font-size:30px;margin:8px 0}.topic p{color:#aeb6c1}.proof{background:linear-gradient(180deg,#0a0d11,#050607)}.quotes{display:flex;gap:14px;overflow:auto;scroll-snap-type:x mandatory;padding-bottom:12px}.quote{min-width:min(420px,86vw);scroll-snap-align:start;border:1px solid #343d49;padding:30px;background:#0c1015}.quote q{font-family:var(--serif);font-size:30px;line-height:1.25}.quote span{display:block;margin-top:24px;color:#aeb5c0;font-size:12px;text-transform:uppercase;letter-spacing:.12em}.cta{text-align:center;border-top:3px solid var(--blue);background:radial-gradient(circle at 50% 0,rgba(47,102,235,.25),transparent 50%)}.cta h2{margin-left:auto;margin-right:auto}.footer{display:grid;grid-template-columns:1fr auto;gap:40px;padding:46px clamp(20px,6vw,90px);color:#abb3bf}.footer strong{color:#fff;font-family:var(--serif);font-size:26px}.generated{font-size:11px;color:#737d8b;margin-top:10px}html[data-theme='slate']{--blue:#7f95b8;--blue-soft:#dfe6ef}html[data-theme='monochrome']{--blue:#fff;--blue-soft:#e7e7e7}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}
|
|
72987
73299
|
@media(max-width:760px){.header{height:78px}.menu{display:block}.nav{display:none;position:absolute;left:0;right:0;top:77px;padding:18px 20px;background:#090b0e;border-bottom:1px solid #303844;flex-direction:column;align-items:stretch}.nav.open{display:flex}.hero{grid-template-columns:1fr;min-height:0}.portrait{min-height:390px}.portrait-card{width:72%;max-height:360px}.hero-copy{padding:48px 20px 66px}.hero h1{font-size:64px}.role{font-size:34px}.actions{display:grid}.button{width:100%}.consult{grid-template-columns:1fr}.accent-card{min-height:220px}.grid,.topic-grid{grid-template-columns:1fr}.light,.section{padding:64px 20px}.light h2,.section h2{font-size:46px}.footer{grid-template-columns:1fr}}
|
|
72988
73300
|
</style></head>
|
|
72989
73301
|
<body><a class="skip" href="#main">Skip to main content</a>
|
|
72990
|
-
<header class="header"><a class="brand" href="#top"><span class="mark">${
|
|
72991
|
-
<main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${
|
|
72992
|
-
${section(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${
|
|
72993
|
-
${section(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${
|
|
72994
|
-
${section(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${
|
|
72995
|
-
${section(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${
|
|
72996
|
-
${section(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${
|
|
72997
|
-
${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${
|
|
72998
|
-
</main><footer class="footer"><div><strong>${
|
|
73302
|
+
<header class="header"><a class="brand" href="#top"><span class="mark">${escapeHtml9(initials(input.name).slice(0, 1))}</span><strong>${escapeHtml9(brand)}</strong></a>${navigation}</header>
|
|
73303
|
+
<main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${escapeHtml9(initials(input.name))}</div></div><div class="hero-copy"><h1>${escapeHtml9(input.name)}</h1><p class="role">${escapeHtml9(input.professionalTitle)}</p><p class="summary">${escapeHtml9(input.summary)}</p><div class="actions">${action(input.primaryAction)}${input.secondaryAction ? action(input.secondaryAction, true) : ""}</div>${social}</div></section>
|
|
73304
|
+
${section(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${escapeHtml9(authority?.heading ?? "")}</h2>${authority?.paragraphs.map((paragraph) => `<p>${escapeHtml9(paragraph)}</p>`).join("") ?? ""}</section>`)}
|
|
73305
|
+
${section(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${escapeHtml9(consultation?.eyebrow ?? "Start a conversation")}</p><h2>${escapeHtml9(consultation?.heading ?? "")}</h2><p class="summary">${escapeHtml9(consultation?.summary ?? "")}</p>${consultation ? action(consultation.action) : ""}</div><div class="accent-card" aria-label="Image placeholder">${escapeHtml9(initials(input.name))}</div></section>`)}
|
|
73306
|
+
${section(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${escapeHtml9(learning?.heading ?? "")}</h2><p class="summary">${escapeHtml9(learning?.summary ?? "")}</p></div><div class="topic-grid">${learning?.topics.map((topic) => `<article class="topic"><strong>${escapeHtml9(topic.title)}</strong><h3>${escapeHtml9(topic.headline)}</h3><p>${escapeHtml9(topic.summary)}</p>${topic.href ? `<a href="${safeHref(topic.href)}">Explore \u2192</a>` : ""}</article>`).join("") ?? ""}</div></section>`)}
|
|
73307
|
+
${section(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${escapeHtml9(services?.heading ?? "")}</h2><p class="summary">${escapeHtml9(services?.summary ?? "")}</p></div><div class="grid">${services?.offers.map((offer) => `<article class="card"><h3>${escapeHtml9(offer.title)}</h3><p>${escapeHtml9(offer.description)}</p>${offer.action ? action(offer.action, true) : ""}</article>`).join("") ?? ""}</div></section>`)}
|
|
73308
|
+
${section(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${escapeHtml9(proof?.heading ?? "")}</h2><p class="summary">${escapeHtml9(proof?.summary ?? "")}</p></div><div class="quotes">${proof?.testimonials.map((item) => `<article class="quote"><q>${escapeHtml9(item.quote)}</q><span>${escapeHtml9(item.person)}${item.role ? ` / ${escapeHtml9(item.role)}` : ""}</span></article>`).join("") ?? ""}</div></section>`)}
|
|
73309
|
+
${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${escapeHtml9(finalCta?.eyebrow ?? "Ready when you are")}</p><h2>${escapeHtml9(finalCta?.heading ?? "")}</h2><p class="summary">${escapeHtml9(finalCta?.summary ?? "")}</p>${finalCta ? action(finalCta.action) : ""}</section>`)}
|
|
73310
|
+
</main><footer class="footer"><div><strong>${escapeHtml9(input.name)}</strong><div>${escapeHtml9(input.professionalTitle)}</div>${config.showGeneratedAt ? `<div class="generated">Generated ${escapeHtml9(generatedAtIso)}</div>` : ""}</div><div>${input.location ? `<div>${escapeHtml9(input.location)}</div>` : ""}${input.email ? `<a href="mailto:${escapeHtml9(input.email)}">${escapeHtml9(input.email)}</a>` : ""}${input.phone ? `<div>${escapeHtml9(input.phone)}</div>` : ""}</div></footer>
|
|
72999
73311
|
<script>document.querySelector('.menu')?.addEventListener('click',function(){var nav=document.querySelector('.nav');var open=this.getAttribute('aria-expanded')!=='true';this.setAttribute('aria-expanded',String(open));nav?.classList.toggle('open',open)});document.querySelectorAll('.nav a').forEach(function(link){link.addEventListener('click',function(){document.querySelector('.nav')?.classList.remove('open');document.querySelector('.menu')?.setAttribute('aria-expanded','false')})});</script></body></html>`;
|
|
73000
73312
|
const bytes = Buffer.byteLength(html, "utf8");
|
|
73001
73313
|
return {
|
|
@@ -73015,7 +73327,7 @@ var init_render2 = __esm({
|
|
|
73015
73327
|
});
|
|
73016
73328
|
|
|
73017
73329
|
// src/personal-authority/render-v2.ts
|
|
73018
|
-
function
|
|
73330
|
+
function escapeHtml10(value) {
|
|
73019
73331
|
return value.replace(
|
|
73020
73332
|
/[&<>"']/g,
|
|
73021
73333
|
(character) => ({
|
|
@@ -73029,13 +73341,13 @@ function escapeHtml9(value) {
|
|
|
73029
73341
|
}
|
|
73030
73342
|
function safeHref2(value) {
|
|
73031
73343
|
const trimmed = value.trim();
|
|
73032
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73344
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml10(trimmed) : "#";
|
|
73033
73345
|
}
|
|
73034
73346
|
function initials2(name) {
|
|
73035
73347
|
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("") || "PA";
|
|
73036
73348
|
}
|
|
73037
73349
|
function action2(action3, secondary = false) {
|
|
73038
|
-
return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref2(action3.href)}">${
|
|
73350
|
+
return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref2(action3.href)}">${escapeHtml10(action3.label)} <span aria-hidden="true">\u2197</span></a>`;
|
|
73039
73351
|
}
|
|
73040
73352
|
function section2(enabled, html) {
|
|
73041
73353
|
return enabled ? html : "";
|
|
@@ -73079,7 +73391,7 @@ function renderPersonalAuthorityV2(input, config, generatedAt) {
|
|
|
73079
73391
|
const surfaceContrast = bestContrastTextColor(colors.surface);
|
|
73080
73392
|
const accentChannels = hexChannels(colors.accent);
|
|
73081
73393
|
const generatedAtIso = generatedAt.toISOString();
|
|
73082
|
-
const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link2) => `<a href="${safeHref2(link2.href)}">${
|
|
73394
|
+
const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link2) => `<a href="${safeHref2(link2.href)}">${escapeHtml10(link2.label)}</a>`).join("")}</nav>` : "";
|
|
73083
73395
|
const navigation = flags.navigation ? `<button class="menu" type="button" aria-expanded="false" aria-controls="nav">Menu</button><nav id="nav" class="nav" aria-label="Primary navigation"><a href="#about">About</a><a href="#services">Work</a><a href="#proof">Proof</a><a href="#contact">Contact</a></nav>` : "";
|
|
73084
73396
|
const authority = input.authority;
|
|
73085
73397
|
const consultation = input.consultation;
|
|
@@ -73091,22 +73403,22 @@ function renderPersonalAuthorityV2(input, config, generatedAt) {
|
|
|
73091
73403
|
<html lang="en" data-theme="${config.theme}">
|
|
73092
73404
|
<head>
|
|
73093
73405
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
73094
|
-
<meta name="description" content="${
|
|
73406
|
+
<meta name="description" content="${escapeHtml10(input.summary)}"><title>${escapeHtml10(input.name)} - ${escapeHtml10(input.professionalTitle)}</title>
|
|
73095
73407
|
<style>
|
|
73096
73408
|
:root{--accent:${colors.accent};--accent-rgb:${accentChannels};--accent-contrast:${accentContrast};--background:${colors.background};--surface:${colors.surface};--surface-contrast:${surfaceContrast};--text:${colors.text};--muted:color-mix(in srgb,var(--text) 68%,var(--background));--surface-muted:color-mix(in srgb,var(--surface-contrast) 72%,var(--surface));--line:color-mix(in srgb,var(--text) 16%,var(--background));--display:${displayFont};--body:${bodyFont}}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--background);color:var(--text);font-family:var(--body);line-height:1.55}a{color:inherit}.skip{position:absolute;left:-9999px}.skip:focus{left:16px;top:16px;z-index:9;background:var(--accent);color:var(--accent-contrast);padding:10px 14px;border-radius:999px}.header{height:80px;display:flex;align-items:center;justify-content:space-between;padding:0 clamp(20px,4vw,72px);position:relative;z-index:3;background:var(--surface);color:var(--surface-contrast);border-radius:0 0 24px 24px}.brand{display:flex;align-items:center;gap:12px;text-decoration:none;font-family:var(--display);font-size:24px}.mark{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;background:var(--accent);color:var(--accent-contrast);font-family:var(--body);font-weight:700}.nav{display:flex;align-items:center;gap:28px}.nav a{text-decoration:none;color:var(--surface-muted);font-size:14px}.nav a:hover{color:var(--surface-contrast)}.nav a:focus-visible,.button:focus-visible,.social a:focus-visible,.menu:focus-visible{outline:3px solid var(--accent);outline-offset:4px}.menu{display:none;background:transparent;color:var(--surface-contrast);border:1px solid color-mix(in srgb,var(--surface-contrast) 28%,var(--surface));border-radius:999px;padding:10px 14px}.hero{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.25fr);min-height:min(760px,calc(100dvh - 80px));border-bottom:1px solid var(--line);background:var(--background)}.portrait{margin:clamp(16px,3vw,36px) clamp(12px,2vw,24px) clamp(16px,3vw,36px) clamp(16px,3vw,36px);display:grid;place-items:end center;background:var(--surface);border-radius:28px;overflow:hidden}.portrait-card{width:min(82%,560px);aspect-ratio:4/5;display:grid;place-items:center;align-self:end;border:1px solid color-mix(in srgb,var(--surface-contrast) 18%,var(--surface));border-bottom:0;background:linear-gradient(145deg,color-mix(in srgb,var(--surface-contrast) 12%,var(--surface)),var(--surface) 66%);font-family:var(--display);font-size:clamp(80px,13vw,180px);color:var(--surface-contrast)}.hero-copy{padding:clamp(44px,7vw,110px) clamp(24px,6vw,100px);display:flex;flex-direction:column;justify-content:center;background:var(--background)}h1,h2,h3,p{margin-top:0}.hero h1{font-family:var(--display);font-size:clamp(58px,8vw,116px);line-height:.96;font-weight:500;letter-spacing:-.04em;color:var(--text);margin-bottom:24px;text-wrap:balance}.role{font-family:var(--display);font-size:clamp(28px,3.8vw,52px);line-height:1.08;border-left:5px solid var(--accent);padding-left:22px;max-width:820px;text-wrap:balance}.summary{color:var(--muted);font-size:clamp(17px,1.5vw,22px);max-width:65ch}.actions{display:flex;gap:12px;flex-wrap:wrap;margin:24px 0}.button{display:inline-flex;align-items:center;justify-content:space-between;gap:28px;min-height:58px;padding:0 26px;background:var(--accent);color:var(--accent-contrast);border:1px solid var(--accent);border-radius:999px;text-decoration:none;font-weight:700;transition:transform .2s ease,filter .2s ease}.button:hover{filter:brightness(1.06)}.button:active{transform:translateY(1px)}.button--secondary{background:transparent;color:var(--text);border-color:var(--line)}.social{display:flex;gap:10px;flex-wrap:wrap}.social a{border:1px solid var(--line);border-radius:999px;padding:8px 13px;text-decoration:none;color:var(--muted);font-size:13px}.light{background:var(--background);color:var(--text);padding:clamp(70px,10vw,150px) clamp(20px,6vw,90px)}.light h2,.section h2{font-family:var(--display);font-size:clamp(42px,6vw,82px);line-height:1.05;font-weight:500;letter-spacing:-.035em;max-width:1080px;text-wrap:balance}.light p{max-width:65ch;color:var(--muted);font-size:18px}.section{padding:clamp(70px,9vw,130px) clamp(20px,6vw,90px);border-bottom:1px solid var(--line)}.section-head{max-width:920px;margin-bottom:46px}.eyebrow{text-transform:uppercase;letter-spacing:.18em;font-size:12px;color:var(--accent);font-weight:700}.consult{margin:clamp(20px,4vw,64px);display:grid;grid-template-columns:1.3fr .7fr;gap:50px;background:var(--surface);color:var(--surface-contrast);border:0;border-radius:28px}.consult .summary{color:var(--surface-muted)}.accent-card{min-height:360px;border:1px solid color-mix(in srgb,var(--surface-contrast) 18%,var(--surface));border-radius:24px;background:color-mix(in srgb,var(--accent) 14%,var(--surface));display:grid;place-items:center;font-family:var(--display);font-size:96px;color:var(--surface-contrast)}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.card{padding:30px;min-height:240px;border-radius:28px;background:var(--surface);color:var(--surface-contrast)}.card h3{font-family:var(--display);font-size:30px}.card p{color:var(--surface-muted)}.card .button--secondary{color:var(--surface-contrast);border-color:color-mix(in srgb,var(--surface-contrast) 28%,var(--surface))}.learning{background:var(--background)}.topic-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.topic{background:color-mix(in srgb,var(--text) 5%,var(--background));color:var(--text);border:1px solid var(--line);border-radius:28px;padding:30px}.topic strong{display:block;color:var(--accent);text-transform:uppercase;font-size:11px;letter-spacing:.15em}.topic h3{font-family:var(--display);font-size:30px;margin:8px 0}.topic p{color:var(--muted)}.topic a{color:var(--text);font-weight:700}.proof{background:color-mix(in srgb,var(--text) 5%,var(--background))}.quotes{display:flex;gap:14px;overflow:auto;scroll-snap-type:x mandatory;padding-bottom:12px}.quote{min-width:min(420px,86vw);scroll-snap-align:start;border:1px solid var(--line);border-radius:24px;padding:30px;background:var(--background)}.quote q{font-family:var(--display);font-size:30px;line-height:1.25}.quote span{display:block;margin-top:24px;color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.12em}.cta{margin:clamp(20px,4vw,64px);text-align:center;border:0;border-radius:28px;background:var(--surface);color:var(--surface-contrast)}.cta .summary{color:var(--surface-muted);margin-left:auto;margin-right:auto}.cta h2{margin-left:auto;margin-right:auto}.footer{display:grid;grid-template-columns:1fr auto;gap:40px;padding:46px clamp(20px,6vw,90px);color:var(--muted);background:var(--background)}.footer strong{color:var(--text);font-family:var(--display);font-size:26px}.generated{font-size:11px;color:var(--muted);margin-top:10px}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}
|
|
73097
73409
|
@media(max-width:760px){.header{height:78px;border-radius:0 0 18px 18px}.menu{display:block}.nav{display:none;position:absolute;left:0;right:0;top:77px;padding:18px 20px;background:var(--surface);border-radius:0 0 18px 18px;flex-direction:column;align-items:stretch}.nav.open{display:flex}.hero{grid-template-columns:1fr;min-height:0}.portrait{min-height:390px;margin:16px;border-radius:22px}.portrait-card{width:72%;max-height:360px}.hero-copy{padding:36px 20px 66px}.hero h1{font-size:58px}.role{font-size:34px}.actions{display:grid}.button{width:100%}.consult{grid-template-columns:1fr;margin:16px;border-radius:22px}.cta{margin:16px;border-radius:22px}.accent-card{min-height:220px}.grid,.topic-grid{grid-template-columns:1fr}.card,.topic{border-radius:22px}.light,.section{padding:64px 20px}.consult,.cta{padding:52px 20px}.light h2,.section h2{font-size:46px}.footer{grid-template-columns:1fr}}
|
|
73098
73410
|
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.button{transition:none}}
|
|
73099
73411
|
</style></head>
|
|
73100
73412
|
<body><a class="skip" href="#main">Skip to main content</a>
|
|
73101
|
-
<header class="header"><a class="brand" href="#top"><span class="mark">${
|
|
73102
|
-
<main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${
|
|
73103
|
-
${section2(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${
|
|
73104
|
-
${section2(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${
|
|
73105
|
-
${section2(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${
|
|
73106
|
-
${section2(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${
|
|
73107
|
-
${section2(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${
|
|
73108
|
-
${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${
|
|
73109
|
-
</main><footer class="footer"><div><strong>${
|
|
73413
|
+
<header class="header"><a class="brand" href="#top"><span class="mark">${escapeHtml10(initials2(input.name).slice(0, 1))}</span><strong>${escapeHtml10(brand)}</strong></a>${navigation}</header>
|
|
73414
|
+
<main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${escapeHtml10(initials2(input.name))}</div></div><div class="hero-copy"><h1>${escapeHtml10(input.name)}</h1><p class="role">${escapeHtml10(input.professionalTitle)}</p><p class="summary">${escapeHtml10(input.summary)}</p><div class="actions">${action2(input.primaryAction)}${input.secondaryAction ? action2(input.secondaryAction, true) : ""}</div>${social}</div></section>
|
|
73415
|
+
${section2(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${escapeHtml10(authority?.heading ?? "")}</h2>${authority?.paragraphs.map((paragraph) => `<p>${escapeHtml10(paragraph)}</p>`).join("") ?? ""}</section>`)}
|
|
73416
|
+
${section2(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${escapeHtml10(consultation?.eyebrow ?? "Start a conversation")}</p><h2>${escapeHtml10(consultation?.heading ?? "")}</h2><p class="summary">${escapeHtml10(consultation?.summary ?? "")}</p>${consultation ? action2(consultation.action) : ""}</div><div class="accent-card" aria-label="Image placeholder">${escapeHtml10(initials2(input.name))}</div></section>`)}
|
|
73417
|
+
${section2(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${escapeHtml10(learning?.heading ?? "")}</h2><p class="summary">${escapeHtml10(learning?.summary ?? "")}</p></div><div class="topic-grid">${learning?.topics.map((topic) => `<article class="topic"><strong>${escapeHtml10(topic.title)}</strong><h3>${escapeHtml10(topic.headline)}</h3><p>${escapeHtml10(topic.summary)}</p>${topic.href ? `<a href="${safeHref2(topic.href)}">Explore \u2192</a>` : ""}</article>`).join("") ?? ""}</div></section>`)}
|
|
73418
|
+
${section2(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${escapeHtml10(services?.heading ?? "")}</h2><p class="summary">${escapeHtml10(services?.summary ?? "")}</p></div><div class="grid">${services?.offers.map((offer) => `<article class="card"><h3>${escapeHtml10(offer.title)}</h3><p>${escapeHtml10(offer.description)}</p>${offer.action ? action2(offer.action, true) : ""}</article>`).join("") ?? ""}</div></section>`)}
|
|
73419
|
+
${section2(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${escapeHtml10(proof?.heading ?? "")}</h2><p class="summary">${escapeHtml10(proof?.summary ?? "")}</p></div><div class="quotes">${proof?.testimonials.map((item) => `<article class="quote"><q>${escapeHtml10(item.quote)}</q><span>${escapeHtml10(item.person)}${item.role ? ` / ${escapeHtml10(item.role)}` : ""}</span></article>`).join("") ?? ""}</div></section>`)}
|
|
73420
|
+
${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${escapeHtml10(finalCta?.eyebrow ?? "Ready when you are")}</p><h2>${escapeHtml10(finalCta?.heading ?? "")}</h2><p class="summary">${escapeHtml10(finalCta?.summary ?? "")}</p>${finalCta ? action2(finalCta.action) : ""}</section>`)}
|
|
73421
|
+
</main><footer class="footer"><div><strong>${escapeHtml10(input.name)}</strong><div>${escapeHtml10(input.professionalTitle)}</div>${config.showGeneratedAt ? `<div class="generated">Generated ${escapeHtml10(generatedAtIso)}</div>` : ""}</div><div>${input.location ? `<div>${escapeHtml10(input.location)}</div>` : ""}${input.email ? `<a href="mailto:${escapeHtml10(input.email)}">${escapeHtml10(input.email)}</a>` : ""}${input.phone ? `<div>${escapeHtml10(input.phone)}</div>` : ""}</div></footer>
|
|
73110
73422
|
<script>document.querySelector('.menu')?.addEventListener('click',function(){var nav=document.querySelector('.nav');var open=this.getAttribute('aria-expanded')!=='true';this.setAttribute('aria-expanded',String(open));nav?.classList.toggle('open',open)});document.querySelectorAll('.nav a').forEach(function(link){link.addEventListener('click',function(){document.querySelector('.nav')?.classList.remove('open');document.querySelector('.menu')?.setAttribute('aria-expanded','false')})});</script></body></html>`;
|
|
73111
73423
|
const bytes = Buffer.byteLength(html, "utf8");
|
|
73112
73424
|
return {
|
|
@@ -73132,7 +73444,7 @@ var init_render_v2 = __esm({
|
|
|
73132
73444
|
});
|
|
73133
73445
|
|
|
73134
73446
|
// src/newsroom-publisher/render.ts
|
|
73135
|
-
function
|
|
73447
|
+
function escapeHtml11(value) {
|
|
73136
73448
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
73137
73449
|
"&": "&",
|
|
73138
73450
|
"<": "<",
|
|
@@ -73143,30 +73455,30 @@ function escapeHtml10(value) {
|
|
|
73143
73455
|
}
|
|
73144
73456
|
function safeHref3(value) {
|
|
73145
73457
|
const trimmed = value.trim();
|
|
73146
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73458
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml11(trimmed) : "#";
|
|
73147
73459
|
}
|
|
73148
73460
|
function formatDate(value) {
|
|
73149
73461
|
const date = new Date(value);
|
|
73150
|
-
return Number.isNaN(date.getTime()) ?
|
|
73462
|
+
return Number.isNaN(date.getTime()) ? escapeHtml11(value) : new Intl.DateTimeFormat("en", { month: "short", day: "numeric", year: "numeric" }).format(date);
|
|
73151
73463
|
}
|
|
73152
73464
|
function initials3(value) {
|
|
73153
73465
|
return value.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
|
|
73154
73466
|
}
|
|
73155
73467
|
function storyMedia(story2, className = "") {
|
|
73156
73468
|
if (story2.imageUrl) {
|
|
73157
|
-
return `<div class="story-media ${className}"><img src="${safeHref3(story2.imageUrl)}" alt="${
|
|
73469
|
+
return `<div class="story-media ${className}"><img src="${safeHref3(story2.imageUrl)}" alt="${escapeHtml11(story2.imageAlt || story2.title)}" loading="lazy"></div>`;
|
|
73158
73470
|
}
|
|
73159
73471
|
const tone = [...story2.title].reduce((total, character) => total + character.charCodeAt(0), 0) % 5;
|
|
73160
|
-
return `<div class="story-media story-media--placeholder story-media--tone-${tone} ${className}" role="img" aria-label="Editorial image placeholder for ${
|
|
73472
|
+
return `<div class="story-media story-media--placeholder story-media--tone-${tone} ${className}" role="img" aria-label="Editorial image placeholder for ${escapeHtml11(story2.title)}"><i></i><b></b><span>${escapeHtml11(story2.category)}</span></div>`;
|
|
73161
73473
|
}
|
|
73162
73474
|
function byline(story2, showBylines) {
|
|
73163
|
-
const author = story2.author.href ? `<a href="${safeHref3(story2.author.href)}">${
|
|
73164
|
-
return `<div class="byline">${showBylines ? `<span>By ${author}</span>` : ""}<time datetime="${
|
|
73475
|
+
const author = story2.author.href ? `<a href="${safeHref3(story2.author.href)}">${escapeHtml11(story2.author.name)}</a>` : escapeHtml11(story2.author.name);
|
|
73476
|
+
return `<div class="byline">${showBylines ? `<span>By ${author}</span>` : ""}<time datetime="${escapeHtml11(story2.publishedAt)}">${formatDate(story2.publishedAt)}</time>${story2.sponsored ? "<b>Sponsored</b>" : ""}</div>`;
|
|
73165
73477
|
}
|
|
73166
73478
|
function storyCard(story2, showBylines, variant = "") {
|
|
73167
73479
|
return `<article class="story-card ${variant}">
|
|
73168
73480
|
<a class="story-card__media" href="${safeHref3(story2.href)}">${storyMedia(story2)}</a>
|
|
73169
|
-
<div class="story-card__body"><a class="kicker" href="${safeHref3(story2.href)}">${
|
|
73481
|
+
<div class="story-card__body"><a class="kicker" href="${safeHref3(story2.href)}">${escapeHtml11(story2.category)}</a><h3><a href="${safeHref3(story2.href)}">${escapeHtml11(story2.title)}</a></h3>${story2.dek ? `<p>${escapeHtml11(story2.dek)}</p>` : ""}${byline(story2, showBylines)}</div>
|
|
73170
73482
|
</article>`;
|
|
73171
73483
|
}
|
|
73172
73484
|
function renderNewsroomPublisherV1(input, config, generatedAt) {
|
|
@@ -73183,22 +73495,22 @@ function renderNewsroomPublisherV1(input, config, generatedAt) {
|
|
|
73183
73495
|
input.primaryPages.contact
|
|
73184
73496
|
];
|
|
73185
73497
|
const trustPages = Object.values(input.trustPages);
|
|
73186
|
-
const ticker = flags.breakingTicker && input.ticker ? `<div class="ticker"><div><b>${
|
|
73187
|
-
const masthead = `<nav class="utility-nav" aria-label="Publication pages"><div><span>${
|
|
73188
|
-
<a class="wordmark" href="${safeHref3(input.publication.url)}"><span>${
|
|
73498
|
+
const ticker = flags.breakingTicker && input.ticker ? `<div class="ticker"><div><b>${escapeHtml11(input.ticker.label)}</b><a href="${safeHref3(input.ticker.href || "#latest")}">${escapeHtml11(input.ticker.headline)}</a><span>${formatDate(generatedAtIso)}</span></div></div>` : "";
|
|
73499
|
+
const masthead = `<nav class="utility-nav" aria-label="Publication pages"><div><span>${escapeHtml11(input.publication.location || "Independent newsroom")}</span>${primaryPages.slice(1).map((link2) => `<a href="${safeHref3(link2.href)}">${escapeHtml11(link2.label)}</a>`).join("")}</div></nav><header class="masthead">
|
|
73500
|
+
<a class="wordmark" href="${safeHref3(input.publication.url)}"><span>${escapeHtml11(brand)}</span><small>${escapeHtml11(input.publication.tagline)}</small></a>
|
|
73189
73501
|
<div class="masthead__date"><span>Independent journalism</span><time datetime="${generatedAtIso}">${formatDate(generatedAtIso)}</time></div>
|
|
73190
73502
|
<div class="masthead__tools"><button type="button" aria-label="Search">Search</button><button type="button" aria-label="Open menu">Menu</button></div>
|
|
73191
73503
|
</header>`;
|
|
73192
|
-
const navigation = flags.navigation ? `<nav class="desk-nav" aria-label="Publication categories"><div><a class="desk-nav__home" href="#top">Home</a>${input.categories.map((category) => `<a href="${safeHref3(category.href)}">${
|
|
73504
|
+
const navigation = flags.navigation ? `<nav class="desk-nav" aria-label="Publication categories"><div><a class="desk-nav__home" href="#top">Home</a>${input.categories.map((category) => `<a href="${safeHref3(category.href)}">${escapeHtml11(category.label)}</a>`).join("")}<a class="desk-nav__latest" href="#latest">Latest</a></div></nav>` : "";
|
|
73193
73505
|
const leadGrid = flags.leadGrid ? `<section class="lead-grid" aria-label="Top stories">
|
|
73194
73506
|
<div class="lead-grid__label"><span>Today\u2019s edition</span><b>Top stories</b></div>
|
|
73195
|
-
<article class="lead-story"><a class="lead-story__media" href="${safeHref3(lead.href)}">${storyMedia(lead, "story-media--lead")}</a><div class="lead-story__body"><a class="kicker" href="${safeHref3(lead.href)}">${
|
|
73507
|
+
<article class="lead-story"><a class="lead-story__media" href="${safeHref3(lead.href)}">${storyMedia(lead, "story-media--lead")}</a><div class="lead-story__body"><a class="kicker" href="${safeHref3(lead.href)}">${escapeHtml11(lead.category)}</a><h1><a href="${safeHref3(lead.href)}">${escapeHtml11(lead.title)}</a></h1>${lead.dek ? `<p>${escapeHtml11(lead.dek)}</p>` : ""}${byline(lead, config.showBylines)}<a class="read-story" href="${safeHref3(lead.href)}">Read the full report <span>\u2197</span></a></div></article>
|
|
73196
73508
|
<div class="lead-support">${supporting.slice(0, 4).map((story2, index) => `<div class="lead-support__item"><span>${String(index + 1).padStart(2, "0")}</span>${storyCard(story2, config.showBylines, "story-card--support")}</div>`).join("")}</div>
|
|
73197
73509
|
</section>` : "";
|
|
73198
73510
|
const latest = flags.latestNews && input.latest.length > 0 ? `<section class="latest" id="latest">
|
|
73199
73511
|
<div class="section-title"><div><span>Live desk</span><h2>Latest news</h2></div><a href="#top">Back to top \u2191</a></div>
|
|
73200
|
-
<div class="latest__layout"><div class="latest__feed">${input.latest.map((story2, index) => `<article class="feed-story"><span>${String(index + 1).padStart(2, "0")}</span><div><a class="kicker" href="${safeHref3(story2.href)}">${
|
|
73201
|
-
<aside class="editor-note"><span>From the newsroom</span><h3>Reporting with context, sources, and accountable bylines.</h3><p>${
|
|
73512
|
+
<div class="latest__layout"><div class="latest__feed">${input.latest.map((story2, index) => `<article class="feed-story"><span>${String(index + 1).padStart(2, "0")}</span><div><a class="kicker" href="${safeHref3(story2.href)}">${escapeHtml11(story2.category)}</a><h3><a href="${safeHref3(story2.href)}">${escapeHtml11(story2.title)}</a></h3>${story2.dek ? `<p>${escapeHtml11(story2.dek)}</p>` : ""}${byline(story2, config.showBylines)}</div>${storyMedia(story2, "story-media--feed")}</article>`).join("")}</div>
|
|
73513
|
+
<aside class="editor-note"><span>From the newsroom</span><h3>Reporting with context, sources, and accountable bylines.</h3><p>${escapeHtml11(input.editorial.disclosure)}</p>${trustPages.slice(0, 4).map((link2) => `<a href="${safeHref3(link2.href)}">${escapeHtml11(link2.label)} \u2197</a>`).join("")}</aside></div>
|
|
73202
73514
|
</section>` : "";
|
|
73203
73515
|
const sectionLayouts = ["panorama", "mosaic", "tiles"];
|
|
73204
73516
|
const sections = flags.categorySections ? input.sections.map((section3, sectionIndex) => {
|
|
@@ -73209,16 +73521,16 @@ function renderNewsroomPublisherV1(input, config, generatedAt) {
|
|
|
73209
73521
|
layout === "panorama" && index === 0 ? "story-card--panorama" : layout === "mosaic" && index === 0 ? "story-card--mosaic-lead" : ""
|
|
73210
73522
|
)).join("");
|
|
73211
73523
|
return `<section class="desk-section desk-section--${sectionIndex % 2 ? "tint" : "plain"} desk-section--layout-${layout}">
|
|
73212
|
-
<div class="section-title"><div><span>Coverage desk \xB7 ${String(sectionIndex + 1).padStart(2, "0")}</span><h2>${
|
|
73524
|
+
<div class="section-title"><div><span>Coverage desk \xB7 ${String(sectionIndex + 1).padStart(2, "0")}</span><h2>${escapeHtml11(section3.name)}</h2></div>${section3.href ? `<a href="${safeHref3(section3.href)}">View all ${escapeHtml11(section3.name)} \u2192</a>` : ""}</div>
|
|
73213
73525
|
<div class="desk-section__grid desk-section__grid--${layout}">${cards}</div>
|
|
73214
73526
|
</section>`;
|
|
73215
73527
|
}).join("") : "";
|
|
73216
|
-
const newsletter = flags.newsletter && input.newsletter ? `<section class="newsletter"><div><span>${
|
|
73217
|
-
const pressRoom = flags.pressRoom && input.pressRoom ? `<section class="press-room" id="press-room"><div class="press-room__intro"><span>Separate from editorial coverage</span><h2>${
|
|
73218
|
-
const trustCenter = `<section class="trust-center" id="trust"><div class="trust-center__intro"><span>Public record</span><h2>How this newsroom works.</h2><p>Ownership, editorial practice, technology use, commercial relationships, and reader rights should be easy to find\u2014and written to be understood.</p></div><div class="trust-center__grid">${trustPages.map((link2, index) => `<a href="${safeHref3(link2.href)}"><span>${String(index + 1).padStart(2, "0")}</span><strong>${
|
|
73219
|
-
const trustFooter = flags.trustFooter ? `<footer class="site-footer"><div class="editor"><span class="editor__avatar">${
|
|
73528
|
+
const newsletter = flags.newsletter && input.newsletter ? `<section class="newsletter"><div><span>${escapeHtml11(input.newsletter.eyebrow || "Reader briefing")}</span><h2>${escapeHtml11(input.newsletter.heading)}</h2><p>${escapeHtml11(input.newsletter.summary)}</p></div><a href="${safeHref3(input.newsletter.action.href)}">${escapeHtml11(input.newsletter.action.label)} \u2192</a></section>` : "";
|
|
73529
|
+
const pressRoom = flags.pressRoom && input.pressRoom ? `<section class="press-room" id="press-room"><div class="press-room__intro"><span>Separate from editorial coverage</span><h2>${escapeHtml11(input.pressRoom.heading)}</h2><p>${escapeHtml11(input.pressRoom.summary)}</p><a href="${safeHref3(input.pressRoom.action.href)}">${escapeHtml11(input.pressRoom.action.label)} \u2192</a></div><div class="release-list">${input.pressRoom.releases.map((release) => `<article><time datetime="${escapeHtml11(release.publishedAt)}">${formatDate(release.publishedAt)}</time><span>${escapeHtml11(release.originatingCity)}</span><h3><a href="${safeHref3(release.href)}">${escapeHtml11(release.headline)}</a></h3></article>`).join("") || "<p>No releases are currently published.</p>"}</div></section>` : "";
|
|
73530
|
+
const trustCenter = `<section class="trust-center" id="trust"><div class="trust-center__intro"><span>Public record</span><h2>How this newsroom works.</h2><p>Ownership, editorial practice, technology use, commercial relationships, and reader rights should be easy to find\u2014and written to be understood.</p></div><div class="trust-center__grid">${trustPages.map((link2, index) => `<a href="${safeHref3(link2.href)}"><span>${String(index + 1).padStart(2, "0")}</span><strong>${escapeHtml11(link2.label)}</strong><small>Read \u2192</small></a>`).join("")}</div></section>`;
|
|
73531
|
+
const trustFooter = flags.trustFooter ? `<footer class="site-footer"><div class="editor"><span class="editor__avatar">${escapeHtml11(initials3(input.editorial.managingEditor.name))}</span><div><small>${escapeHtml11(input.editorial.managingEditor.role)}</small><h2>${input.editorial.managingEditor.href ? `<a href="${safeHref3(input.editorial.managingEditor.href)}">${escapeHtml11(input.editorial.managingEditor.name)}</a>` : escapeHtml11(input.editorial.managingEditor.name)}</h2><p>${escapeHtml11(input.editorial.managingEditor.bio)}</p></div></div><div class="footer-links"><h3>${escapeHtml11(brand)}</h3><p>${escapeHtml11(input.publication.tagline)}</p><nav>${primaryPages.map((link2) => `<a href="${safeHref3(link2.href)}">${escapeHtml11(link2.label)}</a>`).join("")}</nav>${config.showGeneratedAt ? `<time datetime="${generatedAtIso}">Updated ${formatDate(generatedAtIso)}</time>` : ""}</div></footer>` : "";
|
|
73220
73532
|
const html = `<!doctype html>
|
|
73221
|
-
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><title>${
|
|
73533
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><title>${escapeHtml11(brand)} \xB7 News Publisher</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@75..125,300..900&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
73222
73534
|
<style>
|
|
73223
73535
|
:root{--ink:#0b0b0c;--soft-ink:#222326;--muted:#696b70;--paper:#fff;--cream:#f4f0e8;--wash:#f5f5f3;--line:#d8d8d4;--signal:#275cf3;--acid:#d9ff43;--dark:#0b0b0c;--serif:"Instrument Serif",Georgia,serif;--sans:"Archivo",Arial,sans-serif;--mono:"JetBrains Mono",monospace;font-family:var(--sans);color:var(--ink);background:var(--paper)}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--paper);line-height:1.45}body[data-theme=journal]{--cream:#eee7da;--signal:#9d2d25;--acid:#f0c84f}body[data-theme=midnight]{--paper:#e8e9ec;--cream:#dfe1e6;--wash:#d8dae0;--line:#b9bdc6;--signal:#224bcc}a{color:inherit;text-decoration:none}a,button{transition:color .18s ease,background .18s ease,opacity .18s ease,transform .18s ease}button{font:inherit}.utility-nav{color:#d2d2d2;background:var(--dark);border-bottom:1px solid #292929}.utility-nav>div{max-width:1180px;height:35px;margin:auto;display:flex;align-items:center;justify-content:flex-end;gap:20px;padding:0 18px;overflow:auto}.utility-nav span{margin-right:auto;color:#8d8d8d}.utility-nav a,.utility-nav span{font:600 8px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;white-space:nowrap}.utility-nav a:hover{color:#fff}.ticker{color:var(--ink);background:var(--acid);padding:0 18px}.ticker>div{max-width:1180px;height:36px;margin:auto;display:flex;align-items:center;gap:16px;font:600 10px/1 var(--mono)}.ticker b{padding:5px 7px;color:#fff;background:var(--ink);font-size:8px;letter-spacing:.1em;text-transform:uppercase}.ticker a{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ticker a:hover{text-decoration:underline}.ticker span{margin-left:auto;opacity:.58;font-size:8px;text-transform:uppercase}.masthead{max-width:1180px;height:126px;margin:auto;display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:42px;padding:0 18px}.wordmark{display:grid;justify-self:start}.wordmark span{font:400 clamp(40px,5vw,68px)/.82 var(--serif);letter-spacing:-.055em}.wordmark small{max-width:430px;margin-top:11px;color:var(--muted);font:600 8px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase}.masthead__date{display:grid;gap:3px;text-align:right}.masthead__date span,.masthead__date time{font:600 8px/1.4 var(--mono);letter-spacing:.08em;text-transform:uppercase}.masthead__date span{color:var(--signal)}.masthead__date time{color:var(--muted)}.masthead__tools{display:flex;border:1px solid var(--ink)}.masthead__tools button{height:38px;padding:0 13px;border:0;background:transparent;font:700 9px/1 var(--mono);text-transform:uppercase;cursor:pointer}.masthead__tools button+button{border-left:1px solid var(--ink)}.masthead__tools button:hover{color:#fff;background:var(--ink)}.desk-nav{position:sticky;top:0;z-index:20;color:var(--ink);background:rgba(255,255,255,.96);border-top:1px solid var(--ink);border-bottom:1px solid var(--ink);backdrop-filter:blur(10px)}.desk-nav>div{max-width:1180px;height:43px;margin:auto;display:flex;align-items:center;overflow-x:auto;padding:0 18px}.desk-nav a{height:42px;display:grid;place-items:center;padding:0 17px;border-right:1px solid var(--line);font:650 9px/1 var(--mono);letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}.desk-nav a:first-child{border-left:1px solid var(--line)}.desk-nav a:hover,.desk-nav__home{color:#fff!important;background:var(--ink)}.desk-nav__latest{margin-left:auto;color:var(--signal);border-left:1px solid var(--line)}main{max-width:1180px;margin:auto;padding:30px 18px 90px}.lead-grid{margin:0 -18px;padding:0 18px 42px;color:#fff;background:var(--dark);border-bottom:1px solid var(--ink)}.lead-grid__label{height:50px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #303030}.lead-grid__label span,.lead-grid__label b{font:600 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.lead-grid__label span{color:var(--acid)}.lead-grid__label b{color:#8f8f8f}.lead-story{display:grid;grid-template-columns:minmax(0,1.28fr) minmax(340px,.72fr);min-height:500px;border-bottom:1px solid #303030}.lead-story__media{display:block;margin-left:calc((1180px - 100vw)/2);min-width:0}.story-media{position:relative;aspect-ratio:16/10;overflow:hidden;background:#e2e2df}.story-media img{width:100%;height:100%;display:block;object-fit:cover;filter:saturate(.88) contrast(1.03);transition:transform .55s cubic-bezier(.2,.7,.2,1)}a:hover .story-media img{transform:scale(1.025)}.story-media--lead{height:100%;min-height:500px;aspect-ratio:auto}.story-media--placeholder{isolation:isolate;display:block;background:#d9d7d1}.story-media--placeholder:after{position:absolute;z-index:1;inset:0;background:linear-gradient(145deg,transparent 35%,rgba(0,0,0,.14));content:""}.story-media--placeholder i,.story-media--placeholder b{position:absolute;display:block}.story-media--placeholder i{width:72%;aspect-ratio:1;right:-20%;top:-32%;border:clamp(22px,5vw,72px) solid currentColor;border-radius:50%;opacity:.78}.story-media--placeholder b{width:42%;height:115%;left:15%;bottom:-45%;background:currentColor;transform:rotate(32deg);opacity:.88}.story-media--placeholder span{position:absolute;z-index:2;left:18px;bottom:15px;padding:6px 8px;color:#fff;background:var(--ink);font:600 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.story-media--tone-0{color:#123fce;background:#a5c8ff}.story-media--tone-1{color:#ef4d25;background:#ffd9bd}.story-media--tone-2{color:#907000;background:#f3df36}.story-media--tone-3{color:#1a7857;background:#b8e8cc}.story-media--tone-4{color:#7d3de0;background:#dfc5ff}.lead-story__body{display:flex;flex-direction:column;justify-content:center;padding:45px 0 45px 40px}.kicker{display:inline-flex;width:max-content;color:var(--signal);font:700 8px/1 var(--mono);letter-spacing:.11em;text-transform:uppercase}.lead-grid .kicker{color:var(--acid)}.lead-story h1{max-width:540px;margin:13px 0 18px;font:400 clamp(48px,5vw,76px)/.92 var(--serif);letter-spacing:-.052em}.lead-story p{max-width:490px;margin:0;color:#bdbdbd;font-size:15px;line-height:1.55}.byline{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:16px;color:var(--muted);font:600 8px/1.4 var(--mono);letter-spacing:.05em;text-transform:uppercase}.byline span{color:var(--ink);font-weight:700}.lead-grid .byline{color:#848484}.lead-grid .byline span{color:#e7e7e7}.byline b{padding:4px 6px;color:var(--ink);background:var(--acid)}.read-story{width:max-content;margin-top:34px;padding-bottom:6px;border-bottom:1px solid #777;font:650 10px/1 var(--mono);text-transform:uppercase}.read-story span{color:var(--acid)}.read-story:hover{border-color:#fff}.lead-support{display:grid;grid-template-columns:repeat(4,1fr);gap:0}.lead-support__item{display:grid;grid-template-columns:25px minmax(0,1fr);gap:12px;padding:22px 18px 0 0;border-right:1px solid #303030}.lead-support__item+.lead-support__item{padding-left:18px}.lead-support__item:last-child{border-right:0}.lead-support__item>span{color:#666;font:600 9px/1 var(--mono)}.story-card{min-width:0}.story-card h3{margin:7px 0;font:400 26px/1.02 var(--serif);letter-spacing:-.025em}.story-card p{margin:9px 0;color:var(--muted);font-size:12px}.story-card__body{padding-top:11px}.story-card--support .story-card__media{display:none}.story-card--support .story-card__body{padding:0}.story-card--support h3{margin-top:8px;color:#fff;font-size:21px}.story-card--support p,.story-card--support .byline span{display:none}.story-card--support .byline{color:#777}.section-title{display:flex;align-items:end;justify-content:space-between;gap:30px;margin-bottom:24px;padding-bottom:11px;border-bottom:2px solid var(--ink)}.section-title span,.newsletter span,.press-room__intro>span,.trust-center__intro>span{display:block;color:var(--signal);font:700 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.section-title h2,.newsletter h2,.press-room h2,.trust-center h2,.site-footer h2{margin:7px 0 0;font:400 clamp(38px,5vw,58px)/.95 var(--serif);letter-spacing:-.04em}.section-title>a{padding-bottom:4px;border-bottom:1px solid var(--ink);font:650 9px/1 var(--mono);text-transform:uppercase}.latest{padding:64px 0}.latest__layout{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:55px}.latest__feed{border-top:1px solid var(--ink)}.feed-story{display:grid;grid-template-columns:34px minmax(0,1fr) 180px;gap:18px;align-items:start;padding:19px 0;border-bottom:1px solid var(--line)}.feed-story>span{color:#a0a0a0;font:600 9px/1 var(--mono)}.feed-story h3{margin:7px 0;font:400 29px/1.02 var(--serif);letter-spacing:-.025em}.feed-story p{margin:8px 0;color:var(--muted);font-size:12px}.story-media--feed{aspect-ratio:4/3}.editor-note{position:sticky;top:68px;align-self:start;padding:25px;color:#fff;background:var(--dark);border-top:5px solid var(--acid)}.editor-note>span{color:var(--acid);font:600 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.editor-note h3{margin:13px 0;font:400 31px/.98 var(--serif)}.editor-note p{color:#aaa;font-size:12px}.editor-note a{display:block;padding:11px 0;border-top:1px solid #333;font:600 9px/1 var(--mono);text-transform:uppercase}.editor-note a:hover{color:var(--acid)}.desk-section{margin:0 -18px;padding:58px 18px;border-top:1px solid var(--ink)}.desk-section--tint{background:var(--cream)}.desk-section__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:26px 14px}.story-card--wide{grid-column:span 2;grid-row:span 2}.story-card--wide h3{max-width:530px;font-size:40px}.story-card--wide p{max-width:540px;font-size:13px}.desk-section__grid>.story-card:not(.story-card--wide) .story-media{aspect-ratio:1}.newsletter{position:relative;margin:64px 0;display:grid;grid-template-columns:1fr auto;align-items:end;gap:50px;overflow:hidden;padding:clamp(38px,6vw,72px);color:var(--ink);background:var(--acid)}.newsletter:after{position:absolute;width:260px;height:260px;right:18%;top:-160px;border:55px solid var(--ink);border-radius:50%;content:"";opacity:.08}.newsletter span{color:var(--ink)}.newsletter h2{max-width:760px;font-size:clamp(44px,6vw,72px)}.newsletter p{max-width:680px;margin-bottom:0;color:#303030}.newsletter>a,.press-room__intro>a{position:relative;z-index:1;display:inline-flex;padding:14px 18px;color:#fff;background:var(--ink);border:1px solid var(--ink);font:700 9px/1 var(--mono);text-transform:uppercase}.newsletter>a:hover,.press-room__intro>a:hover{color:var(--ink);background:transparent}.press-room{display:grid;grid-template-columns:.7fr 1.3fr;gap:56px;padding:62px 0;border-top:6px solid var(--ink)}.press-room__intro p{max-width:390px;color:var(--muted)}.release-list{border-top:1px solid var(--ink)}.release-list article{display:grid;grid-template-columns:105px 105px 1fr;gap:15px;align-items:start;padding:20px 0;border-bottom:1px solid var(--line)}.release-list time,.release-list span{color:var(--muted);font:500 8px/1.4 var(--mono);text-transform:uppercase}.release-list h3{margin:0;font:400 22px/1.04 var(--serif)}.trust-center{margin:20px -18px -90px;padding:70px max(18px,calc((100vw - 1144px)/2)) 82px;color:#fff;background:var(--dark)}.trust-center__intro{max-width:810px;margin-bottom:38px}.trust-center__intro>span{color:var(--acid)}.trust-center__intro p{max-width:670px;color:#aaa}.trust-center__grid{display:grid;grid-template-columns:repeat(2,1fr);border-top:1px solid #444}.trust-center__grid a{display:grid;grid-template-columns:32px minmax(0,1fr) auto;align-items:center;gap:15px;min-height:70px;padding:0 18px 0 0;border-bottom:1px solid #333}.trust-center__grid a:nth-child(odd){margin-right:28px}.trust-center__grid a:hover{color:var(--acid)}.trust-center__grid span,.trust-center__grid small{color:#696969;font:600 8px/1 var(--mono)}.trust-center__grid strong{font:400 20px/1 var(--serif)}.site-footer{display:grid;grid-template-columns:1.15fr .85fr;gap:80px;padding:70px max(24px,calc((100vw - 1144px)/2));color:var(--ink);background:var(--cream);border-top:1px solid var(--ink)}.editor{display:grid;grid-template-columns:78px 1fr;gap:22px}.editor__avatar{width:78px;height:78px;display:grid;place-items:center;color:#fff;background:var(--signal);font:400 27px/1 var(--serif)}.editor small{color:var(--signal);font:700 8px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase}.editor h2{font-size:38px}.editor p,.footer-links p{max-width:620px;color:var(--muted)}.footer-links h3{margin-top:0;font:400 29px/1 var(--serif)}.footer-links nav{display:grid;grid-template-columns:1fr 1fr;border-top:1px solid var(--ink)}.footer-links nav a{padding:9px 0;border-bottom:1px solid var(--line);font:600 8px/1 var(--mono);text-transform:uppercase}.footer-links time{display:block;margin-top:24px;color:var(--muted);font:500 8px/1 var(--mono)}@media(max-width:900px){.masthead{grid-template-columns:1fr auto;height:110px}.masthead__date{display:none}.lead-story{grid-template-columns:1fr}.lead-story__media{margin:0}.lead-story__body{padding:35px 0}.lead-support{grid-template-columns:1fr 1fr}.lead-support__item:nth-child(2){border-right:0}.lead-support__item:nth-child(n+3){border-top:1px solid #303030}.latest__layout,.press-room,.site-footer{grid-template-columns:1fr}.editor-note{position:static}.desk-section__grid{grid-template-columns:1fr 1fr}.story-card--wide{grid-column:1/-1}.site-footer{gap:40px}.feed-story{grid-template-columns:30px 1fr 150px}}@media(max-width:620px){.utility-nav span,.utility-nav a:nth-of-type(-n+2),.ticker span{display:none}.ticker>div{height:34px}.masthead{height:92px;gap:14px}.wordmark span{font-size:38px}.wordmark small{max-width:220px;font-size:6px}.masthead__tools button:first-child{display:none}.desk-nav>div{padding:0}.desk-nav a{padding:0 13px}.lead-grid{padding-bottom:20px}.lead-grid__label{height:40px}.story-media--lead{min-height:320px}.lead-story{min-height:0}.lead-story h1{font-size:48px}.lead-story__body{padding:27px 0 34px}.lead-support{grid-template-columns:1fr}.lead-support__item,.lead-support__item+.lead-support__item{padding:17px 0;border-right:0;border-top:1px solid #303030}.story-card--support h3{font-size:24px}.section-title{align-items:start}.section-title>a{display:none}.latest{padding:48px 0}.feed-story{grid-template-columns:25px 1fr}.story-media--feed{grid-column:2}.feed-story h3{font-size:26px}.desk-section__grid{grid-template-columns:1fr}.story-card--wide{grid-column:auto;grid-row:auto}.story-card--wide h3{font-size:34px}.newsletter{grid-template-columns:1fr}.newsletter h2{font-size:48px}.release-list article{grid-template-columns:1fr}.trust-center__grid{grid-template-columns:1fr}.trust-center__grid a:nth-child(odd){margin-right:0}.site-footer{padding:50px 20px}.editor{grid-template-columns:1fr}.footer-links nav{grid-template-columns:1fr}}
|
|
73224
73536
|
/* Tampa-inspired publication palette */
|
|
@@ -73235,7 +73547,7 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
|
|
|
73235
73547
|
@media(max-width:620px){main{width:100%}.story-media--lead{height:360px;min-height:0}.lead-story__body,.lead-support,.latest,.feed-story{width:100%;max-width:calc(100vw - 36px)}.feed-story>div{min-width:0}.lead-story h1,.story-card h3,.feed-story h3,.story-card h3 a,.feed-story h3 a{white-space:normal;word-break:break-word;overflow-wrap:anywhere}.lead-story h1{max-width:100%;font-size:40px;line-height:.94}.lead-support__item{width:100%;max-width:100%;grid-template-columns:24px minmax(0,1fr);overflow:hidden}.story-card--support,.story-card--support .story-card__body,.story-card--support h3{width:100%;max-width:calc(100vw - 92px)}.feed-story>div,.feed-story h3,.feed-story p{max-width:calc(100vw - 100px)}}
|
|
73236
73548
|
@media(max-width:900px){.story-card--panorama{grid-template-columns:1fr}.desk-section__grid--mosaic{grid-template-columns:repeat(2,1fr)}.desk-section__grid--tiles{grid-template-columns:repeat(2,1fr)}}
|
|
73237
73549
|
@media(max-width:620px){.desk-section__grid--panorama,.desk-section__grid--mosaic,.desk-section__grid--tiles{grid-template-columns:1fr}.story-card--panorama{display:block}.story-card--panorama h3,.story-card--mosaic-lead h3{font-size:34px}.story-card--mosaic-lead{grid-column:auto;grid-row:auto}.desk-section__grid--tiles>.story-card:nth-child(3n+2){margin-top:0}}
|
|
73238
|
-
</style></head><body data-theme="${
|
|
73550
|
+
</style></head><body data-theme="${escapeHtml11(config.theme)}" id="top" data-scheduled-renderer="newsroom_publisher_v1">${ticker}${masthead}${navigation}<main>${leadGrid}${latest}${sections}${newsletter}${pressRoom}${trustCenter}</main>${trustFooter}</body></html>`;
|
|
73239
73551
|
const bytes = Buffer.byteLength(html);
|
|
73240
73552
|
const sha2563 = (0, import_node_crypto48.createHash)("sha256").update(html).digest("hex");
|
|
73241
73553
|
const filename = `${brand.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "newsroom"}-news-site.html`;
|
|
@@ -73250,7 +73562,7 @@ var init_render3 = __esm({
|
|
|
73250
73562
|
});
|
|
73251
73563
|
|
|
73252
73564
|
// src/blog-article/render.ts
|
|
73253
|
-
function
|
|
73565
|
+
function escapeHtml12(value) {
|
|
73254
73566
|
return value.replace(
|
|
73255
73567
|
/[&<>"']/g,
|
|
73256
73568
|
(character) => ({
|
|
@@ -73264,11 +73576,11 @@ function escapeHtml11(value) {
|
|
|
73264
73576
|
}
|
|
73265
73577
|
function safeHref4(value) {
|
|
73266
73578
|
const trimmed = value.trim();
|
|
73267
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73579
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml12(trimmed) : "#";
|
|
73268
73580
|
}
|
|
73269
73581
|
function formatDate2(value) {
|
|
73270
73582
|
const date = new Date(value);
|
|
73271
|
-
return Number.isNaN(date.getTime()) ?
|
|
73583
|
+
return Number.isNaN(date.getTime()) ? escapeHtml12(value) : new Intl.DateTimeFormat("en", {
|
|
73272
73584
|
month: "long",
|
|
73273
73585
|
day: "numeric",
|
|
73274
73586
|
year: "numeric"
|
|
@@ -73282,15 +73594,15 @@ function jsonForScript(value) {
|
|
|
73282
73594
|
}
|
|
73283
73595
|
function portrait(input) {
|
|
73284
73596
|
if (input.author.portraitUrl) {
|
|
73285
|
-
return `<img class="author-portrait" src="${safeHref4(input.author.portraitUrl)}" alt="${
|
|
73597
|
+
return `<img class="author-portrait" src="${safeHref4(input.author.portraitUrl)}" alt="${escapeHtml12(input.author.portraitAlt || input.author.name)}">`;
|
|
73286
73598
|
}
|
|
73287
|
-
return `<span class="author-portrait author-initials" aria-label="${
|
|
73599
|
+
return `<span class="author-portrait author-initials" aria-label="${escapeHtml12(input.author.name)}">${escapeHtml12(initials4(input.author.name))}</span>`;
|
|
73288
73600
|
}
|
|
73289
73601
|
function sidebarArt(input) {
|
|
73290
73602
|
if (input.sidebarMedia?.imageUrl) {
|
|
73291
|
-
return `<img src="${safeHref4(input.sidebarMedia.imageUrl)}" alt="${
|
|
73603
|
+
return `<img src="${safeHref4(input.sidebarMedia.imageUrl)}" alt="${escapeHtml12(input.sidebarMedia.imageAlt)}">`;
|
|
73292
73604
|
}
|
|
73293
|
-
return `<svg viewBox="0 0 560 330" role="img" aria-label="${
|
|
73605
|
+
return `<svg viewBox="0 0 560 330" role="img" aria-label="${escapeHtml12(input.sidebarMedia?.imageAlt || "Editorial article illustration")}"><defs><linearGradient id="ba-sky" x1="0" x2="1"><stop stop-color="#dbeafe"/><stop offset="1" stop-color="#d1fae5"/></linearGradient></defs><rect width="560" height="330" fill="url(#ba-sky)"/><circle cx="455" cy="72" r="88" fill="#93c5fd" opacity=".35"/><path d="M76 180 280 42l204 138v118H76Z" fill="#fff"/><path d="M52 185 280 28l228 157" fill="none" stroke="#10213d" stroke-width="18" stroke-linecap="round" stroke-linejoin="round"/><rect x="232" y="180" width="96" height="118" rx="8" fill="#bfdbfe"/><circle cx="385" cy="178" r="40" fill="#f8d5b8"/><path d="M335 330v-70c0-39 22-68 50-68s50 29 50 68v70" fill="#2563eb"/><circle cx="458" cy="196" r="34" fill="#8b5e3c"/><path d="M418 330v-64c0-34 18-60 40-60s40 26 40 60v64" fill="#45d5aa"/></svg>`;
|
|
73294
73606
|
}
|
|
73295
73607
|
function citations(input) {
|
|
73296
73608
|
const published = new Date(input.publishedAt);
|
|
@@ -73319,23 +73631,23 @@ function renderBlogArticleV1(input, config, generatedAt) {
|
|
|
73319
73631
|
...flags.faq && input.faq.length ? [{ id: "faq", title: "Frequently asked questions" }] : []
|
|
73320
73632
|
];
|
|
73321
73633
|
const contributorText = [
|
|
73322
|
-
`Written by <a href="${safeHref4(input.author.href || "#author")}">${
|
|
73323
|
-
input.editor ? `Edited by <a href="${safeHref4(input.editor.href || "#")}">${
|
|
73324
|
-
input.reviewer ? `Reviewed by <a href="${safeHref4(input.reviewer.href || "#")}">${
|
|
73634
|
+
`Written by <a href="${safeHref4(input.author.href || "#author")}">${escapeHtml12(input.author.name)}</a>`,
|
|
73635
|
+
input.editor ? `Edited by <a href="${safeHref4(input.editor.href || "#")}">${escapeHtml12(input.editor.name)}</a>` : "",
|
|
73636
|
+
input.reviewer ? `Reviewed by <a href="${safeHref4(input.reviewer.href || "#")}">${escapeHtml12(input.reviewer.name)}${input.reviewer.credential ? `, ${escapeHtml12(input.reviewer.credential)}` : ""}</a>` : ""
|
|
73325
73637
|
].filter(Boolean).join(" \xB7 ");
|
|
73326
73638
|
const sections = input.sections.map(
|
|
73327
|
-
(section3) => `<section id="${
|
|
73639
|
+
(section3) => `<section id="${escapeHtml12(section3.id)}" class="article-section"><header>${section3.eyebrow ? `<span class="eyebrow">${escapeHtml12(section3.eyebrow)}</span>` : ""}<h2>${escapeHtml12(section3.title)}</h2></header>${section3.paragraphs.map((paragraph) => `<p>${escapeHtml12(paragraph)}</p>`).join("")}${section3.bullets?.length ? `<ul>${section3.bullets.map((item) => `<li>${escapeHtml12(item)}</li>`).join("")}</ul>` : ""}${section3.callout ? `<aside class="callout"><span>Worth noting</span><h3>${escapeHtml12(section3.callout.heading)}</h3><p>${escapeHtml12(section3.callout.body)}</p></aside>` : ""}</section>`
|
|
73328
73640
|
).join("");
|
|
73329
|
-
const faq = flags.faq && input.faq.length ? `<section id="faq" class="faq"><span class="eyebrow">Common questions</span><h2>Frequently asked questions</h2><div>${input.faq.map((item, index) => `<article><h3><button type="button" aria-expanded="false" aria-controls="faq-${index}"><span>${
|
|
73330
|
-
const media = flags.sidebarMedia && input.sidebarMedia ? `<figure class="sidebar-media" data-article-media>${sidebarArt(input)}${input.sidebarMedia.caption ? `<figcaption>${
|
|
73331
|
-
const disclosure = flags.disclosure && input.disclosure ? `<section class="disclosure"><button type="button" aria-expanded="false" aria-controls="disclosure-details"><span>${
|
|
73332
|
-
const toc = flags.stickyToc ? `<aside class="toc" data-sticky-toc><header><strong>Table of contents</strong><button type="button" aria-expanded="true" aria-controls="toc-links" aria-label="Collapse table of contents">\u2303</button></header><nav id="toc-links" aria-label="Table of contents">${tocItems.map((item, index) => `<a href="#${
|
|
73641
|
+
const faq = flags.faq && input.faq.length ? `<section id="faq" class="faq"><span class="eyebrow">Common questions</span><h2>Frequently asked questions</h2><div>${input.faq.map((item, index) => `<article><h3><button type="button" aria-expanded="false" aria-controls="faq-${index}"><span>${escapeHtml12(item.question)}</span><b aria-hidden="true">+</b></button></h3><p id="faq-${index}" hidden>${escapeHtml12(item.answer)}</p></article>`).join("")}</div></section>` : "";
|
|
73642
|
+
const media = flags.sidebarMedia && input.sidebarMedia ? `<figure class="sidebar-media" data-article-media>${sidebarArt(input)}${input.sidebarMedia.caption ? `<figcaption>${escapeHtml12(input.sidebarMedia.caption)}</figcaption>` : ""}</figure>` : "";
|
|
73643
|
+
const disclosure = flags.disclosure && input.disclosure ? `<section class="disclosure"><button type="button" aria-expanded="false" aria-controls="disclosure-details"><span>${escapeHtml12(input.disclosure.summary)}</span><b aria-hidden="true">\u2304</b></button><p id="disclosure-details" hidden>${escapeHtml12(input.disclosure.details)}</p></section>` : "";
|
|
73644
|
+
const toc = flags.stickyToc ? `<aside class="toc" data-sticky-toc><header><strong>Table of contents</strong><button type="button" aria-expanded="true" aria-controls="toc-links" aria-label="Collapse table of contents">\u2303</button></header><nav id="toc-links" aria-label="Table of contents">${tocItems.map((item, index) => `<a href="#${escapeHtml12(item.id)}"${index === 0 ? ' aria-current="location"' : ""}><i></i><span>${escapeHtml12(item.title)}</span></a>`).join("")}</nav><button class="back-top" type="button">Back to top \u2191</button></aside>` : "";
|
|
73333
73645
|
const actions = flags.citation || flags.share ? `<div class="article-actions">${flags.citation ? '<button type="button" data-cite aria-haspopup="dialog">\u270E <span>Cite us</span></button>' : ""}${flags.share ? '<button type="button" data-share>\u21E7 <span>Share this article</span></button>' : ""}</div><p class="action-status" aria-live="polite"></p>` : "";
|
|
73334
|
-
const author = flags.authorCard ? `<section id="author" class="author-card">${actions}<div class="author-grid">${portrait(input)}<div><span>Written by</span><h2>${input.author.href ? `<a href="${safeHref4(input.author.href)}">${
|
|
73335
|
-
const citationDialog = flags.citation ? `<dialog id="citation-dialog"><div><button class="dialog-close" type="button" aria-label="Close citation guide">\xD7</button><h2>Quick citation guide</h2><p>Select a citation to automatically copy it to your clipboard.</p><section>${Object.keys(citationValues).map((style) => `<button type="button" data-citation="${style}"><strong>${style}:</strong> ${
|
|
73336
|
-
const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><meta name="description" content="${
|
|
73646
|
+
const author = flags.authorCard ? `<section id="author" class="author-card">${actions}<div class="author-grid">${portrait(input)}<div><span>Written by</span><h2>${input.author.href ? `<a href="${safeHref4(input.author.href)}">${escapeHtml12(input.author.name)}</a>` : escapeHtml12(input.author.name)}</h2><p>${escapeHtml12(input.author.role)}</p>${input.author.socialLinks.length || input.author.email ? `<nav aria-label="Author links">${input.author.socialLinks.map((link2) => `<a href="${safeHref4(link2.href)}">${escapeHtml12(link2.label)}</a>`).join("")}${input.author.email ? `<a href="mailto:${escapeHtml12(input.author.email)}">Email</a>` : ""}</nav>` : ""}</div>${input.author.href ? `<a class="author-more" href="${safeHref4(input.author.href)}">Read more from ${escapeHtml12(input.author.name.split(/\s+/)[0] || input.author.name)}</a>` : ""}</div><p class="author-bio">${escapeHtml12(input.author.bio)}</p></section>` : actions;
|
|
73647
|
+
const citationDialog = flags.citation ? `<dialog id="citation-dialog"><div><button class="dialog-close" type="button" aria-label="Close citation guide">\xD7</button><h2>Quick citation guide</h2><p>Select a citation to automatically copy it to your clipboard.</p><section>${Object.keys(citationValues).map((style) => `<button type="button" data-citation="${style}"><strong>${style}:</strong> ${escapeHtml12(citationValues[style])}</button>`).join("")}</section><p class="citation-status" aria-live="polite"></p></div></dialog>` : "";
|
|
73648
|
+
const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><meta name="description" content="${escapeHtml12(input.dek || input.keyTakeaways[0])}"><title>${escapeHtml12(input.title)} \xB7 ${escapeHtml12(brand)}</title><style>
|
|
73337
73649
|
:root{--ink:#10213d;--ink2:#1c355a;--blue:#2563eb;--blue2:#1749b6;--mint:#45d5aa;--paper:#f7f5f0;--line:#dce4ef;--card:#fff;--body:#475569;--serif:Iowan Old Style,Palatino Linotype,Palatino,Georgia,serif;--sans:Inter,Avenir Next,ui-sans-serif,system-ui,sans-serif}body[data-theme="slate"]{--ink:#1e293b;--ink2:#334155;--blue:#475569;--blue2:#1e293b;--mint:#94a3b8;--paper:#f8fafc}body[data-theme="forest"]{--ink:#12352e;--ink2:#23584c;--blue:#147d64;--blue2:#0c5b48;--mint:#79d8bd;--paper:#f4f8f3}*{box-sizing:border-box}html{scroll-behavior:smooth;background:var(--paper)}body{margin:0;color:#252a33;background:var(--paper);font-family:var(--sans);line-height:1.6}a{color:inherit}button{font:inherit}button:focus-visible,a:focus-visible{outline:3px solid var(--mint);outline-offset:3px}.progress{position:fixed;z-index:50;top:0;left:0;height:4px;width:0;background:var(--mint)}.hero{position:relative;overflow:hidden;color:#fff;background:var(--ink)}.hero:after{position:absolute;right:-110px;top:-150px;width:420px;height:420px;border:1px solid #ffffff1a;border-radius:50%;content:""}.hero-inner{position:relative;z-index:1;max-width:1240px;margin:auto;padding:58px 42px 126px}.breadcrumb{display:flex;gap:8px;margin-bottom:34px;color:#dbeafecc;font-size:14px}.eyebrow{display:block;color:var(--blue);font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase}.hero .eyebrow{color:var(--mint)}h1,h2,h3,p{margin-top:0}.hero h1{max-width:1000px;margin:14px 0 24px;font:700 clamp(44px,6vw,78px)/.98 var(--serif);letter-spacing:-.035em}.hero .dek{max-width:780px;color:#dbeafe;font-size:20px}.contributors{margin-top:30px;color:#eff6ff;font-size:14px}.contributors a{font-weight:800}.meta{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:#dbeafecc}.layout{position:relative;z-index:2;display:grid;grid-template-columns:minmax(0,760px) 290px;gap:64px;max-width:1240px;margin:-78px auto 0;padding:0 42px 80px}.main{min-width:0}.takeaways{padding:38px 44px;border-radius:24px;background:#fff;box-shadow:0 24px 70px #10213d24}.takeaways h2{margin:5px 0 20px;font:700 32px/1.1 var(--serif);color:var(--ink)}.takeaways ul{display:grid;gap:16px;margin:0;padding:0;list-style:none}.takeaways li{position:relative;padding-left:26px;color:var(--body);font-size:17px}.takeaways li:before{position:absolute;left:2px;top:.7em;width:8px;height:8px;border-radius:50%;background:var(--blue);content:""}.intro{padding:40px 0 4px}.intro p,.article-section>p{margin-bottom:22px;color:var(--body);font:400 18px/1.75 var(--sans)}.article-section{scroll-margin-top:28px;padding-top:45px}.article-section h2,.faq h2{margin:6px 0 20px;color:var(--ink);font:700 38px/1.08 var(--serif);letter-spacing:-.02em}.article-section ul{display:grid;gap:10px;margin:22px 0;padding-left:24px;color:var(--body);font-size:17px}.article-section li::marker{color:var(--blue)}.callout{margin:34px 0;padding:24px 28px;border-left:4px solid var(--blue);border-radius:0 16px 16px 0;background:#fff}.callout span{color:var(--blue);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.callout h3{margin:5px 0 8px;color:var(--ink);font:700 24px/1.15 var(--serif)}.callout p{margin:0;color:var(--body)}.rail{padding-top:0}.sidebar-media{overflow:hidden;margin:0 0 18px;border:1px solid #dbeafe;border-radius:16px;background:#fff}.sidebar-media img,.sidebar-media svg{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.sidebar-media figcaption{padding:10px 13px;color:#64748b;font-size:11px}.disclosure{margin-bottom:28px;border-top:1px solid #dbeafe;border-bottom:1px solid #dbeafe}.disclosure button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:14px;padding:15px 0;border:0;color:#64748b;background:transparent;text-align:left;font-size:12px;cursor:pointer}.disclosure button b{color:var(--blue);font-size:18px;transition:transform .2s}.disclosure button[aria-expanded="true"] b{transform:rotate(180deg)}.disclosure p{padding:0 0 16px;margin:0;color:#64748b;font-size:12px}.toc{position:sticky;top:30px;padding:22px;border:1px solid var(--line);border-radius:16px;background:#fff;box-shadow:0 2px 5px #10213d12}.toc header{display:flex;align-items:center;justify-content:space-between}.toc header strong{color:var(--ink);font:700 21px/1 var(--serif)}.toc header button{width:34px;height:34px;border:0;border-radius:50%;color:var(--blue);background:transparent;cursor:pointer}.toc nav{display:grid;margin-top:14px}.toc nav a{display:flex;align-items:flex-start;gap:11px;padding:8px 0;color:#64748b;text-decoration:none;font-size:13px;line-height:1.35}.toc nav i{width:8px;height:8px;margin-top:5px;border:2px solid #bfdbfe;border-radius:50%}.toc nav a[aria-current="location"]{color:var(--ink);font-weight:800}.toc nav a[aria-current="location"] i{border-color:var(--blue);background:var(--blue)}.back-top{width:100%;margin-top:18px;padding:16px 0 0;border:0;border-top:1px solid var(--line);color:var(--blue);background:transparent;text-align:right;font-size:13px;font-weight:800;cursor:pointer}.faq{scroll-margin-top:28px;padding-top:64px}.faq>div{border-top:1px solid var(--line);border-bottom:1px solid var(--line)}.faq article+article{border-top:1px solid var(--line)}.faq h3{margin:0}.faq h3 button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:18px;padding:19px 0;border:0;color:var(--ink);background:transparent;text-align:left;font-weight:800;cursor:pointer}.faq h3 b{color:var(--blue);font-size:22px}.faq article>p{padding:0 0 20px;margin:0;color:var(--body);font-size:16px}.author-card{margin-top:64px;padding:32px 36px;border-radius:18px;background:#fff}.article-actions{display:flex;flex-wrap:wrap;justify-content:space-between;gap:14px}.article-actions button{display:inline-flex;min-height:46px;align-items:center;justify-content:center;gap:8px;padding:8px 18px;border:2px solid var(--blue);border-radius:999px;color:var(--ink);background:#fff;font-weight:800;cursor:pointer}.article-actions button:hover{color:#fff;background:var(--blue)}.action-status{min-height:20px;margin:8px 0 0;color:var(--blue);text-align:right;font-size:13px;font-weight:700}.author-grid{display:grid;grid-template-columns:auto 1fr auto;gap:22px;align-items:center;margin-top:24px}.author-portrait{width:88px;height:88px;border-radius:50%;object-fit:cover}.author-initials{display:grid;place-items:center;color:var(--ink);background:#fecdd3;font-size:22px;font-weight:900}.author-grid span{color:#64748b;font-size:13px}.author-grid h2{margin:2px 0;color:var(--ink);font:700 27px/1 var(--serif)}.author-grid h2 a{text-decoration:none}.author-grid p{margin:8px 0;color:#64748b;font-size:14px}.author-grid nav{display:flex;flex-wrap:wrap;gap:14px}.author-grid nav a{color:#64748b;font-size:12px}.author-more{display:inline-flex;min-height:48px;align-items:center;justify-content:center;padding:10px 24px;border:2px solid var(--blue);color:var(--blue);text-align:center;text-decoration:none;font-size:13px;font-weight:800}.author-bio{margin:24px 0 0!important;padding-top:20px;border-top:1px solid var(--line);color:var(--body);font-size:16px}dialog{width:min(720px,calc(100% - 30px));max-height:calc(100dvh - 30px);padding:0;border:0;border-radius:18px;color:var(--ink);background:#fff;box-shadow:0 24px 70px #10213d38}dialog::backdrop{background:#0f172a7a;backdrop-filter:blur(2px)}dialog>div{position:relative;padding:30px}dialog h2{margin:0 50px 2px 0;font:700 30px/1.1 var(--serif)}dialog>div>p{color:#64748b}.dialog-close{position:absolute;top:13px;right:13px;width:44px;height:44px;border:0;border-radius:50%;color:var(--blue);background:transparent;font-size:29px;cursor:pointer}dialog section{border-top:1px solid var(--line)}dialog section button{display:block;width:100%;padding:17px 5px;border:0;border-bottom:1px solid var(--line);color:var(--body);background:#fff;text-align:left;line-height:1.65;cursor:pointer}.citation-status{min-height:22px;margin:14px 0 0!important;color:var(--blue)!important;font-size:13px;font-weight:800}.generated{max-width:1156px;margin:-52px auto 50px;padding:0 42px;color:#94a3b8;font-size:11px}@media(max-width:900px){.layout{display:block}.rail{display:none}.hero-inner{padding-bottom:116px}}@media(max-width:620px){.hero-inner{padding:36px 20px 104px}.hero h1{font-size:46px}.hero .dek{font-size:17px}.layout{margin-top:-70px;padding:0 16px 54px}.takeaways{padding:28px 24px}.article-section h2,.faq h2{font-size:32px}.author-card{padding:24px}.article-actions{display:grid;justify-content:start}.author-grid{grid-template-columns:1fr;gap:12px}.author-more{width:100%}dialog>div{padding:24px}.generated{padding:0 20px}}
|
|
73338
|
-
</style></head><body data-theme="${
|
|
73650
|
+
</style></head><body data-theme="${escapeHtml12(config.theme)}" data-scheduled-renderer="blog_article_v1"><div class="progress" aria-hidden="true"></div><header class="hero"><div class="hero-inner"><nav class="breadcrumb" aria-label="Breadcrumb"><a href="${safeHref4(input.canonicalUrl)}">${escapeHtml12(input.category)}</a><span>/</span><span>Article</span></nav><span class="eyebrow">${escapeHtml12(input.eyebrow)}</span><h1>${escapeHtml12(input.title)}</h1>${input.dek ? `<p class="dek">${escapeHtml12(input.dek)}</p>` : ""}<div class="contributors">${contributorText}<div class="meta"><time datetime="${escapeHtml12(articleDate)}">Updated ${formatDate2(articleDate)}</time><span>\u2022</span><span>${input.readTimeMinutes} min read</span>${input.reviewer ? "<span>\u2022</span><strong>Expert reviewed</strong>" : ""}</div></div></div></header><main class="layout"><article class="main"><section class="takeaways"><span class="eyebrow">The short answer</span><h2>Key takeaways</h2><ul>${input.keyTakeaways.map((item) => `<li>${escapeHtml12(item)}</li>`).join("")}</ul></section><section class="intro">${input.introduction.map((paragraph) => `<p>${escapeHtml12(paragraph)}</p>`).join("")}</section>${sections}${faq}${author}</article><div class="rail">${media}${disclosure}${toc}</div></main>${config.showGeneratedAt ? `<p class="generated">Rendered ${formatDate2(generatedAtIso)} by MCP Scraper.</p>` : ""}${citationDialog}<script>(()=>{const citations=${jsonForScript(citationValues)};const canonical=${jsonForScript(input.canonicalUrl)};const title=${jsonForScript(input.title)};const progress=document.querySelector('.progress');const tocLinks=[...document.querySelectorAll('.toc nav a')];const targets=tocLinks.map(link=>document.querySelector(link.hash)).filter(Boolean);const update=()=>{const max=document.documentElement.scrollHeight-innerHeight;if(progress)progress.style.width=(max>0?scrollY/max*100:0)+'%';let active=targets[0]?.id;for(const target of targets){if(target.getBoundingClientRect().top<=innerHeight*.55)active=target.id}tocLinks.forEach(link=>link.toggleAttribute('aria-current',link.hash==='#'+active));tocLinks.forEach(link=>{if(link.hash==='#'+active)link.setAttribute('aria-current','location');else link.removeAttribute('aria-current')})};addEventListener('scroll',update,{passive:true});addEventListener('resize',update);update();document.querySelectorAll('.faq h3 button').forEach(button=>button.addEventListener('click',()=>{const panel=document.getElementById(button.getAttribute('aria-controls'));const open=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!open));panel.hidden=open;button.querySelector('b').textContent=open?'+':'\u2212'}));const disclosure=document.querySelector('.disclosure button');disclosure?.addEventListener('click',()=>{const panel=document.getElementById(disclosure.getAttribute('aria-controls'));const open=disclosure.getAttribute('aria-expanded')==='true';disclosure.setAttribute('aria-expanded',String(!open));panel.hidden=open});const tocToggle=document.querySelector('.toc header button');tocToggle?.addEventListener('click',()=>{const nav=document.getElementById('toc-links');const open=tocToggle.getAttribute('aria-expanded')==='true';tocToggle.setAttribute('aria-expanded',String(!open));nav.hidden=open;tocToggle.textContent=open?'\u2304':'\u2303'});document.querySelector('.back-top')?.addEventListener('click',()=>scrollTo({top:0,behavior:'smooth'}));const copy=async text=>{try{await navigator.clipboard.writeText(text)}catch{const area=document.createElement('textarea');area.value=text;area.style.position='fixed';area.style.opacity='0';document.body.append(area);area.select();document.execCommand('copy');area.remove()}};const dialog=document.getElementById('citation-dialog');document.querySelector('[data-cite]')?.addEventListener('click',()=>dialog.showModal());document.querySelector('.dialog-close')?.addEventListener('click',()=>dialog.close());dialog?.addEventListener('click',event=>{if(event.target===dialog)dialog.close()});document.querySelectorAll('[data-citation]').forEach(button=>button.addEventListener('click',async()=>{const style=button.dataset.citation;await copy(citations[style]);document.querySelector('.citation-status').textContent=style+' citation copied to clipboard.'}));document.querySelector('[data-share]')?.addEventListener('click',async()=>{const status=document.querySelector('.action-status');if(navigator.share){try{await navigator.share({title,url:canonical});status.textContent='Sharing options opened.';return}catch(error){if(error.name==='AbortError')return}}await copy(canonical);status.textContent='Article link copied to clipboard.'})})()</script></body></html>`;
|
|
73339
73651
|
const bytes = Buffer.byteLength(html);
|
|
73340
73652
|
const sha2563 = (0, import_node_crypto49.createHash)("sha256").update(html).digest("hex");
|
|
73341
73653
|
return {
|
|
@@ -76235,7 +76547,7 @@ function sql() {
|
|
|
76235
76547
|
if (_sql) return _sql;
|
|
76236
76548
|
const url = process.env.MEMORY_DATABASE_URL?.trim();
|
|
76237
76549
|
if (!url) throw new Error("MEMORY_DATABASE_URL is not set (paa-crawler needs mcp-memory Neon URL for reads)");
|
|
76238
|
-
_sql = (0,
|
|
76550
|
+
_sql = (0, import_serverless2.neon)(url);
|
|
76239
76551
|
return _sql;
|
|
76240
76552
|
}
|
|
76241
76553
|
function physicalVault(owner, vault) {
|
|
@@ -76428,11 +76740,11 @@ async function dbUsage(identity, plan) {
|
|
|
76428
76740
|
unlimited: isUnlimited(plan)
|
|
76429
76741
|
};
|
|
76430
76742
|
}
|
|
76431
|
-
var
|
|
76743
|
+
var import_serverless2, _sql, EMBED_BYTES_PER_CHUNK, FREE_COST_CAP_USD;
|
|
76432
76744
|
var init_memory_db = __esm({
|
|
76433
76745
|
"src/api/memory-db.ts"() {
|
|
76434
76746
|
"use strict";
|
|
76435
|
-
|
|
76747
|
+
import_serverless2 = require("@neondatabase/serverless");
|
|
76436
76748
|
init_rates();
|
|
76437
76749
|
init_memory_universe();
|
|
76438
76750
|
_sql = null;
|
|
@@ -79453,6 +79765,7 @@ var init_server = __esm({
|
|
|
79453
79765
|
init_scheduled_artifact_internal_routes();
|
|
79454
79766
|
init_site_audit_worker();
|
|
79455
79767
|
init_local_sourcebook_worker();
|
|
79768
|
+
init_commons_embeddings();
|
|
79456
79769
|
init_local_sourcebook_dispatch();
|
|
79457
79770
|
import_factory8 = require("hono/factory");
|
|
79458
79771
|
import_cookie2 = require("hono/cookie");
|
|
@@ -82236,7 +82549,7 @@ var init_server = __esm({
|
|
|
82236
82549
|
const budget = { maxJobs: 10, deadlineMs: startedAt + CRON_TICK_DRAIN_BUDGET_MS };
|
|
82237
82550
|
const origin = `${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`;
|
|
82238
82551
|
const unfinished = [];
|
|
82239
|
-
const [results, sweepResult, reapResult, expiredResult, blobCleanup, connectedDataArtifactCleanup, connectedAccountBilling, directoryWorkflowDispatch, directoryWorkflowReconciliation, directoryArtifactCleanup, siteExtractArtifactCleanup, siteExtractRedispatch, siteExtractReconciliation, paaHarvestRedispatch, paaHarvestReconciliation, localSourcebookRedispatch, analyticsRollup, analyticsFormDelivery, workflowDispatchResult, scheduledRunReconciliation, retentionSweep] = await Promise.all([
|
|
82552
|
+
const [results, sweepResult, reapResult, expiredResult, blobCleanup, connectedDataArtifactCleanup, connectedAccountBilling, directoryWorkflowDispatch, directoryWorkflowReconciliation, directoryArtifactCleanup, siteExtractArtifactCleanup, siteExtractRedispatch, siteExtractReconciliation, paaHarvestRedispatch, paaHarvestReconciliation, commonsEmbeddingDrain, localSourcebookRedispatch, analyticsRollup, analyticsFormDelivery, workflowDispatchResult, scheduledRunReconciliation, retentionSweep] = await Promise.all([
|
|
82240
82553
|
settleWithinTickBudget("drainQueue", unfinished, drainQueue2(budget), []),
|
|
82241
82554
|
settleWithinTickBudget("monthlyRefreshSweep", unfinished, runMonthlyRefreshSweep(), { status: "skipped_deadline" }),
|
|
82242
82555
|
settleWithinTickBudget("reapBrowserSessions", unfinished, reapIdleBrowserSessions(120), { reaped: 0 }),
|
|
@@ -82253,6 +82566,7 @@ var init_server = __esm({
|
|
|
82253
82566
|
settleWithinTickBudget("siteExtractReconcile", unfinished, reconcileSiteExtractSettlements(10), { checked: 0, settled: 0, failed: 0 }),
|
|
82254
82567
|
settleWithinTickBudget("paaRedispatch", unfinished, redispatchPendingPaaHarvests(10), { checked: 0, dispatched: 0, failed: 0 }),
|
|
82255
82568
|
settleWithinTickBudget("paaReconcile", unfinished, reconcilePaaHarvestSettlements(10), { checked: 0, staleFailed: 0, settled: 0, failed: 0 }),
|
|
82569
|
+
settleWithinTickBudget("commonsEmbeddingDrain", unfinished, embedQueuedCommonsDocuments(50), { claimed: 0, embedded: 0, failed: 0, remaining: 0 }),
|
|
82256
82570
|
settleWithinTickBudget("localSourcebookRedispatch", unfinished, redispatchQueuedLocalSourcebookAcquisitions(5), { checked: 0, dispatched: 0, failed: 0 }),
|
|
82257
82571
|
settleWithinTickBudget("analyticsRollup", unfinished, refreshAnalyticsDailyRollupsIfDue(), { status: "failed", rows: 0 }),
|
|
82258
82572
|
settleWithinTickBudget("analyticsForms", unfinished, deliverPendingAnalyticsForms(10), { claimed: 0, delivered: 0, deferred: 0 }),
|
|
@@ -82283,6 +82597,7 @@ var init_server = __esm({
|
|
|
82283
82597
|
siteExtractReconciliation,
|
|
82284
82598
|
paaHarvestRedispatch,
|
|
82285
82599
|
paaHarvestReconciliation,
|
|
82600
|
+
commonsEmbeddingDrain,
|
|
82286
82601
|
localSourcebookRedispatch,
|
|
82287
82602
|
analyticsRollup,
|
|
82288
82603
|
analyticsFormDelivery,
|