Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion io.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func loadURL(u *url.URL) (map[string]interface{}, error) {
return nil, fmt.Errorf("unsupported %q URL scheme", u.Scheme)
}

return loadFile(filepath.FromSlash(u.Path))
return loadFile(urlPathToOSPath(u.Path))
}

func loadFile(pth string) (map[string]interface{}, error) {
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func processFile(pth string, encode func(interface{}) error, debug *debugFlags)

err = ExpandRefs(&tmp, &url.URL{
//Scheme: "file",
Path: filepath.ToSlash(pth),
Path: osPathToURLPath(pth),
}, trace)
if err != nil {
return err
Expand Down
6 changes: 3 additions & 3 deletions refs.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (l *loc) Index(i int) loc {

func (l *loc) Rel(basePath string) loc {
// FIXME do not use FS dependent paths
rel, err := filepath.Rel(filepath.FromSlash(basePath), filepath.FromSlash(l.Path))
rel, err := filepath.Rel(urlPathToOSPath(basePath), urlPathToOSPath(l.Path))
if err != nil {
return *l
}
Expand Down Expand Up @@ -240,7 +240,7 @@ func (resolver *refResolver) resolve(link string, relativeTo *loc) (*node, error
rdoc, loaded := resolver.docs[targetLoc.Path]
if !loaded {
//log.Println("Loading", &targetLoc)
doc, err := loadFile(filepath.FromSlash(targetLoc.Path))
doc, err := loadFile(urlPathToOSPath(targetLoc.Path))
if err != nil {
return nil, fmt.Errorf("can't load %q: %v", targetLoc.Path, err)
}
Expand Down Expand Up @@ -629,7 +629,7 @@ func ExpandRefs(rdoc *interface{}, docURL *url.URL, trace func(string)) error {

path := path.Clean(docURL.Path)
resolver := refResolver{
basePath: filepath.ToSlash(cwd),
basePath: osPathToURLPath(cwd),
rootPath: path,
docs: map[string]*interface{}{
path: rdoc,
Expand Down
45 changes: 44 additions & 1 deletion resolvepath.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,50 @@

package main

import "strings"
import (
"path/filepath"
"runtime"
"strings"
)

// osPathToURLPath converts a native absolute filesystem path (as returned by
// filepath.Abs) into the "/"-rooted path convention used internally to
// identify documents, which resolvePath always produces and expects as input.
//
// On POSIX this is a no-op beyond slash conversion, since native absolute
// paths already start with "/". On Windows, native absolute paths start with
// a drive letter (e.g. "C:\foo\bar") with no leading separator, so one is
// added, matching the "file:///C:/foo/bar" URI convention.
func osPathToURLPath(pth string) string {
pth = filepath.ToSlash(pth)
if pth == "" || pth[0] != '/' {
pth = "/" + pth
}
return pth
}

// isWindowsDriveAbs reports whether pth is an internal "/"-rooted path
// wrapping a Windows drive-absolute path, e.g. "/C:/foo/bar".
func isWindowsDriveAbs(pth string) bool {
return len(pth) >= 3 &&
pth[0] == '/' &&
(('a' <= pth[1] && pth[1] <= 'z') || ('A' <= pth[1] && pth[1] <= 'Z')) &&
pth[2] == ':' &&
(len(pth) == 3 || pth[3] == '/')
}

// urlPathToOSPath is the reverse of osPathToURLPath: it turns an internal
// "/"-rooted document path back into a native OS path suitable for os.Open.
//
// On Windows, a path like "/C:/foo/bar" must have its leading "/" stripped
// before the drive letter, or filepath.FromSlash would produce the invalid
// "\C:\foo\bar".
func urlPathToOSPath(pth string) string {
if runtime.GOOS == "windows" && isWindowsDriveAbs(pth) {
pth = pth[1:]
}
return filepath.FromSlash(pth)
}

// resolvePath applies special path segments from refs and applies
// them to base, per RFC 3986.
Expand Down
Loading