Link uri encoding, URL-escaping should be left alone inside the destination (dart-lang/markdown#598)
By the Rule "URL-escaping should be left alone inside the destination", Reimplement
`normalizeLinkDestination` util function with splitting by URL escapings and concat them
diff --git a/pkgs/markdown/lib/src/util.dart b/pkgs/markdown/lib/src/util.dart
index ddeb22f..93ea1e6 100644
--- a/pkgs/markdown/lib/src/util.dart
+++ b/pkgs/markdown/lib/src/util.dart
@@ -41,21 +41,28 @@
}
/// Normalizes a link destination, including the process of HTML characters
-/// decoding and percent encoding.
+/// decoding and percent encoding.
// See the description of these examples:
// https://spec.commonmark.org/0.30/#example-501
// https://spec.commonmark.org/0.30/#example-502
String normalizeLinkDestination(String destination) {
- // Decode first, because the destination might have been partly encoded.
- // For example https://spec.commonmark.org/0.30/#example-502.
- // With this function, `foo%20bä` will be parsed in the following steps:
- // 1. foo bä
- // 2. foo bä
- // 3. foo%20b%C3%A4
- try {
- destination = Uri.decodeFull(destination);
- } catch (_) {}
- return Uri.encodeFull(decodeHtmlCharacters(destination));
+ // Split by url escaping characters
+ // Concatenate them with unmodified URL-escaping.
+ // URL-escaping should be left alone inside the destination
+ // Refer: https://spec.commonmark.org/0.30/#example-502.
+
+ final regex = RegExp('%[0-9A-Fa-f]{2}');
+
+ return destination.splitMapJoin(
+ regex,
+ onMatch: (m) => m.match,
+ onNonMatch: (e) {
+ try {
+ e = Uri.decodeFull(e);
+ } catch (_) {}
+ return Uri.encodeFull(decodeHtmlCharacters(e));
+ },
+ );
}
/// Normalizes a link title, including the process of HTML characters decoding
diff --git a/pkgs/markdown/test/original/inline_images.unit b/pkgs/markdown/test/original/inline_images.unit
index 9e58264..c8180ce 100644
--- a/pkgs/markdown/test/original/inline_images.unit
+++ b/pkgs/markdown/test/original/inline_images.unit
@@ -22,4 +22,8 @@
)
<<<
-<p><img src="%22onerror=%22alert('XSS')" alt="Uh oh..." /></p>
\ No newline at end of file
+<p><img src="%22onerror=%22alert('XSS')" alt="Uh oh..." /></p>
+>>> URL-escaping should be left alone inside the destination
+
+<<<
+<p><img src="https://example/foo%2Fvar" alt="" /></p>
\ No newline at end of file