@@ -110,32 +110,78 @@ export function absoluteToStylesheet(
110110 ) ;
111111}
112112
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 ] + / ;
113115function 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+ */
114124 if ( attributeValue . trim ( ) === '' ) {
115125 return attributeValue ;
116126 }
117127
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 ;
137129
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 ( ', ' ) ;
139185}
140186
141187export function absoluteToDoc ( doc : Document , attributeValue : string ) : string {
0 commit comments