import Immutable from "immutable" ; import is from "is" ; import Token from "./token" ; const inherits = require ( "util" ) . inherits ; const RuleRecord = Immutable . Record ( { type : new String ( ) , listeners : Immutable . Map ( ) , } ) ; function Rule ( type ? ) { if ( ! ( this instanceof Rule ) ) { return new Rule ( type ) ; } RuleRecord . call ( this , { type : type , } ) ; } inherits ( Rule , RuleRecord ) ; Rule . prototype . getType = function ( ) { return this . get ( "type" ) ; } ; Rule . prototype . getListeners = function ( ) { return this . get ( "listeners" ) ; } ; param { string } key param { Function } fn return { Rule } Rule . prototype . on = function ( key , fn ) { let listeners = this . getListeners ( ) ; let fns = listeners . get ( key ) || Immutable . List ( ) ; fns = fns . push ( fn ) ; listeners = listeners . set ( key , fns ) ; return this . set ( "listeners" , listeners ) ; } ; param { String | Function } fn return { Rule } Rule . prototype . toText = function ( fn ) { if ( is . string ( fn ) ) { const tpl = fn ; fn = function ( state , token ) { return tpl . replace ( "%s" , ( ) => { return state . render ( token ) ; } ) ; } ; } return this . on ( "text" , fn ) ; } ; param { Function } fn return { Rule } Rule . prototype . match = function ( fn ) { return this . on ( "match" , fn ) ; } ; param { RegExp } re param { Funciton } propsFn return { Rule } Rule . prototype . regExp = function ( re , propsFn ) { return this . match ( ( state , text ) => { let block = { } ; const match = re . exec ( text ) ; if ( ! match ) { return null ; } if ( propsFn ) { block = propsFn . call ( null , state , match ) ; } if ( ! block ) { return null ; } else if ( block instanceof Token ) { return block ; } else if ( is . array ( block ) ) { return block ; } block . raw = is . undefined ( block . raw ) ? match [ 0 ] : block . raw ; return block ; } ) ; } ; param { string } key return { Mixed } Rule . prototype . emit = function ( key ) { const args = Array . prototype . slice . call ( arguments , 1 ) ; const listeners = this . getListeners ( ) ; const fns = listeners . get ( key ) || Immutable . List ( ) ; return fns . reduce ( ( result , fn ) => { if ( result ) return result ; return fn . apply ( null , args ) ; } , null ) ; } ; param { ParsingState } state param { string } text return { List < Token > } Rule . prototype . onText = function ( state , text ) { return this . emit ( "match" , state , text ) ; } ; param { RenderingState } state param { Token } token return { string } Rule . prototype . onToken = function ( state , text ) { return this . emit ( "text" , state , text ) ; } ; export default Rule ;