ygopro-deck-encode 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,6 +15,18 @@ const anotherDeck = YGOProDeck.fromEncodedString(code); // decode it back
15
15
 
16
16
  const ydk = deck.toYdkString(); // YDK format
17
17
  const yetAnotherDeck = YGOProDeck.fromYdkString(ydk); // decode it back
18
+
19
+ const ydke = deck.toYdkeURL();
20
+ const yetAnotherDeck2 = YGOProDeck.fromYdkeURL(ydke); // decode it back
21
+
22
+ const ygomobileDeckUrl = deck.toYGOMobileDeckURL(); // YGOMobile Deck URL
23
+ const yetAnotherDeck3 = YGOProDeck.fromYGOMobileDeckURL(ygomobileDeckUrl); // decode it back
24
+
25
+ const updateDeckPayload = deck.toUpdateDeckPayload(); // payload for MSG_UPDATE_DECK
26
+ // decode it back, but a callback is needed for check if it's extra deck
27
+ // use SQLite3 is recommended
28
+ // by default, it would assume everything is main deck
29
+ const yetAnotherDeck4 = YGOProDeck.fromUpdateDeckPayload(updateDeckPayload, (code, i, mainc) => i >= mainc - 15);
18
30
  ```
19
31
 
20
32
 
package/dist/index.cjs CHANGED
@@ -23,6 +23,25 @@ __export(ygopro_deck_encode_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(ygopro_deck_encode_exports);
25
25
 
26
+ // src/base64.ts
27
+ function toBase64Url(bytes) {
28
+ const base64 = typeof Buffer !== "undefined" ? Buffer.from(bytes).toString("base64") : btoa(String.fromCharCode(...bytes));
29
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
30
+ }
31
+ function fromBase64Url(encoded) {
32
+ const base64 = encoded.replace(/-/g, "+").replace(/_/g, "/");
33
+ const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
34
+ if (typeof Buffer !== "undefined") {
35
+ return Uint8Array.from(Buffer.from(padded, "base64"));
36
+ }
37
+ const binary = atob(padded);
38
+ const bytes = new Uint8Array(binary.length);
39
+ for (let i = 0; i < binary.length; i++) {
40
+ bytes[i] = binary.charCodeAt(i);
41
+ }
42
+ return bytes;
43
+ }
44
+
26
45
  // src/utils.ts
27
46
  function countItems(arr) {
28
47
  const map = /* @__PURE__ */ new Map();
@@ -31,49 +50,264 @@ function countItems(arr) {
31
50
  }
32
51
  return map;
33
52
  }
34
- var BufferWriter = class {
35
- constructor(length) {
53
+ var BufferCursor = class {
54
+ constructor(bufOrLength) {
36
55
  this.pointer = 0;
37
- this.buffer = new Uint8Array(length);
56
+ if (typeof bufOrLength === "number") {
57
+ this.buffer = new Uint8Array(bufOrLength);
58
+ } else {
59
+ this.buffer = bufOrLength;
60
+ }
61
+ }
62
+ /**
63
+ * 安全地将 pointer 向前移动指定字节数。
64
+ * @param bytes 要移动的字节数
65
+ * @returns 原来 pointer 的值
66
+ * @throws RangeError 如果越界
67
+ */
68
+ increasePointer(bytes) {
69
+ const old = this.pointer;
70
+ const next = old + bytes;
71
+ if (next > this.buffer.length) {
72
+ throw new RangeError(
73
+ `Pointer overflow: tried to move to ${next}, but buffer length is ${this.buffer.length}`
74
+ );
75
+ }
76
+ this.pointer = next;
77
+ return old;
78
+ }
79
+ };
80
+ var BufferWriter = class extends BufferCursor {
81
+ constructor(length) {
82
+ super(length);
38
83
  }
39
84
  writeUint32LE(value) {
40
- this.buffer[this.pointer++] = value & 255;
41
- this.buffer[this.pointer++] = value >>> 8 & 255;
42
- this.buffer[this.pointer++] = value >>> 16 & 255;
43
- this.buffer[this.pointer++] = value >>> 24 & 255;
85
+ const idx = this.increasePointer(4);
86
+ this.buffer[idx] = value & 255;
87
+ this.buffer[idx + 1] = value >>> 8 & 255;
88
+ this.buffer[idx + 2] = value >>> 16 & 255;
89
+ this.buffer[idx + 3] = value >>> 24 & 255;
44
90
  return this;
45
91
  }
46
92
  writeUint32BE(value) {
47
- this.buffer[this.pointer++] = value >>> 24 & 255;
48
- this.buffer[this.pointer++] = value >>> 16 & 255;
49
- this.buffer[this.pointer++] = value >>> 8 & 255;
50
- this.buffer[this.pointer++] = value & 255;
93
+ const idx = this.increasePointer(4);
94
+ this.buffer[idx] = value >>> 24 & 255;
95
+ this.buffer[idx + 1] = value >>> 16 & 255;
96
+ this.buffer[idx + 2] = value >>> 8 & 255;
97
+ this.buffer[idx + 3] = value & 255;
51
98
  return this;
52
99
  }
53
100
  writeUint16LE(value) {
54
- this.buffer[this.pointer++] = value & 255;
55
- this.buffer[this.pointer++] = value >>> 8 & 255;
101
+ const idx = this.increasePointer(2);
102
+ this.buffer[idx] = value & 255;
103
+ this.buffer[idx + 1] = value >>> 8 & 255;
56
104
  return this;
57
105
  }
58
106
  writeUint16BE(value) {
59
- this.buffer[this.pointer++] = value >>> 8 & 255;
60
- this.buffer[this.pointer++] = value & 255;
107
+ const idx = this.increasePointer(2);
108
+ this.buffer[idx] = value >>> 8 & 255;
109
+ this.buffer[idx + 1] = value & 255;
61
110
  return this;
62
111
  }
63
112
  writeUint8(value) {
64
- this.buffer[this.pointer++] = value & 255;
113
+ const idx = this.increasePointer(1);
114
+ this.buffer[idx] = value & 255;
65
115
  return this;
66
116
  }
67
117
  writeString(str) {
68
118
  for (let i = 0; i < str.length; i++) {
69
- this.buffer[this.pointer++] = str.charCodeAt(i);
119
+ const idx = this.increasePointer(1);
120
+ this.buffer[idx] = str.charCodeAt(i);
70
121
  }
71
122
  return this;
72
123
  }
73
124
  };
125
+ var BufferReader = class extends BufferCursor {
126
+ constructor(buf) {
127
+ super(buf);
128
+ }
129
+ readUint32LE() {
130
+ const idx = this.increasePointer(4);
131
+ const b = this.buffer;
132
+ return (b[idx] | b[idx + 1] << 8 | b[idx + 2] << 16 | b[idx + 3] << 24) >>> 0;
133
+ }
134
+ readUint32BE() {
135
+ const idx = this.increasePointer(4);
136
+ const b = this.buffer;
137
+ return (b[idx] << 24 | b[idx + 1] << 16 | b[idx + 2] << 8 | b[idx + 3]) >>> 0;
138
+ }
139
+ readUint16LE() {
140
+ const idx = this.increasePointer(2);
141
+ const b = this.buffer;
142
+ return b[idx] | b[idx + 1] << 8;
143
+ }
144
+ readUint16BE() {
145
+ const idx = this.increasePointer(2);
146
+ const b = this.buffer;
147
+ return b[idx] << 8 | b[idx + 1];
148
+ }
149
+ readUint8() {
150
+ const idx = this.increasePointer(1);
151
+ return this.buffer[idx];
152
+ }
153
+ readString(length) {
154
+ let s = "";
155
+ for (let i = 0; i < length; i++) {
156
+ const idx = this.increasePointer(1);
157
+ s += String.fromCharCode(this.buffer[idx]);
158
+ }
159
+ return s;
160
+ }
161
+ readRemaining() {
162
+ const remaining = this.buffer.length - this.pointer;
163
+ const idx = this.increasePointer(remaining);
164
+ return this.buffer.subarray(idx, this.buffer.length);
165
+ }
166
+ };
167
+
168
+ // src/ydke.ts
169
+ function base64ToUint32Array(base64) {
170
+ const binary = atob(base64);
171
+ const bytes = new Uint8Array(binary.length);
172
+ for (let i = 0; i < binary.length; i++) {
173
+ bytes[i] = binary.charCodeAt(i);
174
+ }
175
+ const view = new DataView(bytes.buffer);
176
+ const result = [];
177
+ for (let i = 0; i < bytes.length; i += 4) {
178
+ result.push(view.getUint32(i, true));
179
+ }
180
+ return result;
181
+ }
182
+ function uint32ArrayToBase64(data) {
183
+ const buffer = new ArrayBuffer(data.length * 4);
184
+ const view = new DataView(buffer);
185
+ data.forEach((val, i) => view.setUint32(i * 4, val, true));
186
+ const bytes = new Uint8Array(buffer);
187
+ let binary = "";
188
+ for (let i = 0; i < bytes.length; i++) {
189
+ binary += String.fromCharCode(bytes[i]);
190
+ }
191
+ return btoa(binary);
192
+ }
193
+ function toYdkeURL(deck) {
194
+ return "ydke://" + uint32ArrayToBase64(deck.main) + "!" + uint32ArrayToBase64(deck.extra) + "!" + uint32ArrayToBase64(deck.side) + "!";
195
+ }
196
+ function fromYdkeURL(ydke) {
197
+ if (!ydke.startsWith("ydke://")) {
198
+ throw new Error("Invalid ydke:// URI");
199
+ }
200
+ const [mainStr, extraStr, sideStr] = ydke.slice(7).split("!");
201
+ if (mainStr === void 0 || extraStr === void 0 || sideStr === void 0) {
202
+ throw new Error("Incomplete ydke:// URI");
203
+ }
204
+ return {
205
+ main: base64ToUint32Array(mainStr),
206
+ extra: base64ToUint32Array(extraStr),
207
+ side: base64ToUint32Array(sideStr)
208
+ };
209
+ }
210
+
211
+ // src/ygom.ts
212
+ var QUERY_YGO_TYPE = "ygotype";
213
+ var QUERY_VERSION = "v";
214
+ var ARG_DECK = "deck";
215
+ var QUERY_DECK = "d";
216
+ var QUERY_NAME = "name";
217
+ var URL_SCHEME_HTTP = "http";
218
+ var URL_HOST_DECK = "deck.ourygo.top";
219
+ function toBinary(value, length) {
220
+ return value.toString(2).padStart(length, "0");
221
+ }
222
+ function encodeCards(cards) {
223
+ const bits = [];
224
+ for (let i = 0; i < cards.length; ) {
225
+ const id = cards[i];
226
+ let count = 1;
227
+ while (i + count < cards.length && cards[i + count] === id && count < 3)
228
+ count++;
229
+ const prefix = count === 2 ? "10" : count === 3 ? "11" : "01";
230
+ bits.push(prefix + toBinary(id, 27));
231
+ i += count;
232
+ }
233
+ return bits.join("");
234
+ }
235
+ function countUnique(cards) {
236
+ let num = 0;
237
+ for (let i = 0; i < cards.length; i++) {
238
+ const id = cards[i];
239
+ if (id > 0) {
240
+ num++;
241
+ if (i < cards.length - 1 && cards[i + 1] === id) {
242
+ i++;
243
+ if (i < cards.length - 1 && cards[i + 1] === id) {
244
+ i++;
245
+ }
246
+ }
247
+ }
248
+ }
249
+ return num;
250
+ }
251
+ function toYGOMobileDeckURL(main, extra, side, customParams = {}) {
252
+ const mNum = countUnique(main);
253
+ const eNum = countUnique(extra);
254
+ const sNum = countUnique(side);
255
+ const header = toBinary(mNum, 8) + toBinary(eNum, 4) + toBinary(sNum, 4);
256
+ let bitString = header + encodeCards(main) + encodeCards(extra) + encodeCards(side);
257
+ while (bitString.length % 8 !== 0)
258
+ bitString += "0";
259
+ const bytes = new Uint8Array(bitString.length / 8);
260
+ for (let i = 0; i < bytes.length; i++) {
261
+ bytes[i] = parseInt(bitString.slice(i * 8, i * 8 + 8), 2);
262
+ }
263
+ let encoded = toBase64Url(bytes);
264
+ const searchParams = new URLSearchParams();
265
+ for (const [key, value] of Object.entries(customParams)) {
266
+ searchParams.set(key, value);
267
+ }
268
+ searchParams.set(QUERY_YGO_TYPE, ARG_DECK);
269
+ searchParams.set(QUERY_VERSION, "1");
270
+ searchParams.set(QUERY_DECK, encoded);
271
+ return `${URL_SCHEME_HTTP}://${URL_HOST_DECK}?${searchParams.toString()}`;
272
+ }
273
+ function fromYGOMobileDeckURL(uri) {
274
+ const url = new URL(uri);
275
+ if (url.searchParams.get(QUERY_YGO_TYPE) !== ARG_DECK) {
276
+ throw new Error("Not a YGO Mobile deck URI");
277
+ }
278
+ let encoded = url.searchParams.get(QUERY_DECK);
279
+ if (!encoded)
280
+ throw new Error("Missing deck data");
281
+ const bytes = fromBase64Url(encoded);
282
+ const bits = Array.from(bytes).map((b) => b.toString(2).padStart(8, "0")).join("");
283
+ const mNum = parseInt(bits.slice(0, 8), 2);
284
+ const eNum = parseInt(bits.slice(8, 12), 2);
285
+ const sNum = parseInt(bits.slice(12, 16), 2);
286
+ const all = mNum + eNum + sNum;
287
+ const cards = [];
288
+ let pos = 16;
289
+ const res = {
290
+ main: [],
291
+ extra: [],
292
+ side: []
293
+ };
294
+ let i = 0;
295
+ while (pos + 29 <= bits.length && cards.length < all) {
296
+ const countBits = bits.slice(pos, pos + 2);
297
+ const count = countBits === "10" ? 2 : countBits === "11" ? 3 : 1;
298
+ const id = parseInt(bits.slice(pos + 2, pos + 29), 2);
299
+ const field = i < mNum ? "main" : i < mNum + eNum ? "extra" : "side";
300
+ res[field].push(...Array(count).fill(id));
301
+ pos += 29;
302
+ i++;
303
+ }
304
+ return {
305
+ ...res,
306
+ name: url.searchParams.get(QUERY_NAME)
307
+ };
308
+ }
74
309
 
75
310
  // index.ts
76
- var import_js_base64 = require("js-base64");
77
311
  var YGOProDeck = class {
78
312
  constructor() {
79
313
  this.main = [];
@@ -102,7 +336,7 @@ var YGOProDeck = class {
102
336
  return writer.buffer;
103
337
  }
104
338
  toEncodedString() {
105
- return import_js_base64.Base64.fromUint8Array(this.toUint8Array(), true);
339
+ return toBase64Url(this.toUint8Array());
106
340
  }
107
341
  toString() {
108
342
  return this.toEncodedString();
@@ -124,7 +358,7 @@ var YGOProDeck = class {
124
358
  return new YGOProDeck().fromUint8Array(buf);
125
359
  }
126
360
  fromEncodedString(str) {
127
- return this.fromUint8Array(import_js_base64.Base64.toUint8Array(str));
361
+ return this.fromUint8Array(fromBase64Url(str));
128
362
  }
129
363
  static fromEncodedString(str) {
130
364
  return new YGOProDeck().fromEncodedString(str);
@@ -163,12 +397,69 @@ var YGOProDeck = class {
163
397
  static fromYdkString(str) {
164
398
  return new YGOProDeck().fromYdkString(str);
165
399
  }
400
+ fromUpdateDeckPayload(buf, isExtraDeckCard = () => false) {
401
+ const reader = new BufferReader(buf);
402
+ const mainc = reader.readUint32LE();
403
+ const sidec = reader.readUint32LE();
404
+ this.main = [];
405
+ this.extra = [];
406
+ this.side = [];
407
+ for (let i = 0; i < mainc; i++) {
408
+ const id = reader.readUint32LE();
409
+ if (isExtraDeckCard(id, i, mainc)) {
410
+ this.extra.push(id);
411
+ } else {
412
+ this.main.push(id);
413
+ }
414
+ }
415
+ for (let i = 0; i < sidec; i++) {
416
+ const id = reader.readUint32LE();
417
+ this.side.push(id);
418
+ }
419
+ return this;
420
+ }
421
+ static fromUpdateDeckPayload(buf, isExtraDeckCard = () => false) {
422
+ return new YGOProDeck().fromUpdateDeckPayload(buf, isExtraDeckCard);
423
+ }
166
424
  toUpdateDeckPayload() {
167
425
  const cards = [...this.main, ...this.extra, ...this.side];
168
426
  const writer = new BufferWriter(cards.length * 4 + 8).writeUint32LE(this.main.length + this.extra.length).writeUint32LE(this.side.length);
169
427
  cards.forEach((id) => writer.writeUint32LE(id));
170
428
  return writer.buffer;
171
429
  }
430
+ fromYGOMobileDeckURL(uri) {
431
+ const parsed = fromYGOMobileDeckURL(uri);
432
+ this.main = parsed.main;
433
+ this.extra = parsed.extra;
434
+ this.side = parsed.side;
435
+ this.name = parsed.name;
436
+ return this;
437
+ }
438
+ static fromYGOMobileDeckURL(uri) {
439
+ return new YGOProDeck().fromYGOMobileDeckURL(uri);
440
+ }
441
+ toYGOMobileDeckURL() {
442
+ return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {
443
+ name: this.name
444
+ });
445
+ }
446
+ fromYdkeURL(uri) {
447
+ const parsed = fromYdkeURL(uri);
448
+ this.main = parsed.main;
449
+ this.extra = parsed.extra;
450
+ this.side = parsed.side;
451
+ return this;
452
+ }
453
+ static fromYdkeURL(uri) {
454
+ return new YGOProDeck().fromYdkeURL(uri);
455
+ }
456
+ toYdkeURL() {
457
+ return toYdkeURL({
458
+ main: this.main,
459
+ extra: this.extra,
460
+ side: this.side
461
+ });
462
+ }
172
463
  };
173
464
  // Annotate the CommonJS export names for ESM import in node:
174
465
  0 && (module.exports = {});
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../index.ts", "../src/utils.ts"],
4
- "sourcesContent": ["import { BufferWriter, countItems } from './src/utils';\nimport { Base64 } from 'js-base64';\n\nexport default class YGOProDeck {\n main: number[] = [];\n extra: number[] = [];\n side: number[] = [];\n\n bufferLength() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n return counted.reduce((a, b) => a + b.size * 4, 0);\n }\n\n toUint8Array() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n const writer = new BufferWriter(\n counted.reduce((a, b) => a + b.size * 4, 0),\n );\n const writeCards = (countMap: Map<number, number>, type: number) => {\n // each card: 28 bits for id, 2 bits(0, 1, 2, 3) for type(0: main, 1: extra, 2: side, 3: unknown), 2 bits for count (0: 1, 1: 2, 2: 3, 3: 4)\n for (const [id, count] of countMap.entries()) {\n if (count > 4) {\n throw new Error(`Too many cards: ${id}`);\n }\n const value = (id & 0xfffffff) | (type << 28) | ((count - 1) << 30);\n writer.writeUint32LE(value);\n }\n };\n counted.forEach(writeCards);\n return writer.buffer;\n }\n\n toEncodedString() {\n return Base64.fromUint8Array(this.toUint8Array(), true);\n }\n\n toString() {\n return this.toEncodedString();\n }\n\n fromUint8Array(buf: Uint8Array) {\n for (let i = 0; i < buf.length - 3; i += 4) {\n const value =\n buf[i] | (buf[i + 1] << 8) | (buf[i + 2] << 16) | (buf[i + 3] << 24);\n const id = value & 0xfffffff;\n const type = (value >>> 28) & 0x3;\n const count = ((value >>> 30) & 0x3) + 1;\n const cards = [this.main, this.extra, this.side][type];\n for (let j = 0; j < count; j++) {\n cards.push(id);\n }\n }\n return this;\n }\n\n static fromUint8Array(buf: Uint8Array) {\n return new YGOProDeck().fromUint8Array(buf);\n }\n\n fromEncodedString(str: string) {\n return this.fromUint8Array(Base64.toUint8Array(str));\n }\n\n static fromEncodedString(str: string) {\n return new YGOProDeck().fromEncodedString(str);\n }\n\n toYdkString() {\n return [\n '#created by ygopro-deck-encode',\n '#main',\n ...this.main.map((id) => id.toString()),\n '#extra',\n ...this.extra.map((id) => id.toString()),\n '!side',\n ...this.side.map((id) => id.toString()),\n ].join('\\n');\n }\n\n fromYdkString(str: string) {\n const lines = str.split(/\\r?\\n/);\n let current = this.main;\n for (const _line of lines) {\n const line = _line.trim();\n if (line === '#main') {\n current = this.main;\n }\n if (line === '#extra') {\n current = this.extra;\n }\n if (line === '!side') {\n current = this.side;\n }\n if (line.match(/^\\d+$/)) {\n current.push(parseInt(line, 10));\n }\n }\n return this;\n }\n\n static fromYdkString(str: string) {\n return new YGOProDeck().fromYdkString(str);\n }\n\n toUpdateDeckPayload() {\n const cards = [...this.main, ...this.extra, ...this.side];\n const writer = new BufferWriter(cards.length * 4 + 8)\n .writeUint32LE(this.main.length + this.extra.length)\n .writeUint32LE(this.side.length);\n cards.forEach((id) => writer.writeUint32LE(id));\n return writer.buffer;\n }\n}\n", "export function countItems<T>(arr: T[]) {\n const map = new Map<T, number>();\n for (const item of arr) {\n map.set(item, (map.get(item) || 0) + 1);\n }\n return map;\n}\n\nexport class BufferWriter {\n buffer: Uint8Array;\n pointer = 0;\n constructor(length: number) {\n this.buffer = new Uint8Array(length);\n }\n writeUint32LE(value: number) {\n this.buffer[this.pointer++] = value & 0xff;\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n this.buffer[this.pointer++] = (value >>> 16) & 0xff;\n this.buffer[this.pointer++] = (value >>> 24) & 0xff;\n return this;\n }\n\n writeUint32BE(value: number) {\n this.buffer[this.pointer++] = (value >>> 24) & 0xff;\n this.buffer[this.pointer++] = (value >>> 16) & 0xff;\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n this.buffer[this.pointer++] = value & 0xff;\n return this;\n }\n\n writeUint16LE(value: number) {\n this.buffer[this.pointer++] = value & 0xff;\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n return this;\n }\n\n writeUint16BE(value: number) {\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n this.buffer[this.pointer++] = value & 0xff;\n return this;\n }\n\n writeUint8(value: number) {\n this.buffer[this.pointer++] = value & 0xff;\n return this;\n }\n\n writeString(str: string) {\n for (let i = 0; i < str.length; i++) {\n this.buffer[this.pointer++] = str.charCodeAt(i);\n }\n return this;\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,SAAS,WAAc,KAAU;AACtC,QAAM,MAAM,oBAAI,IAAe;AAC/B,aAAW,QAAQ,KAAK;AACtB,QAAI,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AAEO,IAAM,eAAN,MAAmB;AAAA,EAGxB,YAAY,QAAgB;AAD5B,mBAAU;AAER,SAAK,SAAS,IAAI,WAAW,MAAM;AAAA,EACrC;AAAA,EACA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,OAAe;AACxB,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,KAAa;AACvB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,WAAK,OAAO,KAAK,SAAS,IAAI,IAAI,WAAW,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AACF;;;ADpDA,uBAAuB;AAEvB,IAAqB,aAArB,MAAgC;AAAA,EAAhC;AACE,gBAAiB,CAAC;AAClB,iBAAkB,CAAC;AACnB,gBAAiB,CAAC;AAAA;AAAA,EAElB,eAAe;AACb,UAAM,UAAU,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI,UAAU;AACjE,WAAO,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,EACnD;AAAA,EAEA,eAAe;AACb,UAAM,UAAU,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI,UAAU;AACjE,UAAM,SAAS,IAAI;AAAA,MACjB,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,IAC5C;AACA,UAAM,aAAa,CAAC,UAA+B,SAAiB;AAElE,iBAAW,CAAC,IAAI,KAAK,KAAK,SAAS,QAAQ,GAAG;AAC5C,YAAI,QAAQ,GAAG;AACb,gBAAM,IAAI,MAAM,mBAAmB,IAAI;AAAA,QACzC;AACA,cAAM,QAAS,KAAK,YAAc,QAAQ,KAAQ,QAAQ,KAAM;AAChE,eAAO,cAAc,KAAK;AAAA,MAC5B;AAAA,IACF;AACA,YAAQ,QAAQ,UAAU;AAC1B,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,kBAAkB;AAChB,WAAO,wBAAO,eAAe,KAAK,aAAa,GAAG,IAAI;AAAA,EACxD;AAAA,EAEA,WAAW;AACT,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA,EAEA,eAAe,KAAiB;AAC9B,aAAS,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG;AAC1C,YAAM,QACJ,IAAI,CAAC,IAAK,IAAI,IAAI,CAAC,KAAK,IAAM,IAAI,IAAI,CAAC,KAAK,KAAO,IAAI,IAAI,CAAC,KAAK;AACnE,YAAM,KAAK,QAAQ;AACnB,YAAM,OAAQ,UAAU,KAAM;AAC9B,YAAM,SAAU,UAAU,KAAM,KAAO;AACvC,YAAM,QAAQ,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI;AACrD,eAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,cAAM,KAAK,EAAE;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,eAAe,KAAiB;AACrC,WAAO,IAAI,WAAW,EAAE,eAAe,GAAG;AAAA,EAC5C;AAAA,EAEA,kBAAkB,KAAa;AAC7B,WAAO,KAAK,eAAe,wBAAO,aAAa,GAAG,CAAC;AAAA,EACrD;AAAA,EAEA,OAAO,kBAAkB,KAAa;AACpC,WAAO,IAAI,WAAW,EAAE,kBAAkB,GAAG;AAAA,EAC/C;AAAA,EAEA,cAAc;AACZ,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,MACtC;AAAA,MACA,GAAG,KAAK,MAAM,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,MACvC;AAAA,MACA,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,IACxC,EAAE,KAAK,IAAI;AAAA,EACb;AAAA,EAEA,cAAc,KAAa;AACzB,UAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,QAAI,UAAU,KAAK;AACnB,eAAW,SAAS,OAAO;AACzB,YAAM,OAAO,MAAM,KAAK;AACxB,UAAI,SAAS,SAAS;AACpB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,SAAS,UAAU;AACrB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,SAAS,SAAS;AACpB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,KAAK,MAAM,OAAO,GAAG;AACvB,gBAAQ,KAAK,SAAS,MAAM,EAAE,CAAC;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,cAAc,KAAa;AAChC,WAAO,IAAI,WAAW,EAAE,cAAc,GAAG;AAAA,EAC3C;AAAA,EAEA,sBAAsB;AACpB,UAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,IAAI;AACxD,UAAM,SAAS,IAAI,aAAa,MAAM,SAAS,IAAI,CAAC,EACjD,cAAc,KAAK,KAAK,SAAS,KAAK,MAAM,MAAM,EAClD,cAAc,KAAK,KAAK,MAAM;AACjC,UAAM,QAAQ,CAAC,OAAO,OAAO,cAAc,EAAE,CAAC;AAC9C,WAAO,OAAO;AAAA,EAChB;AACF;",
3
+ "sources": ["../index.ts", "../src/base64.ts", "../src/utils.ts", "../src/ydke.ts", "../src/ygom.ts"],
4
+ "sourcesContent": ["import { fromBase64Url, toBase64Url } from './src/base64';\nimport { BufferReader, BufferWriter, countItems } from './src/utils';\nimport { fromYdkeURL, toYdkeURL } from './src/ydke';\nimport { fromYGOMobileDeckURL, toYGOMobileDeckURL } from './src/ygom';\n\nexport default class YGOProDeck {\n main: number[] = [];\n extra: number[] = [];\n side: number[] = [];\n name?: string;\n\n bufferLength() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n return counted.reduce((a, b) => a + b.size * 4, 0);\n }\n\n toUint8Array() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n const writer = new BufferWriter(\n counted.reduce((a, b) => a + b.size * 4, 0),\n );\n const writeCards = (countMap: Map<number, number>, type: number) => {\n // each card: 28 bits for id, 2 bits(0, 1, 2, 3) for type(0: main, 1: extra, 2: side, 3: unknown), 2 bits for count (0: 1, 1: 2, 2: 3, 3: 4)\n for (const [id, count] of countMap.entries()) {\n if (count > 4) {\n throw new Error(`Too many cards: ${id}`);\n }\n const value = (id & 0xfffffff) | (type << 28) | ((count - 1) << 30);\n writer.writeUint32LE(value);\n }\n };\n counted.forEach(writeCards);\n return writer.buffer;\n }\n\n toEncodedString() {\n return toBase64Url(this.toUint8Array());\n }\n\n toString() {\n return this.toEncodedString();\n }\n\n fromUint8Array(buf: Uint8Array) {\n for (let i = 0; i < buf.length - 3; i += 4) {\n const value =\n buf[i] | (buf[i + 1] << 8) | (buf[i + 2] << 16) | (buf[i + 3] << 24);\n const id = value & 0xfffffff;\n const type = (value >>> 28) & 0x3;\n const count = ((value >>> 30) & 0x3) + 1;\n const cards = [this.main, this.extra, this.side][type];\n for (let j = 0; j < count; j++) {\n cards.push(id);\n }\n }\n return this;\n }\n\n static fromUint8Array(buf: Uint8Array) {\n return new YGOProDeck().fromUint8Array(buf);\n }\n\n fromEncodedString(str: string) {\n return this.fromUint8Array(fromBase64Url(str));\n }\n\n static fromEncodedString(str: string) {\n return new YGOProDeck().fromEncodedString(str);\n }\n\n toYdkString() {\n return [\n '#created by ygopro-deck-encode',\n '#main',\n ...this.main.map((id) => id.toString()),\n '#extra',\n ...this.extra.map((id) => id.toString()),\n '!side',\n ...this.side.map((id) => id.toString()),\n ].join('\\n');\n }\n\n fromYdkString(str: string) {\n const lines = str.split(/\\r?\\n/);\n let current = this.main;\n for (const _line of lines) {\n const line = _line.trim();\n if (line === '#main') {\n current = this.main;\n }\n if (line === '#extra') {\n current = this.extra;\n }\n if (line === '!side') {\n current = this.side;\n }\n if (line.match(/^\\d+$/)) {\n current.push(parseInt(line, 10));\n }\n }\n return this;\n }\n\n static fromYdkString(str: string) {\n return new YGOProDeck().fromYdkString(str);\n }\n\n fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard: (code: number, i: number, mainc: number) => boolean = () => false) {\n const reader = new BufferReader(buf);\n const mainc = reader.readUint32LE();\n const sidec = reader.readUint32LE();\n this.main = [];\n this.extra = [];\n this.side = [];\n for(let i = 0; i < mainc; i++) {\n const id = reader.readUint32LE();\n if (isExtraDeckCard(id, i, mainc)) {\n this.extra.push(id);\n } else {\n this.main.push(id);\n }\n }\n for(let i = 0; i < sidec; i++) {\n const id = reader.readUint32LE();\n this.side.push(id);\n }\n return this;\n }\n\n static fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard: (code: number) => boolean = () => false) { \n return new YGOProDeck().fromUpdateDeckPayload(buf, isExtraDeckCard);\n }\n\n toUpdateDeckPayload() {\n const cards = [...this.main, ...this.extra, ...this.side];\n const writer = new BufferWriter(cards.length * 4 + 8)\n .writeUint32LE(this.main.length + this.extra.length)\n .writeUint32LE(this.side.length);\n cards.forEach((id) => writer.writeUint32LE(id));\n return writer.buffer;\n }\n\n fromYGOMobileDeckURL(uri: string): YGOProDeck {\n const parsed = fromYGOMobileDeckURL(uri);\n this.main = parsed.main;\n this.extra = parsed.extra;\n this.side = parsed.side;\n this.name = parsed.name;\n return this;\n }\n\n static fromYGOMobileDeckURL(uri: string): YGOProDeck {\n return new YGOProDeck().fromYGOMobileDeckURL(uri);\n }\n\n toYGOMobileDeckURL(): string {\n return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {\n name: this.name,\n });\n }\n\n fromYdkeURL(uri: string): YGOProDeck {\n const parsed = fromYdkeURL(uri);\n this.main = parsed.main;\n this.extra = parsed.extra;\n this.side = parsed.side;\n return this;\n }\n\n static fromYdkeURL(uri: string): YGOProDeck {\n return new YGOProDeck().fromYdkeURL(uri);\n }\n\n toYdkeURL(): string {\n return toYdkeURL({\n main: this.main,\n extra: this.extra,\n side: this.side,\n });\n }\n}\n", "export function toBase64Url(bytes: Uint8Array): string {\n const base64 = typeof Buffer !== 'undefined'\n ? Buffer.from(bytes).toString('base64')\n : btoa(String.fromCharCode(...bytes));\n\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nexport function fromBase64Url(encoded: string): Uint8Array {\n const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, '=');\n\n if (typeof Buffer !== 'undefined') {\n return Uint8Array.from(Buffer.from(padded, 'base64'));\n }\n\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n", "export function countItems<T>(arr: T[]) {\n const map = new Map<T, number>();\n for (const item of arr) {\n map.set(item, (map.get(item) || 0) + 1);\n }\n return map;\n}\nabstract class BufferCursor {\n buffer: Uint8Array;\n pointer = 0;\n\n constructor(bufOrLength: Uint8Array | number) {\n if (typeof bufOrLength === 'number') {\n this.buffer = new Uint8Array(bufOrLength);\n } else {\n this.buffer = bufOrLength;\n }\n }\n\n /**\n * \u5B89\u5168\u5730\u5C06 pointer \u5411\u524D\u79FB\u52A8\u6307\u5B9A\u5B57\u8282\u6570\u3002\n * @param bytes \u8981\u79FB\u52A8\u7684\u5B57\u8282\u6570\n * @returns \u539F\u6765 pointer \u7684\u503C\n * @throws RangeError \u5982\u679C\u8D8A\u754C\n */\n protected increasePointer(bytes: number): number {\n const old = this.pointer;\n const next = old + bytes;\n if (next > this.buffer.length) {\n throw new RangeError(\n `Pointer overflow: tried to move to ${next}, but buffer length is ${this.buffer.length}`\n );\n }\n this.pointer = next;\n return old;\n }\n}\n\nexport class BufferWriter extends BufferCursor {\n constructor(length: number) {\n super(length);\n }\n\n writeUint32LE(value: number) {\n const idx = this.increasePointer(4);\n this.buffer[idx ] = value & 0xff;\n this.buffer[idx + 1] = (value >>> 8) & 0xff;\n this.buffer[idx + 2] = (value >>> 16) & 0xff;\n this.buffer[idx + 3] = (value >>> 24) & 0xff;\n return this;\n }\n\n writeUint32BE(value: number) {\n const idx = this.increasePointer(4);\n this.buffer[idx ] = (value >>> 24) & 0xff;\n this.buffer[idx + 1] = (value >>> 16) & 0xff;\n this.buffer[idx + 2] = (value >>> 8) & 0xff;\n this.buffer[idx + 3] = value & 0xff;\n return this;\n }\n\n writeUint16LE(value: number) {\n const idx = this.increasePointer(2);\n this.buffer[idx ] = value & 0xff;\n this.buffer[idx + 1] = (value >>> 8) & 0xff;\n return this;\n }\n\n writeUint16BE(value: number) {\n const idx = this.increasePointer(2);\n this.buffer[idx ] = (value >>> 8) & 0xff;\n this.buffer[idx + 1] = value & 0xff;\n return this;\n }\n\n writeUint8(value: number) {\n const idx = this.increasePointer(1);\n this.buffer[idx] = value & 0xff;\n return this;\n }\n\n writeString(str: string) {\n for (let i = 0; i < str.length; i++) {\n const idx = this.increasePointer(1);\n this.buffer[idx] = str.charCodeAt(i);\n }\n return this;\n }\n}\n\nexport class BufferReader extends BufferCursor {\n constructor(buf: Uint8Array) {\n super(buf);\n }\n\n readUint32LE(): number {\n const idx = this.increasePointer(4);\n const b = this.buffer;\n // >>>0 \u4FDD\u8BC1\u65E0\u7B26\u53F7\u8F93\u51FA\n return (\n (b[idx ] ) |\n (b[idx + 1] << 8) |\n (b[idx + 2] << 16) |\n (b[idx + 3] << 24)\n ) >>> 0;\n }\n\n readUint32BE(): number {\n const idx = this.increasePointer(4);\n const b = this.buffer;\n return (\n (b[idx ] << 24) |\n (b[idx + 1] << 16) |\n (b[idx + 2] << 8) |\n (b[idx + 3] )\n ) >>> 0;\n }\n\n readUint16LE(): number {\n const idx = this.increasePointer(2);\n const b = this.buffer;\n return (b[idx] | (b[idx + 1] << 8));\n }\n\n readUint16BE(): number {\n const idx = this.increasePointer(2);\n const b = this.buffer;\n return ((b[idx] << 8) | b[idx + 1]);\n }\n\n readUint8(): number {\n const idx = this.increasePointer(1);\n return this.buffer[idx];\n }\n\n readString(length: number): string {\n let s = '';\n for (let i = 0; i < length; i++) {\n const idx = this.increasePointer(1);\n s += String.fromCharCode(this.buffer[idx]);\n }\n return s;\n }\n\n readRemaining(): Uint8Array {\n const remaining = this.buffer.length - this.pointer;\n const idx = this.increasePointer(remaining);\n return this.buffer.subarray(idx, this.buffer.length);\n }\n}\n", "// ydke.ts\n\nexport interface TypedDeck {\n main: number[];\n extra: number[];\n side: number[];\n}\n\nfunction base64ToUint32Array(base64: string): number[] {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n const view = new DataView(bytes.buffer);\n const result: number[] = [];\n for (let i = 0; i < bytes.length; i += 4) {\n result.push(view.getUint32(i, true)); // little-endian\n }\n return result;\n}\n\nfunction uint32ArrayToBase64(data: number[]): string {\n const buffer = new ArrayBuffer(data.length * 4);\n const view = new DataView(buffer);\n data.forEach((val, i) => view.setUint32(i * 4, val, true));\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nexport function toYdkeURL(deck: TypedDeck): string {\n return (\n 'ydke://' +\n uint32ArrayToBase64(deck.main) +\n '!' +\n uint32ArrayToBase64(deck.extra) +\n '!' +\n uint32ArrayToBase64(deck.side) +\n '!'\n );\n}\n\nexport function fromYdkeURL(ydke: string): TypedDeck {\n if (!ydke.startsWith('ydke://')) {\n throw new Error('Invalid ydke:// URI');\n }\n const [mainStr, extraStr, sideStr] = ydke.slice(7).split('!');\n if (mainStr === undefined || extraStr === undefined || sideStr === undefined) {\n throw new Error('Incomplete ydke:// URI');\n }\n return {\n main: base64ToUint32Array(mainStr),\n extra: base64ToUint32Array(extraStr),\n side: base64ToUint32Array(sideStr),\n };\n}\n", "import { fromBase64Url, toBase64Url } from \"./base64\";\n\n// === \u5E38\u91CF\u533A\u57DF ===\nconst QUERY_YGO_TYPE = 'ygotype';\nconst QUERY_VERSION = 'v';\nconst ARG_DECK = 'deck';\nconst QUERY_DECK = 'd';\nconst QUERY_NAME = 'name';\n\nconst URL_SCHEME_HTTP = 'http';\nconst URL_HOST_DECK = 'deck.ourygo.top';\n\n// === \u5DE5\u5177\u51FD\u6570 ===\nfunction toBinary(value: number, length: number): string {\n return value.toString(2).padStart(length, '0');\n}\n\nfunction encodeCards(cards: number[]): string {\n const bits: string[] = [];\n for (let i = 0; i < cards.length; ) {\n const id = cards[i];\n let count = 1;\n while (i + count < cards.length && cards[i + count] === id && count < 3) count++;\n const prefix = count === 2 ? '10' : count === 3 ? '11' : '01';\n bits.push(prefix + toBinary(id, 27));\n i += count;\n }\n return bits.join('');\n}\n\nfunction countUnique(cards: number[]): number {\n let num = 0;\n for (let i = 0; i < cards.length; i++) {\n const id = cards[i];\n if (id > 0) {\n num++;\n if (i < cards.length - 1 && cards[i + 1] === id) {\n i++;\n if (i < cards.length - 1 && cards[i + 1] === id) {\n i++;\n }\n }\n }\n }\n return num;\n}\n\n// === \u4E3B\u51FD\u6570 ===\n\nexport function toYGOMobileDeckURL(\n main: number[],\n extra: number[],\n side: number[],\n customParams: Record<string, string> = {},\n): string {\n const mNum = countUnique(main);\n const eNum = countUnique(extra);\n const sNum = countUnique(side);\n\n const header = toBinary(mNum, 8) + toBinary(eNum, 4) + toBinary(sNum, 4);\n let bitString = header + encodeCards(main) + encodeCards(extra) + encodeCards(side);\n while (bitString.length % 8 !== 0) bitString += '0';\n\n const bytes = new Uint8Array(bitString.length / 8);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(bitString.slice(i * 8, i * 8 + 8), 2);\n }\n\n let encoded = toBase64Url(bytes)\n\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(customParams)) {\n searchParams.set(key, value);\n }\n searchParams.set(QUERY_YGO_TYPE, ARG_DECK);\n searchParams.set(QUERY_VERSION, '1');\n searchParams.set(QUERY_DECK, encoded);\n\n return `${URL_SCHEME_HTTP}://${URL_HOST_DECK}?${searchParams.toString()}`;\n}\n\n\nexport function fromYGOMobileDeckURL(uri: string): {\n main: number[];\n extra: number[];\n side: number[];\n name?: string;\n} {\n const url = new URL(uri);\n if (url.searchParams.get(QUERY_YGO_TYPE) !== ARG_DECK) {\n throw new Error('Not a YGO Mobile deck URI');\n }\n\n let encoded = url.searchParams.get(QUERY_DECK);\n if (!encoded) throw new Error('Missing deck data');\n\n const bytes = fromBase64Url(encoded);\n\n const bits = Array.from(bytes)\n .map((b) => b.toString(2).padStart(8, '0'))\n .join('');\n\n const mNum = parseInt(bits.slice(0, 8), 2);\n const eNum = parseInt(bits.slice(8, 12), 2);\n const sNum = parseInt(bits.slice(12, 16), 2);\n\n const all = mNum + eNum + sNum;\n const cards: number[] = [];\n let pos = 16;\n \n const res = {\n main: [] as number[],\n extra: [] as number[],\n side: [] as number[],\n }\n\n let i = 0;\n\n while (pos + 29 <= bits.length && cards.length < all) {\n const countBits = bits.slice(pos, pos + 2);\n const count = countBits === '10' ? 2 : countBits === '11' ? 3 : 1;\n const id = parseInt(bits.slice(pos + 2, pos + 29), 2);\n const field = i < mNum ? 'main' : i < mNum + eNum ? 'extra' : 'side';\n res[field].push(...Array(count).fill(id));\n pos += 29;\n i++;\n }\n\n return {\n ...res,\n name: url.searchParams.get(QUERY_NAME),\n };\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,SAAS,YAAY,OAA2B;AACrD,QAAM,SAAS,OAAO,WAAW,cAC7B,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ,IACpC,KAAK,OAAO,aAAa,GAAG,KAAK,CAAC;AAEtC,SAAO,OAAO,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AACzE;AAEO,SAAS,cAAc,SAA6B;AACzD,QAAM,SAAS,QAAQ,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAC3D,QAAM,SAAS,OAAO,OAAO,OAAO,UAAU,IAAI,OAAO,SAAS,KAAK,GAAG,GAAG;AAE7E,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,WAAW,KAAK,OAAO,KAAK,QAAQ,QAAQ,CAAC;AAAA,EACtD;AAEA,QAAM,SAAS,KAAK,MAAM;AAC1B,QAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EAChC;AACA,SAAO;AACT;;;ACtBO,SAAS,WAAc,KAAU;AACtC,QAAM,MAAM,oBAAI,IAAe;AAC/B,aAAW,QAAQ,KAAK;AACtB,QAAI,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AACA,IAAe,eAAf,MAA4B;AAAA,EAI1B,YAAY,aAAkC;AAF9C,mBAAU;AAGR,QAAI,OAAO,gBAAgB,UAAU;AACnC,WAAK,SAAS,IAAI,WAAW,WAAW;AAAA,IAC1C,OAAO;AACL,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,gBAAgB,OAAuB;AAC/C,UAAM,MAAM,KAAK;AACjB,UAAM,OAAO,MAAM;AACnB,QAAI,OAAO,KAAK,OAAO,QAAQ;AAC7B,YAAM,IAAI;AAAA,QACR,sCAAsC,8BAA8B,KAAK,OAAO;AAAA,MAClF;AAAA,IACF;AACA,SAAK,UAAU;AACf,WAAO;AAAA,EACT;AACF;AAEO,IAAM,eAAN,cAA2B,aAAa;AAAA,EAC7C,YAAY,QAAgB;AAC1B,UAAM,MAAM;AAAA,EACd;AAAA,EAEA,cAAc,OAAe;AAC3B,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,SAAK,OAAO,GAAO,IAAK,QAAgB;AACxC,SAAK,OAAO,MAAM,CAAC,IAAK,UAAU,IAAM;AACxC,SAAK,OAAO,MAAM,CAAC,IAAK,UAAU,KAAM;AACxC,SAAK,OAAO,MAAM,CAAC,IAAK,UAAU,KAAM;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,SAAK,OAAO,GAAO,IAAK,UAAU,KAAM;AACxC,SAAK,OAAO,MAAM,CAAC,IAAK,UAAU,KAAM;AACxC,SAAK,OAAO,MAAM,CAAC,IAAK,UAAU,IAAM;AACxC,SAAK,OAAO,MAAM,CAAC,IAAK,QAAgB;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,SAAK,OAAO,GAAO,IAAK,QAAe;AACvC,SAAK,OAAO,MAAM,CAAC,IAAK,UAAU,IAAK;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,SAAK,OAAO,GAAO,IAAK,UAAU,IAAK;AACvC,SAAK,OAAO,MAAM,CAAC,IAAK,QAAe;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,OAAe;AACxB,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,SAAK,OAAO,GAAG,IAAI,QAAQ;AAC3B,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,KAAa;AACvB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,WAAK,OAAO,GAAG,IAAI,IAAI,WAAW,CAAC;AAAA,IACrC;AACA,WAAO;AAAA,EACT;AACF;AAEO,IAAM,eAAN,cAA2B,aAAa;AAAA,EAC7C,YAAY,KAAiB;AAC3B,UAAM,GAAG;AAAA,EACX;AAAA,EAEA,eAAuB;AACrB,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,UAAM,IAAI,KAAK;AAEf,YACG,EAAE,GAAO,IACT,EAAE,MAAM,CAAC,KAAM,IACf,EAAE,MAAM,CAAC,KAAK,KACd,EAAE,MAAM,CAAC,KAAK,QACX;AAAA,EACR;AAAA,EAEA,eAAuB;AACrB,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,UAAM,IAAI,KAAK;AACf,YACG,EAAE,GAAO,KAAK,KACd,EAAE,MAAM,CAAC,KAAK,KACd,EAAE,MAAM,CAAC,KAAM,IACf,EAAE,MAAM,CAAC,OACN;AAAA,EACR;AAAA,EAEA,eAAuB;AACrB,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,UAAM,IAAI,KAAK;AACf,WAAQ,EAAE,GAAG,IAAK,EAAE,MAAM,CAAC,KAAK;AAAA,EAClC;AAAA,EAEA,eAAuB;AACrB,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,UAAM,IAAI,KAAK;AACf,WAAS,EAAE,GAAG,KAAK,IAAK,EAAE,MAAM,CAAC;AAAA,EACnC;AAAA,EAEA,YAAoB;AAClB,UAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,WAAO,KAAK,OAAO,GAAG;AAAA,EACxB;AAAA,EAEA,WAAW,QAAwB;AACjC,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,YAAM,MAAM,KAAK,gBAAgB,CAAC;AAClC,WAAK,OAAO,aAAa,KAAK,OAAO,GAAG,CAAC;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,gBAA4B;AAC1B,UAAM,YAAY,KAAK,OAAO,SAAS,KAAK;AAC5C,UAAM,MAAM,KAAK,gBAAgB,SAAS;AAC1C,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK,OAAO,MAAM;AAAA,EACrD;AACF;;;AC7IA,SAAS,oBAAoB,QAA0B;AACrD,QAAM,SAAS,KAAK,MAAM;AAC1B,QAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EAChC;AACA,QAAM,OAAO,IAAI,SAAS,MAAM,MAAM;AACtC,QAAM,SAAmB,CAAC;AAC1B,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,WAAO,KAAK,KAAK,UAAU,GAAG,IAAI,CAAC;AAAA,EACrC;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,MAAwB;AACnD,QAAM,SAAS,IAAI,YAAY,KAAK,SAAS,CAAC;AAC9C,QAAM,OAAO,IAAI,SAAS,MAAM;AAChC,OAAK,QAAQ,CAAC,KAAK,MAAM,KAAK,UAAU,IAAI,GAAG,KAAK,IAAI,CAAC;AACzD,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAAA,EACxC;AACA,SAAO,KAAK,MAAM;AACpB;AAEO,SAAS,UAAU,MAAyB;AACjD,SACE,YACA,oBAAoB,KAAK,IAAI,IAC7B,MACA,oBAAoB,KAAK,KAAK,IAC9B,MACA,oBAAoB,KAAK,IAAI,IAC7B;AAEJ;AAEO,SAAS,YAAY,MAAyB;AACnD,MAAI,CAAC,KAAK,WAAW,SAAS,GAAG;AAC/B,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AACA,QAAM,CAAC,SAAS,UAAU,OAAO,IAAI,KAAK,MAAM,CAAC,EAAE,MAAM,GAAG;AAC5D,MAAI,YAAY,UAAa,aAAa,UAAa,YAAY,QAAW;AAC5E,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC1C;AACA,SAAO;AAAA,IACL,MAAM,oBAAoB,OAAO;AAAA,IACjC,OAAO,oBAAoB,QAAQ;AAAA,IACnC,MAAM,oBAAoB,OAAO;AAAA,EACnC;AACF;;;ACxDA,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AACtB,IAAM,WAAW;AACjB,IAAM,aAAa;AACnB,IAAM,aAAa;AAEnB,IAAM,kBAAkB;AACxB,IAAM,gBAAgB;AAGtB,SAAS,SAAS,OAAe,QAAwB;AACvD,SAAO,MAAM,SAAS,CAAC,EAAE,SAAS,QAAQ,GAAG;AAC/C;AAEA,SAAS,YAAY,OAAyB;AAC5C,QAAM,OAAiB,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,MAAM,UAAU;AAClC,UAAM,KAAK,MAAM,CAAC;AAClB,QAAI,QAAQ;AACZ,WAAO,IAAI,QAAQ,MAAM,UAAU,MAAM,IAAI,KAAK,MAAM,MAAM,QAAQ;AAAG;AACzE,UAAM,SAAS,UAAU,IAAI,OAAO,UAAU,IAAI,OAAO;AACzD,SAAK,KAAK,SAAS,SAAS,IAAI,EAAE,CAAC;AACnC,SAAK;AAAA,EACP;AACA,SAAO,KAAK,KAAK,EAAE;AACrB;AAEA,SAAS,YAAY,OAAyB;AAC5C,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,KAAK,MAAM,CAAC;AAClB,QAAI,KAAK,GAAG;AACV;AACA,UAAI,IAAI,MAAM,SAAS,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI;AAC/C;AACA,YAAI,IAAI,MAAM,SAAS,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI;AAC/C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAIO,SAAS,mBACd,MACA,OACA,MACA,eAAuC,CAAC,GAChC;AACR,QAAM,OAAO,YAAY,IAAI;AAC7B,QAAM,OAAO,YAAY,KAAK;AAC9B,QAAM,OAAO,YAAY,IAAI;AAE7B,QAAM,SAAS,SAAS,MAAM,CAAC,IAAI,SAAS,MAAM,CAAC,IAAI,SAAS,MAAM,CAAC;AACvE,MAAI,YAAY,SAAS,YAAY,IAAI,IAAI,YAAY,KAAK,IAAI,YAAY,IAAI;AAClF,SAAO,UAAU,SAAS,MAAM;AAAG,iBAAa;AAEhD,QAAM,QAAQ,IAAI,WAAW,UAAU,SAAS,CAAC;AACjD,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,CAAC,IAAI,SAAS,UAAU,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;AAAA,EAC1D;AAEA,MAAI,UAAU,YAAY,KAAK;AAE/B,QAAM,eAAe,IAAI,gBAAgB;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,iBAAa,IAAI,KAAK,KAAK;AAAA,EAC7B;AACA,eAAa,IAAI,gBAAgB,QAAQ;AACzC,eAAa,IAAI,eAAe,GAAG;AACnC,eAAa,IAAI,YAAY,OAAO;AAEpC,SAAO,GAAG,qBAAqB,iBAAiB,aAAa,SAAS;AACxE;AAGO,SAAS,qBAAqB,KAKnC;AACA,QAAM,MAAM,IAAI,IAAI,GAAG;AACvB,MAAI,IAAI,aAAa,IAAI,cAAc,MAAM,UAAU;AACrD,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC7C;AAEA,MAAI,UAAU,IAAI,aAAa,IAAI,UAAU;AAC7C,MAAI,CAAC;AAAS,UAAM,IAAI,MAAM,mBAAmB;AAEjD,QAAM,QAAQ,cAAc,OAAO;AAEnC,QAAM,OAAO,MAAM,KAAK,KAAK,EAC1B,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC,EACzC,KAAK,EAAE;AAEV,QAAM,OAAO,SAAS,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC;AACzC,QAAM,OAAO,SAAS,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC;AAC1C,QAAM,OAAO,SAAS,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC;AAE3C,QAAM,MAAM,OAAO,OAAO;AAC1B,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM;AAEV,QAAM,MAAM;AAAA,IACV,MAAM,CAAC;AAAA,IACP,OAAO,CAAC;AAAA,IACR,MAAM,CAAC;AAAA,EACT;AAEA,MAAI,IAAI;AAER,SAAO,MAAM,MAAM,KAAK,UAAU,MAAM,SAAS,KAAK;AACpD,UAAM,YAAY,KAAK,MAAM,KAAK,MAAM,CAAC;AACzC,UAAM,QAAQ,cAAc,OAAO,IAAI,cAAc,OAAO,IAAI;AAChE,UAAM,KAAK,SAAS,KAAK,MAAM,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC;AACpD,UAAM,QAAQ,IAAI,OAAO,SAAS,IAAI,OAAO,OAAO,UAAU;AAC9D,QAAI,KAAK,EAAE,KAAK,GAAG,MAAM,KAAK,EAAE,KAAK,EAAE,CAAC;AACxC,WAAO;AACP;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,IAAI,aAAa,IAAI,UAAU;AAAA,EACvC;AACF;;;AJ/HA,IAAqB,aAArB,MAAgC;AAAA,EAAhC;AACE,gBAAiB,CAAC;AAClB,iBAAkB,CAAC;AACnB,gBAAiB,CAAC;AAAA;AAAA,EAGlB,eAAe;AACb,UAAM,UAAU,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI,UAAU;AACjE,WAAO,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,EACnD;AAAA,EAEA,eAAe;AACb,UAAM,UAAU,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI,UAAU;AACjE,UAAM,SAAS,IAAI;AAAA,MACjB,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,IAC5C;AACA,UAAM,aAAa,CAAC,UAA+B,SAAiB;AAElE,iBAAW,CAAC,IAAI,KAAK,KAAK,SAAS,QAAQ,GAAG;AAC5C,YAAI,QAAQ,GAAG;AACb,gBAAM,IAAI,MAAM,mBAAmB,IAAI;AAAA,QACzC;AACA,cAAM,QAAS,KAAK,YAAc,QAAQ,KAAQ,QAAQ,KAAM;AAChE,eAAO,cAAc,KAAK;AAAA,MAC5B;AAAA,IACF;AACA,YAAQ,QAAQ,UAAU;AAC1B,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,kBAAkB;AAChB,WAAO,YAAY,KAAK,aAAa,CAAC;AAAA,EACxC;AAAA,EAEA,WAAW;AACT,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA,EAEA,eAAe,KAAiB;AAC9B,aAAS,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG;AAC1C,YAAM,QACJ,IAAI,CAAC,IAAK,IAAI,IAAI,CAAC,KAAK,IAAM,IAAI,IAAI,CAAC,KAAK,KAAO,IAAI,IAAI,CAAC,KAAK;AACnE,YAAM,KAAK,QAAQ;AACnB,YAAM,OAAQ,UAAU,KAAM;AAC9B,YAAM,SAAU,UAAU,KAAM,KAAO;AACvC,YAAM,QAAQ,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI;AACrD,eAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,cAAM,KAAK,EAAE;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,eAAe,KAAiB;AACrC,WAAO,IAAI,WAAW,EAAE,eAAe,GAAG;AAAA,EAC5C;AAAA,EAEA,kBAAkB,KAAa;AAC7B,WAAO,KAAK,eAAe,cAAc,GAAG,CAAC;AAAA,EAC/C;AAAA,EAEA,OAAO,kBAAkB,KAAa;AACpC,WAAO,IAAI,WAAW,EAAE,kBAAkB,GAAG;AAAA,EAC/C;AAAA,EAEA,cAAc;AACZ,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,MACtC;AAAA,MACA,GAAG,KAAK,MAAM,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,MACvC;AAAA,MACA,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,IACxC,EAAE,KAAK,IAAI;AAAA,EACb;AAAA,EAEA,cAAc,KAAa;AACzB,UAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,QAAI,UAAU,KAAK;AACnB,eAAW,SAAS,OAAO;AACzB,YAAM,OAAO,MAAM,KAAK;AACxB,UAAI,SAAS,SAAS;AACpB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,SAAS,UAAU;AACrB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,SAAS,SAAS;AACpB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,KAAK,MAAM,OAAO,GAAG;AACvB,gBAAQ,KAAK,SAAS,MAAM,EAAE,CAAC;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,cAAc,KAAa;AAChC,WAAO,IAAI,WAAW,EAAE,cAAc,GAAG;AAAA,EAC3C;AAAA,EAEA,sBAAsB,KAAiB,kBAAuE,MAAM,OAAO;AACzH,UAAM,SAAS,IAAI,aAAa,GAAG;AACnC,UAAM,QAAQ,OAAO,aAAa;AAClC,UAAM,QAAQ,OAAO,aAAa;AAClC,SAAK,OAAO,CAAC;AACb,SAAK,QAAQ,CAAC;AACd,SAAK,OAAO,CAAC;AACb,aAAQ,IAAI,GAAG,IAAI,OAAO,KAAK;AAC7B,YAAM,KAAK,OAAO,aAAa;AAC/B,UAAI,gBAAgB,IAAI,GAAG,KAAK,GAAG;AACjC,aAAK,MAAM,KAAK,EAAE;AAAA,MACpB,OAAO;AACL,aAAK,KAAK,KAAK,EAAE;AAAA,MACnB;AAAA,IACF;AACA,aAAQ,IAAI,GAAG,IAAI,OAAO,KAAK;AAC7B,YAAM,KAAK,OAAO,aAAa;AAC/B,WAAK,KAAK,KAAK,EAAE;AAAA,IACnB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,sBAAsB,KAAiB,kBAA6C,MAAM,OAAO;AACtG,WAAO,IAAI,WAAW,EAAE,sBAAsB,KAAK,eAAe;AAAA,EACpE;AAAA,EAEA,sBAAsB;AACpB,UAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,IAAI;AACxD,UAAM,SAAS,IAAI,aAAa,MAAM,SAAS,IAAI,CAAC,EACjD,cAAc,KAAK,KAAK,SAAS,KAAK,MAAM,MAAM,EAClD,cAAc,KAAK,KAAK,MAAM;AACjC,UAAM,QAAQ,CAAC,OAAO,OAAO,cAAc,EAAE,CAAC;AAC9C,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,qBAAqB,KAAyB;AAC5C,UAAM,SAAS,qBAAqB,GAAG;AACvC,SAAK,OAAO,OAAO;AACnB,SAAK,QAAQ,OAAO;AACpB,SAAK,OAAO,OAAO;AACnB,SAAK,OAAO,OAAO;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,qBAAqB,KAAyB;AACnD,WAAO,IAAI,WAAW,EAAE,qBAAqB,GAAG;AAAA,EAClD;AAAA,EAEA,qBAA6B;AAC3B,WAAO,mBAAmB,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,MACvE,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,KAAyB;AACnC,UAAM,SAAS,YAAY,GAAG;AAC9B,SAAK,OAAO,OAAO;AACnB,SAAK,QAAQ,OAAO;AACpB,SAAK,OAAO,OAAO;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,YAAY,KAAyB;AAC1C,WAAO,IAAI,WAAW,EAAE,YAAY,GAAG;AAAA,EACzC;AAAA,EAEA,YAAoB;AAClB,WAAO,UAAU;AAAA,MACf,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AACF;",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export default class YGOProDeck {
2
2
  main: number[];
3
3
  extra: number[];
4
4
  side: number[];
5
+ name?: string;
5
6
  bufferLength(): number;
6
7
  toUint8Array(): Uint8Array;
7
8
  toEncodedString(): string;
@@ -13,5 +14,13 @@ export default class YGOProDeck {
13
14
  toYdkString(): string;
14
15
  fromYdkString(str: string): this;
15
16
  static fromYdkString(str: string): YGOProDeck;
17
+ fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard?: (code: number, i: number, mainc: number) => boolean): this;
18
+ static fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard?: (code: number) => boolean): YGOProDeck;
16
19
  toUpdateDeckPayload(): Uint8Array;
20
+ fromYGOMobileDeckURL(uri: string): YGOProDeck;
21
+ static fromYGOMobileDeckURL(uri: string): YGOProDeck;
22
+ toYGOMobileDeckURL(): string;
23
+ fromYdkeURL(uri: string): YGOProDeck;
24
+ static fromYdkeURL(uri: string): YGOProDeck;
25
+ toYdkeURL(): string;
17
26
  }
package/dist/index.mjs CHANGED
@@ -1,3 +1,22 @@
1
+ // src/base64.ts
2
+ function toBase64Url(bytes) {
3
+ const base64 = typeof Buffer !== "undefined" ? Buffer.from(bytes).toString("base64") : btoa(String.fromCharCode(...bytes));
4
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
5
+ }
6
+ function fromBase64Url(encoded) {
7
+ const base64 = encoded.replace(/-/g, "+").replace(/_/g, "/");
8
+ const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
9
+ if (typeof Buffer !== "undefined") {
10
+ return Uint8Array.from(Buffer.from(padded, "base64"));
11
+ }
12
+ const binary = atob(padded);
13
+ const bytes = new Uint8Array(binary.length);
14
+ for (let i = 0; i < binary.length; i++) {
15
+ bytes[i] = binary.charCodeAt(i);
16
+ }
17
+ return bytes;
18
+ }
19
+
1
20
  // src/utils.ts
2
21
  function countItems(arr) {
3
22
  const map = /* @__PURE__ */ new Map();
@@ -6,54 +25,270 @@ function countItems(arr) {
6
25
  }
7
26
  return map;
8
27
  }
9
- var BufferWriter = class {
28
+ var BufferCursor = class {
10
29
  buffer;
11
30
  pointer = 0;
31
+ constructor(bufOrLength) {
32
+ if (typeof bufOrLength === "number") {
33
+ this.buffer = new Uint8Array(bufOrLength);
34
+ } else {
35
+ this.buffer = bufOrLength;
36
+ }
37
+ }
38
+ /**
39
+ * 安全地将 pointer 向前移动指定字节数。
40
+ * @param bytes 要移动的字节数
41
+ * @returns 原来 pointer 的值
42
+ * @throws RangeError 如果越界
43
+ */
44
+ increasePointer(bytes) {
45
+ const old = this.pointer;
46
+ const next = old + bytes;
47
+ if (next > this.buffer.length) {
48
+ throw new RangeError(
49
+ `Pointer overflow: tried to move to ${next}, but buffer length is ${this.buffer.length}`
50
+ );
51
+ }
52
+ this.pointer = next;
53
+ return old;
54
+ }
55
+ };
56
+ var BufferWriter = class extends BufferCursor {
12
57
  constructor(length) {
13
- this.buffer = new Uint8Array(length);
58
+ super(length);
14
59
  }
15
60
  writeUint32LE(value) {
16
- this.buffer[this.pointer++] = value & 255;
17
- this.buffer[this.pointer++] = value >>> 8 & 255;
18
- this.buffer[this.pointer++] = value >>> 16 & 255;
19
- this.buffer[this.pointer++] = value >>> 24 & 255;
61
+ const idx = this.increasePointer(4);
62
+ this.buffer[idx] = value & 255;
63
+ this.buffer[idx + 1] = value >>> 8 & 255;
64
+ this.buffer[idx + 2] = value >>> 16 & 255;
65
+ this.buffer[idx + 3] = value >>> 24 & 255;
20
66
  return this;
21
67
  }
22
68
  writeUint32BE(value) {
23
- this.buffer[this.pointer++] = value >>> 24 & 255;
24
- this.buffer[this.pointer++] = value >>> 16 & 255;
25
- this.buffer[this.pointer++] = value >>> 8 & 255;
26
- this.buffer[this.pointer++] = value & 255;
69
+ const idx = this.increasePointer(4);
70
+ this.buffer[idx] = value >>> 24 & 255;
71
+ this.buffer[idx + 1] = value >>> 16 & 255;
72
+ this.buffer[idx + 2] = value >>> 8 & 255;
73
+ this.buffer[idx + 3] = value & 255;
27
74
  return this;
28
75
  }
29
76
  writeUint16LE(value) {
30
- this.buffer[this.pointer++] = value & 255;
31
- this.buffer[this.pointer++] = value >>> 8 & 255;
77
+ const idx = this.increasePointer(2);
78
+ this.buffer[idx] = value & 255;
79
+ this.buffer[idx + 1] = value >>> 8 & 255;
32
80
  return this;
33
81
  }
34
82
  writeUint16BE(value) {
35
- this.buffer[this.pointer++] = value >>> 8 & 255;
36
- this.buffer[this.pointer++] = value & 255;
83
+ const idx = this.increasePointer(2);
84
+ this.buffer[idx] = value >>> 8 & 255;
85
+ this.buffer[idx + 1] = value & 255;
37
86
  return this;
38
87
  }
39
88
  writeUint8(value) {
40
- this.buffer[this.pointer++] = value & 255;
89
+ const idx = this.increasePointer(1);
90
+ this.buffer[idx] = value & 255;
41
91
  return this;
42
92
  }
43
93
  writeString(str) {
44
94
  for (let i = 0; i < str.length; i++) {
45
- this.buffer[this.pointer++] = str.charCodeAt(i);
95
+ const idx = this.increasePointer(1);
96
+ this.buffer[idx] = str.charCodeAt(i);
46
97
  }
47
98
  return this;
48
99
  }
49
100
  };
101
+ var BufferReader = class extends BufferCursor {
102
+ constructor(buf) {
103
+ super(buf);
104
+ }
105
+ readUint32LE() {
106
+ const idx = this.increasePointer(4);
107
+ const b = this.buffer;
108
+ return (b[idx] | b[idx + 1] << 8 | b[idx + 2] << 16 | b[idx + 3] << 24) >>> 0;
109
+ }
110
+ readUint32BE() {
111
+ const idx = this.increasePointer(4);
112
+ const b = this.buffer;
113
+ return (b[idx] << 24 | b[idx + 1] << 16 | b[idx + 2] << 8 | b[idx + 3]) >>> 0;
114
+ }
115
+ readUint16LE() {
116
+ const idx = this.increasePointer(2);
117
+ const b = this.buffer;
118
+ return b[idx] | b[idx + 1] << 8;
119
+ }
120
+ readUint16BE() {
121
+ const idx = this.increasePointer(2);
122
+ const b = this.buffer;
123
+ return b[idx] << 8 | b[idx + 1];
124
+ }
125
+ readUint8() {
126
+ const idx = this.increasePointer(1);
127
+ return this.buffer[idx];
128
+ }
129
+ readString(length) {
130
+ let s = "";
131
+ for (let i = 0; i < length; i++) {
132
+ const idx = this.increasePointer(1);
133
+ s += String.fromCharCode(this.buffer[idx]);
134
+ }
135
+ return s;
136
+ }
137
+ readRemaining() {
138
+ const remaining = this.buffer.length - this.pointer;
139
+ const idx = this.increasePointer(remaining);
140
+ return this.buffer.subarray(idx, this.buffer.length);
141
+ }
142
+ };
143
+
144
+ // src/ydke.ts
145
+ function base64ToUint32Array(base64) {
146
+ const binary = atob(base64);
147
+ const bytes = new Uint8Array(binary.length);
148
+ for (let i = 0; i < binary.length; i++) {
149
+ bytes[i] = binary.charCodeAt(i);
150
+ }
151
+ const view = new DataView(bytes.buffer);
152
+ const result = [];
153
+ for (let i = 0; i < bytes.length; i += 4) {
154
+ result.push(view.getUint32(i, true));
155
+ }
156
+ return result;
157
+ }
158
+ function uint32ArrayToBase64(data) {
159
+ const buffer = new ArrayBuffer(data.length * 4);
160
+ const view = new DataView(buffer);
161
+ data.forEach((val, i) => view.setUint32(i * 4, val, true));
162
+ const bytes = new Uint8Array(buffer);
163
+ let binary = "";
164
+ for (let i = 0; i < bytes.length; i++) {
165
+ binary += String.fromCharCode(bytes[i]);
166
+ }
167
+ return btoa(binary);
168
+ }
169
+ function toYdkeURL(deck) {
170
+ return "ydke://" + uint32ArrayToBase64(deck.main) + "!" + uint32ArrayToBase64(deck.extra) + "!" + uint32ArrayToBase64(deck.side) + "!";
171
+ }
172
+ function fromYdkeURL(ydke) {
173
+ if (!ydke.startsWith("ydke://")) {
174
+ throw new Error("Invalid ydke:// URI");
175
+ }
176
+ const [mainStr, extraStr, sideStr] = ydke.slice(7).split("!");
177
+ if (mainStr === void 0 || extraStr === void 0 || sideStr === void 0) {
178
+ throw new Error("Incomplete ydke:// URI");
179
+ }
180
+ return {
181
+ main: base64ToUint32Array(mainStr),
182
+ extra: base64ToUint32Array(extraStr),
183
+ side: base64ToUint32Array(sideStr)
184
+ };
185
+ }
186
+
187
+ // src/ygom.ts
188
+ var QUERY_YGO_TYPE = "ygotype";
189
+ var QUERY_VERSION = "v";
190
+ var ARG_DECK = "deck";
191
+ var QUERY_DECK = "d";
192
+ var QUERY_NAME = "name";
193
+ var URL_SCHEME_HTTP = "http";
194
+ var URL_HOST_DECK = "deck.ourygo.top";
195
+ function toBinary(value, length) {
196
+ return value.toString(2).padStart(length, "0");
197
+ }
198
+ function encodeCards(cards) {
199
+ const bits = [];
200
+ for (let i = 0; i < cards.length; ) {
201
+ const id = cards[i];
202
+ let count = 1;
203
+ while (i + count < cards.length && cards[i + count] === id && count < 3)
204
+ count++;
205
+ const prefix = count === 2 ? "10" : count === 3 ? "11" : "01";
206
+ bits.push(prefix + toBinary(id, 27));
207
+ i += count;
208
+ }
209
+ return bits.join("");
210
+ }
211
+ function countUnique(cards) {
212
+ let num = 0;
213
+ for (let i = 0; i < cards.length; i++) {
214
+ const id = cards[i];
215
+ if (id > 0) {
216
+ num++;
217
+ if (i < cards.length - 1 && cards[i + 1] === id) {
218
+ i++;
219
+ if (i < cards.length - 1 && cards[i + 1] === id) {
220
+ i++;
221
+ }
222
+ }
223
+ }
224
+ }
225
+ return num;
226
+ }
227
+ function toYGOMobileDeckURL(main, extra, side, customParams = {}) {
228
+ const mNum = countUnique(main);
229
+ const eNum = countUnique(extra);
230
+ const sNum = countUnique(side);
231
+ const header = toBinary(mNum, 8) + toBinary(eNum, 4) + toBinary(sNum, 4);
232
+ let bitString = header + encodeCards(main) + encodeCards(extra) + encodeCards(side);
233
+ while (bitString.length % 8 !== 0)
234
+ bitString += "0";
235
+ const bytes = new Uint8Array(bitString.length / 8);
236
+ for (let i = 0; i < bytes.length; i++) {
237
+ bytes[i] = parseInt(bitString.slice(i * 8, i * 8 + 8), 2);
238
+ }
239
+ let encoded = toBase64Url(bytes);
240
+ const searchParams = new URLSearchParams();
241
+ for (const [key, value] of Object.entries(customParams)) {
242
+ searchParams.set(key, value);
243
+ }
244
+ searchParams.set(QUERY_YGO_TYPE, ARG_DECK);
245
+ searchParams.set(QUERY_VERSION, "1");
246
+ searchParams.set(QUERY_DECK, encoded);
247
+ return `${URL_SCHEME_HTTP}://${URL_HOST_DECK}?${searchParams.toString()}`;
248
+ }
249
+ function fromYGOMobileDeckURL(uri) {
250
+ const url = new URL(uri);
251
+ if (url.searchParams.get(QUERY_YGO_TYPE) !== ARG_DECK) {
252
+ throw new Error("Not a YGO Mobile deck URI");
253
+ }
254
+ let encoded = url.searchParams.get(QUERY_DECK);
255
+ if (!encoded)
256
+ throw new Error("Missing deck data");
257
+ const bytes = fromBase64Url(encoded);
258
+ const bits = Array.from(bytes).map((b) => b.toString(2).padStart(8, "0")).join("");
259
+ const mNum = parseInt(bits.slice(0, 8), 2);
260
+ const eNum = parseInt(bits.slice(8, 12), 2);
261
+ const sNum = parseInt(bits.slice(12, 16), 2);
262
+ const all = mNum + eNum + sNum;
263
+ const cards = [];
264
+ let pos = 16;
265
+ const res = {
266
+ main: [],
267
+ extra: [],
268
+ side: []
269
+ };
270
+ let i = 0;
271
+ while (pos + 29 <= bits.length && cards.length < all) {
272
+ const countBits = bits.slice(pos, pos + 2);
273
+ const count = countBits === "10" ? 2 : countBits === "11" ? 3 : 1;
274
+ const id = parseInt(bits.slice(pos + 2, pos + 29), 2);
275
+ const field = i < mNum ? "main" : i < mNum + eNum ? "extra" : "side";
276
+ res[field].push(...Array(count).fill(id));
277
+ pos += 29;
278
+ i++;
279
+ }
280
+ return {
281
+ ...res,
282
+ name: url.searchParams.get(QUERY_NAME)
283
+ };
284
+ }
50
285
 
51
286
  // index.ts
52
- import { Base64 } from "js-base64";
53
287
  var YGOProDeck = class {
54
288
  main = [];
55
289
  extra = [];
56
290
  side = [];
291
+ name;
57
292
  bufferLength() {
58
293
  const counted = [this.main, this.extra, this.side].map(countItems);
59
294
  return counted.reduce((a, b) => a + b.size * 4, 0);
@@ -76,7 +311,7 @@ var YGOProDeck = class {
76
311
  return writer.buffer;
77
312
  }
78
313
  toEncodedString() {
79
- return Base64.fromUint8Array(this.toUint8Array(), true);
314
+ return toBase64Url(this.toUint8Array());
80
315
  }
81
316
  toString() {
82
317
  return this.toEncodedString();
@@ -98,7 +333,7 @@ var YGOProDeck = class {
98
333
  return new YGOProDeck().fromUint8Array(buf);
99
334
  }
100
335
  fromEncodedString(str) {
101
- return this.fromUint8Array(Base64.toUint8Array(str));
336
+ return this.fromUint8Array(fromBase64Url(str));
102
337
  }
103
338
  static fromEncodedString(str) {
104
339
  return new YGOProDeck().fromEncodedString(str);
@@ -137,12 +372,69 @@ var YGOProDeck = class {
137
372
  static fromYdkString(str) {
138
373
  return new YGOProDeck().fromYdkString(str);
139
374
  }
375
+ fromUpdateDeckPayload(buf, isExtraDeckCard = () => false) {
376
+ const reader = new BufferReader(buf);
377
+ const mainc = reader.readUint32LE();
378
+ const sidec = reader.readUint32LE();
379
+ this.main = [];
380
+ this.extra = [];
381
+ this.side = [];
382
+ for (let i = 0; i < mainc; i++) {
383
+ const id = reader.readUint32LE();
384
+ if (isExtraDeckCard(id, i, mainc)) {
385
+ this.extra.push(id);
386
+ } else {
387
+ this.main.push(id);
388
+ }
389
+ }
390
+ for (let i = 0; i < sidec; i++) {
391
+ const id = reader.readUint32LE();
392
+ this.side.push(id);
393
+ }
394
+ return this;
395
+ }
396
+ static fromUpdateDeckPayload(buf, isExtraDeckCard = () => false) {
397
+ return new YGOProDeck().fromUpdateDeckPayload(buf, isExtraDeckCard);
398
+ }
140
399
  toUpdateDeckPayload() {
141
400
  const cards = [...this.main, ...this.extra, ...this.side];
142
401
  const writer = new BufferWriter(cards.length * 4 + 8).writeUint32LE(this.main.length + this.extra.length).writeUint32LE(this.side.length);
143
402
  cards.forEach((id) => writer.writeUint32LE(id));
144
403
  return writer.buffer;
145
404
  }
405
+ fromYGOMobileDeckURL(uri) {
406
+ const parsed = fromYGOMobileDeckURL(uri);
407
+ this.main = parsed.main;
408
+ this.extra = parsed.extra;
409
+ this.side = parsed.side;
410
+ this.name = parsed.name;
411
+ return this;
412
+ }
413
+ static fromYGOMobileDeckURL(uri) {
414
+ return new YGOProDeck().fromYGOMobileDeckURL(uri);
415
+ }
416
+ toYGOMobileDeckURL() {
417
+ return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {
418
+ name: this.name
419
+ });
420
+ }
421
+ fromYdkeURL(uri) {
422
+ const parsed = fromYdkeURL(uri);
423
+ this.main = parsed.main;
424
+ this.extra = parsed.extra;
425
+ this.side = parsed.side;
426
+ return this;
427
+ }
428
+ static fromYdkeURL(uri) {
429
+ return new YGOProDeck().fromYdkeURL(uri);
430
+ }
431
+ toYdkeURL() {
432
+ return toYdkeURL({
433
+ main: this.main,
434
+ extra: this.extra,
435
+ side: this.side
436
+ });
437
+ }
146
438
  };
147
439
  export {
148
440
  YGOProDeck as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/utils.ts", "../index.ts"],
4
- "sourcesContent": ["export function countItems<T>(arr: T[]) {\n const map = new Map<T, number>();\n for (const item of arr) {\n map.set(item, (map.get(item) || 0) + 1);\n }\n return map;\n}\n\nexport class BufferWriter {\n buffer: Uint8Array;\n pointer = 0;\n constructor(length: number) {\n this.buffer = new Uint8Array(length);\n }\n writeUint32LE(value: number) {\n this.buffer[this.pointer++] = value & 0xff;\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n this.buffer[this.pointer++] = (value >>> 16) & 0xff;\n this.buffer[this.pointer++] = (value >>> 24) & 0xff;\n return this;\n }\n\n writeUint32BE(value: number) {\n this.buffer[this.pointer++] = (value >>> 24) & 0xff;\n this.buffer[this.pointer++] = (value >>> 16) & 0xff;\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n this.buffer[this.pointer++] = value & 0xff;\n return this;\n }\n\n writeUint16LE(value: number) {\n this.buffer[this.pointer++] = value & 0xff;\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n return this;\n }\n\n writeUint16BE(value: number) {\n this.buffer[this.pointer++] = (value >>> 8) & 0xff;\n this.buffer[this.pointer++] = value & 0xff;\n return this;\n }\n\n writeUint8(value: number) {\n this.buffer[this.pointer++] = value & 0xff;\n return this;\n }\n\n writeString(str: string) {\n for (let i = 0; i < str.length; i++) {\n this.buffer[this.pointer++] = str.charCodeAt(i);\n }\n return this;\n }\n}\n", "import { BufferWriter, countItems } from './src/utils';\nimport { Base64 } from 'js-base64';\n\nexport default class YGOProDeck {\n main: number[] = [];\n extra: number[] = [];\n side: number[] = [];\n\n bufferLength() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n return counted.reduce((a, b) => a + b.size * 4, 0);\n }\n\n toUint8Array() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n const writer = new BufferWriter(\n counted.reduce((a, b) => a + b.size * 4, 0),\n );\n const writeCards = (countMap: Map<number, number>, type: number) => {\n // each card: 28 bits for id, 2 bits(0, 1, 2, 3) for type(0: main, 1: extra, 2: side, 3: unknown), 2 bits for count (0: 1, 1: 2, 2: 3, 3: 4)\n for (const [id, count] of countMap.entries()) {\n if (count > 4) {\n throw new Error(`Too many cards: ${id}`);\n }\n const value = (id & 0xfffffff) | (type << 28) | ((count - 1) << 30);\n writer.writeUint32LE(value);\n }\n };\n counted.forEach(writeCards);\n return writer.buffer;\n }\n\n toEncodedString() {\n return Base64.fromUint8Array(this.toUint8Array(), true);\n }\n\n toString() {\n return this.toEncodedString();\n }\n\n fromUint8Array(buf: Uint8Array) {\n for (let i = 0; i < buf.length - 3; i += 4) {\n const value =\n buf[i] | (buf[i + 1] << 8) | (buf[i + 2] << 16) | (buf[i + 3] << 24);\n const id = value & 0xfffffff;\n const type = (value >>> 28) & 0x3;\n const count = ((value >>> 30) & 0x3) + 1;\n const cards = [this.main, this.extra, this.side][type];\n for (let j = 0; j < count; j++) {\n cards.push(id);\n }\n }\n return this;\n }\n\n static fromUint8Array(buf: Uint8Array) {\n return new YGOProDeck().fromUint8Array(buf);\n }\n\n fromEncodedString(str: string) {\n return this.fromUint8Array(Base64.toUint8Array(str));\n }\n\n static fromEncodedString(str: string) {\n return new YGOProDeck().fromEncodedString(str);\n }\n\n toYdkString() {\n return [\n '#created by ygopro-deck-encode',\n '#main',\n ...this.main.map((id) => id.toString()),\n '#extra',\n ...this.extra.map((id) => id.toString()),\n '!side',\n ...this.side.map((id) => id.toString()),\n ].join('\\n');\n }\n\n fromYdkString(str: string) {\n const lines = str.split(/\\r?\\n/);\n let current = this.main;\n for (const _line of lines) {\n const line = _line.trim();\n if (line === '#main') {\n current = this.main;\n }\n if (line === '#extra') {\n current = this.extra;\n }\n if (line === '!side') {\n current = this.side;\n }\n if (line.match(/^\\d+$/)) {\n current.push(parseInt(line, 10));\n }\n }\n return this;\n }\n\n static fromYdkString(str: string) {\n return new YGOProDeck().fromYdkString(str);\n }\n\n toUpdateDeckPayload() {\n const cards = [...this.main, ...this.extra, ...this.side];\n const writer = new BufferWriter(cards.length * 4 + 8)\n .writeUint32LE(this.main.length + this.extra.length)\n .writeUint32LE(this.side.length);\n cards.forEach((id) => writer.writeUint32LE(id));\n return writer.buffer;\n }\n}\n"],
5
- "mappings": ";AAAO,SAAS,WAAc,KAAU;AACtC,QAAM,MAAM,oBAAI,IAAe;AAC/B,aAAW,QAAQ,KAAK;AACtB,QAAI,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AAEO,IAAM,eAAN,MAAmB;AAAA,EACxB;AAAA,EACA,UAAU;AAAA,EACV,YAAY,QAAgB;AAC1B,SAAK,SAAS,IAAI,WAAW,MAAM;AAAA,EACrC;AAAA,EACA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,KAAM;AAC/C,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAe;AAC3B,SAAK,OAAO,KAAK,SAAS,IAAK,UAAU,IAAK;AAC9C,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,OAAe;AACxB,SAAK,OAAO,KAAK,SAAS,IAAI,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,KAAa;AACvB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,WAAK,OAAO,KAAK,SAAS,IAAI,IAAI,WAAW,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AACF;;;ACpDA,SAAS,cAAc;AAEvB,IAAqB,aAArB,MAAgC;AAAA,EAC9B,OAAiB,CAAC;AAAA,EAClB,QAAkB,CAAC;AAAA,EACnB,OAAiB,CAAC;AAAA,EAElB,eAAe;AACb,UAAM,UAAU,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI,UAAU;AACjE,WAAO,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,EACnD;AAAA,EAEA,eAAe;AACb,UAAM,UAAU,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI,UAAU;AACjE,UAAM,SAAS,IAAI;AAAA,MACjB,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,IAC5C;AACA,UAAM,aAAa,CAAC,UAA+B,SAAiB;AAElE,iBAAW,CAAC,IAAI,KAAK,KAAK,SAAS,QAAQ,GAAG;AAC5C,YAAI,QAAQ,GAAG;AACb,gBAAM,IAAI,MAAM,mBAAmB,IAAI;AAAA,QACzC;AACA,cAAM,QAAS,KAAK,YAAc,QAAQ,KAAQ,QAAQ,KAAM;AAChE,eAAO,cAAc,KAAK;AAAA,MAC5B;AAAA,IACF;AACA,YAAQ,QAAQ,UAAU;AAC1B,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,kBAAkB;AAChB,WAAO,OAAO,eAAe,KAAK,aAAa,GAAG,IAAI;AAAA,EACxD;AAAA,EAEA,WAAW;AACT,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA,EAEA,eAAe,KAAiB;AAC9B,aAAS,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG;AAC1C,YAAM,QACJ,IAAI,CAAC,IAAK,IAAI,IAAI,CAAC,KAAK,IAAM,IAAI,IAAI,CAAC,KAAK,KAAO,IAAI,IAAI,CAAC,KAAK;AACnE,YAAM,KAAK,QAAQ;AACnB,YAAM,OAAQ,UAAU,KAAM;AAC9B,YAAM,SAAU,UAAU,KAAM,KAAO;AACvC,YAAM,QAAQ,CAAC,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAAI;AACrD,eAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,cAAM,KAAK,EAAE;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,eAAe,KAAiB;AACrC,WAAO,IAAI,WAAW,EAAE,eAAe,GAAG;AAAA,EAC5C;AAAA,EAEA,kBAAkB,KAAa;AAC7B,WAAO,KAAK,eAAe,OAAO,aAAa,GAAG,CAAC;AAAA,EACrD;AAAA,EAEA,OAAO,kBAAkB,KAAa;AACpC,WAAO,IAAI,WAAW,EAAE,kBAAkB,GAAG;AAAA,EAC/C;AAAA,EAEA,cAAc;AACZ,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,MACtC;AAAA,MACA,GAAG,KAAK,MAAM,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,MACvC;AAAA,MACA,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;AAAA,IACxC,EAAE,KAAK,IAAI;AAAA,EACb;AAAA,EAEA,cAAc,KAAa;AACzB,UAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,QAAI,UAAU,KAAK;AACnB,eAAW,SAAS,OAAO;AACzB,YAAM,OAAO,MAAM,KAAK;AACxB,UAAI,SAAS,SAAS;AACpB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,SAAS,UAAU;AACrB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,SAAS,SAAS;AACpB,kBAAU,KAAK;AAAA,MACjB;AACA,UAAI,KAAK,MAAM,OAAO,GAAG;AACvB,gBAAQ,KAAK,SAAS,MAAM,EAAE,CAAC;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,cAAc,KAAa;AAChC,WAAO,IAAI,WAAW,EAAE,cAAc,GAAG;AAAA,EAC3C;AAAA,EAEA,sBAAsB;AACpB,UAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,IAAI;AACxD,UAAM,SAAS,IAAI,aAAa,MAAM,SAAS,IAAI,CAAC,EACjD,cAAc,KAAK,KAAK,SAAS,KAAK,MAAM,MAAM,EAClD,cAAc,KAAK,KAAK,MAAM;AACjC,UAAM,QAAQ,CAAC,OAAO,OAAO,cAAc,EAAE,CAAC;AAC9C,WAAO,OAAO;AAAA,EAChB;AACF;",
3
+ "sources": ["../src/base64.ts", "../src/utils.ts", "../src/ydke.ts", "../src/ygom.ts", "../index.ts"],
4
+ "sourcesContent": ["export function toBase64Url(bytes: Uint8Array): string {\n const base64 = typeof Buffer !== 'undefined'\n ? Buffer.from(bytes).toString('base64')\n : btoa(String.fromCharCode(...bytes));\n\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nexport function fromBase64Url(encoded: string): Uint8Array {\n const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, '=');\n\n if (typeof Buffer !== 'undefined') {\n return Uint8Array.from(Buffer.from(padded, 'base64'));\n }\n\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n", "export function countItems<T>(arr: T[]) {\n const map = new Map<T, number>();\n for (const item of arr) {\n map.set(item, (map.get(item) || 0) + 1);\n }\n return map;\n}\nabstract class BufferCursor {\n buffer: Uint8Array;\n pointer = 0;\n\n constructor(bufOrLength: Uint8Array | number) {\n if (typeof bufOrLength === 'number') {\n this.buffer = new Uint8Array(bufOrLength);\n } else {\n this.buffer = bufOrLength;\n }\n }\n\n /**\n * \u5B89\u5168\u5730\u5C06 pointer \u5411\u524D\u79FB\u52A8\u6307\u5B9A\u5B57\u8282\u6570\u3002\n * @param bytes \u8981\u79FB\u52A8\u7684\u5B57\u8282\u6570\n * @returns \u539F\u6765 pointer \u7684\u503C\n * @throws RangeError \u5982\u679C\u8D8A\u754C\n */\n protected increasePointer(bytes: number): number {\n const old = this.pointer;\n const next = old + bytes;\n if (next > this.buffer.length) {\n throw new RangeError(\n `Pointer overflow: tried to move to ${next}, but buffer length is ${this.buffer.length}`\n );\n }\n this.pointer = next;\n return old;\n }\n}\n\nexport class BufferWriter extends BufferCursor {\n constructor(length: number) {\n super(length);\n }\n\n writeUint32LE(value: number) {\n const idx = this.increasePointer(4);\n this.buffer[idx ] = value & 0xff;\n this.buffer[idx + 1] = (value >>> 8) & 0xff;\n this.buffer[idx + 2] = (value >>> 16) & 0xff;\n this.buffer[idx + 3] = (value >>> 24) & 0xff;\n return this;\n }\n\n writeUint32BE(value: number) {\n const idx = this.increasePointer(4);\n this.buffer[idx ] = (value >>> 24) & 0xff;\n this.buffer[idx + 1] = (value >>> 16) & 0xff;\n this.buffer[idx + 2] = (value >>> 8) & 0xff;\n this.buffer[idx + 3] = value & 0xff;\n return this;\n }\n\n writeUint16LE(value: number) {\n const idx = this.increasePointer(2);\n this.buffer[idx ] = value & 0xff;\n this.buffer[idx + 1] = (value >>> 8) & 0xff;\n return this;\n }\n\n writeUint16BE(value: number) {\n const idx = this.increasePointer(2);\n this.buffer[idx ] = (value >>> 8) & 0xff;\n this.buffer[idx + 1] = value & 0xff;\n return this;\n }\n\n writeUint8(value: number) {\n const idx = this.increasePointer(1);\n this.buffer[idx] = value & 0xff;\n return this;\n }\n\n writeString(str: string) {\n for (let i = 0; i < str.length; i++) {\n const idx = this.increasePointer(1);\n this.buffer[idx] = str.charCodeAt(i);\n }\n return this;\n }\n}\n\nexport class BufferReader extends BufferCursor {\n constructor(buf: Uint8Array) {\n super(buf);\n }\n\n readUint32LE(): number {\n const idx = this.increasePointer(4);\n const b = this.buffer;\n // >>>0 \u4FDD\u8BC1\u65E0\u7B26\u53F7\u8F93\u51FA\n return (\n (b[idx ] ) |\n (b[idx + 1] << 8) |\n (b[idx + 2] << 16) |\n (b[idx + 3] << 24)\n ) >>> 0;\n }\n\n readUint32BE(): number {\n const idx = this.increasePointer(4);\n const b = this.buffer;\n return (\n (b[idx ] << 24) |\n (b[idx + 1] << 16) |\n (b[idx + 2] << 8) |\n (b[idx + 3] )\n ) >>> 0;\n }\n\n readUint16LE(): number {\n const idx = this.increasePointer(2);\n const b = this.buffer;\n return (b[idx] | (b[idx + 1] << 8));\n }\n\n readUint16BE(): number {\n const idx = this.increasePointer(2);\n const b = this.buffer;\n return ((b[idx] << 8) | b[idx + 1]);\n }\n\n readUint8(): number {\n const idx = this.increasePointer(1);\n return this.buffer[idx];\n }\n\n readString(length: number): string {\n let s = '';\n for (let i = 0; i < length; i++) {\n const idx = this.increasePointer(1);\n s += String.fromCharCode(this.buffer[idx]);\n }\n return s;\n }\n\n readRemaining(): Uint8Array {\n const remaining = this.buffer.length - this.pointer;\n const idx = this.increasePointer(remaining);\n return this.buffer.subarray(idx, this.buffer.length);\n }\n}\n", "// ydke.ts\n\nexport interface TypedDeck {\n main: number[];\n extra: number[];\n side: number[];\n}\n\nfunction base64ToUint32Array(base64: string): number[] {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n const view = new DataView(bytes.buffer);\n const result: number[] = [];\n for (let i = 0; i < bytes.length; i += 4) {\n result.push(view.getUint32(i, true)); // little-endian\n }\n return result;\n}\n\nfunction uint32ArrayToBase64(data: number[]): string {\n const buffer = new ArrayBuffer(data.length * 4);\n const view = new DataView(buffer);\n data.forEach((val, i) => view.setUint32(i * 4, val, true));\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nexport function toYdkeURL(deck: TypedDeck): string {\n return (\n 'ydke://' +\n uint32ArrayToBase64(deck.main) +\n '!' +\n uint32ArrayToBase64(deck.extra) +\n '!' +\n uint32ArrayToBase64(deck.side) +\n '!'\n );\n}\n\nexport function fromYdkeURL(ydke: string): TypedDeck {\n if (!ydke.startsWith('ydke://')) {\n throw new Error('Invalid ydke:// URI');\n }\n const [mainStr, extraStr, sideStr] = ydke.slice(7).split('!');\n if (mainStr === undefined || extraStr === undefined || sideStr === undefined) {\n throw new Error('Incomplete ydke:// URI');\n }\n return {\n main: base64ToUint32Array(mainStr),\n extra: base64ToUint32Array(extraStr),\n side: base64ToUint32Array(sideStr),\n };\n}\n", "import { fromBase64Url, toBase64Url } from \"./base64\";\n\n// === \u5E38\u91CF\u533A\u57DF ===\nconst QUERY_YGO_TYPE = 'ygotype';\nconst QUERY_VERSION = 'v';\nconst ARG_DECK = 'deck';\nconst QUERY_DECK = 'd';\nconst QUERY_NAME = 'name';\n\nconst URL_SCHEME_HTTP = 'http';\nconst URL_HOST_DECK = 'deck.ourygo.top';\n\n// === \u5DE5\u5177\u51FD\u6570 ===\nfunction toBinary(value: number, length: number): string {\n return value.toString(2).padStart(length, '0');\n}\n\nfunction encodeCards(cards: number[]): string {\n const bits: string[] = [];\n for (let i = 0; i < cards.length; ) {\n const id = cards[i];\n let count = 1;\n while (i + count < cards.length && cards[i + count] === id && count < 3) count++;\n const prefix = count === 2 ? '10' : count === 3 ? '11' : '01';\n bits.push(prefix + toBinary(id, 27));\n i += count;\n }\n return bits.join('');\n}\n\nfunction countUnique(cards: number[]): number {\n let num = 0;\n for (let i = 0; i < cards.length; i++) {\n const id = cards[i];\n if (id > 0) {\n num++;\n if (i < cards.length - 1 && cards[i + 1] === id) {\n i++;\n if (i < cards.length - 1 && cards[i + 1] === id) {\n i++;\n }\n }\n }\n }\n return num;\n}\n\n// === \u4E3B\u51FD\u6570 ===\n\nexport function toYGOMobileDeckURL(\n main: number[],\n extra: number[],\n side: number[],\n customParams: Record<string, string> = {},\n): string {\n const mNum = countUnique(main);\n const eNum = countUnique(extra);\n const sNum = countUnique(side);\n\n const header = toBinary(mNum, 8) + toBinary(eNum, 4) + toBinary(sNum, 4);\n let bitString = header + encodeCards(main) + encodeCards(extra) + encodeCards(side);\n while (bitString.length % 8 !== 0) bitString += '0';\n\n const bytes = new Uint8Array(bitString.length / 8);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(bitString.slice(i * 8, i * 8 + 8), 2);\n }\n\n let encoded = toBase64Url(bytes)\n\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(customParams)) {\n searchParams.set(key, value);\n }\n searchParams.set(QUERY_YGO_TYPE, ARG_DECK);\n searchParams.set(QUERY_VERSION, '1');\n searchParams.set(QUERY_DECK, encoded);\n\n return `${URL_SCHEME_HTTP}://${URL_HOST_DECK}?${searchParams.toString()}`;\n}\n\n\nexport function fromYGOMobileDeckURL(uri: string): {\n main: number[];\n extra: number[];\n side: number[];\n name?: string;\n} {\n const url = new URL(uri);\n if (url.searchParams.get(QUERY_YGO_TYPE) !== ARG_DECK) {\n throw new Error('Not a YGO Mobile deck URI');\n }\n\n let encoded = url.searchParams.get(QUERY_DECK);\n if (!encoded) throw new Error('Missing deck data');\n\n const bytes = fromBase64Url(encoded);\n\n const bits = Array.from(bytes)\n .map((b) => b.toString(2).padStart(8, '0'))\n .join('');\n\n const mNum = parseInt(bits.slice(0, 8), 2);\n const eNum = parseInt(bits.slice(8, 12), 2);\n const sNum = parseInt(bits.slice(12, 16), 2);\n\n const all = mNum + eNum + sNum;\n const cards: number[] = [];\n let pos = 16;\n \n const res = {\n main: [] as number[],\n extra: [] as number[],\n side: [] as number[],\n }\n\n let i = 0;\n\n while (pos + 29 <= bits.length && cards.length < all) {\n const countBits = bits.slice(pos, pos + 2);\n const count = countBits === '10' ? 2 : countBits === '11' ? 3 : 1;\n const id = parseInt(bits.slice(pos + 2, pos + 29), 2);\n const field = i < mNum ? 'main' : i < mNum + eNum ? 'extra' : 'side';\n res[field].push(...Array(count).fill(id));\n pos += 29;\n i++;\n }\n\n return {\n ...res,\n name: url.searchParams.get(QUERY_NAME),\n };\n}\n", "import { fromBase64Url, toBase64Url } from './src/base64';\nimport { BufferReader, BufferWriter, countItems } from './src/utils';\nimport { fromYdkeURL, toYdkeURL } from './src/ydke';\nimport { fromYGOMobileDeckURL, toYGOMobileDeckURL } from './src/ygom';\n\nexport default class YGOProDeck {\n main: number[] = [];\n extra: number[] = [];\n side: number[] = [];\n name?: string;\n\n bufferLength() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n return counted.reduce((a, b) => a + b.size * 4, 0);\n }\n\n toUint8Array() {\n const counted = [this.main, this.extra, this.side].map(countItems);\n const writer = new BufferWriter(\n counted.reduce((a, b) => a + b.size * 4, 0),\n );\n const writeCards = (countMap: Map<number, number>, type: number) => {\n // each card: 28 bits for id, 2 bits(0, 1, 2, 3) for type(0: main, 1: extra, 2: side, 3: unknown), 2 bits for count (0: 1, 1: 2, 2: 3, 3: 4)\n for (const [id, count] of countMap.entries()) {\n if (count > 4) {\n throw new Error(`Too many cards: ${id}`);\n }\n const value = (id & 0xfffffff) | (type << 28) | ((count - 1) << 30);\n writer.writeUint32LE(value);\n }\n };\n counted.forEach(writeCards);\n return writer.buffer;\n }\n\n toEncodedString() {\n return toBase64Url(this.toUint8Array());\n }\n\n toString() {\n return this.toEncodedString();\n }\n\n fromUint8Array(buf: Uint8Array) {\n for (let i = 0; i < buf.length - 3; i += 4) {\n const value =\n buf[i] | (buf[i + 1] << 8) | (buf[i + 2] << 16) | (buf[i + 3] << 24);\n const id = value & 0xfffffff;\n const type = (value >>> 28) & 0x3;\n const count = ((value >>> 30) & 0x3) + 1;\n const cards = [this.main, this.extra, this.side][type];\n for (let j = 0; j < count; j++) {\n cards.push(id);\n }\n }\n return this;\n }\n\n static fromUint8Array(buf: Uint8Array) {\n return new YGOProDeck().fromUint8Array(buf);\n }\n\n fromEncodedString(str: string) {\n return this.fromUint8Array(fromBase64Url(str));\n }\n\n static fromEncodedString(str: string) {\n return new YGOProDeck().fromEncodedString(str);\n }\n\n toYdkString() {\n return [\n '#created by ygopro-deck-encode',\n '#main',\n ...this.main.map((id) => id.toString()),\n '#extra',\n ...this.extra.map((id) => id.toString()),\n '!side',\n ...this.side.map((id) => id.toString()),\n ].join('\\n');\n }\n\n fromYdkString(str: string) {\n const lines = str.split(/\\r?\\n/);\n let current = this.main;\n for (const _line of lines) {\n const line = _line.trim();\n if (line === '#main') {\n current = this.main;\n }\n if (line === '#extra') {\n current = this.extra;\n }\n if (line === '!side') {\n current = this.side;\n }\n if (line.match(/^\\d+$/)) {\n current.push(parseInt(line, 10));\n }\n }\n return this;\n }\n\n static fromYdkString(str: string) {\n return new YGOProDeck().fromYdkString(str);\n }\n\n fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard: (code: number, i: number, mainc: number) => boolean = () => false) {\n const reader = new BufferReader(buf);\n const mainc = reader.readUint32LE();\n const sidec = reader.readUint32LE();\n this.main = [];\n this.extra = [];\n this.side = [];\n for(let i = 0; i < mainc; i++) {\n const id = reader.readUint32LE();\n if (isExtraDeckCard(id, i, mainc)) {\n this.extra.push(id);\n } else {\n this.main.push(id);\n }\n }\n for(let i = 0; i < sidec; i++) {\n const id = reader.readUint32LE();\n this.side.push(id);\n }\n return this;\n }\n\n static fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard: (code: number) => boolean = () => false) { \n return new YGOProDeck().fromUpdateDeckPayload(buf, isExtraDeckCard);\n }\n\n toUpdateDeckPayload() {\n const cards = [...this.main, ...this.extra, ...this.side];\n const writer = new BufferWriter(cards.length * 4 + 8)\n .writeUint32LE(this.main.length + this.extra.length)\n .writeUint32LE(this.side.length);\n cards.forEach((id) => writer.writeUint32LE(id));\n return writer.buffer;\n }\n\n fromYGOMobileDeckURL(uri: string): YGOProDeck {\n const parsed = fromYGOMobileDeckURL(uri);\n this.main = parsed.main;\n this.extra = parsed.extra;\n this.side = parsed.side;\n this.name = parsed.name;\n return this;\n }\n\n static fromYGOMobileDeckURL(uri: string): YGOProDeck {\n return new YGOProDeck().fromYGOMobileDeckURL(uri);\n }\n\n toYGOMobileDeckURL(): string {\n return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {\n name: this.name,\n });\n }\n\n fromYdkeURL(uri: string): YGOProDeck {\n const parsed = fromYdkeURL(uri);\n this.main = parsed.main;\n this.extra = parsed.extra;\n this.side = parsed.side;\n return this;\n }\n\n static fromYdkeURL(uri: string): YGOProDeck {\n return new YGOProDeck().fromYdkeURL(uri);\n }\n\n toYdkeURL(): string {\n return toYdkeURL({\n main: this.main,\n extra: this.extra,\n side: this.side,\n });\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,2 @@
1
+ export declare function toBase64Url(bytes: Uint8Array): string;
2
+ export declare function fromBase64Url(encoded: string): Uint8Array;
@@ -1,7 +1,17 @@
1
1
  export declare function countItems<T>(arr: T[]): Map<T, number>;
2
- export declare class BufferWriter {
2
+ declare abstract class BufferCursor {
3
3
  buffer: Uint8Array;
4
4
  pointer: number;
5
+ constructor(bufOrLength: Uint8Array | number);
6
+ /**
7
+ * 安全地将 pointer 向前移动指定字节数。
8
+ * @param bytes 要移动的字节数
9
+ * @returns 原来 pointer 的值
10
+ * @throws RangeError 如果越界
11
+ */
12
+ protected increasePointer(bytes: number): number;
13
+ }
14
+ export declare class BufferWriter extends BufferCursor {
5
15
  constructor(length: number);
6
16
  writeUint32LE(value: number): this;
7
17
  writeUint32BE(value: number): this;
@@ -10,3 +20,14 @@ export declare class BufferWriter {
10
20
  writeUint8(value: number): this;
11
21
  writeString(str: string): this;
12
22
  }
23
+ export declare class BufferReader extends BufferCursor {
24
+ constructor(buf: Uint8Array);
25
+ readUint32LE(): number;
26
+ readUint32BE(): number;
27
+ readUint16LE(): number;
28
+ readUint16BE(): number;
29
+ readUint8(): number;
30
+ readString(length: number): string;
31
+ readRemaining(): Uint8Array;
32
+ }
33
+ export {};
@@ -0,0 +1,7 @@
1
+ export interface TypedDeck {
2
+ main: number[];
3
+ extra: number[];
4
+ side: number[];
5
+ }
6
+ export declare function toYdkeURL(deck: TypedDeck): string;
7
+ export declare function fromYdkeURL(ydke: string): TypedDeck;
@@ -0,0 +1,7 @@
1
+ export declare function toYGOMobileDeckURL(main: number[], extra: number[], side: number[], customParams?: Record<string, string>): string;
2
+ export declare function fromYGOMobileDeckURL(uri: string): {
3
+ main: number[];
4
+ extra: number[];
5
+ side: number[];
6
+ name?: string;
7
+ };
package/index.ts CHANGED
@@ -1,10 +1,13 @@
1
- import { BufferWriter, countItems } from './src/utils';
2
- import { Base64 } from 'js-base64';
1
+ import { fromBase64Url, toBase64Url } from './src/base64';
2
+ import { BufferReader, BufferWriter, countItems } from './src/utils';
3
+ import { fromYdkeURL, toYdkeURL } from './src/ydke';
4
+ import { fromYGOMobileDeckURL, toYGOMobileDeckURL } from './src/ygom';
3
5
 
4
6
  export default class YGOProDeck {
5
7
  main: number[] = [];
6
8
  extra: number[] = [];
7
9
  side: number[] = [];
10
+ name?: string;
8
11
 
9
12
  bufferLength() {
10
13
  const counted = [this.main, this.extra, this.side].map(countItems);
@@ -31,7 +34,7 @@ export default class YGOProDeck {
31
34
  }
32
35
 
33
36
  toEncodedString() {
34
- return Base64.fromUint8Array(this.toUint8Array(), true);
37
+ return toBase64Url(this.toUint8Array());
35
38
  }
36
39
 
37
40
  toString() {
@@ -58,7 +61,7 @@ export default class YGOProDeck {
58
61
  }
59
62
 
60
63
  fromEncodedString(str: string) {
61
- return this.fromUint8Array(Base64.toUint8Array(str));
64
+ return this.fromUint8Array(fromBase64Url(str));
62
65
  }
63
66
 
64
67
  static fromEncodedString(str: string) {
@@ -102,6 +105,32 @@ export default class YGOProDeck {
102
105
  return new YGOProDeck().fromYdkString(str);
103
106
  }
104
107
 
108
+ fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard: (code: number, i: number, mainc: number) => boolean = () => false) {
109
+ const reader = new BufferReader(buf);
110
+ const mainc = reader.readUint32LE();
111
+ const sidec = reader.readUint32LE();
112
+ this.main = [];
113
+ this.extra = [];
114
+ this.side = [];
115
+ for(let i = 0; i < mainc; i++) {
116
+ const id = reader.readUint32LE();
117
+ if (isExtraDeckCard(id, i, mainc)) {
118
+ this.extra.push(id);
119
+ } else {
120
+ this.main.push(id);
121
+ }
122
+ }
123
+ for(let i = 0; i < sidec; i++) {
124
+ const id = reader.readUint32LE();
125
+ this.side.push(id);
126
+ }
127
+ return this;
128
+ }
129
+
130
+ static fromUpdateDeckPayload(buf: Uint8Array, isExtraDeckCard: (code: number) => boolean = () => false) {
131
+ return new YGOProDeck().fromUpdateDeckPayload(buf, isExtraDeckCard);
132
+ }
133
+
105
134
  toUpdateDeckPayload() {
106
135
  const cards = [...this.main, ...this.extra, ...this.side];
107
136
  const writer = new BufferWriter(cards.length * 4 + 8)
@@ -110,4 +139,43 @@ export default class YGOProDeck {
110
139
  cards.forEach((id) => writer.writeUint32LE(id));
111
140
  return writer.buffer;
112
141
  }
142
+
143
+ fromYGOMobileDeckURL(uri: string): YGOProDeck {
144
+ const parsed = fromYGOMobileDeckURL(uri);
145
+ this.main = parsed.main;
146
+ this.extra = parsed.extra;
147
+ this.side = parsed.side;
148
+ this.name = parsed.name;
149
+ return this;
150
+ }
151
+
152
+ static fromYGOMobileDeckURL(uri: string): YGOProDeck {
153
+ return new YGOProDeck().fromYGOMobileDeckURL(uri);
154
+ }
155
+
156
+ toYGOMobileDeckURL(): string {
157
+ return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {
158
+ name: this.name,
159
+ });
160
+ }
161
+
162
+ fromYdkeURL(uri: string): YGOProDeck {
163
+ const parsed = fromYdkeURL(uri);
164
+ this.main = parsed.main;
165
+ this.extra = parsed.extra;
166
+ this.side = parsed.side;
167
+ return this;
168
+ }
169
+
170
+ static fromYdkeURL(uri: string): YGOProDeck {
171
+ return new YGOProDeck().fromYdkeURL(uri);
172
+ }
173
+
174
+ toYdkeURL(): string {
175
+ return toYdkeURL({
176
+ main: this.main,
177
+ extra: this.extra,
178
+ side: this.side,
179
+ });
180
+ }
113
181
  }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "ygopro-deck-encode",
3
3
  "description": "YGOPro Deck encode and decode, with well-browser support.",
4
- "version": "1.0.5",
4
+ "version": "1.0.7",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "scripts": {
9
9
  "lint": "eslint --fix .",
10
- "compile:cjs": "esbuild index.ts --outfile=dist/index.cjs --bundle --sourcemap --platform=node --target=es2019 --external:js-base64",
11
- "compile:esm": "esbuild index.ts --outfile=dist/index.mjs --bundle --sourcemap --platform=neutral --target=esnext --external:js-base64",
10
+ "compile:cjs": "esbuild index.ts --outfile=dist/index.cjs --bundle --sourcemap --platform=node --target=es2019",
11
+ "compile:esm": "esbuild index.ts --outfile=dist/index.mjs --bundle --sourcemap --platform=neutral --target=esnext",
12
12
  "compile:types": "tsc --emitDeclarationOnly --declaration",
13
13
  "build": "rimraf dist && npm run compile:cjs && npm run compile:esm && npm run compile:types",
14
14
  "test": "jest --passWithNoTests",
@@ -56,9 +56,7 @@
56
56
  "prettier": "^2.8.4",
57
57
  "rimraf": "^4.1.2",
58
58
  "ts-jest": "^29.0.5",
59
- "typescript": "^4.9.5"
60
- },
61
- "dependencies": {
62
- "js-base64": "^3.7.5"
59
+ "typescript": "^4.9.5",
60
+ "ydke": "^1.1.0"
63
61
  }
64
62
  }