1
- // Copyright 2021 The Hugo Authors. All rights reserved.
1
+ // Copyright 2024 The Hugo Authors. All rights reserved.
2
2
//
3
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
4
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ import (
18
18
"net/url"
19
19
"path"
20
20
"path/filepath"
21
+ "runtime"
21
22
"strings"
22
23
)
23
24
@@ -159,9 +160,78 @@ func Uglify(in string) string {
159
160
return path .Clean (in )
160
161
}
161
162
163
+ // URLEscape escapes unicode letters.
164
+ func URLEscape (uri string ) string {
165
+ // escape unicode letters
166
+ u , err := url .Parse (uri )
167
+ if err != nil {
168
+ panic (err )
169
+ }
170
+ return u .String ()
171
+ }
172
+
173
+ // TrimExt trims the extension from a path..
174
+ func TrimExt (in string ) string {
175
+ return strings .TrimSuffix (in , path .Ext (in ))
176
+ }
177
+
178
+ // From https://github.com/golang/go/blob/e0c76d95abfc1621259864adb3d101cf6f1f90fc/src/cmd/go/internal/web/url.go#L45
179
+ func UrlFromFilename (filename string ) (* url.URL , error ) {
180
+ if ! filepath .IsAbs (filename ) {
181
+ return nil , fmt .Errorf ("filepath must be absolute" )
182
+ }
183
+
184
+ // If filename has a Windows volume name, convert the volume to a host and prefix
185
+ // per https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/.
186
+ if vol := filepath .VolumeName (filename ); vol != "" {
187
+ if strings .HasPrefix (vol , `\\` ) {
188
+ filename = filepath .ToSlash (filename [2 :])
189
+ i := strings .IndexByte (filename , '/' )
190
+
191
+ if i < 0 {
192
+ // A degenerate case.
193
+ // \\host.example.com (without a share name)
194
+ // becomes
195
+ // file://host.example.com/
196
+ return & url.URL {
197
+ Scheme : "file" ,
198
+ Host : filename ,
199
+ Path : "/" ,
200
+ }, nil
201
+ }
202
+
203
+ // \\host.example.com\Share\path\to\file
204
+ // becomes
205
+ // file://host.example.com/Share/path/to/file
206
+ return & url.URL {
207
+ Scheme : "file" ,
208
+ Host : filename [:i ],
209
+ Path : filepath .ToSlash (filename [i :]),
210
+ }, nil
211
+ }
212
+
213
+ // C:\path\to\file
214
+ // becomes
215
+ // file:///C:/path/to/file
216
+ return & url.URL {
217
+ Scheme : "file" ,
218
+ Path : "/" + filepath .ToSlash (filename ),
219
+ }, nil
220
+ }
221
+
222
+ // /path/to/file
223
+ // becomes
224
+ // file:///path/to/file
225
+ return & url.URL {
226
+ Scheme : "file" ,
227
+ Path : filepath .ToSlash (filename ),
228
+ }, nil
229
+ }
230
+
162
231
// UrlToFilename converts the URL s to a filename.
163
232
// If ParseRequestURI fails, the input is just converted to OS specific slashes and returned.
164
- func UrlToFilename (s string ) (string , bool ) {
233
+ func UrlStringToFilename (s string ) (string , bool ) {
234
+ s = strings .Replace (s , "hugostdin:" , "file:" , 1 )
165
235
u , err := url .ParseRequestURI (s )
166
236
if err != nil {
167
237
return filepath .FromSlash (s ), false
@@ -174,22 +244,33 @@ func UrlToFilename(s string) (string, bool) {
174
244
return filepath .FromSlash (p ), true
175
245
}
176
246
177
- p = filepath . FromSlash ( p )
247
+ fmt . Println ( "URL" , s , "h" , u . Host , "p" , p )
178
248
179
- if u .Host != "" {
180
- // C:\data\file.txt
181
- p = strings .ToUpper (u .Host ) + ":" + p
249
+ if runtime .GOOS == "windows" {
250
+ return convertFileURLPathWindows (u .Host , p )
182
251
}
183
252
253
+ p = filepath .FromSlash (p )
254
+
184
255
return p , true
185
256
}
186
257
187
- // URLEscape escapes unicode letters.
188
- func URLEscape (uri string ) string {
189
- // escape unicode letters
190
- u , err := url .Parse (uri )
191
- if err != nil {
192
- panic (err )
258
+ func convertFileURLPathWindows (host , path string ) (string , bool ) {
259
+ if len (path ) == 0 || path [0 ] != '/' {
260
+ return "" , false
193
261
}
194
- return u .String ()
262
+
263
+ p = filepath .FromSlash (p )
264
+
265
+ if host != "" && host != "localhost" {
266
+ if filepath .VolumeName (host ) != "" {
267
+ return "" , false
268
+ }
269
+ return `\\` + host + path , true
270
+ }
271
+
272
+ if vol := filepath .VolumeName (path [1 :]); vol == "" || strings .HasPrefix (vol , `\\` ) {
273
+ return "" , false
274
+ }
275
+ return path [1 :], true
195
276
}
0 commit comments