Skip to content

BlackGlory/match

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

match

A module for matching elements from pages.

Install

npm install --save @blackglory/match
# or
yarn add @blackglory/match

Usage

import { matchElement, element, css, childNodes, textNode, children, multiple } from '@blackglory/match'

const result = matchElement(node
, element(
    css`header`
  , childNodes(
      textNode`heading`()
    )
  )
, element(
    css`section`
  , children(
      multiple([1, Infinity], element(
        css`p`
      , childNodes(
          textNode`paragraph`()
        )
      ))
    )
  )
)
// { heading: Text, paragraph: [ Text, Text ] }

API

interface IContext {
  readonly document: Document
  readonly next: (node: Node, distance?: number) => Node | undefined
  readonly collection: {
    [name: string]: Node | Node[]
  }
}

interface IReadonlyContext {
  readonly document: Document
  readonly next: (node: Node, distance?: number) => Node | undefined
  readonly collection: {
    readonly [name: string]: Node | Node[]
  }
}

type IMatcher<T extends Node> =
| ITerminalMatcher<T>
| INestedMatcher<T>
| ISkipMatcher<T>

type ITerminalMatcher<T extends Node> = (
  this: IReadonlyContext<T>
, node: T
) => boolean

type INestedMatcher<T extends Node> = (
  this: IReadonlyContext<T>
, node: T
) => boolean

type ISkipMatcher<T extends Node> = (
  this: IReadonlyContext<T>
, node: T
) => number | false

match

function match(
  this: void | Document
, node: Node
, ...matchers: Array<IMatcher<Node>>
): { [name: string]: Node | Node[] } | null

matchElement

function matchElement(
  this: void | Document
, element: Element
, ...matchers: Array<IMatcher<Element>>
): { [name: string]: Node | Node[] } | null

Matchers

anyOf

function anyOf<T extends Node>(
  ...matchers: [
    INestedMatcher<T> | ITerminalMatcher<T>
  , INestedMatcher<T> | ITerminalMatcher<T>
  , ...Array<INestedMatcher<T> | ITerminalMatcher<T>>
  ]
): INestedMatcher<T>

childNodes

function childNodes(...matchers: Array<IMatcher<Node>>): INestedMatcher<Node>

children

function children(...matchers: Array<IMatcher<Element>>): INestedMatcher<Element>

css

function css(strings: TemplateStringsArray, ...values: string[]): ITerminalMatcher<Element>
function css(selector: string): ITerminalMatcher<Element>

element

function element(
  strings: TemplateStringsArray
, ...values: string[]
): (...matchers: Array<INestedMatcher<Element> | ITerminalMatcher<Element>>) => INestedMatcher<Node>
function element(name: string, ...matchers: Array<INestedMatcher<Element>>):
  INestedMatcher<Node>
function element(...matchers: Array<INestedMatcher<Element>>):
  INestedMatcher<Node>

multiple

interface IMultipleOptions {
  greedy: boolean
}

function multiple<T extends Node>(
  range: [min: number, max: number]
, matcher: INestedMatcher<T> | ITerminalMatcher<T>
, options:  IMultipleOptions = { greedy: true }
): ISkipMatcher<T>

node

function node(
  strings: TemplateStringsArray
, ...values: string[]
): (...matchers: Array<INestedMatcher<Node> | ITerminalMatcher<Node>>) => INestedMatcher<Node>
function node(
  name: string
, ...matchers: Array<INestedMatcher<Node> | ITerminalMatcher<Node>>
): INestedMatcher<Node>
function node(
  ...matchers: Array<INestedMatcher<Node> | ITerminalMatcher<Node>>
): INestedMatcher<Node>

optional

function optional<T extends Node>(
  matcher: INestedMatcher<T> | ITerminalMatcher<T>
): ISkipMatcher<T>

repeat

function repeat<T extends Node>(
  times: number
, matcher: INestedMatcher<T> | ITerminalMatcher<T>
): ISkipMatcher<T>

tap

function tap<T extends Node, U extends ReturnType<IMatcher<any>>>(
  matcher: (this: IReadonlyContext, node: T) => U
, callback: (value: U) => void
): (this: IReadonlyContext, node: T) => U

textContentEquals

interface ITextContentEqualsOptions {
  caseSensitive?: boolean
  trim?: boolean
}

function textContentEquals(
  text: string
, {
    caseSensitive = true
  , trim = false
  }: ITextContentEqualsOptions = {}
): ITerminalMatcher<Node>

textContentIncludes

interface ITextContentIncludesOptions {
  caseSensitive?: boolean
  trim?: boolean
}

export function textContentIncludes(
  searchString: string
, {
    caseSensitive = true
  , trim = false
  }: ITextContentIncludesOptions = {}
): ITerminalMatcher<Node>

textContentMatches

interface ITextContentMatchesOptions {
  trim?: boolean
}

export function textContentMatches(
  pattern: RegExp
, { trim = false }: ITextContentMatchesOptions = {}
): ITerminalMatcher<Node>

textNode

function textNode(
  strings: TemplateStringsArray
, ...values: string[]
): (...matchers: Array<ITerminalMatcher<Node>>) => INestedMatcher<Node>
function textNode(
  name: string
, ...matchers: Array<ITerminalMatcher<Node>>
): INestedMatcher<Node>
function textNode(
  ...matchers: Array<ITerminalMatcher<Node>>
): INestedMatcher<Node>

xpath

function xpath(
  strings: TemplateStringsArray
, ...values: string[]
): ITerminalMatcher<Node>
function xpath(experssion: string): ITerminalMatcher<Node>