Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

css selector engine for React elements and components

NotificationsYou must be signed in to change notification settings

jquense/bill

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sort of likeSizzle for React,bill isa set of tools for matching React Element and Component trees against CSS selectors.bill is meant to be asubstrate library for building more interesting and user friendly testing utilities. It probably shouldn'tbe used as a standalone tool.

import{querySelectorAll}from'bill';letmatches=querySelectorAll('div li.foo',<div><List><liclassName='foo'>John</li><li>Betty</li></List></div>)matches.length// 1matches[0].element// ReactElement{ type: 'li', props: { className: 'foo' }}

For selecting non string values, like custom Component types, you can use atagged template strings

import{querySelectorAll,selectorass}from'bill';letmin=5;letmatches=querySelectorAll(s`div >${List}, li[min=${min}]`,<div><List><limin={min}>John</li><li>Betty</li></List></div>)matches.length// 2matches[0].element// { type: List, props }

React Compatibility

WARNING: mising module 'react/lib/ReactDOMComponentTree'

bill supports the latest React and back to v0.13.0, because a library like this involves the use of private API's, maintaining support across major versions of React isharder than normal. In particular we need to do dynamic requires to internal apis, which makes bundlers like Webpack warning about missing modules, and bundling with a less smart bundler hard.

Don't worry though they are missing because the version of React you are using doesn't have them, and thats ok, bill knows how todo its work on each supported version.

Supported

  • id:#foo
  • classes:.foo
  • attributes:div[propName="hi"] ordiv[boolProp]
  • >: direct descendentdiv > .foo
  • +: adjacent sibling selector
  • ~: general sibling selector
  • :has(): parent selectordiv:has(a.foo)
  • :not(): negation
  • :first-child
  • :last-child
  • :text matches "text" (renderable) nodes, which may be a non string value (like a number)
  • :dom matches only DOM components
  • :composite matches composite (user defined) components

Not supported

  • other pseudo selectors
  • non string interpolations for anything other than "tag" or prop values

API

Node

Nodes are a light object abstraction over both instances and elements that allow for a commonmatching and traversal API between the distinct types of React objects.The interface is similar to a traditional DOM node.

Mostbill methods that accept elements or instances will also accept a node,allowing you to use the return values of the methods directly with other methods.

Node :{nodeType:NODE_TYPE,element:ReactElement,instance:ReactComponent|HTMLElement,privateInstance:ReactPrivateInstance,nextSibling:Node,prevSibling:Node,parentNode:Node,children:Array<Node>,findAll:(test(node)=>bool,includeSelf? :bool)=>array<Node>}

Their is a caveat to thepublicInstance property, when it comes to stateless functional components. Insteadof returningnull as React would,bill returns the instance of the internal wrapper component. This is to allow,potential chaining and also retrieval of the underlying DOM node if necessary (as in the example above).

Note: Nodes only have instances when matching against arendered component tree

querySelectorAll(selector, subject: Element|Instance|Node) -> Array<Node>

querySelectorAll() traverses a react element or instance tree searching for nodes that match the provided selector.As the name suggests it's analogous todocument.querySelectorAll. The return valueis anarray of Nodes.

letmatches;letelements=(<div><List><liclassName='foo'>John</li><li>Betty</li></List></div>)// find elements in the above element descriptionmatches=bill.querySelectorAll('div li.foo',elements)// "John"lettextContent=matches.reduce((str,node)=>str+node.element.props.children,'')// or search a rendered hierarchymatches=bill.querySelectorAll('div li.foo',ReactDOM.render(elements))letdomNodes=matches.map(node=>ReactDOM.findDOMNode(node.instance))

matches(selector, subject: Element|Instance|Node) -> bool

Analogous to the DOMelement.matches method,matches returns true if a give element, instance or node is matchedby the providedselector.

letmatches;letelements=(<div><List><liclassName='foo'>John</li><li>Betty</li></List></div>)letjohnItem=bill.querySelectorAll('div li',elements).filter(node=>bill.matches('.foo',node))// or search a rendered hierarchyletbettyItem=bill.querySelectorAll('div li.foo',ReactDOM.render(elements)).filter(node=>bill.matches(':not(.foo)',node))

selector() -> Selector

A function used for tagged template strings,

You really only need to use theselector function when you want to write a selector matching exact prop values or acomposite type.

selector`div >${List}[length=${5}]`

findAll(subject: Element|Instance|Node, test: (node: Node)=> bool, includeSelf? : bool) -> Array

A tree traversal utility function for finding nodes that returntrue from thetestFunction. findAllis similar toReactTestUtils.findAllInRenderedTree, but more robust and works on both elements and instance trees.

import{findAll,NODE_TYPES}from'bill';letfound=findAll(elements,function(node){returnnode.nodeType===NODE_TYPES.COMPOSITE})

compile(selector) => (node: Node) => bool

Compiles a selector string into a function that matches nodes.

registerPseudo(pseudoSelector, handlePseudo: (selector) => (node: Node) => bool)

Registers a new pseudo selector with the compiler. The second parameter is a function that will be calledwith the pseudo selector's argument (if it exists). The handler function should return a function that matchesa node.

// A simple `:text(foo)` pseudo selectorbill.registerPseudo('text',function(value){returnfunction(node){returnnode.children.filter(n=>n.nodeType===NODE_TYPES.TEXT).every(node=>node.element===value)}})letmatches=bill.querySelectorAll('li:text(john)',<ul><li>betsy</li><li>john</li><li>yolanda</li></ul>)matches[0].instance// <li class='bar'>john</li>

For pseudoSelectors whose inner argument is a selector, you can compile itto a test function withbill.compile.

// We want to test if an element has a sibling that matches// a selector e.g. :nextSibling(.foo)bill.registerPseudo('nextSibling',function(selector){letmatcher=bill.compile(selector);returnfunction(node){node=node.nextSiblingreturn!!node&&matcher(node)}})letmatches=bill.querySelectorAll('li:nextSibling(li.baz)',<ul><liclassName='foo'>1</li><liclassName='bar'>2</li><liclassName='baz'>3</li></ul>)matches[0].instance// <li class='bar'>2</li>

registerNesting(nestingCombinator, handleNesting: (matcher: function) => (node: Node) => bool)

Similar toregisterPseudo you can also register new combinator selectors (*, >, ~, +) using the same pattern.The handler function is called with thecompiled selector segment.

Note: remember that selectors are matchedright-to-left so the logic is generally reversed from what youmight expect.

// lets implement the same previous sibling selector as above// but with a nesting selector.bill.registerNesting('!',test=>node=>{node=node.nextSiblingreturn!!(node&&test(node))})letmatches=bill.querySelectorAll('li.baz ! li',<ul><liclassName='foo'>1</li><liclassName='bar'>2</li><liclassName='baz'>3</li></ul>)matches[0].instance// <li class='bar'>2</li>

NODE_TYPES Object

Set of constants that correspond toNode.nodeType. Useful for filtering out types of nodes while traversing a tree.

  • NODE_TYPES.COMPOSITE
  • NODE_TYPES.DOM
  • NODE_TYPES.TEXT

isNode() -> boolean

Determine if an object is a Node object.

About

css selector engine for React elements and components

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp