mcp-scraper 0.57.3 → 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 +29 -0
- package/README.md +2 -2
- package/dist/bin/api-server.cjs +549 -107
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- 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 +2 -2
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +36 -8
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +4 -4
- package/dist/{chunk-R6CO77BN.js → chunk-2U2ZDDSI.js} +3 -3
- package/dist/{chunk-R6CO77BN.js.map → chunk-2U2ZDDSI.js.map} +1 -1
- package/dist/{chunk-QSUSTYB3.js → chunk-AIA3MFT2.js} +38 -9
- 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/{chunk-HU4R6BP2.js → chunk-IMBMDZUO.js} +2 -2
- package/dist/{chunk-HU4R6BP2.js.map → chunk-IMBMDZUO.js.map} +1 -1
- package/dist/{chunk-5XYBKE3X.js → chunk-KMGRM4FL.js} +2 -2
- package/dist/editorial-reading-room/assets/app.js +17 -3
- package/dist/{extract-bundle-H7JEELY7.js → extract-bundle-XRRN6NAZ.js} +3 -3
- package/dist/{server-EP2SK2ID.js → server-IRKNU6LO.js} +505 -105
- package/dist/server-IRKNU6LO.js.map +1 -0
- package/dist/{site-extract-repository-CFMSWAVL.js → site-extract-repository-XAA2FVDN.js} +3 -3
- package/dist/{worker-S2WXELUC.js → worker-QFSOMF2N.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-LHH3GX3W.js +0 -7
- package/dist/chunk-LHH3GX3W.js.map +0 -1
- package/dist/chunk-QSUSTYB3.js.map +0 -1
- package/dist/server-EP2SK2ID.js.map +0 -1
- /package/dist/{chunk-5XYBKE3X.js.map → chunk-KMGRM4FL.js.map} +0 -0
- /package/dist/{extract-bundle-H7JEELY7.js.map → extract-bundle-XRRN6NAZ.js.map} +0 -0
- /package/dist/{site-extract-repository-CFMSWAVL.js.map → site-extract-repository-XAA2FVDN.js.map} +0 -0
- /package/dist/{worker-S2WXELUC.js.map → worker-QFSOMF2N.js.map} +0 -0
package/dist/bin/api-server.cjs
CHANGED
|
@@ -12455,8 +12455,8 @@ var init_product_contract_generated = __esm({
|
|
|
12455
12455
|
"freeSignupCredits": 0
|
|
12456
12456
|
},
|
|
12457
12457
|
"inventory": {
|
|
12458
|
-
"totalTools":
|
|
12459
|
-
"scraperTools":
|
|
12458
|
+
"totalTools": 252,
|
|
12459
|
+
"scraperTools": 151,
|
|
12460
12460
|
"memoryTools": 101
|
|
12461
12461
|
},
|
|
12462
12462
|
"concurrencyPack": {
|
|
@@ -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
|
|
|
@@ -46479,7 +46479,7 @@ var init_contracts = __esm({
|
|
|
46479
46479
|
});
|
|
46480
46480
|
|
|
46481
46481
|
// src/mcp/mcp-tool-schemas.ts
|
|
46482
|
-
var import_zod43, WEBSITE_URL_OR_DOMAIN_ERROR, WebsiteUrlOrDomainSchema, HarvestPaaInputSchema, ExtractUrlBaseInputSchema, ExtractUrlInputSchema, ExtractUrlLocalInputSchema, DiffPageBaseInputSchema, DiffPageInputSchema, DiffPageLocalInputSchema, MapSiteUrlsInputSchema, MapWaybackSnapshotsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, CheckSiteExportInputSchema, ArchiveReadInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, RedditTrendingInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, LocationMarketsInputSchema, CommonsSearchEntitiesInputSchema, CommonsGetEntityInputSchema, CommonsGetEntityLinksetInputSchema, CommonsFeaturedImageInputSchema, CommonsMediaInputSchema, CommonsCitationInputSchema, CommonsSourceInputSchema, CommonsRelatedLinkInputSchema, CommonsClaimInputSchema, CommonsPrepareEntityInputSchema, CommonsSubmitEntityInputSchema, CommonsValidateEntityInputSchema, CommonsGetEntityLedgerInputSchema, CommonsHostImageInputSchema, CommonsGetProposalInputSchema, CommonsSaveFilterInputSchema, CommonsListFiltersInputSchema, CommonsListNeedsLinksInputSchema, CommonsGenericOutputSchema, DirectoryWorkflowStatusInputSchema, LocalSourcebookSubmitInputSchema, LocalSourcebookCategorySchema, LocalSourcebookSchemaTypeInputSchema, LocalSourcebookTagCandidateObjectSchema, LocalSourcebookTagDecisionObjectSchema, LocalSourcebookIdentityObjectSchema, GetLocalSourcebookContractInputSchema, ListLocalSourcebookTagsInputSchema, ResolveLocalSourcebookTagsInputSchema, PrepareLocalSourcebookWriteInputSchema, ValidateLocalSourcebookWriteInputSchema, LocalSourcebookCaptureInputSchema, LocalSourcebookSubmissionStatusInputSchema, LocalSourcebookRefreshInputSchema, LocalSourcebookOutputSchema, ArtifactPointerOutputSchema, EditorialReadingRoomSiteSchema, EditorialReadingRoomImageSchema, EditorialReadingRoomArticleSchema, EditorialReadingRoomGuideInputSchema, EditorialReadingRoomGuideOutputSchema, CreateEditorialReadingRoomInputSchema, EditorialReadingRoomArtifactSchema, CreateEditorialReadingRoomOutputSchema, RenewEditorialReadingRoomDownloadInputSchema, RenewEditorialReadingRoomDownloadOutputSchema, CommonsPublicationSubdomainSchema, CommonsPreparePublicationInputSchema, CommonsValidatePublicationInputSchema, CommonsClaimPublicationInputSchema, CommonsPublishEditorialInputSchema, CommonsGetPublicationInputSchema, RankTrackerModeSchema, RankTrackerBlueprintInputSchema, NullableString, MapsSearchAttemptOutput, MapsSearchOutputSchema, DirectoryMapsBusinessOutput, DirectoryCsvArtifactOutput, DirectoryWorkflowOutputSchema, LocationDatasetProvenanceOutput, LocationMarketsOutputSchema, RankTrackerToolPlanOutput, RankTrackerTableOutput, RankTrackerCronJobOutput, RankTrackerBlueprintOutputSchema, OrganicResultOutput, AiOverviewOutput, EntityIdsOutput, HarvestPaaOutputSchema, SearchSerpOutputSchema, PageMediaAssetOutput, PageMediaArtifactOutput, ExtractUrlOutputSchema, DiffPageOutputSchema, ExtractSiteOutputSchema, AuditSiteOutputSchema, CheckSiteExportOutputSchema, ArchiveEntryOutputSchema, ArchiveReadOutputSchema, MapsPlaceIntelOutputSchema, TrustpilotReviewsOutputSchema, G2ReviewsOutputSchema, CreditsInfoOutputSchema, MapSiteUrlsOutputSchema, WaybackCaptureOutputSchema, MapWaybackSnapshotsOutputSchema, YoutubeHarvestOutputSchema, FacebookAdSearchOutputSchema, VideoFrameAnalysisOutputSchema, VideoFrameAnalysisStatusOutputSchema, RedditThreadOutputSchema, RedditTrendingOutputSchema, FacebookPageIntelOutputSchema, GoogleAdsSearchOutputSchema, GoogleAdsPageIntelOutputSchema, TranscriptSignalOutput, FacebookVideoTranscribeOutputSchema, TranscriptChunkOutput, InstagramBrowserOutput, InstagramPaginationOutput, InstagramProfileContentOutputSchema, InstagramMediaTrackOutput, InstagramDownloadOutput, InstagramMediaDownloadOutputSchema, YoutubeTranscribeOutputSchema, FacebookAdTranscribeOutputSchema, GoogleAdsTranscribeOutputSchema, CaptureSerpSnapshotOutputSchema, CaptureSerpPageSnapshotsOutputSchema, CreditsInfoInputSchema, WorkflowIdSchema2, WorkflowListInputSchema, WorkflowSuggestInputSchema, WorkflowRunInputSchema, WorkflowStepInputSchema, WorkflowStatusInputSchema, WorkflowArtifactReadInputSchema, WorkflowRecipeOutput, WorkflowDefinitionOutput, WorkflowArtifactOutput, WorkflowListOutputSchema, WorkflowSuggestOutputSchema, WorkflowRunOutputSchema, WorkflowStepOutputSchema, WorkflowStatusOutputSchema, WorkflowArtifactReadOutputSchema, SearchSerpInputSchema, CaptureSerpSnapshotInputSchema, ScreenshotInputSchema, CaptureSerpPageSnapshotsInputSchema, ReportArtifactReadInputSchema, ReportArtifactReadOutputSchema, ListServiceConnectionsInputSchema, ListServiceConnectionsOutputSchema, TestServiceConnectionInputSchema, TestServiceConnectionOutputSchema, ReadServiceConnectionInputSchema, ReadServiceConnectionOutputSchema, MetaAdCreativeMediaInputSchema, MetaAdCreativeMediaOutputSchema, ImportServiceConnectionToMemoryInputSchema, ImportServiceConnectionToMemoryOutputSchema, DescribeServiceConnectionToolInputSchema, DescribeServiceConnectionToolOutputSchema, ConnectedDataContinuationSchema, ExportConnectedServiceDataInputSchema, ConnectedDataArtifactSchema, ExportConnectedServiceDataOutputSchema, SearchConsoleTableColumnSchema, SearchConsoleTableFilterSchema, ExportSearchConsoleTableDataInputSchema, ExportSearchConsoleTableDataOutputSchema, RenewConnectedDataExportDownloadInputSchema, RenewConnectedDataExportDownloadOutputSchema, CallServiceConnectionActionInputSchema, CallServiceConnectionActionOutputSchema, SetScheduledActionConnectionsInputSchema, SetScheduledActionConnectionsOutputSchema, SlackSendMessageInputSchema, SlackSendMessageOutputSchema, GmailSendMessageInputSchema, GmailSendMessageOutputSchema, GmailSearchContactsInputSchema, GmailSearchContactsOutputSchema, GoogleCalendarCreateEventInputSchema, GoogleCalendarCreateEventOutputSchema, ZoomCreateMeetingInputSchema, ZoomCreateMeetingOutputSchema;
|
|
46482
|
+
var import_zod43, WEBSITE_URL_OR_DOMAIN_ERROR, WebsiteUrlOrDomainSchema, HarvestPaaInputSchema, ExtractUrlBaseInputSchema, ExtractUrlInputSchema, ExtractUrlLocalInputSchema, DiffPageBaseInputSchema, DiffPageInputSchema, DiffPageLocalInputSchema, MapSiteUrlsInputSchema, MapWaybackSnapshotsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, CheckSiteExportInputSchema, ArchiveReadInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, RedditTrendingInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, LocationMarketsInputSchema, CommonsSearchEntitiesInputSchema, CommonsGetEntityInputSchema, CommonsGetEntityLinksetInputSchema, CommonsFeaturedImageInputSchema, CommonsMediaInputSchema, CommonsCitationInputSchema, CommonsSourceInputSchema, CommonsRelatedLinkInputSchema, CommonsClaimInputSchema, CommonsPrepareEntityInputSchema, CommonsSubmitEntityInputSchema, CommonsValidateEntityInputSchema, CommonsGetEntityLedgerInputSchema, CommonsHostImageInputSchema, CommonsGetProposalInputSchema, CommonsSaveFilterInputSchema, CommonsListFiltersInputSchema, CommonsListNeedsLinksInputSchema, CommonsGenericOutputSchema, DirectoryWorkflowStatusInputSchema, LocalSourcebookSubmitInputSchema, LocalSourcebookCategorySchema, LocalSourcebookSchemaTypeInputSchema, LocalSourcebookTagCandidateObjectSchema, LocalSourcebookTagDecisionObjectSchema, LocalSourcebookIdentityObjectSchema, GetLocalSourcebookContractInputSchema, ListLocalSourcebookTagsInputSchema, ResolveLocalSourcebookTagsInputSchema, PrepareLocalSourcebookWriteInputSchema, ValidateLocalSourcebookWriteInputSchema, LocalSourcebookCaptureInputSchema, LocalSourcebookSubmissionStatusInputSchema, LocalSourcebookRefreshInputSchema, LocalSourcebookOutputSchema, ArtifactPointerOutputSchema, EditorialReadingRoomSiteSchema, EditorialReadingRoomImageSchema, EditorialReadingRoomArticleSchema, EditorialReadingRoomGuideInputSchema, EditorialReadingRoomGuideOutputSchema, CreateEditorialReadingRoomInputSchema, EditorialReadingRoomArtifactSchema, CreateEditorialReadingRoomOutputSchema, RenewEditorialReadingRoomDownloadInputSchema, RenewEditorialReadingRoomDownloadOutputSchema, CommonsPublicationSubdomainSchema, CommonsPreparePublicationInputSchema, CommonsValidatePublicationInputSchema, CommonsClaimPublicationInputSchema, CommonsPublishEditorialInputSchema, CommonsUpdateEditorialArticleInputSchema, CommonsGetPublicationInputSchema, RankTrackerModeSchema, RankTrackerBlueprintInputSchema, NullableString, MapsSearchAttemptOutput, MapsSearchOutputSchema, DirectoryMapsBusinessOutput, DirectoryCsvArtifactOutput, DirectoryWorkflowOutputSchema, LocationDatasetProvenanceOutput, LocationMarketsOutputSchema, RankTrackerToolPlanOutput, RankTrackerTableOutput, RankTrackerCronJobOutput, RankTrackerBlueprintOutputSchema, OrganicResultOutput, AiOverviewOutput, EntityIdsOutput, HarvestPaaOutputSchema, SearchSerpOutputSchema, PageMediaAssetOutput, PageMediaArtifactOutput, ExtractUrlOutputSchema, DiffPageOutputSchema, ExtractSiteOutputSchema, AuditSiteOutputSchema, CheckSiteExportOutputSchema, ArchiveEntryOutputSchema, ArchiveReadOutputSchema, MapsPlaceIntelOutputSchema, TrustpilotReviewsOutputSchema, G2ReviewsOutputSchema, CreditsInfoOutputSchema, MapSiteUrlsOutputSchema, WaybackCaptureOutputSchema, MapWaybackSnapshotsOutputSchema, YoutubeHarvestOutputSchema, FacebookAdSearchOutputSchema, VideoFrameAnalysisOutputSchema, VideoFrameAnalysisStatusOutputSchema, RedditThreadOutputSchema, RedditTrendingOutputSchema, FacebookPageIntelOutputSchema, GoogleAdsSearchOutputSchema, GoogleAdsPageIntelOutputSchema, TranscriptSignalOutput, FacebookVideoTranscribeOutputSchema, TranscriptChunkOutput, InstagramBrowserOutput, InstagramPaginationOutput, InstagramProfileContentOutputSchema, InstagramMediaTrackOutput, InstagramDownloadOutput, InstagramMediaDownloadOutputSchema, YoutubeTranscribeOutputSchema, FacebookAdTranscribeOutputSchema, GoogleAdsTranscribeOutputSchema, CaptureSerpSnapshotOutputSchema, CaptureSerpPageSnapshotsOutputSchema, CreditsInfoInputSchema, WorkflowIdSchema2, WorkflowListInputSchema, WorkflowSuggestInputSchema, WorkflowRunInputSchema, WorkflowStepInputSchema, WorkflowStatusInputSchema, WorkflowArtifactReadInputSchema, WorkflowRecipeOutput, WorkflowDefinitionOutput, WorkflowArtifactOutput, WorkflowListOutputSchema, WorkflowSuggestOutputSchema, WorkflowRunOutputSchema, WorkflowStepOutputSchema, WorkflowStatusOutputSchema, WorkflowArtifactReadOutputSchema, SearchSerpInputSchema, CaptureSerpSnapshotInputSchema, ScreenshotInputSchema, CaptureSerpPageSnapshotsInputSchema, ReportArtifactReadInputSchema, ReportArtifactReadOutputSchema, ListServiceConnectionsInputSchema, ListServiceConnectionsOutputSchema, TestServiceConnectionInputSchema, TestServiceConnectionOutputSchema, ReadServiceConnectionInputSchema, ReadServiceConnectionOutputSchema, MetaAdCreativeMediaInputSchema, MetaAdCreativeMediaOutputSchema, ImportServiceConnectionToMemoryInputSchema, ImportServiceConnectionToMemoryOutputSchema, DescribeServiceConnectionToolInputSchema, DescribeServiceConnectionToolOutputSchema, ConnectedDataContinuationSchema, ExportConnectedServiceDataInputSchema, ConnectedDataArtifactSchema, ExportConnectedServiceDataOutputSchema, SearchConsoleTableColumnSchema, SearchConsoleTableFilterSchema, ExportSearchConsoleTableDataInputSchema, ExportSearchConsoleTableDataOutputSchema, RenewConnectedDataExportDownloadInputSchema, RenewConnectedDataExportDownloadOutputSchema, CallServiceConnectionActionInputSchema, CallServiceConnectionActionOutputSchema, SetScheduledActionConnectionsInputSchema, SetScheduledActionConnectionsOutputSchema, SlackSendMessageInputSchema, SlackSendMessageOutputSchema, GmailSendMessageInputSchema, GmailSendMessageOutputSchema, GmailSearchContactsInputSchema, GmailSearchContactsOutputSchema, GoogleCalendarCreateEventInputSchema, GoogleCalendarCreateEventOutputSchema, ZoomCreateMeetingInputSchema, ZoomCreateMeetingOutputSchema;
|
|
46483
46483
|
var init_mcp_tool_schemas = __esm({
|
|
46484
46484
|
"src/mcp/mcp-tool-schemas.ts"() {
|
|
46485
46485
|
"use strict";
|
|
@@ -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."),
|
|
@@ -47190,7 +47191,21 @@ var init_mcp_tool_schemas = __esm({
|
|
|
47190
47191
|
baseRevision: import_zod43.z.number().int().positive().optional().describe("Required when revising an existing edition; use the current revision from commons_get_publication."),
|
|
47191
47192
|
...CreateEditorialReadingRoomInputSchema
|
|
47192
47193
|
};
|
|
47194
|
+
CommonsUpdateEditorialArticleInputSchema = {
|
|
47195
|
+
publicationSubdomain: CommonsPublicationSubdomainSchema.describe("Publication owned by the authenticated account."),
|
|
47196
|
+
editionSlug: import_zod43.z.string().trim().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(80).optional().describe("Edition holding the article. Defaults to the publication\u2019s latest edition."),
|
|
47197
|
+
articleSlug: import_zod43.z.string().trim().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(80).describe("Slug of the one article to replace, from commons_get_publication with includeArticles."),
|
|
47198
|
+
idempotencyKey: import_zod43.z.string().trim().min(8).max(200).describe("Unique key for this intended edit. Reuse it only when retrying the same edit."),
|
|
47199
|
+
baseRevision: import_zod43.z.number().int().positive().describe("Current edition revision from commons_get_publication. The edit is refused if the edition moved on."),
|
|
47200
|
+
markdown: import_zod43.z.string().trim().min(1).max(4e5).optional().describe("Replacement Markdown body for this article. Omit to change only the metadata fields below."),
|
|
47201
|
+
title: import_zod43.z.string().trim().min(1).max(180).optional().describe("Replacement article title."),
|
|
47202
|
+
summary: import_zod43.z.string().trim().min(1).max(500).optional().describe("Replacement one or two sentence summary."),
|
|
47203
|
+
category: import_zod43.z.string().trim().min(1).max(80).optional().describe("Replacement section label."),
|
|
47204
|
+
kicker: import_zod43.z.string().trim().min(1).max(140).optional().describe("Replacement framing line above the title."),
|
|
47205
|
+
order: import_zod43.z.number().int().min(1).max(1e3).optional().describe("Replacement reading-order position.")
|
|
47206
|
+
};
|
|
47193
47207
|
CommonsGetPublicationInputSchema = {
|
|
47208
|
+
includeArticles: import_zod43.z.boolean().optional().describe("Return every stored article\u2019s Markdown source alongside each edition. Large payload; request it only when you intend to edit an article. Owner-only: a publication read by name never returns sources."),
|
|
47194
47209
|
subdomain: CommonsPublicationSubdomainSchema.optional().describe("Public publication name to inspect. Omit to return the publication owned by the authenticated account."),
|
|
47195
47210
|
includeEditions: import_zod43.z.boolean().default(true).describe("Include the latest revision of every published edition.")
|
|
47196
47211
|
};
|
|
@@ -50408,7 +50423,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50408
50423
|
}, async (input) => formatG2Reviews(await executor.g2Reviews(input), input));
|
|
50409
50424
|
server.registerTool("commons_search_entities", {
|
|
50410
50425
|
title: "Transparent Commons Entity Search",
|
|
50411
|
-
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.",
|
|
50412
50427
|
inputSchema: CommonsSearchEntitiesInputSchema,
|
|
50413
50428
|
outputSchema: recordOutputSchema("commons_search_entities", CommonsGenericOutputSchema),
|
|
50414
50429
|
annotations: {
|
|
@@ -50486,7 +50501,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50486
50501
|
}, async (input) => executor.commonsValidateEntity(input));
|
|
50487
50502
|
server.registerTool("commons_submit_entity", {
|
|
50488
50503
|
title: "Transparent Commons Governed Entity Write",
|
|
50489
|
-
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.",
|
|
50490
50505
|
inputSchema: CommonsSubmitEntityInputSchema,
|
|
50491
50506
|
outputSchema: recordOutputSchema("commons_submit_entity", CommonsGenericOutputSchema),
|
|
50492
50507
|
annotations: {
|
|
@@ -50512,7 +50527,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50512
50527
|
}, async (input) => executor.commonsGetEntityLedger(input));
|
|
50513
50528
|
server.registerTool("commons_host_image", {
|
|
50514
50529
|
title: "Host a Transparent Commons Image",
|
|
50515
|
-
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.",
|
|
50516
50531
|
inputSchema: CommonsHostImageInputSchema,
|
|
50517
50532
|
outputSchema: recordOutputSchema("commons_host_image", CommonsGenericOutputSchema),
|
|
50518
50533
|
annotations: {
|
|
@@ -50590,9 +50605,16 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50590
50605
|
outputSchema: recordOutputSchema("commons_publish_editorial", CommonsGenericOutputSchema),
|
|
50591
50606
|
annotations: { title: "Publish Transparent Commons Editorial Edition", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
50592
50607
|
}, async (input) => executor.commonsPublishEditorial(input));
|
|
50608
|
+
server.registerTool("commons_update_editorial_article", {
|
|
50609
|
+
title: "Edit One Transparent Commons Article",
|
|
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.",
|
|
50611
|
+
inputSchema: CommonsUpdateEditorialArticleInputSchema,
|
|
50612
|
+
outputSchema: recordOutputSchema("commons_update_editorial_article", CommonsGenericOutputSchema),
|
|
50613
|
+
annotations: { title: "Edit One Transparent Commons Article", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
50614
|
+
}, async (input) => executor.commonsUpdateEditorialArticle(input));
|
|
50593
50615
|
server.registerTool("commons_get_publication", {
|
|
50594
50616
|
title: "Get Transparent Commons Publication",
|
|
50595
|
-
description: "Read a Transparent Commons publication and its latest edition revisions. Omit subdomain to inspect the caller-owned publication; pass a name to inspect a public publication. Returns the permanent public and archive URLs needed for sharing or later edits.",
|
|
50617
|
+
description: "Read a Transparent Commons publication and its latest edition revisions. Omit subdomain to inspect the caller-owned publication; pass a name to inspect a public publication. Returns the permanent public and archive URLs needed for sharing or later edits. Set includeArticles to also return every stored article\u2019s Markdown source and slug, which is what commons_update_editorial_article edits \u2014 the payload is large, so request it only when you intend to edit.",
|
|
50596
50618
|
inputSchema: CommonsGetPublicationInputSchema,
|
|
50597
50619
|
outputSchema: recordOutputSchema("commons_get_publication", CommonsGenericOutputSchema),
|
|
50598
50620
|
annotations: { title: "Get Transparent Commons Publication", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
@@ -50659,7 +50681,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50659
50681
|
}, async (input) => executor.localSourcebookCapture(input));
|
|
50660
50682
|
server.registerTool("local_sourcebook_submission_status", {
|
|
50661
50683
|
title: "Local Sourcebook Submission Status",
|
|
50662
|
-
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.",
|
|
50663
50685
|
inputSchema: LocalSourcebookSubmissionStatusInputSchema,
|
|
50664
50686
|
outputSchema: recordOutputSchema("local_sourcebook_submission_status", LocalSourcebookOutputSchema),
|
|
50665
50687
|
annotations: localPlanningToolAnnotations("Local Sourcebook Submission Status")
|
|
@@ -51589,6 +51611,12 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
51589
51611
|
commonsHostImage(input) {
|
|
51590
51612
|
return this.call("/commons/images", input);
|
|
51591
51613
|
}
|
|
51614
|
+
commonsUpdateEditorialArticle(input) {
|
|
51615
|
+
const { idempotencyKey: idempotencyKey3, ...body } = input;
|
|
51616
|
+
return this.call("/commons/publications/articles", { ...body, idempotencyKey: idempotencyKey3 }, this.timeoutMs, "POST", {
|
|
51617
|
+
"Idempotency-Key": `commons-article-${(0, import_node_crypto28.createHash)("sha256").update(idempotencyKey3).digest("hex")}`
|
|
51618
|
+
});
|
|
51619
|
+
}
|
|
51592
51620
|
commonsSaveFilter(input) {
|
|
51593
51621
|
return this.call("/commons/filters", input);
|
|
51594
51622
|
}
|
|
@@ -51617,7 +51645,7 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
51617
51645
|
});
|
|
51618
51646
|
}
|
|
51619
51647
|
commonsGetPublication(input) {
|
|
51620
|
-
const query = new URLSearchParams({ includeEditions: String(input.includeEditions ?? true) });
|
|
51648
|
+
const query = new URLSearchParams({ includeEditions: String(input.includeEditions ?? true), includeArticles: String(input.includeArticles ?? false) });
|
|
51621
51649
|
return this.getJson(input.subdomain ? `/commons/publications/${encodeURIComponent(input.subdomain)}?${query}` : `/commons/publications/me?${query}`);
|
|
51622
51650
|
}
|
|
51623
51651
|
async captureSerpSnapshot(input) {
|
|
@@ -64052,9 +64080,7 @@ function socialMeta(input) {
|
|
|
64052
64080
|
];
|
|
64053
64081
|
return tags.join("\n ");
|
|
64054
64082
|
}
|
|
64055
|
-
function
|
|
64056
|
-
const sourceBytes = input.articles.reduce((total, article) => total + Buffer.byteLength(article.markdown), 0);
|
|
64057
|
-
if (sourceBytes > 2e6) throw new Error("Editorial reading-room Markdown must be 2,000,000 bytes or fewer in total.");
|
|
64083
|
+
function buildEditorialArticles(input) {
|
|
64058
64084
|
const seenSlugs = /* @__PURE__ */ new Set();
|
|
64059
64085
|
const seenOrders = /* @__PURE__ */ new Set();
|
|
64060
64086
|
const parser = markdownRenderer();
|
|
@@ -64081,7 +64107,19 @@ function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
|
|
|
64081
64107
|
html: rendered
|
|
64082
64108
|
};
|
|
64083
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.");
|
|
64084
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;
|
|
64085
64123
|
const data = { ...input, generatedAt, articles };
|
|
64086
64124
|
const template = readAsset("index.html");
|
|
64087
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"));
|
|
@@ -64562,6 +64600,141 @@ var init_commons_image_store = __esm({
|
|
|
64562
64600
|
}
|
|
64563
64601
|
});
|
|
64564
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
|
+
|
|
64565
64738
|
// src/api/schema-presence.ts
|
|
64566
64739
|
async function loadSchemaObjects() {
|
|
64567
64740
|
const res = await getDb().execute(
|
|
@@ -65055,17 +65228,35 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
65055
65228
|
args.push(mergedFilters.updatedAfter);
|
|
65056
65229
|
}
|
|
65057
65230
|
const terms = tokenize(mergedFilters.query);
|
|
65058
|
-
|
|
65059
|
-
|
|
65060
|
-
|
|
65061
|
-
|
|
65062
|
-
|
|
65063
|
-
|
|
65064
|
-
|
|
65065
|
-
|
|
65066
|
-
|
|
65067
|
-
|
|
65068
|
-
|
|
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
|
+
}
|
|
65069
65260
|
}
|
|
65070
65261
|
if (!terms.length) {
|
|
65071
65262
|
args.push(limit, offset);
|
|
@@ -65102,6 +65293,7 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
65102
65293
|
`,
|
|
65103
65294
|
args
|
|
65104
65295
|
});
|
|
65296
|
+
const mode = searchMode;
|
|
65105
65297
|
const ranked = candidates.rows.map((row) => {
|
|
65106
65298
|
const record = row;
|
|
65107
65299
|
const score = relevanceScore(terms, {
|
|
@@ -65112,8 +65304,10 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
65112
65304
|
searchText: String(record.search_text ?? ""),
|
|
65113
65305
|
claimText: String(record.claim_text ?? "")
|
|
65114
65306
|
});
|
|
65115
|
-
|
|
65116
|
-
|
|
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));
|
|
65117
65311
|
const pageIds = ranked.slice(offset, offset + limit).map((candidate) => candidate.id);
|
|
65118
65312
|
if (!pageIds.length) return { results: [], filters: mergedFilters, limit, offset };
|
|
65119
65313
|
const page = await getDb().execute({
|
|
@@ -66599,6 +66793,7 @@ function normalizeRelatedEntities(related) {
|
|
|
66599
66793
|
}
|
|
66600
66794
|
function sanitizeSearchFilters(filters) {
|
|
66601
66795
|
return {
|
|
66796
|
+
mode: filters.mode === "lexical" || filters.mode === "semantic" ? filters.mode : "hybrid",
|
|
66602
66797
|
query: optionalText2(filters.query, 300) ?? void 0,
|
|
66603
66798
|
entityType: filters.entityType ? normalizeEntityType(filters.entityType) : void 0,
|
|
66604
66799
|
tag: optionalText2(filters.tag, 80) ?? void 0,
|
|
@@ -66866,6 +67061,7 @@ var init_commons_repository = __esm({
|
|
|
66866
67061
|
import_node_crypto39 = require("crypto");
|
|
66867
67062
|
init_db();
|
|
66868
67063
|
init_commons_image_store();
|
|
67064
|
+
init_commons_embeddings();
|
|
66869
67065
|
init_schema_presence();
|
|
66870
67066
|
init_rates();
|
|
66871
67067
|
init_commons_linksets();
|
|
@@ -67057,6 +67253,101 @@ var init_commons_repository = __esm({
|
|
|
67057
67253
|
}
|
|
67058
67254
|
});
|
|
67059
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
|
+
|
|
67060
67351
|
// src/api/commons-publication-repository.ts
|
|
67061
67352
|
async function prepareCommonsPublication(input, user) {
|
|
67062
67353
|
await ensureCommonsSchema();
|
|
@@ -67241,6 +67532,92 @@ async function publishCommonsEditorial(input, user) {
|
|
|
67241
67532
|
if (!edition) throw new CommonsPublicationError("publication_publish_failed", "The published edition was not persisted.");
|
|
67242
67533
|
return publicationResult({ ...publication, latestEditionId: editionId, updatedAt: now }, edition, false);
|
|
67243
67534
|
}
|
|
67535
|
+
async function updateCommonsEditorialArticle(input, user) {
|
|
67536
|
+
await ensureCommonsSchema();
|
|
67537
|
+
const subdomain = normalizePublicationSubdomain(input.publicationSubdomain);
|
|
67538
|
+
const publication = await getCommonsPublicationBySubdomain(subdomain);
|
|
67539
|
+
if (!publication) throw new CommonsPublicationError("publication_not_found", "Claim this publication name before editing an edition.", 404);
|
|
67540
|
+
if (publication.ownerUserId !== Number(user.id)) {
|
|
67541
|
+
throw new CommonsPublicationError("publication_not_owned", "Only the account that claimed this publication can edit it.", 404);
|
|
67542
|
+
}
|
|
67543
|
+
const idempotencyKey3 = requiredIdempotencyKey(input.idempotencyKey);
|
|
67544
|
+
const replay = await getEditionByIdempotency(Number(user.id), idempotencyKey3);
|
|
67545
|
+
if (replay) return publicationResult(publication, replay, true);
|
|
67546
|
+
const latestOverall = publication.latestEditionId ? await getPublicationEditionById(publication.latestEditionId) : null;
|
|
67547
|
+
const editionSlug = normalizeEditionSlug(input.editionSlug || latestOverall?.editionSlug || "");
|
|
67548
|
+
if (!editionSlug) throw new CommonsPublicationError("publication_edition_required", "This publication has no edition yet; publish one before editing an article.", 409);
|
|
67549
|
+
const latest = await getLatestEdition(publication.id, editionSlug);
|
|
67550
|
+
if (!latest) throw new CommonsPublicationError("publication_edition_not_found", `Edition ${editionSlug} does not exist.`, 404);
|
|
67551
|
+
if (input.baseRevision !== latest.revision) {
|
|
67552
|
+
throw new CommonsPublicationError("publication_revision_conflict", `Edition ${editionSlug} is revision ${latest.revision}; read it again before editing.`, 409);
|
|
67553
|
+
}
|
|
67554
|
+
const articles = latest.articles;
|
|
67555
|
+
const index = articles.findIndex((article) => article.slug === input.articleSlug);
|
|
67556
|
+
if (index === -1) {
|
|
67557
|
+
throw new CommonsPublicationError("publication_article_not_found", `Edition ${editionSlug} has no article with slug ${input.articleSlug}. Known slugs: ${articles.map((article) => article.slug).join(", ")}.`, 404);
|
|
67558
|
+
}
|
|
67559
|
+
const current = articles[index];
|
|
67560
|
+
const nextArticles = [...articles];
|
|
67561
|
+
nextArticles[index] = {
|
|
67562
|
+
...current,
|
|
67563
|
+
...input.markdown === void 0 ? {} : { markdown: input.markdown },
|
|
67564
|
+
...input.title === void 0 ? {} : { title: input.title },
|
|
67565
|
+
...input.summary === void 0 ? {} : { summary: input.summary },
|
|
67566
|
+
...input.category === void 0 ? {} : { category: input.category },
|
|
67567
|
+
...input.kicker === void 0 ? {} : { kicker: input.kicker },
|
|
67568
|
+
...input.order === void 0 ? {} : { order: input.order }
|
|
67569
|
+
};
|
|
67570
|
+
const editionInput = { site: latest.site, deck: latest.deck, articles: nextArticles };
|
|
67571
|
+
const canonicalUrl = editionPublicUrl(subdomain, editionSlug);
|
|
67572
|
+
const rendered = renderEditorialReadingRoom(editionInput);
|
|
67573
|
+
const html = addPublicMetadata(rendered.html, canonicalUrl, publication.title);
|
|
67574
|
+
const editionId = `tced_${(0, import_node_crypto40.randomUUID)()}`;
|
|
67575
|
+
const revision = latest.revision + 1;
|
|
67576
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
67577
|
+
await getDb().batch([
|
|
67578
|
+
{
|
|
67579
|
+
sql: `
|
|
67580
|
+
INSERT INTO commons_publication_editions (
|
|
67581
|
+
id, publication_id, owner_user_id, edition_slug, revision, title, site_json, deck,
|
|
67582
|
+
articles_json, html, filename, sha256, article_count, word_count, bytes, warnings_json,
|
|
67583
|
+
idempotency_key, created_at, published_at
|
|
67584
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
67585
|
+
`,
|
|
67586
|
+
args: [
|
|
67587
|
+
editionId,
|
|
67588
|
+
publication.id,
|
|
67589
|
+
Number(user.id),
|
|
67590
|
+
editionSlug,
|
|
67591
|
+
revision,
|
|
67592
|
+
latest.site.title,
|
|
67593
|
+
JSON.stringify(latest.site),
|
|
67594
|
+
latest.deck,
|
|
67595
|
+
JSON.stringify(nextArticles),
|
|
67596
|
+
html,
|
|
67597
|
+
rendered.filename,
|
|
67598
|
+
(0, import_node_crypto40.createHash)("sha256").update(html).digest("hex"),
|
|
67599
|
+
rendered.articleCount,
|
|
67600
|
+
rendered.wordCount,
|
|
67601
|
+
Buffer.byteLength(html),
|
|
67602
|
+
JSON.stringify(rendered.warnings),
|
|
67603
|
+
idempotencyKey3,
|
|
67604
|
+
now,
|
|
67605
|
+
now
|
|
67606
|
+
]
|
|
67607
|
+
},
|
|
67608
|
+
{
|
|
67609
|
+
sql: "UPDATE commons_publications SET latest_edition_id = ?, updated_at = ? WHERE id = ? AND owner_user_id = ?",
|
|
67610
|
+
args: [editionId, now, publication.id, Number(user.id)]
|
|
67611
|
+
}
|
|
67612
|
+
], "write");
|
|
67613
|
+
const edition = await getPublicationEditionById(editionId);
|
|
67614
|
+
if (!edition) throw new CommonsPublicationError("publication_publish_failed", "The edited edition was not persisted.");
|
|
67615
|
+
return {
|
|
67616
|
+
...publicationResult({ ...publication, latestEditionId: editionId, updatedAt: now }, edition, false),
|
|
67617
|
+
updatedArticle: { slug: input.articleSlug, previousRevision: latest.revision, revision },
|
|
67618
|
+
unchangedArticles: articles.length - 1
|
|
67619
|
+
};
|
|
67620
|
+
}
|
|
67244
67621
|
async function getCommonsPublicationBySubdomain(subdomainInput) {
|
|
67245
67622
|
await ensureCommonsSchema();
|
|
67246
67623
|
const subdomain = normalizePublicationSubdomain(subdomainInput);
|
|
@@ -67269,6 +67646,20 @@ async function listCommonsPublicationEditions(publicationId) {
|
|
|
67269
67646
|
if (!publication) return [];
|
|
67270
67647
|
return result.rows.map((row) => rowToEdition(row, publication.subdomain));
|
|
67271
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
|
+
}
|
|
67272
67663
|
async function getCommonsPublicationEditionHtml(subdomainInput, editionSlugInput) {
|
|
67273
67664
|
const publication = await getCommonsPublicationBySubdomain(subdomainInput);
|
|
67274
67665
|
if (!publication) return null;
|
|
@@ -67338,6 +67729,7 @@ function rowToEdition(row, subdomain) {
|
|
|
67338
67729
|
revision: Number(row.revision),
|
|
67339
67730
|
title: String(row.title),
|
|
67340
67731
|
site: parseJson4(row.site_json, {}),
|
|
67732
|
+
articles: parseJson4(row.articles_json, []),
|
|
67341
67733
|
deck: String(row.deck),
|
|
67342
67734
|
filename: String(row.filename),
|
|
67343
67735
|
sha256: String(row.sha256),
|
|
@@ -67416,6 +67808,7 @@ var init_commons_publication_repository = __esm({
|
|
|
67416
67808
|
init_db();
|
|
67417
67809
|
init_commons_repository();
|
|
67418
67810
|
init_render();
|
|
67811
|
+
init_article_page();
|
|
67419
67812
|
PUBLICATION_ROOT_DOMAIN = process.env.COMMONS_PUBLICATION_ROOT_DOMAIN || "transparent-commons.cc";
|
|
67420
67813
|
RESERVED_SUBDOMAINS = /* @__PURE__ */ new Set([
|
|
67421
67814
|
"admin",
|
|
@@ -67455,6 +67848,7 @@ var init_commons_publication_repository = __esm({
|
|
|
67455
67848
|
// src/api/commons-routes.ts
|
|
67456
67849
|
function filtersFromQuery(query) {
|
|
67457
67850
|
return {
|
|
67851
|
+
mode: query.mode === "lexical" || query.mode === "semantic" ? query.mode : void 0,
|
|
67458
67852
|
query: query.query || query.q,
|
|
67459
67853
|
entityType: query.entityType,
|
|
67460
67854
|
tag: query.tag,
|
|
@@ -67510,10 +67904,17 @@ function publicationError(c, error) {
|
|
|
67510
67904
|
}
|
|
67511
67905
|
throw error;
|
|
67512
67906
|
}
|
|
67907
|
+
function withArticleSources(editions, include) {
|
|
67908
|
+
if (include) return editions;
|
|
67909
|
+
return editions.map((edition) => {
|
|
67910
|
+
const { articles: _articles, ...rest } = edition;
|
|
67911
|
+
return rest;
|
|
67912
|
+
});
|
|
67913
|
+
}
|
|
67513
67914
|
function xmlEscape(value) {
|
|
67514
67915
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
67515
67916
|
}
|
|
67516
|
-
var import_hono31, import_zod52, commonsApp, auth2, SearchBodySchema, FeaturedImageSchema, MediaSchema, CitationSchema, RelatedLinkSchema, SubmitEntitySchema, PrepareEntitySchema, ValidateEntitySchema, SaveFilterSchema, NeedsLinkBodySchema, PreparePublicationSchema, ValidatePublicationSchema, ClaimPublicationSchema, PublishEditorialSchema, HostImageSchema;
|
|
67917
|
+
var import_hono31, import_zod52, commonsApp, auth2, SearchBodySchema, FeaturedImageSchema, MediaSchema, CitationSchema, RelatedLinkSchema, SubmitEntitySchema, PrepareEntitySchema, ValidateEntitySchema, SaveFilterSchema, NeedsLinkBodySchema, PreparePublicationSchema, ValidatePublicationSchema, ClaimPublicationSchema, PublishEditorialSchema, UpdateEditorialArticleSchema, HostImageSchema;
|
|
67517
67918
|
var init_commons_routes = __esm({
|
|
67518
67919
|
"src/api/commons-routes.ts"() {
|
|
67519
67920
|
"use strict";
|
|
@@ -67522,6 +67923,7 @@ var init_commons_routes = __esm({
|
|
|
67522
67923
|
init_api_auth();
|
|
67523
67924
|
init_commons_repository();
|
|
67524
67925
|
init_commons_image_store();
|
|
67926
|
+
init_commons_embeddings();
|
|
67525
67927
|
init_commons_linksets();
|
|
67526
67928
|
init_listing_write_billing();
|
|
67527
67929
|
init_commons_publication_repository();
|
|
@@ -67529,6 +67931,7 @@ var init_commons_routes = __esm({
|
|
|
67529
67931
|
commonsApp = new import_hono31.Hono();
|
|
67530
67932
|
auth2 = createApiKeyAuth();
|
|
67531
67933
|
SearchBodySchema = import_zod52.z.object({
|
|
67934
|
+
mode: import_zod52.z.enum(["lexical", "semantic", "hybrid"]).optional(),
|
|
67532
67935
|
query: import_zod52.z.string().max(300).optional(),
|
|
67533
67936
|
entityType: import_zod52.z.string().max(120).optional(),
|
|
67534
67937
|
tag: import_zod52.z.string().max(80).optional(),
|
|
@@ -67691,6 +68094,15 @@ var init_commons_routes = __esm({
|
|
|
67691
68094
|
ValidatePublicationSchema = import_zod52.z.object(CommonsValidatePublicationInputSchema).strict();
|
|
67692
68095
|
ClaimPublicationSchema = import_zod52.z.object(CommonsClaimPublicationInputSchema).strict();
|
|
67693
68096
|
PublishEditorialSchema = import_zod52.z.object(CommonsPublishEditorialInputSchema).strict();
|
|
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
|
+
});
|
|
67694
68106
|
commonsApp.get("/health", async (c) => {
|
|
67695
68107
|
await ensureCommonsSchema();
|
|
67696
68108
|
return c.json({ ok: true, data: commonsDatabaseReport() });
|
|
@@ -67726,11 +68138,16 @@ var init_commons_routes = __esm({
|
|
|
67726
68138
|
if (!parsed.success) return validationError(c, parsed.error);
|
|
67727
68139
|
return publicationOperation(c, () => publishCommonsEditorial(parsed.data, c.get("user")), 201);
|
|
67728
68140
|
});
|
|
68141
|
+
commonsApp.post("/publications/articles", auth2, async (c) => {
|
|
68142
|
+
const parsed = UpdateEditorialArticleSchema.safeParse(await c.req.json().catch(() => ({})));
|
|
68143
|
+
if (!parsed.success) return validationError(c, parsed.error);
|
|
68144
|
+
return publicationOperation(c, () => updateCommonsEditorialArticle(parsed.data, c.get("user")), 201);
|
|
68145
|
+
});
|
|
67729
68146
|
commonsApp.get("/publications/me", auth2, async (c) => {
|
|
67730
68147
|
const publication = await getCommonsPublicationForOwner(Number(c.get("user").id));
|
|
67731
68148
|
if (!publication) return c.json({ ok: false, error: "publication_not_found", message: "This account has not claimed a Commons publication yet." }, 404);
|
|
67732
68149
|
const editions = c.req.query("includeEditions") === "false" ? [] : await listCommonsPublicationEditions(publication.id);
|
|
67733
|
-
return c.json({ ok: true, data: { publication, editions } });
|
|
68150
|
+
return c.json({ ok: true, data: { publication, editions: withArticleSources(editions, c.req.query("includeArticles") === "true") } });
|
|
67734
68151
|
});
|
|
67735
68152
|
commonsApp.get("/publications/:subdomain/site", async (c) => {
|
|
67736
68153
|
try {
|
|
@@ -67744,6 +68161,28 @@ var init_commons_routes = __esm({
|
|
|
67744
68161
|
return publicationError(c, error);
|
|
67745
68162
|
}
|
|
67746
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
|
+
});
|
|
67747
68186
|
commonsApp.get("/publications/:subdomain/editions/:editionSlug/site", async (c) => {
|
|
67748
68187
|
try {
|
|
67749
68188
|
const result = await getCommonsPublicationEditionHtml(c.req.param("subdomain"), c.req.param("editionSlug"));
|
|
@@ -67770,7 +68209,7 @@ var init_commons_routes = __esm({
|
|
|
67770
68209
|
const publication = await getCommonsPublicationBySubdomain(c.req.param("subdomain"));
|
|
67771
68210
|
if (!publication) return c.json({ ok: false, error: "publication_not_found", message: "No Commons publication matched that name." }, 404);
|
|
67772
68211
|
const editions = c.req.query("includeEditions") === "false" ? [] : await listCommonsPublicationEditions(publication.id);
|
|
67773
|
-
return c.json({ ok: true, data: { publication, editions } });
|
|
68212
|
+
return c.json({ ok: true, data: { publication, editions: withArticleSources(editions, false) } });
|
|
67774
68213
|
} catch (error) {
|
|
67775
68214
|
return publicationError(c, error);
|
|
67776
68215
|
}
|
|
@@ -71312,7 +71751,7 @@ function pixelSnippet(publicId) {
|
|
|
71312
71751
|
function formSnippet(publicId) {
|
|
71313
71752
|
return `<div data-mcp-form="${publicId}"></div><script async src="https://mcpscraper.dev/analytics/v1/form.js?form=${publicId}"></script>`;
|
|
71314
71753
|
}
|
|
71315
|
-
function
|
|
71754
|
+
function escapeHtml8(value) {
|
|
71316
71755
|
return String(value ?? "").replace(
|
|
71317
71756
|
/[&<>"']/g,
|
|
71318
71757
|
(character) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[character]
|
|
@@ -71324,13 +71763,13 @@ function renderPublicForm(form, placementUrl) {
|
|
|
71324
71763
|
const fields = form.fields.map((field) => {
|
|
71325
71764
|
const required = field.required ? " required" : "";
|
|
71326
71765
|
const options = (field.options ?? []).map(
|
|
71327
|
-
(option) => `<option value="${
|
|
71766
|
+
(option) => `<option value="${escapeHtml8(option)}">${escapeHtml8(option)}</option>`
|
|
71328
71767
|
).join("");
|
|
71329
|
-
const control = field.type === "textarea" ? `<textarea id="${
|
|
71330
|
-
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>`;
|
|
71331
71770
|
}).join("");
|
|
71332
71771
|
const brand = form.brand;
|
|
71333
|
-
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>`;
|
|
71334
71773
|
}
|
|
71335
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;
|
|
71336
71775
|
var init_analytics_routes = __esm({
|
|
@@ -72816,7 +73255,7 @@ var init_scheduled_run_view_links = __esm({
|
|
|
72816
73255
|
});
|
|
72817
73256
|
|
|
72818
73257
|
// src/personal-authority/render.ts
|
|
72819
|
-
function
|
|
73258
|
+
function escapeHtml9(value) {
|
|
72820
73259
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
72821
73260
|
"&": "&",
|
|
72822
73261
|
"<": "<",
|
|
@@ -72827,13 +73266,13 @@ function escapeHtml8(value) {
|
|
|
72827
73266
|
}
|
|
72828
73267
|
function safeHref(value) {
|
|
72829
73268
|
const trimmed = value.trim();
|
|
72830
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73269
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml9(trimmed) : "#";
|
|
72831
73270
|
}
|
|
72832
73271
|
function initials(name) {
|
|
72833
73272
|
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("") || "PA";
|
|
72834
73273
|
}
|
|
72835
73274
|
function action(action3, secondary = false) {
|
|
72836
|
-
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>`;
|
|
72837
73276
|
}
|
|
72838
73277
|
function section(enabled, html) {
|
|
72839
73278
|
return enabled ? html : "";
|
|
@@ -72842,7 +73281,7 @@ function renderPersonalAuthorityV1(input, config, generatedAt) {
|
|
|
72842
73281
|
const flags = config.featureFlags;
|
|
72843
73282
|
const brand = config.brandName || input.name;
|
|
72844
73283
|
const generatedAtIso = generatedAt.toISOString();
|
|
72845
|
-
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>` : "";
|
|
72846
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>` : "";
|
|
72847
73286
|
const authority = input.authority;
|
|
72848
73287
|
const consultation = input.consultation;
|
|
@@ -72854,21 +73293,21 @@ function renderPersonalAuthorityV1(input, config, generatedAt) {
|
|
|
72854
73293
|
<html lang="en" data-theme="${config.theme}">
|
|
72855
73294
|
<head>
|
|
72856
73295
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
72857
|
-
<meta name="description" content="${
|
|
73296
|
+
<meta name="description" content="${escapeHtml9(input.summary)}"><title>${escapeHtml9(input.name)} \u2014 ${escapeHtml9(input.professionalTitle)}</title>
|
|
72858
73297
|
<style>
|
|
72859
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)}
|
|
72860
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}}
|
|
72861
73300
|
</style></head>
|
|
72862
73301
|
<body><a class="skip" href="#main">Skip to main content</a>
|
|
72863
|
-
<header class="header"><a class="brand" href="#top"><span class="mark">${
|
|
72864
|
-
<main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${
|
|
72865
|
-
${section(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${
|
|
72866
|
-
${section(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${
|
|
72867
|
-
${section(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${
|
|
72868
|
-
${section(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${
|
|
72869
|
-
${section(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${
|
|
72870
|
-
${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${
|
|
72871
|
-
</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>
|
|
72872
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>`;
|
|
72873
73312
|
const bytes = Buffer.byteLength(html, "utf8");
|
|
72874
73313
|
return {
|
|
@@ -72888,7 +73327,7 @@ var init_render2 = __esm({
|
|
|
72888
73327
|
});
|
|
72889
73328
|
|
|
72890
73329
|
// src/personal-authority/render-v2.ts
|
|
72891
|
-
function
|
|
73330
|
+
function escapeHtml10(value) {
|
|
72892
73331
|
return value.replace(
|
|
72893
73332
|
/[&<>"']/g,
|
|
72894
73333
|
(character) => ({
|
|
@@ -72902,13 +73341,13 @@ function escapeHtml9(value) {
|
|
|
72902
73341
|
}
|
|
72903
73342
|
function safeHref2(value) {
|
|
72904
73343
|
const trimmed = value.trim();
|
|
72905
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73344
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml10(trimmed) : "#";
|
|
72906
73345
|
}
|
|
72907
73346
|
function initials2(name) {
|
|
72908
73347
|
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("") || "PA";
|
|
72909
73348
|
}
|
|
72910
73349
|
function action2(action3, secondary = false) {
|
|
72911
|
-
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>`;
|
|
72912
73351
|
}
|
|
72913
73352
|
function section2(enabled, html) {
|
|
72914
73353
|
return enabled ? html : "";
|
|
@@ -72952,7 +73391,7 @@ function renderPersonalAuthorityV2(input, config, generatedAt) {
|
|
|
72952
73391
|
const surfaceContrast = bestContrastTextColor(colors.surface);
|
|
72953
73392
|
const accentChannels = hexChannels(colors.accent);
|
|
72954
73393
|
const generatedAtIso = generatedAt.toISOString();
|
|
72955
|
-
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>` : "";
|
|
72956
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>` : "";
|
|
72957
73396
|
const authority = input.authority;
|
|
72958
73397
|
const consultation = input.consultation;
|
|
@@ -72964,22 +73403,22 @@ function renderPersonalAuthorityV2(input, config, generatedAt) {
|
|
|
72964
73403
|
<html lang="en" data-theme="${config.theme}">
|
|
72965
73404
|
<head>
|
|
72966
73405
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
72967
|
-
<meta name="description" content="${
|
|
73406
|
+
<meta name="description" content="${escapeHtml10(input.summary)}"><title>${escapeHtml10(input.name)} - ${escapeHtml10(input.professionalTitle)}</title>
|
|
72968
73407
|
<style>
|
|
72969
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)}
|
|
72970
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}}
|
|
72971
73410
|
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.button{transition:none}}
|
|
72972
73411
|
</style></head>
|
|
72973
73412
|
<body><a class="skip" href="#main">Skip to main content</a>
|
|
72974
|
-
<header class="header"><a class="brand" href="#top"><span class="mark">${
|
|
72975
|
-
<main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${
|
|
72976
|
-
${section2(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${
|
|
72977
|
-
${section2(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${
|
|
72978
|
-
${section2(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${
|
|
72979
|
-
${section2(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${
|
|
72980
|
-
${section2(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${
|
|
72981
|
-
${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${
|
|
72982
|
-
</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>
|
|
72983
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>`;
|
|
72984
73423
|
const bytes = Buffer.byteLength(html, "utf8");
|
|
72985
73424
|
return {
|
|
@@ -73005,7 +73444,7 @@ var init_render_v2 = __esm({
|
|
|
73005
73444
|
});
|
|
73006
73445
|
|
|
73007
73446
|
// src/newsroom-publisher/render.ts
|
|
73008
|
-
function
|
|
73447
|
+
function escapeHtml11(value) {
|
|
73009
73448
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
73010
73449
|
"&": "&",
|
|
73011
73450
|
"<": "<",
|
|
@@ -73016,30 +73455,30 @@ function escapeHtml10(value) {
|
|
|
73016
73455
|
}
|
|
73017
73456
|
function safeHref3(value) {
|
|
73018
73457
|
const trimmed = value.trim();
|
|
73019
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73458
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml11(trimmed) : "#";
|
|
73020
73459
|
}
|
|
73021
73460
|
function formatDate(value) {
|
|
73022
73461
|
const date = new Date(value);
|
|
73023
|
-
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);
|
|
73024
73463
|
}
|
|
73025
73464
|
function initials3(value) {
|
|
73026
73465
|
return value.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
|
|
73027
73466
|
}
|
|
73028
73467
|
function storyMedia(story2, className = "") {
|
|
73029
73468
|
if (story2.imageUrl) {
|
|
73030
|
-
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>`;
|
|
73031
73470
|
}
|
|
73032
73471
|
const tone = [...story2.title].reduce((total, character) => total + character.charCodeAt(0), 0) % 5;
|
|
73033
|
-
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>`;
|
|
73034
73473
|
}
|
|
73035
73474
|
function byline(story2, showBylines) {
|
|
73036
|
-
const author = story2.author.href ? `<a href="${safeHref3(story2.author.href)}">${
|
|
73037
|
-
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>`;
|
|
73038
73477
|
}
|
|
73039
73478
|
function storyCard(story2, showBylines, variant = "") {
|
|
73040
73479
|
return `<article class="story-card ${variant}">
|
|
73041
73480
|
<a class="story-card__media" href="${safeHref3(story2.href)}">${storyMedia(story2)}</a>
|
|
73042
|
-
<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>
|
|
73043
73482
|
</article>`;
|
|
73044
73483
|
}
|
|
73045
73484
|
function renderNewsroomPublisherV1(input, config, generatedAt) {
|
|
@@ -73056,22 +73495,22 @@ function renderNewsroomPublisherV1(input, config, generatedAt) {
|
|
|
73056
73495
|
input.primaryPages.contact
|
|
73057
73496
|
];
|
|
73058
73497
|
const trustPages = Object.values(input.trustPages);
|
|
73059
|
-
const ticker = flags.breakingTicker && input.ticker ? `<div class="ticker"><div><b>${
|
|
73060
|
-
const masthead = `<nav class="utility-nav" aria-label="Publication pages"><div><span>${
|
|
73061
|
-
<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>
|
|
73062
73501
|
<div class="masthead__date"><span>Independent journalism</span><time datetime="${generatedAtIso}">${formatDate(generatedAtIso)}</time></div>
|
|
73063
73502
|
<div class="masthead__tools"><button type="button" aria-label="Search">Search</button><button type="button" aria-label="Open menu">Menu</button></div>
|
|
73064
73503
|
</header>`;
|
|
73065
|
-
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>` : "";
|
|
73066
73505
|
const leadGrid = flags.leadGrid ? `<section class="lead-grid" aria-label="Top stories">
|
|
73067
73506
|
<div class="lead-grid__label"><span>Today\u2019s edition</span><b>Top stories</b></div>
|
|
73068
|
-
<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>
|
|
73069
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>
|
|
73070
73509
|
</section>` : "";
|
|
73071
73510
|
const latest = flags.latestNews && input.latest.length > 0 ? `<section class="latest" id="latest">
|
|
73072
73511
|
<div class="section-title"><div><span>Live desk</span><h2>Latest news</h2></div><a href="#top">Back to top \u2191</a></div>
|
|
73073
|
-
<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)}">${
|
|
73074
|
-
<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>
|
|
73075
73514
|
</section>` : "";
|
|
73076
73515
|
const sectionLayouts = ["panorama", "mosaic", "tiles"];
|
|
73077
73516
|
const sections = flags.categorySections ? input.sections.map((section3, sectionIndex) => {
|
|
@@ -73082,16 +73521,16 @@ function renderNewsroomPublisherV1(input, config, generatedAt) {
|
|
|
73082
73521
|
layout === "panorama" && index === 0 ? "story-card--panorama" : layout === "mosaic" && index === 0 ? "story-card--mosaic-lead" : ""
|
|
73083
73522
|
)).join("");
|
|
73084
73523
|
return `<section class="desk-section desk-section--${sectionIndex % 2 ? "tint" : "plain"} desk-section--layout-${layout}">
|
|
73085
|
-
<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>
|
|
73086
73525
|
<div class="desk-section__grid desk-section__grid--${layout}">${cards}</div>
|
|
73087
73526
|
</section>`;
|
|
73088
73527
|
}).join("") : "";
|
|
73089
|
-
const newsletter = flags.newsletter && input.newsletter ? `<section class="newsletter"><div><span>${
|
|
73090
|
-
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>${
|
|
73091
|
-
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>${
|
|
73092
|
-
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>` : "";
|
|
73093
73532
|
const html = `<!doctype html>
|
|
73094
|
-
<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">
|
|
73095
73534
|
<style>
|
|
73096
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}}
|
|
73097
73536
|
/* Tampa-inspired publication palette */
|
|
@@ -73108,7 +73547,7 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
|
|
|
73108
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)}}
|
|
73109
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)}}
|
|
73110
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}}
|
|
73111
|
-
</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>`;
|
|
73112
73551
|
const bytes = Buffer.byteLength(html);
|
|
73113
73552
|
const sha2563 = (0, import_node_crypto48.createHash)("sha256").update(html).digest("hex");
|
|
73114
73553
|
const filename = `${brand.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "newsroom"}-news-site.html`;
|
|
@@ -73123,7 +73562,7 @@ var init_render3 = __esm({
|
|
|
73123
73562
|
});
|
|
73124
73563
|
|
|
73125
73564
|
// src/blog-article/render.ts
|
|
73126
|
-
function
|
|
73565
|
+
function escapeHtml12(value) {
|
|
73127
73566
|
return value.replace(
|
|
73128
73567
|
/[&<>"']/g,
|
|
73129
73568
|
(character) => ({
|
|
@@ -73137,11 +73576,11 @@ function escapeHtml11(value) {
|
|
|
73137
73576
|
}
|
|
73138
73577
|
function safeHref4(value) {
|
|
73139
73578
|
const trimmed = value.trim();
|
|
73140
|
-
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ?
|
|
73579
|
+
return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml12(trimmed) : "#";
|
|
73141
73580
|
}
|
|
73142
73581
|
function formatDate2(value) {
|
|
73143
73582
|
const date = new Date(value);
|
|
73144
|
-
return Number.isNaN(date.getTime()) ?
|
|
73583
|
+
return Number.isNaN(date.getTime()) ? escapeHtml12(value) : new Intl.DateTimeFormat("en", {
|
|
73145
73584
|
month: "long",
|
|
73146
73585
|
day: "numeric",
|
|
73147
73586
|
year: "numeric"
|
|
@@ -73155,15 +73594,15 @@ function jsonForScript(value) {
|
|
|
73155
73594
|
}
|
|
73156
73595
|
function portrait(input) {
|
|
73157
73596
|
if (input.author.portraitUrl) {
|
|
73158
|
-
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)}">`;
|
|
73159
73598
|
}
|
|
73160
|
-
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>`;
|
|
73161
73600
|
}
|
|
73162
73601
|
function sidebarArt(input) {
|
|
73163
73602
|
if (input.sidebarMedia?.imageUrl) {
|
|
73164
|
-
return `<img src="${safeHref4(input.sidebarMedia.imageUrl)}" alt="${
|
|
73603
|
+
return `<img src="${safeHref4(input.sidebarMedia.imageUrl)}" alt="${escapeHtml12(input.sidebarMedia.imageAlt)}">`;
|
|
73165
73604
|
}
|
|
73166
|
-
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>`;
|
|
73167
73606
|
}
|
|
73168
73607
|
function citations(input) {
|
|
73169
73608
|
const published = new Date(input.publishedAt);
|
|
@@ -73192,23 +73631,23 @@ function renderBlogArticleV1(input, config, generatedAt) {
|
|
|
73192
73631
|
...flags.faq && input.faq.length ? [{ id: "faq", title: "Frequently asked questions" }] : []
|
|
73193
73632
|
];
|
|
73194
73633
|
const contributorText = [
|
|
73195
|
-
`Written by <a href="${safeHref4(input.author.href || "#author")}">${
|
|
73196
|
-
input.editor ? `Edited by <a href="${safeHref4(input.editor.href || "#")}">${
|
|
73197
|
-
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>` : ""
|
|
73198
73637
|
].filter(Boolean).join(" \xB7 ");
|
|
73199
73638
|
const sections = input.sections.map(
|
|
73200
|
-
(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>`
|
|
73201
73640
|
).join("");
|
|
73202
|
-
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>${
|
|
73203
|
-
const media = flags.sidebarMedia && input.sidebarMedia ? `<figure class="sidebar-media" data-article-media>${sidebarArt(input)}${input.sidebarMedia.caption ? `<figcaption>${
|
|
73204
|
-
const disclosure = flags.disclosure && input.disclosure ? `<section class="disclosure"><button type="button" aria-expanded="false" aria-controls="disclosure-details"><span>${
|
|
73205
|
-
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>` : "";
|
|
73206
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>` : "";
|
|
73207
|
-
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)}">${
|
|
73208
|
-
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> ${
|
|
73209
|
-
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>
|
|
73210
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}}
|
|
73211
|
-
</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>`;
|
|
73212
73651
|
const bytes = Buffer.byteLength(html);
|
|
73213
73652
|
const sha2563 = (0, import_node_crypto49.createHash)("sha256").update(html).digest("hex");
|
|
73214
73653
|
return {
|
|
@@ -76108,7 +76547,7 @@ function sql() {
|
|
|
76108
76547
|
if (_sql) return _sql;
|
|
76109
76548
|
const url = process.env.MEMORY_DATABASE_URL?.trim();
|
|
76110
76549
|
if (!url) throw new Error("MEMORY_DATABASE_URL is not set (paa-crawler needs mcp-memory Neon URL for reads)");
|
|
76111
|
-
_sql = (0,
|
|
76550
|
+
_sql = (0, import_serverless2.neon)(url);
|
|
76112
76551
|
return _sql;
|
|
76113
76552
|
}
|
|
76114
76553
|
function physicalVault(owner, vault) {
|
|
@@ -76301,11 +76740,11 @@ async function dbUsage(identity, plan) {
|
|
|
76301
76740
|
unlimited: isUnlimited(plan)
|
|
76302
76741
|
};
|
|
76303
76742
|
}
|
|
76304
|
-
var
|
|
76743
|
+
var import_serverless2, _sql, EMBED_BYTES_PER_CHUNK, FREE_COST_CAP_USD;
|
|
76305
76744
|
var init_memory_db = __esm({
|
|
76306
76745
|
"src/api/memory-db.ts"() {
|
|
76307
76746
|
"use strict";
|
|
76308
|
-
|
|
76747
|
+
import_serverless2 = require("@neondatabase/serverless");
|
|
76309
76748
|
init_rates();
|
|
76310
76749
|
init_memory_universe();
|
|
76311
76750
|
_sql = null;
|
|
@@ -79326,6 +79765,7 @@ var init_server = __esm({
|
|
|
79326
79765
|
init_scheduled_artifact_internal_routes();
|
|
79327
79766
|
init_site_audit_worker();
|
|
79328
79767
|
init_local_sourcebook_worker();
|
|
79768
|
+
init_commons_embeddings();
|
|
79329
79769
|
init_local_sourcebook_dispatch();
|
|
79330
79770
|
import_factory8 = require("hono/factory");
|
|
79331
79771
|
import_cookie2 = require("hono/cookie");
|
|
@@ -82109,7 +82549,7 @@ var init_server = __esm({
|
|
|
82109
82549
|
const budget = { maxJobs: 10, deadlineMs: startedAt + CRON_TICK_DRAIN_BUDGET_MS };
|
|
82110
82550
|
const origin = `${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`;
|
|
82111
82551
|
const unfinished = [];
|
|
82112
|
-
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([
|
|
82113
82553
|
settleWithinTickBudget("drainQueue", unfinished, drainQueue2(budget), []),
|
|
82114
82554
|
settleWithinTickBudget("monthlyRefreshSweep", unfinished, runMonthlyRefreshSweep(), { status: "skipped_deadline" }),
|
|
82115
82555
|
settleWithinTickBudget("reapBrowserSessions", unfinished, reapIdleBrowserSessions(120), { reaped: 0 }),
|
|
@@ -82126,6 +82566,7 @@ var init_server = __esm({
|
|
|
82126
82566
|
settleWithinTickBudget("siteExtractReconcile", unfinished, reconcileSiteExtractSettlements(10), { checked: 0, settled: 0, failed: 0 }),
|
|
82127
82567
|
settleWithinTickBudget("paaRedispatch", unfinished, redispatchPendingPaaHarvests(10), { checked: 0, dispatched: 0, failed: 0 }),
|
|
82128
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 }),
|
|
82129
82570
|
settleWithinTickBudget("localSourcebookRedispatch", unfinished, redispatchQueuedLocalSourcebookAcquisitions(5), { checked: 0, dispatched: 0, failed: 0 }),
|
|
82130
82571
|
settleWithinTickBudget("analyticsRollup", unfinished, refreshAnalyticsDailyRollupsIfDue(), { status: "failed", rows: 0 }),
|
|
82131
82572
|
settleWithinTickBudget("analyticsForms", unfinished, deliverPendingAnalyticsForms(10), { claimed: 0, delivered: 0, deferred: 0 }),
|
|
@@ -82156,6 +82597,7 @@ var init_server = __esm({
|
|
|
82156
82597
|
siteExtractReconciliation,
|
|
82157
82598
|
paaHarvestRedispatch,
|
|
82158
82599
|
paaHarvestReconciliation,
|
|
82600
|
+
commonsEmbeddingDrain,
|
|
82159
82601
|
localSourcebookRedispatch,
|
|
82160
82602
|
analyticsRollup,
|
|
82161
82603
|
analyticsFormDelivery,
|