string.test.tsโข64.1 kB
import { randomBytes } from "node:crypto";
import { expect, test } from "vitest";
import * as z from "zod/v4";
const minFive = z.string().min(5, "min5");
const maxFive = z.string().max(5, "max5");
const justFive = z.string().length(5);
const nonempty = z.string().min(1, "nonempty");
const includes = z.string().includes("includes");
const includesFromIndex2 = z.string().includes("includes", { position: 2 });
const startsWith = z.string().startsWith("startsWith");
const endsWith = z.string().endsWith("endsWith");
test("length checks", () => {
  minFive.parse("12345");
  minFive.parse("123456");
  maxFive.parse("12345");
  maxFive.parse("1234");
  nonempty.parse("1");
  justFive.parse("12345");
  expect(() => minFive.parse("1234")).toThrow();
  expect(() => maxFive.parse("123456")).toThrow();
  expect(() => nonempty.parse("")).toThrow();
  expect(() => justFive.parse("1234")).toThrow();
  expect(() => justFive.parse("123456")).toThrow();
});
test("includes", () => {
  includes.parse("XincludesXX");
  includesFromIndex2.parse("XXXincludesXX");
  expect(() => includes.parse("XincludeXX")).toThrow();
  expect(() => includesFromIndex2.parse("XincludesXX")).toThrow();
});
test("startswith/endswith", () => {
  startsWith.parse("startsWithX");
  endsWith.parse("XendsWith");
  expect(() => startsWith.parse("x")).toThrow();
  expect(() => endsWith.parse("x")).toThrow();
});
test("email validations", () => {
  const validEmails = [
    `email@domain.com`,
    `firstname.lastname@domain.com`,
    `email@subdomain.domain.com`,
    `firstname+lastname@domain.com`,
    `1234567890@domain.com`,
    `email@domain-one.com`,
    `_______@domain.com`,
    `email@domain.name`,
    `email@domain.co.jp`,
    `firstname-lastname@domain.com`,
    `very.common@example.com`,
    `disposable.style.email.with+symbol@example.com`,
    `other.email-with-hyphen@example.com`,
    `fully-qualified-domain@example.com`,
    `user.name+tag+sorting@example.com`,
    `x@example.com`,
    `mojojojo@asdf.example.com`,
    `example-indeed@strange-example.com`,
    `example@s.example`,
    `user-@example.org`,
    `user@my-example.com`,
    `a@b.cd`,
    `work+user@mail.com`,
    `tom@test.te-st.com`,
    `something@subdomain.domain-with-hyphens.tld`,
    `common'name@domain.com`,
    `francois@etu.inp-n7.fr`,
  ];
  const invalidEmails = [
    // no "printable characters"
    // `user%example.com@example.org`,
    // `mailhost!username@example.org`,
    // `test/test@test.com`,
    // double @
    `francois@@etu.inp-n7.fr`,
    // do not support quotes
    `"email"@domain.com`,
    `"e asdf sadf ?<>ail"@domain.com`,
    `" "@example.org`,
    `"john..doe"@example.org`,
    `"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com`,
    // do not support comma
    `a,b@domain.com`,
    // do not support IPv4
    `email@123.123.123.123`,
    `email@[123.123.123.123]`,
    `postmaster@123.123.123.123`,
    `user@[68.185.127.196]`,
    `ipv4@[85.129.96.247]`,
    `valid@[79.208.229.53]`,
    `valid@[255.255.255.255]`,
    `valid@[255.0.55.2]`,
    `valid@[255.0.55.2]`,
    // do not support ipv6
    `hgrebert0@[IPv6:4dc8:ac7:ce79:8878:1290:6098:5c50:1f25]`,
    `bshapiro4@[IPv6:3669:c709:e981:4884:59a3:75d1:166b:9ae]`,
    `jsmith@[IPv6:2001:db8::1]`,
    `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]`,
    `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:192.168.1.1]`,
    // microsoft test cases
    `plainaddress`,
    `#@%^%#$@#$@#.com`,
    `@domain.com`,
    `Joe Smith <email@domain.com>`,
    `email.domain.com`,
    `email@domain@domain.com`,
    `.email@domain.com`,
    `email.@domain.com`,
    `email..email@domain.com`,
    `ใใใใใ@domain.com`,
    `email@domain.com (Joe Smith)`,
    `email@domain`,
    `email@-domain.com`,
    `email@111.222.333.44444`,
    `email@domain..com`,
    `Abc.example.com`,
    `A@b@c@example.com`,
    `colin..hacks@domain.com`,
    `a"b(c)d,e:f;g<h>i[j\k]l@example.com`,
    `just"not"right@example.com`,
    `this is"not\allowed@example.com`,
    `this\ still\"not\\allowed@example.com`,
    // random
    `i_like_underscore@but_its_not_allowed_in_this_part.example.com`,
    `QA[icon]CHOCOLATE[icon]@test.com`,
    `invalid@-start.com`,
    `invalid@end.com-`,
    `a.b@c.d`,
    `invalid@[1.1.1.-1]`,
    `invalid@[68.185.127.196.55]`,
    `temp@[192.168.1]`,
    `temp@[9.18.122.]`,
    `double..point@test.com`,
    `asdad@test..com`,
    `asdad@hghg...sd...au`,
    `asdad@hghg........au`,
    `invalid@[256.2.2.48]`,
    `invalid@[256.2.2.48]`,
    `invalid@[999.465.265.1]`,
    `jkibbey4@[IPv6:82c4:19a8::70a9:2aac:557::ea69:d985:28d]`,
    `mlivesay3@[9952:143f:b4df:2179:49a1:5e82:b92e:6b6]`,
    `gbacher0@[IPv6:bc37:4d3f:5048:2e26:37cc:248e:df8e:2f7f:af]`,
    `invalid@[IPv6:5348:4ed3:5d38:67fb:e9b:acd2:c13:192.168.256.1]`,
    `test@.com`,
    `aaaaaaaaaaaaaaalongemailthatcausesregexDoSvulnerability@test.c`,
  ];
  const emailSchema = z.string().email();
  expect(
    validEmails.every((email) => {
      return emailSchema.safeParse(email).success;
    })
  ).toBe(true);
  expect(
    invalidEmails.every((email) => {
      return emailSchema.safeParse(email).success === false;
    })
  ).toBe(true);
});
test("base64 validations", () => {
  const validBase64Strings = [
    "SGVsbG8gV29ybGQ=", // "Hello World"
    "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string"
    "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work"
    "UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // "Patience is the key to success"
    "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun"
    "MTIzNDU2Nzg5MA==", // "1234567890"
    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz"
    "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "ISIkJSMmJyonKCk=", // "!\"#$%&'()*"
    "", // Empty string is technically a valid base64
  ];
  for (const str of validBase64Strings) {
    expect(str + z.string().base64().safeParse(str).success).toBe(`${str}true`);
  }
  const invalidBase64Strings = [
    "12345", // Not padded correctly, not a multiple of 4 characters
    "SGVsbG8gV29ybGQ", // Missing padding
    "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw", // Missing padding
    "!UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // Invalid character '!'
    "?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?'
    ".MTIzND2Nzg5MC4=", // Invalid character '.'
    "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // Missing padding
  ];
  for (const str of invalidBase64Strings) {
    expect(str + z.string().base64().safeParse(str).success).toBe(`${str}false`);
  }
});
test("base64url validations", () => {
  const base64url = z.string().base64url();
  const validBase64URLStrings = [
    "SGVsbG8gV29ybGQ", // "Hello World"
    "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw", // "This is an encoded string"
    "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms", // "Many hands make light work"
    "UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // "Patience is the key to success"
    "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg", // "Base64 encoding is fun"
    "MTIzNDU2Nzg5MA", // "1234567890"
    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo", // "abcdefghijklmnopqrstuvwxyz"
    "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "ISIkJSMmJyonKCk", // "!\"#$%&'()*"
    "", // Empty string is technically valid base64url
    "w7_Dv8O-w74K", // รฟรฟรพรพ
    "123456",
  ];
  for (const str of validBase64URLStrings) {
    expect(str + base64url.safeParse(str).success).toBe(`${str}true`);
  }
  const invalidBase64URLStrings = [
    "w7/Dv8O+w74K", // Has + and / characters (is base64)
    "12345", // Invalid length (not a multiple of 4 characters when adding allowed number of padding characters)
    "12345===", // Not padded correctly
    "!UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // Invalid character '!'
    "?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?'
    ".MTIzND2Nzg5MC4=", // Invalid character '.'
    // disallow valid padding
    "SGVsbG8gV29ybGQ=", // "Hello World" with padding
    "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string" with padding
    "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work" with padding
    "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun" with padding
    "MTIzNDU2Nzg5MA==", // "1234567890" with padding
    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz with padding"
    "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" with padding
    "ISIkJSMmJyonKCk=", // "!\"#$%&'()*" with padding
  ];
  for (const str of invalidBase64URLStrings) {
    expect(str + base64url.safeParse(str).success).toBe(`${str}false`);
  }
});
test("big base64 and base64url", () => {
  const bigbase64 = randomBytes(1024 * 1024 * 10).toString("base64");
  z.base64().parse(bigbase64);
  const bigbase64url = randomBytes(1024 * 1024 * 10).toString("base64url");
  z.base64url().parse(bigbase64url);
});
function makeJwt(header: object, payload: object) {
  const headerBase64 = Buffer.from(JSON.stringify(header)).toString("base64url");
  const payloadBase64 = Buffer.from(JSON.stringify(payload)).toString("base64url");
  const signature = "signature"; // Placeholder for the signature
  return `${headerBase64}.${payloadBase64}.${signature}`;
}
test("jwt token", () => {
  const jwt = z.string().jwt();
  expect(() => jwt.parse("invalid")).toThrow();
  expect(() => jwt.parse("invalid.invalid")).toThrow();
  expect(() => jwt.parse("invalid.invalid.invalid")).toThrow();
  // Valid JWTs
  const es256jwt = z.string().jwt({ alg: "ES256" });
  const d1 = makeJwt({ typ: "JWT", alg: "ES256" }, {});
  jwt.parse(d1);
  es256jwt.parse(d1);
  // Invalid header
  const d2 = makeJwt({}, {});
  expect(() => jwt.parse(d2)).toThrow();
  // Wrong algorithm
  const d3 = makeJwt({ typ: "JWT", alg: "RS256" }, {});
  expect(() => es256jwt.parse(d3)).toThrow();
  // missing typ is fine
  const d4 = makeJwt({ alg: "HS256" }, {});
  jwt.parse(d4);
  // type isn't JWT
  const d5 = makeJwt({ typ: "SUP", alg: "HS256" }, { foo: "bar" });
  expect(() => jwt.parse(d5)).toThrow();
});
test("url validations", () => {
  const url = z.string().url();
  url.parse("http://google.com");
  url.parse("https://google.com/asdf?asdf=ljk3lk4&asdf=234#asdf");
  url.parse("https://anonymous:flabada@developer.mozilla.org/en-US/docs/Web/API/URL/password");
  url.parse("https://localhost");
  url.parse("https://my.local");
  url.parse("http://aslkfjdalsdfkjaf");
  url.parse("http://localhost");
  url.parse("c:");
  expect(() => url.parse("asdf")).toThrow();
  expect(() => url.parse("https:/")).toThrow();
  expect(() => url.parse("asdfj@lkjsdf.com")).toThrow();
  expect(() => url.parse("https://")).toThrow();
});
test("httpurl", () => {
  const httpUrl = z.url({
    protocol: /^https?$/,
    hostname: z.regexes.domain,
    // /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/
  });
  httpUrl.parse("https://example.com");
  httpUrl.parse("http://example.com");
  // ports
  httpUrl.parse("https://example.com:8080");
  httpUrl.parse("http://example.com:8080");
  // subdomains
  httpUrl.parse("https://sub.example.com");
  httpUrl.parse("http://sub.example.com");
  // paths
  httpUrl.parse("https://example.com/path/to/resource");
  httpUrl.parse("http://example.com/path/to/resource");
  // query parameters
  httpUrl.parse("https://example.com/path?query=param");
  httpUrl.parse("http://example.com/path?query=param");
  // fragment identifiers
  httpUrl.parse("https://example.com/path#fragment");
  httpUrl.parse("http://example.com/path#fragment");
  // fails
  expect(() => httpUrl.parse("ftp://example.com")).toThrow();
  expect(() => httpUrl.parse("shttp://example.com")).toThrow();
  expect(() => httpUrl.parse("httpz://example.com")).toThrow();
  expect(() => httpUrl.parse("http://")).toThrow();
  expect(() => httpUrl.parse("http://localhost")).toThrow();
  expect(() => httpUrl.parse("http://-asdf.com")).toThrow();
  expect(() =>
    httpUrl.parse(
      "http://asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf.com"
    )
  ).toThrow();
  expect(() => httpUrl.parse("http://asdf.c")).toThrow();
  expect(() => httpUrl.parse("mailto:asdf@lckj.com")).toThrow();
});
test("url error overrides", () => {
  try {
    z.string().url().parse("https");
  } catch (err) {
    expect((err as z.ZodError).issues[0].message).toEqual("Invalid URL");
  }
  try {
    z.string().url("badurl").parse("https");
  } catch (err) {
    expect((err as z.ZodError).issues[0].message).toEqual("badurl");
  }
  try {
    z.string().url({ message: "badurl" }).parse("https");
  } catch (err) {
    expect((err as z.ZodError).issues[0].message).toEqual("badurl");
  }
});
test("emoji validations", () => {
  const emoji = z.string().emoji();
  emoji.parse("๐๐๐๐");
  emoji.parse("๐บ๐ฉโ๐๐ซก");
  emoji.parse("๐๐๐๐โค๏ธ");
  emoji.parse("๐๐๐๐ก๐ฆ๐ข๐จ๐ซ๐โ๐ก๐น๐๐ฌโก๏ธ๐น๐๐จโ๐ใฝ๏ธ๐ฆ๐๐ด๐๐๐ฐ๐ณ๐บ๐");
  emoji.parse("๐น๐ท๐คฝ๐ฟโโ๏ธ");
  emoji.parse(
    "๐๐๐๐คฃ๐๐๐
๐๐๐๐๐๐๐๐ฅฐ๐๐๐โบ๏ธโบ๐๐ค๐คฉ๐ค๐คจ๐๐๐ถ๐๐๐ฃ๐ฅ๐ฎ๐ค๐ฏ๐ช๐ซ๐ด๐๐๐๐๐คค๐๐๐๐๐๐ค๐ฒโน๏ธโน๐๐๐๐๐ค๐ข๐ญ๐ฆ๐ง๐จ๐ฉ๐คฏ๐ฌ๐ฐ๐ฑ๐ฅต๐ฅถ๐ณ๐คช๐ต๐ก๐ ๐คฌ๐ท๐ค๐ค๐คข๐คฎ๐คง๐๐ค ๐ฅณ๐ฅด๐ฅบ๐คฅ๐คซ๐คญ๐ง๐ค๐๐ฟ๐คก๐น๐บ๐โ ๏ธโ ๐ป๐ฝ๐พ๐ค๐ฉ๐บ๐ธ๐น๐ป๐ผ๐ฝ๐๐ฟ๐พ๐๐๐๐ป๐ผ๐ฝ๐พ๐ฟ๐ถ๐ถ๐ป๐ถ๐ผ๐ถ๐ฝ๐ถ๐พ๐ถ๐ฟ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐ฆ๐ฆ๐ป๐ฆ๐ผ๐ฆ๐ฝ๐ฆ๐พ๐ฆ๐ฟ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐จ๐จ๐ป๐จ๐ผ๐จ๐ฝ๐จ๐พ๐จ๐ฟ๐ฉ๐ฉ๐ป๐ฉ๐ผ๐ฉ๐ฝ๐ฉ๐พ๐ฉ๐ฟ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐ด๐ด๐ป๐ด๐ผ๐ด๐ฝ๐ด๐พ๐ด๐ฟ๐ต๐ต๐ป๐ต๐ผ๐ต๐ฝ๐ต๐พ๐ต๐ฟ๐จโโ๏ธ๐จโโ๐จ๐ปโโ๏ธ๐จ๐ปโโ๐จ๐ผโโ๏ธ๐จ๐ผโโ๐จ๐ฝโโ๏ธ๐จ๐ฝโโ๐จ๐พโโ๏ธ๐จ๐พโโ๐จ๐ฟโโ๏ธ๐จ๐ฟโโ๐ฉโโ๏ธ๐ฉโโ๐ฉ๐ปโโ๏ธ๐ฉ๐ปโโ๐ฉ๐ผโโ๏ธ๐ฉ๐ผโโ๐ฉ๐ฝโโ๏ธ๐ฉ๐ฝโโ๐ฉ๐พโโ๏ธ๐ฉ๐พโโ๐ฉ๐ฟโโ๏ธ๐ฉ๐ฟโโ๐จโ๐๐จ๐ปโ๐๐จ๐ผโ๐๐จ๐ฝโ๐๐จ๐พโ๐๐จ๐ฟโ๐๐ฉโ๐๐ฉ๐ปโ๐๐ฉ๐ผโ๐๐ฉ๐ฝโ๐๐ฉ๐พโ๐๐ฉ๐ฟโ๐๐จโ๐ซ๐จ๐ปโ๐ซ๐จ๐ผโ๐ซ๐จ๐ฝโ๐ซ๐จ๐พโ๐ซ๐จ๐ฟโ๐ซ๐ฉโ๐ซ๐ฉ๐ปโ๐ซ๐ฉ๐ผโ๐ซ๐ฉ๐ฝโ๐ซ๐ฉ๐พโ๐ซ๐ฉ๐ฟโ๐ซ๐จโโ๏ธ๐จโโ๐จ๐ปโโ๏ธ๐จ๐ปโโ๐จ๐ผโโ๏ธ๐จ๐ผโโ๐จ๐ฝโโ๏ธ๐จ๐ฝโโ๐จ๐พโโ๏ธ๐จ๐พโโ๐จ๐ฟโโ๏ธ๐จ๐ฟโโ๐ฉโโ๏ธ๐ฉโโ๐ฉ๐ปโโ๏ธ๐ฉ๐ปโโ๐ฉ๐ผโโ๏ธ๐ฉ๐ผโโ๐ฉ๐ฝโโ๏ธ๐ฉ๐ฝโโ๐ฉ๐พโโ๏ธ๐ฉ๐พโโ๐ฉ๐ฟโโ๏ธ๐ฉ๐ฟโโ๐จโ๐พ๐จ๐ปโ๐พ๐จ๐ผโ๐พ๐จ๐ฝโ๐พ๐จ๐พโ๐พ๐จ๐ฟโ๐พ๐ฉโ๐พ๐ฉ๐ปโ๐พ๐ฉ๐ผโ๐พ๐ฉ๐ฝโ๐พ๐ฉ๐พโ๐พ๐ฉ๐ฟโ๐พ๐จโ๐ณ๐จ๐ปโ๐ณ๐จ๐ผโ๐ณ๐จ๐ฝโ๐ณ๐จ๐พโ๐ณ๐จ๐ฟโ๐ณ๐ฉโ๐ณ๐ฉ๐ปโ๐ณ๐ฉ๐ผโ๐ณ๐ฉ๐ฝโ๐ณ๐ฉ๐พโ๐ณ๐ฉ๐ฟโ๐ณ๐จโ๐ง๐จ๐ปโ๐ง๐จ๐ผโ๐ง๐จ๐ฝโ๐ง๐จ๐พโ๐ง๐จ๐ฟโ๐ง๐ฉโ๐ง๐ฉ๐ปโ๐ง๐ฉ๐ผโ๐ง๐ฉ๐ฝโ๐ง๐ฉ๐พโ๐ง๐ฉ๐ฟโ๐ง๐จโ๐ญ๐จ๐ปโ๐ญ๐จ๐ผโ๐ญ๐จ๐ฝโ๐ญ๐จ๐พโ๐ญ๐จ๐ฟโ๐ญ๐ฉโ๐ญ๐ฉ๐ปโ๐ญ๐ฉ๐ผโ๐ญ๐ฉ๐ฝโ๐ญ๐ฉ๐พโ๐ญ๐ฉ๐ฟโ๐ญ๐จโ๐ผ๐จ๐ปโ๐ผ๐จ๐ผโ๐ผ๐จ๐ฝโ๐ผ๐จ๐พโ๐ผ๐จ๐ฟโ๐ผ๐ฉโ๐ผ๐ฉ๐ปโ๐ผ๐ฉ๐ผโ๐ผ๐ฉ๐ฝโ๐ผ๐ฉ๐พโ๐ผ๐ฉ๐ฟโ๐ผ๐จโ๐ฌ๐จ๐ปโ๐ฌ๐จ๐ผโ๐ฌ๐จ๐ฝโ๐ฌ๐จ๐พโ๐ฌ๐จ๐ฟโ๐ฌ๐ฉโ๐ฌ๐ฉ๐ปโ๐ฌ๐ฉ๐ผโ๐ฌ๐ฉ๐ฝโ๐ฌ๐ฉ๐พโ๐ฌ๐ฉ๐ฟโ๐ฌ๐จโ๐ป๐จ๐ปโ๐ป๐จ๐ผโ๐ป๐จ๐ฝโ๐ป๐จ๐พโ๐ป๐จ๐ฟโ๐ป๐ฉโ๐ป๐ฉ๐ปโ๐ป๐ฉ๐ผโ๐ป๐ฉ๐ฝโ๐ป๐ฉ๐พโ๐ป๐ฉ๐ฟโ๐ป๐จโ๐ค๐จ๐ปโ๐ค๐จ๐ผโ๐ค๐จ๐ฝโ๐ค๐จ๐พโ๐ค๐จ๐ฟโ๐ค๐ฉโ๐ค๐ฉ๐ปโ๐ค๐ฉ๐ผโ๐ค๐ฉ๐ฝโ๐ค๐ฉ๐พโ๐ค๐ฉ๐ฟโ๐ค๐จโ๐จ๐จ๐ปโ๐จ๐จ๐ผโ๐จ๐จ๐ฝโ๐จ๐จ๐พโ๐จ๐จ๐ฟโ๐จ๐ฉโ๐จ๐ฉ๐ปโ๐จ๐ฉ๐ผโ๐จ๐ฉ๐ฝโ๐จ๐ฉ๐พโ๐จ๐ฉ๐ฟโ๐จ๐จโโ๏ธ๐จโโ๐จ๐ปโโ๏ธ๐จ๐ปโโ๐จ๐ผโโ๏ธ๐จ๐ผโโ๐จ๐ฝโโ๏ธ๐จ๐ฝโโ๐จ๐พโโ๏ธ๐จ๐พโโ๐จ๐ฟโโ๏ธ๐จ๐ฟโโ๐ฉโโ๏ธ๐ฉโโ๐ฉ๐ปโโ๏ธ๐ฉ๐ปโโ๐ฉ๐ผโโ๏ธ๐ฉ๐ผโโ๐ฉ๐ฝโโ๏ธ๐ฉ๐ฝโโ๐ฉ๐พโโ๏ธ๐ฉ๐พโโ๐ฉ๐ฟโโ๏ธ๐ฉ๐ฟโโ๐จโ๐๐จ๐ปโ๐๐จ๐ผโ๐๐จ๐ฝโ๐๐จ๐พโ๐๐จ๐ฟโ๐๐ฉโ๐๐ฉ๐ปโ๐๐ฉ๐ผโ๐๐ฉ๐ฝโ๐๐ฉ๐พโ๐๐ฉ๐ฟโ๐๐จโ๐๐จ๐ปโ๐๐จ๐ผโ๐๐จ๐ฝโ๐๐จ๐พโ๐๐จ๐ฟโ๐๐ฉโ๐๐ฉ๐ปโ๐๐ฉ๐ผโ๐๐ฉ๐ฝโ๐๐ฉ๐พโ๐๐ฉ๐ฟโ๐๐ฎ๐ฎ๐ป๐ฎ๐ผ๐ฎ๐ฝ๐ฎ๐พ๐ฎ๐ฟ๐ฎโโ๏ธ๐ฎโโ๐ฎ๐ปโโ๏ธ๐ฎ๐ปโโ๐ฎ๐ผโโ๏ธ๐ฎ๐ผโโ๐ฎ๐ฝโโ๏ธ๐ฎ๐ฝโโ๐ฎ๐พโโ๏ธ๐ฎ๐พโโ๐ฎ๐ฟโโ๏ธ๐ฎ๐ฟโโ๐ฎโโ๏ธ๐ฎโโ๐ฎ๐ปโโ๏ธ๐ฎ๐ปโโ๐ฎ๐ผโโ๏ธ๐ฎ๐ผโโ๐ฎ๐ฝโโ๏ธ๐ฎ๐ฝโโ๐ฎ๐พโโ๏ธ๐ฎ๐พโโ๐ฎ๐ฟโโ๏ธ๐ฎ๐ฟโโ๐ต๏ธ๐ต๐ต๐ป๐ต๐ผ๐ต๐ฝ๐ต๐พ๐ต๐ฟ๐ต๏ธโโ๏ธ๐ตโโ๏ธ๐ต๏ธโโ๐ตโโ๐ต๐ปโโ๏ธ๐ต๐ปโโ๐ต๐ผโโ๏ธ๐ต๐ผโโ๐ต๐ฝโโ๏ธ๐ต๐ฝโโ๐ต๐พโโ๏ธ๐ต๐พโโ๐ต๐ฟโโ๏ธ๐ต๐ฟโโ๐ต๏ธโโ๏ธ๐ตโโ๏ธ๐ต๏ธโโ๐ตโโ๐ต๐ปโโ๏ธ๐ต๐ปโโ๐ต๐ผโโ๏ธ๐ต๐ผโโ๐ต๐ฝโโ๏ธ๐ต๐ฝโโ๐ต๐พโโ๏ธ๐ต๐พโโ๐ต๐ฟโโ๏ธ๐ต๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐ท๐ท๐ป๐ท๐ผ๐ท๐ฝ๐ท๐พ๐ท๐ฟ๐ทโโ๏ธ๐ทโโ๐ท๐ปโโ๏ธ๐ท๐ปโโ๐ท๐ผโโ๏ธ๐ท๐ผโโ๐ท๐ฝโโ๏ธ๐ท๐ฝโโ๐ท๐พโโ๏ธ๐ท๐พโโ๐ท๐ฟโโ๏ธ๐ท๐ฟโโ๐ทโโ๏ธ๐ทโโ๐ท๐ปโโ๏ธ๐ท๐ปโโ๐ท๐ผโโ๏ธ๐ท๐ผโโ๐ท๐ฝโโ๏ธ๐ท๐ฝโโ๐ท๐พโโ๏ธ๐ท๐พโโ๐ท๐ฟโโ๏ธ๐ท๐ฟโโ๐คด๐คด๐ป๐คด๐ผ๐คด๐ฝ๐คด๐พ๐คด๐ฟ๐ธ๐ธ๐ป๐ธ๐ผ๐ธ๐ฝ๐ธ๐พ๐ธ๐ฟ๐ณ๐ณ๐ป๐ณ๐ผ๐ณ๐ฝ๐ณ๐พ๐ณ๐ฟ๐ณโโ๏ธ๐ณโโ๐ณ๐ปโโ๏ธ๐ณ๐ปโโ๐ณ๐ผโโ๏ธ๐ณ๐ผโโ๐ณ๐ฝโโ๏ธ๐ณ๐ฝโโ๐ณ๐พโโ๏ธ๐ณ๐พโโ๐ณ๐ฟโโ๏ธ๐ณ๐ฟโโ๐ณโโ๏ธ๐ณโโ๐ณ๐ปโโ๏ธ๐ณ๐ปโโ๐ณ๐ผโโ๏ธ๐ณ๐ผโโ๐ณ๐ฝโโ๏ธ๐ณ๐ฝโโ๐ณ๐พโโ๏ธ๐ณ๐พโโ๐ณ๐ฟโโ๏ธ๐ณ๐ฟโโ๐ฒ๐ฒ๐ป๐ฒ๐ผ๐ฒ๐ฝ๐ฒ๐พ๐ฒ๐ฟ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐ฑ๐ฑ๐ป๐ฑ๐ผ๐ฑ๐ฝ๐ฑ๐พ๐ฑ๐ฟ๐ฑโโ๏ธ๐ฑโโ๐ฑ๐ปโโ๏ธ๐ฑ๐ปโโ๐ฑ๐ผโโ๏ธ๐ฑ๐ผโโ๐ฑ๐ฝโโ๏ธ๐ฑ๐ฝโโ๐ฑ๐พโโ๏ธ๐ฑ๐พโโ๐ฑ๐ฟโโ๏ธ๐ฑ๐ฟโโ๐ฑโโ๏ธ๐ฑโโ๐ฑ๐ปโโ๏ธ๐ฑ๐ปโโ๐ฑ๐ผโโ๏ธ๐ฑ๐ผโโ๐ฑ๐ฝโโ๏ธ๐ฑ๐ฝโโ๐ฑ๐พโโ๏ธ๐ฑ๐พโโ๐ฑ๐ฟโโ๏ธ๐ฑ๐ฟโโ๐จโ๐ฆฐ๐จ๐ปโ๐ฆฐ๐จ๐ผโ๐ฆฐ๐จ๐ฝโ๐ฆฐ๐จ๐พโ๐ฆฐ๐จ๐ฟโ๐ฆฐ๐ฉโ๐ฆฐ๐ฉ๐ปโ๐ฆฐ๐ฉ๐ผโ๐ฆฐ๐ฉ๐ฝโ๐ฆฐ๐ฉ๐พโ๐ฆฐ๐ฉ๐ฟโ๐ฆฐ๐จโ๐ฆฑ๐จ๐ปโ๐ฆฑ๐จ๐ผโ๐ฆฑ๐จ๐ฝโ๐ฆฑ๐จ๐พโ๐ฆฑ๐จ๐ฟโ๐ฆฑ๐ฉโ๐ฆฑ๐ฉ๐ปโ๐ฆฑ๐ฉ๐ผโ๐ฆฑ๐ฉ๐ฝโ๐ฆฑ๐ฉ๐พโ๐ฆฑ๐ฉ๐ฟโ๐ฆฑ๐จโ๐ฆฒ๐จ๐ปโ๐ฆฒ๐จ๐ผโ๐ฆฒ๐จ๐ฝโ๐ฆฒ๐จ๐พโ๐ฆฒ๐จ๐ฟโ๐ฆฒ๐ฉโ๐ฆฒ๐ฉ๐ปโ๐ฆฒ๐ฉ๐ผโ๐ฆฒ๐ฉ๐ฝโ๐ฆฒ๐ฉ๐พโ๐ฆฒ๐ฉ๐ฟโ๐ฆฒ๐จโ๐ฆณ๐จ๐ปโ๐ฆณ๐จ๐ผโ๐ฆณ๐จ๐ฝโ๐ฆณ๐จ๐พโ๐ฆณ๐จ๐ฟโ๐ฆณ๐ฉโ๐ฆณ๐ฉ๐ปโ๐ฆณ๐ฉ๐ผโ๐ฆณ๐ฉ๐ฝโ๐ฆณ๐ฉ๐พโ๐ฆณ๐ฉ๐ฟโ๐ฆณ๐คต๐คต๐ป๐คต๐ผ๐คต๐ฝ๐คต๐พ๐คต๐ฟ๐ฐ๐ฐ๐ป๐ฐ๐ผ๐ฐ๐ฝ๐ฐ๐พ๐ฐ๐ฟ๐คฐ๐คฐ๐ป๐คฐ๐ผ๐คฐ๐ฝ๐คฐ๐พ๐คฐ๐ฟ๐คฑ๐คฑ๐ป๐คฑ๐ผ๐คฑ๐ฝ๐คฑ๐พ๐คฑ๐ฟ๐ผ๐ผ๐ป๐ผ๐ผ๐ผ๐ฝ๐ผ๐พ๐ผ๐ฟ๐
๐
๐ป๐
๐ผ๐
๐ฝ๐
๐พ๐
๐ฟ๐คถ๐คถ๐ป๐คถ๐ผ๐คถ๐ฝ๐คถ๐พ๐คถ๐ฟ๐ฆธ๐ฆธ๐ป๐ฆธ๐ผ๐ฆธ๐ฝ๐ฆธ๐พ๐ฆธ๐ฟ๐ฆธโโ๏ธ๐ฆธโโ๐ฆธ๐ปโโ๏ธ๐ฆธ๐ปโโ๐ฆธ๐ผโโ๏ธ๐ฆธ๐ผโโ๐ฆธ๐ฝโโ๏ธ๐ฆธ๐ฝโโ๐ฆธ๐พโโ๏ธ๐ฆธ๐พโโ๐ฆธ๐ฟโโ๏ธ๐ฆธ๐ฟโโ๐ฆธโโ๏ธ๐ฆธโโ๐ฆธ๐ปโโ๏ธ๐ฆธ๐ปโโ๐ฆธ๐ผโโ๏ธ๐ฆธ๐ผโโ๐ฆธ๐ฝโโ๏ธ๐ฆธ๐ฝโโ๐ฆธ๐พโโ๏ธ๐ฆธ๐พโโ๐ฆธ๐ฟโโ๏ธ๐ฆธ๐ฟโโ๐ฆน๐ฆน๐ป๐ฆน๐ผ๐ฆน๐ฝ๐ฆน๐พ๐ฆน๐ฟ๐ฆนโโ๏ธ๐ฆนโโ๐ฆน๐ปโโ๏ธ๐ฆน๐ปโโ๐ฆน๐ผโโ๏ธ๐ฆน๐ผโโ๐ฆน๐ฝโโ๏ธ๐ฆน๐ฝโโ๐ฆน๐พโโ๏ธ๐ฆน๐พโโ๐ฆน๐ฟโโ๏ธ๐ฆน๐ฟโโ๐ฆนโโ๏ธ๐ฆนโโ๐ฆน๐ปโโ๏ธ๐ฆน๐ปโโ๐ฆน๐ผโโ๏ธ๐ฆน๐ผโโ๐ฆน๐ฝโโ๏ธ๐ฆน๐ฝโโ๐ฆน๐พโโ๏ธ๐ฆน๐พโโ๐ฆน๐ฟโโ๏ธ๐ฆน๐ฟโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐ง๐งโโ๏ธ๐งโโ๐งโโ๏ธ๐งโโ๐ง๐งโโ๏ธ๐งโโ๐งโโ๏ธ๐งโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐
๐
๐ป๐
๐ผ๐
๐ฝ๐
๐พ๐
๐ฟ๐
โโ๏ธ๐
โโ๐
๐ปโโ๏ธ๐
๐ปโโ๐
๐ผโโ๏ธ๐
๐ผโโ๐
๐ฝโโ๏ธ๐
๐ฝโโ๐
๐พโโ๏ธ๐
๐พโโ๐
๐ฟโโ๏ธ๐
๐ฟโโ๐
โโ๏ธ๐
โโ๐
๐ปโโ๏ธ๐
๐ปโโ๐
๐ผโโ๏ธ๐
๐ผโโ๐
๐ฝโโ๏ธ๐
๐ฝโโ๐
๐พโโ๏ธ๐
๐พโโ๐
๐ฟโโ๏ธ๐
๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐คฆ๐คฆ๐ป๐คฆ๐ผ๐คฆ๐ฝ๐คฆ๐พ๐คฆ๐ฟ๐คฆโโ๏ธ๐คฆโโ๐คฆ๐ปโโ๏ธ๐คฆ๐ปโโ๐คฆ๐ผโโ๏ธ๐คฆ๐ผโโ๐คฆ๐ฝโโ๏ธ๐คฆ๐ฝโโ๐คฆ๐พโโ๏ธ๐คฆ๐พโโ๐คฆ๐ฟโโ๏ธ๐คฆ๐ฟโโ๐คฆโโ๏ธ๐คฆโโ๐คฆ๐ปโโ๏ธ๐คฆ๐ปโโ๐คฆ๐ผโโ๏ธ๐คฆ๐ผโโ๐คฆ๐ฝโโ๏ธ๐คฆ๐ฝโโ๐คฆ๐พโโ๏ธ๐คฆ๐พโโ๐คฆ๐ฟโโ๏ธ๐คฆ๐ฟโโ๐คท๐คท๐ป๐คท๐ผ๐คท๐ฝ๐คท๐พ๐คท๐ฟ๐คทโโ๏ธ๐คทโโ๐คท๐ปโโ๏ธ๐คท๐ปโโ๐คท๐ผโโ๏ธ๐คท๐ผโโ๐คท๐ฝโโ๏ธ๐คท๐ฝโโ๐คท๐พโโ๏ธ๐คท๐พโโ๐คท๐ฟโโ๏ธ๐คท๐ฟโโ๐คทโโ๏ธ๐คทโโ๐คท๐ปโโ๏ธ๐คท๐ปโโ๐คท๐ผโโ๏ธ๐คท๐ผโโ๐คท๐ฝโโ๏ธ๐คท๐ฝโโ๐คท๐พโโ๏ธ๐คท๐พโโ๐คท๐ฟโโ๏ธ๐คท๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐ถ๐ถ๐ป๐ถ๐ผ๐ถ๐ฝ๐ถ๐พ๐ถ๐ฟ๐ถโโ๏ธ๐ถโโ๐ถ๐ปโโ๏ธ๐ถ๐ปโโ๐ถ๐ผโโ๏ธ๐ถ๐ผโโ๐ถ๐ฝโโ๏ธ๐ถ๐ฝโโ๐ถ๐พโโ๏ธ๐ถ๐พโโ๐ถ๐ฟโโ๏ธ๐ถ๐ฟโโ๐ถโโ๏ธ๐ถโโ๐ถ๐ปโโ๏ธ๐ถ๐ปโโ๐ถ๐ผโโ๏ธ๐ถ๐ผโโ๐ถ๐ฝโโ๏ธ๐ถ๐ฝโโ๐ถ๐พโโ๏ธ๐ถ๐พโโ๐ถ๐ฟโโ๏ธ๐ถ๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐บ๐บ๐ป๐บ๐ผ๐บ๐ฝ๐บ๐พ๐บ๐ฟ๐ฏ๐ฏโโ๏ธ๐ฏโโ๐ฏโโ๏ธ๐ฏโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐ง๐ง๐ป๐ง๐ผ๐ง๐ฝ๐ง๐พ๐ง๐ฟ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐งโโ๏ธ๐งโโ๐ง๐ปโโ๏ธ๐ง๐ปโโ๐ง๐ผโโ๏ธ๐ง๐ผโโ๐ง๐ฝโโ๏ธ๐ง๐ฝโโ๐ง๐พโโ๏ธ๐ง๐พโโ๐ง๐ฟโโ๏ธ๐ง๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐ด๏ธ๐ด๐ด๐ป๐ด๐ผ๐ด๐ฝ๐ด๐พ๐ด๐ฟ๐ฃ๏ธ๐ฃ๐ค๐ฅ๐คบ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟโท๏ธโท๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๏ธ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๏ธโโ๏ธ๐โโ๏ธ๐๏ธโโ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๏ธโโ๏ธ๐โโ๏ธ๐๏ธโโ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐ฃ๐ฃ๐ป๐ฃ๐ผ๐ฃ๐ฝ๐ฃ๐พ๐ฃ๐ฟ๐ฃโโ๏ธ๐ฃโโ๐ฃ๐ปโโ๏ธ๐ฃ๐ปโโ๐ฃ๐ผโโ๏ธ๐ฃ๐ผโโ๐ฃ๐ฝโโ๏ธ๐ฃ๐ฝโโ๐ฃ๐พโโ๏ธ๐ฃ๐พโโ๐ฃ๐ฟโโ๏ธ๐ฃ๐ฟโโ๐ฃโโ๏ธ๐ฃโโ๐ฃ๐ปโโ๏ธ๐ฃ๐ปโโ๐ฃ๐ผโโ๏ธ๐ฃ๐ผโโ๐ฃ๐ฝโโ๏ธ๐ฃ๐ฝโโ๐ฃ๐พโโ๏ธ๐ฃ๐พโโ๐ฃ๐ฟโโ๏ธ๐ฃ๐ฟโโ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐โโ๏ธ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโโน๏ธโนโน๐ปโน๐ผโน๐ฝโน๐พโน๐ฟโน๏ธโโ๏ธโนโโ๏ธโน๏ธโโโนโโโน๐ปโโ๏ธโน๐ปโโโน๐ผโโ๏ธโน๐ผโโโน๐ฝโโ๏ธโน๐ฝโโโน๐พโโ๏ธโน๐พโโโน๐ฟโโ๏ธโน๐ฟโโโน๏ธโโ๏ธโนโโ๏ธโน๏ธโโโนโโโน๐ปโโ๏ธโน๐ปโโโน๐ผโโ๏ธโน๐ผโโโน๐ฝโโ๏ธโน๐ฝโโโน๐พโโ๏ธโน๐พโโโน๐ฟโโ๏ธโน๐ฟโโ๐๏ธ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๏ธโโ๏ธ๐โโ๏ธ๐๏ธโโ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐๏ธโโ๏ธ๐โโ๏ธ๐๏ธโโ๐โโ๐๐ปโโ๏ธ๐๐ปโโ๐๐ผโโ๏ธ๐๐ผโโ๐๐ฝโโ๏ธ๐๐ฝโโ๐๐พโโ๏ธ๐๐พโโ๐๐ฟโโ๏ธ๐๐ฟโโ๐ด๐ด๐ป๐ด๐ผ๐ด๐ฝ๐ด๐พ๐ด๐ฟ๐ดโโ๏ธ๐ดโโ๐ด๐ปโโ๏ธ๐ด๐ปโโ๐ด๐ผโโ๏ธ๐ด๐ผโโ๐ด๐ฝโโ๏ธ๐ด๐ฝโโ๐ด๐พโโ๏ธ๐ด๐พโโ๐ด๐ฟโโ๏ธ๐ด๐ฟโโ๐ดโโ๏ธ๐ดโโ๐ด๐ปโโ๏ธ๐ด๐ปโโ๐ด๐ผโโ๏ธ๐ด๐ผโโ๐ด๐ฝโโ๏ธ๐ด๐ฝโโ๐ด๐พโโ๏ธ๐ด๐พโโ๐ด๐ฟโโ๏ธ๐ด๐ฟโโ๐ต๐ต๐ป๐ต๐ผ๐ต๐ฝ๐ต๐พ๐ต๐ฟ๐ตโโ๏ธ๐ตโโ๐ต๐ปโโ๏ธ๐ต๐ปโโ๐ต๐ผโโ๏ธ๐ต๐ผโโ๐ต๐ฝโโ๏ธ๐ต๐ฝโโ๐ต๐พโโ๏ธ๐ต๐พโโ๐ต๐ฟโโ๏ธ๐ต๐ฟโโ๐ตโโ๏ธ๐ตโโ๐ต๐ปโโ๏ธ๐ต๐ปโโ๐ต๐ผโโ๏ธ๐ต๐ผโโ๐ต๐ฝโโ๏ธ๐ต๐ฝโโ๐ต๐พโโ๏ธ๐ต๐พโโ๐ต๐ฟโโ๏ธ๐ต๐ฟโโ๐๏ธ๐๐๏ธ๐๐คธ๐คธ๐ป๐คธ๐ผ๐คธ๐ฝ๐คธ๐พ๐คธ๐ฟ๐คธโโ๏ธ๐คธโโ๐คธ๐ปโโ๏ธ๐คธ๐ปโโ๐คธ๐ผโโ๏ธ๐คธ๐ผโโ๐คธ๐ฝโโ๏ธ๐คธ๐ฝโโ๐คธ๐พโโ๏ธ๐คธ๐พโโ๐คธ๐ฟโโ๏ธ๐คธ๐ฟโโ๐คธโโ๏ธ๐คธโโ๐คธ๐ปโโ๏ธ๐คธ๐ปโโ๐คธ๐ผโโ๏ธ๐คธ๐ผโโ๐คธ๐ฝโโ๏ธ๐คธ๐ฝโโ๐คธ๐พโโ๏ธ๐คธ๐พโโ๐คธ๐ฟโโ๏ธ๐คธ๐ฟโโ๐คผ๐คผโโ๏ธ๐คผโโ๐คผโโ๏ธ๐คผโโ๐คฝ๐คฝ๐ป๐คฝ๐ผ๐คฝ๐ฝ๐คฝ๐พ๐คฝ๐ฟ๐คฝโโ๏ธ๐คฝโโ๐คฝ๐ปโโ๏ธ๐คฝ๐ปโโ๐คฝ๐ผโโ๏ธ๐คฝ๐ผโโ๐คฝ๐ฝโโ๏ธ๐คฝ๐ฝโโ๐คฝ๐พโโ๏ธ๐คฝ๐พโโ๐คฝ๐ฟโโ๏ธ๐คฝ๐ฟโโ๐คฝโโ๏ธ๐คฝโโ๐คฝ๐ปโโ๏ธ๐คฝ๐ปโโ๐คฝ๐ผโโ๏ธ๐คฝ๐ผโโ๐คฝ๐ฝโโ๏ธ๐คฝ๐ฝโโ๐คฝ๐พโโ๏ธ๐คฝ๐พโโ๐คฝ๐ฟโโ๏ธ๐คฝ๐ฟโโ๐คพ๐คพ๐ป๐คพ๐ผ๐คพ๐ฝ๐คพ๐พ๐คพ๐ฟ๐คพโโ๏ธ๐คพโโ๐คพ๐ปโโ๏ธ๐คพ๐ปโโ๐คพ๐ผโโ๏ธ๐คพ๐ผโโ๐คพ๐ฝโโ๏ธ๐คพ๐ฝโโ๐คพ๐พโโ๏ธ๐คพ๐พโโ๐คพ๐ฟโโ๏ธ๐คพ๐ฟโโ๐คพโโ๏ธ๐คพโโ๐คพ๐ปโโ๏ธ๐คพ๐ปโโ๐คพ๐ผโโ๏ธ๐คพ๐ผโโ๐คพ๐ฝโโ๏ธ๐คพ๐ฝโโ๐คพ๐พโโ๏ธ๐คพ๐พโโ๐คพ๐ฟโโ๏ธ๐คพ๐ฟโโ๐คน๐คน๐ป๐คน๐ผ๐คน๐ฝ๐คน๐พ๐คน๐ฟ๐คนโโ๏ธ๐คนโโ๐คน๐ปโโ๏ธ๐คน๐ปโโ๐คน๐ผโโ๏ธ๐คน๐ผโโ๐คน๐ฝโโ๏ธ๐คน๐ฝโโ๐คน๐พโโ๏ธ๐คน๐พโโ๐คน๐ฟโโ๏ธ๐คน๐ฟโโ๐คนโโ๏ธ๐คนโโ๐คน๐ปโโ๏ธ๐คน๐ปโโ๐คน๐ผโโ๏ธ๐คน๐ผโโ๐คน๐ฝโโ๏ธ๐คน๐ฝโโ๐คน๐พโโ๏ธ๐คน๐พโโ๐คน๐ฟโโ๏ธ๐คน๐ฟโโ๐ซ๐ฌ๐ญ๐๐ฉโโค๏ธโ๐โ๐จ๐ฉโโคโ๐โ๐จ๐จโโค๏ธโ๐โ๐จ๐จโโคโ๐โ๐จ๐ฉโโค๏ธโ๐โ๐ฉ๐ฉโโคโ๐โ๐ฉ๐๐ฉโโค๏ธโ๐จ๐ฉโโคโ๐จ๐จโโค๏ธโ๐จ๐จโโคโ๐จ๐ฉโโค๏ธโ๐ฉ๐ฉโโคโ๐ฉ๐ช๐จโ๐ฉโ๐ฆ๐จโ๐ฉโ๐ง๐จโ๐ฉโ๐งโ๐ฆ๐จโ๐ฉโ๐ฆโ๐ฆ๐จโ๐ฉโ๐งโ๐ง๐จโ๐จโ๐ฆ๐จโ๐จโ๐ง๐จโ๐จโ๐งโ๐ฆ๐จโ๐จโ๐ฆโ๐ฆ๐จโ๐จโ๐งโ๐ง๐ฉโ๐ฉโ๐ฆ๐ฉโ๐ฉโ๐ง๐ฉโ๐ฉโ๐งโ๐ฆ๐ฉโ๐ฉโ๐ฆโ๐ฆ๐ฉโ๐ฉโ๐งโ๐ง๐จโ๐ฆ๐จโ๐ฆโ๐ฆ๐จโ๐ง๐จโ๐งโ๐ฆ๐จโ๐งโ๐ง๐ฉโ๐ฆ๐ฉโ๐ฆโ๐ฆ๐ฉโ๐ง๐ฉโ๐งโ๐ฆ๐ฉโ๐งโ๐ง๐คณ๐คณ๐ป๐คณ๐ผ๐คณ๐ฝ๐คณ๐พ๐คณ๐ฟ๐ช๐ช๐ป๐ช๐ผ๐ช๐ฝ๐ช๐พ๐ช๐ฟ๐ฆต๐ฆต๐ป๐ฆต๐ผ๐ฆต๐ฝ๐ฆต๐พ๐ฆต๐ฟ๐ฆถ๐ฆถ๐ป๐ฆถ๐ผ๐ฆถ๐ฝ๐ฆถ๐พ๐ฆถ๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟโ๏ธโโ๐ปโ๐ผโ๐ฝโ๐พโ๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟโ๏ธโโ๐ปโ๐ผโ๐ฝโ๐พโ๐ฟ๐ค๐ค๐ป๐ค๐ผ๐ค๐ฝ๐ค๐พ๐ค๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐ค๐ค๐ป๐ค๐ผ๐ค๐ฝ๐ค๐พ๐ค๐ฟ๐ค๐ค๐ป๐ค๐ผ๐ค๐ฝ๐ค๐พ๐ค๐ฟ๐๏ธ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟโโ๐ปโ๐ผโ๐ฝโ๐พโ๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟโโ๐ปโ๐ผโ๐ฝโ๐พโ๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐ค๐ค๐ป๐ค๐ผ๐ค๐ฝ๐ค๐พ๐ค๐ฟ๐ค๐ค๐ป๐ค๐ผ๐ค๐ฝ๐ค๐พ๐ค๐ฟ๐ค๐ค๐ป๐ค๐ผ๐ค๐ฝ๐ค๐พ๐ค๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐ค๐ค๐ป๐ค๐ผ๐ค๐ฝ๐ค๐พ๐ค๐ฟโ๏ธโโ๐ปโ๐ผโ๐ฝโ๐พโ๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐คฒ๐คฒ๐ป๐คฒ๐ผ๐คฒ๐ฝ๐คฒ๐พ๐คฒ๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐ค๐
๐
๐ป๐
๐ผ๐
๐ฝ๐
๐พ๐
๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐๐๐ป๐๐ผ๐๐ฝ๐๐พ๐๐ฟ๐ฆฐ๐ฆฑ๐ฆฒ๐ฆณ๐ฃ๐๐๏ธ๐๐๏ธโ๐จ๏ธ๐โ๐จ๏ธ๐๏ธโ๐จ๐โ๐จ๐ง ๐ฆด๐ฆท๐
๐๐๐โค๏ธโค๐๐๐๐๐๐๐๐๐งก๐๐ค๐๐๐โฃ๏ธโฃ๐๐ค๐ข๐ฃ๐ฅ๐ฆ๐จ๐ซ๐ฌ๐จ๏ธ๐จ๐ฏ๏ธ๐ฏ๐ญ๐ณ๏ธ๐ณ๐๐ถ๏ธ๐ถ๐ฅฝ๐ฅผ๐๐๐๐งฃ๐งค๐งฅ๐งฆ๐๐๐๐๐๐๐๐๏ธ๐๐๐๐๐ฅพ๐ฅฟ๐ ๐ก๐ข๐๐๐ฉ๐๐งขโ๏ธโ๐ฟ๐๐๐๐ต๐๐ฆ๐ถ๐๐ฉ๐บ๐ฆ๐ฆ๐ฑ๐๐ฆ๐ฏ๐
๐๐ด๐๐ฆ๐ฆ๐ฆ๐ฎ๐๐๐๐ท๐๐๐ฝ๐๐๐๐ช๐ซ๐ฆ๐ฆ๐๐ฆ๐ฆ๐ญ๐๐๐น๐ฐ๐๐ฟ๏ธ๐ฟ๐ฆ๐ฆ๐ป๐จ๐ผ๐ฆ๐ฆก๐พ๐ฆ๐๐๐ฃ๐ค๐ฅ๐ฆ๐ง๐๏ธ๐๐ฆ
๐ฆ๐ฆข๐ฆ๐ฆ๐ฆ๐ธ๐๐ข๐ฆ๐๐ฒ๐๐ฆ๐ฆ๐ณ๐๐ฌ๐๐ ๐ก๐ฆ๐๐๐ฆ๐ฆ๐ฆ๐ฆ๐๐ฆ๐๐๐๐๐ฆ๐ท๏ธ๐ท๐ธ๏ธ๐ธ๐ฆ๐ฆ๐ฆ ๐๐ธ๐ฎ๐ต๏ธ๐ต๐น๐ฅ๐บ๐ป๐ผ๐ท๐ฑ๐ฒ๐ณ๐ด๐ต๐พ๐ฟโ๏ธโ๐๐๐๐๐๐๐๐๐๐๐๐ฅญ๐๐๐๐๐๐๐ฅ๐
๐ฅฅ๐ฅ๐๐ฅ๐ฅ๐ฝ๐ถ๏ธ๐ถ๐ฅ๐ฅฌ๐ฅฆ๐๐ฅ๐ฐ๐๐ฅ๐ฅ๐ฅจ๐ฅฏ๐ฅ๐ง๐๐๐ฅฉ๐ฅ๐๐๐๐ญ๐ฅช๐ฎ๐ฏ๐ฅ๐ฅ๐ณ๐ฅ๐ฒ๐ฅฃ๐ฅ๐ฟ๐ง๐ฅซ๐ฑ๐๐๐๐๐๐๐ ๐ข๐ฃ๐ค๐ฅ๐ฅฎ๐ก๐ฅ๐ฅ ๐ฅก๐ฆ๐ง๐จ๐ฉ๐ช๐๐ฐ๐ง๐ฅง๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ผ๐ฅโ๐ต๐ถ๐พ๐ท๐ธ๐น๐บ๐ป๐ฅ๐ฅ๐ฅค๐ฅข๐ฝ๏ธ๐ฝ๐ด๐ฅ๐ช๐บ๐๐๐๐๐บ๏ธ๐บ๐พ๐งญ๐๏ธ๐โฐ๏ธโฐ๐๐ป๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๏ธ๐๐งฑ๐๏ธ๐๐๏ธ๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฏ๐ฐ๐๐ผ๐ฝโช๐๐โฉ๏ธโฉ๐โฒโบ๐๐๐๏ธ๐๐๐
๐๐๐โจ๏ธโจ๐๐ ๐ก๐ข๐๐ช๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ฒ๐ด๐น๐ต๐๐ฃ๏ธ๐ฃ๐ค๏ธ๐ค๐ข๏ธ๐ขโฝ๐จ๐ฅ๐ฆ๐๐งโโต๐ถ๐ค๐ณ๏ธ๐ณโด๏ธโด๐ฅ๏ธ๐ฅ๐ขโ๏ธโ๐ฉ๏ธ๐ฉ๐ซ๐ฌ๐บ๐๐๐ ๐ก๐ฐ๏ธ๐ฐ๐๐ธ๐๏ธ๐๐งณโโณโโฐโฑ๏ธโฑโฒ๏ธโฒ๐ฐ๏ธ๐ฐ๐๐ง๐๐๐๐๐๐๐๐๐๐ ๐๐ก๐๐ข๐๐ฃ๐๐ค๐๐ฅ๐๐ฆ๐๐๐๐๐๐๐๐๐๐๐๐๐ก๏ธ๐กโ๏ธโ๐๐โญ๐๐ โ๏ธโโ
โ๏ธโ๐ค๏ธ๐ค๐ฅ๏ธ๐ฅ๐ฆ๏ธ๐ฆ๐ง๏ธ๐ง๐จ๏ธ๐จ๐ฉ๏ธ๐ฉ๐ช๏ธ๐ช๐ซ๏ธ๐ซ๐ฌ๏ธ๐ฌ๐๐๐โ๏ธโโโฑ๏ธโฑโกโ๏ธโโ๏ธโโโ๏ธโ๐ฅ๐ง๐๐๐๐๐๐งจโจ๐๐๐๐๐๐๐๐๐๐งง๐๐๐๏ธ๐๐๏ธ๐๐ซ๐๏ธ๐๐๐
๐ฅ๐ฅ๐ฅโฝโพ๐ฅ๐๐๐๐๐พ๐ฅ๐ณ๐๐๐๐ฅ๐๐ธ๐ฅ๐ฅ๐ฅ
โณโธ๏ธโธ๐ฃ๐ฝ๐ฟ๐ท๐ฅ๐ฏ๐ฑ๐ฎ๐งฟ๐ฎ๐น๏ธ๐น๐ฐ๐ฒ๐งฉ๐งธโ ๏ธโ โฅ๏ธโฅโฆ๏ธโฆโฃ๏ธโฃโ๏ธโ๐๐๐ด๐ญ๐ผ๏ธ๐ผ๐จ๐งต๐งถ๐๐๐๐๐ข๐ฃ๐ฏ๐๐๐ผ๐ต๐ถ๐๏ธ๐๐๏ธ๐๐๏ธ๐๐ค๐ง๐ป๐ท๐ธ๐น๐บ๐ป๐ฅ๐ฑ๐ฒโ๏ธโ๐๐๐ ๐๐๐ป๐ฅ๏ธ๐ฅ๐จ๏ธ๐จโจ๏ธโจ๐ฑ๏ธ๐ฑ๐ฒ๏ธ๐ฒ๐ฝ๐พ๐ฟ๐๐งฎ๐ฅ๐๏ธ๐๐ฝ๏ธ๐ฝ๐ฌ๐บ๐ท๐ธ๐น๐ผ๐๐๐ฏ๏ธ๐ฏ๐ก๐ฆ๐ฎ๐๐๐๐๐๐๐๐๐๐๐๐๐ฐ๐๏ธ๐๐๐๐ท๏ธ๐ท๐ฐ๐ด๐ต๐ถ๐ท๐ธ๐ณ๐งพ๐น๐ฑ๐ฒโ๏ธโ๐ง๐จ๐ฉ๐ค๐ฅ๐ฆ๐ซ๐ช๐ฌ๐ญ๐ฎ๐ณ๏ธ๐ณโ๏ธโโ๏ธโ๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๐ผ๐๐๐๏ธ๐๐
๐๐๏ธ๐๐๏ธ๐๐๐๐๐๐๐๐๐๐๏ธ๐๐๐โ๏ธโ๐๏ธ๐๐๏ธ๐๐๏ธ๐๐๐๐๐๐๐๏ธ๐๐จโ๏ธโโ๏ธโ๐ ๏ธ๐ ๐ก๏ธ๐กโ๏ธโ๐ซ๐น๐ก๏ธ๐ก๐ง๐ฉโ๏ธโ๐๏ธ๐โ๏ธโ๐โ๏ธโ๐งฐ๐งฒโ๏ธโ๐งช๐งซ๐งฌ๐ฌ๐ญ๐ก๐๐๐ช๐๏ธ๐๐๏ธ๐๐ฝ๐ฟ๐๐งด๐งท๐งน๐งบ๐งป๐งผ๐งฝ๐งฏ๐๐ฌโฐ๏ธโฐโฑ๏ธโฑ๐ฟ๐ง๐ฎ๐ฐโฟ๐น๐บ๐ป๐ผ๐พ๐๐๐๐
โ ๏ธโ ๐ธโ๐ซ๐ณ๐ญ๐ฏ๐ฑ๐ท๐ต๐โข๏ธโขโฃ๏ธโฃโฌ๏ธโฌโ๏ธโโก๏ธโกโ๏ธโโฌ๏ธโฌโ๏ธโโฌ
๏ธโฌ
โ๏ธโโ๏ธโโ๏ธโโฉ๏ธโฉโช๏ธโชโคด๏ธโคดโคต๏ธโคต๐๐๐๐๐๐๐๐โ๏ธโ๐๏ธ๐โก๏ธโกโธ๏ธโธโฏ๏ธโฏโ๏ธโโฆ๏ธโฆโช๏ธโชโฎ๏ธโฎ๐๐ฏโโโโโโโโโโโโโ๐๐๐โถ๏ธโถโฉโญ๏ธโญโฏ๏ธโฏโ๏ธโโชโฎ๏ธโฎ๐ผโซ๐ฝโฌโธ๏ธโธโน๏ธโนโบ๏ธโบโ๏ธโ๐ฆ๐
๐๐ถ๐ณ๐ดโ๏ธโโ๏ธโโ๏ธโโพ๏ธโพโป๏ธโปโ๏ธโ๐ฑ๐๐ฐโญโ
โ๏ธโโ๏ธโโ๏ธโโโโโโโฐโฟใฝ๏ธใฝโณ๏ธโณโด๏ธโดโ๏ธโโผ๏ธโผโ๏ธโโโโโใฐ๏ธใฐยฉ๏ธยฉยฎ๏ธยฎโข๏ธโข#๏ธโฃ#โฃ*๏ธโฃ*โฃ0๏ธโฃ0โฃ1๏ธโฃ1โฃ2๏ธโฃ2โฃ3๏ธโฃ3โฃ4๏ธโฃ4โฃ5๏ธโฃ5โฃ6๏ธโฃ6โฃ7๏ธโฃ7โฃ8๏ธโฃ8โฃ9๏ธโฃ9โฃ๐๐ฏ๐ ๐ก๐ข๐ฃ๐ค๐
ฐ๏ธ๐
ฐ๐๐
ฑ๏ธ๐
ฑ๐๐๐โน๏ธโน๐โ๏ธโ๐๐๐
พ๏ธ๐
พ๐๐
ฟ๏ธ๐
ฟ๐๐๐๐๐๏ธ๐๐ท๏ธ๐ท๐ถ๐ฏ๐๐น๐๐ฒ๐๐ธ๐ด๐ณใ๏ธใใ๏ธใ๐บ๐ตโช๏ธโชโซ๏ธโซโป๏ธโปโผ๏ธโผโฝโพโฌโฌ๐ถ๐ท๐ธ๐น๐บ๐ป๐ ๐๐ฒ๐ณโชโซ๐ด๐ต๐๐ฉ๐๐ด๐ณ๏ธ๐ณ๐ณ๏ธโ๐๐ณโ๐๐ดโโ ๏ธ๐ดโโ ๐ฆ๐จ๐ฆ๐ฉ๐ฆ๐ช๐ฆ๐ซ๐ฆ๐ฌ๐ฆ๐ฎ๐ฆ๐ฑ๐ฆ๐ฒ๐ฆ๐ด๐ฆ๐ถ๐ฆ๐ท๐ฆ๐ธ๐ฆ๐น๐ฆ๐บ๐ฆ๐ผ๐ฆ๐ฝ๐ฆ๐ฟ๐ง๐ฆ๐ง๐ง๐ง๐ฉ๐ง๐ช๐ง๐ซ๐ง๐ฌ๐ง๐ญ๐ง๐ฎ๐ง๐ฏ๐ง๐ฑ๐ง๐ฒ๐ง๐ณ๐ง๐ด๐ง๐ถ๐ง๐ท๐ง๐ธ๐ง๐น๐ง๐ป๐ง๐ผ๐ง๐พ๐ง๐ฟ๐จ๐ฆ๐จ๐จ๐จ๐ฉ๐จ๐ซ๐จ๐ฌ๐จ๐ญ๐จ๐ฎ๐จ๐ฐ๐จ๐ฑ๐จ๐ฒ๐จ๐ณ๐จ๐ด๐จ๐ต๐จ๐ท๐จ๐บ๐จ๐ป๐จ๐ผ๐จ๐ฝ๐จ๐พ๐จ๐ฟ๐ฉ๐ช๐ฉ๐ฌ๐ฉ๐ฏ๐ฉ๐ฐ๐ฉ๐ฒ๐ฉ๐ด๐ฉ๐ฟ๐ช๐ฆ๐ช๐จ๐ช๐ช๐ช๐ฌ๐ช๐ญ๐ช๐ท๐ช๐ธ๐ช๐น๐ช๐บ๐ซ๐ฎ๐ซ๐ฏ๐ซ๐ฐ๐ซ๐ฒ๐ซ๐ด๐ซ๐ท๐ฌ๐ฆ๐ฌ๐ง๐ฌ๐ฉ๐ฌ๐ช๐ฌ๐ซ๐ฌ๐ฌ๐ฌ๐ญ๐ฌ๐ฎ๐ฌ๐ฑ๐ฌ๐ฒ๐ฌ๐ณ๐ฌ๐ต๐ฌ๐ถ๐ฌ๐ท๐ฌ๐ธ๐ฌ๐น๐ฌ๐บ๐ฌ๐ผ๐ฌ๐พ๐ญ๐ฐ๐ญ๐ฒ๐ญ๐ณ๐ญ๐ท๐ญ๐น๐ญ๐บ๐ฎ๐จ๐ฎ๐ฉ๐ฎ๐ช๐ฎ๐ฑ๐ฎ๐ฒ๐ฎ๐ณ๐ฎ๐ด๐ฎ๐ถ๐ฎ๐ท๐ฎ๐ธ๐ฎ๐น๐ฏ๐ช๐ฏ๐ฒ๐ฏ๐ด๐ฏ๐ต๐ฐ๐ช๐ฐ๐ฌ๐ฐ๐ญ๐ฐ๐ฎ๐ฐ๐ฒ๐ฐ๐ณ๐ฐ๐ต๐ฐ๐ท๐ฐ๐ผ๐ฐ๐พ๐ฐ๐ฟ๐ฑ๐ฆ๐ฑ๐ง๐ฑ๐จ๐ฑ๐ฎ๐ฑ๐ฐ๐ฑ๐ท๐ฑ๐ธ๐ฑ๐น๐ฑ๐บ๐ฑ๐ป๐ฑ๐พ๐ฒ๐ฆ๐ฒ๐จ๐ฒ๐ฉ๐ฒ๐ช๐ฒ๐ซ๐ฒ๐ฌ๐ฒ๐ญ๐ฒ๐ฐ๐ฒ๐ฑ๐ฒ๐ฒ๐ฒ๐ณ๐ฒ๐ด๐ฒ๐ต๐ฒ๐ถ๐ฒ๐ท๐ฒ๐ธ๐ฒ๐น๐ฒ๐บ๐ฒ๐ป๐ฒ๐ผ๐ฒ๐ฝ๐ฒ๐พ๐ฒ๐ฟ๐ณ๐ฆ๐ณ๐จ๐ณ๐ช๐ณ๐ซ๐ณ๐ฌ๐ณ๐ฎ๐ณ๐ฑ๐ณ๐ด๐ณ๐ต๐ณ๐ท๐ณ๐บ๐ณ๐ฟ๐ด๐ฒ๐ต๐ฆ๐ต๐ช๐ต๐ซ๐ต๐ฌ๐ต๐ญ๐ต๐ฐ๐ต๐ฑ๐ต๐ฒ๐ต๐ณ๐ต๐ท๐ต๐ธ๐ต๐น๐ต๐ผ๐ต๐พ๐ถ๐ฆ๐ท๐ช๐ท๐ด๐ท๐ธ๐ท๐บ๐ท๐ผ๐ธ๐ฆ๐ธ๐ง๐ธ๐จ๐ธ๐ฉ๐ธ๐ช๐ธ๐ฌ๐ธ๐ญ๐ธ๐ฎ๐ธ๐ฏ๐ธ๐ฐ๐ธ๐ฑ๐ธ๐ฒ๐ธ๐ณ๐ธ๐ด๐ธ๐ท๐ธ๐ธ๐ธ๐น๐ธ๐ป๐ธ๐ฝ๐ธ๐พ๐ธ๐ฟ๐น๐ฆ๐น๐จ๐น๐ฉ๐น๐ซ๐น๐ฌ๐น๐ญ๐น๐ฏ๐น๐ฐ๐น๐ฑ๐น๐ฒ๐น๐ณ๐น๐ด๐น๐ท๐น๐น๐น๐ป๐น๐ผ๐น๐ฟ๐บ๐ฆ๐บ๐ฌ๐บ๐ฒ๐บ๐ณ๐บ๐ธ๐บ๐พ๐บ๐ฟ๐ป๐ฆ๐ป๐จ๐ป๐ช๐ป๐ฌ๐ป๐ฎ๐ป๐ณ๐ป๐บ๐ผ๐ซ๐ผ๐ธ๐ฝ๐ฐ๐พ๐ช๐พ๐น๐ฟ๐ฆ๐ฟ๐ฒ๐ฟ๐ผ๐ด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ๐ด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ๐ด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ"
  );
  expect(() => emoji.parse(":-)")).toThrow();
  expect(() => emoji.parse("๐ is an emoji")).toThrow();
  expect(() => emoji.parse("๐stuff")).toThrow();
  expect(() => emoji.parse("stuff๐")).toThrow();
});
test("nanoid", () => {
  const nanoid = z.string().nanoid("custom error");
  nanoid.parse("lfNZluvAxMkf7Q8C5H-QS");
  nanoid.parse("mIU_4PJWikaU8fMbmkouz");
  nanoid.parse("Hb9ZUtUa2JDm_dD-47EGv");
  nanoid.parse("5Noocgv_8vQ9oPijj4ioQ");
  const result = nanoid.safeParse("Xq90uDyhddC53KsoASYJGX");
  expect(result).toMatchObject({ success: false });
  expect(result.error!.issues[0].message).toEqual("custom error");
  expect(result.error).toMatchInlineSnapshot(`
    [ZodError: [
      {
        "origin": "string",
        "code": "invalid_format",
        "format": "nanoid",
        "pattern": "/^[a-zA-Z0-9_-]{21}$/",
        "path": [],
        "message": "custom error"
      }
    ]]
  `);
});
test("bad nanoid", () => {
  const nanoid = z.string().nanoid("custom error");
  nanoid.parse("ySh_984wpDUu7IQRrLXAp");
  const result = nanoid.safeParse("invalid nanoid");
  expect(result).toMatchObject({ success: false });
  expect(result.error!.issues[0].message).toEqual("custom error");
  expect(result.error).toMatchInlineSnapshot(`
    [ZodError: [
      {
        "origin": "string",
        "code": "invalid_format",
        "format": "nanoid",
        "pattern": "/^[a-zA-Z0-9_-]{21}$/",
        "path": [],
        "message": "custom error"
      }
    ]]
  `);
});
test("good uuid", () => {
  const uuid = z.string().uuid("custom error");
  const goodUuids = [
    "9491d710-3185-1e06-bea0-6a2f275345e0",
    "9491d710-3185-2e06-bea0-6a2f275345e0",
    "9491d710-3185-3e06-bea0-6a2f275345e0",
    "9491d710-3185-4e06-bea0-6a2f275345e0",
    "9491d710-3185-5e06-bea0-6a2f275345e0",
    "9491d710-3185-5e06-aea0-6a2f275345e0",
    "9491d710-3185-5e06-8ea0-6a2f275345e0",
    "9491d710-3185-5e06-9ea0-6a2f275345e0",
    "00000000-0000-0000-0000-000000000000",
  ];
  for (const goodUuid of goodUuids) {
    const result = uuid.safeParse(goodUuid);
    expect(result.success).toEqual(true);
  }
});
test(`bad uuid`, () => {
  const uuid = z.string().uuid("custom error");
  for (const badUuid of [
    "9491d710-3185-0e06-bea0-6a2f275345e0",
    "9491d710-3185-5e06-0ea0-6a2f275345e0",
    "d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
    "b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
    "92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
    "invalid uuid",
    "9491d710-3185-4e06-bea0-6a2f275345e0X",
    "ffffffff-ffff-ffff-ffff-ffffffffffff",
  ]) {
    const result = uuid.safeParse(badUuid);
    expect(result).toMatchObject({ success: false });
    expect(result.error?.issues[0].message).toEqual("custom error");
  }
});
test("good guid", () => {
  const guid = z.string().guid("custom error");
  for (const goodGuid of [
    "9491d710-3185-4e06-bea0-6a2f275345e0",
    "d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
    "b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
    "92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
    "00000000-0000-0000-0000-000000000000",
    "ffffffff-ffff-ffff-ffff-ffffffffffff",
  ]) {
    const result = guid.safeParse(goodGuid);
    expect(result.success).toEqual(true);
  }
});
test("bad guid", () => {
  const guid = z.string().guid("custom error");
  for (const badGuid of ["9491d710-3185-4e06-bea0-6a2f275345e0X"]) {
    const result = guid.safeParse(badGuid);
    expect(result).toMatchObject({ success: false });
    expect(result.error?.issues[0].message).toEqual("custom error");
  }
});
test("cuid", () => {
  const cuid = z.string().cuid();
  cuid.parse("ckopqwooh000001la8mbi2im9");
  const result = cuid.safeParse("cifjhdsfhsd-invalid-cuid");
  expect(result).toMatchObject({ success: false });
  expect(result.error!.issues[0].message).toEqual("Invalid cuid");
  expect(result.error).toMatchInlineSnapshot(`
    [ZodError: [
      {
        "origin": "string",
        "code": "invalid_format",
        "format": "cuid",
        "pattern": "/^[cC][^\\\\s-]{8,}$/",
        "path": [],
        "message": "Invalid cuid"
      }
    ]]
  `);
});
test("cuid2", () => {
  const cuid2 = z.string().cuid2();
  const validStrings = [
    "a", // short string
    "tz4a98xxat96iws9zmbrgj3a", // normal string
    "kf5vz6ssxe4zjcb409rjgo747tc5qjazgptvotk6", // longer than require("@paralleldrive/cuid2").bigLength
  ];
  for (const s of validStrings) {
    cuid2.parse(s);
  }
  const invalidStrings = [
    "", // empty string
    "tz4a98xxat96iws9zMbrgj3a", // include uppercase
    "tz4a98xxat96iws-zmbrgj3a", // involve symbols
  ];
  const results = invalidStrings.map((s) => cuid2.safeParse(s));
  expect(results.every((r) => !r.success)).toEqual(true);
  if (!results[0].success) {
    expect(results[0].error.issues[0].message).toEqual("Invalid cuid2");
  }
});
test("ulid", () => {
  const ulid = z.string().ulid();
  ulid.parse("01ARZ3NDEKTSV4RRFFQ69G5FAV");
  const result = ulid.safeParse("invalidulid");
  expect(result).toMatchObject({ success: false });
  const tooLong = "01ARZ3NDEKTSV4RRFFQ69G5FAVA";
  expect(ulid.safeParse(tooLong)).toMatchObject({ success: false });
  const caseInsensitive = ulid.safeParse("01arZ3nDeKTsV4RRffQ69G5FAV");
  expect(caseInsensitive.success).toEqual(true);
  expect(result.error!.issues[0].message).toEqual("Invalid ULID");
  expect(result.error).toMatchInlineSnapshot(`
    [ZodError: [
      {
        "origin": "string",
        "code": "invalid_format",
        "format": "ulid",
        "pattern": "/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/",
        "path": [],
        "message": "Invalid ULID"
      }
    ]]
  `);
});
test("xid", () => {
  const xid = z.string().xid();
  xid.parse("9m4e2mr0ui3e8a215n4g");
  const result = xid.safeParse("invalidxid");
  expect(result).toMatchObject({ success: false });
  expect(result.error!.issues[0].message).toEqual("Invalid XID");
  expect(result.error).toMatchInlineSnapshot(`
    [ZodError: [
      {
        "origin": "string",
        "code": "invalid_format",
        "format": "xid",
        "pattern": "/^[0-9a-vA-V]{20}$/",
        "path": [],
        "message": "Invalid XID"
      }
    ]]
  `);
});
test("ksuid", () => {
  const ksuid = z.string().ksuid();
  ksuid.parse("0o0t9hkGxgFLtd3lmJ4TSTeY0Vb");
  const result = ksuid.safeParse("invalidksuid");
  expect(result).toMatchObject({ success: false });
  const tooLong = "0o0t9hkGxgFLtd3lmJ4TSTeY0VbA";
  expect(ksuid.safeParse(tooLong)).toMatchObject({ success: false });
  expect(result.error!.issues).toMatchInlineSnapshot(`
    [
      {
        "code": "invalid_format",
        "format": "ksuid",
        "message": "Invalid KSUID",
        "origin": "string",
        "path": [],
        "pattern": "/^[A-Za-z0-9]{27}$/",
      },
    ]
  `);
});
test("regex", () => {
  z.string()
    .regex(/^moo+$/)
    .parse("mooooo");
  expect(() => z.string().uuid().parse("purr")).toThrow();
});
test("regexp error message", () => {
  const result = z
    .string()
    .regex(/^moo+$/)
    .safeParse("boooo");
  expect(result.error!.issues).toMatchInlineSnapshot(`
    [
      {
        "code": "invalid_format",
        "format": "regex",
        "message": "Invalid string: must match pattern /^moo+$/",
        "origin": "string",
        "path": [],
        "pattern": "/^moo+$/",
      },
    ]
  `);
  expect(() => z.string().uuid().parse("purr")).toThrow();
});
test("regexp error custom message", () => {
  const result = z
    .string()
    .regex(/^moo+$/, { message: "Custom error message" })
    .safeParse("boooo");
  expect(result.error!.issues).toMatchInlineSnapshot(`
    [
      {
        "code": "invalid_format",
        "format": "regex",
        "message": "Custom error message",
        "origin": "string",
        "path": [],
        "pattern": "/^moo+$/",
      },
    ]
  `);
  expect(() => z.string().uuid().parse("purr")).toThrow();
});
test("regex lastIndex reset", () => {
  const schema = z.string().regex(/^\d+$/g);
  expect(schema.safeParse("123").success).toEqual(true);
  expect(schema.safeParse("123").success).toEqual(true);
  expect(schema.safeParse("123").success).toEqual(true);
  expect(schema.safeParse("123").success).toEqual(true);
  expect(schema.safeParse("123").success).toEqual(true);
});
test("format", () => {
  expect(z.string().email().format).toEqual("email");
  expect(z.string().url().format).toEqual("url");
  expect(z.string().jwt().format).toEqual("jwt");
  expect(z.string().emoji().format).toEqual("emoji");
  expect(z.string().guid().format).toEqual("guid");
  expect(z.string().uuid().format).toEqual("uuid");
  expect(z.string().uuidv4().format).toEqual("uuid");
  expect(z.string().uuidv6().format).toEqual("uuid");
  expect(z.string().uuidv7().format).toEqual("uuid");
  expect(z.string().nanoid().format).toEqual("nanoid");
  expect(z.string().guid().format).toEqual("guid");
  expect(z.string().cuid().format).toEqual("cuid");
  expect(z.string().cuid2().format).toEqual("cuid2");
  expect(z.string().ulid().format).toEqual("ulid");
  expect(z.string().base64().format).toEqual("base64");
  // expect(z.string().jsonString().format).toEqual("json_string");
  // expect(z.string().json().format).toEqual("json_string");
  expect(z.string().xid().format).toEqual("xid");
  expect(z.string().ksuid().format).toEqual("ksuid");
  // expect(z.string().ip().format).toEqual("ip");
  expect(z.string().ipv4().format).toEqual("ipv4");
  expect(z.string().ipv6().format).toEqual("ipv6");
  expect(z.string().e164().format).toEqual("e164");
  expect(z.string().datetime().format).toEqual("datetime");
  expect(z.string().date().format).toEqual("date");
  expect(z.string().time().format).toEqual("time");
  expect(z.string().duration().format).toEqual("duration");
});
test("min max getters", () => {
  expect(z.string().min(5).minLength).toEqual(5);
  expect(z.string().min(5).min(10).minLength).toEqual(10);
  expect(z.string().minLength).toEqual(null);
  expect(z.string().max(5).maxLength).toEqual(5);
  expect(z.string().max(5).max(1).maxLength).toEqual(1);
  expect(z.string().max(5).max(10).maxLength).toEqual(5);
  expect(z.string().maxLength).toEqual(null);
});
test("trim", () => {
  expect(z.string().trim().min(2).parse(" 12 ")).toEqual("12");
  // ordering of methods is respected
  expect(z.string().min(2).trim().parse(" 1 ")).toEqual("1");
  expect(() => z.string().trim().min(2).parse(" 1 ")).toThrow();
});
test("lowerCase", () => {
  expect(z.string().toLowerCase().parse("ASDF")).toEqual("asdf");
  expect(z.string().toUpperCase().parse("asdf")).toEqual("ASDF");
});
// test("IP validation", () => {
//   const ipSchema = z.string().ip();
//   // General IP validation (accepts both v4 and v6)
//   expect(ipSchema.safeParse("114.71.82.94").success).toBe(true);
//   expect(ipSchema.safeParse("0.0.0.0").success).toBe(true);
//   expect(ipSchema.safeParse("37.85.236.115").success).toBe(true);
//   expect(ipSchema.safeParse("1e5e:e6c8:daac:514b:114b:e360:d8c0:682c").success).toBe(true);
//   expect(ipSchema.safeParse("9d4:c956:420f:5788:4339:9b3b:2418:75c3").success).toBe(true);
//   expect(ipSchema.safeParse("a6ea::2454:a5ce:94.105.123.75").success).toBe(true);
//   expect(ipSchema.safeParse("474f:4c83::4e40:a47:ff95:0cda").success).toBe(true);
//   expect(ipSchema.safeParse("d329:0:25b4:db47:a9d1:0:4926:0000").success).toBe(true);
//   expect(ipSchema.safeParse("e48:10fb:1499:3e28:e4b6:dea5:4692:912c").success).toBe(true);
//   expect(ipSchema.safeParse("d329:1be4:25b4:db47:a9d1:dc71:4926:992c:14af").success).toBe(false);
//   expect(ipSchema.safeParse("d5e7:7214:2b78::3906:85e6:53cc:709:32ba").success).toBe(false);
//   expect(ipSchema.safeParse("8f69::c757:395e:976e::3441").success).toBe(false);
//   expect(ipSchema.safeParse("54cb::473f:d516:0.255.256.22").success).toBe(false);
//   expect(ipSchema.safeParse("54cb::473f:d516:192.168.1").success).toBe(false);
//   expect(ipSchema.safeParse("256.0.4.4").success).toBe(false);
//   expect(ipSchema.safeParse("-1.0.555.4").success).toBe(false);
//   expect(ipSchema.safeParse("0.0.0.0.0").success).toBe(false);
//   expect(ipSchema.safeParse("1.1.1").success).toBe(false);
// });
test("IPv4 validation", () => {
  const ipv4 = z.string().ipv4();
  // Valid IPv4 addresses
  expect(ipv4.safeParse("114.71.82.94").success).toBe(true);
  expect(ipv4.safeParse("0.0.0.0").success).toBe(true);
  expect(ipv4.safeParse("37.85.236.115").success).toBe(true);
  expect(ipv4.safeParse("192.168.0.1").success).toBe(true);
  expect(ipv4.safeParse("255.255.255.255").success).toBe(true);
  expect(ipv4.safeParse("1.2.3.4").success).toBe(true);
  // Invalid IPv4 addresses
  expect(ipv4.safeParse("256.0.4.4").success).toBe(false);
  expect(ipv4.safeParse("-1.0.555.4").success).toBe(false);
  expect(ipv4.safeParse("0.0.0.0.0").success).toBe(false);
  expect(ipv4.safeParse("1.1.1").success).toBe(false);
  expect(ipv4.safeParse("1e5e:e6c8:daac:514b:114b:e360:d8c0:682c").success).toBe(false);
  expect(ipv4.safeParse("a6ea::2454:a5ce:94.105.123.75").success).toBe(false);
  expect(ipv4.safeParse("not an ip").success).toBe(false);
  expect(ipv4.safeParse("1.2.3").success).toBe(false);
  expect(ipv4.safeParse("1.2.3.4.5").success).toBe(false);
  expect(ipv4.safeParse("1.2.3.256").success).toBe(false);
  // Test specific error
  expect(() => ipv4.parse("6097:adfa:6f0b:220d:db08:5021:6191:7990")).toThrow();
});
test("IPv6 validation", () => {
  const ipv6 = z.string().ipv6();
  // Valid IPv6 addresses
  expect(ipv6.safeParse("1e5e:e6c8:daac:514b:114b:e360:d8c0:682c").success).toBe(true);
  expect(ipv6.safeParse("9d4:c956:420f:5788:4339:9b3b:2418:75c3").success).toBe(true);
  expect(ipv6.safeParse("a6ea::2454:a5ce:94.105.123.75").success).toBe(true);
  expect(ipv6.safeParse("474f:4c83::4e40:a47:ff95:0cda").success).toBe(true);
  expect(ipv6.safeParse("d329:0:25b4:db47:a9d1:0:4926:0000").success).toBe(true);
  expect(ipv6.safeParse("e48:10fb:1499:3e28:e4b6:dea5:4692:912c").success).toBe(true);
  expect(ipv6.safeParse("::1").success).toBe(true);
  expect(ipv6.safeParse("2001:db8::").success).toBe(true);
  expect(ipv6.safeParse("2001:0db8:85a3:0000:0000:8a2e:0370:7334").success).toBe(true);
  expect(ipv6.safeParse("2001:db8::192.168.0.1").success).toBe(true);
  expect(ipv6.safeParse("::ffff:192.168.0.1").success).toBe(true);
  expect(ipv6.safeParse("::ffff:c000:0280").success).toBe(true); // IPv4-mapped IPv6 address
  expect(ipv6.safeParse("64:ff9b::192.168.0.1").success).toBe(true); // IPv4/IPv6 translation
  // Invalid IPv6 addresses
  expect(ipv6.safeParse("d329:1be4:25b4:db47:a9d1:dc71:4926:992c:14af").success).toBe(false);
  expect(ipv6.safeParse("d5e7:7214:2b78::3906:85e6:53cc:709:32ba").success).toBe(false);
  expect(ipv6.safeParse("8f69::c757:395e:976e::3441").success).toBe(false);
  expect(ipv6.safeParse("54cb::473f:d516:0.255.256.22").success).toBe(false);
  expect(ipv6.safeParse("54cb::473f:d516:192.168.1").success).toBe(false);
  expect(ipv6.safeParse("114.71.82.94").success).toBe(false);
  expect(ipv6.safeParse("not an ip").success).toBe(false);
  expect(ipv6.safeParse("g123::1234:5678").success).toBe(false);
  // Test specific error
  expect(() => ipv6.parse("254.164.77.1")).toThrow();
});
test("CIDR v4 validation", () => {
  const cidrV4 = z.string().cidrv4();
  // Valid CIDR v4 addresses
  expect(cidrV4.safeParse("192.168.0.0/24").success).toBe(true);
  expect(cidrV4.safeParse("10.0.0.0/8").success).toBe(true);
  expect(cidrV4.safeParse("172.16.0.0/12").success).toBe(true);
  expect(cidrV4.safeParse("0.0.0.0/0").success).toBe(true);
  expect(cidrV4.safeParse("255.255.255.255/32").success).toBe(true);
  // Invalid CIDR v4 addresses
  expect(cidrV4.safeParse("192.168.0.0").success).toBe(false); // Missing prefix
  expect(cidrV4.safeParse("192.168.0.0/33").success).toBe(false); // Invalid prefix length
  expect(cidrV4.safeParse("256.0.0.0/24").success).toBe(false); // Invalid IP
  expect(cidrV4.safeParse("192.168.0.0/-1").success).toBe(false); // Negative prefix length
  expect(cidrV4.safeParse("not a cidr").success).toBe(false); // Invalid format
});
test("CIDR v6 validation", () => {
  const cidrV6 = z.string().cidrv6();
  // Valid CIDR v6 addresses
  expect(cidrV6.safeParse("2001:db8::/32").success).toBe(true);
  expect(cidrV6.safeParse("::/0").success).toBe(true);
  expect(cidrV6.safeParse("fe80::/10").success).toBe(true);
  expect(cidrV6.safeParse("::1/128").success).toBe(true);
  expect(cidrV6.safeParse("2001:0db8:85a3::/64").success).toBe(true);
  // Invalid CIDR v6 addresses
  expect(cidrV6.safeParse("2001:db8::").success).toBe(false); // Missing prefix
  expect(cidrV6.safeParse("2001:db8::/129").success).toBe(false); // Invalid prefix length
  expect(cidrV6.safeParse("2001:db8::/abc").success).toBe(false); // Invalid prefix format
  expect(cidrV6.safeParse("not a cidr").success).toBe(false); // Invalid format
  expect(cidrV6.safeParse("192.168.0.0/24").success).toBe(false); // IPv4 CIDR in v6 validation
});
test("E.164 validation", () => {
  const e164Number = z.string().e164();
  expect(e164Number.safeParse("+1555555").success).toBe(true);
  const validE164Numbers = [
    "+1555555", // min-length (7 digits + '+')
    "+15555555",
    "+155555555",
    "+1555555555",
    "+15555555555",
    "+155555555555",
    "+1555555555555",
    "+15555555555555",
    "+155555555555555",
    "+105555555555555",
    "+100555555555555", // max-length (15 digits + '+')
  ];
  const invalidE164Numbers = [
    "", // empty
    "+", // only plus sign
    "-", // wrong sign
    " 555555555", // starts with space
    "555555555", // missing plus sign
    "+1 555 555 555", // space after plus sign
    "+1555 555 555", // space between numbers
    "+1555+555", // multiple plus signs
    "+1555555555555555", // too long
    "+115abc55", // non numeric characters in number part
    "+1555555 ", // space after number
  ];
  expect(validE164Numbers.every((number) => e164Number.safeParse(number).success)).toBe(true);
  expect(invalidE164Numbers.every((number) => e164Number.safeParse(number).success === false)).toBe(true);
});