123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- var TYPE = require('../../tokenizer').TYPE;
- var IDENTIFIER = TYPE.Identifier;
- var STRING = TYPE.String;
- var DOLLARSIGN = TYPE.DollarSign;
- var ASTERISK = TYPE.Asterisk;
- var COLON = TYPE.Colon;
- var EQUALSSIGN = TYPE.EqualsSign;
- var LEFTSQUAREBRACKET = TYPE.LeftSquareBracket;
- var RIGHTSQUAREBRACKET = TYPE.RightSquareBracket;
- var CIRCUMFLEXACCENT = TYPE.CircumflexAccent;
- var VERTICALLINE = TYPE.VerticalLine;
- var TILDE = TYPE.Tilde;
- function getAttributeName() {
- if (this.scanner.eof) {
- this.scanner.error('Unexpected end of input');
- }
- var start = this.scanner.tokenStart;
- var expectIdentifier = false;
- var checkColon = true;
- if (this.scanner.tokenType === ASTERISK) {
- expectIdentifier = true;
- checkColon = false;
- this.scanner.next();
- } else if (this.scanner.tokenType !== VERTICALLINE) {
- this.scanner.eat(IDENTIFIER);
- }
- if (this.scanner.tokenType === VERTICALLINE) {
- if (this.scanner.lookupType(1) !== EQUALSSIGN) {
- this.scanner.next();
- this.scanner.eat(IDENTIFIER);
- } else if (expectIdentifier) {
- this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
- }
- } else if (expectIdentifier) {
- this.scanner.error('Vertical line is expected');
- }
- if (checkColon && this.scanner.tokenType === COLON) {
- this.scanner.next();
- this.scanner.eat(IDENTIFIER);
- }
- return {
- type: 'Identifier',
- loc: this.getLocation(start, this.scanner.tokenStart),
- name: this.scanner.substrToCursor(start)
- };
- }
- function getOperator() {
- var start = this.scanner.tokenStart;
- var tokenType = this.scanner.tokenType;
- if (tokenType !== EQUALSSIGN && // =
- tokenType !== TILDE && // ~=
- tokenType !== CIRCUMFLEXACCENT && // ^=
- tokenType !== DOLLARSIGN && // $=
- tokenType !== ASTERISK && // *=
- tokenType !== VERTICALLINE // |=
- ) {
- this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
- }
- if (tokenType === EQUALSSIGN) {
- this.scanner.next();
- } else {
- this.scanner.next();
- this.scanner.eat(EQUALSSIGN);
- }
- return this.scanner.substrToCursor(start);
- }
- // '[' S* attrib_name ']'
- // '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']'
- module.exports = {
- name: 'AttributeSelector',
- structure: {
- name: 'Identifier',
- matcher: [String, null],
- value: ['String', 'Identifier', null],
- flags: [String, null]
- },
- parse: function() {
- var start = this.scanner.tokenStart;
- var name;
- var matcher = null;
- var value = null;
- var flags = null;
- this.scanner.eat(LEFTSQUAREBRACKET);
- this.scanner.skipSC();
- name = getAttributeName.call(this);
- this.scanner.skipSC();
- if (this.scanner.tokenType !== RIGHTSQUAREBRACKET) {
- // avoid case `[name i]`
- if (this.scanner.tokenType !== IDENTIFIER) {
- matcher = getOperator.call(this);
- this.scanner.skipSC();
- value = this.scanner.tokenType === STRING
- ? this.String()
- : this.Identifier();
- this.scanner.skipSC();
- }
- // attribute flags
- if (this.scanner.tokenType === IDENTIFIER) {
- flags = this.scanner.getTokenValue();
- this.scanner.next();
- this.scanner.skipSC();
- }
- }
- this.scanner.eat(RIGHTSQUAREBRACKET);
- return {
- type: 'AttributeSelector',
- loc: this.getLocation(start, this.scanner.tokenStart),
- name: name,
- matcher: matcher,
- value: value,
- flags: flags
- };
- },
- generate: function(node) {
- var flagsPrefix = ' ';
- this.chunk('[');
- this.node(node.name);
- if (node.matcher !== null) {
- this.chunk(node.matcher);
- if (node.value !== null) {
- this.node(node.value);
- // space between string and flags is not required
- if (node.value.type === 'String') {
- flagsPrefix = '';
- }
- }
- }
- if (node.flags !== null) {
- this.chunk(flagsPrefix);
- this.chunk(node.flags);
- }
- this.chunk(']');
- }
- };
|