rotur-sdk 1.0.11 → 1.1.0

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/dist/index.d.mts CHANGED
@@ -1200,4 +1200,34 @@ declare class AuthError extends Error {
1200
1200
  }
1201
1201
  declare function performAuth(options?: AuthOptions): Promise<AuthResult>;
1202
1202
 
1203
- export { type Activity, type ActivityApplication, type ActivityMedia, type AdminCosmeticCreate, type AdminCosmeticUpdate, ApiError, AuthError, type AuthOptions, type AuthResult, type Badge, type CheckAuthResponse, type CheckAuthResponseFull, type CheckBannedResponse, type CosmeticCatalogEntryPublic, type CosmeticItem, type CosmeticPurchaseResult, type EconomyStats, type ErrorResponse, type EscrowReleaseResult, type EscrowTransferResult, type ExistsResponse, type FileEntry, type FileUsageResponse, type FollowResponse, type FriendActionResponse, type GiftCancelResponse, type GiftClaimResponse, type GiftCreateResponse, type GiftNet, type GiftPublic, type GroupAnnouncement, type GroupEvent, type GroupMessageResponse, type GroupPublic, type GroupRepresentResponse, type GroupRole, type GroupTip, type ItemBuyResponse, type ItemDeleteResponse, type ItemSellResponse, type ItemSetPriceResponse, type ItemStopSellingResponse, type ItemTransferResponse, type JoinPolicy, type KeyBuyResponse, type KeyCancelSubscriptionResponse, type KeyCheckResponse, type KeyCreateResponse, type KeyPublic, type KeyStatusResponse, type KeySubscription, type KeyUserData, type LimitsResponse, type MeDeleteAccountResponse, type MeDeleteKeyResponse, type MeTransferResponse, type MeUpdateResponse, type MyCosmeticsResponse, type NetItem, type NetKey, type NetPost, type NetReply, type NetTransferHistory, type NotificationEntry, type NotifyAllowedSender, type NotifyEndpoint, type NotifyLogEntry, type PermissionGroup, type PostDeleteResponse, type PostPinResponse, type PostRateResponse, type Presence, type PushAllowSenderResponse, type PushCheckResponse, type PushDeleteDeviceResponse, type PushRegisterResponse, type PushSendManyResponse, type PushSendResponse, type RoomMember, Rotur, RoturSocket, type ShopResponse, type StandingHistoryEntry, type StandingInfo, type StandingLevel, type SubTokenCreate, type SubTokenPublic, type System, type SystemUpdateResponse, type TokenAbilities, type TokenActivityResponse, type TokenDeleteResponse, type TokenPermission, type TokenRenameResponse, type TokenRevokeResponse, type Transaction, type UserId, type UserProfile, type UserStats, type UserStatusResponse, type Username, type ValidatorGenerateResult, type ValidatorResult, type WSMessage$1 as WSMessage, performAuth };
1203
+ type IconResolver = (name: string) => string | undefined;
1204
+ interface IconToSvgOptions {
1205
+ /** Overall scale factor applied to all coordinates (default: 1). */
1206
+ size?: number;
1207
+ /**
1208
+ * Half-extent of the SVG viewBox — the icon is centred at 0,0.
1209
+ * Defaults to `size * 20`.
1210
+ */
1211
+ viewSize?: number;
1212
+ /** Initial stroke colour (default: "#ffffff"). */
1213
+ color?: string;
1214
+ /** Initial stroke width in unscaled icon units (default: 1). */
1215
+ strokeWidth?: number;
1216
+ /**
1217
+ * Boldness multiplier applied to every `w` command: `w_final = |w_arg × size| × (boldness + 1)`.
1218
+ * Matches the `p6` parameter from the original renderer (default: 0 → no extra boldness).
1219
+ */
1220
+ boldness?: number;
1221
+ /**
1222
+ * Overall rotation of the icon in degrees, measured clockwise from up (north).
1223
+ * Matches Scratch's direction convention: 90° = right (default: 90, i.e. no rotation).
1224
+ */
1225
+ direction?: number;
1226
+ /** Resolve named sub-icons for the `icn` command. */
1227
+ resolver?: IconResolver;
1228
+ /** Extra attributes written onto the root `<svg>` element. */
1229
+ svgAttrs?: Record<string, string>;
1230
+ }
1231
+ declare function iconToSvg(iconString: string, options?: IconToSvgOptions): string;
1232
+
1233
+ export { type Activity, type ActivityApplication, type ActivityMedia, type AdminCosmeticCreate, type AdminCosmeticUpdate, ApiError, AuthError, type AuthOptions, type AuthResult, type Badge, type CheckAuthResponse, type CheckAuthResponseFull, type CheckBannedResponse, type CosmeticCatalogEntryPublic, type CosmeticItem, type CosmeticPurchaseResult, type EconomyStats, type ErrorResponse, type EscrowReleaseResult, type EscrowTransferResult, type ExistsResponse, type FileEntry, type FileUsageResponse, type FollowResponse, type FriendActionResponse, type GiftCancelResponse, type GiftClaimResponse, type GiftCreateResponse, type GiftNet, type GiftPublic, type GroupAnnouncement, type GroupEvent, type GroupMessageResponse, type GroupPublic, type GroupRepresentResponse, type GroupRole, type GroupTip, type ItemBuyResponse, type ItemDeleteResponse, type ItemSellResponse, type ItemSetPriceResponse, type ItemStopSellingResponse, type ItemTransferResponse, type JoinPolicy, type KeyBuyResponse, type KeyCancelSubscriptionResponse, type KeyCheckResponse, type KeyCreateResponse, type KeyPublic, type KeyStatusResponse, type KeySubscription, type KeyUserData, type LimitsResponse, type MeDeleteAccountResponse, type MeDeleteKeyResponse, type MeTransferResponse, type MeUpdateResponse, type MyCosmeticsResponse, type NetItem, type NetKey, type NetPost, type NetReply, type NetTransferHistory, type NotificationEntry, type NotifyAllowedSender, type NotifyEndpoint, type NotifyLogEntry, type PermissionGroup, type PostDeleteResponse, type PostPinResponse, type PostRateResponse, type Presence, type PushAllowSenderResponse, type PushCheckResponse, type PushDeleteDeviceResponse, type PushRegisterResponse, type PushSendManyResponse, type PushSendResponse, type RoomMember, Rotur, RoturSocket, type ShopResponse, type StandingHistoryEntry, type StandingInfo, type StandingLevel, type SubTokenCreate, type SubTokenPublic, type System, type SystemUpdateResponse, type TokenAbilities, type TokenActivityResponse, type TokenDeleteResponse, type TokenPermission, type TokenRenameResponse, type TokenRevokeResponse, type Transaction, type UserId, type UserProfile, type UserStats, type UserStatusResponse, type Username, type ValidatorGenerateResult, type ValidatorResult, type WSMessage$1 as WSMessage, iconToSvg, performAuth };
package/dist/index.d.ts CHANGED
@@ -1200,4 +1200,34 @@ declare class AuthError extends Error {
1200
1200
  }
1201
1201
  declare function performAuth(options?: AuthOptions): Promise<AuthResult>;
1202
1202
 
1203
- export { type Activity, type ActivityApplication, type ActivityMedia, type AdminCosmeticCreate, type AdminCosmeticUpdate, ApiError, AuthError, type AuthOptions, type AuthResult, type Badge, type CheckAuthResponse, type CheckAuthResponseFull, type CheckBannedResponse, type CosmeticCatalogEntryPublic, type CosmeticItem, type CosmeticPurchaseResult, type EconomyStats, type ErrorResponse, type EscrowReleaseResult, type EscrowTransferResult, type ExistsResponse, type FileEntry, type FileUsageResponse, type FollowResponse, type FriendActionResponse, type GiftCancelResponse, type GiftClaimResponse, type GiftCreateResponse, type GiftNet, type GiftPublic, type GroupAnnouncement, type GroupEvent, type GroupMessageResponse, type GroupPublic, type GroupRepresentResponse, type GroupRole, type GroupTip, type ItemBuyResponse, type ItemDeleteResponse, type ItemSellResponse, type ItemSetPriceResponse, type ItemStopSellingResponse, type ItemTransferResponse, type JoinPolicy, type KeyBuyResponse, type KeyCancelSubscriptionResponse, type KeyCheckResponse, type KeyCreateResponse, type KeyPublic, type KeyStatusResponse, type KeySubscription, type KeyUserData, type LimitsResponse, type MeDeleteAccountResponse, type MeDeleteKeyResponse, type MeTransferResponse, type MeUpdateResponse, type MyCosmeticsResponse, type NetItem, type NetKey, type NetPost, type NetReply, type NetTransferHistory, type NotificationEntry, type NotifyAllowedSender, type NotifyEndpoint, type NotifyLogEntry, type PermissionGroup, type PostDeleteResponse, type PostPinResponse, type PostRateResponse, type Presence, type PushAllowSenderResponse, type PushCheckResponse, type PushDeleteDeviceResponse, type PushRegisterResponse, type PushSendManyResponse, type PushSendResponse, type RoomMember, Rotur, RoturSocket, type ShopResponse, type StandingHistoryEntry, type StandingInfo, type StandingLevel, type SubTokenCreate, type SubTokenPublic, type System, type SystemUpdateResponse, type TokenAbilities, type TokenActivityResponse, type TokenDeleteResponse, type TokenPermission, type TokenRenameResponse, type TokenRevokeResponse, type Transaction, type UserId, type UserProfile, type UserStats, type UserStatusResponse, type Username, type ValidatorGenerateResult, type ValidatorResult, type WSMessage$1 as WSMessage, performAuth };
1203
+ type IconResolver = (name: string) => string | undefined;
1204
+ interface IconToSvgOptions {
1205
+ /** Overall scale factor applied to all coordinates (default: 1). */
1206
+ size?: number;
1207
+ /**
1208
+ * Half-extent of the SVG viewBox — the icon is centred at 0,0.
1209
+ * Defaults to `size * 20`.
1210
+ */
1211
+ viewSize?: number;
1212
+ /** Initial stroke colour (default: "#ffffff"). */
1213
+ color?: string;
1214
+ /** Initial stroke width in unscaled icon units (default: 1). */
1215
+ strokeWidth?: number;
1216
+ /**
1217
+ * Boldness multiplier applied to every `w` command: `w_final = |w_arg × size| × (boldness + 1)`.
1218
+ * Matches the `p6` parameter from the original renderer (default: 0 → no extra boldness).
1219
+ */
1220
+ boldness?: number;
1221
+ /**
1222
+ * Overall rotation of the icon in degrees, measured clockwise from up (north).
1223
+ * Matches Scratch's direction convention: 90° = right (default: 90, i.e. no rotation).
1224
+ */
1225
+ direction?: number;
1226
+ /** Resolve named sub-icons for the `icn` command. */
1227
+ resolver?: IconResolver;
1228
+ /** Extra attributes written onto the root `<svg>` element. */
1229
+ svgAttrs?: Record<string, string>;
1230
+ }
1231
+ declare function iconToSvg(iconString: string, options?: IconToSvgOptions): string;
1232
+
1233
+ export { type Activity, type ActivityApplication, type ActivityMedia, type AdminCosmeticCreate, type AdminCosmeticUpdate, ApiError, AuthError, type AuthOptions, type AuthResult, type Badge, type CheckAuthResponse, type CheckAuthResponseFull, type CheckBannedResponse, type CosmeticCatalogEntryPublic, type CosmeticItem, type CosmeticPurchaseResult, type EconomyStats, type ErrorResponse, type EscrowReleaseResult, type EscrowTransferResult, type ExistsResponse, type FileEntry, type FileUsageResponse, type FollowResponse, type FriendActionResponse, type GiftCancelResponse, type GiftClaimResponse, type GiftCreateResponse, type GiftNet, type GiftPublic, type GroupAnnouncement, type GroupEvent, type GroupMessageResponse, type GroupPublic, type GroupRepresentResponse, type GroupRole, type GroupTip, type ItemBuyResponse, type ItemDeleteResponse, type ItemSellResponse, type ItemSetPriceResponse, type ItemStopSellingResponse, type ItemTransferResponse, type JoinPolicy, type KeyBuyResponse, type KeyCancelSubscriptionResponse, type KeyCheckResponse, type KeyCreateResponse, type KeyPublic, type KeyStatusResponse, type KeySubscription, type KeyUserData, type LimitsResponse, type MeDeleteAccountResponse, type MeDeleteKeyResponse, type MeTransferResponse, type MeUpdateResponse, type MyCosmeticsResponse, type NetItem, type NetKey, type NetPost, type NetReply, type NetTransferHistory, type NotificationEntry, type NotifyAllowedSender, type NotifyEndpoint, type NotifyLogEntry, type PermissionGroup, type PostDeleteResponse, type PostPinResponse, type PostRateResponse, type Presence, type PushAllowSenderResponse, type PushCheckResponse, type PushDeleteDeviceResponse, type PushRegisterResponse, type PushSendManyResponse, type PushSendResponse, type RoomMember, Rotur, RoturSocket, type ShopResponse, type StandingHistoryEntry, type StandingInfo, type StandingLevel, type SubTokenCreate, type SubTokenPublic, type System, type SystemUpdateResponse, type TokenAbilities, type TokenActivityResponse, type TokenDeleteResponse, type TokenPermission, type TokenRenameResponse, type TokenRevokeResponse, type Transaction, type UserId, type UserProfile, type UserStats, type UserStatusResponse, type Username, type ValidatorGenerateResult, type ValidatorResult, type WSMessage$1 as WSMessage, iconToSvg, performAuth };
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ __export(index_exports, {
24
24
  AuthError: () => AuthError,
25
25
  Rotur: () => Rotur,
26
26
  RoturSocket: () => RoturSocket,
27
+ iconToSvg: () => iconToSvg,
27
28
  performAuth: () => performAuth
28
29
  });
29
30
  module.exports = __toCommonJS(index_exports);
@@ -355,6 +356,11 @@ function performAuth(options) {
355
356
  const authUrl = new URL(AUTH_URL);
356
357
  if (options?.system) authUrl.searchParams.set("system", options.system);
357
358
  let iframe;
359
+ const w = window.open(
360
+ authUrl.toString(),
361
+ "rotur-auth",
362
+ "width=480,height=720"
363
+ );
358
364
  return new Promise((resolve, reject) => {
359
365
  const signal = options?.signal;
360
366
  const rejectWithError = (code, msg) => {
@@ -378,13 +384,12 @@ function performAuth(options) {
378
384
  window.removeEventListener("message", handler);
379
385
  signal?.removeEventListener("abort", onAbort);
380
386
  iframe?.remove();
387
+ try {
388
+ w?.close();
389
+ } catch {
390
+ }
381
391
  }
382
392
  window.addEventListener("message", handler);
383
- const w = window.open(
384
- authUrl.toString(),
385
- "rotur-auth",
386
- "width=480,height=720"
387
- );
388
393
  if (w) return;
389
394
  iframe = document.createElement("iframe");
390
395
  iframe.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:none;z-index:9999";
@@ -1138,11 +1143,279 @@ var CheckNamespace = class extends Namespace {
1138
1143
  return this.$post("/check/banned", usernames.join(","));
1139
1144
  }
1140
1145
  };
1146
+
1147
+ // src/icon.ts
1148
+ function dp(n2) {
1149
+ return (Math.round(n2 * 1e4) / 1e4).toString();
1150
+ }
1151
+ var n = (v) => +v || 0;
1152
+ function rotateVec(x, y, angleDeg) {
1153
+ const rad = angleDeg * Math.PI / 180;
1154
+ return [
1155
+ x * Math.cos(rad) - y * Math.sin(rad),
1156
+ x * Math.sin(rad) + y * Math.cos(rad)
1157
+ ];
1158
+ }
1159
+ function tokenise(src) {
1160
+ if (Array.isArray(src)) return src.map(String);
1161
+ return String(src).trim().split(/[ \n\t]+/g).filter(Boolean);
1162
+ }
1163
+ function renderTokens(tokens, ox, oy, boldness, state, resolver, out) {
1164
+ let i = 0;
1165
+ const next = () => tokens[++i] ?? "0";
1166
+ const toSVG = (lx, ly) => {
1167
+ const wx = state.offx + lx;
1168
+ const wy = state.offy + ly;
1169
+ return [ox + wx * state.size, oy - wy * state.size];
1170
+ };
1171
+ while (i < tokens.length) {
1172
+ const op = tokens[i];
1173
+ switch (op) {
1174
+ case "c":
1175
+ state.color = next();
1176
+ break;
1177
+ case "w": {
1178
+ const wArg = n(next());
1179
+ state.strokeWidth = Math.abs(wArg * state.size) * (boldness + 1);
1180
+ break;
1181
+ }
1182
+ case "line": {
1183
+ const [ax, ay] = toSVG(n(next()), n(next()));
1184
+ const [bx, by] = toSVG(n(next()), n(next()));
1185
+ out.push(
1186
+ `<line x1="${dp(ax)}" y1="${dp(ay)}" x2="${dp(bx)}" y2="${dp(by)}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" stroke-linecap="round"/>`
1187
+ );
1188
+ state.penX = bx;
1189
+ state.penY = by;
1190
+ break;
1191
+ }
1192
+ case "cont": {
1193
+ const [bx, by] = toSVG(n(next()), n(next()));
1194
+ out.push(
1195
+ `<line x1="${dp(state.penX)}" y1="${dp(state.penY)}" x2="${dp(bx)}" y2="${dp(by)}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" stroke-linecap="round"/>`
1196
+ );
1197
+ state.penX = bx;
1198
+ state.penY = by;
1199
+ break;
1200
+ }
1201
+ case "dot": {
1202
+ const [cx, cy] = toSVG(n(next()), n(next()));
1203
+ out.push(
1204
+ `<circle cx="${dp(cx)}" cy="${dp(cy)}" r="${dp(state.strokeWidth / 2)}" fill="${state.color}"/>`
1205
+ );
1206
+ break;
1207
+ }
1208
+ case "move":
1209
+ state.offx += n(next());
1210
+ state.offy += n(next());
1211
+ break;
1212
+ case "back":
1213
+ state.offx = 0;
1214
+ state.offy = 0;
1215
+ break;
1216
+ case "scale":
1217
+ state.size *= n(next());
1218
+ break;
1219
+ case "rect": {
1220
+ const cx = n(next()), cy = n(next());
1221
+ const hw = n(next()), hh = n(next());
1222
+ const [lx, ty] = toSVG(cx - hw, cy + hh);
1223
+ const [rx, by] = toSVG(cx + hw, cy - hh);
1224
+ const w = Math.abs(rx - lx), h = Math.abs(by - ty);
1225
+ const x = Math.min(lx, rx), y = Math.min(ty, by);
1226
+ out.push(`<rect x="${dp(x)}" y="${dp(y)}" width="${dp(w)}" height="${dp(h)}" fill="${state.color}"/>`);
1227
+ break;
1228
+ }
1229
+ case "square": {
1230
+ const cx = n(next()), cy = n(next());
1231
+ const hw = n(next()), hh = n(next());
1232
+ const corners = [
1233
+ toSVG(cx + hw, cy + hh),
1234
+ toSVG(cx - hw, cy + hh),
1235
+ toSVG(cx - hw, cy - hh),
1236
+ toSVG(cx + hw, cy - hh)
1237
+ ];
1238
+ const pts = [...corners, corners[0]].map((vals) => `${dp(vals[0])},${dp(vals[1])}`).join(" ");
1239
+ out.push(
1240
+ `<polyline points="${pts}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" stroke-linejoin="round" stroke-linecap="round" fill="none"/>`
1241
+ );
1242
+ break;
1243
+ }
1244
+ case "tri": {
1245
+ const [x1, y1] = toSVG(n(next()), n(next()));
1246
+ const [x2, y2] = toSVG(n(next()), n(next()));
1247
+ const [x3, y3] = toSVG(n(next()), n(next()));
1248
+ out.push(
1249
+ `<polygon points="${dp(x1)},${dp(y1)} ${dp(x2)},${dp(y2)} ${dp(x3)},${dp(y3)}" fill="${state.color}"/>`
1250
+ );
1251
+ break;
1252
+ }
1253
+ case "cutcircle": {
1254
+ const cx = n(next()), cy = n(next());
1255
+ const radius = n(next());
1256
+ const dir = n(next());
1257
+ const arcDeg = n(next());
1258
+ let angleDeg = dir * 10 - arcDeg;
1259
+ const steps = Math.floor(arcDeg / 3);
1260
+ const pts = [];
1261
+ {
1262
+ const px = cx + Math.round(Math.sin(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1263
+ const py = cy + Math.round(Math.cos(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1264
+ const [sx, sy] = toSVG(px, py);
1265
+ pts.push(`M${dp(sx)},${dp(sy)}`);
1266
+ }
1267
+ for (let a = steps; a >= 0.5; a--) {
1268
+ angleDeg += 6;
1269
+ const px = cx + Math.round(Math.sin(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1270
+ const py = cy + Math.round(Math.cos(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1271
+ const [sx, sy] = toSVG(px, py);
1272
+ pts.push(`L${dp(sx)},${dp(sy)}`);
1273
+ }
1274
+ out.push(
1275
+ `<path d="${pts.join("")}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`
1276
+ );
1277
+ break;
1278
+ }
1279
+ case "ellipse": {
1280
+ const elCx = n(next()), elCy = n(next());
1281
+ const rx = n(next());
1282
+ const mult = n(next());
1283
+ const rot = n(next());
1284
+ const ry = rx * mult;
1285
+ const [ccx, ccy] = toSVG(elCx, elCy);
1286
+ const ellipseRotDeg = 90 - rot;
1287
+ const pts = [];
1288
+ let eli = 0;
1289
+ {
1290
+ const lx = Math.round(Math.sin(Math.PI * eli / 180) * 1e10) / 1e10 * rx;
1291
+ const ly = Math.round(Math.cos(Math.PI * eli / 180) * 1e10) / 1e10 * rx * mult;
1292
+ const [rx2, ry2] = rotateVec(lx * state.size, ly * state.size, ellipseRotDeg);
1293
+ pts.push(`M${dp(ccx + rx2)},${dp(ccy - ry2)}`);
1294
+ }
1295
+ for (let a = 180; a >= 0.5; a--) {
1296
+ eli += 4;
1297
+ const lx = Math.round(Math.sin(Math.PI * eli / 180) * 1e10) / 1e10 * rx;
1298
+ const ly = Math.round(Math.cos(Math.PI * eli / 180) * 1e10) / 1e10 * rx * mult;
1299
+ const [drx, dry] = rotateVec(lx * state.size, ly * state.size, ellipseRotDeg);
1300
+ pts.push(`L${dp(ccx + drx)},${dp(ccy - dry)}`);
1301
+ }
1302
+ pts.push("Z");
1303
+ out.push(
1304
+ `<path d="${pts.join("")}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" fill="none"/>`
1305
+ );
1306
+ break;
1307
+ }
1308
+ case "curve": {
1309
+ const rawX1 = next();
1310
+ if (rawX1 === "res") break;
1311
+ let x1 = n(rawX1), y1 = n(next());
1312
+ let x2 = n(next()), y2 = n(next());
1313
+ const cpx = n(next()), cpy = n(next());
1314
+ let cx1 = cpx - x1, cy1 = cpy - y1;
1315
+ let cx2 = cpx - x2, cy2 = cpy - y2;
1316
+ x2 = cpx;
1317
+ y2 = cpy;
1318
+ const res = Math.min(1e4, Math.round(state.size * 50));
1319
+ const [startX, startY] = toSVG(x1, y1);
1320
+ const pts = [`M${dp(startX)},${dp(startY)}`];
1321
+ for (let step = 1; step <= res; step++) {
1322
+ x1 += cx1 / res;
1323
+ y1 += cy1 / res;
1324
+ x2 -= cx2 / res;
1325
+ y2 -= cy2 / res;
1326
+ const per = step / res;
1327
+ const midX = (x2 - x1) * per + x1;
1328
+ const midY = (y2 - y1) * per + y1;
1329
+ const [sx, sy] = toSVG(midX, midY);
1330
+ pts.push(`L${dp(sx)},${dp(sy)}`);
1331
+ }
1332
+ out.push(
1333
+ `<path d="${pts.join("")}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`
1334
+ );
1335
+ break;
1336
+ }
1337
+ case "icn": {
1338
+ if (!resolver) {
1339
+ next();
1340
+ next();
1341
+ next();
1342
+ next();
1343
+ break;
1344
+ }
1345
+ const name = next();
1346
+ const subScale = n(next()) * state.size;
1347
+ const subOx = n(next()), subOy = n(next());
1348
+ const resolved = resolver(name);
1349
+ if (resolved !== void 0) {
1350
+ const [sox, soy] = toSVG(subOx, subOy);
1351
+ renderTokens(
1352
+ tokenise(resolved),
1353
+ sox,
1354
+ soy,
1355
+ boldness,
1356
+ { ...state, size: subScale, offx: 0, offy: 0 },
1357
+ resolver,
1358
+ out
1359
+ );
1360
+ }
1361
+ break;
1362
+ }
1363
+ case "ricn": {
1364
+ const inlineStr = next();
1365
+ const subScale = n(next()) * state.size;
1366
+ const subOx = n(next()), subOy = n(next());
1367
+ const [sox, soy] = toSVG(subOx, subOy);
1368
+ renderTokens(
1369
+ tokenise(inlineStr),
1370
+ sox,
1371
+ soy,
1372
+ boldness,
1373
+ { ...state, size: subScale, offx: 0, offy: 0 },
1374
+ resolver,
1375
+ out
1376
+ );
1377
+ break;
1378
+ }
1379
+ }
1380
+ i++;
1381
+ }
1382
+ }
1383
+ function iconToSvg(iconString, options = {}) {
1384
+ const {
1385
+ size = 1,
1386
+ color = "#ffffff",
1387
+ strokeWidth = 1,
1388
+ boldness = 0,
1389
+ resolver,
1390
+ svgAttrs = {}
1391
+ } = options;
1392
+ const viewSize = options.viewSize ?? size * 20;
1393
+ const state = {
1394
+ penX: 0,
1395
+ penY: 0,
1396
+ penDown: false,
1397
+ color,
1398
+ strokeWidth,
1399
+ offx: 0,
1400
+ offy: 0,
1401
+ size
1402
+ };
1403
+ const elements = [];
1404
+ renderTokens(tokenise(iconString), 0, 0, boldness, state, resolver, elements);
1405
+ const vb = `${-viewSize} ${-viewSize} ${viewSize * 2} ${viewSize * 2}`;
1406
+ const attrs = Object.entries(svgAttrs).map(([k, v]) => ` ${k}="${v}"`).join("");
1407
+ return [
1408
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${vb}"${attrs}>`,
1409
+ ...elements,
1410
+ `</svg>`
1411
+ ].join("\n");
1412
+ }
1141
1413
  // Annotate the CommonJS export names for ESM import in node:
1142
1414
  0 && (module.exports = {
1143
1415
  ApiError,
1144
1416
  AuthError,
1145
1417
  Rotur,
1146
1418
  RoturSocket,
1419
+ iconToSvg,
1147
1420
  performAuth
1148
1421
  });
package/dist/index.mjs CHANGED
@@ -325,6 +325,11 @@ function performAuth(options) {
325
325
  const authUrl = new URL(AUTH_URL);
326
326
  if (options?.system) authUrl.searchParams.set("system", options.system);
327
327
  let iframe;
328
+ const w = window.open(
329
+ authUrl.toString(),
330
+ "rotur-auth",
331
+ "width=480,height=720"
332
+ );
328
333
  return new Promise((resolve, reject) => {
329
334
  const signal = options?.signal;
330
335
  const rejectWithError = (code, msg) => {
@@ -348,13 +353,12 @@ function performAuth(options) {
348
353
  window.removeEventListener("message", handler);
349
354
  signal?.removeEventListener("abort", onAbort);
350
355
  iframe?.remove();
356
+ try {
357
+ w?.close();
358
+ } catch {
359
+ }
351
360
  }
352
361
  window.addEventListener("message", handler);
353
- const w = window.open(
354
- authUrl.toString(),
355
- "rotur-auth",
356
- "width=480,height=720"
357
- );
358
362
  if (w) return;
359
363
  iframe = document.createElement("iframe");
360
364
  iframe.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:none;z-index:9999";
@@ -1108,10 +1112,278 @@ var CheckNamespace = class extends Namespace {
1108
1112
  return this.$post("/check/banned", usernames.join(","));
1109
1113
  }
1110
1114
  };
1115
+
1116
+ // src/icon.ts
1117
+ function dp(n2) {
1118
+ return (Math.round(n2 * 1e4) / 1e4).toString();
1119
+ }
1120
+ var n = (v) => +v || 0;
1121
+ function rotateVec(x, y, angleDeg) {
1122
+ const rad = angleDeg * Math.PI / 180;
1123
+ return [
1124
+ x * Math.cos(rad) - y * Math.sin(rad),
1125
+ x * Math.sin(rad) + y * Math.cos(rad)
1126
+ ];
1127
+ }
1128
+ function tokenise(src) {
1129
+ if (Array.isArray(src)) return src.map(String);
1130
+ return String(src).trim().split(/[ \n\t]+/g).filter(Boolean);
1131
+ }
1132
+ function renderTokens(tokens, ox, oy, boldness, state, resolver, out) {
1133
+ let i = 0;
1134
+ const next = () => tokens[++i] ?? "0";
1135
+ const toSVG = (lx, ly) => {
1136
+ const wx = state.offx + lx;
1137
+ const wy = state.offy + ly;
1138
+ return [ox + wx * state.size, oy - wy * state.size];
1139
+ };
1140
+ while (i < tokens.length) {
1141
+ const op = tokens[i];
1142
+ switch (op) {
1143
+ case "c":
1144
+ state.color = next();
1145
+ break;
1146
+ case "w": {
1147
+ const wArg = n(next());
1148
+ state.strokeWidth = Math.abs(wArg * state.size) * (boldness + 1);
1149
+ break;
1150
+ }
1151
+ case "line": {
1152
+ const [ax, ay] = toSVG(n(next()), n(next()));
1153
+ const [bx, by] = toSVG(n(next()), n(next()));
1154
+ out.push(
1155
+ `<line x1="${dp(ax)}" y1="${dp(ay)}" x2="${dp(bx)}" y2="${dp(by)}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" stroke-linecap="round"/>`
1156
+ );
1157
+ state.penX = bx;
1158
+ state.penY = by;
1159
+ break;
1160
+ }
1161
+ case "cont": {
1162
+ const [bx, by] = toSVG(n(next()), n(next()));
1163
+ out.push(
1164
+ `<line x1="${dp(state.penX)}" y1="${dp(state.penY)}" x2="${dp(bx)}" y2="${dp(by)}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" stroke-linecap="round"/>`
1165
+ );
1166
+ state.penX = bx;
1167
+ state.penY = by;
1168
+ break;
1169
+ }
1170
+ case "dot": {
1171
+ const [cx, cy] = toSVG(n(next()), n(next()));
1172
+ out.push(
1173
+ `<circle cx="${dp(cx)}" cy="${dp(cy)}" r="${dp(state.strokeWidth / 2)}" fill="${state.color}"/>`
1174
+ );
1175
+ break;
1176
+ }
1177
+ case "move":
1178
+ state.offx += n(next());
1179
+ state.offy += n(next());
1180
+ break;
1181
+ case "back":
1182
+ state.offx = 0;
1183
+ state.offy = 0;
1184
+ break;
1185
+ case "scale":
1186
+ state.size *= n(next());
1187
+ break;
1188
+ case "rect": {
1189
+ const cx = n(next()), cy = n(next());
1190
+ const hw = n(next()), hh = n(next());
1191
+ const [lx, ty] = toSVG(cx - hw, cy + hh);
1192
+ const [rx, by] = toSVG(cx + hw, cy - hh);
1193
+ const w = Math.abs(rx - lx), h = Math.abs(by - ty);
1194
+ const x = Math.min(lx, rx), y = Math.min(ty, by);
1195
+ out.push(`<rect x="${dp(x)}" y="${dp(y)}" width="${dp(w)}" height="${dp(h)}" fill="${state.color}"/>`);
1196
+ break;
1197
+ }
1198
+ case "square": {
1199
+ const cx = n(next()), cy = n(next());
1200
+ const hw = n(next()), hh = n(next());
1201
+ const corners = [
1202
+ toSVG(cx + hw, cy + hh),
1203
+ toSVG(cx - hw, cy + hh),
1204
+ toSVG(cx - hw, cy - hh),
1205
+ toSVG(cx + hw, cy - hh)
1206
+ ];
1207
+ const pts = [...corners, corners[0]].map((vals) => `${dp(vals[0])},${dp(vals[1])}`).join(" ");
1208
+ out.push(
1209
+ `<polyline points="${pts}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" stroke-linejoin="round" stroke-linecap="round" fill="none"/>`
1210
+ );
1211
+ break;
1212
+ }
1213
+ case "tri": {
1214
+ const [x1, y1] = toSVG(n(next()), n(next()));
1215
+ const [x2, y2] = toSVG(n(next()), n(next()));
1216
+ const [x3, y3] = toSVG(n(next()), n(next()));
1217
+ out.push(
1218
+ `<polygon points="${dp(x1)},${dp(y1)} ${dp(x2)},${dp(y2)} ${dp(x3)},${dp(y3)}" fill="${state.color}"/>`
1219
+ );
1220
+ break;
1221
+ }
1222
+ case "cutcircle": {
1223
+ const cx = n(next()), cy = n(next());
1224
+ const radius = n(next());
1225
+ const dir = n(next());
1226
+ const arcDeg = n(next());
1227
+ let angleDeg = dir * 10 - arcDeg;
1228
+ const steps = Math.floor(arcDeg / 3);
1229
+ const pts = [];
1230
+ {
1231
+ const px = cx + Math.round(Math.sin(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1232
+ const py = cy + Math.round(Math.cos(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1233
+ const [sx, sy] = toSVG(px, py);
1234
+ pts.push(`M${dp(sx)},${dp(sy)}`);
1235
+ }
1236
+ for (let a = steps; a >= 0.5; a--) {
1237
+ angleDeg += 6;
1238
+ const px = cx + Math.round(Math.sin(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1239
+ const py = cy + Math.round(Math.cos(Math.PI * angleDeg / 180) * 1e10) / 1e10 * radius;
1240
+ const [sx, sy] = toSVG(px, py);
1241
+ pts.push(`L${dp(sx)},${dp(sy)}`);
1242
+ }
1243
+ out.push(
1244
+ `<path d="${pts.join("")}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`
1245
+ );
1246
+ break;
1247
+ }
1248
+ case "ellipse": {
1249
+ const elCx = n(next()), elCy = n(next());
1250
+ const rx = n(next());
1251
+ const mult = n(next());
1252
+ const rot = n(next());
1253
+ const ry = rx * mult;
1254
+ const [ccx, ccy] = toSVG(elCx, elCy);
1255
+ const ellipseRotDeg = 90 - rot;
1256
+ const pts = [];
1257
+ let eli = 0;
1258
+ {
1259
+ const lx = Math.round(Math.sin(Math.PI * eli / 180) * 1e10) / 1e10 * rx;
1260
+ const ly = Math.round(Math.cos(Math.PI * eli / 180) * 1e10) / 1e10 * rx * mult;
1261
+ const [rx2, ry2] = rotateVec(lx * state.size, ly * state.size, ellipseRotDeg);
1262
+ pts.push(`M${dp(ccx + rx2)},${dp(ccy - ry2)}`);
1263
+ }
1264
+ for (let a = 180; a >= 0.5; a--) {
1265
+ eli += 4;
1266
+ const lx = Math.round(Math.sin(Math.PI * eli / 180) * 1e10) / 1e10 * rx;
1267
+ const ly = Math.round(Math.cos(Math.PI * eli / 180) * 1e10) / 1e10 * rx * mult;
1268
+ const [drx, dry] = rotateVec(lx * state.size, ly * state.size, ellipseRotDeg);
1269
+ pts.push(`L${dp(ccx + drx)},${dp(ccy - dry)}`);
1270
+ }
1271
+ pts.push("Z");
1272
+ out.push(
1273
+ `<path d="${pts.join("")}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" fill="none"/>`
1274
+ );
1275
+ break;
1276
+ }
1277
+ case "curve": {
1278
+ const rawX1 = next();
1279
+ if (rawX1 === "res") break;
1280
+ let x1 = n(rawX1), y1 = n(next());
1281
+ let x2 = n(next()), y2 = n(next());
1282
+ const cpx = n(next()), cpy = n(next());
1283
+ let cx1 = cpx - x1, cy1 = cpy - y1;
1284
+ let cx2 = cpx - x2, cy2 = cpy - y2;
1285
+ x2 = cpx;
1286
+ y2 = cpy;
1287
+ const res = Math.min(1e4, Math.round(state.size * 50));
1288
+ const [startX, startY] = toSVG(x1, y1);
1289
+ const pts = [`M${dp(startX)},${dp(startY)}`];
1290
+ for (let step = 1; step <= res; step++) {
1291
+ x1 += cx1 / res;
1292
+ y1 += cy1 / res;
1293
+ x2 -= cx2 / res;
1294
+ y2 -= cy2 / res;
1295
+ const per = step / res;
1296
+ const midX = (x2 - x1) * per + x1;
1297
+ const midY = (y2 - y1) * per + y1;
1298
+ const [sx, sy] = toSVG(midX, midY);
1299
+ pts.push(`L${dp(sx)},${dp(sy)}`);
1300
+ }
1301
+ out.push(
1302
+ `<path d="${pts.join("")}" stroke="${state.color}" stroke-width="${dp(state.strokeWidth)}" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`
1303
+ );
1304
+ break;
1305
+ }
1306
+ case "icn": {
1307
+ if (!resolver) {
1308
+ next();
1309
+ next();
1310
+ next();
1311
+ next();
1312
+ break;
1313
+ }
1314
+ const name = next();
1315
+ const subScale = n(next()) * state.size;
1316
+ const subOx = n(next()), subOy = n(next());
1317
+ const resolved = resolver(name);
1318
+ if (resolved !== void 0) {
1319
+ const [sox, soy] = toSVG(subOx, subOy);
1320
+ renderTokens(
1321
+ tokenise(resolved),
1322
+ sox,
1323
+ soy,
1324
+ boldness,
1325
+ { ...state, size: subScale, offx: 0, offy: 0 },
1326
+ resolver,
1327
+ out
1328
+ );
1329
+ }
1330
+ break;
1331
+ }
1332
+ case "ricn": {
1333
+ const inlineStr = next();
1334
+ const subScale = n(next()) * state.size;
1335
+ const subOx = n(next()), subOy = n(next());
1336
+ const [sox, soy] = toSVG(subOx, subOy);
1337
+ renderTokens(
1338
+ tokenise(inlineStr),
1339
+ sox,
1340
+ soy,
1341
+ boldness,
1342
+ { ...state, size: subScale, offx: 0, offy: 0 },
1343
+ resolver,
1344
+ out
1345
+ );
1346
+ break;
1347
+ }
1348
+ }
1349
+ i++;
1350
+ }
1351
+ }
1352
+ function iconToSvg(iconString, options = {}) {
1353
+ const {
1354
+ size = 1,
1355
+ color = "#ffffff",
1356
+ strokeWidth = 1,
1357
+ boldness = 0,
1358
+ resolver,
1359
+ svgAttrs = {}
1360
+ } = options;
1361
+ const viewSize = options.viewSize ?? size * 20;
1362
+ const state = {
1363
+ penX: 0,
1364
+ penY: 0,
1365
+ penDown: false,
1366
+ color,
1367
+ strokeWidth,
1368
+ offx: 0,
1369
+ offy: 0,
1370
+ size
1371
+ };
1372
+ const elements = [];
1373
+ renderTokens(tokenise(iconString), 0, 0, boldness, state, resolver, elements);
1374
+ const vb = `${-viewSize} ${-viewSize} ${viewSize * 2} ${viewSize * 2}`;
1375
+ const attrs = Object.entries(svgAttrs).map(([k, v]) => ` ${k}="${v}"`).join("");
1376
+ return [
1377
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${vb}"${attrs}>`,
1378
+ ...elements,
1379
+ `</svg>`
1380
+ ].join("\n");
1381
+ }
1111
1382
  export {
1112
1383
  ApiError,
1113
1384
  AuthError,
1114
1385
  Rotur,
1115
1386
  RoturSocket,
1387
+ iconToSvg,
1116
1388
  performAuth
1117
1389
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rotur-sdk",
3
- "version": "1.0.11",
3
+ "version": "1.1.0",
4
4
  "description": "The official SDK for the Rotur platform",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",