import { BaseExtractor, ExtractorOptions } from './_base'; import { ExtractorResult } from '../types/extractors'; export declare class TwitterExtractor extends BaseExtractor { private mainTweet; private threadTweets; private replyTweets; private replyDepths; constructor(document: Document, url: string, schemaOrgData?: any, options?: ExtractorOptions); /** * Conversation cells, in document order, stopping at X's "Discover more" and * similar trailing sections. * * Cells and boundary candidates are collected in one combined-selector query * so that document order comes from the query itself. Comparing positions * any other way would mean `compareDocumentPosition`, which cannot be used * here: the `Node` global is absent under linkedom, and linkedom inverts the * result for nodes at different depths. * * Anything before the first cell is a header, not a boundary — X renders a * "Post" heading above the timeline and wraps the conversation in a * `
`, and treating either as the boundary drops every tweet. */ private conversationCells; /** * Walk cells to classify tweets: * 1. Main tweet (first article) * 2. Thread tweets: consecutive self-replies by the main author at the top of * the timeline, before any reply by a different person * 3. Reply tweets: everything after the thread ends */ private classifyCells; canExtract(): boolean; extract(): ExtractorResult; private extractComments; private static readonly RESERVED_PATHS; /** * The @handle for a tweet. * * Tried in order: link text starting with "@", the profile path in a link * href, then any "@name" in the name block's text (quoted tweets render the * handle as plain text rather than a link). Positional lookups like * `links[1]` break whenever X reorders the name block. */ private getHandle; private formatTweetText; private replaceEmojiImages; private findQuotedTweet; private extractTweetContent; private extractQuotedTweet; private extractUserInfo; private extractImages; private extractCard; private getTweetId; private getTweetAuthor; private createDescription; }