diff --git a/src/utils/standard-site.js b/src/utils/standard-site.js deleted file mode 100644 index 217c1ff6..00000000 --- a/src/utils/standard-site.js +++ /dev/null @@ -1,42 +0,0 @@ -const STANDARD_SITE_DOCUMENT_COLLECTION = 'site.standard.document'; - -export function isStandardSiteDocumentRecord(record) { - if (!record) return false; - - if (typeof record === 'string') { - return record.includes(STANDARD_SITE_DOCUMENT_COLLECTION); - } - - if (typeof record !== 'object') return false; - - const uri = record.uri || record.record?.uri; - const collection = record.collection || record.record?.collection; - const type = record.$type || record.record?.$type; - - return [uri, collection, type].some((value) => - String(value || '').includes(STANDARD_SITE_DOCUMENT_COLLECTION), - ); -} - -export function isLeafletUrl(url) { - try { - const { hostname } = new URL(url); - return ( - hostname === 'leaflet.pub' || - hostname.endsWith('.leaflet.pub') || - hostname.startsWith('leaflet.') - ); - } catch { - return false; - } -} - -export function canReadCardInline(card) { - if (!card?.url) return false; - - return ( - isLeafletUrl(card.url) || - isStandardSiteDocumentRecord(card.associatedRecord) || - isStandardSiteDocumentRecord(card.associated_record) - ); -} diff --git a/src/utils/standard-site.ts b/src/utils/standard-site.ts new file mode 100644 index 00000000..119e89f6 --- /dev/null +++ b/src/utils/standard-site.ts @@ -0,0 +1,79 @@ +const STANDARD_SITE_DOCUMENT_COLLECTION = 'site.standard.document'; + +interface StandardSiteRecordFields { + $type?: unknown; + collection?: unknown; + uri?: unknown; +} + +interface StandardSiteDocumentCandidate extends StandardSiteRecordFields { + record?: StandardSiteRecordFields; +} + +interface CardCandidate { + associated_record?: unknown; + associatedRecord?: unknown; + url?: string; +} + +function hasStandardSiteDocumentCollection(value: unknown): boolean { + return ( + typeof value === 'string' && + value.includes(STANDARD_SITE_DOCUMENT_COLLECTION) + ); +} + +function isObject(value: unknown): value is object { + return typeof value === 'object' && Object(value) === value; +} + +function isStandardSiteDocumentRecord(record: unknown): boolean { + if (typeof record === 'string') { + return record.includes(STANDARD_SITE_DOCUMENT_COLLECTION); + } + + if (!isObject(record)) { + return false; + } + + const candidate = record as StandardSiteDocumentCandidate; + const uri = candidate.uri || candidate.record?.uri; + const collection = candidate.collection || candidate.record?.collection; + const type = candidate.$type || candidate.record?.$type; + + return [uri, collection, type].some((value) => + hasStandardSiteDocumentCollection(value), + ); +} + +function isLeafletUrl(url: string): boolean { + try { + const { hostname } = new URL(url); + return ( + hostname === 'leaflet.pub' || + hostname.endsWith('.leaflet.pub') || + hostname.startsWith('leaflet.') + ); + } catch { + return false; + } +} + +function canReadCardInline(card: unknown): boolean { + if (!isObject(card)) { + return false; + } + + const candidate = card as CardCandidate; + if (typeof candidate.url !== 'string' || candidate.url === '') { + return false; + } + + return ( + isLeafletUrl(candidate.url) || + isStandardSiteDocumentRecord(candidate.associatedRecord) || + isStandardSiteDocumentRecord(candidate.associated_record) + ); +} + +export { canReadCardInline, isLeafletUrl, isStandardSiteDocumentRecord }; diff --git a/tests/atproto-standard-site.spec.js b/tests/atproto-standard-site.spec.js index f7d4b5bc..317afd80 100644 --- a/tests/atproto-standard-site.spec.js +++ b/tests/atproto-standard-site.spec.js @@ -5,7 +5,7 @@ import { canReadCardInline, isLeafletUrl, isStandardSiteDocumentRecord, -} from '../src/utils/standard-site.js'; +} from '../src/utils/standard-site.ts'; function postWithEmbed(embed) { return {