diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8fba738..ee5b7f78 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
- `arr.insert`,`arr.remove`を追加
- `arr.sort`の処理を非同期的にして高速化
- `arr.flat`,`arr.flat_map`を追加
+- `Uri:encode_full`, `Uri:encode_component`, `Uri:decode_full`, `Uri:decode_component`を追加
# 0.18.0
- `Core:abort`でプログラムを緊急停止できるように
diff --git a/docs/std.md b/docs/std.md
index d857e498..c3f804e9 100644
--- a/docs/std.md
+++ b/docs/std.md
@@ -116,27 +116,44 @@ _time_offset_ を渡していない場合はローカルのものを参照しま
型: `str`
改行コード(LF)です。
-### #Str:lt(a: str, b: str): num
+### @Str:lt(a: str, b: str): num
a < b ならば -1、a == b ならば 0、a > b ならば 1 を返します。
arr.sortの比較関数として使用できます。
-### #Str:gt(a: str, b: str): num
+### @Str:gt(a: str, b: str): num
a > b ならば -1、a == b ならば 0、a < b ならば 1 を返します。
arr.sortの比較関数として使用できます。
-### #Str:from_codepoint(codepoint: num): str
+### @Str:from_codepoint(codepoint: num): str
Unicodeのコードポイントから文字を生成します。
_codepoint_ は 0 以上、10FFFF16 以下である必要があります。
-### #Str:from_unicode_codepoints(_codePoints_: `arr`): str
+### @Str:from_unicode_codepoints(_codePoints_: `arr`): str
Unicodeのコードポイント列を表す数値の配列から文字を生成します。
_codePoints_の各要素は 0 以上、10FFFF16 以下である必要があります。
-### #Str:from_utf8_bytes(_bytes_: `arr`): str
+### @Str:from_utf8_bytes(_bytes_: `arr`): str
UTF-8のバイト列を表す数値の配列から文字を生成します。
_bytes_の各要素は 0 以上、255 以下である必要があります。
+## :: Uri
+### @Uri:encode_full(uri: str): str
+uri をURIとしてエンコードした文字列を返します。以下の文字はエンコードされません。
+`A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; , / ? : @ & = + $ #`
+
+### @Uri:encode_component(text: str): str
+text をURI構成要素としてエンコードした文字列を返します。以下の文字はエンコードされません。
+`A-Z a-z 0-9 - _ . ! ~ * ' ( )`
+
+### @Uri:decode_full(encoded_uri: str): str
+encoded_uri をエンコードされたURIとしてデコードした文字列を返します。
+以下の文字に対応するエスケープシーケンスはデコードされません。
+`; , / ? : @ & = + $ #`
+
+### @Uri:decode_component(encoded_text: str): str
+encoded_text をエンコードされたURI構成要素としてデコードした文字列を返します。
+
## :: Arr
### @Arr:create(_length_: num, _initial_?: value): arr
長さが`length`の配列を作成します。
diff --git a/src/interpreter/lib/std.ts b/src/interpreter/lib/std.ts
index b3d5081d..b451d7e6 100644
--- a/src/interpreter/lib/std.ts
+++ b/src/interpreter/lib/std.ts
@@ -533,6 +533,28 @@ export const std: Record = {
}),
//#endregion
+ //#region Uri
+ 'Uri:encode_full': FN_NATIVE(([v]) => {
+ assertString(v);
+ return STR(encodeURI(v.value));
+ }),
+
+ 'Uri:encode_component': FN_NATIVE(([v]) => {
+ assertString(v);
+ return STR(encodeURIComponent(v.value));
+ }),
+
+ 'Uri:decode_full': FN_NATIVE(([v]) => {
+ assertString(v);
+ return STR(decodeURI(v.value));
+ }),
+
+ 'Uri:decode_component': FN_NATIVE(([v]) => {
+ assertString(v);
+ return STR(decodeURIComponent(v.value));
+ }),
+ //#endregion
+
//#region Arr
'Arr:create': FN_NATIVE(([length, initial]) => {
assertNumber(length);
diff --git a/test/index.ts b/test/index.ts
index 529e85a5..026603fe 100644
--- a/test/index.ts
+++ b/test/index.ts
@@ -3269,6 +3269,36 @@ describe('std', () => {
});
});
+ describe('Uri', () => {
+ test.concurrent('encode_full', async () => {
+ const res = await exe(`
+ <: Uri:encode_full("https://example.com/?q=あいちゃん")
+ `);
+ eq(res, STR('https://example.com/?q=%E3%81%82%E3%81%84%E3%81%A1%E3%82%83%E3%82%93'));
+ });
+
+ test.concurrent('encode_component', async () => {
+ const res = await exe(`
+ <: Uri:encode_component("https://example.com/?q=あいちゃん")
+ `);
+ eq(res, STR('https%3A%2F%2Fexample.com%2F%3Fq%3D%E3%81%82%E3%81%84%E3%81%A1%E3%82%83%E3%82%93'));
+ });
+
+ test.concurrent('decode_full', async () => {
+ const res = await exe(`
+ <: Uri:decode_full("https%3A%2F%2Fexample.com%2F%3Fq%3D%E3%81%82%E3%81%84%E3%81%A1%E3%82%83%E3%82%93")
+ `);
+ eq(res, STR('https%3A%2F%2Fexample.com%2F%3Fq%3Dあいちゃん'));
+ });
+
+ test.concurrent('decode_component', async () => {
+ const res = await exe(`
+ <: Uri:decode_component("https%3A%2F%2Fexample.com%2F%3Fq%3D%E3%81%82%E3%81%84%E3%81%A1%E3%82%83%E3%82%93")
+ `);
+ eq(res, STR('https://example.com/?q=あいちゃん'));
+ });
+ });
+
describe('Error', () => {
test.concurrent('create', async () => {
eq(
diff --git a/translations/en/docs/std.md b/translations/en/docs/std.md
index 67d36237..32098a9e 100644
--- a/translations/en/docs/std.md
+++ b/translations/en/docs/std.md
@@ -113,19 +113,19 @@ Generates a numeric value from a hexadecimal string.
Type: `str`.
Newline code (LF).
-### #Str:lt(a: str, b: str): num
+### @Str:lt(a: str, b: str): num
Returns -1 if a < b,
0 if a == b,
or 1 if a > b.
Using this as a comparison function for `arr.sort`, the array is sorted in ascending lexicographic order.
-### #Str:gt(a: str, b: str): num
+### @Str:gt(a: str, b: str): num
Returns -1 if a > b,
0 if a == b,
or 1 if a < b.
Using this as the comparison function for `arr.sort`, the array is sorted in descending lexicographic order.
-### #Str:from_codepoint(codepoint: num): str
+### @Str:from_codepoint(codepoint: num): str
Generates character from unicode code point.
_codepoint_ must be greater than or equal to 0 and less than or equal to 10FFFFFF16.
Multiple arguments are not supported yet.