2015-04-19 21:32:35 +00:00
// Charset nodes are used for `[abc1-9]` regular expression syntax. It is
// rendered as a labeled box with each literal, escape, and range rendering
// handled by the nested node(s).
2014-12-20 15:25:32 +00:00
import util from '../../util.js' ;
2014-12-03 02:02:48 +00:00
import _ from 'lodash' ;
2015-04-19 21:32:35 +00:00
2014-12-17 16:53:04 +00:00
export default {
2014-12-07 22:38:24 +00:00
type : 'charset' ,
2014-12-17 21:04:55 +00:00
definedProperties : {
2015-04-19 21:32:35 +00:00
// Default anchor is overridden to move it down so that it connects at the
// middle of the box that wraps all of the charset parts, instead of the
// middle of the container, which would take the label into account.
2014-12-17 21:04:55 +00:00
_anchor : {
get : function ( ) {
2015-04-16 21:13:12 +00:00
var matrix = this . transform ( ) . localMatrix ;
2014-12-17 21:04:55 +00:00
return {
ay : matrix . y ( 0 , this . partContainer . getBBox ( ) . cy )
} ;
}
}
} ,
2015-04-19 21:32:35 +00:00
// Renders the charset into the currently set container.
2014-12-11 00:01:57 +00:00
_render ( ) {
2014-12-15 00:08:14 +00:00
this . partContainer = this . container . group ( ) ;
2014-12-07 22:38:24 +00:00
2015-04-19 21:32:35 +00:00
// Renders each part of the charset into the part container.
2015-03-14 21:11:14 +00:00
return Promise . all ( _ . map ( this . elements , part => {
2014-12-15 00:08:14 +00:00
return part . render ( this . partContainer . group ( ) ) ;
2014-12-16 03:00:24 +00:00
} ) )
. then ( ( ) => {
2015-04-19 21:32:35 +00:00
// Space the parts of the charset vertically in the part container.
2014-12-20 15:25:32 +00:00
util . spaceVertically ( this . elements , {
2014-12-13 17:55:03 +00:00
padding : 5
} ) ;
2014-12-07 22:38:24 +00:00
2015-04-19 21:32:35 +00:00
// Label the part container.
2014-12-22 15:57:16 +00:00
return this . renderLabeledBox ( this . label , this . partContainer , {
2014-12-13 17:55:03 +00:00
padding : 5
} ) ;
2014-12-16 03:00:24 +00:00
} ) ;
2014-12-07 22:38:24 +00:00
} ,
2014-12-17 19:44:48 +00:00
setup ( ) {
2015-04-19 21:32:35 +00:00
// The label for the charset will be:
// - "One of:" for charsets of the form: `[abc]`.
// - "None of:" for charsets of the form: `[^abc]`.
2014-12-22 15:57:16 +00:00
this . label = ( this . properties . invert . textValue === '^' ) ? 'None of:' : 'One of:' ;
2015-04-19 21:32:35 +00:00
// Removes any duplicate parts from the charset. This is based on the type
// and text value of the part, so `[aa]` will have only one item, but
// `[a\x61]` will contain two since the first matches "a" and the second
// matches 0x61 (even though both are an "a").
2014-12-17 19:44:48 +00:00
this . elements = _ . unique ( this . properties . parts . elements , part => {
2015-04-19 20:45:06 +00:00
return ` ${ part . type } : ${ part . textValue } ` ;
2014-12-17 19:44:48 +00:00
} ) ;
2014-12-22 21:57:30 +00:00
2015-04-19 21:32:35 +00:00
// Include a warning for charsets that attempt to match `\c` followed by
// any character other than A-Z (case insensitive). Charsets like `[\c@]`
// behave differently in different browsers. Some match the character
// reference by the control charater escape, others match "\", "c", or "@",
// and some do not appear to match anything.
2014-12-22 21:57:30 +00:00
if ( this . textValue . match ( /\\c[^a-zA-Z]/ ) ) {
this . state . warnings . push ( ` The character set " ${ this . textValue } " contains the \\ c escape followed by a character other than A-Z. This can lead to different behavior depending on browser. The representation here is the most common interpretation. ` ) ;
}
2014-12-07 22:38:24 +00:00
}
2014-12-22 21:57:30 +00:00
}