1+ const EVENTS = Object . keys ( window ) . filter ( e => e . substring ( 0 , 2 ) == 'on' ) . map ( e => e . substring ( 2 ) . toLowerCase ( ) ) ;
2+
3+ const REGEXES_COMMENTS = [
4+ / \/ \* [ \s \S ] * ?\* \/ / g,
5+ / \/ \/ .* / g
6+ ] ;
7+ const REGEXES = [
8+ / ( [ a - z A - Z 0 - 9 \- , ] + ) - \[ ( [ a - z A - Z 0 - 9 . % # , \- ( ) ' " \/ : ? ! ] + ) \] / g,
9+ / ( (?: \[ [ a - z A - Z 0 - 9 \- @ ( ) : > , + ] + \] : ) * ) \{ \s * ?( (?: [ a - z A - Z \- ] + - \[ [ a - z A - Z 0 - 9 , % . \- ( ) / : ? ! ' " # ] + \] \s * ?) + ) \} / g
10+ ] ;
11+
12+ function getIndexChildren ( element , index = 0 ) {
13+ if ( 'HTML' !== element . tagName ) {
14+ return getIndexChildren ( element . parentElement , index + 1 ) ;
15+ }
16+ return index ;
17+ }
18+
19+ function joinArrays ( ...arrays ) {
20+ const newArray = [ ] ;
21+ const highestLength = Math . max ( ...arrays . map ( arr => arr . length ) ) ;
22+ for ( let i = 0 ; i < highestLength ; i ++ ) {
23+ const newElement = [ ] ;
24+ for ( const arr of arrays ) {
25+ newElement . push ( arr [ i ] || null ) ;
26+ }
27+ newArray . push ( newElement ) ;
28+ }
29+ return newArray ;
30+ }
31+
32+ function isEvents ( string ) {
33+ const events = string . split ( ',' ) . map ( e => e . trim ( ) . toLowerCase ( ) ) ;
34+ return events . every ( e => EVENTS . includes ( e ) ) ;
35+ }
36+
37+ function getCurrentDOMPath ( element ) {
38+ let dompath = '' ;
39+ let currentElement = element ;
40+ while ( currentElement && currentElement . tagName !== 'HTML' ) {
41+ const tagName = currentElement . tagName . toLowerCase ( ) ;
42+ const siblingsWithSameTag = Array . from ( currentElement . parentNode . children ) . filter ( child => child . tagName === currentElement . tagName ) ;
43+ const index = siblingsWithSameTag . indexOf ( currentElement ) + 1 ;
44+ dompath = `>${ tagName } ${ index > 1 ? `:nth-of-type(${ index } )` : '' } ` + dompath ;
45+ currentElement = currentElement . parentNode ;
46+ if ( currentElement . hasAttribute ( 'data-cijih-current-tag' ) ) {
47+ dompath = `${ currentElement . getAttribute ( 'data-cijih-current-tag' ) } ` + dompath ;
48+ return dompath ;
49+ }
50+ }
51+ if ( currentElement . tagName === 'HTML' ) {
52+ return `html` ;
53+ }
54+ return xpath . substring ( 1 ) ;
55+ }
56+
57+ function getQueries ( string ) {
58+ const queries = [ ] ;
59+ let currentQuery = '' ;
60+ let indexBracket = 0 ;
61+ for ( let i = 0 ; i < string . length ; i ++ ) {
62+ const char = string [ i ] ;
63+ if ( char === '[' ) {
64+ indexBracket ++ ;
65+ currentQuery += char ;
66+ } else if ( char === ']' ) {
67+ indexBracket -- ;
68+ currentQuery += char ;
69+ } else if ( char === ',' && indexBracket === 0 ) {
70+ queries . push ( currentQuery . trim ( ) ) ;
71+ currentQuery = '' ;
72+ } else {
73+ currentQuery += char ;
74+ }
75+ }
76+ if ( currentQuery ) {
77+ queries . push ( currentQuery . trim ( ) ) ;
78+ }
79+ return queries ;
80+ }
81+
82+ function getGroupsBrackets ( string , result = {
83+ media : '' ,
84+ events : '' ,
85+ query : ''
86+ } ) {
87+ const groups = [ ]
88+ let j = 0 ;
89+ for ( let i = 0 ; i < string . length ; i ++ ) {
90+ const char = string [ i ] ;
91+ if ( char === '[' ) {
92+ j = i + 1 ;
93+ while ( j < string . length && string [ j ] !== ']' ) {
94+ j ++ ;
95+ }
96+ groups . push ( string . slice ( i , j + 1 ) ) ;
97+ i = j ;
98+ }
99+ }
100+ for ( let i = 0 ; i < groups . length ; i ++ ) {
101+ const group = groups [ i ] . substring ( 1 , groups [ i ] . length - 1 ) ;
102+ if ( group . startsWith ( '@media(' ) ) {
103+ result . media = group
104+ } else if ( isEvents ( group ) ) {
105+ result . events = group
106+ } else {
107+ result . query = group
108+ }
109+ }
110+ return result ;
111+ }
112+
113+ function getStylesFromClasses ( classes ) {
114+ const styles = { } ;
115+ const matches = classes . matchAll ( REGEXES [ 0 ] ) ;
116+ for ( const match of matches ) {
117+ const [ _ , property , value ] = match ;
118+ styles [ property ] = value ;
119+ }
120+ return styles ;
121+ }
122+
123+ window . addEventListener ( 'DOMContentLoaded' , function ( ) {
124+ let elements = document . querySelectorAll ( '[class]' ) ;
125+ const indexes = Array . from ( elements ) . map ( e => getIndexChildren ( e ) ) ;
126+ elements = Array . from ( elements ) . map ( ( e , i ) => [ e , indexes [ i ] ] ) ;
127+ elements = elements . sort ( ( a , b ) => a [ 1 ] - b [ 1 ] ) ;
128+ for ( let i = 0 ; i < elements . length ; i ++ ) {
129+ const element = elements [ i ] [ 0 ] ;
130+
131+ for ( const regex of REGEXES_COMMENTS ) {
132+ element . className = element . className . replace ( regex , '' ) ;
133+ }
134+
135+ const matchesSecondCase = element . className . matchAll ( REGEXES [ 1 ] ) ;
136+
137+ for ( const match of matchesSecondCase ) {
138+ const [ _ , groupsBrackets , classes ] = match ;
139+ const groups = getGroupsBrackets ( groupsBrackets ) ;
140+ const queries = getQueries ( groups . query ) ;
141+ for ( let i = 0 ; i < queries . length ; i ++ ) {
142+ if ( queries [ i ] . startsWith ( '>' ) ) {
143+ const currentDOMPath = getCurrentDOMPath ( element ) ;
144+ element . dataset . cijihCurrentTag = currentDOMPath ;
145+ queries [ i ] = currentDOMPath + queries [ i ] ;
146+ }
147+ if ( 'current' === queries [ i ] ) {
148+ const currentDOMPath = getCurrentDOMPath ( element ) ;
149+ element . dataset . cijihCurrentTag = currentDOMPath ;
150+ queries [ i ] = currentDOMPath ;
151+ }
152+ }
153+ if ( groups . events ) {
154+ const events = groups . events . split ( ',' ) . map ( e => e . trim ( ) . toLowerCase ( ) ) ;
155+ for ( const event of events ) {
156+ element . addEventListener ( event , function ( ) {
157+ if ( queries . length > 0 ) {
158+ for ( const query of queries ) {
159+ const elements = element . querySelectorAll ( query ) ;
160+ const styles = getStylesFromClasses ( classes ) ;
161+ for ( const [ property , value ] of Object . entries ( styles ) ) {
162+ elements . forEach ( el => el . style . setProperty ( property , value ) ) ;
163+ }
164+ }
165+ }
166+ else {
167+ const styles = getStylesFromClasses ( classes ) ;
168+ for ( const [ property , value ] of Object . entries ( styles ) ) {
169+ element . style . setProperty ( property , value ) ;
170+ }
171+ }
172+ } ) ;
173+ }
174+ }
175+ for ( const query of queries ) {
176+ const elements = document . querySelectorAll ( query ) ;
177+ const styles = getStylesFromClasses ( classes ) ;
178+ for ( const [ property , value ] of Object . entries ( styles ) ) {
179+ elements . forEach ( el => el . style . setProperty ( property , value ) ) ;
180+ }
181+ }
182+ const length = match [ 0 ] . length ;
183+ const spaces = ' ' . repeat ( length ) ;
184+ element . className = element . className . replace ( match [ 0 ] , spaces ) ;
185+ }
186+
187+ const matchesFirstCase = element . className . matchAll ( REGEXES [ 0 ] ) ;
188+ const styles = getStylesFromClasses ( element . className ) ;
189+ for ( const [ property , value ] of Object . entries ( styles ) ) {
190+ element . style . setProperty ( property , value ) ;
191+ }
192+ for ( const match of matchesFirstCase ) {
193+ const length = match [ 0 ] . length ;
194+ const spaces = ' ' . repeat ( length ) ;
195+ element . className = element . className . replace ( match [ 0 ] , spaces ) ;
196+ }
197+ element . className = element . className . trim ( ) ;
198+ }
199+ this . document . documentElement . removeAttribute ( 'hidden' ) ;
200+ const elementsWithClasses = document . querySelector ( '[class]' ) ;
201+ } ) ;
0 commit comments