@dan-uni/dan-any 0.0.7 → 0.2.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.
Files changed (55) hide show
  1. package/README.md +10 -1
  2. package/dist/index.js +5956 -1
  3. package/dist/index.umd.min.js +19951 -1
  4. package/dist/index.umd.min.js.LICENSE.txt +17 -0
  5. package/dist/src/ass-gen/__tests__/generate.test.d.ts +1 -0
  6. package/dist/src/ass-gen/ass/create.d.ts +4 -0
  7. package/dist/src/ass-gen/ass/dialogue.d.ts +17 -0
  8. package/dist/src/ass-gen/ass/event.d.ts +3 -0
  9. package/dist/src/ass-gen/ass/info.d.ts +8 -0
  10. package/dist/src/ass-gen/ass/raw.d.ts +10 -0
  11. package/dist/src/ass-gen/ass/style.d.ts +3 -0
  12. package/dist/src/ass-gen/config.d.ts +3 -0
  13. package/dist/src/ass-gen/index.d.ts +26 -0
  14. package/dist/src/ass-gen/types.d.ts +47 -0
  15. package/dist/src/ass-gen/util/color.d.ts +18 -0
  16. package/dist/src/ass-gen/util/danconvert.d.ts +4 -0
  17. package/dist/src/ass-gen/util/index.d.ts +4 -0
  18. package/dist/src/ass-gen/util/lang.d.ts +3 -0
  19. package/dist/src/ass-gen/util/layout.d.ts +4 -0
  20. package/dist/{index.d.ts → src/index.d.ts} +16 -1
  21. package/dist/src/index.test.d.ts +1 -0
  22. package/dist/{utils → src/utils}/dm-gen.d.ts +26 -9
  23. package/dist/src/utils/dm-gen.test.d.ts +1 -0
  24. package/package.json +9 -7
  25. package/rslib.config.ts +81 -0
  26. package/src/ass-gen/__tests__/898651903.xml +1619 -0
  27. package/src/ass-gen/__tests__/898651903.xml.ass +1392 -0
  28. package/src/ass-gen/__tests__/canvas.test.ts +11 -0
  29. package/src/ass-gen/__tests__/generate.test.ts +20 -0
  30. package/src/ass-gen/ass/create.ts +26 -0
  31. package/src/ass-gen/ass/dialogue.ts +91 -0
  32. package/src/ass-gen/ass/event.ts +58 -0
  33. package/src/ass-gen/ass/info.ts +28 -0
  34. package/src/ass-gen/ass/raw.ts +69 -0
  35. package/src/ass-gen/ass/style.ts +67 -0
  36. package/src/ass-gen/config.ts +45 -0
  37. package/src/ass-gen/index.ts +52 -0
  38. package/src/ass-gen/types.ts +52 -0
  39. package/src/ass-gen/util/color.ts +55 -0
  40. package/src/ass-gen/util/danconvert.ts +36 -0
  41. package/src/ass-gen/util/index.ts +10 -0
  42. package/src/ass-gen/util/lang.ts +35 -0
  43. package/src/ass-gen/util/layout.ts +238 -0
  44. package/src/index.test.ts +16 -0
  45. package/src/index.ts +114 -0
  46. package/src/utils/dm-gen.test.ts +66 -0
  47. package/src/utils/dm-gen.ts +153 -34
  48. package/tsconfig.json +7 -7
  49. package/CHANGELOG.md +0 -9
  50. package/dist/index.min.js +0 -1
  51. package/rollup.config.mjs +0 -51
  52. /package/dist/{index.test.d.ts → src/ass-gen/__tests__/canvas.test.d.ts} +0 -0
  53. /package/dist/{proto → src/proto}/gen/bili/dm_pb.d.ts +0 -0
  54. /package/dist/{proto → src/proto}/gen/danuni_pb.d.ts +0 -0
  55. /package/dist/{utils → src/utils}/id-gen.d.ts +0 -0
@@ -6,6 +6,29 @@ import { createDMID, domainPreset, UniID as ID, platforms } from './id-gen'
6
6
  const BigIntSerializer = (k: string, v: any) =>
7
7
  typeof v === 'bigint' ? v.toString() : v
8
8
 
9
+ function cleanEmptyObjects(obj: object): object {
10
+ if (obj === null || typeof obj !== 'object') {
11
+ return obj
12
+ }
13
+ if (Array.isArray(obj)) {
14
+ return obj
15
+ }
16
+ const cleaned: any = {}
17
+ for (const [key, value] of Object.entries(obj)) {
18
+ const cleanedValue = cleanEmptyObjects(value)
19
+ if (
20
+ cleanedValue !== undefined &&
21
+ !(
22
+ typeof cleanedValue === 'object' &&
23
+ Object.keys(cleanedValue).length === 0
24
+ )
25
+ ) {
26
+ cleaned[key] = cleanedValue
27
+ }
28
+ }
29
+ return Object.keys(cleaned).length > 0 ? cleaned : {}
30
+ }
31
+
9
32
  class SetBin {
10
33
  constructor(public bin: number) {}
11
34
  set1(bit: number) {
@@ -193,14 +216,21 @@ interface ExtraBili {
193
216
  command?: DMBiliCommand
194
217
  }
195
218
  export interface ExtraDanUni {
196
- chapter?: {
197
- // seg: {
198
- // st: number //开始时刻
199
- // } //起止时间(ms)
200
- duration: number //持续时间
201
- type: ExtraDanUniChapterType
202
- // action: ExtraDanUniChapterAction
203
- }
219
+ chapter?: ExtraDanUniChapter
220
+ merge?: ExtraDanUniMerge
221
+ }
222
+ export interface ExtraDanUniChapter {
223
+ // seg: {
224
+ // st: number //开始时刻
225
+ // } //起止时间(ms)
226
+ duration: number //持续时间
227
+ type: ExtraDanUniChapterType
228
+ // action: ExtraDanUniChapterAction
229
+ }
230
+ export interface ExtraDanUniMerge {
231
+ duration: number //持续时间(重复内容第一次出现时间开始到合并了的弹幕中最后一次出现的时间)
232
+ count: number //重复次数
233
+ senders: string[] //发送者
204
234
  }
205
235
  export enum ExtraDanUniChapterType {
206
236
  Chapter = 'ch', //其它片段(用于标记章节)
@@ -256,7 +286,8 @@ export interface UniDMObj {
256
286
  attr: DMAttr[]
257
287
  platform: platfrom | string
258
288
  SPMO: string
259
- extra: string
289
+ extra: string | Extra
290
+ extraStr: string
260
291
  DMID: string
261
292
  }
262
293
 
@@ -274,7 +305,7 @@ export class UniDM {
274
305
  */
275
306
  public FCID: string,
276
307
  /**
277
- * 弹幕出现位置(单位ms)
308
+ * 弹幕出现位置(单位s;精度为ms,即保留三位小数)
278
309
  */
279
310
  public progress: number = 0,
280
311
  /**
@@ -359,29 +390,40 @@ export class UniDM {
359
390
  if (pool < Pools.Def || pool > Pools.Ix) this.pool = Pools.Def
360
391
  // if (attr < 0 || attr > 0b111) this.attr = 0
361
392
  if (!DMID) DMID = this.toDMID()
393
+
394
+ this.progress = Number.parseFloat(progress.toFixed(3))
395
+ if (extraStr)
396
+ this.extraStr = JSON.stringify(cleanEmptyObjects(JSON.parse(extraStr)))
397
+ if (extraStr === '{}') this.extraStr = undefined
362
398
  }
363
- static create(args: Partial<UniDMObj>) {
364
- return new UniDM(
365
- args.FCID || ID.fromNull().toString(),
366
- args.progress,
367
- args.mode,
368
- args.fontsize,
369
- args.color,
370
- args.senderID,
371
- args.content,
372
- args.ctime,
373
- args.weight,
374
- args.pool,
375
- args.attr,
376
- args.platform,
377
- args.SPMO,
378
- args.extra,
379
- args.DMID,
380
- )
399
+ static create(args?: Partial<UniDMObj>) {
400
+ return args
401
+ ? new UniDM(
402
+ args.FCID || ID.fromNull().toString(),
403
+ args.progress,
404
+ args.mode,
405
+ args.fontsize,
406
+ args.color,
407
+ args.senderID,
408
+ args.content,
409
+ args.ctime,
410
+ args.weight,
411
+ args.pool,
412
+ args.attr,
413
+ args.platform,
414
+ args.SPMO,
415
+ typeof args.extra === 'object'
416
+ ? JSON.stringify(args.extra)
417
+ : args.extra || args.extraStr,
418
+ args.DMID,
419
+ )
420
+ : new UniDM(ID.fromNull().toString())
381
421
  }
382
- get extra() {
422
+ get extra(): Extra {
383
423
  const extra = JSON.parse(this.extraStr || '{}')
384
- return (typeof extra === 'object' ? extra : {}) as Extra
424
+ // this.extraStr = JSON.stringify(cleanEmptyObjects(extra))
425
+ return extra
426
+ // return cleanEmptyObjects(extra) as Extra
385
427
  }
386
428
  get isFrom3rdPlatform() {
387
429
  if (this.platform && platforms.includes(this.platform as platfrom))
@@ -396,15 +438,92 @@ export class UniDM {
396
438
  toDMID() {
397
439
  return createDMID(this.content, this.senderID, this.ctime)
398
440
  }
441
+ isSameAs(dan: UniDM, _check2 = false): boolean {
442
+ const isSame = (k: keyof UniDMObj) => this[k] === dan[k],
443
+ checks = (
444
+ [
445
+ 'FCID',
446
+ 'content',
447
+ 'mode',
448
+ 'platform',
449
+ 'pool',
450
+ 'SPMO',
451
+ ] satisfies (keyof UniDMObj)[]
452
+ ).every((k) => isSame(k))
453
+ // 如果两个对象的extra都是空对象,只检查基本字段
454
+ if (
455
+ JSON.stringify(this.extra) === '{}' &&
456
+ JSON.stringify(dan.extra) === '{}'
457
+ ) {
458
+ return checks
459
+ }
460
+ // 特殊情况:只包含danuni.merge的情况
461
+ const thisHasOnlyMerge =
462
+ this.extra.danuni?.merge &&
463
+ !this.extra.artplayer &&
464
+ !this.extra.bili &&
465
+ !this.extra.danuni.chapter
466
+ const danHasOnlyMerge =
467
+ dan.extra.danuni?.merge &&
468
+ !dan.extra.artplayer &&
469
+ !dan.extra.bili &&
470
+ !dan.extra.danuni.chapter
471
+ if (thisHasOnlyMerge && danHasOnlyMerge) {
472
+ return checks
473
+ }
474
+ if (_check2) {
475
+ return isSame('extraStr') && checks
476
+ }
477
+ const a = { ...this.extra }
478
+ const b = { ...dan.extra }
479
+ if (a.danuni) delete a.danuni.merge
480
+ if (b.danuni) delete b.danuni.merge
481
+ return UniDM.create({ ...a, extraStr: JSON.stringify(a) }).isSameAs(
482
+ UniDM.create({ ...b, extraStr: JSON.stringify(b) }),
483
+ true,
484
+ )
485
+ }
486
+ minify() {
487
+ type UObj = Partial<UniDMObj> & Pick<UniDMObj, 'FCID'>
488
+ const def: UObj = UniDM.create(),
489
+ dan: UObj = UniDM.create(this)
490
+ // const prototypes = Object.getOwnPropertyNames(this)
491
+ for (const key in dan) {
492
+ const k = key as keyof UObj,
493
+ v = dan[k]
494
+ // if (key in prototypes) continue
495
+ if (key === 'FCID') continue
496
+ else if (!v) delete dan[k]
497
+ else if (v === def[k]) delete dan[k]
498
+ else {
499
+ if (k === 'attr' && Array.isArray(v) && v.length === 0) delete dan[k]
500
+ if (k === 'extraStr' && v === '{}') delete dan[k]
501
+ }
502
+ }
503
+ return JSON.parse(JSON.stringify(dan)) as UObj
504
+ }
399
505
  downgradeAdvcancedDan() {
400
506
  if (!this.extra) return this
401
507
  else {
402
508
  // TODO 分别对 mode7/8/9 command artplayer等正常播放器无法绘制的弹幕做降级处理
403
509
  }
404
510
  }
405
- static transCtime(oriCtime: ctime) {
406
- if (typeof oriCtime === 'number') return new Date(oriCtime)
407
- else if (typeof oriCtime === 'bigint') return new Date(Number(oriCtime))
511
+ /**
512
+ * 将各种类型的时间进行格式化
513
+ * @param oriCtime
514
+ * @param tsUnit 当`oriCtime`为数字类型表时间戳时的单位;
515
+ * 为 毫秒(ms)/秒(s)
516
+ * @returns {Date} Date格式时间
517
+ */
518
+ static transCtime(oriCtime: ctime, tsUnit?: 'ms' | 's'): Date {
519
+ function isMsTs(ts: number | bigint) {
520
+ if (tsUnit === 'ms') return true
521
+ else if (tsUnit === 's') return false
522
+ else return ts < 100000000
523
+ }
524
+ if (typeof oriCtime === 'number' || typeof oriCtime === 'bigint')
525
+ if (isMsTs(oriCtime)) return new Date(Number(oriCtime))
526
+ else return new Date(Number(oriCtime) * 1000)
408
527
  else if (typeof oriCtime === 'string') {
409
528
  if (/^\d+n$/.test(oriCtime))
410
529
  return new Date(Number(oriCtime.slice(0, -1)))
@@ -522,7 +641,7 @@ export class UniDM {
522
641
  // color: args.color,
523
642
  senderID: senderID.toString(),
524
643
  // content: args.content,
525
- ctime: this.transCtime(args.ctime),
644
+ ctime: this.transCtime(args.ctime, 's'),
526
645
  weight: args.weight ? args.weight : pool === Pools.Ix ? 1 : 0,
527
646
  pool,
528
647
  attr: DMAttrUtils.fromBin(args.attr, 'bili'),
package/tsconfig.json CHANGED
@@ -24,12 +24,6 @@
24
24
  /* Modules */
25
25
  "module": "ESNext", /* Skip type checking all .d.ts files. */
26
26
  "moduleResolution": "Node",
27
- "allowImportingTsExtensions": true, /* Ensure that casing is correct in imports. */
28
- /* Type Checking */
29
- "strict": true, /* Enable all strict type-checking options. */
30
- "noImplicitAny": true,
31
- "declaration": true,
32
- "emitDeclarationOnly": true, /* Specify what module code is generated. */
33
27
  // "rootDir": "./", /* Specify the root folder within your source files. */
34
28
  // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
35
29
  // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
@@ -43,7 +37,13 @@
43
37
  // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
44
38
  // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
45
39
  // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
46
- // "resolveJsonModule": true, /* Enable importing .json files. */
40
+ "resolveJsonModule": true, /* Enable importing .json files. */
41
+ "allowImportingTsExtensions": true, /* Ensure that casing is correct in imports. */
42
+ /* Type Checking */
43
+ "strict": true, /* Enable all strict type-checking options. */
44
+ "noImplicitAny": true,
45
+ "declaration": true,
46
+ "emitDeclarationOnly": true, /* Specify what module code is generated. */
47
47
  // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
48
48
  // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
49
49
  /* JavaScript Support */
package/CHANGELOG.md DELETED
@@ -1,9 +0,0 @@
1
- ## 0.0.7 (2025-01-26)
2
-
3
-
4
- ### Features
5
-
6
- * **dan-any:** add `.split(key)` method to split UniPool by shared value ([2568c76](https://github.com/ani-uni/danuni/commit/2568c7645f95c6b564bf22cfef2ca1a05d96f8ba))
7
-
8
-
9
-