@@ -110,32 +110,78 @@ export function absoluteToStylesheet(
110
110
) ;
111
111
}
112
112
113
+ const SRCSET_NOT_SPACES = / ^ [ ^ \t \n \r \u000c ] + / ; // Don't use \s, to avoid matching non-breaking space
114
+ const SRCSET_COMMAS_OR_SPACES = / ^ [ , \t \n \r \u000c ] + / ;
113
115
function getAbsoluteSrcsetString ( doc : Document , attributeValue : string ) {
116
+ /*
117
+ run absoluteToDoc over every url in the srcset
118
+
119
+ this is adapted from https://github.com/albell/parse-srcset/
120
+ without the parsing of the descriptors (we return these as-is)
121
+ parce-srcset is in turn based on
122
+ https://html.spec.whatwg.org/multipage/embedded-content.html#parse-a-srcset-attribute
123
+ */
114
124
if ( attributeValue . trim ( ) === '' ) {
115
125
return attributeValue ;
116
126
}
117
127
118
- const srcsetValues = attributeValue . split ( ',' ) ;
119
- // srcset attributes is defined as such:
120
- // srcset = "url size,url1 size1"
121
- const resultingSrcsetString = srcsetValues
122
- . map ( ( srcItem ) => {
123
- // removing all but middle spaces
124
- const trimmedSrcItem = srcItem . trimLeft ( ) . trimRight ( ) ;
125
- const urlAndSize = trimmedSrcItem . split ( ' ' ) ;
126
- // this means we have both 0:url and 1:size
127
- if ( urlAndSize . length === 2 ) {
128
- const absUrl = absoluteToDoc ( doc , urlAndSize [ 0 ] ) ;
129
- return `${ absUrl } ${ urlAndSize [ 1 ] } ` ;
130
- } else if ( urlAndSize . length === 1 ) {
131
- const absUrl = absoluteToDoc ( doc , urlAndSize [ 0 ] ) ;
132
- return `${ absUrl } ` ;
133
- }
134
- return '' ;
135
- } )
136
- . join ( ', ' ) ;
128
+ let pos = 0 ;
137
129
138
- return resultingSrcsetString ;
130
+ function collectCharacters ( regEx : RegExp ) {
131
+ var chars ,
132
+ match = regEx . exec ( attributeValue . substring ( pos ) ) ;
133
+ if ( match ) {
134
+ chars = match [ 0 ] ;
135
+ pos += chars . length ;
136
+ return chars ;
137
+ }
138
+ return '' ;
139
+ }
140
+
141
+ let output = [ ] ;
142
+ while ( true ) {
143
+ collectCharacters ( SRCSET_COMMAS_OR_SPACES ) ;
144
+ if ( pos >= attributeValue . length ) {
145
+ break ;
146
+ }
147
+ // don't split on commas within urls
148
+ let url = collectCharacters ( SRCSET_NOT_SPACES ) ;
149
+ if ( url . slice ( - 1 ) === ',' ) {
150
+ // aside: according to spec more than one comma at the end is a parse error, but we ignore that
151
+ url = absoluteToDoc ( doc , url . substring ( 0 , url . length - 1 ) )
152
+ // the trailing comma splits the srcset, so the interpretion is that
153
+ // another url will follow, and the descriptor is empty
154
+ output . push ( url ) ;
155
+ } else {
156
+ let descriptorsStr = '' ;
157
+ url = absoluteToDoc ( doc , url )
158
+ let inParens = false ;
159
+ while ( true ) {
160
+ let c = attributeValue . charAt ( pos ) ;
161
+ if ( c === '' ) {
162
+ output . push ( ( url + descriptorsStr ) . trim ( ) ) ;
163
+ break ;
164
+ } else if ( ! inParens ) {
165
+ if ( c === ',' ) {
166
+ pos += 1 ;
167
+ output . push ( ( url + descriptorsStr ) . trim ( ) ) ;
168
+ break ; // parse the next url
169
+ } else if ( c === '(' ) {
170
+ inParens = true ;
171
+ }
172
+ } else {
173
+ // in parenthesis; ignore commas
174
+ // (parenthesis may be supported by future additions to spec)
175
+ if ( c === ')' ) {
176
+ inParens = false ;
177
+ }
178
+ }
179
+ descriptorsStr += c ;
180
+ pos += 1 ;
181
+ }
182
+ }
183
+ }
184
+ return output . join ( ', ' ) ;
139
185
}
140
186
141
187
export function absoluteToDoc ( doc : Document , attributeValue : string ) : string {
0 commit comments