Ctrl K
ComunidadGuías…

global.d.ts

Rama develop · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
interface ElementOffset {
  top: number;
  left: number;
  bottom: number;
  right: number;
}

interface PostValidatorMessage {
  type: "error" | "warning" | "error";
  message: string;
}

type PostValidator = (postText: string) => [boolean, PostValidatorMessage[]];

interface ProcessedTag {
  id: number | string
  text: string
  desc: string
  synonyms?: string | QPixelTagSynonym[]
}

interface UserPreferences {
  community: Record<string, string | null>;
  global: Record<string, string | null>;
}

interface DelegatedListener {
  event: string;
  selector: string;
  callback: EventListener;
}

type ClassWatcherCallback = (element: HTMLElement) => void;

interface MarkdownAction {
  apply($field: JQuery<HTMLTextAreaElement | HTMLInputElement>): void
}

interface QPixelDOM {
  // private properties
  _delegatedListeners?: DelegatedListener[];
  _eventListeners?: Record<string, (ev: Event) => void>;

  /**
   * Adds a delegated event listener. Use when an event listener is required that will fire for elements added to the
   * DOM dynamically after the delegated listener is added.
   * @param event An event name to listen for.
   * @param selector A CSS selector representing elements on which to apply the listener.
   * @param callback A callback function to pass to the event listener.
   */
  addDelegatedListener?: (event: string, selector: string, callback: EventListener) => void;
  /**
   * Adds an event listener to _all_ elements that currently match a selector.
   * @param event An event name to listen for.
   * @param selector A CSS selector representing elements on which to apply the listener.
   * @param callback A callback function to pass to the event listener.
   */
  addSelectorListener?: (event: string, selector: string, callback: EventListener) => void;
  /**
   * Smoothly fade an element out of view, then remove it.
   * @param element The element to fade out.
   * @param duration A duration for the effect in milliseconds.
   */
  fadeOut?: (element: HTMLElement, duration: number) => void;
  /**
   * Formats a given {@link timestamp} with the standard format
   * @param timestamp timestamp to format
   */
  formatTimestamp?: (timestamp: string | number | Date) => string;
  /**
   * Checks common modifier states on a given keyboard event
   * @param event 
   */
  getModifierState?: (event: KeyboardEvent | MouseEvent | JQuery.KeyboardEventBase) => boolean;
  /**
   * Is a given event target an HTMLElement?
   * @param target event target to check
   */
  isHTMLElement?: (target: EventTarget) => target is HTMLElement;
  /**
   * Sets visibility of an element or array of elements. Uses display: none so should work with screen readers.
   * @param elements An element or array of elements to set visibility for.
   * @param visible Whether or not the elements should be visible.
   */
  setVisible?: (elements: HTMLElement | HTMLElement[], visible: boolean) => void;
  /**
   * Registers a callback to run on class list change
   * @param selector CSS selector to watch for
   * @param callback callback to call on match
   */
  watchClass?: (selector: string, callback: ClassWatcherCallback) => void;
}

interface StripMarkdownOptions {
  /**
   * Whether to strip away the leading quote ("> content"), if any
   * @default false
   */
  removeLeadingQuote?: boolean
}

interface QPixelMD {
  /**
   * Inserts text around a given {@link $field}'s selection
   * @param $field field to insert text into
   * @param start text to insert at selection start
   * @param end text to insert at selection end, if any
   */
  insertIntoField?: ($field: JQuery<HTMLInputElement | HTMLTextAreaElement>, start: string, end?: string | null) => void;
  /**
   * Replace the selected text in an input field with a provided replacement.
   * @param $field the field in which to replace text
   * @param text the text with which to replace the selection
   */
  replaceSelection?: ($field: JQuery<HTMLInputElement | HTMLTextAreaElement>, text: string) => void;
  /**
   * Inserts text at a given {@link idx} in a given {@link str}
   * @param str text to insert into
   * @param idx position to insert at
   * @param insert text to insert
   */
  stringInsert?: (str: string, idx: number, insert: string) => string;
  /**
   * See [strip_markdown](app/helpers/application_helper.rb) application helper
   */
  stripMarkdown?: (content: string, options?: StripMarkdownOptions) => string;
}

interface QPixelStorageGetOptions {
  /**
   * Whether the value is supposed to be parsed after retrieval
   */
  parse?: boolean
}

interface QPixelStorage {
  /**
   * Storage prefix to avoid collisions
   */
  readonly prefix: string
  /**
   * Gets a value from storage by a given key
   * @param key key to get a value by
   * @param options optional configuration
   */
  get(key: string, options: Omit<QPixelStorageGetOptions, 'parse'> & { parse: true }): object | null;
  get(key: string, options: Omit<QPixelStorageGetOptions, 'parse'> & { parse: false }): string | null;
  get(key: string): string | null;
  get(key: string, options?: QPixelStorageGetOptions): unknown;
  /**
   * Removes a value from storage by a given key
   * @param key key to remove a value by
   */
  remove(key: string): this
  /**
   * Saves a given value to storage under a given key
   * @param key key to save the value under
   * @param value value to save (objects will be serialized)
   */
  set(key: string, value: unknown): this
}

type QPixelKeyboardState =
  | "home"
  | "goto"
  | "tools"
  | "goto/category-tags"
  | "goto/category-edits"
  | "goto/category"
  | "tools/vote";

type SelectedItemType = "link" | "post";

interface QPixelKeyboard {
  is_mod: boolean;
  state: QPixelKeyboardState;
  selectedItem: HTMLElement | null;
  selectedItemData?: {
    type: SelectedItemType;
    post_id: string;
  };
  user_id: number | null;

  categories: () => Record<string, string>;
  dialog: (...elements: (HTMLElement | string)[]) => void;
  dialogClose: () => void;
  updateSelected: () => void;
}

type QPixelNotification = {
  community_id: number,
  community_name: string,
  content: string,
  created_at: string,
  id: number,
  is_read: boolean,
  link: string,
  updated_at: string,
  user_id: number
}

type NotificationType = "warning" | "success" | "danger";

type QPixelPopupCallback = (ev: JQuery.ClickEvent, popup: QPixelPopup) => void

type QPixelPingablePopupCallback = (ev: JQuery.KeyUpEvent) => Promise<void>

declare class QPixelPopup {
  static destroyAll: () => void;
  static getPopup: (
    items: JQuery[],
    field: HTMLInputElement | HTMLTextAreaElement,
    callback: QPixelPopupCallback
  ) => QPixelPopup;
  static isSpecialKey: (keyCode: number) => boolean;

  constructor(
    items: JQuery[],
    field: HTMLInputElement | HTMLTextAreaElement,
    callback: QPixelPopupCallback
  );

  destroy: () => void;
  getActiveIdx: () => number | null;
  setActive: (index: number) => void;
  setCallback: (callback: QPixelPopupCallback) => void;
  getClickHandler: () => (ev: JQuery.Event) => void;
  getKeyHandler: () => (ev: JQuery.KeyboardEventBase) => void;
  updateItems: (items: JQuery[]) => void;
  updatePosition: () => void;
}

type QPixelSuccessResponseStatusJSON = 'success' | 'modified'

type QPixelFailedResponseStatusJSON = 'failed'

type QPixelResponseStatusJSON = QPixelSuccessResponseStatusJSON | QPixelFailedResponseStatusJSON

type QPixelBaseResponseJSON = {
  status: QPixelResponseStatusJSON
  message?: string
}

type QPixelSuccessResponseJSON = QPixelBaseResponseJSON & {
  status: QPixelSuccessResponseStatusJSON
}

type QPixelFailedResponseJSON = QPixelBaseResponseJSON & {
  errors?: string[]
}

type QPixelResponseJSON<
  Success extends object = object
> = (Success & QPixelSuccessResponseJSON) | QPixelFailedResponseJSON

type QPixelUploadResponseJSON = QPixelResponseJSON<{
  link: string
}>

type QPixelVoteResponseJSON = QPixelResponseJSON<{
  vote_id: number
  upvotes: number
  downvotes: number
  score: number
}>

type QPixelRetractVoteResponseJSON = QPixelResponseJSON<{
  score: number
  downvotes: number
  upvotes: number
}>

type QPixelComment = {
  id: number
  created_at: string
  updated_at: string
  post_id: number
  content: string
  deleted: boolean
  user_id: number
  community_id: number
  comment_thread_id: number
  has_reference: false
  reference_text: string | null
  references_comment_id: string | null
}

type QPixelFilterSource = 'any' | 'native' | 'imported'

type QPixelFilterStatus = 'any' | 'closed' | 'open'

type QPixelFilter = {
  exclude_tags: [string, number][]
  include_tags: [string, number][]
  max_answers: number | null
  max_score: number | null
  min_answers: number | null
  min_score: number | null
  source: QPixelFilterSource
  status: QPixelFilterStatus
  system: boolean
}

type QPixelSuggestedEditActionResult = {
  message?: string
  redirect_url?: string
  status: 'success' | 'error'
}

type QPixelTag = {
  community_id: number
  created_at: string
  excerpt: string
  id: number
  name: string
  parent_id: number | null
  tag_set_id: number
  tag_synonyms: QPixelTagSynonym[]
  updated_at: string
  wiki: string | null
  wiki_markdown: string
}

type QPixelTagSynonym = {
  name: string
}

type QPixelUser = {
  id: number
  is_standard: boolean
  is_moderator: boolean
  is_admin: boolean
  is_global_moderator: boolean
  is_global_admin: boolean
  se_acct_id: string | null
  trust_level: number
  username: string
}

type QPixelDraft = {
  body: string
  comment?: string
  excerpt?: string
  license?: string
  tag_name?: string
  tags?: string[]
  title?: string
}

type QPixelFlagData = {
  flag_type: number | null
  post_id: string
  post_type: 'Comment' | 'Post'
  reason?: string
}

interface GetThreadContentOptions {
  inline?: boolean,
  showDeleted?: boolean
}

type QPixelPostType = {
  id: number
  name: string
  description: string | null
  has_answers: boolean
  has_votes: boolean
  has_tags: boolean
  has_parent: boolean
  has_category: boolean
  has_license: boolean
  is_public_editable: boolean
  is_closeable: boolean
  is_top_level: boolean
  is_freely_editable: boolean
  icon_name: string | null
  has_reactions: boolean
  answer_type_id: number | null
  has_only_specific_reactions: boolean
}

interface QPixel {
  // constants

  /**
   * List of HTML tags allowed in posts, supplied by the server
   */
  readonly ALLOWED_POST_TAGS?: readonly string[]
  /**
   * List of attributes allowed on HTML tags in posts, supplied by the server
   */
  readonly ALLOWED_POST_ATTRS?: readonly string[]
  /**
   * Currently used locale (BCP 47 language tag), supplied by the server
   */
  readonly LOCALE?: string
  /**
   * Maximum file upload size (in bytes), supplied by the server
   */
  readonly MAX_UPLOAD_SIZE?: number

  // private properties
  _filters?: Record<string, QPixelFilter> | null;
  _pendingUser?: Promise<QPixelUser> | null;
  _popups?: Record<string, QPixelPopup>;
  _preferences?: UserPreferences | null;
  _user?: QPixelUser | null;

  // private methods

  /**
   * Call _fetchPreferences but only the first time to prevent redundant HTTP requests
   */
  _cachedFetchPreferences?: () => Promise<void>;

  /**
   * Update local variable _preferences and storage with an AJAX call for the user preferences
   */
  _fetchPreferences?: () => Promise<void>;

  /**
   * FIFO-style fetch wrapper for /users/me requests
   */
  _fetchUser?: () => Promise<QPixelUser | null>;

  /**
   * Get an object containing the current user's preferences. Loads, in order of precedence, from local variable,
   * {@link QPixelStorage}, or Redis via AJAX.
   * @returns user preferences or `null` on failure
   */
  _getPreferences?: () => Promise<UserPreferences | null>;

  /**
   * Get the key to use for storing user preferences in storage, to avoid conflating users
   * @returns string the storage key
   */
  _preferencesLocalStorageKey?: () => string;

  /**
   * Set local variable _preferences and storage to new preferences data
   * @param data an object, containing the new preferences data
   */
  _updatePreferencesLocally?: (data: UserPreferences) => void;

  // public methods

  /**
   * Add a button to the Markdown editor.
   * @param $buttonHtml the HTML content that the button should show - just text, if you like, or
   *                    something more complex if you want to.
   * @param shortName a short name for the action that will be used as the title and aria-label attributes.
   * @param callback a function that will be passed as the click event callback.
   */
  addEditorButton?: ($buttonHtml: JQuery.htmlString, shortName: string, callback: () => void) => void;

  /**
   * Add a validator that will be called before creating a post.
   * callback should take one parameter, the post text, and should return an array in
   * the following format:
   *
   * [
   *   true | false,  // is the post valid for this check?
   *   [
   *     { type: 'warning', message: 'warning message - will not block posting' },
   *     { type: 'error', message: 'error message - will block posting' }
   *   ]
   * ]
   */
  addPrePostValidation?: (callback: PostValidator) => void;

  /**
   * Create a notification popup - not an inbox notification.
   * @param type the type to apply to the popup - warning, danger, etc.
   * @param message the message to show
   */
  createNotification?: (type: NotificationType, message: string) => void;

  /**
   * Get the word in a string that the given position is in, and the position within that word.
   * @param splat an array, containing the string already split by however you define a "word"
   * @param posIdx the index to search for
   * @returns the word the given position is in, and the position within that word
   */
  currentCaretSequence?: (splat: string[], posIdx: number) => [string, number];
  /**
   * Fetches default user filter for a given category
   * @param categoryId id of the category to fetch
   */
  defaultFilter?: (categoryId: string) => Promise<string>;
  deleteFilter?: (name: string, system?: boolean) => Promise<void>;
  filters?: () => Promise<Record<string, QPixelFilter>>;

  /**
   * Get a list of supported canonical locales for {@link Intl.NumberFormat} based on {@link QPixel.LOCALE}.
   */
  supportedNumberLocales?: () => string[];

  /**
   * Format a given {@link value} into a human-friendly representation.
   * @param value value (in bytes) to format
   */
  numberToHumanSize?: (value: number) => string;

  /**
   * Get the absolute offset of an element.
   * @param element the element for which to find the offset.
   * @returns element offset information
   */
  offset?: (element: HTMLElement) => ElementOffset;

  /**
   * Get a single user preference by name.
   * @param name the name of the requested preference
   * @param community is the requested preference community-local (true), or network-wide (false)?
   * @returns the value of the requested preference
   */
  preference?: (name: string, community?: boolean) => Promise<string>;

  setFilter?: (name: string, filter: QPixelFilter, category: string, isDefault: boolean) => Promise<void>;

  /**
   * Set a user preference by name to the value provided.
   * @param name the name of the preference to set
   * @param value the value to set to - must respond to toString() for {@link QPixelStorage} and Redis
   * @param community is this preference community-local (true), or network-wide (false)?
   */
  setPreference?: (name: string, value: unknown, community?: boolean) => Promise<void>;

  /**
   * Get the user object for the current user.
   * @returns JSON object containing user details
   */
  user?: () => Promise<QPixelUser>;

  /**
   * Internal. Called just before a post is sent to the server to validate that it passes
   * all custom checks.
   */
  validatePost?: (postText: string) => [boolean, PostValidatorMessage[]];

  /**
   * Wrapper around {@link fetch} to ensure credentials, CSRF token, and X-Requested-With are always sent
   * @param uri target URI of the request
   * @param options options to pass to {@link fetch}
   */
  fetch?: (uri: string | URL, options?: RequestInit) => Promise<Response>

  /**
   * Send a request with JSON data, pre-authorized with QPixel credentials for the signed in user.
   * @param uri The URI to which to send the request.
   * @param data An object containing data to send as the request body. Must be acceptable by JSON.stringify.
   * @param options An optional {@link RequestInit} to override the defaults provided by this method. 
   * @returns The Response promise returned from {@link fetch}.
   */
  fetchJSON?: (uri: string, data: any, options?: RequestInit) => Promise<Response>;

  /**
   * @param uri The URI to which to send the request.
   * @param options An optional {@link RequestInit} to override the defaults provided by {@link fetchJSON}
   */
  getJSON?: (uri: string, options?: Omit<RequestInit, 'method'>) => Promise<Response>;

  /**
   * Attempts to get a JSON reprentation of a comment
   * @param id id of the comment to get
   */
  getComment?: (id: string) => Promise<QPixelComment>

  /**
   * Attempts to get a list of notifications for the current user
   */
  getNotifications?: () => Promise<QPixelNotification[]>

  /**
   * Attempts to dynamically load thread content
   * @param id id of the comment thread
   * @param options configuration options
   */
  getThreadContent?: (id: string, options?: GetThreadContentOptions) => Promise<string>

  /**
   * Attempts to dynamically load a list of comment threads for a given post
   * @param id id of the post to load
   */
  getThreadsListContent?: (id: string) => Promise<string>

  /**
   * Safely parses a JSON response from QPixel API
   * @param response API response to parse
   * @param errorMessage error to set on failure to parse
   */
  parseJSONResponse?: <T extends QPixelResponseJSON>(response: Response, errorMessage: string) => Promise<T>

  /**
   * Processes JSON responses from QPixel API
   * @param data parsed response JSON body from the API
   * @param onSuccess callback to call for successful requests
   * @param onFinally callback to call for all requests
   */
  handleJSONResponse?: <T extends QPixelResponseJSON>(data: T,
    onSuccess: (data: Extract<T, QPixelSuccessResponseJSON>) => void,
    onFinally?: (data: T) => void) => boolean

  /**
   * Attempts to archive a comment thread
   * @param id id of the thread to archive
   * @returns result of the operation
   */
  archiveThread?: (id: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to delete a comment
   * @param id id of the comment to delete
   * @returns result of the operation
   */
  deleteComment?: (id: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to delete a comment thread
   * @param id id of the thread to delete
   * @returns result of the operation
   */
  deleteThread?: (id: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to follow a comment thread
   * @param id id of the thread to follow
   * @returns result of the operation
   */
  followThread?: (id: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to unfollow a comment thread
   * @param id id of the thread to unfollow
   * @returns result of the operation
   */
  unfollowThread?: (id: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to start following comments on a given post
   * @param postId id of the post to follow comments on
   * @returns result of the operation
   */
  followComments?: (postId: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to delete a given post draft
   * @returns result of the operation
   */
  deleteDraft?: () => Promise<QPixelResponseJSON>

  /**
   * Attempts to save a post draft
   * @param draft draft to save
   * @returns result of the operation
   */
  saveDraft?: (draft: QPixelDraft) => Promise<QPixelResponseJSON>

  /**
   * Attempts to undelete a comment
   * @param id id of the comment to undelete
   * @returns result of the operation
   */
  undeleteComment?: (id: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to stop following comments on a given post
   * @param postId id of the post to stop following comments on
   * @returns result of the operation
   */
  unfollowComments?: (postId: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to lock a comment thread
   * @param id id of the comment thread to lock
   * @param duration how long should the thread be locked for, in days
   * @returns result of the operation
   */
  lockThread?: (id: string, duration?: number) => Promise<QPixelResponseJSON>

  /**
   * Attempts to rename a tag
   * @param categoryId id of the category to rename the tag in
   * @param tagId id of the tag to rename
   * @param name new tag name
   * @returns result of the operation
   */
  renameTag?: (categoryId: string, tagId: string, name: string) => Promise<QPixelResponseJSON>

  /**
   * Attempts to retract a vote
   * @param id id of the vote to retract
   * @returns result of the operation
   */
  retractVote?: (id: string) => Promise<QPixelRetractVoteResponseJSON>

  /**
   * Attempts to raise a flag
   * @param flag new flag data
   * @returns result of the operation
   */
  flag?: (flag: QPixelFlagData) => Promise<QPixelResponseJSON>

  /**
   * Attempts to vote on a given post
   * @param postId id of the post to vote on
   * @param voteType type of the vote
   * @returns result of the operation
   */
  vote?: (postId: string, voteType: string) => Promise<QPixelVoteResponseJSON>

  /**
   * @param url upload endpoint URL (differs between routes)
   * @param form upload form to get the file from
   */
  upload?: (url: string, form: HTMLFormElement) => Promise<QPixelUploadResponseJSON>

  // qpixel_dom
  DOM?: QPixelDOM;
  // qpixel keyboard actions
  Keyboard?: QPixelKeyboard;
  // qpixel Markdown
  MD?: QPixelMD;
  // qpixel popups
  Popup?: typeof QPixelPopup;
  // qpixel storage management
  Storage?: QPixelStorage;
  // Stripe integration, TODO: types
  stripe?: any;
}

// Chartkick, TODO: types
declare var Chartkick: any;
// Highlight.js lib, TODO: types
declare var hljs: any;
// MathJax lib, TODO: types
declare var MathJax: any;
// Moment.js lib
declare var moment: typeof import('moment');
// DOMPurify lib, TODO: types
declare var DOMPurify: any;
// Sefaria Linker (no known types), see https://developers.sefaria.org/docs/linker-v2
declare var sefaria: {
  link: (options?: {
    contentLang?: 'bilingual' | 'english' | 'hebrew',
    dynamic?: boolean,
    excludeFromLinking?: string,
    excludeFromTracking?: string,
    hidePopupsOnMobile?: boolean,
    interfaceLang?: 'english' | 'hebrew',
    mode?: 'link' | 'popup-click',
    parenthesesOnly?: boolean,
    popupStyles?: Record<string, string>,
    selector?: string,
    quotationOnly?: boolean
  }) => void
} | undefined;
declare var QPixel: QPixel;

declare var getCaretCoordinates: (
  element: any,
  position: any,
  options: any
) => {
  top: number;
  left: number;
  height: number;
};

interface Window {
  mozInnerScreenX?: number;

  // MarkdownIt lib, TODO: types
  converter?: any;
  markdownit?: (...args: any[]) => any;
  markdownitFootnote?: (...args: any[]) => any;
}