<commit_before>import Attributor from './attributor/attributor';
import { Blot, Formattable } from './blot/abstract/blot';


export interface BlotConstructor {
  blotName: string;
  new(node: Node, value?: any): Blot;
  create(value?): Node;
}

export class ParchmentError extends Error {
  message: string;
  name: string;
  stack: string;

  constructor(message) {
    message = '[Parchment] ' + message;
    super(message);
    this.message = message;
    this.name = (<any>this.constructor).name;
  }
}

let attributes: { [key: string]: Attributor } = {};
let classes: { [key: string]: BlotConstructor } = {};
let tags: { [key: string]: BlotConstructor } = {};
let types: { [key: string]: Attributor | BlotConstructor } = {};

export const DATA_KEY = '__blot';

export enum Scope {
  TYPE = (1 << 2) - 1,          // 0011 Lower two bits
  LEVEL = ((1 << 2) - 1) << 2,  // 1100 Higher two bits

  ATTRIBUTE = (1 << 0) | LEVEL, // 1101
  BLOT = (1 << 1) | LEVEL,      // 1110
  INLINE = (1 << 2) | TYPE,     // 0111
  BLOCK = (1 << 3) | TYPE,      // 1011

  BLOCK_BLOT = BLOCK & BLOT,              // 1010
  INLINE_BLOT = INLINE & BLOT,            // 0110
  BLOCK_ATTRIBUTE = BLOCK & ATTRIBUTE,    // 1001
  INLINE_ATTRIBUTE = INLINE & ATTRIBUTE,  // 0101

  ANY = TYPE | LEVEL
};


export function create(input: Node | string | Scope, value?: any): Blot {
  let match = query(input);
  if (match == null) {
    throw new ParchmentError(`Unable to create ${input} blot`);
  }
  let BlotClass = <BlotConstructor>match;
  let node = input instanceof Node ? input : BlotClass.create(value);
  return new BlotClass(node, value);
}

export function find(node: Node, bubble: boolean = false): Blot {
  if (node == null) return null;
  if (node[DATA_KEY] != null) return node[DATA_KEY].blot;
  if (bubble) return find(node.parentNode, bubble);
  return null;
}

export function query(query: string | Node | Scope, scope: Scope = Scope.ANY): Attributor | BlotConstructor {
  let match;
  if (typeof query === 'string') {
    match = types[query] || attributes[query];
  } else if (query instanceof Text) {
    match = types['text'];
  } else if (typeof query === 'number') {
    if (query & Scope.LEVEL & Scope.BLOCK) {<commit_msg>IE Edge instanceof Text does not work<commit_after>import Attributor from './attributor/attributor';
import { Blot, Formattable } from './blot/abstract/blot';


export interface BlotConstructor {
  blotName: string;
  new(node: Node, value?: any): Blot;
  create(value?): Node;
}

export class ParchmentError extends Error {
  message: string;
  name: string;
  stack: string;

  constructor(message) {
    message = '[Parchment] ' + message;
    super(message);
    this.message = message;
    this.name = (<any>this.constructor).name;
  }
}

let attributes: { [key: string]: Attributor } = {};
let classes: { [key: string]: BlotConstructor } = {};
let tags: { [key: string]: BlotConstructor } = {};
let types: { [key: string]: Attributor | BlotConstructor } = {};

export const DATA_KEY = '__blot';

export enum Scope {
  TYPE = (1 << 2) - 1,          // 0011 Lower two bits
  LEVEL = ((1 << 2) - 1) << 2,  // 1100 Higher two bits

  ATTRIBUTE = (1 << 0) | LEVEL, // 1101
  BLOT = (1 << 1) | LEVEL,      // 1110
  INLINE = (1 << 2) | TYPE,     // 0111
  BLOCK = (1 << 3) | TYPE,      // 1011

  BLOCK_BLOT = BLOCK & BLOT,              // 1010
  INLINE_BLOT = INLINE & BLOT,            // 0110
  BLOCK_ATTRIBUTE = BLOCK & ATTRIBUTE,    // 1001
  INLINE_ATTRIBUTE = INLINE & ATTRIBUTE,  // 0101

  ANY = TYPE | LEVEL
};


export function create(input: Node | string | Scope, value?: any): Blot {
  let match = query(input);
  if (match == null) {
    throw new ParchmentError(`Unable to create ${input} blot`);
  }
  let BlotClass = <BlotConstructor>match;
  let node = (input instanceof Node || input['nodeType'] === Node.TEXT_NODE) ?
             input :
             BlotClass.create(value);
  return new BlotClass(<Node>node, value);
}

export function find(node: Node, bubble: boolean = false): Blot {
  if (node == null) return null;
  if (node[DATA_KEY] != null) return node[DATA_KEY].blot;
  if (bubble) return find(node.parentNode, bubble);
  return null;
}

export function query(query: string | Node | Scope, scope: Scope = Scope.ANY): Attributor | BlotConstructor {
  let match;
  if (typeof query === 'string') {
    match = types[query] || attributes[query];
  } else if (query instanceof Text || query['nodeType'] === Node.TEXT_NODE) {
    match = types['text'];
  } else if (typeof query === 'number') {
    if (query & Scope.LEVEL & Scope.BLOCK) {
{'fraction_non_alphanumeric': 0.1503267973856209, 'fraction_numerical': 0.023965141612200435, 'mean_word_length': 3.1547511312217194, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1823985', 'n_tokens_mistral': 1642, 'n_tokens_neox': 1516, 'n_words': 454}