{"version":3,"file":"index.cjs","names":["mime"],"sources":["../src/types.ts","../src/utils.ts","../src/publisher.ts","../src/link-tags.ts","../src/plugin.ts","../src/index.ts"],"sourcesContent":["/** Default AT Protocol PDS URL used when none is configured. */\nexport const DEFAULT_PDS_URL = \"https://bsky.social\";\n\n/** AT Protocol XRPC endpoint paths used by the publisher. */\nexport const ENDPOINTS = {\n  createSession: \"/xrpc/com.atproto.server.createSession\",\n  createRecord: \"/xrpc/com.atproto.repo.createRecord\",\n  putRecord: \"/xrpc/com.atproto.repo.putRecord\",\n  listRecords: \"/xrpc/com.atproto.repo.listRecords\",\n  uploadBlob: \"/xrpc/com.atproto.repo.uploadBlob\",\n  getBlob: \"/xrpc/com.atproto.sync.getBlob\"\n};\n\n/** Standard.site lexicon NSIDs for the records this plugin manages. */\nexport const LEXICONS = {\n  publication: \"site.standard.publication\",\n  document: \"site.standard.document\",\n  basicTheme: \"site.standard.theme.basic\",\n  rgbColor: \"site.standard.theme.color#rgb\"\n};\n\n/** An RGB color with channel values in the 0–255 range. */\nexport interface RGBColor {\n  r: number;\n  g: number;\n  b: number;\n}\n\n/** Theme color set accepted in the plugin options. */\nexport interface ColorConfig {\n  bg: RGBColor;\n  fg: RGBColor;\n  accent: RGBColor;\n  accentFg: RGBColor;\n}\n\n/** Basic theme record as stored in a publication's `site.standard.theme.basic`. */\nexport interface BasicTheme {\n  $type: string;\n  background: {\n    $type: string;\n    r: number;\n    g: number;\n    b: number;\n  };\n  foreground: {\n    $type: string;\n    r: number;\n    g: number;\n    b: number;\n  };\n  accent: {\n    $type: string;\n    r: number;\n    g: number;\n    b: number;\n  };\n  accentForeground: {\n    $type: string;\n    r: number;\n    g: number;\n    b: number;\n  };\n}\n\n/** Reference to a blob (e.g. uploaded image) stored on the PDS. */\nexport interface BlobRef {\n  $type: \"blob\";\n  ref: {\n    $link: string;\n  };\n  mimeType: string;\n  size: number;\n}\n\n/** Credentials and PDS configuration used to authenticate the publisher. */\nexport interface PublisherOptions {\n  pds?: string;\n  identifier?: string;\n  password?: string;\n}\n\n/** Slim response from the PDS session creation endpoint. */\nexport interface SessionResponse {\n  accessJwt: string;\n  did: string;\n}\n\n/** A generic record returned stored in a PDS. */\nexport interface Record {\n  cid: string;\n  uri: string;\n  value: object;\n}\n\n/** Response from creating or updating a record on the PDS. */\nexport interface CreateOrPutRecordResponse {\n  uri: string;\n  cid: string;\n  commit: {\n    cid: string;\n    rev: string;\n  };\n  validationStatus: string;\n}\n\n/** Response from listing records of a given collection on the PDS. */\nexport interface ListRecordsResponse {\n  cursor: string | null;\n  records: Record[];\n}\n\n/** Response from uploading a blob to the PDS. */\nexport interface UploadBlobResponse {\n  blob: BlobRef;\n}\n\n/** A `site.standard.publication` record describing the site as a whole. */\nexport interface Publication {\n  $type: string;\n  url: string;\n  name: string;\n  description?: string;\n  basicTheme?: BasicTheme;\n  icon?: BlobRef;\n  preferences: {\n    showInDiscover: boolean;\n  };\n}\n\n/** A `site.standard.document` record describing a single published page. */\nexport interface Document {\n  $type: string;\n  site: string;\n  title: string;\n  publishedAt: string;\n  path?: string;\n  description?: string;\n  coverImage?: BlobRef;\n  textContent?: string;\n  bskyPostRef?: string;\n}\n\n/** A publication record paired with its AT URI. */\nexport interface PublicationWithUri extends Publication {\n  uri: string;\n}\n\n/** A document record paired with its AT URI. */\nexport interface DocumentWithUri extends Document {\n  uri: string;\n}\n\n/** Client that authenticates to a PDS and syncs publication and document records. */\nexport interface Publisher {\n  startSession: () => Promise<void>;\n  createOrUpdatePublicationRecord: (\n    publication: Publication,\n    options?: { themeColors?: ColorConfig; iconPath?: string }\n  ) => Promise<string>;\n  createOrUpdateDocumentRecord: (document: Document, options?: { coverImagePath?: string }) => Promise<string>;\n}\n\n/** Configuration options accepted by the Eleventy plugin. */\nexport type StandardSitePluginOptions = Partial<PublisherOptions> & {\n  publicationName: string;\n  publicationDescription?: string;\n  publicationUrl: string;\n  showInDiscover?: boolean;\n  includeTextContent?: boolean;\n  themeColors?: ColorConfig;\n  publicationIconPath?: string;\n};\n","/** Returns the record key (rkey), i.e. the last path segment, of an AT URI. */\nexport function extractRecordKey(uri: string): string {\n  const parts = uri.split(\"/\");\n  return parts[parts.length - 1];\n}\n\n/** Normalizes a PDS URL by trimming whitespace, dropping a trailing slash, and ensuring https scheme. */\nexport function normalizePdsUrl(url: string): string {\n  let normalizedUrl = url.trim();\n\n  if (normalizedUrl.endsWith(\"/\")) {\n    normalizedUrl = normalizedUrl.slice(0, -1);\n  }\n\n  if (normalizedUrl.length === 0) {\n    throw new Error(\"PDS URL cannot be empty after normalization.\");\n  }\n\n  if (!normalizedUrl.startsWith(\"http://\") && !normalizedUrl.startsWith(\"https://\")) {\n    normalizedUrl = `https://${normalizedUrl}`;\n  }\n\n  return normalizedUrl;\n}\n\n/** Normalizes an identifier by trimming whitespace (and stripping a leading `@` from handles). */\nexport function normalizeIdentifier(identifier: string): string {\n  let normalizedIdentifier = identifier.trim();\n\n  if (normalizedIdentifier.startsWith(\"@\")) {\n    normalizedIdentifier = normalizedIdentifier.slice(1);\n  }\n\n  if (normalizedIdentifier.length === 0) {\n    throw new Error(\"Identifier cannot be empty after normalization.\");\n  }\n\n  return normalizedIdentifier;\n}\n","import {\n  ENDPOINTS,\n  LEXICONS,\n  PublisherOptions,\n  SessionResponse,\n  Record,\n  CreateOrPutRecordResponse,\n  ListRecordsResponse,\n  Publication,\n  PublicationWithUri,\n  Publisher,\n  Document,\n  DocumentWithUri,\n  DEFAULT_PDS_URL,\n  BlobRef,\n  BasicTheme,\n  ColorConfig,\n  UploadBlobResponse,\n  RGBColor\n} from \"./types\";\nimport { extractRecordKey, normalizePdsUrl, normalizeIdentifier } from \"./utils\";\nimport { readFileSync, existsSync } from \"fs\";\nimport mime from \"mime-types\";\n\n/** Creates a {@link Publisher} that authenticates to the PDS and syncs records. */\nexport function createPublisher({ pds, identifier, password }: PublisherOptions): Publisher {\n  if (!pds) {\n    pds = DEFAULT_PDS_URL;\n  }\n\n  if (!identifier || !password) {\n    throw new Error(\"Missing required PDS configuration: identifier and password are required.\");\n  }\n\n  const normalizedPds = normalizePdsUrl(pds);\n  let normalizedIdentifier = normalizeIdentifier(identifier);\n  const getEndpointUrl = (endpoint: string) => `${normalizedPds}${endpoint}`;\n\n  let accessJwt: string | null = null;\n  const checkSession = () => {\n    if (!accessJwt) {\n      throw new Error(\"Session not started. Call startSession() before making requests.\");\n    }\n  };\n\n  const uploadBlob = async (filePath: string): Promise<BlobRef> => {\n    checkSession();\n\n    const fileBuffer = readFileSync(filePath);\n    const mimeType = mime.lookup(filePath) || \"application/octet-stream\";\n\n    const response = await fetch(getEndpointUrl(ENDPOINTS.uploadBlob), {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${accessJwt}`,\n        \"Content-Type\": mimeType\n      },\n      body: fileBuffer\n    });\n\n    if (!response.ok) {\n      throw new Error(`Failed to upload blob: ${response.statusText}`);\n    }\n\n    const data = (await response.json()) as UploadBlobResponse;\n    return data.blob;\n  };\n\n  const getBlobBuffer = async (cid: string): Promise<Buffer> => {\n    const params = new URLSearchParams();\n    params.set(\"did\", normalizedIdentifier);\n    params.set(\"cid\", cid);\n\n    const url = new URL(getEndpointUrl(ENDPOINTS.getBlob));\n    url.search = params.toString();\n\n    const response = await fetch(url.toString(), {\n      method: \"GET\"\n    });\n\n    if (!response.ok) {\n      throw new Error(`Failed to fetch existing blob ${cid}: ${response.statusText}`);\n    }\n\n    const body = await response.arrayBuffer();\n    return Buffer.from(body);\n  };\n\n  const isSameFileAsExistingBlob = async (filePath: string, blob: BlobRef): Promise<boolean> => {\n    const localFileBuffer = readFileSync(filePath);\n    const existingBlobBuffer = await getBlobBuffer(blob.ref.$link);\n    return localFileBuffer.equals(existingBlobBuffer);\n  };\n\n  const resolveBlobFromPath = async (options: {\n    filePath?: string;\n    existingBlob?: BlobRef;\n  }): Promise<BlobRef | undefined> => {\n    const { filePath, existingBlob } = options;\n\n    if (!filePath) {\n      return undefined;\n    }\n\n    if (!existsSync(filePath)) {\n      console.warn(`\\tBlob file not found: ${filePath}`);\n      return undefined;\n    }\n\n    try {\n      if (existingBlob) {\n        try {\n          const shouldReuseExistingBlob = await isSameFileAsExistingBlob(filePath, existingBlob);\n          if (shouldReuseExistingBlob) {\n            return existingBlob;\n          }\n        } catch (error) {\n          console.warn(`\\tFailed to compare against existing blob, re-uploading from ${filePath}:`, error);\n        }\n      }\n\n      return await uploadBlob(filePath);\n    } catch (error) {\n      console.warn(`\\tFailed to process blob from ${filePath}:`, error);\n      return undefined;\n    }\n  };\n\n  const isValidRgbColor = (color: RGBColor): boolean => {\n    for (const channel of [color.r, color.g, color.b]) {\n      if (!Number.isInteger(channel) || channel < 0 || channel > 255) {\n        return false;\n      }\n    }\n\n    return true;\n  };\n\n  const colorConfigToBasicTheme = (colors: ColorConfig): BasicTheme => {\n    if (!colors.bg || !colors.fg || !colors.accent || !colors.accentFg) {\n      throw new Error(\n        \"Incomplete color configuration provided. All colors (bg, fg, accent, accentFg) are required if you want to create a basic theme.\"\n      );\n    }\n\n    if (\n      !isValidRgbColor(colors.bg) ||\n      !isValidRgbColor(colors.fg) ||\n      !isValidRgbColor(colors.accent) ||\n      !isValidRgbColor(colors.accentFg)\n    ) {\n      throw new Error(\"Invalid color configuration provided. RGB color values must be integers between 0 and 255.\");\n    }\n\n    return {\n      $type: LEXICONS.basicTheme,\n      background: {\n        $type: LEXICONS.rgbColor,\n        r: colors.bg.r,\n        g: colors.bg.g,\n        b: colors.bg.b\n      },\n      foreground: {\n        $type: LEXICONS.rgbColor,\n        r: colors.fg.r,\n        g: colors.fg.g,\n        b: colors.fg.b\n      },\n      accent: {\n        $type: LEXICONS.rgbColor,\n        r: colors.accent.r,\n        g: colors.accent.g,\n        b: colors.accent.b\n      },\n      accentForeground: {\n        $type: LEXICONS.rgbColor,\n        r: colors.accentFg.r,\n        g: colors.accentFg.g,\n        b: colors.accentFg.b\n      }\n    };\n  };\n\n  const listRecords = async (collection: string): Promise<Record[]> => {\n    const baseEndpointUrl = getEndpointUrl(ENDPOINTS.listRecords);\n\n    let cursor: string | undefined;\n    const records: Record[] = [];\n    do {\n      const params = new URLSearchParams();\n      params.set(\"collection\", collection);\n      params.set(\"repo\", normalizedIdentifier);\n      if (cursor) {\n        params.set(\"cursor\", cursor);\n      }\n\n      const url = new URL(baseEndpointUrl);\n      url.search = params.toString();\n\n      const response = await fetch(url.toString(), {\n        method: \"GET\"\n      });\n\n      if (!response.ok) {\n        throw new Error(`Failed to list ${collection} records: ${response.statusText}`);\n      }\n\n      const data = (await response.json()) as ListRecordsResponse;\n      records.push(...data.records);\n\n      cursor = data.cursor ?? undefined;\n    } while (cursor);\n\n    return records;\n  };\n\n  const getPublicationRecords = async (): Promise<PublicationWithUri[]> => {\n    const records = await listRecords(LEXICONS.publication);\n    return records.map((record) => ({ ...(record.value as Publication), uri: record.uri }));\n  };\n\n  const createRecord = async (collection: string, value: object): Promise<CreateOrPutRecordResponse> => {\n    checkSession();\n\n    const response = await fetch(getEndpointUrl(ENDPOINTS.createRecord), {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${accessJwt}`,\n        \"Content-Type\": \"application/json\"\n      },\n      body: JSON.stringify({\n        collection,\n        record: value,\n        repo: normalizedIdentifier\n      })\n    });\n\n    if (!response.ok) {\n      throw new Error(`Failed to create record in ${collection}: ${response.statusText}`);\n    }\n\n    return (await response.json()) as CreateOrPutRecordResponse;\n  };\n\n  const getSiteDocumentRecords = async (site: string): Promise<DocumentWithUri[]> => {\n    const records = await listRecords(LEXICONS.document);\n    return records\n      .filter((record) => (record.value as Document).site === site)\n      .map((record) => ({ ...(record.value as Document), uri: record.uri }));\n  };\n\n  const putRecord = async (\n    collection: string,\n    recordKey: string,\n    value: object\n  ): Promise<CreateOrPutRecordResponse> => {\n    checkSession();\n\n    const response = await fetch(getEndpointUrl(ENDPOINTS.putRecord), {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${accessJwt}`,\n        \"Content-Type\": \"application/json\"\n      },\n      body: JSON.stringify({\n        collection,\n        rkey: recordKey,\n        record: value,\n        repo: normalizedIdentifier\n      })\n    });\n\n    if (!response.ok) {\n      throw new Error(`Failed to update record in ${collection}: ${response.statusText}`);\n    }\n\n    return (await response.json()) as CreateOrPutRecordResponse;\n  };\n\n  return {\n    startSession: async () => {\n      const response = await fetch(getEndpointUrl(ENDPOINTS.createSession), {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\"\n        },\n        body: JSON.stringify({\n          identifier: normalizedIdentifier,\n          password\n        })\n      });\n\n      if (!response.ok) {\n        throw new Error(`Failed to create session on PDS ${pds} with provided credentials: ${response.statusText}`);\n      }\n\n      const data = (await response.json()) as SessionResponse;\n      accessJwt = data.accessJwt;\n\n      // once session is established, we use the response DID as identifier for all future requests\n      normalizedIdentifier = data.did;\n    },\n\n    createOrUpdatePublicationRecord: async (\n      publication: Publication,\n      options?: { themeColors?: ColorConfig; iconPath?: string }\n    ) => {\n      checkSession();\n\n      const publicationToPublish: Publication = { ...publication };\n\n      if (options?.themeColors) {\n        publicationToPublish.basicTheme = colorConfigToBasicTheme(options.themeColors);\n      }\n\n      // Try getting existing record to determine if we need to create or update\n      const existingRecords = await getPublicationRecords();\n      const existingRecord = existingRecords.find((record) => record.url === publication.url);\n\n      const resolvedIconBlob = await resolveBlobFromPath({\n        filePath: options?.iconPath,\n        existingBlob: existingRecord?.icon\n      });\n      if (resolvedIconBlob) {\n        publicationToPublish.icon = resolvedIconBlob;\n      }\n\n      let recordUri: string | undefined;\n      if (existingRecord) {\n        const existingRecordUri = existingRecord.uri;\n        const existingRecordKey = extractRecordKey(existingRecordUri);\n\n        const updateRecordResponse = await putRecord(LEXICONS.publication, existingRecordKey, publicationToPublish);\n        recordUri = updateRecordResponse.uri;\n      } else {\n        const newRecordResponse = await createRecord(LEXICONS.publication, publicationToPublish);\n        recordUri = newRecordResponse.uri;\n      }\n\n      const recordKey = extractRecordKey(recordUri);\n      console.log(\n        `Publication record for URL ${publication.url} available at URI: ${recordUri} (record key: ${recordKey})`\n      );\n\n      return recordUri;\n    },\n\n    createOrUpdateDocumentRecord: async (\n      document: Document,\n      options?: { coverImagePath?: string }\n    ): Promise<string> => {\n      checkSession();\n\n      const documentToPublish: Document = { ...document };\n\n      // Try getting existing record to determine if we need to create or update\n      const existingRecords = await getSiteDocumentRecords(document.site);\n      const existingRecord = existingRecords.find((record) => record.path === document.path);\n\n      const resolvedCoverImageBlob = await resolveBlobFromPath({\n        filePath: options?.coverImagePath,\n        existingBlob: existingRecord?.coverImage\n      });\n      if (resolvedCoverImageBlob) {\n        documentToPublish.coverImage = resolvedCoverImageBlob;\n      }\n\n      let recordUri: string | undefined;\n      if (existingRecord) {\n        const existingRecordUri = existingRecord.uri;\n        const existingRecordKey = extractRecordKey(existingRecordUri);\n\n        const updateRecordResponse = await putRecord(LEXICONS.document, existingRecordKey, documentToPublish);\n        recordUri = updateRecordResponse.uri;\n      } else {\n        const newRecordResponse = await createRecord(LEXICONS.document, documentToPublish);\n        recordUri = newRecordResponse.uri;\n      }\n\n      const recordKey = extractRecordKey(recordUri);\n      console.log(\n        `\\tDocument record for path ${document.path} available at URI: ${recordUri} (record key: ${recordKey})`\n      );\n\n      return recordUri;\n    }\n  };\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { LEXICONS } from \"./types\";\n\nconst STANDARD_SITE_DOCUMENT_REL = LEXICONS.document;\nconst STANDARD_SITE_PUBLICATION_REL = LEXICONS.publication;\n\nfunction getOutputHtmlPath(outputDir: string, postUrl: string): string {\n  const normalizedPostUrl = postUrl.replace(/^\\/+/, \"\");\n\n  if (!normalizedPostUrl) {\n    return path.join(outputDir, \"index.html\");\n  }\n\n  if (normalizedPostUrl.endsWith(\"/\")) {\n    return path.join(outputDir, normalizedPostUrl, \"index.html\");\n  }\n\n  if (path.extname(normalizedPostUrl)) {\n    return path.join(outputDir, normalizedPostUrl);\n  }\n\n  return path.join(outputDir, normalizedPostUrl, \"index.html\");\n}\n\nfunction getOutputHtmlPaths(outputDir: string): string[] {\n  const htmlPaths: string[] = [];\n  const directoriesToVisit = [outputDir];\n\n  while (directoriesToVisit.length > 0) {\n    const currentDirectory = directoriesToVisit.pop();\n    if (!currentDirectory) {\n      continue;\n    }\n\n    let entries: fs.Dirent[];\n    try {\n      entries = fs.readdirSync(currentDirectory, { withFileTypes: true });\n    } catch (error) {\n      console.warn(`Skipping publication link tag injection: failed reading directory ${currentDirectory}.`, error);\n      continue;\n    }\n\n    for (const entry of entries) {\n      const entryPath = path.join(currentDirectory, entry.name);\n\n      if (entry.isDirectory()) {\n        directoriesToVisit.push(entryPath);\n        continue;\n      }\n\n      if (entry.isFile() && path.extname(entry.name).toLowerCase() === \".html\") {\n        htmlPaths.push(entryPath);\n      }\n    }\n  }\n\n  return htmlPaths;\n}\n\nfunction upsertLinkTagInHtmlFile(htmlPath: string, rel: string, href: string): void {\n  const linkTag = `<link rel=\"${rel}\" href=\"${href}\" />`;\n  const existingLinkPattern = new RegExp(`<link\\\\b[^>]*\\\\brel=(?:\"${rel}\"|'${rel}')[^>]*>`, \"i\");\n\n  let htmlContent: string;\n  try {\n    htmlContent = fs.readFileSync(htmlPath, \"utf-8\");\n  } catch (error) {\n    console.warn(`Skipping link tag injection for ${htmlPath}: failed reading file.`, error);\n    return;\n  }\n\n  let updatedHtmlContent = htmlContent;\n  if (existingLinkPattern.test(updatedHtmlContent)) {\n    updatedHtmlContent = updatedHtmlContent.replace(existingLinkPattern, linkTag);\n  } else if (/<\\/head>/i.test(updatedHtmlContent)) {\n    updatedHtmlContent = updatedHtmlContent.replace(/<\\/head>/i, `  ${linkTag}\\n</head>`);\n  } else {\n    console.warn(`Skipping link tag injection for ${htmlPath}: file does not include a </head> tag.`);\n    return;\n  }\n\n  if (updatedHtmlContent === htmlContent) {\n    return;\n  }\n\n  try {\n    fs.writeFileSync(htmlPath, updatedHtmlContent, \"utf-8\");\n  } catch (error) {\n    console.warn(`Skipping link tag injection for ${htmlPath}: failed writing file.`, error);\n  }\n}\n\n/** Injects the `site.standard.document` link tag into the given post's HTML output. */\nexport function injectDocumentLinkTag(outputDir: string, postUrl: string, documentRecordUri: string): void {\n  const htmlPath = getOutputHtmlPath(outputDir, postUrl);\n  upsertLinkTagInHtmlFile(htmlPath, STANDARD_SITE_DOCUMENT_REL, documentRecordUri);\n}\n\n/** Injects the `site.standard.publication` link tag into every HTML file in the output. */\nexport function injectPublicationLinkTags(outputDir: string, publicationRecordUri: string): void {\n  const htmlPaths = getOutputHtmlPaths(outputDir);\n  for (const htmlPath of htmlPaths) {\n    upsertLinkTagInHtmlFile(htmlPath, STANDARD_SITE_PUBLICATION_REL, publicationRecordUri);\n  }\n}\n","import { createPublisher } from \"./publisher\";\nimport { LEXICONS, Publication, StandardSitePluginOptions, Document, DEFAULT_PDS_URL } from \"./types\";\nimport { injectDocumentLinkTag, injectPublicationLinkTags } from \"./link-tags\";\nimport { convert } from \"html-to-text\";\nimport path from \"path\";\nimport fs from \"fs\";\n\nconst htmlToPlainText = (html: string): string =>\n  convert(html, {\n    wordwrap: false,\n    selectors: [\n      { selector: \"a\", options: { ignoreHref: true } },\n      { selector: \"img\", format: \"skip\" }\n    ]\n  });\n\nconst DEFAULT_OPTIONS: Partial<StandardSitePluginOptions> = {\n  pds: DEFAULT_PDS_URL,\n  showInDiscover: true,\n  includeTextContent: true\n};\n\ntype EleventyAfterEvent = \"eleventy.after\";\n\ninterface EleventyAfterEventData {\n  dir: {\n    output: string;\n  };\n}\n\ninterface EleventyCollectionItemData {\n  title: string;\n  description?: string;\n  bskyPostRef?: string;\n  standardSiteDocument?: boolean;\n  coverImagePath?: string;\n}\n\ninterface EleventyCollectionItem {\n  url: string;\n  date: Date;\n  templateContent?: string;\n  data: EleventyCollectionItemData;\n}\n\ninterface EleventyCollectionApiLike {\n  getAll(): EleventyCollectionItem[];\n}\n\ninterface EleventyConfigLike {\n  addCollection(name: string, callback: (collection: EleventyCollectionApiLike) => EleventyCollectionItem[]): void;\n  on(event: EleventyAfterEvent, callback: (data: EleventyAfterEventData) => Promise<void> | void): void;\n}\n\n/**\n * Eleventy plugin that syncs the site publication and its documents to Standard.site records\n * on an AT Protocol PDS and injects the corresponding `<link>` tags into the output.\n */\nexport default function pluginStandardSite(\n  eleventyConfig: EleventyConfigLike,\n  options: StandardSitePluginOptions\n): void {\n  const resolvedOptions: StandardSitePluginOptions = {\n    ...DEFAULT_OPTIONS,\n    ...options\n  };\n\n  let standardSiteDocumentPosts: EleventyCollectionItem[] = [];\n  eleventyConfig.addCollection(\"standardSiteDocuments\", (collection: EleventyCollectionApiLike) => {\n    standardSiteDocumentPosts = collection.getAll().filter((item) => item.data.standardSiteDocument === true);\n    return standardSiteDocumentPosts;\n  });\n\n  eleventyConfig.on(\"eleventy.after\", async ({ dir }) => {\n    const publisher = createPublisher(resolvedOptions);\n\n    const resolveAssetPath = (assetPath?: string): string | undefined =>\n      assetPath ? path.join(dir.output, assetPath) : undefined;\n\n    // Authenticating to the PDS\n    try {\n      await publisher.startSession();\n    } catch (error) {\n      console.error(\"Failed to authenticate to PDS:\", error);\n      return;\n    }\n\n    // Get or create the publication record\n    const publication: Publication = {\n      $type: LEXICONS.publication,\n      url: resolvedOptions.publicationUrl,\n      name: resolvedOptions.publicationName,\n      description: resolvedOptions.publicationDescription,\n      preferences: {\n        showInDiscover: resolvedOptions.showInDiscover ?? DEFAULT_OPTIONS.showInDiscover!\n      }\n    };\n    const publicationRecordUri = await publisher.createOrUpdatePublicationRecord(publication, {\n      themeColors: resolvedOptions.themeColors,\n      iconPath: resolveAssetPath(resolvedOptions.publicationIconPath)\n    });\n\n    // Expose .well-known endpoint for the publication record\n    const outputDir = dir.output;\n    const wellKnownEndpointPath = path.join(outputDir, \".well-known\", LEXICONS.publication);\n\n    fs.mkdirSync(path.dirname(wellKnownEndpointPath), { recursive: true });\n    fs.writeFileSync(wellKnownEndpointPath, publicationRecordUri, \"utf-8\");\n    injectPublicationLinkTags(outputDir, publicationRecordUri);\n\n    // Create or update document records for each post with standardSiteDocument: true\n    for (const post of standardSiteDocumentPosts) {\n      console.log(`Processing post: ${post.url}`);\n      const documentRecord: Document = {\n        $type: LEXICONS.document,\n        site: publicationRecordUri,\n        title: post.data.title,\n        publishedAt: post.date.toISOString(),\n        path: post.url,\n        description: post.data.description,\n        bskyPostRef: post.data.bskyPostRef,\n        textContent:\n          resolvedOptions.includeTextContent && post.templateContent !== undefined\n            ? htmlToPlainText(post.templateContent)\n            : undefined\n      };\n\n      try {\n        const documentRecordUri = await publisher.createOrUpdateDocumentRecord(documentRecord, {\n          coverImagePath: resolveAssetPath(post.data.coverImagePath)\n        });\n        injectDocumentLinkTag(outputDir, post.url, documentRecordUri);\n      } catch (error) {\n        console.error(`Failed to sync document record for ${post.url}:`, error);\n      }\n    }\n\n    console.log(\n      `Finished processing Standard.site records with 1 publication and ${standardSiteDocumentPosts.length} documents.`\n    );\n  });\n}\n","import pluginStandardSite from \"./plugin\";\n\nexport default pluginStandardSite;\nexport { pluginStandardSite };\nexport type { StandardSitePluginOptions } from \"./types\";\n"],"mappings":"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"}