Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/khaki-deer-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"unicode-segmenter": minor
---

Implement word segmentation
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"./emoji": "./src/emoji.js",
"./general": "./src/general.js",
"./grapheme": "./src/grapheme.js",
"./word": "./src/word.js",
"./utils": "./src/utils.js",
"./intl-adapter": {
"types": "./src/intl-adapter.js",
Expand Down Expand Up @@ -68,6 +69,11 @@
"import": "./grapheme.js",
"require": "./grapheme.cjs"
},
"./word": {
"types": "./word.d.ts",
"import": "./word.js",
"require": "./word.cjs"
},
"./utils": {
"types": "./utils.d.ts",
"import": "./utils.js",
Expand Down
98 changes: 74 additions & 24 deletions scripts/unicode.js
Original file line number Diff line number Diff line change
Expand Up @@ -693,12 +693,14 @@ let printTestDataModule = async f => {
};

let grapehmeTestDataSrc = await fetchData('auxiliary/GraphemeBreakTest.txt');
let wordTestDataSrc = await fetchData('auxiliary/WordBreakTest.txt');
// rules 9.1 and 9.2 are for extended graphemes only
let optsplits = ['9.1', '9.2'];
let graphemeTestData = parseTestData(grapehmeTestDataSrc, optsplits);
let wordTestData = parseTestData(wordTestDataSrc, optsplits);

/** @type {TestCaseRow[]} */
let tests = [];
let graphemeTests = [];

for (let [c, i] of graphemeTestData) {
let allChars = c.flatMap(s => s);
Expand All @@ -725,9 +727,44 @@ let printTestDataModule = async f => {
extgraphs.push(extwork);

if (arraysEqual(extgraphs, c)) {
tests.push([allChars, c]);
graphemeTests.push([allChars, c]);
} else {
tests.push([allChars, extgraphs]);
graphemeTests.push([allChars, extgraphs]);
}
}


/** @type {TestCaseRow[]} */
let wordTests = [];

for (let [c, i] of wordTestData) {
let allChars = c.flatMap(s => s);

/** @type {UnicodeValues[]} */
let extgraphs = [];

/** @type {UnicodeValues} */
let extwork = [];

extwork = extwork.concat(c[0]);
for (let n of range(0, i.length)) {
if (optsplits.includes(i[n])) {
extwork = extwork.concat(c[n + 1]);
} else {
extgraphs.push(extwork);
extwork = [];
extwork = extwork.concat(c[n + 1]);
}
}

// These are the extended grapheme clusters
// And the JS' segmenter only cares extended grapheme clusters
extgraphs.push(extwork);

if (arraysEqual(extgraphs, c)) {
wordTests.push([allChars, c]);
} else {
wordTests.push([allChars, extgraphs]);
}
}

Expand All @@ -741,7 +778,20 @@ let printTestDataModule = async f => {
*/
`,
);
printTableRaw(f, 'TESTDATA_GRAPHEME', tests, formatTestCase);
printTableRaw(f, 'TESTDATA_GRAPHEME', graphemeTests, formatTestCase);
f.write('\n');

f.write(`
/**
* Official Unicode test data for word break
*
* @see http://www.unicode.org/Public/${UNICODE_VERSION_STRING}/ucd/auxiliary/WordBreakTest.txt
*
* @type {TestCase[]}
*/
`,
);
printTableRaw(f, 'TESTDATA_WORD', wordTests, formatTestCase);
f.write('\n');
};

Expand Down Expand Up @@ -779,12 +829,12 @@ let emitTest = async (file, print) => {
let [
graphemeData,
emojiData,
// wordData,
wordData,
// sentenceData,
] = await Promise.all([
fetchData('auxiliary/GraphemeBreakProperty.txt'),
fetchData('emoji/emoji-data.txt'),
// fetchData('auxiliary/WordBreakProperty.txt'),
fetchData('auxiliary/WordBreakProperty.txt'),
// fetchData('auxiliary/SentenceBreakProperty.txt'),
]);

Expand Down Expand Up @@ -823,15 +873,15 @@ for (let chars of graphemeTable) {
last = chars[1];
}

// let wordCats = parseProperties(wordData);
// /** @type {CategorizedUnicodeRange[]} */
// let wordTable = [];
// for (let [cat, ranges] of Object.entries(wordCats)) {
// for (let [from, to] of ranges) {
// graphemeTable.push([from, to, cat]);
// }
// }
// wordTable.sort((a, b) => a[0] - b[0]);
let wordCats = parseProperties(wordData);
/** @type {CategorizedUnicodeRange[]} */
let wordTable = [];
for (let [cat, ranges] of Object.entries(wordCats)) {
for (let [from, to] of ranges) {
wordTable.push([from, to, cat]);
}
}
wordTable.sort((a, b) => a[0] - b[0]);

// let sentenceCats = parseProperties(sentenceData);
// /** @type {CategorizedUnicodeRange[]} */
Expand All @@ -853,15 +903,15 @@ await emitSrc(
),
);

// emitSrc(
// '_word_data.js',
// async f => printBreakModule(
// f,
// wordTable,
// Object.keys(wordCats),
// 'word',
// ),
// );
emitSrc(
'_word_data.js',
async f => printBreakModule(
f,
wordTable,
Object.keys(wordCats),
'word',
),
);

// emitSrc(
// '_sentence_data.js',
Expand Down
120 changes: 120 additions & 0 deletions src/_word_data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// The following code was generated by "scripts/unicode.js",
// DO NOT EDIT DIRECTLY.
//
// @ts-check

import { decodeUnicodeData } from './core.js';

/**
* @typedef {import('./core.js').UnicodeDataEncoding} UnicodeDataEncoding
*/

/**
* @typedef {0} WC_Any
* @typedef {1} WC_ALetter
* @typedef {2} WC_CR
* @typedef {3} WC_Double_Quote
* @typedef {4} WC_Extend
* @typedef {5} WC_ExtendNumLet
* @typedef {6} WC_Format
* @typedef {7} WC_Hebrew_Letter
* @typedef {8} WC_Katakana
* @typedef {9} WC_LF
* @typedef {10} WC_MidLetter
* @typedef {11} WC_MidNum
* @typedef {12} WC_MidNumLet
* @typedef {13} WC_Newline
* @typedef {14} WC_Numeric
* @typedef {15} WC_Regional_Indicator
* @typedef {16} WC_Single_Quote
* @typedef {17} WC_WSegSpace
* @typedef {18} WC_ZWJ
* @typedef {(
* | WC_Any
* | WC_ALetter
* | WC_CR
* | WC_Double_Quote
* | WC_Extend
* | WC_ExtendNumLet
* | WC_Format
* | WC_Hebrew_Letter
* | WC_Katakana
* | WC_LF
* | WC_MidLetter
* | WC_MidNum
* | WC_MidNumLet
* | WC_Newline
* | WC_Numeric
* | WC_Regional_Indicator
* | WC_Single_Quote
* | WC_WSegSpace
* | WC_ZWJ
* )} WordCategoryNum
*/

/**
* @typedef {import('./core.js').CategorizedUnicodeRange<WordCategoryNum>} WordCategoryRange
*/

/**
* @typedef {(
* | 'Any'
* | 'ALetter'
* | 'CR'
* | 'Double_Quote'
* | 'Extend'
* | 'ExtendNumLet'
* | 'Format'
* | 'Hebrew_Letter'
* | 'Katakana'
* | 'LF'
* | 'MidLetter'
* | 'MidNum'
* | 'MidNumLet'
* | 'Newline'
* | 'Numeric'
* | 'Regional_Indicator'
* | 'Single_Quote'
* | 'WSegSpace'
* | 'ZWJ'
* )} WordCategoryKey
*/

/**
* Grapheme category enum
*
* Note: The enum object is not actually `Object.freeze`
* because it increases 800 bytes of Brotli compression... Not sure why :P
*
* @type {Readonly<Record<WordCategoryKey, WordCategoryNum>>}
*/
export const WordCategory = {
Any: 0,
ALetter: 1,
CR: 2,
Double_Quote: 3,
Extend: 4,
ExtendNumLet: 5,
Format: 6,
Hebrew_Letter: 7,
Katakana: 8,
LF: 9,
MidLetter: 10,
MidNum: 11,
MidNumLet: 12,
Newline: 13,
Numeric: 14,
Regional_Indicator: 15,
Single_Quote: 16,
WSegSpace: 17,
ZWJ: 18,
};

/**
* @type {WordCategoryRange[]}
*/
export const word_ranges = decodeUnicodeData(
/** @type {UnicodeDataEncoding} */
('a,,b,1,d,,w,,y,,13,,18,,1a,,1c,9,1m,,1n,,1t,p,2n,,2p,p,3p,,4q,,4t,,51,,53,,56,,5c,m,60,u,6w,db,ke,x,lc,33,og,4,om,1,oq,3,ou,,ov,,p2,,p3,,p4,2,p8,,pa,j,pv,2a,s7,3u,w3,6,wa,4l,10x,11,121,3,126,,127,,128,14,13d,,13e,,13l,18,14v,,14x,1,150,1,153,,15c,q,167,3,16b,,16c,,16o,5,170,1,174,a,17g,,17k,16,18r,k,19c,9,19n,,19o,,19q,1,19s,,19t,2q,1cl,,1cm,6,1ct,,1cv,5,1d1,1,1d3,1,1d6,3,1da,1,1dc,9,1dm,2,1dr,,1e7,1,1e9,,1ea,t,1f4,q,1fx,2g,1ie,a,1ip,,1j4,9,1je,w,1kb,8,1kk,1,1ko,,1kq,,1kt,,1kw,l,1li,3,1lm,,1ln,8,1lw,,1lx,2,1m0,,1m1,4,1mo,o,1nd,2,1nk,a,1o0,n,1op,5,1ow,1,1p3,8,1pc,15,1qi,n,1r6,,1r7,w,1s4,1h,1tm,2,1tp,,1tq,h,1u8,,1u9,6,1ug,9,1uq,1,1uu,9,1v5,f,1vl,2,1vp,7,1vz,1,1w3,l,1wq,6,1wy,,1x2,3,1x8,,1x9,,1xa,6,1xj,1,1xn,2,1xq,,1xz,,1y4,1,1y7,2,1ya,1,1ye,9,1yo,1,1z0,,1z2,,1z5,2,1z9,5,1zj,1,1zn,l,20a,6,20i,1,20l,1,20o,1,20s,,20u,4,213,1,217,2,21d,,21l,3,21q,,21y,9,228,1,22a,2,22d,,22p,2,22t,8,233,2,237,l,23u,6,242,1,245,4,24c,,24d,,24e,7,24n,2,24r,2,24w,,25c,1,25e,1,25i,9,261,,262,5,269,2,26d,7,26n,1,26r,l,27e,6,27m,1,27p,4,27w,,27x,,27y,6,287,1,28b,2,28l,2,28s,1,28v,2,28y,1,292,9,29d,,29u,,29v,,29x,5,2a6,2,2aa,3,2ah,1,2ak,,2am,1,2ar,1,2aw,2,2b2,b,2bi,4,2bq,2,2bu,3,2c0,,2c7,,2cm,9,2dc,4,2dh,7,2dq,2,2du,m,2ei,f,2f0,,2f1,,2f2,6,2fa,2,2fe,3,2fp,1,2fs,2,2fx,,2g0,1,2g2,1,2g6,9,2gw,,2gx,2,2h1,7,2ha,2,2he,m,2i2,9,2id,4,2ik,,2il,,2im,6,2iu,2,2iy,3,2j9,1,2jh,1,2jk,1,2jm,1,2jq,9,2k1,1,2k3,,2kg,3,2kk,8,2ku,2,2ky,14,2m3,1,2m5,,2m6,6,2me,2,2mi,3,2mm,,2ms,2,2mv,,2n3,2,2n6,1,2na,9,2nu,5,2o1,2,2o5,h,2oq,n,2pf,8,2pp,,2ps,6,2q2,,2q7,5,2qe,,2qg,7,2qu,9,2r6,1,2sx,,2t0,6,2tj,7,2ts,9,2wh,,2wk,8,2x4,6,2xc,9,2yo,,2zc,1,2zk,9,305,,307,,309,,30e,1,30g,7,30p,z,31t,j,32e,1,32g,4,32l,a,32x,z,346,,36z,j,37k,9,386,3,38e,2,38i,2,38n,6,38x,3,39e,b,39r,,39s,9,3a2,3,3a8,11,3bb,,3bh,,3bk,16,3cs,98,3m2,3,3m8,6,3mg,,3mi,3,3mo,14,3nu,3,3o0,w,3oy,3,3p4,6,3pc,,3pe,3,3pk,e,3q0,1k,3rm,3,3rs,1u,3tp,2,3uo,f,3vk,2d,3y0,5,3y9,h7,4fj,g,4g0,,4g1,p,4gw,22,4j2,a,4jk,h,4k2,3,4kf,i,4ky,2,4lc,h,4lu,1,4m8,c,4mm,2,4mq,1,4ok,v,4pp,,4ps,9,4qz,2,4r2,,4r3,,4r4,9,4rk,2g,4u8,4,4ud,1,4uf,x,4vd,,4ve,,4vk,1x,4xs,u,4yo,b,4z4,b,4zq,9,53k,a,54w,m,55j,4,579,9,57k,s,58f,,58g,9,58w,9,59s,u,5c0,4,5c5,1a,5dg,g,5dx,7,5e8,9,5ez,8,5fk,2,5fn,t,5gh,c,5gu,1,5gw,9,5h6,17,5ie,d,5j4,z,5k4,j,5kw,9,5l9,2,5lc,9,5lm,z,5mo,a,5n4,16,5od,2,5ow,2,5p0,k,5pl,3,5pp,,5pq,5,5pw,,5px,1,5pz,2,5q2,,5q8,5b,5vk,1r,5xc,7p,654,5,65c,11,66g,5,66o,7,66x,,66z,,671,,673,u,680,1g,69i,6,69q,,69u,2,69y,6,6a8,3,6ae,5,6ao,c,6b6,2,6ba,6,6bk,6,6bs,2,6bw,,6bx,,6by,1,6c8,1,6ck,,6cn,,6co,1,6cq,4,6cv,,6db,1,6dg,,6dw,,6e7,,6e8,4,6ee,9,6ep,,6f3,,6fk,c,6hc,w,6iq,,6iv,,6iy,9,6j9,,6jd,4,6jo,,6jq,,6js,,6ju,3,6jz,a,6kc,3,6kl,4,6ku,,6lc,14,792,1f,8ow,6c,8vf,3,8vj,2,8vm,1,8w0,11,8x3,,8x9,,8xc,1j,8z3,,8zj,,8zk,m,90g,6,90o,6,90w,6,914,6,91c,6,91k,6,91s,6,920,6,928,v,94f,,9hc,,9hh,,9ii,5,9ip,4,9iz,1,9ll,1,9ln,1,9ls,2i,9oc,3,9ol,16,9pt,2l,9sw,v,9v4,f,a1c,1a,a2o,2f,vls,wc,wk0,19,wlc,7g,wsw,f,wtc,9,wtm,1,wu8,1a,wvj,3,wvo,9,wvz,u,wwu,1,www,27,wz4,1,wzs,5h,x5c,1,x5f,,x5h,7,x6a,f,x6q,,x6r,2,x6u,,x6v,3,x6z,,x70,m,x7n,4,x7w,,x8g,1f,xa8,1,xaa,1d,xbo,h,xcg,9,xcw,h,xde,5,xdn,,xdp,1,xdr,,xds,9,xe2,r,xeu,7,xf4,m,xfr,c,xgg,s,xhc,3,xhg,1a,xir,d,xjj,,xjk,9,xk5,,xkg,9,xkw,14,xm1,d,xmo,2,xmr,,xms,7,xn0,1,xn4,9,xob,2,xps,,xpu,2,xpz,1,xq6,1,xq9,,xr4,a,xrf,4,xrm,2,xrp,1,xs1,5,xs9,5,xsh,5,xsw,6,xt4,6,xtc,1l,xv4,36,xyb,7,xyk,1,xyo,9,xz4,8mb,16ls,m,16mj,1c,1dkw,6,1dlf,4,1dlp,,1dlq,,1dlr,9,1dm2,c,1dmg,4,1dmm,,1dmo,1,1dmr,1,1dmu,9,1dn4,2p,1dqr,a2,1e1c,1r,1e36,1h,1e5s,b,1e68,f,1e6r,,1e74,f,1e7n,1,1e8d,2,1e8g,,1e8i,,1e8k,,1e8l,,1e9c,4,1e9i,3q,1edb,,1edj,,1edo,,1edq,,1eds,9,1ee2,,1ee3,,1ee9,p,1ef3,,1ef5,p,1eg6,1j,1ehq,1,1ehs,u,1eiq,5,1eiy,5,1ej6,5,1eje,2,1ek9,2,1ekg,b,1ekt,p,1elk,i,1em4,1,1em7,e,1emo,d,1eo0,3e,1etc,1g,1eyl,,1f28,s,1f34,1c,1f4w,,1f5s,v,1f71,t,1f80,11,1f92,4,1f9c,t,1fa8,z,1fbc,7,1fbl,4,1fcw,4d,1fhc,9,1fhs,z,1fiw,z,1fk0,13,1flc,1f,1fn4,a,1fng,e,1fnw,6,1fo4,1,1fo7,a,1foj,e,1foz,6,1fp7,1,1fpc,1f,1fr4,8m,1g00,l,1g0w,7,1g1s,5,1g1z,15,1g36,8,1g5c,5,1g5k,,1g5m,17,1g6v,1,1g70,,1g73,m,1g80,m,1g8w,u,1gbk,i,1gc4,1,1gcg,l,1gdc,p,1gg0,1j,1ghq,1,1gjk,,1gjl,2,1gjp,1,1gjw,3,1gk0,3,1gk5,2,1gk9,s,1gl4,2,1glb,,1gm8,s,1gn4,s,1gow,7,1gp5,r,1gpx,1,1gqo,1h,1gsg,l,1gtc,i,1gu8,h,1gxs,20,1h1c,1e,1h34,1e,1h4w,z,1h5w,3,1h68,9,1h6o,9,1h6y,r,1h7t,4,1h7z,m,1hfk,15,1hgr,1,1hgw,1,1hhe,2,1hj0,3,1hj4,s,1hk7,,1hkg,l,1hl2,a,1hm8,h,1hmq,3,1ho0,k,1hpc,m,1hq8,2,1hqb,1g,1hrs,e,1ht2,9,1htc,,1htd,1,1htf,1,1hth,,1htr,3,1htv,18,1hv4,a,1hvh,,1hvm,,1hvx,,1hw0,o,1hww,9,1hxc,2,1hxf,z,1hyf,d,1hyu,9,1hz8,,1hz9,1,1hzb,,1hzk,y,1i0j,,1i0m,,1i0w,2,1i0z,1b,1i2b,d,1i2p,3,1i2x,3,1i32,1,1i34,9,1i3e,,1i3g,,1i4g,h,1i4z,o,1i5o,b,1i66,,1i67,1,1i69,,1i80,6,1i88,,1i8a,3,1i8f,e,1i8v,9,1i9c,1a,1ian,b,1ib4,9,1ibk,3,1ibp,7,1ibz,1,1ic3,l,1icq,6,1icy,1,1id1,4,1id7,1,1id9,,1ida,6,1idj,1,1idn,2,1ids,,1idz,,1ie5,4,1iea,1,1iee,6,1ieo,4,1if4,9,1iff,,1ifi,,1ifk,11,1ign,,1igo,8,1igy,,1ih1,,1ih3,3,1ih8,4,1ihd,,1ihe,,1ihf,,1iht,1,1iio,1g,1ik5,h,1ikn,3,1ikw,9,1ila,,1ilb,2,1im8,1b,1ink,j,1io4,1,1io7,,1iog,9,1itc,1a,1iun,6,1iuw,8,1ivs,3,1ivw,1,1iww,1b,1iy8,g,1iys,,1iz4,9,1j0g,16,1j1n,c,1j20,,1j28,9,1j2o,j,1j4t,e,1j5c,9,1jb4,17,1jcc,e,1jfk,1r,1jhc,9,1ji7,7,1jih,,1jik,7,1jit,1,1jiw,n,1jjk,5,1jjr,1,1jjv,3,1jjz,,1jk0,,1jk1,,1jk2,1,1jkg,9,1jmo,7,1jmy,12,1jo1,6,1joa,6,1joh,,1joj,,1jok,,1jpc,,1jpd,9,1jpn,13,1jqr,6,1jqy,,1jqz,3,1jrb,,1jrk,,1jrl,a,1jrw,19,1jt6,f,1jtp,,1ju8,20,1k1s,w,1k34,9,1k3k,8,1k3u,10,1k4v,7,1k54,7,1k5c,,1k5s,9,1k6q,t,1k7m,l,1k89,d,1kao,6,1kaw,1,1kaz,11,1kc1,5,1kca,,1kcc,1,1kcf,6,1kcm,,1kcn,,1kcw,9,1kdc,5,1kdj,1,1kdm,v,1kei,4,1keo,1,1ker,4,1kew,,1kf4,9,1ko0,i,1koj,3,1kow,1,1koy,,1koz,,1kp0,c,1kpe,x,1kqc,6,1kqm,4,1kr4,9,1kre,,1kts,,1kw0,pl,1log,32,1ls0,5f,1nyo,2o,1o1s,tr,1ovk,f,1ow0,,1ow1,5,1ow7,e,1oww,32y,1s00,g6,1xq8,t,1xr2,h,1xrk,9,1z40,fs,1zk0,u,1zkw,9,1zlc,26,1znk,9,1zo0,t,1zow,4,1zpc,1b,1zqo,6,1zr4,3,1zrk,9,1zs3,k,1zst,i,205c,18,206o,9,20cg,1r,20hs,22,20jz,,20k0,,20k1,1i,20lr,3,20lv,c,20o0,1,20o3,,20o4,,20og,1,2dbk,3,2dbp,6,2dbx,1,2dc0,,2dk0,2,2dlh,,2dlw,3,2fpc,2y,2fsg,c,2fsw,8,2ftc,9,2ftp,1,2fts,3,2j1s,9,2jgg,19,2jhs,m,2jxh,4,2jxp,5,2jxv,7,2jy3,7,2jyd,6,2jze,3,2k3m,2,2kg0,2c,2kie,1y,2kke,1,2kki,,2kkl,1,2kkp,3,2kku,b,2kl7,,2kl9,6,2klh,1s,2knb,3,2knh,7,2knq,6,2kny,r,2kor,3,2kow,4,2kp2,,2kp6,6,2kpe,9f,2kyw,o,2kzm,o,2l0c,u,2l18,o,2l1y,u,2l2u,o,2l3k,u,2l4g,o,2l56,u,2l62,o,2l6s,7,2l72,1d,2lmo,1i,2lob,1d,2lpx,,2lqc,,2lqz,4,2lr5,e,2mm8,u,2mn9,5,2mtc,6,2mtk,g,2mu3,6,2mub,1,2mue,4,2muo,1p,2mxb,,2n0g,18,2n1s,6,2n1z,6,2n28,9,2n2m,,2nbk,t,2nce,,2ncw,17,2ne4,3,2ne8,9,2nrk,r,2nsc,3,2nsg,9,2nyo,t,2nzi,1,2nzk,,2nzl,9,2odc,6,2odk,3,2odp,1,2ods,e,2oe8,5g,2ok0,6,2olc,1v,2on8,6,2onf,,2onk,9,2pkw,3,2pl1,q,2plt,1,2plw,,2plz,,2pm1,9,2pmc,3,2pmh,,2pmj,,2pmq,,2pmv,,2pmx,,2pmz,,2pn1,2,2pn5,1,2pn8,,2pnb,,2pnd,,2pnf,,2pnh,,2pnj,,2pnl,1,2pno,,2pnr,3,2pnw,6,2po4,3,2po9,3,2poe,,2pog,9,2por,g,2ppd,2,2pph,4,2ppn,g,2q7k,p,2q8g,p,2q9c,p,2qcm,p,2qrf,4,2sc0,9,jny9,,jnz4,2n,jo5c,6n'),
'9d2h3gbceab151d161a111114111b11a1111141111a1b144444771aeb4614eeb14114e41441e111414141e141b141414141414111e414e414141414e141111114144414114e114411111114444411e414411111141444114e144111111414444114e14111111111144414e411114144441114e1411111414444114e1441114144411414e14111114444e4444e444e14e4444114414444e4444444e411111111111111111111411111h11114141411444e464e1141411144ee14444ee44141e44141e1414e1e1111441414141141111111111111111111hh4i6ccad655b5h661114111111111111111114111111411111111141h148148881118881111e1144141411111414141441414e41114e141414141e4e141414e4444441414111111144e11111747777777111114a455bcba116cbceab15184111116111111114114111411111e11111111111111111111111111111111114441114411114111111114ee1411411411141411414e4141414e4e1e414e141141414144e111144141111114e41111114144414144411111444441414141e411411e14414141e141ee4e141e111114441414e114411414141441414111e11441e144111444414e1114441e144141144e411111164141114e11e1e14141e111e114144111448888888111146e444464444111111111111111111111111111111e444444114444414141e11414e14e141e111114141e111111111111111111111111111111111111f4e644',
);
Loading
Loading