ygopro-deck-encode 1.0.5 → 1.0.6

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,14 @@ 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
18
26
  ```
19
27
 
20
28
 
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();
@@ -72,8 +91,149 @@ var BufferWriter = class {
72
91
  }
73
92
  };
74
93
 
94
+ // src/ydke.ts
95
+ function base64ToUint32Array(base64) {
96
+ const binary = atob(base64);
97
+ const bytes = new Uint8Array(binary.length);
98
+ for (let i = 0; i < binary.length; i++) {
99
+ bytes[i] = binary.charCodeAt(i);
100
+ }
101
+ const view = new DataView(bytes.buffer);
102
+ const result = [];
103
+ for (let i = 0; i < bytes.length; i += 4) {
104
+ result.push(view.getUint32(i, true));
105
+ }
106
+ return result;
107
+ }
108
+ function uint32ArrayToBase64(data) {
109
+ const buffer = new ArrayBuffer(data.length * 4);
110
+ const view = new DataView(buffer);
111
+ data.forEach((val, i) => view.setUint32(i * 4, val, true));
112
+ const bytes = new Uint8Array(buffer);
113
+ let binary = "";
114
+ for (let i = 0; i < bytes.length; i++) {
115
+ binary += String.fromCharCode(bytes[i]);
116
+ }
117
+ return btoa(binary);
118
+ }
119
+ function toYdkeURL(deck) {
120
+ return "ydke://" + uint32ArrayToBase64(deck.main) + "!" + uint32ArrayToBase64(deck.extra) + "!" + uint32ArrayToBase64(deck.side) + "!";
121
+ }
122
+ function fromYdkeURL(ydke) {
123
+ if (!ydke.startsWith("ydke://")) {
124
+ throw new Error("Invalid ydke:// URI");
125
+ }
126
+ const [mainStr, extraStr, sideStr] = ydke.slice(7).split("!");
127
+ if (mainStr === void 0 || extraStr === void 0 || sideStr === void 0) {
128
+ throw new Error("Incomplete ydke:// URI");
129
+ }
130
+ return {
131
+ main: base64ToUint32Array(mainStr),
132
+ extra: base64ToUint32Array(extraStr),
133
+ side: base64ToUint32Array(sideStr)
134
+ };
135
+ }
136
+
137
+ // src/ygom.ts
138
+ var QUERY_YGO_TYPE = "ygotype";
139
+ var QUERY_VERSION = "v";
140
+ var ARG_DECK = "deck";
141
+ var QUERY_DECK = "d";
142
+ var QUERY_NAME = "name";
143
+ var URL_SCHEME_HTTP = "http";
144
+ var URL_HOST_DECK = "deck.ourygo.top";
145
+ function toBinary(value, length) {
146
+ return value.toString(2).padStart(length, "0");
147
+ }
148
+ function encodeCards(cards) {
149
+ const bits = [];
150
+ for (let i = 0; i < cards.length; ) {
151
+ const id = cards[i];
152
+ let count = 1;
153
+ while (i + count < cards.length && cards[i + count] === id && count < 3)
154
+ count++;
155
+ const prefix = count === 2 ? "10" : count === 3 ? "11" : "01";
156
+ bits.push(prefix + toBinary(id, 27));
157
+ i += count;
158
+ }
159
+ return bits.join("");
160
+ }
161
+ function countUnique(cards) {
162
+ let num = 0;
163
+ for (let i = 0; i < cards.length; i++) {
164
+ const id = cards[i];
165
+ if (id > 0) {
166
+ num++;
167
+ if (i < cards.length - 1 && cards[i + 1] === id) {
168
+ i++;
169
+ if (i < cards.length - 1 && cards[i + 1] === id) {
170
+ i++;
171
+ }
172
+ }
173
+ }
174
+ }
175
+ return num;
176
+ }
177
+ function toYGOMobileDeckURL(main, extra, side, customParams = {}) {
178
+ const mNum = countUnique(main);
179
+ const eNum = countUnique(extra);
180
+ const sNum = countUnique(side);
181
+ const header = toBinary(mNum, 8) + toBinary(eNum, 4) + toBinary(sNum, 4);
182
+ let bitString = header + encodeCards(main) + encodeCards(extra) + encodeCards(side);
183
+ while (bitString.length % 8 !== 0)
184
+ bitString += "0";
185
+ const bytes = new Uint8Array(bitString.length / 8);
186
+ for (let i = 0; i < bytes.length; i++) {
187
+ bytes[i] = parseInt(bitString.slice(i * 8, i * 8 + 8), 2);
188
+ }
189
+ let encoded = toBase64Url(bytes);
190
+ const searchParams = new URLSearchParams();
191
+ for (const [key, value] of Object.entries(customParams)) {
192
+ searchParams.set(key, value);
193
+ }
194
+ searchParams.set(QUERY_YGO_TYPE, ARG_DECK);
195
+ searchParams.set(QUERY_VERSION, "1");
196
+ searchParams.set(QUERY_DECK, encoded);
197
+ return `${URL_SCHEME_HTTP}://${URL_HOST_DECK}?${searchParams.toString()}`;
198
+ }
199
+ function fromYGOMobileDeckURL(uri) {
200
+ const url = new URL(uri);
201
+ if (url.searchParams.get(QUERY_YGO_TYPE) !== ARG_DECK) {
202
+ throw new Error("Not a YGO Mobile deck URI");
203
+ }
204
+ let encoded = url.searchParams.get(QUERY_DECK);
205
+ if (!encoded)
206
+ throw new Error("Missing deck data");
207
+ const bytes = fromBase64Url(encoded);
208
+ const bits = Array.from(bytes).map((b) => b.toString(2).padStart(8, "0")).join("");
209
+ const mNum = parseInt(bits.slice(0, 8), 2);
210
+ const eNum = parseInt(bits.slice(8, 12), 2);
211
+ const sNum = parseInt(bits.slice(12, 16), 2);
212
+ const all = mNum + eNum + sNum;
213
+ const cards = [];
214
+ let pos = 16;
215
+ const res = {
216
+ main: [],
217
+ extra: [],
218
+ side: []
219
+ };
220
+ let i = 0;
221
+ while (pos + 29 <= bits.length && cards.length < all) {
222
+ const countBits = bits.slice(pos, pos + 2);
223
+ const count = countBits === "10" ? 2 : countBits === "11" ? 3 : 1;
224
+ const id = parseInt(bits.slice(pos + 2, pos + 29), 2);
225
+ const field = i < mNum ? "main" : i < mNum + eNum ? "extra" : "side";
226
+ res[field].push(...Array(count).fill(id));
227
+ pos += 29;
228
+ i++;
229
+ }
230
+ return {
231
+ ...res,
232
+ name: url.searchParams.get(QUERY_NAME)
233
+ };
234
+ }
235
+
75
236
  // index.ts
76
- var import_js_base64 = require("js-base64");
77
237
  var YGOProDeck = class {
78
238
  constructor() {
79
239
  this.main = [];
@@ -102,7 +262,7 @@ var YGOProDeck = class {
102
262
  return writer.buffer;
103
263
  }
104
264
  toEncodedString() {
105
- return import_js_base64.Base64.fromUint8Array(this.toUint8Array(), true);
265
+ return toBase64Url(this.toUint8Array());
106
266
  }
107
267
  toString() {
108
268
  return this.toEncodedString();
@@ -124,7 +284,7 @@ var YGOProDeck = class {
124
284
  return new YGOProDeck().fromUint8Array(buf);
125
285
  }
126
286
  fromEncodedString(str) {
127
- return this.fromUint8Array(import_js_base64.Base64.toUint8Array(str));
287
+ return this.fromUint8Array(fromBase64Url(str));
128
288
  }
129
289
  static fromEncodedString(str) {
130
290
  return new YGOProDeck().fromEncodedString(str);
@@ -169,6 +329,39 @@ var YGOProDeck = class {
169
329
  cards.forEach((id) => writer.writeUint32LE(id));
170
330
  return writer.buffer;
171
331
  }
332
+ fromYGOMobileDeckURL(uri) {
333
+ const parsed = fromYGOMobileDeckURL(uri);
334
+ this.main = parsed.main;
335
+ this.extra = parsed.extra;
336
+ this.side = parsed.side;
337
+ this.name = parsed.name;
338
+ return this;
339
+ }
340
+ static fromYGOMobileDeckURL(uri) {
341
+ return new YGOProDeck().fromYGOMobileDeckURL(uri);
342
+ }
343
+ toYGOMobileDeckURL() {
344
+ return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {
345
+ name: this.name
346
+ });
347
+ }
348
+ fromYdkeURL(uri) {
349
+ const parsed = fromYdkeURL(uri);
350
+ this.main = parsed.main;
351
+ this.extra = parsed.extra;
352
+ this.side = parsed.side;
353
+ return this;
354
+ }
355
+ static fromYdkeURL(uri) {
356
+ return new YGOProDeck().fromYdkeURL(uri);
357
+ }
358
+ toYdkeURL() {
359
+ return toYdkeURL({
360
+ main: this.main,
361
+ extra: this.extra,
362
+ side: this.side
363
+ });
364
+ }
172
365
  };
173
366
  // Annotate the CommonJS export names for ESM import in node:
174
367
  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": "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",
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 { 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 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}\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", "// 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": "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",
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;
@@ -14,4 +15,10 @@ export default class YGOProDeck {
14
15
  fromYdkString(str: string): this;
15
16
  static fromYdkString(str: string): YGOProDeck;
16
17
  toUpdateDeckPayload(): Uint8Array;
18
+ fromYGOMobileDeckURL(uri: string): YGOProDeck;
19
+ static fromYGOMobileDeckURL(uri: string): YGOProDeck;
20
+ toYGOMobileDeckURL(): string;
21
+ fromYdkeURL(uri: string): YGOProDeck;
22
+ static fromYdkeURL(uri: string): YGOProDeck;
23
+ toYdkeURL(): string;
17
24
  }
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();
@@ -48,12 +67,154 @@ var BufferWriter = class {
48
67
  }
49
68
  };
50
69
 
70
+ // src/ydke.ts
71
+ function base64ToUint32Array(base64) {
72
+ const binary = atob(base64);
73
+ const bytes = new Uint8Array(binary.length);
74
+ for (let i = 0; i < binary.length; i++) {
75
+ bytes[i] = binary.charCodeAt(i);
76
+ }
77
+ const view = new DataView(bytes.buffer);
78
+ const result = [];
79
+ for (let i = 0; i < bytes.length; i += 4) {
80
+ result.push(view.getUint32(i, true));
81
+ }
82
+ return result;
83
+ }
84
+ function uint32ArrayToBase64(data) {
85
+ const buffer = new ArrayBuffer(data.length * 4);
86
+ const view = new DataView(buffer);
87
+ data.forEach((val, i) => view.setUint32(i * 4, val, true));
88
+ const bytes = new Uint8Array(buffer);
89
+ let binary = "";
90
+ for (let i = 0; i < bytes.length; i++) {
91
+ binary += String.fromCharCode(bytes[i]);
92
+ }
93
+ return btoa(binary);
94
+ }
95
+ function toYdkeURL(deck) {
96
+ return "ydke://" + uint32ArrayToBase64(deck.main) + "!" + uint32ArrayToBase64(deck.extra) + "!" + uint32ArrayToBase64(deck.side) + "!";
97
+ }
98
+ function fromYdkeURL(ydke) {
99
+ if (!ydke.startsWith("ydke://")) {
100
+ throw new Error("Invalid ydke:// URI");
101
+ }
102
+ const [mainStr, extraStr, sideStr] = ydke.slice(7).split("!");
103
+ if (mainStr === void 0 || extraStr === void 0 || sideStr === void 0) {
104
+ throw new Error("Incomplete ydke:// URI");
105
+ }
106
+ return {
107
+ main: base64ToUint32Array(mainStr),
108
+ extra: base64ToUint32Array(extraStr),
109
+ side: base64ToUint32Array(sideStr)
110
+ };
111
+ }
112
+
113
+ // src/ygom.ts
114
+ var QUERY_YGO_TYPE = "ygotype";
115
+ var QUERY_VERSION = "v";
116
+ var ARG_DECK = "deck";
117
+ var QUERY_DECK = "d";
118
+ var QUERY_NAME = "name";
119
+ var URL_SCHEME_HTTP = "http";
120
+ var URL_HOST_DECK = "deck.ourygo.top";
121
+ function toBinary(value, length) {
122
+ return value.toString(2).padStart(length, "0");
123
+ }
124
+ function encodeCards(cards) {
125
+ const bits = [];
126
+ for (let i = 0; i < cards.length; ) {
127
+ const id = cards[i];
128
+ let count = 1;
129
+ while (i + count < cards.length && cards[i + count] === id && count < 3)
130
+ count++;
131
+ const prefix = count === 2 ? "10" : count === 3 ? "11" : "01";
132
+ bits.push(prefix + toBinary(id, 27));
133
+ i += count;
134
+ }
135
+ return bits.join("");
136
+ }
137
+ function countUnique(cards) {
138
+ let num = 0;
139
+ for (let i = 0; i < cards.length; i++) {
140
+ const id = cards[i];
141
+ if (id > 0) {
142
+ num++;
143
+ if (i < cards.length - 1 && cards[i + 1] === id) {
144
+ i++;
145
+ if (i < cards.length - 1 && cards[i + 1] === id) {
146
+ i++;
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return num;
152
+ }
153
+ function toYGOMobileDeckURL(main, extra, side, customParams = {}) {
154
+ const mNum = countUnique(main);
155
+ const eNum = countUnique(extra);
156
+ const sNum = countUnique(side);
157
+ const header = toBinary(mNum, 8) + toBinary(eNum, 4) + toBinary(sNum, 4);
158
+ let bitString = header + encodeCards(main) + encodeCards(extra) + encodeCards(side);
159
+ while (bitString.length % 8 !== 0)
160
+ bitString += "0";
161
+ const bytes = new Uint8Array(bitString.length / 8);
162
+ for (let i = 0; i < bytes.length; i++) {
163
+ bytes[i] = parseInt(bitString.slice(i * 8, i * 8 + 8), 2);
164
+ }
165
+ let encoded = toBase64Url(bytes);
166
+ const searchParams = new URLSearchParams();
167
+ for (const [key, value] of Object.entries(customParams)) {
168
+ searchParams.set(key, value);
169
+ }
170
+ searchParams.set(QUERY_YGO_TYPE, ARG_DECK);
171
+ searchParams.set(QUERY_VERSION, "1");
172
+ searchParams.set(QUERY_DECK, encoded);
173
+ return `${URL_SCHEME_HTTP}://${URL_HOST_DECK}?${searchParams.toString()}`;
174
+ }
175
+ function fromYGOMobileDeckURL(uri) {
176
+ const url = new URL(uri);
177
+ if (url.searchParams.get(QUERY_YGO_TYPE) !== ARG_DECK) {
178
+ throw new Error("Not a YGO Mobile deck URI");
179
+ }
180
+ let encoded = url.searchParams.get(QUERY_DECK);
181
+ if (!encoded)
182
+ throw new Error("Missing deck data");
183
+ const bytes = fromBase64Url(encoded);
184
+ const bits = Array.from(bytes).map((b) => b.toString(2).padStart(8, "0")).join("");
185
+ const mNum = parseInt(bits.slice(0, 8), 2);
186
+ const eNum = parseInt(bits.slice(8, 12), 2);
187
+ const sNum = parseInt(bits.slice(12, 16), 2);
188
+ const all = mNum + eNum + sNum;
189
+ const cards = [];
190
+ let pos = 16;
191
+ const res = {
192
+ main: [],
193
+ extra: [],
194
+ side: []
195
+ };
196
+ let i = 0;
197
+ while (pos + 29 <= bits.length && cards.length < all) {
198
+ const countBits = bits.slice(pos, pos + 2);
199
+ const count = countBits === "10" ? 2 : countBits === "11" ? 3 : 1;
200
+ const id = parseInt(bits.slice(pos + 2, pos + 29), 2);
201
+ const field = i < mNum ? "main" : i < mNum + eNum ? "extra" : "side";
202
+ res[field].push(...Array(count).fill(id));
203
+ pos += 29;
204
+ i++;
205
+ }
206
+ return {
207
+ ...res,
208
+ name: url.searchParams.get(QUERY_NAME)
209
+ };
210
+ }
211
+
51
212
  // index.ts
52
- import { Base64 } from "js-base64";
53
213
  var YGOProDeck = class {
54
214
  main = [];
55
215
  extra = [];
56
216
  side = [];
217
+ name;
57
218
  bufferLength() {
58
219
  const counted = [this.main, this.extra, this.side].map(countItems);
59
220
  return counted.reduce((a, b) => a + b.size * 4, 0);
@@ -76,7 +237,7 @@ var YGOProDeck = class {
76
237
  return writer.buffer;
77
238
  }
78
239
  toEncodedString() {
79
- return Base64.fromUint8Array(this.toUint8Array(), true);
240
+ return toBase64Url(this.toUint8Array());
80
241
  }
81
242
  toString() {
82
243
  return this.toEncodedString();
@@ -98,7 +259,7 @@ var YGOProDeck = class {
98
259
  return new YGOProDeck().fromUint8Array(buf);
99
260
  }
100
261
  fromEncodedString(str) {
101
- return this.fromUint8Array(Base64.toUint8Array(str));
262
+ return this.fromUint8Array(fromBase64Url(str));
102
263
  }
103
264
  static fromEncodedString(str) {
104
265
  return new YGOProDeck().fromEncodedString(str);
@@ -143,6 +304,39 @@ var YGOProDeck = class {
143
304
  cards.forEach((id) => writer.writeUint32LE(id));
144
305
  return writer.buffer;
145
306
  }
307
+ fromYGOMobileDeckURL(uri) {
308
+ const parsed = fromYGOMobileDeckURL(uri);
309
+ this.main = parsed.main;
310
+ this.extra = parsed.extra;
311
+ this.side = parsed.side;
312
+ this.name = parsed.name;
313
+ return this;
314
+ }
315
+ static fromYGOMobileDeckURL(uri) {
316
+ return new YGOProDeck().fromYGOMobileDeckURL(uri);
317
+ }
318
+ toYGOMobileDeckURL() {
319
+ return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {
320
+ name: this.name
321
+ });
322
+ }
323
+ fromYdkeURL(uri) {
324
+ const parsed = fromYdkeURL(uri);
325
+ this.main = parsed.main;
326
+ this.extra = parsed.extra;
327
+ this.side = parsed.side;
328
+ return this;
329
+ }
330
+ static fromYdkeURL(uri) {
331
+ return new YGOProDeck().fromYdkeURL(uri);
332
+ }
333
+ toYdkeURL() {
334
+ return toYdkeURL({
335
+ main: this.main,
336
+ extra: this.extra,
337
+ side: this.side
338
+ });
339
+ }
146
340
  };
147
341
  export {
148
342
  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": "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",
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}\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", "// 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 { 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 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;
@@ -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 { fromBase64Url, toBase64Url } from './src/base64';
1
2
  import { BufferWriter, countItems } from './src/utils';
2
- import { Base64 } from 'js-base64';
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) {
@@ -110,4 +113,43 @@ export default class YGOProDeck {
110
113
  cards.forEach((id) => writer.writeUint32LE(id));
111
114
  return writer.buffer;
112
115
  }
116
+
117
+ fromYGOMobileDeckURL(uri: string): YGOProDeck {
118
+ const parsed = fromYGOMobileDeckURL(uri);
119
+ this.main = parsed.main;
120
+ this.extra = parsed.extra;
121
+ this.side = parsed.side;
122
+ this.name = parsed.name;
123
+ return this;
124
+ }
125
+
126
+ static fromYGOMobileDeckURL(uri: string): YGOProDeck {
127
+ return new YGOProDeck().fromYGOMobileDeckURL(uri);
128
+ }
129
+
130
+ toYGOMobileDeckURL(): string {
131
+ return toYGOMobileDeckURL(this.main, this.extra, this.side, this.name && {
132
+ name: this.name,
133
+ });
134
+ }
135
+
136
+ fromYdkeURL(uri: string): YGOProDeck {
137
+ const parsed = fromYdkeURL(uri);
138
+ this.main = parsed.main;
139
+ this.extra = parsed.extra;
140
+ this.side = parsed.side;
141
+ return this;
142
+ }
143
+
144
+ static fromYdkeURL(uri: string): YGOProDeck {
145
+ return new YGOProDeck().fromYdkeURL(uri);
146
+ }
147
+
148
+ toYdkeURL(): string {
149
+ return toYdkeURL({
150
+ main: this.main,
151
+ extra: this.extra,
152
+ side: this.side,
153
+ });
154
+ }
113
155
  }
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.6",
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
  }