4
4
*/
5
5
'use strict' ;
6
6
7
- var os = require ( 'os' ) ,
8
- path = require ( 'path' ) ,
9
- postcss = require ( 'postcss' ) ;
7
+ const os = require ( 'os' ) ;
8
+ const path = require ( 'path' ) ;
9
+ const postcss = require ( 'postcss' ) ;
10
10
11
- var fileProtocol = require ( '../file-protocol' ) ;
12
- var algerbra = require ( '../position-algerbra' ) ;
11
+ const fileProtocol = require ( '../file-protocol' ) ;
12
+ const algerbra = require ( '../position-algerbra' ) ;
13
13
14
- var ORPHAN_CR_REGEX = / \r (? ! \n ) ( .| \n ) ? / g;
14
+ const ORPHAN_CR_REGEX = / \r (? ! \n ) ( .| \n ) ? / g;
15
15
16
16
/**
17
17
* Process the given CSS content into reworked CSS content.
@@ -24,66 +24,96 @@ var ORPHAN_CR_REGEX = /\r(?!\n)(.|\n)?/g;
24
24
*/
25
25
function process ( sourceFile , sourceContent , params ) {
26
26
// #107 libsass emits orphan CR not considered newline, postcss does consider newline (content vs source-map mismatch)
27
- var correctedContent = params . removeCR && ( os . EOL !== '\r' ) ?
27
+ const correctedContent = params . removeCR && ( os . EOL !== '\r' ) ?
28
28
sourceContent . replace ( ORPHAN_CR_REGEX , ' $1' ) :
29
29
sourceContent ;
30
30
31
- /**
32
- * Plugin for postcss that follows SASS transpilation.
33
- */
34
- const postcssPlugin = {
35
- postcssPlugin : 'postcss-resolve-url' ,
36
- Declaration : ( declaration ) => {
37
- var prefix ,
38
- isValid = declaration . value && ( declaration . value . indexOf ( 'url' ) >= 0 ) ;
39
- if ( isValid ) {
40
- prefix = declaration . prop + declaration . raws . between ;
41
- declaration . value = params . transformDeclaration ( declaration . value , getPathsAtChar ) ;
42
- }
31
+ // IMPORTANT - prepend file protocol to all sources to avoid problems with source map
32
+ const plugin = Object . assign (
33
+ ( ) => ( {
34
+ postcssPlugin : 'postcss-resolve-url' ,
35
+ prepare : ( ) => {
36
+ const visited = new Set ( ) ;
37
+
38
+ /**
39
+ * Given an apparent position find the directory of the original file.
40
+ *
41
+ * @param startPosApparent {{line: number, column: number}}
42
+ * @returns {false|string } Directory of original file or false on invalid
43
+ */
44
+ const positionToOriginalDirectory = ( startPosApparent ) => {
45
+ // reverse the original source-map to find the original source file before transpilation
46
+ const startPosOriginal =
47
+ ! ! params . sourceMapConsumer &&
48
+ params . sourceMapConsumer . originalPositionFor ( startPosApparent ) ;
43
49
44
- /**
45
- * Create a hash of base path strings.
46
- *
47
- * Position in the declaration is supported by postcss at the position of the url() statement.
48
- *
49
- * @param {number } index Index in the declaration value at which to evaluate
50
- * @throws Error on invalid source map
51
- * @returns {{subString:string, value:string, property:string, selector:string} } Hash of base path strings
52
- */
53
- function getPathsAtChar ( index ) {
54
- var subString = declaration . value . slice ( 0 , index ) ,
55
- posSelector = algerbra . sanitise ( declaration . parent . source . start ) ,
56
- posProperty = algerbra . sanitise ( declaration . source . start ) ,
57
- posValue = algerbra . add ( [ posProperty , algerbra . strToOffset ( prefix ) ] ) ,
58
- posSubString = algerbra . add ( [ posValue , algerbra . strToOffset ( subString ) ] ) ;
50
+ // we require a valid directory for the specified file
51
+ const directory =
52
+ ! ! startPosOriginal &&
53
+ ! ! startPosOriginal . source &&
54
+ fileProtocol . remove ( path . dirname ( startPosOriginal . source ) ) ;
59
55
60
- var result = {
61
- subString : positionToOriginalDirectory ( posSubString ) ,
62
- value : positionToOriginalDirectory ( posValue ) ,
63
- property : positionToOriginalDirectory ( posProperty ) ,
64
- selector : positionToOriginalDirectory ( posSelector )
56
+ return directory ;
65
57
} ;
66
58
67
- var isValid = [ result . subString , result . value , result . property , result . selector ] . every ( Boolean ) ;
68
- if ( isValid ) {
69
- return result ;
70
- }
71
- else if ( params . sourceMapConsumer ) {
72
- throw new Error (
73
- 'source-map information is not available at url() declaration ' +
74
- ( ORPHAN_CR_REGEX . test ( sourceContent ) ? '(found orphan CR, try removeCR option)' : '(no orphan CR found)' )
75
- ) ;
76
- } else {
77
- throw new Error ( 'a valid source-map is not present (ensure preceding loaders output a source-map)' ) ;
78
- }
59
+ return {
60
+ Declaration : ( declaration ) => {
61
+ var prefix ,
62
+ isValid = declaration . value && ( declaration . value . indexOf ( 'url' ) >= 0 ) && ! visited . has ( declaration ) ;
63
+ if ( isValid ) {
64
+ prefix = declaration . prop + declaration . raws . between ;
65
+ declaration . value = params . transformDeclaration ( declaration . value , getPathsAtChar ) ;
66
+ visited . add ( declaration ) ;
67
+ }
68
+
69
+ /**
70
+ * Create a hash of base path strings.
71
+ *
72
+ * Position in the declaration is supported by postcss at the position of the url() statement.
73
+ *
74
+ * @param {number } index Index in the declaration value at which to evaluate
75
+ * @throws Error on invalid source map
76
+ * @returns {{subString:string, value:string, property:string, selector:string} } Hash of base path strings
77
+ */
78
+ function getPathsAtChar ( index ) {
79
+ var subString = declaration . value . slice ( 0 , index ) ,
80
+ posSelector = algerbra . sanitise ( declaration . parent . source . start ) ,
81
+ posProperty = algerbra . sanitise ( declaration . source . start ) ,
82
+ posValue = algerbra . add ( [ posProperty , algerbra . strToOffset ( prefix ) ] ) ,
83
+ posSubString = algerbra . add ( [ posValue , algerbra . strToOffset ( subString ) ] ) ;
84
+
85
+ var result = {
86
+ subString : positionToOriginalDirectory ( posSubString ) ,
87
+ value : positionToOriginalDirectory ( posValue ) ,
88
+ property : positionToOriginalDirectory ( posProperty ) ,
89
+ selector : positionToOriginalDirectory ( posSelector )
90
+ } ;
91
+
92
+ var isValid = [ result . subString , result . value , result . property , result . selector ] . every ( Boolean ) ;
93
+ if ( isValid ) {
94
+ return result ;
95
+ }
96
+ else if ( params . sourceMapConsumer ) {
97
+ throw new Error (
98
+ 'source-map information is not available at url() declaration ' + (
99
+ ORPHAN_CR_REGEX . test ( sourceContent ) ?
100
+ '(found orphan CR, try removeCR option)' :
101
+ '(no orphan CR found)'
102
+ )
103
+ ) ;
104
+ } else {
105
+ throw new Error ( 'a valid source-map is not present (ensure preceding loaders output a source-map)' ) ;
106
+ }
107
+ }
108
+ }
109
+ } ;
79
110
}
80
- }
81
- }
111
+ } ) ,
112
+ { postcss : true }
113
+ ) ;
82
114
83
- // prepend file protocol to all sources to avoid problems with source map
84
- return postcss ( [
85
- postcssPlugin
86
- ] )
115
+ // IMPORTANT - prepend file protocol to all sources to avoid problems with source map
116
+ return postcss ( [ plugin ] )
87
117
. process ( correctedContent , {
88
118
from : fileProtocol . prepend ( sourceFile ) ,
89
119
map : params . outputSourceMap && {
@@ -93,31 +123,10 @@ function process(sourceFile, sourceContent, params) {
93
123
sourcesContent : true // #98 sourcesContent missing from output map
94
124
}
95
125
} )
96
- . then ( result => ( {
97
- content : result . css ,
98
- map : params . outputSourceMap ? fileProtocol . remove ( result . map . toJSON ( ) ) : null
126
+ . then ( ( { css , map } ) => ( {
127
+ content : css ,
128
+ map : params . outputSourceMap ? fileProtocol . remove ( map . toJSON ( ) ) : null
99
129
} ) ) ;
100
-
101
- /**
102
- * Given an apparent position find the directory of the original file.
103
- *
104
- * @param startPosApparent {{line: number, column: number}}
105
- * @returns {false|string } Directory of original file or false on invalid
106
- */
107
- function positionToOriginalDirectory ( startPosApparent ) {
108
- // reverse the original source-map to find the original source file before transpilation
109
- var startPosOriginal =
110
- ! ! params . sourceMapConsumer &&
111
- params . sourceMapConsumer . originalPositionFor ( startPosApparent ) ;
112
-
113
- // we require a valid directory for the specified file
114
- var directory =
115
- ! ! startPosOriginal &&
116
- ! ! startPosOriginal . source &&
117
- fileProtocol . remove ( path . dirname ( startPosOriginal . source ) ) ;
118
-
119
- return directory ;
120
- }
121
130
}
122
131
123
132
module . exports = process ;
0 commit comments