etro 0.12.1 → 0.14.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 (145) hide show
  1. package/.github/dependabot.yml +6 -0
  2. package/.github/scripts/update-changelog.js +72 -0
  3. package/.github/workflows/dependabot-changelog.yml +57 -0
  4. package/.github/workflows/nodejs.yml +6 -2
  5. package/.github/workflows/shipjs-trigger.yml +2 -1
  6. package/.husky/pre-commit +1 -1
  7. package/AGENTS.md +106 -0
  8. package/CHANGELOG.md +46 -0
  9. package/CONTRIBUTING.md +5 -5
  10. package/README.md +8 -7
  11. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/base.css +224 -0
  12. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/block-navigation.js +87 -0
  13. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/favicon.png +0 -0
  14. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/index.html +161 -0
  15. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/prettify.css +1 -0
  16. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/prettify.js +2 -0
  17. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
  18. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/sorter.js +196 -0
  19. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/custom-array.ts.html +214 -0
  20. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/base.ts.html +481 -0
  21. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/brightness.ts.html +214 -0
  22. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/channels.ts.html +235 -0
  23. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/chroma-key.ts.html +331 -0
  24. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/contrast.ts.html +211 -0
  25. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/elliptical-mask.ts.html +310 -0
  26. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/gaussian-blur.ts.html +796 -0
  27. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/grayscale.ts.html +187 -0
  28. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/index.html +311 -0
  29. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/index.ts.html +154 -0
  30. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/pixelate.ts.html +259 -0
  31. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/shader.ts.html +1774 -0
  32. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/stack.ts.html +358 -0
  33. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/transform.ts.html +685 -0
  34. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/effect/visual.ts.html +148 -0
  35. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/etro.ts.html +163 -0
  36. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/event.ts.html +691 -0
  37. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/index.html +176 -0
  38. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/index.ts.html +109 -0
  39. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/audio-source.ts.html +835 -0
  40. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/audio.ts.html +241 -0
  41. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/base.ts.html +826 -0
  42. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/image.ts.html +181 -0
  43. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/index.html +236 -0
  44. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/index.ts.html +124 -0
  45. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/text.ts.html +658 -0
  46. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/video.ts.html +211 -0
  47. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/visual-source.ts.html +721 -0
  48. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/layer/visual.ts.html +760 -0
  49. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/movie/effects.ts.html +163 -0
  50. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/movie/index.html +161 -0
  51. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/movie/index.ts.html +88 -0
  52. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/movie/layers.ts.html +163 -0
  53. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/movie/movie.ts.html +3037 -0
  54. package/coverage/Chrome Headless 148.0.0.0 (Mac OS 10.15.7)/html/src/util.ts.html +1765 -0
  55. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/base.css +224 -0
  56. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/block-navigation.js +87 -0
  57. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/favicon.png +0 -0
  58. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/index.html +161 -0
  59. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/prettify.css +1 -0
  60. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/prettify.js +2 -0
  61. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/sort-arrow-sprite.png +0 -0
  62. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/sorter.js +196 -0
  63. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/custom-array.ts.html +214 -0
  64. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/base.ts.html +481 -0
  65. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/brightness.ts.html +214 -0
  66. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/channels.ts.html +235 -0
  67. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/chroma-key.ts.html +331 -0
  68. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/contrast.ts.html +211 -0
  69. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/elliptical-mask.ts.html +310 -0
  70. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/gaussian-blur.ts.html +796 -0
  71. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/grayscale.ts.html +187 -0
  72. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/index.html +311 -0
  73. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/index.ts.html +154 -0
  74. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/pixelate.ts.html +259 -0
  75. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/shader.ts.html +1774 -0
  76. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/stack.ts.html +358 -0
  77. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/transform.ts.html +685 -0
  78. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/effect/visual.ts.html +148 -0
  79. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/etro.ts.html +163 -0
  80. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/event.ts.html +691 -0
  81. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/index.html +176 -0
  82. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/index.ts.html +109 -0
  83. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/audio-source.ts.html +835 -0
  84. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/audio.ts.html +241 -0
  85. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/base.ts.html +826 -0
  86. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/image.ts.html +181 -0
  87. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/index.html +236 -0
  88. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/index.ts.html +124 -0
  89. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/text.ts.html +658 -0
  90. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/video.ts.html +211 -0
  91. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/visual-source.ts.html +721 -0
  92. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/layer/visual.ts.html +760 -0
  93. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/movie/effects.ts.html +163 -0
  94. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/movie/index.html +161 -0
  95. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/movie/index.ts.html +88 -0
  96. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/movie/layers.ts.html +163 -0
  97. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/movie/movie.ts.html +3037 -0
  98. package/coverage/Firefox 151.0 (Mac OS 10.15)/html/src/util.ts.html +1765 -0
  99. package/dist/custom-array.d.ts +10 -10
  100. package/dist/effect/base.d.ts +61 -60
  101. package/dist/effect/brightness.d.ts +16 -16
  102. package/dist/effect/channels.d.ts +23 -23
  103. package/dist/effect/chroma-key.d.ts +23 -23
  104. package/dist/effect/contrast.d.ts +15 -15
  105. package/dist/effect/elliptical-mask.d.ts +31 -31
  106. package/dist/effect/gaussian-blur.d.ts +60 -60
  107. package/dist/effect/grayscale.d.ts +7 -7
  108. package/dist/effect/index.d.ts +16 -16
  109. package/dist/effect/pixelate.d.ts +18 -18
  110. package/dist/effect/shader.d.ts +109 -109
  111. package/dist/effect/stack.d.ts +27 -27
  112. package/dist/effect/transform.d.ts +73 -73
  113. package/dist/effect/visual.d.ts +17 -17
  114. package/dist/etro-cjs.js +3601 -3556
  115. package/dist/etro-iife.js +3602 -3557
  116. package/dist/etro.d.ts +7 -7
  117. package/dist/event.d.ts +40 -40
  118. package/dist/index.d.ts +6 -6
  119. package/dist/layer/audio-source.d.ts +28 -28
  120. package/dist/layer/audio.d.ts +27 -27
  121. package/dist/layer/base.d.ts +129 -128
  122. package/dist/layer/image.d.ts +20 -20
  123. package/dist/layer/index.d.ts +11 -11
  124. package/dist/layer/text.d.ts +78 -78
  125. package/dist/layer/video.d.ts +23 -23
  126. package/dist/layer/visual-source.d.ts +47 -47
  127. package/dist/layer/visual.d.ts +62 -62
  128. package/dist/movie/effects.d.ts +6 -6
  129. package/dist/movie/index.d.ts +1 -1
  130. package/dist/movie/layers.d.ts +6 -6
  131. package/dist/movie/movie.d.ts +280 -277
  132. package/dist/object.d.ts +19 -19
  133. package/dist/util.d.ts +128 -121
  134. package/karma.conf.js +70 -3
  135. package/package.json +14 -17
  136. package/ship.config.js +9 -11
  137. package/src/effect/base.ts +16 -0
  138. package/src/effect/shader.ts +1 -1
  139. package/src/layer/base.ts +19 -1
  140. package/src/movie/movie.ts +123 -8
  141. package/src/util.ts +116 -3
  142. package/tsconfig.json +3 -2
  143. package/.husky/commit-msg +0 -4
  144. package/.husky/prepare-commit-msg +0 -11
  145. package/commitlint.config.ts +0 -39
@@ -3,9 +3,11 @@
3
3
  */
4
4
 
5
5
  import { publish, deprecate } from '../event'
6
- import { Dynamic, val, clearCachedValues, applyOptions, Color, parseColor } from '../util'
6
+ import { Dynamic, val, clearCachedValues, applyOptions, Color, parseColor, serializeProperty, deserializeProperty } from '../util'
7
7
  import { Base as BaseLayer, Audio as AudioLayer, Video as VideoLayer, Visual } from '../layer/index' // `Media` mixins
8
8
  import { Base as BaseEffect } from '../effect/index'
9
+ import * as Layers from '../layer/index'
10
+ import * as Effects from '../effect/index'
9
11
  import { MovieEffects } from './effects'
10
12
  import { MovieLayers } from './layers'
11
13
 
@@ -124,12 +126,13 @@ export class Movie {
124
126
  * Plays the movie
125
127
  *
126
128
  * @param [options]
129
+ * @param [options.onDraw] Called when the current frame is drawn to the canvas
127
130
  * @param [options.onStart] Called when the movie starts playing
128
131
  * @param [options.duration] The duration of the movie to play in seconds
129
- *
130
132
  * @return Fulfilled when the movie is done playing, never fails
131
133
  */
132
134
  async play (options: {
135
+ onDraw?: () => void,
133
136
  onStart?: () => void,
134
137
  duration?: number,
135
138
  } = {}): Promise<void> {
@@ -152,7 +155,7 @@ export class Movie {
152
155
  await new Promise<void>(resolve => {
153
156
  if (!this.renderingFrame) {
154
157
  // Not rendering (and not playing), so play.
155
- this._render(undefined, resolve)
158
+ this._render(undefined, resolve, options.onDraw)
156
159
  }
157
160
 
158
161
  // Stop rendering frame if currently doing so, because playing has higher
@@ -181,7 +184,7 @@ export class Movie {
181
184
  * Streams the movie to a MediaStream
182
185
  *
183
186
  * @param options Options for the stream
184
- * @param options.frameRate The frame rate of the stream's video
187
+ * @param options.frameRate The maximum frame rate of the stream's video
185
188
  * @param options.duration The duration of the stream in seconds
186
189
  * @param options.video Whether to stream video. Defaults to true.
187
190
  * @param options.audio Whether to stream audio. Defaults to true.
@@ -264,7 +267,7 @@ export class Movie {
264
267
  * Plays the movie in the background and records it
265
268
  *
266
269
  * @param options
267
- * @param [options.frameRate] - Video frame rate
270
+ * @param [options.frameRate] - Maximum video frame rate (fps)
268
271
  * @param [options.video=true] - whether to include video in recording
269
272
  * @param [options.audio=true] - whether to include audio in recording
270
273
  * @param [options.mediaRecorderOptions=undefined] - Options to pass to the
@@ -399,10 +402,10 @@ export class Movie {
399
402
  * Processes one frame of the movie and draws it to the canvas
400
403
  *
401
404
  * @param [timestamp=performance.now()]
402
- * @param [done=undefined] - Called when done playing or when the current
403
- * frame is loaded
405
+ * @param [done=undefined] - Called when done playing or when the current frame is loaded
406
+ * @param [onFrameRender=undefined] - Called when the current frame is rendered
404
407
  */
405
- private _render (timestamp = performance.now(), done = undefined) {
408
+ private _render (timestamp = performance.now(), done = undefined, onFrameRender = undefined) {
406
409
  clearCachedValues(this)
407
410
 
408
411
  if (!this.rendering) {
@@ -482,6 +485,7 @@ export class Movie {
482
485
  this._renderBackground(timestamp)
483
486
  this._renderLayers()
484
487
  this._applyEffects()
488
+ onFrameRender?.()
485
489
  } else {
486
490
  // If we are recording, pause the media recorder until the movie is
487
491
  // ready.
@@ -852,6 +856,117 @@ export class Movie {
852
856
  repeat: false
853
857
  }
854
858
  }
859
+
860
+ toJSON (): object {
861
+ return {
862
+ type: 'movie',
863
+ canvas: this.canvas ? { width: this.canvas.width, height: this.canvas.height } : undefined,
864
+ background: serializeProperty(this.background),
865
+ repeat: this.repeat,
866
+ layers: this.layers.map(layer => (layer as any).toJSON()),
867
+ effects: this.effects.map(effect => (effect as any).toJSON())
868
+ }
869
+ }
870
+
871
+ static fromJSON (json: any, canvas?: HTMLCanvasElement, actx?: AudioContext): Movie {
872
+ if (!canvas) {
873
+ canvas = document.createElement('canvas')
874
+ if (json.canvas) {
875
+ canvas.width = json.canvas.width
876
+ canvas.height = json.canvas.height
877
+ }
878
+ }
879
+ const options: any = {
880
+ canvas,
881
+ actx,
882
+ background: deserializeProperty(json.background),
883
+ repeat: json.repeat
884
+ }
885
+ const movie = new Movie(options)
886
+
887
+ const deserializeEffect = (effectJson: any): any => {
888
+ const type = effectJson.type.replace('effect.', '')
889
+ const EffectClass = (Effects as any)[type]
890
+ if (!EffectClass) {
891
+ throw new Error(`Unknown effect type: ${type}`)
892
+ }
893
+
894
+ const effectOptions: any = {}
895
+ const defaultOptions = EffectClass.prototype.getDefaultOptions ? EffectClass.prototype.getDefaultOptions() : {}
896
+
897
+ for (const key in effectJson) {
898
+ if (key !== 'type' && key !== 'effects') {
899
+ if (key in defaultOptions) {
900
+ effectOptions[key] = deserializeProperty(effectJson[key])
901
+ }
902
+ }
903
+ }
904
+
905
+ if (effectJson.effects) {
906
+ effectOptions.effects = effectJson.effects.map((subEffectJson: any) => deserializeEffect(subEffectJson))
907
+ }
908
+
909
+ const effect = new EffectClass(effectOptions)
910
+ for (const key in effectJson) {
911
+ if (key !== 'type' && key !== 'effects' && !(key in defaultOptions)) {
912
+ effect[key] = deserializeProperty(effectJson[key])
913
+ }
914
+ }
915
+ return effect
916
+ }
917
+
918
+ const deserializeLayer = (layerJson: any): any => {
919
+ const type = layerJson.type.replace('layer.', '')
920
+ const LayerClass = (Layers as any)[type]
921
+ if (!LayerClass) {
922
+ throw new Error(`Unknown layer type: ${type}`)
923
+ }
924
+
925
+ const layerOptions: any = {}
926
+ const defaultOptions = LayerClass.prototype.getDefaultOptions ? LayerClass.prototype.getDefaultOptions() : {}
927
+ if (!('startTime' in defaultOptions)) {
928
+ defaultOptions.startTime = undefined
929
+ }
930
+ if (!('duration' in defaultOptions)) {
931
+ defaultOptions.duration = undefined
932
+ }
933
+
934
+ for (const key in layerJson) {
935
+ if (key !== 'type' && key !== 'effects') {
936
+ if (key in defaultOptions) {
937
+ layerOptions[key] = deserializeProperty(layerJson[key])
938
+ }
939
+ }
940
+ }
941
+
942
+ const layer = new LayerClass(layerOptions)
943
+ for (const key in layerJson) {
944
+ if (key !== 'type' && key !== 'effects' && !(key in defaultOptions)) {
945
+ layer[key] = deserializeProperty(layerJson[key])
946
+ }
947
+ }
948
+ if (layerJson.effects) {
949
+ for (const effectJson of layerJson.effects) {
950
+ layer.addEffect(deserializeEffect(effectJson))
951
+ }
952
+ }
953
+ return layer
954
+ }
955
+
956
+ if (json.layers) {
957
+ for (const layerJson of json.layers) {
958
+ movie.addLayer(deserializeLayer(layerJson))
959
+ }
960
+ }
961
+
962
+ if (json.effects) {
963
+ for (const effectJson of json.effects) {
964
+ movie.addEffect(deserializeEffect(effectJson))
965
+ }
966
+ }
967
+
968
+ return movie
969
+ }
855
970
  }
856
971
 
857
972
  // Id for events
package/src/util.ts CHANGED
@@ -91,6 +91,13 @@ export function clearCachedValues (movie: Movie): void {
91
91
  valCache.delete(movie)
92
92
  }
93
93
 
94
+ type Interpolate = <U = number | object>(
95
+ startValue: U,
96
+ endValue: U,
97
+ percentProgress: number,
98
+ interpolationKeys: string[]
99
+ ) => U
100
+
94
101
  /**
95
102
  * A keyframe set.
96
103
  *
@@ -101,7 +108,7 @@ export function clearCachedValues (movie: Movie): void {
101
108
  * TypeScript users need to specify the type of the value as a type parameter.
102
109
  */
103
110
  export class KeyFrame<T> {
104
- value: unknown[][]
111
+ value: (number|T|Interpolate)[][]
105
112
  /** Keys to interpolate, or all keys if undefined */
106
113
  interpolationKeys: string[]
107
114
 
@@ -115,6 +122,25 @@ export class KeyFrame<T> {
115
122
  return this
116
123
  }
117
124
 
125
+ toJSON (): object {
126
+ return {
127
+ type: 'KeyFrame',
128
+ value: this.value.map(point => {
129
+ const out: any[] = [point[0], serializeProperty(point[1])]
130
+ if (point.length === 3) {
131
+ const interp = point[2] as Interpolate
132
+ if (interp === linearInterp) {
133
+ out.push('linear')
134
+ } else if (interp === cosineInterp) {
135
+ out.push('cosine')
136
+ }
137
+ }
138
+ return out
139
+ }),
140
+ interpolationKeys: this.interpolationKeys
141
+ }
142
+ }
143
+
118
144
  evaluate (time: number): T {
119
145
  if (this.value.length === 0) {
120
146
  throw new Error('Empty keyframe')
@@ -133,8 +159,10 @@ export class KeyFrame<T> {
133
159
  for (let i = 0; i < this.value.length; i++) {
134
160
  const startTime = this.value[i][0] as number
135
161
  const startValue = this.value[i][1] as T
136
- type interpolateType = <U = number | object>(startValue: U, endValue: U, percentProgress: number, interpolationKeys: string[]) => U // eslint-disable-line @typescript-eslint/ban-types
137
- const interpolate = this.value[i].length === 3 ? this.value[i][2] as interpolateType : linearInterp
162
+ const interpolate =
163
+ this.value[i].length === 3
164
+ ? (this.value[i][2] as Interpolate)
165
+ : linearInterp
138
166
  if (i + 1 < this.value.length) {
139
167
  const endTime = this.value[i + 1][0] as number
140
168
  const endValue = this.value[i + 1][1] as T
@@ -313,6 +341,10 @@ export class Color {
313
341
  toString (): string {
314
342
  return `rgba(${this.r}, ${this.g}, ${this.b}, ${this.a})`
315
343
  }
344
+
345
+ toJSON (): object {
346
+ return { type: 'Color', r: this.r, g: this.g, b: this.b, a: this.a }
347
+ }
316
348
  }
317
349
 
318
350
  const parseColorCanvas = document.createElement('canvas')
@@ -389,6 +421,20 @@ export class Font {
389
421
 
390
422
  return s
391
423
  }
424
+
425
+ toJSON (): object {
426
+ return {
427
+ type: 'Font',
428
+ size: this.size,
429
+ sizeUnit: this.sizeUnit,
430
+ family: this.family,
431
+ style: this.style,
432
+ variant: this.variant,
433
+ weight: this.weight,
434
+ stretch: this.stretch,
435
+ lineHeight: this.lineHeight
436
+ }
437
+ }
392
438
  }
393
439
 
394
440
  const parseFontEl = document.createElement('div')
@@ -445,3 +491,70 @@ export function mapPixels (
445
491
  ctx.putImageData(frame, x, y)
446
492
  }
447
493
  }
494
+
495
+ export function serializeProperty (val: any): any {
496
+ if (val && typeof val === 'object') {
497
+ if (typeof val.toJSON === 'function') {
498
+ return val.toJSON()
499
+ }
500
+ if (Array.isArray(val)) {
501
+ return val.map(serializeProperty)
502
+ }
503
+ if (val instanceof HTMLImageElement || val instanceof HTMLVideoElement || val instanceof HTMLAudioElement) {
504
+ // It's a DOM element serving as a media source
505
+ return val.getAttribute('src') || val.src
506
+ }
507
+ // plain object
508
+ if (val.constructor === Object) {
509
+ const out: any = {}
510
+ for (const k in val) {
511
+ if (Object.prototype.hasOwnProperty.call(val, k)) {
512
+ out[k] = serializeProperty(val[k])
513
+ }
514
+ }
515
+ return out
516
+ }
517
+ }
518
+ return val
519
+ }
520
+
521
+ export function deserializeProperty (val: any): any {
522
+ if (val && typeof val === 'object') {
523
+ if (Array.isArray(val)) {
524
+ return val.map(deserializeProperty)
525
+ }
526
+ if (val.type === 'Color') {
527
+ return new Color(val.r, val.g, val.b, val.a)
528
+ }
529
+ if (val.type === 'Font') {
530
+ return new Font(val.size, val.sizeUnit, val.family, val.style, val.variant, val.weight, val.stretch, val.lineHeight)
531
+ }
532
+ if (val.type === 'KeyFrame') {
533
+ const kf = new KeyFrame()
534
+ kf.value = val.value.map((point: any[]) => {
535
+ const out: any[] = [point[0], deserializeProperty(point[1])]
536
+ if (point.length === 3) {
537
+ if (point[2] === 'linear') {
538
+ out.push(linearInterp)
539
+ } else if (point[2] === 'cosine') {
540
+ out.push(cosineInterp)
541
+ }
542
+ }
543
+ return out
544
+ })
545
+ kf.interpolationKeys = val.interpolationKeys
546
+ return kf
547
+ }
548
+ // plain object
549
+ if (val.constructor === Object) {
550
+ const out: any = {}
551
+ for (const k in val) {
552
+ if (Object.prototype.hasOwnProperty.call(val, k)) {
553
+ out[k] = deserializeProperty(val[k])
554
+ }
555
+ }
556
+ return out
557
+ }
558
+ }
559
+ return val
560
+ }
package/tsconfig.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "lib": ["es6", "DOM"],
4
- "target": "es5",
3
+ "lib": ["es2016", "DOM"],
4
+ "target": "es6",
5
+ "moduleResolution": "node",
5
6
  "declaration": true
6
7
  },
7
8
  "include": [
package/.husky/commit-msg DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env sh
2
- . "$(dirname -- "$0")/_/husky.sh"
3
-
4
- npx --no -- commitlint --edit ${1}
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # gitmoji as a commit hook
4
- if npx -v >&/dev/null
5
- then
6
- exec < /dev/tty
7
- npx -c "gitmoji --hook $1 $2"
8
- else
9
- exec < /dev/tty
10
- gitmoji --hook $1 $2
11
- fi
@@ -1,39 +0,0 @@
1
- import type {UserConfig} from '@commitlint/types';
2
- import { RuleConfigSeverity } from "@commitlint/types";
3
-
4
- const Configuration: UserConfig = {
5
- /*
6
- * Resolve and load @commitlint/format from node_modules.
7
- * Referenced package must be installed
8
- */
9
- formatter: '@commitlint/format',
10
- /*
11
- * Any rules defined here will override the default ones
12
- */
13
- rules: {
14
- 'header-max-length': [RuleConfigSeverity.Error, 'always', 72],
15
- 'body-max-line-length': [RuleConfigSeverity.Error, 'always', 72],
16
- },
17
- /*
18
- * Functions that return true if commitlint should ignore the given message.
19
- */
20
- ignores: [(commit) => commit === ''],
21
- /*
22
- * Whether commitlint uses the default ignore rules.
23
- */
24
- defaultIgnores: true,
25
- /*
26
- * Custom URL to show upon failure
27
- */
28
- helpUrl:
29
- 'https://github.com/conventional-changelog/commitlint/#what-is-commitlint',
30
- /*
31
- * Custom prompt configs
32
- */
33
- prompt: {
34
- messages: {},
35
- questions: {},
36
- },
37
- };
38
-
39
- module.exports = Configuration;