@@ -8,14 +8,20 @@ import (
8
8
"strings"
9
9
)
10
10
11
- // InferLoader analyzes the input and returns an appropriate loader based on type inference.
12
- // It supports the following input types:
13
- // - string: Infers from URI scheme (http/https -> HTTP, file -> Disk) or content (inline string with base64 decoding)
14
- // - []byte: Returns FromBytes loader
15
- // - io.Reader: Returns FromIoReader loader
16
- // - Loader: Returns as-is
11
+ // InferLoader determines the appropriate loader for the given input.
17
12
//
18
- // Returns an error if the input type is unsupported or if loader creation fails.
13
+ // For string inputs, it applies the following checks in order:
14
+ // 1. URI scheme detection (http/https -> HTTP, file -> Disk)
15
+ // 2. File path format detection (absolute paths, known extensions)
16
+ // 3. Base64 validation (attempts decode)
17
+ // 4. String fallback
18
+ //
19
+ // Other input types:
20
+ // - []byte: FromBytes loader
21
+ // - io.Reader: FromIoReader loader
22
+ // - Loader: returned unchanged
23
+ //
24
+ // Returns an error for unsupported input types or loader creation failures.
19
25
func InferLoader (input any ) (Loader , error ) {
20
26
switch v := input .(type ) {
21
27
case string :
@@ -32,21 +38,20 @@ func InferLoader(input any) (Loader, error) {
32
38
}
33
39
34
40
// inferFromString analyzes a string input and returns the appropriate loader.
35
- // It checks for URI schemes and falls back to treating the string as inline content .
41
+ // It follows this order: scheme check -> file path check -> base64 check -> string fallback .
36
42
func inferFromString (input string ) (Loader , error ) {
37
43
input = strings .TrimSpace (input )
38
44
if input == "" {
39
45
return nil , fmt .Errorf ("empty string input" )
40
46
}
41
47
42
- // Try to parse as URL to detect scheme
48
+ // 1. Check for URI scheme
43
49
if parsed , err := url .Parse (input ); err == nil && parsed .Scheme != "" {
44
50
switch parsed .Scheme {
45
51
case "http" , "https" :
46
52
return NewFromHTTP (input )
47
53
case "file" :
48
54
path := parsed .Path
49
- // Convert relative paths to absolute paths
50
55
if ! filepath .IsAbs (path ) {
51
56
absPath , err := filepath .Abs (path )
52
57
if err != nil {
@@ -55,26 +60,44 @@ func inferFromString(input string) (Loader, error) {
55
60
path = absPath
56
61
}
57
62
return NewFromDisk (path )
58
- default :
59
- // Unknown scheme, treat as inline content
60
- return NewFromStringBase64 (input )
61
63
}
62
64
}
63
65
64
- // Check if it looks like a file path
65
- if filepath .IsAbs (input ) || strings .Contains (input , "/" ) || strings .Contains (input , "\\ " ) {
66
+ // 2. Check if it's a valid file path
67
+ if isValidFilePath (input ) {
68
+ path := input
66
69
// Convert relative paths to absolute paths
67
70
if ! filepath .IsAbs (input ) {
68
71
absPath , err := filepath .Abs (input )
69
72
if err != nil {
70
- // If we can't resolve the path, treat as inline content
71
- return NewFromStringBase64 (input )
73
+ return nil , fmt .Errorf ("failed to resolve relative path %q: %w" , input , err )
72
74
}
73
- input = absPath
75
+ path = absPath
74
76
}
75
- return NewFromDisk (input )
77
+ return NewFromDisk (path )
76
78
}
77
79
78
- // Default to treating as inline string content
80
+ // 3. Use the base64 check to determine if the input is valid base64
81
+ // (it returns FromBytes if valid, otherwise falls back to FromString)
79
82
return NewFromStringBase64 (input )
80
83
}
84
+
85
+ // isValidFilePath checks if a string looks like a valid file path format.
86
+ func isValidFilePath (s string ) bool {
87
+ // Don't consider strings with newlines/carriage returns as file paths
88
+ if strings .ContainsAny (s , "\n \r " ) {
89
+ return false
90
+ }
91
+
92
+ // Check for specific script file extensions (case insensitive)
93
+ validExtensions := []string {".wasm" , ".risor" , ".star" , ".starlark" }
94
+ lower := strings .ToLower (s )
95
+ for _ , ext := range validExtensions {
96
+ if strings .HasSuffix (lower , ext ) {
97
+ return true
98
+ }
99
+ }
100
+
101
+ // Basic file path patterns without filesystem check
102
+ return filepath .IsAbs (s )
103
+ }
0 commit comments