@@ -11,7 +11,6 @@ import Universal from './selectors/universal';
1111import Combinator from './selectors/combinator' ;
1212import Nesting from './selectors/nesting' ;
1313
14- import sortAsc from './sortAscending' ;
1514import tokenize , { FIELDS as TOKEN } from './tokenize' ;
1615
1716import * as tokens from './tokenTypes' ;
@@ -95,23 +94,6 @@ function unescapeProp (node, prop) {
9594 return node ;
9695}
9796
98- function indexesOf ( array , item ) {
99- let i = - 1 ;
100- const indexes = [ ] ;
101-
102- while ( ( i = array . indexOf ( item , i + 1 ) ) !== - 1 ) {
103- indexes . push ( i ) ;
104- }
105-
106- return indexes ;
107- }
108-
109- function uniqs ( ) {
110- const list = Array . prototype . concat . apply ( [ ] , arguments ) ;
111-
112- return list . filter ( ( item , i ) => i === list . indexOf ( item ) ) ;
113- }
114-
11597export default class Parser {
11698 constructor ( rule , options = { } ) {
11799 this . rule = rule ;
@@ -818,74 +800,94 @@ export default class Parser {
818800 }
819801
820802 splitWord ( namespace , firstCallback ) {
803+ // Collect all the relevant tokens together
804+ const tokensList = [ this . currToken ] ;
821805 let nextToken = this . nextToken ;
822- let word = this . content ( ) ;
823806 while (
824807 nextToken &&
825808 ~ [ tokens . dollar , tokens . caret , tokens . equals , tokens . word ] . indexOf ( nextToken [ TOKEN . TYPE ] )
826809 ) {
827810 this . position ++ ;
828- let current = this . content ( ) ;
829- word += current ;
830- if ( current . lastIndexOf ( '\\' ) === current . length - 1 ) {
811+ const token = this . currToken ;
812+ tokensList . push ( token ) ;
813+ if ( this . content ( token ) . endsWith ( '\\' ) ) {
831814 let next = this . nextToken ;
832815 if ( next && next [ TOKEN . TYPE ] === tokens . space ) {
833- word += this . requiredSpace ( this . content ( next ) ) ;
816+ tokensList . push ( next ) ;
834817 this . position ++ ;
835818 }
836819 }
837820 nextToken = this . nextToken ;
838821 }
839- const hasClass = indexesOf ( word , '.' ) . filter ( i => word [ i - 1 ] !== '\\' ) ;
840- let hasId = indexesOf ( word , '#' ) . filter ( i => word [ i - 1 ] !== '\\' ) ;
841- // Eliminate Sass interpolations from the list of id indexes
842- const interpolations = indexesOf ( word , '#{' ) ;
843- if ( interpolations . length ) {
844- hasId = hasId . filter ( hashIndex => ! ~ interpolations . indexOf ( hashIndex ) ) ;
822+
823+ // Get the content of each token
824+ const tokensContent = tokensList . map ( token => {
825+ if ( token [ TOKEN . TYPE ] === tokens . space ) {
826+ return this . requiredSpace ( token ) ;
827+ }
828+ return this . content ( token ) ;
829+ } ) ;
830+
831+ // Parse the list of tokens and create a list of new nodes
832+ const nodesToCreate = [ ] ;
833+ let inProgressNode ;
834+ tokensList . forEach ( ( token , tokenIndex ) => {
835+ const content = tokensContent [ tokenIndex ] ;
836+ for ( let i = 0 ; i < content . length ; i ++ ) {
837+ const char = content [ i ] ;
838+ const prevChar = content [ i - 1 ] || ( tokenIndex !== 0 ? tokensContent [ tokenIndex - 1 ] . slice ( - 1 ) : undefined ) ;
839+ const nextChar = content [ i + 1 ] || ( tokenIndex !== tokensContent . length - 1 ? tokensContent [ tokenIndex + 1 ] [ 0 ] : undefined ) ;
840+
841+ if ( char === "." && prevChar !== "\\" ) {
842+ initNode ( ClassName ) ;
843+ } else if ( char === "#" && prevChar !== "\\" && nextChar !== "{" ) {
844+ initNode ( ID ) ;
845+ } else if ( ! inProgressNode ) {
846+ initNode ( Tag , char ) ;
847+ } else {
848+ inProgressNode . value += char ;
849+ inProgressNode . endToken = token ;
850+ inProgressNode . endIndex = i ;
851+ }
852+
853+ function initNode ( NodeConstructor , value = "" ) {
854+ if ( inProgressNode ) {
855+ nodesToCreate . push ( inProgressNode ) ;
856+ }
857+ inProgressNode = {
858+ NodeConstructor,
859+ value,
860+ startToken : token ,
861+ endToken : token ,
862+ startIndex : i ,
863+ endIndex : i ,
864+ } ;
865+ }
866+ }
867+ } ) ;
868+ if ( inProgressNode ) {
869+ nodesToCreate . push ( inProgressNode ) ;
845870 }
846- let indices = sortAsc ( uniqs ( [ 0 , ...hasClass , ...hasId ] ) ) ;
847- indices . forEach ( ( ind , i ) => {
848- const index = indices [ i + 1 ] || word . length ;
849- const value = word . slice ( ind , index ) ;
871+
872+ nodesToCreate . forEach ( ( node , i ) => {
850873 if ( i === 0 && firstCallback ) {
851- return firstCallback . call ( this , value , indices . length ) ;
874+ firstCallback . call ( this , node . value , nodesToCreate . length ) ;
875+ return ;
852876 }
853- let node ;
854- const current = this . currToken ;
855- const sourceIndex = current [ TOKEN . START_POS ] + indices [ i ] ;
877+ const { NodeConstructor, value, startToken, endToken, startIndex, endIndex} = node ;
878+ const sourceIndex = startToken [ TOKEN . START_POS ] + startIndex ;
856879 const source = getSource (
857- current [ 1 ] ,
858- current [ 2 ] + ind ,
859- current [ 3 ] ,
860- current [ 2 ] + ( index - 1 )
880+ startToken [ TOKEN . START_LINE ] ,
881+ startToken [ TOKEN . START_COL ] + startIndex ,
882+ endToken [ TOKEN . END_LINE ] ,
883+ endToken [ TOKEN . START_COL ] + endIndex
861884 ) ;
862- if ( ~ hasClass . indexOf ( ind ) ) {
863- let classNameOpts = {
864- value : value . slice ( 1 ) ,
865- source,
866- sourceIndex,
867- } ;
868- node = new ClassName ( unescapeProp ( classNameOpts , "value" ) ) ;
869- } else if ( ~ hasId . indexOf ( ind ) ) {
870- let idOpts = {
871- value : value . slice ( 1 ) ,
872- source,
873- sourceIndex,
874- } ;
875- node = new ID ( unescapeProp ( idOpts , "value" ) ) ;
876- } else {
877- let tagOpts = {
878- value,
879- source,
880- sourceIndex,
881- } ;
882- unescapeProp ( tagOpts , "value" ) ;
883- node = new Tag ( tagOpts ) ;
884- }
885- this . newNode ( node , namespace ) ;
885+ const opts = unescapeProp ( { value, source, sourceIndex} , "value" ) ;
886+ this . newNode ( new NodeConstructor ( opts ) , namespace ) ;
886887 // Ensure that the namespace is used only once
887888 namespace = null ;
888889 } ) ;
890+
889891 this . position ++ ;
890892 }
891893
0 commit comments