11// Dependencies
2- const postcss = require ( 'postcss' ) ;
32const deep = require ( 'deep-get-set' ) ;
43const kindOf = require ( 'kind-of' ) ;
54
@@ -10,65 +9,71 @@ const defaults = {
109 data : { }
1110} ;
1211
13- module . exports = postcss . plugin ( 'postcss-replace' , ( opts = defaults ) => {
12+ function postCSSReplace ( opts = defaults ) {
1413 const options = Object . assign ( { } , defaults , opts ) ;
1514
16- return ( css ) => {
15+ // Check validity of provided pattern. If not valid throw TypeError
16+ let regex = null ;
1717
18- // Check validity of provided pattern. If not valid throw TypeError
19- let regex = null ;
18+ if ( options . pattern instanceof RegExp ) {
19+ regex = options . pattern ;
20+ } else if ( typeof options . pattern === 'string' ) {
21+ regex = new RegExp ( options . pattern , 'gi' ) ;
22+ } else {
23+ throw new TypeError ( `Invalid pattern provided. It is expected to be a string or an instance of RegExp. Got: ${ kindOf ( options . pattern ) } ` ) ;
24+ }
2025
21- if ( options . pattern instanceof RegExp ) {
22- regex = options . pattern ;
23- } else if ( typeof options . pattern === 'string' ) {
24- regex = new RegExp ( options . pattern , 'gi' ) ;
25- } else {
26- throw new TypeError ( `Invalid pattern provided. It is expected to be a string or an instance of RegExp. Got: ${ kindOf ( options . pattern ) } ` ) ;
26+ const replacementArgs = options . data && options . data . replaceAll != null ? [ regex , options . data . replaceAll ] : [ regex , ( match , key ) => {
27+ const replace = deep ( options . data , key ) ;
28+
29+ if ( typeof replace !== 'string' ) {
30+ return match ;
2731 }
2832
29- const replacementArgs = options . data && options . data . replaceAll != null ? [ regex , options . data . replaceAll ] : [ regex , ( match , key ) => {
30- const replace = deep ( options . data , key ) ;
33+ return replace ;
34+ } ] ;
35+
36+ return {
37+ postcssPlugin : 'postcss-replace' ,
38+ OnceExit ( root ) {
39+ root [ options . commentsOnly ? 'walkComments' : 'walk' ] ( ( node ) => {
3140
32- if ( typeof replace !== 'string' ) {
33- return match ;
34- }
41+ // Before we had the switch statement, we just used node.replaceValues(). This could potentially lead to
42+ // incorrect behaviour as described in https://github.com/gridonic/postcss-replace/issues/5.
43+ //
44+ // So for example if the CSS contains at-rules like @media, calling replaceValues() would replace
45+ // everything inside the @media { … } statement and since we are walking through *all* nodes, we would
46+ // encounter the nodes from the @media statement again in the next iteration/call of our walk function.
47+ //
48+ // This is why we have refactored the logic of the walk function to use a switch statement in order to do
49+ // the replacement only on the relevant nodes and use the appropriate replacement logic.
50+ //
51+ // Furthermore it also makes adding/handling new cases quite comfortable.
52+ //
53+ // @see http://api.postcss.org/
54+ switch ( node . constructor . name ) {
55+ case 'Comment' :
56+ node . text = node . text . replace ( ...replacementArgs ) ;
57+ break ;
3558
36- return replace ;
37- } ] ;
59+ case 'Declaration' :
60+ node . prop = node . prop . replace ( ...replacementArgs ) ;
61+ node . value = node . value . replace ( ...replacementArgs ) ;
62+ break ;
3863
39- css [ options . commentsOnly ? 'walkComments' : 'walk' ] ( ( node ) => {
64+ case 'AtRule' :
65+ node . params = node . params . replace ( ...replacementArgs ) ;
66+ break ;
4067
41- // Before we had the switch statement, we just used node.replaceValues(). This could potentially lead to
42- // incorrect behaviour as described in https://github.com/gridonic/postcss-replace/issues/5.
43- //
44- // So for example if the CSS contains at-rules like @media, calling replaceValues() would replace
45- // everything inside the @media { … } statement and since we are walking through *all* nodes, we would
46- // encounter the nodes from the @media statement again in the next iteration/call of our walk function.
47- //
48- // This is why we have refactored the logic of the walk function to use a switch statement in order to do
49- // the replacement only on the relevant nodes and use the appropriate replacement logic.
50- //
51- // Furthermore it also makes adding/handling new cases quite comfortable.
52- //
53- // @see http://api.postcss.org/
54- switch ( node . constructor . name ) {
55- case 'Comment' :
56- node . text = node . text . replace ( ...replacementArgs ) ;
57- break ;
68+ case 'Rule' :
69+ node . selector = node . selector . replace ( ...replacementArgs ) ;
70+ break ;
71+ }
72+ } ) ;
73+ }
74+ }
75+ }
5876
59- case 'Declaration' :
60- node . prop = node . prop . replace ( ...replacementArgs ) ;
61- node . value = node . value . replace ( ...replacementArgs ) ;
62- break ;
77+ postCSSReplace . postcss = true ;
6378
64- case 'AtRule' :
65- node . params = node . params . replace ( ...replacementArgs ) ;
66- break ;
67-
68- case 'Rule' :
69- node . selector = node . selector . replace ( ...replacementArgs ) ;
70- break ;
71- }
72- } ) ;
73- } ;
74- } ) ;
79+ module . exports = postCSSReplace ;
0 commit comments