From 367bf0c8fcd96ff56ce1016e52fcb4751331440a Mon Sep 17 00:00:00 2001
From: anatawa12 <anatawa12@icloud.com>
Date: Mon, 20 May 2024 23:21:11 +0900
Subject: fix: `/share` with unicode characters in the URL (#13846)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: `/share` with unicode characters in the URL

* docs(changelog): `/share` で日本語等を含むurlがurlエンコードされない問題を修正
---
 packages/frontend/src/pages/share.vue | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

(limited to 'packages/frontend/src/pages/share.vue')

diff --git a/packages/frontend/src/pages/share.vue b/packages/frontend/src/pages/share.vue
index 680934e7ce..37f6558d64 100644
--- a/packages/frontend/src/pages/share.vue
+++ b/packages/frontend/src/pages/share.vue
@@ -64,7 +64,34 @@ async function init() {
 	// Googleニュース対策
 	if (text?.startsWith(`${title.value}.\n`)) noteText += text.replace(`${title.value}.\n`, '');
 	else if (text && title.value !== text) noteText += `${text}\n`;
-	if (url) noteText += `${url}`;
+	if (url) {
+		try {
+			// Normalize the URL to URL-encoded and puny-coded from with the URL constructor.
+			//
+			// It's common to use unicode characters in the URL for better visibility of URL
+			//     like: https://ja.wikipedia.org/wiki/ミスキー
+			//  or like: https://藍.moe/
+			// However, in the MFM, the unicode characters must be URL-encoded to be parsed as `url` node
+			//     like: https://ja.wikipedia.org/wiki/%E3%83%9F%E3%82%B9%E3%82%AD%E3%83%BC
+			//  or like: https://xn--931a.moe/
+			// Therefore, we need to normalize the URL to URL-encoded form.
+			//
+			// The URL constructor will parse the URL and normalize unicode characters
+			//   in the host to punycode and in the path component to URL-encoded form.
+			//   (see url.spec.whatwg.org)
+			//
+			// In addition, the current MFM renderer decodes the URL-encoded path and / punycode encoded host name so
+			//   this normalization doesn't make the visible URL ugly.
+			//   (see MkUrl.vue)
+
+			noteText += new URL(url).href;
+		} catch {
+			// fallback to original URL if the URL is invalid.
+			// note that this is extremely rare since the `url` parameter is designed to share a URL and
+			// the URL constructor will throw TypeError only if failure, which means the URL is not valid.
+			noteText += url;
+		}
+	}
 	initialText.value = noteText.trim();
 
 	if (visibility.value === 'specified') {
-- 
cgit v1.2.3-freya

