|
4 | 4 |
|
5 | 5 | import 'package:charcode/charcode.dart';
|
6 | 6 | import 'package:meta/meta.dart';
|
| 7 | +import 'package:path/path.dart' as p; |
7 | 8 | import 'package:source_span/source_span.dart';
|
8 | 9 | import 'package:string_scanner/string_scanner.dart';
|
9 | 10 |
|
@@ -59,10 +60,27 @@ class Parser {
|
59 | 60 | @protected
|
60 | 61 | Parser(String contents,
|
61 | 62 | {Object? url, Logger? logger, InterpolationMap? interpolationMap})
|
62 |
| - : scanner = SpanScanner(contents, sourceUrl: url), |
| 63 | + : scanner = |
| 64 | + SpanScanner(contents, sourceUrl: _canonicalizeIfRelative(url)), |
63 | 65 | logger = logger ?? const Logger.stderr(),
|
64 | 66 | _interpolationMap = interpolationMap;
|
65 | 67 |
|
| 68 | + /// If [url] is a relative (possibly String-serialized) URL, canonicalizes it |
| 69 | + /// as a path and returns it as a URL. |
| 70 | + static Uri? _canonicalizeIfRelative(Object? urlOrString) { |
| 71 | + var url = switch (urlOrString) { |
| 72 | + null => null, |
| 73 | + Uri() => urlOrString, |
| 74 | + String() => Uri.parse(urlOrString), |
| 75 | + _ => throw ArgumentError("url $urlOrString must be a Uri or a String") |
| 76 | + }; |
| 77 | + |
| 78 | + return switch (url) { |
| 79 | + Uri(scheme: '') => p.toUri(canonicalize(p.fromUri(url))), |
| 80 | + _ => url |
| 81 | + }; |
| 82 | + } |
| 83 | + |
66 | 84 | String _parseIdentifier() {
|
67 | 85 | return wrapSpanFormatException(() {
|
68 | 86 | var result = identifier();
|
|
0 commit comments