This library deals with parsing and representing CSS selectors. It uses a parser derived from selecthx, although it is greatly simplified and slightly more flexible.
The library is quite thoroughly tested and has only tink_core
as a dependency.
The data representation is pretty straight forward and is completely described in the Selector
module.
typedef Selector<A> = Array<SelectorOption<A>>;
typedef SelectorOption<A> = Array<SelectorPart<A>>;
typedef SelectorPart<A> = {
universal:Bool,
?id:String,
?tag:String,
classes:Array<String>,
attrs:Array<AttrFilter>,
pseudos:Array<A>,
?combinator:Combinator,
}
typedef AttrFilter = {
var name:String;
var value:String;
var op:AttrOperator;
}
enum Pseudo {
Not(s:Selector<Pseudo>);
Nth(matchType:Bool, factor:Int, offset:Int, backward:Bool);
}
enum AttrOperator {
None;
Exactly;
WhitespaceSeperated;
HyphenSeparated;
BeginsWith;
EndsWith;
Contains;
}
enum Combinator {
Descendant;
Child;
AdjacentSibling;
GeneralSibling;
}
You may note that Selector
has a type parameter. Normally, you would just use Selector<Pseudo>
but since CSS lends itself well to applying rules to any kind of hierarchies, you may want to spin off a CSS flavour with other pseudo selectors - arguably the easiest way to add more functionality without interfering with standard syntax.
For parsing, the library provides the following API:
class Parser {
static function parse(source:String, ?pos:Pos):Outcome<Selector<Pseudo>, Error>
static function parseWith<A>(source:String, pseudos:Plugin<A>, ?pos:Pos):Outcome<Selector<A>, Error>
}
typedef Plugin<A> = {
function not(s:Selector<A>):Outcome<A, String>;
function nth(matchType:Bool, factor:Int, offset:Int, backward:Bool):Outcome<A, String>;
function custom(name:String, args:Array<String>):Outcome<A, String>;
}
To parse with your own pseudo selector rules, you would use parseWith
and supply an adequate Plugin
. That is also how parse
itself is implemented in fact.