@@ -27,6 +27,7 @@ import {
27
27
concat ,
28
28
defer ,
29
29
from ,
30
+ identity ,
30
31
map ,
31
32
merge ,
32
33
mergeMap ,
@@ -112,6 +113,75 @@ function minsvg(data: string): string {
112
113
return result . data
113
114
}
114
115
116
+ /**
117
+ * Return a path with POSIX style separators
118
+ *
119
+ * The default function assumes UNIX system, so it just returns the path.
120
+ *
121
+ * @param p - string path
122
+ * @returns String path
123
+ */
124
+ let assurePosixSep = function ( p : string ) : string {
125
+ return p
126
+ } ;
127
+
128
+ /**
129
+ * Return a path with POSIX style separators
130
+ *
131
+ * The Windows variant of this function replaces the separator with regex.
132
+ *
133
+ * @param p - string path
134
+ * @returns String path
135
+ */
136
+ function assurePosixSepWin ( p : string ) : string {
137
+ return p . replace ( winSepRegex , path . posix . sep )
138
+ } ;
139
+
140
+ const winSepRegex = new RegExp ( `\\${ path . win32 . sep } ` , "g" ) ;
141
+
142
+ if ( path . sep === path . win32 . sep ) {
143
+ assurePosixSep = assurePosixSepWin ;
144
+ }
145
+
146
+ /**
147
+ * Compare two path strings to decide on the order
148
+ *
149
+ * On Windows the default order of paths containing `_` from the resolve function
150
+ * is different than on macOS. This function restores the order to the usual.
151
+ * Implementation adapted based on https://t.ly/VJp78
152
+ *
153
+ * Note: The paths should have no extension like .svg, just the name. Otherwise
154
+ * it won't check the compare.startsWith(reference) properly.
155
+ *
156
+ * @param reference Left string to compare
157
+ * @param compare Right string to compare against
158
+ * @returns Number for the sort function to define the order
159
+ */
160
+ function sortOrderForWindows ( reference : string , compare : string ) : number {
161
+ reference = reference . toLowerCase ( ) ;
162
+ compare = compare . toLowerCase ( ) ;
163
+
164
+ const length = Math . min ( reference . length , compare . length ) ;
165
+
166
+ for ( let i = 0 ; i < length ; i ++ ) {
167
+ const leftChar = reference [ i ] ;
168
+ const rightChar = compare [ i ] ;
169
+
170
+ if ( leftChar !== rightChar )
171
+ return customAlphabet . indexOf ( leftChar ) - customAlphabet . indexOf ( rightChar ) ;
172
+ }
173
+
174
+ if ( reference . length !== compare . length ) {
175
+ if ( compare . startsWith ( reference ) && compare [ reference . length ] === "-" )
176
+ return 1 ;
177
+ return reference . length - compare . length ;
178
+ }
179
+
180
+ return 0 ;
181
+ }
182
+
183
+ const customAlphabet : string = "_,-./0123456789abcdefghijklmnopqrstuvwxyz" ;
184
+
115
185
/* ----------------------------------------------------------------------------
116
186
* Tasks
117
187
* ------------------------------------------------------------------------- */
@@ -187,7 +257,7 @@ const sources$ = copyAll("**/*.py", {
187
257
const stylesheets$ = resolve ( "**/[!_]*.scss" , { cwd : "src" } )
188
258
. pipe (
189
259
mergeMap ( file => zip (
190
- of ( ext ( file , ".css" ) . replace ( / ( o v e r r i d e s | t e m p l a t e s ) \/ / , "" ) ) ,
260
+ of ( ext ( file , ".css" ) . replace ( new RegExp ( `( overrides|templates)\\ ${ path . sep } ` ) , "" ) ) ,
191
261
transformStyle ( {
192
262
from : `src/${ file } ` ,
193
263
to : ext ( `${ base } /${ file } ` , ".css" )
@@ -199,7 +269,7 @@ const stylesheets$ = resolve("**/[!_]*.scss", { cwd: "src" })
199
269
const javascripts$ = resolve ( "**/{custom,bundle,search}.ts" , { cwd : "src" } )
200
270
. pipe (
201
271
mergeMap ( file => zip (
202
- of ( ext ( file , ".js" ) . replace ( / ( o v e r r i d e s | t e m p l a t e s ) \/ / , "" ) ) ,
272
+ of ( ext ( file , ".js" ) . replace ( new RegExp ( `( overrides|templates)\\ ${ path . sep } ` ) , "" ) ) ,
203
273
transformScript ( {
204
274
from : `src/${ file } ` ,
205
275
to : ext ( `${ base } /${ file } ` , ".js" )
@@ -229,10 +299,10 @@ const manifest$ = merge(
229
299
. pipe (
230
300
scan ( ( prev , mapping ) => (
231
301
mapping . reduce ( ( next , [ key , value ] ) => (
232
- next . set ( key , value . replace (
233
- new RegExp ( `${ base } \\/(overrides|templates)\\/ ` ) ,
302
+ next . set ( assurePosixSep ( key ) , assurePosixSep ( value . replace (
303
+ new RegExp ( `${ base } \\/(overrides|templates)\\${ path . sep } ` ) ,
234
304
""
235
- ) )
305
+ ) ) )
236
306
) , prev )
237
307
) , new Map < string , string > ( ) ) ,
238
308
)
@@ -291,9 +361,15 @@ const icons$ = defer(() => resolve("**/*.svg", {
291
361
} ) )
292
362
. pipe (
293
363
reduce ( ( index , file ) => index . set (
294
- file . replace ( / \. s v g $ / , "" ) . replace ( / \/ / g, "-" ) ,
295
- file
296
- ) , new Map < string , string > ( ) )
364
+ file . replace ( / \. s v g $ / , "" ) . replace ( new RegExp ( `\\${ path . sep } ` , "g" ) , "-" ) ,
365
+ assurePosixSep ( file )
366
+ ) , new Map < string , string > ( ) ) ,
367
+ // The icons are stored in the index file, and the output needs to be OS
368
+ // agnostic. Some icons contain the `_` character, which has different order
369
+ // in the glob output on Windows.
370
+ ( path . sep === path . win32 . sep ) ? map ( icons => new Map (
371
+ [ ...icons ] . sort ( ( a , b ) => sortOrderForWindows ( a [ 0 ] , b [ 0 ] ) )
372
+ ) ) : identity
297
373
)
298
374
299
375
/* Compute emoji mappings (based on Twemoji) */
@@ -372,7 +448,7 @@ const schema$ = merge(
372
448
"reference/icons-emojis/#search"
373
449
] . join ( "/" ) ,
374
450
"type" : "string" ,
375
- "enum" : icons . map ( icon => icon . replace ( ".svg" , "" ) )
451
+ "enum" : icons . map ( icon => assurePosixSep ( icon . replace ( ".svg" , "" ) ) )
376
452
} ) ) ,
377
453
switchMap ( data => write (
378
454
"docs/schema/assets/icons.json" ,
0 commit comments