@napi-rs/canvas 0.1.24 → 0.1.27

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
@@ -1,7 +1,7 @@
1
1
  # `skr canvas`
2
2
 
3
3
  ![CI](https://github.com/Brooooooklyn/canvas/workflows/CI/badge.svg)
4
- ![Skia Version](https://img.shields.io/badge/Skia-chrome%2Fm104-hotpink)
4
+ ![Skia Version](https://img.shields.io/badge/Skia-chrome%2Fm105-hotpink)
5
5
  [![install size](https://packagephobia.com/badge?p=@napi-rs/canvas)](https://packagephobia.com/result?p=@napi-rs/canvas)
6
6
  [![Downloads](https://img.shields.io/npm/dm/@napi-rs/canvas.svg?sanitize=true)](https://npmcharts.com/compare/@napi-rs/canvas?minimal=true)
7
7
 
@@ -76,7 +76,7 @@ ctx.closePath()
76
76
  ctx.stroke()
77
77
 
78
78
  async function main() {
79
- const pngData = await canvas.encode('png') // JPEG and WebP is also supported
79
+ const pngData = await canvas.encode('png') // JPEG, AVIF and WebP are also supported
80
80
  // encoding in libuv thread pool, non-blocking
81
81
  await promises.writeFile(join(__dirname, 'simple.png'), pngData)
82
82
  }
package/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /// <reference lib="dom" />
2
+
1
3
  export interface DOMMatrix2DInit {
2
4
  a: number
3
5
  b: number
@@ -354,34 +356,34 @@ interface IGlobalFonts {
354
356
 
355
357
  export const GlobalFonts: IGlobalFonts
356
358
 
357
- export const enum PathOp {
359
+ export enum PathOp {
358
360
  Difference = 0, // subtract the op path from the first path
359
361
  Intersect = 1, // intersect the two paths
360
362
  Union = 2, // union (inclusive-or) the two paths
361
- XOR = 3, // exclusive-or the two paths
363
+ Xor = 3, // exclusive-or the two paths
362
364
  ReverseDifference = 4, // subtract the first path from the op path
363
365
  }
364
366
 
365
- export const enum FillType {
367
+ export enum FillType {
366
368
  Winding = 0,
367
369
  EvenOdd = 1,
368
370
  InverseWinding = 2,
369
371
  InverseEvenOdd = 3,
370
372
  }
371
373
 
372
- export const enum StrokeJoin {
374
+ export enum StrokeJoin {
373
375
  Miter = 0,
374
376
  Round = 1,
375
377
  Bevel = 2,
376
378
  }
377
379
 
378
- export const enum StrokeCap {
380
+ export enum StrokeCap {
379
381
  Butt = 0,
380
382
  Round = 1,
381
383
  Square = 2,
382
384
  }
383
385
 
384
- export const enum SvgExportFlag {
386
+ export enum SvgExportFlag {
385
387
  ConvertTextToPaths = 0x01,
386
388
  NoPrettyXML = 0x02,
387
389
  RelativePathEncoding = 0x04,
@@ -390,9 +392,9 @@ export const enum SvgExportFlag {
390
392
  export function convertSVGTextToPath(svg: Buffer | string): Buffer
391
393
 
392
394
  export interface LoadImageOptions {
393
- alt?: string,
394
- maxRedirects?: number,
395
- requestOptions?: import('http').RequestOptions,
395
+ alt?: string
396
+ maxRedirects?: number
397
+ requestOptions?: import('http').RequestOptions
396
398
  }
397
399
 
398
400
  export function loadImage(
package/index.js CHANGED
@@ -11,95 +11,35 @@ const {
11
11
  Image,
12
12
  CanvasPattern,
13
13
  GlobalFonts,
14
- convertSVGTextToPath: _convertSVGTextToPath,
14
+ PathOp,
15
+ FillType,
16
+ StrokeJoin,
17
+ StrokeCap,
18
+ convertSVGTextToPath,
15
19
  } = require('./js-binding')
16
20
 
17
21
  const { DOMPoint, DOMMatrix, DOMRect } = require('./geometry')
18
22
 
19
23
  const loadImage = require('./load-image')
20
24
 
21
- const StrokeJoin = {
22
- Miter: 0,
23
- Round: 1,
24
- Bevel: 2,
25
- }
26
-
27
- const StrokeCap = {
28
- Butt: 0,
29
- Round: 1,
30
- Square: 2,
31
- }
32
-
33
- const PathOp = {
34
- Difference: 0, // subtract the op path from the first path
35
- Intersect: 1, // intersect the two paths
36
- Union: 2, // union (inclusive-or) the two paths
37
- XOR: 3, // exclusive-or the two paths
38
- ReverseDifference: 4, // subtract the first path from the op path
39
- }
40
-
41
- const FillType = {
42
- Winding: 0,
43
- EvenOdd: 1,
44
- InverseWinding: 2,
45
- InverseEvenOdd: 3,
46
- }
47
-
48
25
  const SvgExportFlag = {
49
26
  ConvertTextToPaths: 0x01,
50
27
  NoPrettyXML: 0x02,
51
28
  RelativePathEncoding: 0x04,
52
29
  }
53
30
 
54
- const GlobalFontsSingleton = new GlobalFonts()
55
- let FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
56
-
57
31
  // eslint-disable-next-line sonarjs/no-unused-collection
58
32
  const Fonts = []
59
33
 
60
- Object.defineProperty(GlobalFontsSingleton, 'register', {
61
- value: function register(fontData, nameAlias = '') {
62
- const result = GlobalFontsSingleton._register(fontData, nameAlias)
63
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
64
- Fonts.push(fontData)
65
- return result
66
- },
67
- configurable: false,
68
- enumerable: false,
69
- writable: false,
70
- })
71
-
72
- Object.defineProperty(GlobalFontsSingleton, 'registerFromPath', {
73
- value: function registerFromPath(path, nameAlias = '') {
74
- const result = GlobalFontsSingleton._registerFromPath(path, nameAlias)
75
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
76
- return result
77
- },
78
- configurable: false,
79
- enumerable: false,
80
- writable: false,
81
- })
82
-
83
- Object.defineProperty(GlobalFontsSingleton, 'loadFontsFromDir', {
84
- value: function loadFontsFromDir(path) {
85
- const result = GlobalFontsSingleton._loadFontsFromDir(path)
86
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
87
- return result
88
- },
89
- configurable: false,
90
- enumerable: false,
91
- writable: false,
92
- })
93
-
94
- Object.defineProperty(GlobalFontsSingleton, 'families', {
34
+ Object.defineProperty(GlobalFonts, 'families', {
95
35
  get: function () {
96
- return FamilyNamesSet
36
+ return JSON.parse(GlobalFonts.getFamilies())
97
37
  },
98
38
  })
99
39
 
100
- Object.defineProperty(GlobalFontsSingleton, 'has', {
40
+ Object.defineProperty(GlobalFonts, 'has', {
101
41
  value: function has(name) {
102
- return !!FamilyNamesSet.find(({ family }) => family === name)
42
+ return !!JSON.parse(GlobalFonts.getFamilies()).find(({ family }) => family === name)
103
43
  },
104
44
  configurable: false,
105
45
  enumerable: false,
@@ -129,27 +69,6 @@ CanvasRenderingContext2D.prototype.getImageData = function getImageData(x, y, w,
129
69
  return new ImageData(data, w, h)
130
70
  }
131
71
 
132
- Path2D.prototype.stroke = function stroke(strokeOptions = {}) {
133
- const width = typeof strokeOptions.width === 'undefined' ? 1 : strokeOptions.width
134
- const miterLimit = typeof strokeOptions.miterLimit === 'undefined' ? 4 : strokeOptions.miterLimit
135
- const join = typeof strokeOptions.join === 'undefined' ? StrokeJoin.Miter : strokeOptions.join
136
- const cap = typeof strokeOptions.cap === 'undefined' ? StrokeCap.Butt : strokeOptions.cap
137
-
138
- return this._stroke(width, miterLimit, join, cap)
139
- }
140
-
141
- Path2D.prototype.getFillTypeString = function getFillTypeString() {
142
- const fillType = this.getFillType()
143
-
144
- if (fillType === FillType.Winding) {
145
- return 'nonzero'
146
- } else if (fillType === FillType.EvenOdd) {
147
- return 'evenodd'
148
- } else {
149
- return 'nonzero' // default
150
- }
151
- }
152
-
153
72
  function createCanvas(width, height, flag) {
154
73
  const isSvgBackend = typeof flag !== 'undefined'
155
74
  const canvasElement = isSvgBackend ? new SVGCanvas(width, height) : new CanvasElement(width, height)
@@ -163,8 +82,8 @@ function createCanvas(width, height, flag) {
163
82
  ctx = ctx
164
83
  ? ctx
165
84
  : isSvgBackend
166
- ? new CanvasRenderingContext2D(this.width, this.height, GlobalFontsSingleton, attrs.colorSpace, flag)
167
- : new CanvasRenderingContext2D(this.width, this.height, GlobalFontsSingleton, attrs.colorSpace)
85
+ ? new CanvasRenderingContext2D(this.width, this.height, attrs.colorSpace, flag)
86
+ : new CanvasRenderingContext2D(this.width, this.height, attrs.colorSpace)
168
87
  createContext(ctx, this.width, this.height, attrs)
169
88
 
170
89
  // napi can not define writable: true but enumerable: false property
@@ -213,87 +132,37 @@ function createCanvas(width, height, flag) {
213
132
  toDataURLAsync: canvasToDataURLAsync,
214
133
  } = Object.getPrototypeOf(canvasElement)
215
134
 
216
- // See also: https://github.com/kornelski/cavif-rs#usage
217
- const avifDefaultQuality = 80
218
- const avifConfig = {
219
- // Quality from 1 (worst) to 100 (best), the default value is 80. The numbers have different meaning than JPEG's quality scale. Beware when comparing codecs. There is no lossless compression support.
220
- quality: avifDefaultQuality,
221
-
222
- // Calculate alphaQuality, this is consistent with cavif.
223
- // https://github.com/kornelski/cavif-rs/blob/37847b95bb81d4cf90e36b7fab2c7fbbcf95abe2/src/main.rs#L97
224
- alphaQuality: Math.min((avifDefaultQuality + 100) / 2, avifDefaultQuality + avifDefaultQuality / 4 + 2),
225
- threads: 0,
226
-
227
- // Encoding speed between 1 (best, but slowest) and 10 (fastest, but a blurry mess), the default value is 4. Speeds 1 and 2 are unbelievably slow, but make files ~3-5% smaller. Speeds 7 and above degrade compression significantly, and are not recommended.
228
- speed: 4,
229
- }
230
-
231
- canvasElement.encode = function encode(type, qualityOrConfig) {
135
+ canvasElement.encode = function encode(type, qualityOrConfig = {}) {
232
136
  if (type === 'avif') {
233
- return canvasEncode.call(
234
- this,
235
- type,
236
- JSON.stringify({
237
- ...avifConfig,
238
- ...(qualityOrConfig || {}),
239
- }),
240
- )
137
+ return canvasEncode.call(this, type, JSON.stringify(qualityOrConfig))
241
138
  }
242
139
  return canvasEncode.call(this, type, qualityOrConfig)
243
140
  }
244
141
 
245
- canvasElement.encodeSync = function encodeSync(type, qualityOrConfig) {
142
+ canvasElement.encodeSync = function encodeSync(type, qualityOrConfig = {}) {
246
143
  if (type === 'avif') {
247
- return canvasEncodeSync.call(
248
- this,
249
- type,
250
- JSON.stringify({
251
- ...avifConfig,
252
- ...(qualityOrConfig || {}),
253
- }),
254
- )
144
+ return canvasEncodeSync.call(this, type, JSON.stringify(qualityOrConfig))
255
145
  }
256
146
  return canvasEncodeSync.call(this, type, qualityOrConfig)
257
147
  }
258
148
 
259
- canvasElement.toBuffer = function toBuffer(type = 'image/png', qualityOrConfig) {
149
+ canvasElement.toBuffer = function toBuffer(type = 'image/png', qualityOrConfig = {}) {
260
150
  if (type === 'avif') {
261
- return canvasToBuffer.call(
262
- this,
263
- type,
264
- JSON.stringify({
265
- ...avifConfig,
266
- ...(qualityOrConfig || {}),
267
- }),
268
- )
151
+ return canvasToBuffer.call(this, type, JSON.stringify(qualityOrConfig))
269
152
  }
270
153
  return canvasToBuffer.call(this, type, qualityOrConfig)
271
154
  }
272
155
 
273
- canvasElement.toDataURL = function toDataURL(type = 'image/png', qualityOrConfig) {
156
+ canvasElement.toDataURL = function toDataURL(type = 'image/png', qualityOrConfig = {}) {
274
157
  if (type === 'avif') {
275
- return canvasToDataURL.call(
276
- this,
277
- type,
278
- JSON.stringify({
279
- ...avifConfig,
280
- ...(qualityOrConfig || {}),
281
- }),
282
- )
158
+ return canvasToDataURL.call(this, type, JSON.stringify(qualityOrConfig))
283
159
  }
284
160
  return canvasToDataURL.call(this, type, qualityOrConfig)
285
161
  }
286
162
 
287
- canvasElement.toDataURLAsync = function toDataURLAsync(type = 'image/png', qualityOrConfig) {
163
+ canvasElement.toDataURLAsync = function toDataURLAsync(type = 'image/png', qualityOrConfig = {}) {
288
164
  if (type === 'avif') {
289
- return canvasToDataURLAsync.call(
290
- this,
291
- type,
292
- JSON.stringify({
293
- ...avifConfig,
294
- ...(qualityOrConfig || {}),
295
- }),
296
- )
165
+ return canvasToDataURLAsync.call(this, type, JSON.stringify(qualityOrConfig))
297
166
  }
298
167
  return canvasToDataURLAsync.call(this, type, qualityOrConfig)
299
168
  }
@@ -308,26 +177,21 @@ class Canvas {
308
177
  }
309
178
 
310
179
  if (!process.env.DISABLE_SYSTEM_FONTS_LOAD) {
311
- GlobalFontsSingleton.loadSystemFonts()
180
+ GlobalFonts.loadSystemFonts()
312
181
  const platformName = platform()
313
182
  const homedirPath = homedir()
314
183
  switch (platformName) {
315
184
  case 'win32':
316
- GlobalFontsSingleton.loadFontsFromDir(join(homedirPath, 'AppData', 'Local', 'Microsoft', 'Windows', 'Fonts'))
185
+ GlobalFonts.loadFontsFromDir(join(homedirPath, 'AppData', 'Local', 'Microsoft', 'Windows', 'Fonts'))
317
186
  break
318
187
  case 'darwin':
319
- GlobalFontsSingleton.loadFontsFromDir(join(homedirPath, 'Library', 'Fonts'))
188
+ GlobalFonts.loadFontsFromDir(join(homedirPath, 'Library', 'Fonts'))
320
189
  break
321
190
  case 'linux':
322
- GlobalFontsSingleton.loadFontsFromDir(join('usr', 'local', 'share', 'fonts'))
323
- GlobalFontsSingleton.loadFontsFromDir(join(homedirPath, '.fonts'))
191
+ GlobalFonts.loadFontsFromDir(join('usr', 'local', 'share', 'fonts'))
192
+ GlobalFonts.loadFontsFromDir(join(homedirPath, '.fonts'))
324
193
  break
325
194
  }
326
- FamilyNamesSet = JSON.parse(GlobalFontsSingleton._families)
327
- }
328
-
329
- function convertSVGTextToPath(input) {
330
- return _convertSVGTextToPath(Buffer.isBuffer(input) ? input : Buffer.from(input), GlobalFontsSingleton)
331
195
  }
332
196
 
333
197
  module.exports = {
@@ -341,7 +205,7 @@ module.exports = {
341
205
  StrokeCap,
342
206
  StrokeJoin,
343
207
  SvgExportFlag,
344
- GlobalFonts: GlobalFontsSingleton,
208
+ GlobalFonts: GlobalFonts,
345
209
  convertSVGTextToPath,
346
210
  DOMPoint,
347
211
  DOMMatrix,
package/js-binding.js CHANGED
@@ -200,21 +200,29 @@ const {
200
200
  CanvasElement,
201
201
  createContext,
202
202
  SVGCanvas,
203
- Path2D,
203
+ Path,
204
204
  ImageData,
205
205
  Image,
206
206
  CanvasPattern,
207
207
  GlobalFonts,
208
208
  convertSVGTextToPath,
209
+ PathOp,
210
+ FillType,
211
+ StrokeJoin,
212
+ StrokeCap,
209
213
  } = nativeBinding
210
214
 
211
215
  module.exports.CanvasRenderingContext2D = CanvasRenderingContext2D
212
216
  module.exports.CanvasElement = CanvasElement
213
217
  module.exports.createContext = createContext
214
218
  module.exports.SVGCanvas = SVGCanvas
215
- module.exports.Path2D = Path2D
219
+ module.exports.Path2D = Path
216
220
  module.exports.ImageData = ImageData
217
221
  module.exports.Image = Image
218
222
  module.exports.CanvasPattern = CanvasPattern
219
223
  module.exports.GlobalFonts = GlobalFonts
220
224
  module.exports.convertSVGTextToPath = convertSVGTextToPath
225
+ module.exports.PathOp = PathOp
226
+ module.exports.FillType = FillType
227
+ module.exports.StrokeJoin = StrokeJoin
228
+ module.exports.StrokeCap = StrokeCap
package/load-image.js ADDED
@@ -0,0 +1,94 @@
1
+ const fs = require('fs')
2
+ const { Image } = require('./js-binding')
3
+ const { Readable } = require('stream')
4
+
5
+ let http, https
6
+
7
+ const MAX_REDIRECTS = 20,
8
+ REDIRECT_STATUSES = new Set([301, 302]),
9
+ DATA_URI = /^\s*data:/
10
+
11
+ /**
12
+ * Loads the given source into canvas Image
13
+ * @param {string|URL|Image|Buffer} source The image source to be loaded
14
+ * @param {object} options Options passed to the loader
15
+ */
16
+ module.exports = async function loadImage(source, options = {}) {
17
+ // load readable stream as image
18
+ if (source instanceof Readable) return createImage(await consumeStream(source), options.alt)
19
+ // use the same buffer without copying if the source is a buffer
20
+ if (Buffer.isBuffer(source)) return createImage(source, options.alt)
21
+ // construct a buffer if the source is buffer-like
22
+ if (isBufferLike(source)) return createImage(Buffer.from(source), options.alt)
23
+ // if the source is Image instance, copy the image src to new image
24
+ if (source instanceof Image) return createImage(source.src, options.alt)
25
+ // if source is string and in data uri format, construct image using data uri
26
+ if (typeof source === 'string' && DATA_URI.test(source)) {
27
+ const commaIdx = source.indexOf(',')
28
+ const encoding = source.lastIndexOf('base64', commaIdx) < 0 ? 'utf-8' : 'base64'
29
+ const data = Buffer.from(source.slice(commaIdx + 1), encoding)
30
+ return createImage(data, options.alt)
31
+ }
32
+ // if source is a string or URL instance
33
+ if (typeof source === 'string' || source instanceof URL) {
34
+ // if the source exists as a file, construct image from that file
35
+ if (fs.existsSync(source)) {
36
+ return createImage(await fs.promises.readFile(source), options.alt)
37
+ } else {
38
+ // the source is a remote url here
39
+ source = !(source instanceof URL) ? new URL(source) : source
40
+ // attempt to download the remote source and construct image
41
+ const data = await new Promise((resolve, reject) =>
42
+ makeRequest(source, resolve, reject, options.maxRedirects ?? MAX_REDIRECTS, options.requestOptions),
43
+ )
44
+ return createImage(data, options.alt)
45
+ }
46
+ }
47
+
48
+ // throw error as dont support that source
49
+ throw new TypeError('unsupported image source')
50
+ }
51
+
52
+ function makeRequest(url, resolve, reject, redirectCount, requestOptions) {
53
+ const isHttps = url.protocol === 'https:'
54
+ // lazy load the lib
55
+ const lib = isHttps ? (!https ? (https = require('https')) : https) : !http ? (http = require('http')) : http
56
+
57
+ lib.get(url, requestOptions ?? {}, (res) => {
58
+ const shouldRedirect = REDIRECT_STATUSES.has(res.statusCode) && typeof res.headers.location === 'string'
59
+ if (shouldRedirect && redirectCount > 0)
60
+ return makeRequest(new URL(res.headers.location), resolve, reject, redirectCount - 1, requestOptions)
61
+ if (typeof res.statusCode === 'number' && (res.statusCode < 200 || res.statusCode >= 300)) {
62
+ return reject(new Error(`remote source rejected with status code ${res.statusCode}`))
63
+ }
64
+
65
+ consumeStream(res).then(resolve, reject)
66
+ })
67
+ }
68
+
69
+ // use stream/consumers in the future?
70
+ function consumeStream(res) {
71
+ return new Promise((resolve, reject) => {
72
+ const chunks = []
73
+
74
+ res.on('data', (chunk) => chunks.push(chunk))
75
+ res.on('end', () => resolve(Buffer.concat(chunks)))
76
+ res.on('error', reject)
77
+ })
78
+ }
79
+
80
+ function createImage(src, alt) {
81
+ const image = new Image()
82
+ image.src = src
83
+ if (typeof alt === 'string') image.alt = alt
84
+ return image
85
+ }
86
+
87
+ function isBufferLike(src) {
88
+ return (
89
+ Array.isArray(src) ||
90
+ src instanceof ArrayBuffer ||
91
+ src instanceof SharedArrayBuffer ||
92
+ src instanceof Object.getPrototypeOf(Uint8Array)
93
+ )
94
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napi-rs/canvas",
3
- "version": "0.1.24",
3
+ "version": "0.1.27",
4
4
  "description": "Canvas for Node.js with skia backend",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/Brooooooklyn/canvas.git",
@@ -22,7 +22,8 @@
22
22
  "index.d.ts",
23
23
  "index.js",
24
24
  "geometry.js",
25
- "js-binding.js"
25
+ "js-binding.js",
26
+ "load-image.js"
26
27
  ],
27
28
  "napi": {
28
29
  "name": "skia",
@@ -65,7 +66,7 @@
65
66
  "@jimp/jpeg": "^0.16.1",
66
67
  "@jimp/png": "^0.16.1",
67
68
  "@napi-rs/cli": "^2.9.0",
68
- "@octokit/rest": "^18.12.0",
69
+ "@octokit/rest": "^19.0.0",
69
70
  "@swc-node/register": "^1.5.1",
70
71
  "@types/lodash": "^4.14.182",
71
72
  "@types/node": "^17.0.35",
@@ -74,7 +75,7 @@
74
75
  "ava": "^4.2.0",
75
76
  "benny": "^3.7.1",
76
77
  "canvas": "^2.9.1",
77
- "canvaskit-wasm": "^0.34.0",
78
+ "canvaskit-wasm": "^0.35.0",
78
79
  "colorette": "^2.0.16",
79
80
  "conventional-changelog-cli": "^2.2.2",
80
81
  "echarts": "^5.3.2",
@@ -82,7 +83,7 @@
82
83
  "eslint-config-prettier": "^8.5.0",
83
84
  "eslint-plugin-import": "^2.26.0",
84
85
  "eslint-plugin-prettier": "^4.0.0",
85
- "eslint-plugin-sonarjs": "^0.13.0",
86
+ "eslint-plugin-sonarjs": "^0.15.0",
86
87
  "husky": "^8.0.1",
87
88
  "lint-staged": "^13.0.0",
88
89
  "lodash": "^4.17.21",
@@ -90,7 +91,7 @@
90
91
  "pinst": "^3.0.0",
91
92
  "png.js": "^0.2.1",
92
93
  "prettier": "^2.6.2",
93
- "skia-canvas": "^0.9.29",
94
+ "skia-canvas": "^1.0.0",
94
95
  "typescript": "^4.7.2"
95
96
  },
96
97
  "lint-staged": {
@@ -108,6 +109,10 @@
108
109
  "extensions": [
109
110
  "ts"
110
111
  ],
112
+ "files": [
113
+ "__test__/**/*.spec.ts",
114
+ "scripts/__test__/**/*.spec.ts"
115
+ ],
111
116
  "workerThreads": false,
112
117
  "cache": false,
113
118
  "timeout": "3m",
@@ -123,16 +128,16 @@
123
128
  "singleQuote": true,
124
129
  "arrowParens": "always"
125
130
  },
126
- "packageManager": "yarn@3.2.1",
131
+ "packageManager": "yarn@3.2.2",
127
132
  "optionalDependencies": {
128
- "@napi-rs/canvas-win32-x64-msvc": "0.1.24",
129
- "@napi-rs/canvas-darwin-x64": "0.1.24",
130
- "@napi-rs/canvas-linux-x64-gnu": "0.1.24",
131
- "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.24",
132
- "@napi-rs/canvas-linux-x64-musl": "0.1.24",
133
- "@napi-rs/canvas-linux-arm64-gnu": "0.1.24",
134
- "@napi-rs/canvas-linux-arm64-musl": "0.1.24",
135
- "@napi-rs/canvas-darwin-arm64": "0.1.24",
136
- "@napi-rs/canvas-android-arm64": "0.1.24"
133
+ "@napi-rs/canvas-win32-x64-msvc": "0.1.27",
134
+ "@napi-rs/canvas-darwin-x64": "0.1.27",
135
+ "@napi-rs/canvas-linux-x64-gnu": "0.1.27",
136
+ "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.27",
137
+ "@napi-rs/canvas-linux-x64-musl": "0.1.27",
138
+ "@napi-rs/canvas-linux-arm64-gnu": "0.1.27",
139
+ "@napi-rs/canvas-linux-arm64-musl": "0.1.27",
140
+ "@napi-rs/canvas-darwin-arm64": "0.1.27",
141
+ "@napi-rs/canvas-android-arm64": "0.1.27"
137
142
  }
138
143
  }