diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..3150993
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,5 @@
+.eslintrc.js
+examples
+node_modules
+harfbuzz
+*.wasm
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..3e67c5a
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,155 @@
+const { defineConfig } = require('eslint-define-config')
+
+module.exports = defineConfig({
+ env: {
+ es6: true,
+ browser: true,
+ node: true,
+ },
+ plugins: ['@typescript-eslint'],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:import/recommended',
+ 'plugin:eslint-comments/recommended',
+ 'plugin:@typescript-eslint/recommended'
+ ],
+ settings: {
+ 'import/resolver': {
+ node: { extensions: ['.js', '.mjs', '.ts', '.d.ts'] },
+ },
+ },
+ overrides: [
+ {
+ files: ['*.ts'],
+ rules: {
+ 'no-undef': 'off',
+ },
+ },
+ {
+ files: ['**/__tests__/**'],
+ rules: {
+ 'no-console': 'off'
+ },
+ },
+ {
+ files: ['*.d.ts'],
+ rules: {
+ 'import/no-duplicates': 'off',
+ },
+ },
+ {
+ files: ['*.js'],
+ rules: {
+ '@typescript-eslint/no-var-requires': 'off',
+ },
+ }
+ ],
+ rules: {
+ // js/ts
+ 'no-console': ['warn', { allow: ['error'] }],
+ 'no-debugger': 'warn',
+ 'no-constant-condition': ['error', { checkLoops: false }],
+ 'no-restricted-syntax': ['error', 'LabeledStatement', 'WithStatement'],
+ 'no-return-await': 'error',
+ 'no-var': 'error',
+ 'no-empty': ['error', { allowEmptyCatch: true }],
+ 'prefer-const': [
+ 'warn',
+ { destructuring: 'all', ignoreReadBeforeAssign: true },
+ ],
+ 'prefer-arrow-callback': [
+ 'error',
+ { allowNamedFunctions: false, allowUnboundThis: true },
+ ],
+ 'object-shorthand': [
+ 'error',
+ 'always',
+ { ignoreConstructors: false, avoidQuotes: true },
+ ],
+ 'prefer-rest-params': 'error',
+ 'prefer-spread': 'error',
+ 'prefer-template': 'error',
+
+ 'no-redeclare': 'off',
+ '@typescript-eslint/no-redeclare': 'error',
+
+ // best-practice
+ 'array-callback-return': 'error',
+ 'block-scoped-var': 'error',
+ 'no-alert': 'warn',
+ 'no-case-declarations': 'error',
+ 'no-multi-str': 'error',
+ 'no-with': 'error',
+ 'no-void': 'error',
+
+ 'sort-imports': [
+ 'warn',
+ {
+ ignoreCase: false,
+ ignoreDeclarationSort: true,
+ ignoreMemberSort: false,
+ memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
+ allowSeparatedGroups: false,
+ },
+ ],
+
+ // stylistic-issues
+ 'prefer-exponentiation-operator': 'error',
+
+ // ts
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
+ '@typescript-eslint/no-explicit-any': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ '@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
+ '@typescript-eslint/consistent-type-imports': [
+ 'error',
+ { disallowTypeAnnotations: false },
+ ],
+
+ // import
+ 'import/first': 'error',
+ 'import/no-duplicates': 'error',
+ 'import/order': [
+ 'error',
+ {
+ groups: [
+ 'builtin',
+ 'external',
+ 'internal',
+ 'parent',
+ 'sibling',
+ 'index',
+ 'object',
+ 'type',
+ ],
+
+ pathGroups: [
+ {
+ pattern: 'vue',
+ group: 'external',
+ position: 'before',
+ },
+ {
+ pattern: '@vue/**',
+ group: 'external',
+ position: 'before',
+ },
+ {
+ pattern: '@element-plus/**',
+ group: 'internal',
+ },
+ ],
+ pathGroupsExcludedImportTypes: ['type'],
+ },
+ ],
+ 'import/no-unresolved': 'off',
+ 'import/namespace': 'off',
+ 'import/default': 'off',
+ 'import/no-named-as-default': 'off',
+ 'import/no-named-as-default-member': 'off',
+ 'import/named': 'off',
+
+ // eslint-plugin-eslint-comments
+ 'eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
+ },
+})
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9a95569..7f3a96c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
*.wasm
-.DS_Store
\ No newline at end of file
+.DS_Store
+node_modules
+dist
\ No newline at end of file
diff --git a/examples/hbjs.example.html b/examples/hbjs.example.html
deleted file mode 100644
index e2ba792..0000000
--- a/examples/hbjs.example.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
diff --git a/examples/hbjs.example.js b/examples/hbjs.example.js
deleted file mode 100644
index b7718e9..0000000
--- a/examples/hbjs.example.js
+++ /dev/null
@@ -1,37 +0,0 @@
-function example(hb, fontBlob, text) {
- var blob = hb.createBlob(fontBlob);
- var face = hb.createFace(blob, 0);
- // console.log(face.getAxisInfos());
- var font = hb.createFont(face);
- // font.setVariations({ wdth: 200, wght: 700 });
- font.setScale(1000, 1000); // Optional, if not given will be in font upem
-
- var buffer = hb.createBuffer();
- buffer.addText(text || 'abc');
- buffer.guessSegmentProperties();
- // buffer.setDirection('ltr'); // optional as can be set by guessSegmentProperties also
- hb.shape(font, buffer); // features are not supported yet
- var result = buffer.json(font);
-
- // returns glyphs paths, totally optional
- var glyphs = {};
- result.forEach(function (x) {
- if (glyphs[x.g]) return;
- glyphs[x.g] = {
- name: font.glyphName(x.g),
- path: font.glyphToPath(x.g),
- json: font.glyphToJson(x.g)
- };
- });
-
- var unicodes = face.collectUnicodes()
-
- buffer.destroy();
- font.destroy();
- face.destroy();
- blob.destroy();
- return { shape: result, glyphs: glyphs, unicodes: unicodes };
-}
-
-// Should be replaced with something more reliable
-try { module.exports = example; } catch(e) {}
diff --git a/harfbuzz.ts b/harfbuzz.ts
deleted file mode 100644
index 486f315..0000000
--- a/harfbuzz.ts
+++ /dev/null
@@ -1,289 +0,0 @@
-type Pointer = number;
-
-const HB_MEMORY_MODE_WRITABLE: number = 2;
-const HB_SET_VALUE_INVALID: Pointer = -1;
-
-class HarfBuzzExports {
- readonly heapu8: Uint8Array;
- readonly heapu32: Uint32Array;
- readonly heapi32: Int32Array;
- readonly utf8Encoder: TextEncoder;
-
- //exported HarfBuzz methods
- readonly malloc: (length: number) => Pointer
- readonly free: (ptr: Pointer) => void
- readonly free_ptr: () => Pointer
- readonly hb_blob_create: (data: Pointer, length: number, memoryMode: number, useData: Pointer, destroyFunction: Pointer) => Pointer
- readonly hb_blob_destroy: (ptr: Pointer) => void
- readonly hb_face_create: (blobPtr: Pointer, index: number) => Pointer
- readonly hb_face_get_upem: (facePtr: Pointer) => number
- readonly hb_face_destroy: (ptr: Pointer) => void
- readonly hb_font_create: (facePtr: Pointer) => Pointer
- readonly hb_font_set_scale: (fontPtr: Pointer, xScale: number, yScale: number) => void
- readonly hb_font_destroy: (ptr: Pointer) => void
- readonly hb_face_collect_unicodes: (facePtr: Pointer, setPtr: Pointer) => void
- readonly hb_set_create: () => Pointer
- readonly hb_set_destroy: (setPtr: Pointer) => void
- readonly hb_set_get_population: (setPtr: Pointer) => number
- readonly hb_set_next_many: (
- setPtr: Pointer,
- greaterThanUnicodePtr: Pointer,
- outputU32ArrayPtr: Pointer,
- size: number,
- ) => number
- readonly hb_buffer_create: () => Pointer
- readonly hb_buffer_add_utf8: (bufferPtr: Pointer, stringPtr: Pointer, stringLength: number, itemOffset: number, itemLength: number) => void
- readonly hb_buffer_guess_segment_properties: (bufferPtr: Pointer) => void
- readonly hb_buffer_set_direction: (bufferPtr: Pointer, direction: number) => void
- readonly hb_shape: (fontPtr: Pointer, bufferPtr: Pointer, features: any, numFeatures: number) => void
- readonly hb_buffer_get_length: (bufferPtr: Pointer) => number
- readonly hb_buffer_get_glyph_infos: (bufferPtr: Pointer, length: number) => any
- readonly hb_buffer_get_glyph_positions: (bufferPtr: Pointer, length: number) => any
- readonly hb_buffer_destroy: (bufferPtr: Pointer) => void
-
- constructor(exports: any) {
- this.heapu8 = new Uint8Array(exports.memory.buffer);
- this.heapu32 = new Uint32Array(exports.memory.buffer);
- this.heapi32 = new Int32Array(exports.memory.buffer);
- this.utf8Encoder = new TextEncoder();
-
- this.malloc = exports.malloc;
- this.free = exports.free;
- this.free_ptr = exports.free_ptr;
- this.hb_blob_destroy = exports.hb_blob_destroy;
- this.hb_blob_create = exports.hb_blob_create;
- this.hb_face_create = exports.hb_face_create;
- this.hb_face_get_upem = exports.hb_face_get_upem;
- this.hb_face_destroy = exports.hb_face_destroy;
- this.hb_face_collect_unicodes = exports.hb_face_collect_unicodes;
- this.hb_set_create = exports.hb_set_create;
- this.hb_set_destroy = exports.hb_set_destroy;
- this.hb_set_get_population = exports.hb_set_get_population;
- this.hb_set_next_many = exports.hb_set_next_many;
- this.hb_font_create = exports.hb_font_create;
- this.hb_font_set_scale = exports.hb_font_set_scale;
- this.hb_font_destroy = exports.hb_font_destroy;
- this.hb_buffer_create = exports.hb_buffer_create;
- this.hb_buffer_add_utf8 = exports.hb_buffer_add_utf8;
- this.hb_buffer_guess_segment_properties = exports.hb_buffer_guess_segment_properties;
- this.hb_buffer_set_direction = exports.hb_buffer_set_direction;
- this.hb_shape = exports.hb_shape;
- this.hb_buffer_get_length = exports.hb_buffer_get_length;
- this.hb_buffer_get_glyph_infos = exports.hb_buffer_get_glyph_infos;
- this.hb_buffer_get_glyph_positions = exports.hb_buffer_get_glyph_positions;
- this.hb_buffer_destroy = exports.hb_buffer_destroy;
- }
-
-}
-
-let hb: HarfBuzzExports;
-
-class CString {
- readonly ptr: Pointer;
- readonly length: number;
-
- constructor(text: string) {
- var bytes = hb.utf8Encoder.encode(text);
- this.ptr = hb.malloc(bytes.byteLength);
- hb.heapu8.set(bytes, this.ptr);
- this.length = bytes.byteLength;
- }
-
- destroy() {
- hb.free(this.ptr);
- }
-}
-
-export class HarfBuzzBlob {
- readonly ptr: Pointer;
-
- constructor(data: Uint8Array) {
- let blobPtr = hb.malloc(data.length);
- hb.heapu8.set(data, blobPtr);
- this.ptr = hb.hb_blob_create(blobPtr, data.byteLength, HB_MEMORY_MODE_WRITABLE, blobPtr, hb.free_ptr());
- }
-
- destroy() {
- hb.hb_blob_destroy(this.ptr);
- }
-}
-
-function typedArrayFromSet(setPtr: Pointer, arrayType: T) {
- const heap = hb[`heap${arrayType}`];
- const bytesPerElment = heap.BYTES_PER_ELEMENT;
- const setCount = hb.hb_set_get_population(setPtr);
- const arrayPtr = hb.malloc(
- setCount * bytesPerElment,
- );
- const arrayOffset = arrayPtr / bytesPerElment;
- const array = heap.subarray(
- arrayOffset,
- arrayOffset + setCount,
- ) as typeof hb[`heap${T}`];
- heap.set(array, arrayOffset);
- hb.hb_set_next_many(
- setPtr,
- HB_SET_VALUE_INVALID,
- arrayPtr,
- setCount,
- );
- return array;
-}
-
-export class HarfBuzzFace {
- readonly ptr: Pointer;
-
- constructor(blob: HarfBuzzBlob, index: number) {
- this.ptr = hb.hb_face_create(blob.ptr, index);
- }
-
- getUnitsPerEM() {
- return hb.hb_face_get_upem(this.ptr);
- }
-
- collectUnicodes() {
- const unicodeSetPtr = hb.hb_set_create();
- hb.hb_face_collect_unicodes(this.ptr, unicodeSetPtr);
- const result = typedArrayFromSet(unicodeSetPtr, 'u32');
- hb.hb_set_destroy(unicodeSetPtr);
- return result;
- }
-
- destroy() {
- hb.hb_face_destroy(this.ptr);
- }
-}
-
-export class HarfBuzzFont {
- readonly ptr: Pointer
- readonly unitsPerEM: number
-
- constructor(face: HarfBuzzFace) {
- this.ptr = hb.hb_font_create(face.ptr);
- this.unitsPerEM = face.getUnitsPerEM();
- }
-
- setScale(xScale: number, yScale: number) {
- hb.hb_font_set_scale(this.ptr, xScale, yScale);
- }
-
- destroy() {
- hb.hb_font_destroy(this.ptr);
- }
-}
-
-export type HarfBuzzDirection = "ltr" | "rtl" | "ttb" | "btt"
-
-class GlyphInformation {
- readonly GlyphId: number
- readonly Cluster: number
- readonly XAdvance: number
- readonly YAdvance: number
- readonly XOffset: number
- readonly YOffset: number
-
- constructor(glyphId: number, cluster: number, xAdvance: number, yAdvance: number, xOffset: number, yOffset: number) {
- this.GlyphId = glyphId;
- this.Cluster = cluster;
- this.XAdvance = xAdvance;
- this.YAdvance = yAdvance;
- this.XOffset = xOffset;
- this.YOffset = yOffset;
- }
-}
-
-export class HarfBuzzBuffer {
- readonly ptr: Pointer
-
- constructor() {
- this.ptr = hb.hb_buffer_create();
- }
-
- addText(text: string) {
- let str = new CString(text);
- hb.hb_buffer_add_utf8(this.ptr, str.ptr, str.length, 0, str.length);
- str.destroy();
- }
-
- guessSegmentProperties() {
- hb.hb_buffer_guess_segment_properties(this.ptr);
- }
-
- setDirection(direction: HarfBuzzDirection) {
- let d = { "ltr": 4, "rtl": 5, "ttb": 6, "btt": 7 }[direction];
- hb.hb_buffer_set_direction(this.ptr, d);
- }
-
- json() {
- var length = hb.hb_buffer_get_length(this.ptr);
- var result = new Array();
- var infosPtr32 = hb.hb_buffer_get_glyph_infos(this.ptr, 0) / 4;
- var positionsPtr32 = hb.hb_buffer_get_glyph_positions(this.ptr, 0) / 4;
- var infos = hb.heapu32.subarray(infosPtr32, infosPtr32 + 5 * length);
- var positions = hb.heapi32.subarray(positionsPtr32, positionsPtr32 + 5 * length);
- for (var i = 0; i < length; ++i) {
- result.push(new GlyphInformation(
- infos[i * 5 + 0],
- infos[i * 5 + 2],
- positions[i * 5 + 0],
- positions[i * 5 + 1],
- positions[i * 5 + 2],
- positions[i * 5 + 3]));
- }
- return result;
- }
-
- destroy() {
- hb.hb_buffer_destroy(this.ptr)
- }
-}
-
-export function shape(text: string, font: HarfBuzzFont, features: any): Array {
- let buffer = new HarfBuzzBuffer();
- buffer.addText(text);
- buffer.guessSegmentProperties();
- buffer.shape(font, features);
- let result = buffer.json();
- buffer.destroy();
- return result;
-}
-
-export function getWidth(text: string, font: HarfBuzzFont, fontSizeInPixel: number, features: any): number {
- let scale = fontSizeInPixel / font.unitsPerEM;
- let shapeResult = shape(text, font, features);
- let totalWidth = shapeResult.map((glyphInformation) => {
- return glyphInformation.XAdvance;
- }).reduce((previous, current, i, arr) => {
- return previous + current;
- }, 0.0);
-
- return totalWidth * scale;
-}
-
-export const harfbuzzFonts = new Map();
-
-export function loadHarfbuzz(webAssemblyUrl: string): Promise {
- return fetch(webAssemblyUrl).then(response => {
- return response.arrayBuffer();
- }).then(wasm => {
- return WebAssembly.instantiate(wasm);
- }).then(result => {
- //@ts-ignore
- hb = new HarfBuzzExports(result.instance.exports);
- });
-}
-
-export function loadAndCacheFont(fontName: string, fontUrl: string): Promise {
- return fetch(fontUrl).then((response) => {
- return response.arrayBuffer().then((blob) => {
- let fontBlob = new Uint8Array(blob);
- let harfbuzzBlob = new HarfBuzzBlob(fontBlob);
- let harfbuzzFace = new HarfBuzzFace(harfbuzzBlob, 0);
- let harfbuzzFont = new HarfBuzzFont(harfbuzzFace);
-
- harfbuzzFonts.set(fontName, harfbuzzFont);
- harfbuzzFace.destroy();
- harfbuzzBlob.destroy();
- });
- });
-}
\ No newline at end of file
diff --git a/hbjs.js b/hbjs.js
deleted file mode 100644
index 78bdbde..0000000
--- a/hbjs.js
+++ /dev/null
@@ -1,450 +0,0 @@
-function hbjs(instance) {
- 'use strict';
-
- var exports = instance.exports;
- var heapu8 = new Uint8Array(exports.memory.buffer);
- var heapu32 = new Uint32Array(exports.memory.buffer);
- var heapi32 = new Int32Array(exports.memory.buffer);
- var heapf32 = new Float32Array(exports.memory.buffer);
- var utf8Decoder = new TextDecoder("utf8");
-
- var HB_MEMORY_MODE_WRITABLE = 2;
- var HB_SET_VALUE_INVALID = -1;
-
- function hb_tag(s) {
- return (
- (s.charCodeAt(0) & 0xFF) << 24 |
- (s.charCodeAt(1) & 0xFF) << 16 |
- (s.charCodeAt(2) & 0xFF) << 8 |
- (s.charCodeAt(3) & 0xFF) << 0
- );
- }
-
- function _hb_untag(tag) {
- return [
- String.fromCharCode((tag >> 24) & 0xFF),
- String.fromCharCode((tag >> 16) & 0xFF),
- String.fromCharCode((tag >> 8) & 0xFF),
- String.fromCharCode((tag >> 0) & 0xFF)
- ].join('');
- }
-
- function _buffer_flag(s) {
- if (s == "BOT") { return 0x1; }
- if (s == "EOT") { return 0x2; }
- if (s == "PRESERVE_DEFAULT_IGNORABLES") { return 0x4; }
- if (s == "REMOVE_DEFAULT_IGNORABLES") { return 0x8; }
- if (s == "DO_NOT_INSERT_DOTTED_CIRCLE") { return 0x10; }
- if (s == "PRODUCE_UNSAFE_TO_CONCAT") { return 0x40; }
- return 0x0;
- }
-
- /**
- * Create an object representing a Harfbuzz blob.
- * @param {string} blob A blob of binary data (usually the contents of a font file).
- **/
- function createBlob(blob) {
- var blobPtr = exports.malloc(blob.byteLength);
- heapu8.set(new Uint8Array(blob), blobPtr);
- var ptr = exports.hb_blob_create(blobPtr, blob.byteLength, HB_MEMORY_MODE_WRITABLE, blobPtr, exports.free_ptr());
- return {
- ptr: ptr,
- /**
- * Free the object.
- */
- destroy: function () { exports.hb_blob_destroy(ptr); }
- };
- }
-
- /**
- * Return the typed array of HarfBuzz set contents.
- * @template {typeof Uint8Array | typeof Uint32Array | typeof Int32Array | typeof Float32Array} T
- * @param {number} setPtr Pointer of set
- * @param {T} arrayClass Typed array class
- * @returns {InstanceType} Typed array instance
- */
- function typedArrayFromSet(setPtr, arrayClass) {
- let heap = heapu8;
- if (arrayClass === Uint32Array) {
- heap = heapu32;
- } else if (arrayClass === Int32Array) {
- heap = heapi32;
- } else if (arrayClass === Float32Array) {
- heap = heapf32;
- }
- const bytesPerElment = arrayClass.BYTES_PER_ELEMENT;
- const setCount = exports.hb_set_get_population(setPtr);
- const arrayPtr = exports.malloc(
- setCount * bytesPerElment,
- );
- const arrayOffset = arrayPtr / bytesPerElment;
- const array = heap.subarray(
- arrayOffset,
- arrayOffset + setCount,
- );
- heap.set(array, arrayOffset);
- exports.hb_set_next_many(
- setPtr,
- HB_SET_VALUE_INVALID,
- arrayPtr,
- setCount,
- );
- return array;
- }
-
- /**
- * Create an object representing a Harfbuzz face.
- * @param {object} blob An object returned from `createBlob`.
- * @param {number} index The index of the font in the blob. (0 for most files,
- * or a 0-indexed font number if the `blob` came form a TTC/OTC file.)
- **/
- function createFace(blob, index) {
- var ptr = exports.hb_face_create(blob.ptr, index);
- const upem = exports.hb_face_get_upem(ptr);
- return {
- ptr: ptr,
- upem,
- /**
- * Return the binary contents of an OpenType table.
- * @param {string} table Table name
- */
- reference_table: function(table) {
- var blob = exports.hb_face_reference_table(ptr, hb_tag(table));
- var length = exports.hb_blob_get_length(blob);
- if (!length) { return; }
- var blobptr = exports.hb_blob_get_data(blob, null);
- var table_string = heapu8.subarray(blobptr, blobptr+length);
- return table_string;
- },
- /**
- * Return variation axis infos
- */
- getAxisInfos: function() {
- var axis = exports.malloc(64 * 32);
- var c = exports.malloc(4);
- heapu32[c / 4] = 64;
- exports.hb_ot_var_get_axis_infos(ptr, 0, c, axis);
- var result = {};
- Array.from({ length: heapu32[c / 4] }).forEach(function (_, i) {
- result[_hb_untag(heapu32[axis / 4 + i * 8 + 1])] = {
- min: heapf32[axis / 4 + i * 8 + 4],
- default: heapf32[axis / 4 + i * 8 + 5],
- max: heapf32[axis / 4 + i * 8 + 6]
- };
- });
- exports.free(c);
- exports.free(axis);
- return result;
- },
- /**
- * Return unicodes the face supports
- */
- collectUnicodes: function() {
- var unicodeSetPtr = exports.hb_set_create();
- exports.hb_face_collect_unicodes(ptr, unicodeSetPtr);
- var result = typedArrayFromSet(unicodeSetPtr, Uint32Array);
- exports.hb_set_destroy(unicodeSetPtr);
- return result;
- },
- /**
- * Free the object.
- */
- destroy: function () {
- exports.hb_face_destroy(ptr);
- },
- };
- }
-
- var pathBufferSize = 65536; // should be enough for most glyphs
- var pathBuffer = exports.malloc(pathBufferSize); // permanently allocated
-
- var nameBufferSize = 256; // should be enough for most glyphs
- var nameBuffer = exports.malloc(nameBufferSize); // permanently allocated
-
- /**
- * Create an object representing a Harfbuzz font.
- * @param {object} blob An object returned from `createFace`.
- **/
- function createFont(face) {
- var ptr = exports.hb_font_create(face.ptr);
-
- /**
- * Return a glyph as an SVG path string.
- * @param {number} glyphId ID of the requested glyph in the font.
- **/
- function glyphToPath(glyphId) {
- var svgLength = exports.hbjs_glyph_svg(ptr, glyphId, pathBuffer, pathBufferSize);
- return svgLength > 0 ? utf8Decoder.decode(heapu8.subarray(pathBuffer, pathBuffer + svgLength)) : "";
- }
-
- /**
- * Return glyph name.
- * @param {number} glyphId ID of the requested glyph in the font.
- **/
- function glyphName(glyphId) {
- exports.hb_font_glyph_to_string(
- ptr,
- glyphId,
- nameBuffer,
- nameBufferSize
- );
- var array = heapu8.subarray(nameBuffer, nameBuffer + nameBufferSize);
- return utf8Decoder.decode(array.slice(0, array.indexOf(0)));
- }
-
- return {
- ptr: ptr,
- glyphName: glyphName,
- glyphToPath: glyphToPath,
- /**
- * Return a glyph as a JSON path string
- * based on format described on https://svgwg.org/specs/paths/#InterfaceSVGPathSegment
- * @param {number} glyphId ID of the requested glyph in the font.
- **/
- glyphToJson: function (glyphId) {
- var path = glyphToPath(glyphId);
- return path.replace(/([MLQCZ])/g, '|$1 ').split('|').filter(function (x) { return x.length; }).map(function (x) {
- var row = x.split(/[ ,]/g);
- return { type: row[0], values: row.slice(1).filter(function (x) { return x.length; }).map(function (x) { return +x; }) };
- });
- },
- /**
- * Set the font's scale factor, affecting the position values returned from
- * shaping.
- * @param {number} xScale Units to scale in the X dimension.
- * @param {number} yScale Units to scale in the Y dimension.
- **/
- setScale: function (xScale, yScale) {
- exports.hb_font_set_scale(ptr, xScale, yScale);
- },
- /**
- * Set the font's variations.
- * @param {object} variations Dictionary of variations to set
- **/
- setVariations: function (variations) {
- var entries = Object.entries(variations);
- var vars = exports.malloc(8 * entries.length);
- entries.forEach(function (entry, i) {
- heapu32[vars / 4 + i * 2 + 0] = hb_tag(entry[0]);
- heapf32[vars / 4 + i * 2 + 1] = entry[1];
- });
- exports.hb_font_set_variations(ptr, vars, entries.length);
- exports.free(vars);
- },
- /**
- * Free the object.
- */
- destroy: function () { exports.hb_font_destroy(ptr); }
- };
- }
-
- /**
- * Use when you know the input range should be ASCII.
- * Faster than encoding to UTF-8
- **/
- function createAsciiString(text) {
- var ptr = exports.malloc(text.length + 1);
- for (let i = 0; i < text.length; ++i) {
- const char = text.charCodeAt(i);
- if (char > 127) throw new Error('Expected ASCII text');
- heapu8[ptr + i] = char;
- }
- heapu8[ptr + text.length] = 0;
- return {
- ptr: ptr,
- length: text.length,
- free: function () { exports.free(ptr); }
- };
- }
-
- function createJsString(text) {
- const ptr = exports.malloc(text.length * 2);
- const words = new Uint16Array(exports.memory.buffer, ptr, text.length);
- for (let i = 0; i < words.length; ++i) words[i] = text.charCodeAt(i);
- return {
- ptr: ptr,
- length: words.length,
- free: function () { exports.free(ptr); }
- };
- }
-
- /**
- * Create an object representing a Harfbuzz buffer.
- **/
- function createBuffer() {
- var ptr = exports.hb_buffer_create();
- return {
- ptr: ptr,
- /**
- * Add text to the buffer.
- * @param {string} text Text to be added to the buffer.
- **/
- addText: function (text) {
- const str = createJsString(text);
- exports.hb_buffer_add_utf16(ptr, str.ptr, str.length, 0, str.length);
- str.free();
- },
- /**
- * Set buffer script, language and direction.
- *
- * This needs to be done before shaping.
- **/
- guessSegmentProperties: function () {
- return exports.hb_buffer_guess_segment_properties(ptr);
- },
- /**
- * Set buffer direction explicitly.
- * @param {string} direction: One of "ltr", "rtl", "ttb" or "btt"
- */
- setDirection: function (dir) {
- exports.hb_buffer_set_direction(ptr, {
- ltr: 4,
- rtl: 5,
- ttb: 6,
- btt: 7
- }[dir] || 0);
- },
- /**
- * Set buffer flags explicitly.
- * @param {string[]} flags: A list of strings which may be either:
- * "BOT"
- * "EOT"
- * "PRESERVE_DEFAULT_IGNORABLES"
- * "REMOVE_DEFAULT_IGNORABLES"
- * "DO_NOT_INSERT_DOTTED_CIRCLE"
- * "PRODUCE_UNSAFE_TO_CONCAT"
- */
- setFlags: function (flags) {
- var flagValue = 0
- flags.forEach(function (s) {
- flagValue |= _buffer_flag(s);
- })
-
- exports.hb_buffer_set_flags(ptr,flagValue);
- },
- /**
- * Set buffer language explicitly.
- * @param {string} language: The buffer language
- */
- setLanguage: function (language) {
- var str = createAsciiString(language);
- exports.hb_buffer_set_language(ptr, exports.hb_language_from_string(str.ptr,-1));
- str.free();
- },
- /**
- * Set buffer script explicitly.
- * @param {string} script: The buffer script
- */
- setScript: function (script) {
- var str = createAsciiString(script);
- exports.hb_buffer_set_script(ptr, exports.hb_script_from_string(str.ptr,-1));
- str.free();
- },
-
- /**
- * Set the Harfbuzz clustering level.
- *
- * Affects the cluster values returned from shaping.
- * @param {number} level: Clustering level. See the Harfbuzz manual chapter
- * on Clusters.
- **/
- setClusterLevel: function (level) {
- exports.hb_buffer_set_cluster_level(ptr, level)
- },
- /**
- * Return the buffer contents as a JSON object.
- *
- * After shaping, this function will return an array of glyph information
- * objects. Each object will have the following attributes:
- *
- * - g: The glyph ID
- * - cl: The cluster ID
- * - ax: Advance width (width to advance after this glyph is painted)
- * - ay: Advance height (height to advance after this glyph is painted)
- * - dx: X displacement (adjustment in X dimension when painting this glyph)
- * - dy: Y displacement (adjustment in Y dimension when painting this glyph)
- * - flags: Glyph flags like `HB_GLYPH_FLAG_UNSAFE_TO_BREAK` (0x1)
- **/
- json: function () {
- var length = exports.hb_buffer_get_length(ptr);
- var result = [];
- var infosPtr = exports.hb_buffer_get_glyph_infos(ptr, 0);
- var infosPtr32 = infosPtr / 4;
- var positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4;
- var infos = heapu32.subarray(infosPtr32, infosPtr32 + 5 * length);
- var positions = heapi32.subarray(positionsPtr32, positionsPtr32 + 5 * length);
- for (var i = 0; i < length; ++i) {
- result.push({
- g: infos[i * 5 + 0],
- cl: infos[i * 5 + 2],
- ax: positions[i * 5 + 0],
- ay: positions[i * 5 + 1],
- dx: positions[i * 5 + 2],
- dy: positions[i * 5 + 3],
- flags: exports.hb_glyph_info_get_glyph_flags(infosPtr + i * 20)
- });
- }
- return result;
- },
- /**
- * Free the object.
- */
- destroy: function () { exports.hb_buffer_destroy(ptr); }
- };
- }
-
- /**
- * Shape a buffer with a given font.
- *
- * This returns nothing, but modifies the buffer.
- *
- * @param {object} font: A font returned from `createFont`
- * @param {object} buffer: A buffer returned from `createBuffer` and suitably
- * prepared.
- * @param {object} features: (Currently unused).
- */
- function shape(font, buffer, features) {
- exports.hb_shape(font.ptr, buffer.ptr, 0, 0);
- }
-
- /**
- * Shape a buffer with a given font, returning a JSON trace of the shaping process.
- *
- * This function supports "partial shaping", where the shaping process is
- * terminated after a given lookup ID is reached. If the user requests the function
- * to terminate shaping after an ID in the GSUB phase, GPOS table lookups will be
- * processed as normal.
- *
- * @param {object} font: A font returned from `createFont`
- * @param {object} buffer: A buffer returned from `createBuffer` and suitably
- * prepared.
- * @param {object} features: A dictionary of OpenType features to apply.
- * @param {number} stop_at: A lookup ID at which to terminate shaping.
- * @param {number} stop_phase: Either 0 (don't terminate shaping), 1 (`stop_at`
- refers to a lookup ID in the GSUB table), 2 (`stop_at` refers to a lookup
- ID in the GPOS table).
- */
-
- function shapeWithTrace(font, buffer, features, stop_at, stop_phase) {
- var bufLen = 1024 * 1024;
- var traceBuffer = exports.malloc(bufLen);
- var featurestr = createAsciiString(features);
- var traceLen = exports.hbjs_shape_with_trace(font.ptr, buffer.ptr, featurestr.ptr, stop_at, stop_phase, traceBuffer, bufLen);
- featurestr.free();
- var trace = utf8Decoder.decode(heapu8.subarray(traceBuffer, traceBuffer + traceLen - 1));
- exports.free(traceBuffer);
- return JSON.parse(trace);
- }
-
- return {
- createBlob: createBlob,
- createFace: createFace,
- createFont: createFont,
- createBuffer: createBuffer,
- shape: shape,
- shapeWithTrace: shapeWithTrace
- };
-};
-
-// Should be replaced with something more reliable
-try { module.exports = hbjs; } catch(e) {}
diff --git a/index.js b/index.js
deleted file mode 100644
index 3931d54..0000000
--- a/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-var fs = require('fs');
-var path = require('path');
-var hbjs = require('./hbjs.js')
-
-module.exports = new Promise(function (resolve, reject) {
- fs.readFile(path.resolve(__dirname, 'hb.wasm'), function (err, data) {
- if (err) { reject(err); return; }
- WebAssembly.instantiate(data).then(function (result) {
- resolve(hbjs(result.instance));
- }, reject);
- });
-});
diff --git a/package.json b/package.json
index ffbd428..813b6c9 100644
--- a/package.json
+++ b/package.json
@@ -2,9 +2,51 @@
"name": "harfbuzzjs",
"version": "0.3.3",
"description": "Minimal version of HarfBuzz for JavaScript use",
- "main": "index.js",
+ "packageManager": "pnpm@8.6.3",
+ "type": "module",
+ "engines": {
+ "node": ">= 16"
+ },
+ "main": "dist/node/node.js",
+ "module": "dist/node/node.mjs",
+ "types": "dist/node/node.d.ts",
+ "files": [
+ "dist",
+ "hb.wasm"
+ ],
"scripts": {
- "test": "mocha test/index.js"
+ "prepare": "simple-git-hooks",
+ "build": "rimraf dist && tsup",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.ts",
+ "lint:fix": "eslint ./src/**/*.ts --fix"
+ },
+ "simple-git-hooks": {
+ "pre-commit": "pnpm exec lint-staged"
+ },
+ "lint-staged": {
+ "packages/**/*.ts": [
+ "pnpm lint"
+ ]
+ },
+ "exports": {
+ ".": {
+ "import": {
+ "default": "./dist/node/node.mjs",
+ "types": "./dist/node/node.d.mts"
+ },
+ "require": {
+ "default": "./dist/node/node.js",
+ "types": "./dist/node/node.d.ts"
+ }
+ },
+ "./package.json": "./package.json",
+ "./client": {
+ "import": {
+ "default": "./dist/client/client.mjs",
+ "types": "./dist/client/client.d.mts"
+ }
+ }
},
"keywords": [
"harfbuzz",
@@ -31,7 +73,22 @@
},
"homepage": "https://github.com/harfbuzz/harfbuzzjs#readme",
"devDependencies": {
+ "@types/node": "^20.4.9",
+ "@typescript-eslint/eslint-plugin": "^6.3.0",
"chai": "^4.3.7",
- "mocha": "^10.2.0"
+ "eslint": "^8.46.0",
+ "eslint-config-standard": "^17.1.0",
+ "eslint-define-config": "^1.22.0",
+ "eslint-plugin-eslint-comments": "^3.2.0",
+ "eslint-plugin-import": "^2.28.0",
+ "eslint-plugin-n": "^16.0.1",
+ "eslint-plugin-promise": "^6.1.1",
+ "lint-staged": "^13.2.3",
+ "mocha": "^10.2.0",
+ "rimraf": "^5.0.1",
+ "simple-git-hooks": "^2.9.0",
+ "tsup": "^7.2.0",
+ "typescript": "^5.1.6",
+ "vitest": "^0.34.1"
}
}
diff --git a/playground/basic/.eslintrc.cjs b/playground/basic/.eslintrc.cjs
new file mode 100644
index 0000000..d6c9537
--- /dev/null
+++ b/playground/basic/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/playground/basic/.gitignore b/playground/basic/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/playground/basic/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/playground/basic/README.md b/playground/basic/README.md
new file mode 100644
index 0000000..1ebe379
--- /dev/null
+++ b/playground/basic/README.md
@@ -0,0 +1,27 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
+ tsconfigRootDir: __dirname,
+ },
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/playground/basic/index.html b/playground/basic/index.html
new file mode 100644
index 0000000..e4b78ea
--- /dev/null
+++ b/playground/basic/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/playground/basic/package.json b/playground/basic/package.json
new file mode 100644
index 0000000..cbc8061
--- /dev/null
+++ b/playground/basic/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "basic",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "harfbuzzjs": "workspace:*"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.15",
+ "@types/react-dom": "^18.2.7",
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "@typescript-eslint/parser": "^6.0.0",
+ "@vitejs/plugin-react": "^4.0.3",
+ "eslint": "^8.45.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.3",
+ "typescript": "^5.0.2",
+ "vite": "^4.4.5"
+ }
+}
diff --git a/playground/basic/public/vite.svg b/playground/basic/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/playground/basic/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/playground/basic/src/App.css b/playground/basic/src/App.css
new file mode 100644
index 0000000..b9d355d
--- /dev/null
+++ b/playground/basic/src/App.css
@@ -0,0 +1,42 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
diff --git a/playground/basic/src/App.tsx b/playground/basic/src/App.tsx
new file mode 100644
index 0000000..8acf680
--- /dev/null
+++ b/playground/basic/src/App.tsx
@@ -0,0 +1,24 @@
+import { useEffect, useState } from 'react'
+import './App.css'
+import { render } from './render'
+
+function App() {
+ const [res, setRes] = useState('')
+
+ useEffect(() => {
+ render()
+ .then(v => setRes(v))
+ .catch(e => {
+ console.error(e)
+ })
+ }, [])
+
+
+ return (
+
+ {res}
+
+ )
+}
+
+export default App
diff --git a/test/fonts/noto/NotoSans-Regular.ttf b/playground/basic/src/assets/NotoSans-Regular.ttf
similarity index 100%
rename from test/fonts/noto/NotoSans-Regular.ttf
rename to playground/basic/src/assets/NotoSans-Regular.ttf
diff --git a/playground/basic/src/assets/react.svg b/playground/basic/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/playground/basic/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/playground/basic/src/index.css b/playground/basic/src/index.css
new file mode 100644
index 0000000..2c3fac6
--- /dev/null
+++ b/playground/basic/src/index.css
@@ -0,0 +1,69 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/playground/basic/src/main.tsx b/playground/basic/src/main.tsx
new file mode 100644
index 0000000..3d7150d
--- /dev/null
+++ b/playground/basic/src/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.tsx'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/playground/basic/src/render.ts b/playground/basic/src/render.ts
new file mode 100644
index 0000000..c32c373
--- /dev/null
+++ b/playground/basic/src/render.ts
@@ -0,0 +1,54 @@
+import { hb as hbjs } from 'harfbuzzjs/client'
+import init from './assets/hb.wasm?init'
+import fontUrl from './assets/NotoSans-Regular.ttf?url'
+
+export async function render () {
+ const wasm = await init({})
+ const res = await fetch(fontUrl)
+ const data = await res.arrayBuffer()
+ return JSON.stringify(
+ preview(hbjs(wasm), new Uint8Array(data), ''),
+ undefined,
+ 2
+ )
+}
+
+function preview (hb: Awaited>, data: ArrayBuffer, text: string) {
+ const blob = hb.createBlob(data)
+ const face = hb.createFace(blob, 0)
+ const font = hb.createFont(face)
+ font.setScale(1000, 1000)
+ const buffer = hb.createBuffer()
+ buffer.addText(text || 'abc')
+ buffer.guessSegmentProperties()
+ hb.shape(font, buffer)
+ const shape = buffer.json()
+ const glyphs = shape
+ .reduce<{
+ [p: number]: {
+ name: string
+ path: string
+ json: {
+ type: string
+ values: number[]
+ }[]
+ }
+ }>((res, item) => {
+ if (item.g) return res
+
+ res[item.g] = {
+ name: font.glyphName(item.g),
+ path: font.glyphToPath(item.g),
+ json: font.glyphToJson(item.g)
+ }
+ return res
+ }, {})
+
+ const unicodes = face.collectUnicodes()
+
+ return {
+ shape,
+ glyphs,
+ unicodes
+ }
+}
\ No newline at end of file
diff --git a/playground/basic/src/vite-env.d.ts b/playground/basic/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/playground/basic/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/playground/basic/tsconfig.json b/playground/basic/tsconfig.json
new file mode 100644
index 0000000..a7fc6fb
--- /dev/null
+++ b/playground/basic/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/playground/basic/tsconfig.node.json b/playground/basic/tsconfig.node.json
new file mode 100644
index 0000000..42872c5
--- /dev/null
+++ b/playground/basic/tsconfig.node.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/playground/basic/vite.config.ts b/playground/basic/vite.config.ts
new file mode 100644
index 0000000..5a33944
--- /dev/null
+++ b/playground/basic/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..61650f9
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,3767 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@types/node':
+ specifier: ^20.4.9
+ version: 20.4.9
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^6.3.0
+ version: 6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.46.0)(typescript@5.1.6)
+ chai:
+ specifier: ^4.3.7
+ version: 4.3.7
+ eslint:
+ specifier: ^8.46.0
+ version: 8.46.0
+ eslint-config-standard:
+ specifier: ^17.1.0
+ version: 17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.46.0)
+ eslint-define-config:
+ specifier: ^1.22.0
+ version: 1.22.0
+ eslint-plugin-eslint-comments:
+ specifier: ^3.2.0
+ version: 3.2.0(eslint@8.46.0)
+ eslint-plugin-import:
+ specifier: ^2.28.0
+ version: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.46.0)
+ eslint-plugin-n:
+ specifier: ^16.0.1
+ version: 16.0.1(eslint@8.46.0)
+ eslint-plugin-promise:
+ specifier: ^6.1.1
+ version: 6.1.1(eslint@8.46.0)
+ lint-staged:
+ specifier: ^13.2.3
+ version: 13.2.3
+ mocha:
+ specifier: ^10.2.0
+ version: 10.2.0
+ rimraf:
+ specifier: ^5.0.1
+ version: 5.0.1
+ simple-git-hooks:
+ specifier: ^2.9.0
+ version: 2.9.0
+ tsup:
+ specifier: ^7.2.0
+ version: 7.2.0(typescript@5.1.6)
+ typescript:
+ specifier: ^5.1.6
+ version: 5.1.6
+ vitest:
+ specifier: ^0.34.1
+ version: 0.34.1
+
+ playground/basic:
+ dependencies:
+ harfbuzzjs:
+ specifier: workspace:*
+ version: link:../..
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.2.0(react@18.2.0)
+ devDependencies:
+ '@types/react':
+ specifier: ^18.2.15
+ version: 18.2.15
+ '@types/react-dom':
+ specifier: ^18.2.7
+ version: 18.2.7
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^6.0.0
+ version: 6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.46.0)(typescript@5.1.6)
+ '@typescript-eslint/parser':
+ specifier: ^6.0.0
+ version: 6.3.0(eslint@8.46.0)(typescript@5.1.6)
+ '@vitejs/plugin-react':
+ specifier: ^4.0.3
+ version: 4.0.3(vite@4.4.9)
+ eslint:
+ specifier: ^8.45.0
+ version: 8.46.0
+ eslint-plugin-react-hooks:
+ specifier: ^4.6.0
+ version: 4.6.0(eslint@8.46.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.3
+ version: 0.4.3(eslint@8.46.0)
+ typescript:
+ specifier: ^5.0.2
+ version: 5.1.6
+ vite:
+ specifier: ^4.4.5
+ version: 4.4.9(@types/node@20.4.9)
+
+packages:
+
+ /@aashutoshrathi/word-wrap@1.2.6:
+ resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /@ampproject/remapping@2.2.1:
+ resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.19
+ dev: true
+
+ /@babel/code-frame@7.22.10:
+ resolution: {integrity: sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/highlight': 7.22.10
+ chalk: 2.4.2
+ dev: true
+
+ /@babel/compat-data@7.22.9:
+ resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/core@7.22.10:
+ resolution: {integrity: sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@ampproject/remapping': 2.2.1
+ '@babel/code-frame': 7.22.10
+ '@babel/generator': 7.22.10
+ '@babel/helper-compilation-targets': 7.22.10
+ '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.10)
+ '@babel/helpers': 7.22.10
+ '@babel/parser': 7.22.10
+ '@babel/template': 7.22.5
+ '@babel/traverse': 7.22.10
+ '@babel/types': 7.22.10
+ convert-source-map: 1.9.0
+ debug: 4.3.4(supports-color@8.1.1)
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/generator@7.22.10:
+ resolution: {integrity: sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.22.10
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.19
+ jsesc: 2.5.2
+ dev: true
+
+ /@babel/helper-compilation-targets@7.22.10:
+ resolution: {integrity: sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/compat-data': 7.22.9
+ '@babel/helper-validator-option': 7.22.5
+ browserslist: 4.21.10
+ lru-cache: 5.1.1
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-environment-visitor@7.22.5:
+ resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-function-name@7.22.5:
+ resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.5
+ '@babel/types': 7.22.10
+ dev: true
+
+ /@babel/helper-hoist-variables@7.22.5:
+ resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.22.10
+ dev: true
+
+ /@babel/helper-module-imports@7.22.5:
+ resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.22.10
+ dev: true
+
+ /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.10):
+ resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.22.10
+ '@babel/helper-environment-visitor': 7.22.5
+ '@babel/helper-module-imports': 7.22.5
+ '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/helper-validator-identifier': 7.22.5
+ dev: true
+
+ /@babel/helper-plugin-utils@7.22.5:
+ resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-simple-access@7.22.5:
+ resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.22.10
+ dev: true
+
+ /@babel/helper-split-export-declaration@7.22.6:
+ resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.22.10
+ dev: true
+
+ /@babel/helper-string-parser@7.22.5:
+ resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-identifier@7.22.5:
+ resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-option@7.22.5:
+ resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helpers@7.22.10:
+ resolution: {integrity: sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.5
+ '@babel/traverse': 7.22.10
+ '@babel/types': 7.22.10
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/highlight@7.22.10:
+ resolution: {integrity: sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-validator-identifier': 7.22.5
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ dev: true
+
+ /@babel/parser@7.22.10:
+ resolution: {integrity: sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.22.10
+ dev: true
+
+ /@babel/plugin-transform-react-jsx-self@7.22.5(@babel/core@7.22.10):
+ resolution: {integrity: sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.22.10
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-react-jsx-source@7.22.5(@babel/core@7.22.10):
+ resolution: {integrity: sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.22.10
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/template@7.22.5:
+ resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.22.10
+ '@babel/parser': 7.22.10
+ '@babel/types': 7.22.10
+ dev: true
+
+ /@babel/traverse@7.22.10:
+ resolution: {integrity: sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.22.10
+ '@babel/generator': 7.22.10
+ '@babel/helper-environment-visitor': 7.22.5
+ '@babel/helper-function-name': 7.22.5
+ '@babel/helper-hoist-variables': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/parser': 7.22.10
+ '@babel/types': 7.22.10
+ debug: 4.3.4(supports-color@8.1.1)
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/types@7.22.10:
+ resolution: {integrity: sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.22.5
+ '@babel/helper-validator-identifier': 7.22.5
+ to-fast-properties: 2.0.0
+ dev: true
+
+ /@esbuild/android-arm64@0.18.20:
+ resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.18.20:
+ resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.18.20:
+ resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.18.20:
+ resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.18.20:
+ resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.18.20:
+ resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.18.20:
+ resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.18.20:
+ resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.18.20:
+ resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.18.20:
+ resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.18.20:
+ resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.18.20:
+ resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.18.20:
+ resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.18.20:
+ resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.18.20:
+ resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.18.20:
+ resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.18.20:
+ resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.18.20:
+ resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.18.20:
+ resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.18.20:
+ resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.18.20:
+ resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.18.20:
+ resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@eslint-community/eslint-utils@4.4.0(eslint@8.46.0):
+ resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ dependencies:
+ eslint: 8.46.0
+ eslint-visitor-keys: 3.4.2
+ dev: true
+
+ /@eslint-community/regexpp@4.6.2:
+ resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ dev: true
+
+ /@eslint/eslintrc@2.1.1:
+ resolution: {integrity: sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.4(supports-color@8.1.1)
+ espree: 9.6.1
+ globals: 13.20.0
+ ignore: 5.2.4
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@eslint/js@8.46.0:
+ resolution: {integrity: sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@humanwhocodes/config-array@0.11.10:
+ resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
+ engines: {node: '>=10.10.0'}
+ dependencies:
+ '@humanwhocodes/object-schema': 1.2.1
+ debug: 4.3.4(supports-color@8.1.1)
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/module-importer@1.0.1:
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /@humanwhocodes/object-schema@1.2.1:
+ resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
+ dev: true
+
+ /@isaacs/cliui@8.0.2:
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: /string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: /strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: /wrap-ansi@7.0.0
+ dev: true
+
+ /@jest/schemas@29.6.0:
+ resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@sinclair/typebox': 0.27.8
+ dev: true
+
+ /@jridgewell/gen-mapping@0.3.3:
+ resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.19
+ dev: true
+
+ /@jridgewell/resolve-uri@3.1.1:
+ resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/set-array@1.1.2:
+ resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+ dev: true
+
+ /@jridgewell/trace-mapping@0.3.19:
+ resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.15.0
+ dev: true
+
+ /@pkgjs/parseargs@0.11.0:
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@sinclair/typebox@0.27.8:
+ resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
+ dev: true
+
+ /@types/chai-subset@1.3.3:
+ resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
+ dependencies:
+ '@types/chai': 4.3.5
+ dev: true
+
+ /@types/chai@4.3.5:
+ resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==}
+ dev: true
+
+ /@types/json-schema@7.0.12:
+ resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
+ dev: true
+
+ /@types/json5@0.0.29:
+ resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ dev: true
+
+ /@types/node@20.4.9:
+ resolution: {integrity: sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==}
+ dev: true
+
+ /@types/prop-types@15.7.5:
+ resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
+ dev: true
+
+ /@types/react-dom@18.2.7:
+ resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==}
+ dependencies:
+ '@types/react': 18.2.15
+ dev: true
+
+ /@types/react@18.2.15:
+ resolution: {integrity: sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==}
+ dependencies:
+ '@types/prop-types': 15.7.5
+ '@types/scheduler': 0.16.3
+ csstype: 3.1.2
+ dev: true
+
+ /@types/scheduler@0.16.3:
+ resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
+ dev: true
+
+ /@types/semver@7.5.0:
+ resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
+ dev: true
+
+ /@typescript-eslint/eslint-plugin@6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.46.0)(typescript@5.1.6):
+ resolution: {integrity: sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
+ eslint: ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@eslint-community/regexpp': 4.6.2
+ '@typescript-eslint/parser': 6.3.0(eslint@8.46.0)(typescript@5.1.6)
+ '@typescript-eslint/scope-manager': 6.3.0
+ '@typescript-eslint/type-utils': 6.3.0(eslint@8.46.0)(typescript@5.1.6)
+ '@typescript-eslint/utils': 6.3.0(eslint@8.46.0)(typescript@5.1.6)
+ '@typescript-eslint/visitor-keys': 6.3.0
+ debug: 4.3.4(supports-color@8.1.1)
+ eslint: 8.46.0
+ graphemer: 1.4.0
+ ignore: 5.2.4
+ natural-compare: 1.4.0
+ natural-compare-lite: 1.4.0
+ semver: 7.5.4
+ ts-api-utils: 1.0.1(typescript@5.1.6)
+ typescript: 5.1.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/parser@6.3.0(eslint@8.46.0)(typescript@5.1.6):
+ resolution: {integrity: sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/scope-manager': 6.3.0
+ '@typescript-eslint/types': 6.3.0
+ '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6)
+ '@typescript-eslint/visitor-keys': 6.3.0
+ debug: 4.3.4(supports-color@8.1.1)
+ eslint: 8.46.0
+ typescript: 5.1.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/scope-manager@6.3.0:
+ resolution: {integrity: sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ dependencies:
+ '@typescript-eslint/types': 6.3.0
+ '@typescript-eslint/visitor-keys': 6.3.0
+ dev: true
+
+ /@typescript-eslint/type-utils@6.3.0(eslint@8.46.0)(typescript@5.1.6):
+ resolution: {integrity: sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6)
+ '@typescript-eslint/utils': 6.3.0(eslint@8.46.0)(typescript@5.1.6)
+ debug: 4.3.4(supports-color@8.1.1)
+ eslint: 8.46.0
+ ts-api-utils: 1.0.1(typescript@5.1.6)
+ typescript: 5.1.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/types@6.3.0:
+ resolution: {integrity: sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ dev: true
+
+ /@typescript-eslint/typescript-estree@6.3.0(typescript@5.1.6):
+ resolution: {integrity: sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/types': 6.3.0
+ '@typescript-eslint/visitor-keys': 6.3.0
+ debug: 4.3.4(supports-color@8.1.1)
+ globby: 11.1.0
+ is-glob: 4.0.3
+ semver: 7.5.4
+ ts-api-utils: 1.0.1(typescript@5.1.6)
+ typescript: 5.1.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/utils@6.3.0(eslint@8.46.0)(typescript@5.1.6):
+ resolution: {integrity: sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0)
+ '@types/json-schema': 7.0.12
+ '@types/semver': 7.5.0
+ '@typescript-eslint/scope-manager': 6.3.0
+ '@typescript-eslint/types': 6.3.0
+ '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6)
+ eslint: 8.46.0
+ semver: 7.5.4
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+ dev: true
+
+ /@typescript-eslint/visitor-keys@6.3.0:
+ resolution: {integrity: sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ dependencies:
+ '@typescript-eslint/types': 6.3.0
+ eslint-visitor-keys: 3.4.2
+ dev: true
+
+ /@vitejs/plugin-react@4.0.3(vite@4.4.9):
+ resolution: {integrity: sha512-pwXDog5nwwvSIzwrvYYmA2Ljcd/ZNlcsSG2Q9CNDBwnsd55UGAyr2doXtB5j+2uymRCnCfExlznzzSFbBRcoCg==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0
+ dependencies:
+ '@babel/core': 7.22.10
+ '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.22.10)
+ '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.22.10)
+ react-refresh: 0.14.0
+ vite: 4.4.9(@types/node@20.4.9)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@vitest/expect@0.34.1:
+ resolution: {integrity: sha512-q2CD8+XIsQ+tHwypnoCk8Mnv5e6afLFvinVGCq3/BOT4kQdVQmY6rRfyKkwcg635lbliLPqbunXZr+L1ssUWiQ==}
+ dependencies:
+ '@vitest/spy': 0.34.1
+ '@vitest/utils': 0.34.1
+ chai: 4.3.7
+ dev: true
+
+ /@vitest/runner@0.34.1:
+ resolution: {integrity: sha512-YfQMpYzDsYB7yqgmlxZ06NI4LurHWfrH7Wy3Pvf/z/vwUSgq1zLAb1lWcItCzQG+NVox+VvzlKQrYEXb47645g==}
+ dependencies:
+ '@vitest/utils': 0.34.1
+ p-limit: 4.0.0
+ pathe: 1.1.1
+ dev: true
+
+ /@vitest/snapshot@0.34.1:
+ resolution: {integrity: sha512-0O9LfLU0114OqdF8lENlrLsnn024Tb1CsS9UwG0YMWY2oGTQfPtkW+B/7ieyv0X9R2Oijhi3caB1xgGgEgclSQ==}
+ dependencies:
+ magic-string: 0.30.2
+ pathe: 1.1.1
+ pretty-format: 29.6.2
+ dev: true
+
+ /@vitest/spy@0.34.1:
+ resolution: {integrity: sha512-UT4WcI3EAPUNO8n6y9QoEqynGGEPmmRxC+cLzneFFXpmacivjHZsNbiKD88KUScv5DCHVDgdBsLD7O7s1enFcQ==}
+ dependencies:
+ tinyspy: 2.1.1
+ dev: true
+
+ /@vitest/utils@0.34.1:
+ resolution: {integrity: sha512-/ql9dsFi4iuEbiNcjNHQWXBum7aL8pyhxvfnD9gNtbjR9fUKAjxhj4AA3yfLXg6gJpMGGecvtF8Au2G9y3q47Q==}
+ dependencies:
+ diff-sequences: 29.4.3
+ loupe: 2.3.6
+ pretty-format: 29.6.2
+ dev: true
+
+ /acorn-jsx@5.3.2(acorn@8.9.0):
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ acorn: 8.9.0
+ dev: true
+
+ /acorn-walk@8.2.0:
+ resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
+ engines: {node: '>=0.4.0'}
+ dev: true
+
+ /acorn@8.9.0:
+ resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /aggregate-error@3.1.0:
+ resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
+ engines: {node: '>=8'}
+ dependencies:
+ clean-stack: 2.2.0
+ indent-string: 4.0.0
+ dev: true
+
+ /ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-colors@4.1.1:
+ resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /ansi-escapes@4.3.2:
+ resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.21.3
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-regex@6.0.1:
+ resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+ dependencies:
+ color-convert: 1.9.3
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+ dev: true
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ dev: true
+
+ /array-buffer-byte-length@1.0.0:
+ resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
+ dependencies:
+ call-bind: 1.0.2
+ is-array-buffer: 3.0.2
+ dev: true
+
+ /array-includes@3.1.6:
+ resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ get-intrinsic: 1.2.1
+ is-string: 1.0.7
+ dev: true
+
+ /array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /array.prototype.findlastindex@1.2.2:
+ resolution: {integrity: sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ es-shim-unscopables: 1.0.0
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /array.prototype.flat@1.3.1:
+ resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ es-shim-unscopables: 1.0.0
+ dev: true
+
+ /array.prototype.flatmap@1.3.1:
+ resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ es-shim-unscopables: 1.0.0
+ dev: true
+
+ /arraybuffer.prototype.slice@1.0.1:
+ resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ get-intrinsic: 1.2.1
+ is-array-buffer: 3.0.2
+ is-shared-array-buffer: 1.0.2
+ dev: true
+
+ /assertion-error@1.1.0:
+ resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
+ dev: true
+
+ /astral-regex@2.0.0:
+ resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /available-typed-arrays@1.0.5:
+ resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /binary-extensions@2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+ dev: true
+
+ /braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
+ /browser-stdout@1.3.1:
+ resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
+ dev: true
+
+ /browserslist@4.21.10:
+ resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001519
+ electron-to-chromium: 1.4.488
+ node-releases: 2.0.13
+ update-browserslist-db: 1.0.11(browserslist@4.21.10)
+ dev: true
+
+ /builtins@5.0.1:
+ resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
+ dependencies:
+ semver: 7.5.4
+ dev: true
+
+ /bundle-require@4.0.1(esbuild@0.18.20):
+ resolution: {integrity: sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ peerDependencies:
+ esbuild: '>=0.17'
+ dependencies:
+ esbuild: 0.18.20
+ load-tsconfig: 0.2.5
+ dev: true
+
+ /cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /call-bind@1.0.2:
+ resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
+ dependencies:
+ function-bind: 1.1.1
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /camelcase@6.3.0:
+ resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /caniuse-lite@1.0.30001519:
+ resolution: {integrity: sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==}
+ dev: true
+
+ /chai@4.3.7:
+ resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==}
+ engines: {node: '>=4'}
+ dependencies:
+ assertion-error: 1.1.0
+ check-error: 1.0.2
+ deep-eql: 4.1.3
+ get-func-name: 2.0.0
+ loupe: 2.3.6
+ pathval: 1.1.1
+ type-detect: 4.0.8
+ dev: true
+
+ /chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+ dev: true
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chalk@5.2.0:
+ resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+ dev: true
+
+ /check-error@1.0.2:
+ resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
+ dev: true
+
+ /chokidar@3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /clean-stack@2.2.0:
+ resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /cli-cursor@3.1.0:
+ resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
+ engines: {node: '>=8'}
+ dependencies:
+ restore-cursor: 3.1.0
+ dev: true
+
+ /cli-truncate@2.1.0:
+ resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
+ engines: {node: '>=8'}
+ dependencies:
+ slice-ansi: 3.0.0
+ string-width: 4.2.3
+ dev: true
+
+ /cli-truncate@3.1.0:
+ resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ slice-ansi: 5.0.0
+ string-width: 5.1.2
+ dev: true
+
+ /cliui@7.0.4:
+ resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+ dev: true
+
+ /color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+ dependencies:
+ color-name: 1.1.3
+ dev: true
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /colorette@2.0.20:
+ resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
+ dev: true
+
+ /commander@10.0.1:
+ resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /convert-source-map@1.9.0:
+ resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
+ dev: true
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /csstype@3.1.2:
+ resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
+ dev: true
+
+ /debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ dev: true
+
+ /debug@4.3.4(supports-color@8.1.1):
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ supports-color: 8.1.1
+ dev: true
+
+ /decamelize@4.0.0:
+ resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /deep-eql@4.1.3:
+ resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
+ engines: {node: '>=6'}
+ dependencies:
+ type-detect: 4.0.8
+ dev: true
+
+ /deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ dev: true
+
+ /define-properties@1.2.0:
+ resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-property-descriptors: 1.0.0
+ object-keys: 1.1.1
+ dev: true
+
+ /diff-sequences@29.4.3:
+ resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dev: true
+
+ /diff@5.0.0:
+ resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==}
+ engines: {node: '>=0.3.1'}
+ dev: true
+
+ /dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-type: 4.0.0
+ dev: true
+
+ /doctrine@2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ dev: true
+
+ /electron-to-chromium@1.4.488:
+ resolution: {integrity: sha512-Dv4sTjiW7t/UWGL+H8ZkgIjtUAVZDgb/PwGWvMsCT7jipzUV/u5skbLXPFKb6iV0tiddVi/bcS2/kUrczeWgIQ==}
+ dev: true
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ dev: true
+
+ /es-abstract@1.22.1:
+ resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ arraybuffer.prototype.slice: 1.0.1
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.2
+ es-set-tostringtag: 2.0.1
+ es-to-primitive: 1.2.1
+ function.prototype.name: 1.1.5
+ get-intrinsic: 1.2.1
+ get-symbol-description: 1.0.0
+ globalthis: 1.0.3
+ gopd: 1.0.1
+ has: 1.0.3
+ has-property-descriptors: 1.0.0
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ internal-slot: 1.0.5
+ is-array-buffer: 3.0.2
+ is-callable: 1.2.7
+ is-negative-zero: 2.0.2
+ is-regex: 1.1.4
+ is-shared-array-buffer: 1.0.2
+ is-string: 1.0.7
+ is-typed-array: 1.1.12
+ is-weakref: 1.0.2
+ object-inspect: 1.12.3
+ object-keys: 1.1.1
+ object.assign: 4.1.4
+ regexp.prototype.flags: 1.5.0
+ safe-array-concat: 1.0.0
+ safe-regex-test: 1.0.0
+ string.prototype.trim: 1.2.7
+ string.prototype.trimend: 1.0.6
+ string.prototype.trimstart: 1.0.6
+ typed-array-buffer: 1.0.0
+ typed-array-byte-length: 1.0.0
+ typed-array-byte-offset: 1.0.0
+ typed-array-length: 1.0.4
+ unbox-primitive: 1.0.2
+ which-typed-array: 1.1.11
+ dev: true
+
+ /es-set-tostringtag@2.0.1:
+ resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.1
+ has: 1.0.3
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /es-shim-unscopables@1.0.0:
+ resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==}
+ dependencies:
+ has: 1.0.3
+ dev: true
+
+ /es-to-primitive@1.2.1:
+ resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.0.5
+ is-symbol: 1.0.4
+ dev: true
+
+ /esbuild@0.18.20:
+ resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/android-arm': 0.18.20
+ '@esbuild/android-arm64': 0.18.20
+ '@esbuild/android-x64': 0.18.20
+ '@esbuild/darwin-arm64': 0.18.20
+ '@esbuild/darwin-x64': 0.18.20
+ '@esbuild/freebsd-arm64': 0.18.20
+ '@esbuild/freebsd-x64': 0.18.20
+ '@esbuild/linux-arm': 0.18.20
+ '@esbuild/linux-arm64': 0.18.20
+ '@esbuild/linux-ia32': 0.18.20
+ '@esbuild/linux-loong64': 0.18.20
+ '@esbuild/linux-mips64el': 0.18.20
+ '@esbuild/linux-ppc64': 0.18.20
+ '@esbuild/linux-riscv64': 0.18.20
+ '@esbuild/linux-s390x': 0.18.20
+ '@esbuild/linux-x64': 0.18.20
+ '@esbuild/netbsd-x64': 0.18.20
+ '@esbuild/openbsd-x64': 0.18.20
+ '@esbuild/sunos-x64': 0.18.20
+ '@esbuild/win32-arm64': 0.18.20
+ '@esbuild/win32-ia32': 0.18.20
+ '@esbuild/win32-x64': 0.18.20
+ dev: true
+
+ /escalade@3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+ dev: true
+
+ /escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /eslint-config-standard@17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.46.0):
+ resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ eslint: ^8.0.1
+ eslint-plugin-import: ^2.25.2
+ eslint-plugin-n: '^15.0.0 || ^16.0.0 '
+ eslint-plugin-promise: ^6.0.0
+ dependencies:
+ eslint: 8.46.0
+ eslint-plugin-import: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.46.0)
+ eslint-plugin-n: 16.0.1(eslint@8.46.0)
+ eslint-plugin-promise: 6.1.1(eslint@8.46.0)
+ dev: true
+
+ /eslint-define-config@1.22.0:
+ resolution: {integrity: sha512-pckNJppFwC4AX+AGK63aa4sX5BluPwWwHES3fq/ER0jDR2U2czwlngg38B4EQ2ibvofufc+R5QfmdPKI6+74vQ==}
+ engines: {node: ^16.13.0 || >=18.0.0, npm: '>=7.0.0', pnpm: '>= 8.6.0'}
+ dev: true
+
+ /eslint-import-resolver-node@0.3.9:
+ resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
+ dependencies:
+ debug: 3.2.7
+ is-core-module: 2.13.0
+ resolve: 1.22.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.3.0)(eslint-import-resolver-node@0.3.9)(eslint@8.46.0):
+ resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 6.3.0(eslint@8.46.0)(typescript@5.1.6)
+ debug: 3.2.7
+ eslint: 8.46.0
+ eslint-import-resolver-node: 0.3.9
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-plugin-es-x@7.2.0(eslint@8.46.0):
+ resolution: {integrity: sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '>=8'
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0)
+ '@eslint-community/regexpp': 4.6.2
+ eslint: 8.46.0
+ dev: true
+
+ /eslint-plugin-eslint-comments@3.2.0(eslint@8.46.0):
+ resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==}
+ engines: {node: '>=6.5.0'}
+ peerDependencies:
+ eslint: '>=4.19.1'
+ dependencies:
+ escape-string-regexp: 1.0.5
+ eslint: 8.46.0
+ ignore: 5.2.4
+ dev: true
+
+ /eslint-plugin-import@2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.46.0):
+ resolution: {integrity: sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 6.3.0(eslint@8.46.0)(typescript@5.1.6)
+ array-includes: 3.1.6
+ array.prototype.findlastindex: 1.2.2
+ array.prototype.flat: 1.3.1
+ array.prototype.flatmap: 1.3.1
+ debug: 3.2.7
+ doctrine: 2.1.0
+ eslint: 8.46.0
+ eslint-import-resolver-node: 0.3.9
+ eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.3.0)(eslint-import-resolver-node@0.3.9)(eslint@8.46.0)
+ has: 1.0.3
+ is-core-module: 2.13.0
+ is-glob: 4.0.3
+ minimatch: 3.1.2
+ object.fromentries: 2.0.6
+ object.groupby: 1.0.0
+ object.values: 1.1.6
+ resolve: 1.22.4
+ semver: 6.3.1
+ tsconfig-paths: 3.14.2
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
+ /eslint-plugin-n@16.0.1(eslint@8.46.0):
+ resolution: {integrity: sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ eslint: '>=7.0.0'
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0)
+ builtins: 5.0.1
+ eslint: 8.46.0
+ eslint-plugin-es-x: 7.2.0(eslint@8.46.0)
+ ignore: 5.2.4
+ is-core-module: 2.13.0
+ minimatch: 3.1.2
+ resolve: 1.22.4
+ semver: 7.5.4
+ dev: true
+
+ /eslint-plugin-promise@6.1.1(eslint@8.46.0):
+ resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ dependencies:
+ eslint: 8.46.0
+ dev: true
+
+ /eslint-plugin-react-hooks@4.6.0(eslint@8.46.0):
+ resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
+ dependencies:
+ eslint: 8.46.0
+ dev: true
+
+ /eslint-plugin-react-refresh@0.4.3(eslint@8.46.0):
+ resolution: {integrity: sha512-Hh0wv8bUNY877+sI0BlCUlsS0TYYQqvzEwJsJJPM2WF4RnTStSnSR3zdJYa2nPOJgg3UghXi54lVyMSmpCalzA==}
+ peerDependencies:
+ eslint: '>=7'
+ dependencies:
+ eslint: 8.46.0
+ dev: true
+
+ /eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+ dev: true
+
+ /eslint-visitor-keys@3.4.2:
+ resolution: {integrity: sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /eslint@8.46.0:
+ resolution: {integrity: sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0)
+ '@eslint-community/regexpp': 4.6.2
+ '@eslint/eslintrc': 2.1.1
+ '@eslint/js': 8.46.0
+ '@humanwhocodes/config-array': 0.11.10
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4(supports-color@8.1.1)
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.2
+ espree: 9.6.1
+ esquery: 1.5.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.20.0
+ graphemer: 1.4.0
+ ignore: 5.2.4
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.3
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ acorn: 8.9.0
+ acorn-jsx: 5.3.2(acorn@8.9.0)
+ eslint-visitor-keys: 3.4.2
+ dev: true
+
+ /esquery@1.5.0:
+ resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+ dev: true
+
+ /execa@7.2.0:
+ resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==}
+ engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0}
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 6.0.1
+ human-signals: 4.3.1
+ is-stream: 3.0.0
+ merge-stream: 2.0.0
+ npm-run-path: 5.1.0
+ onetime: 6.0.0
+ signal-exit: 3.0.7
+ strip-final-newline: 3.0.0
+ dev: true
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob@3.3.1:
+ resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ dev: true
+
+ /fastq@1.15.0:
+ resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flat-cache: 3.0.4
+ dev: true
+
+ /fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /flat-cache@3.0.4:
+ resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flatted: 3.2.7
+ rimraf: 3.0.2
+ dev: true
+
+ /flat@5.0.2:
+ resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
+ hasBin: true
+ dev: true
+
+ /flatted@3.2.7:
+ resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
+ dev: true
+
+ /for-each@0.3.3:
+ resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ dependencies:
+ is-callable: 1.2.7
+ dev: true
+
+ /foreground-child@3.1.1:
+ resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
+ engines: {node: '>=14'}
+ dependencies:
+ cross-spawn: 7.0.3
+ signal-exit: 4.1.0
+ dev: true
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind@1.1.1:
+ resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
+ dev: true
+
+ /function.prototype.name@1.1.5:
+ resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ functions-have-names: 1.2.3
+ dev: true
+
+ /functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+ dev: true
+
+ /get-func-name@2.0.0:
+ resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
+ dev: true
+
+ /get-intrinsic@1.2.1:
+ resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
+ dependencies:
+ function-bind: 1.1.1
+ has: 1.0.3
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ dev: true
+
+ /get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /get-symbol-description@1.0.0:
+ resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob@10.3.3:
+ resolution: {integrity: sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ foreground-child: 3.1.1
+ jackspeak: 2.2.2
+ minimatch: 9.0.3
+ minipass: 7.0.2
+ path-scurry: 1.10.1
+ dev: true
+
+ /glob@7.1.6:
+ resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /glob@7.2.0:
+ resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /globals@11.12.0:
+ resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /globals@13.20.0:
+ resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.20.2
+ dev: true
+
+ /globalthis@1.0.3:
+ resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-properties: 1.2.0
+ dev: true
+
+ /globby@11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.1
+ ignore: 5.2.4
+ merge2: 1.4.1
+ slash: 3.0.0
+ dev: true
+
+ /gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ dependencies:
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ dev: true
+
+ /has-bigints@1.0.2:
+ resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ dev: true
+
+ /has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors@1.0.0:
+ resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
+ dependencies:
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-tostringtag@1.0.0:
+ resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /has@1.0.3:
+ resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ function-bind: 1.1.1
+ dev: true
+
+ /he@1.2.0:
+ resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+ hasBin: true
+ dev: true
+
+ /human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+ dev: true
+
+ /human-signals@4.3.1:
+ resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==}
+ engines: {node: '>=14.18.0'}
+ dev: true
+
+ /ignore@5.2.4:
+ resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+ dev: true
+
+ /indent-string@4.0.0:
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /internal-slot@1.0.5:
+ resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.1
+ has: 1.0.3
+ side-channel: 1.0.4
+ dev: true
+
+ /is-array-buffer@3.0.2:
+ resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /is-bigint@1.0.4:
+ resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ dependencies:
+ has-bigints: 1.0.2
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-boolean-object@1.1.2:
+ resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-core-module@2.13.0:
+ resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
+ dependencies:
+ has: 1.0.3
+ dev: true
+
+ /is-date-object@1.0.5:
+ resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-fullwidth-code-point@4.0.0:
+ resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-negative-zero@2.0.2:
+ resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-number-object@1.0.7:
+ resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-plain-obj@2.1.0:
+ resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-regex@1.1.4:
+ resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-shared-array-buffer@1.0.2:
+ resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ dependencies:
+ call-bind: 1.0.2
+ dev: true
+
+ /is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-stream@3.0.0:
+ resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
+ /is-string@1.0.7:
+ resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-symbol@1.0.4:
+ resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /is-typed-array@1.1.12:
+ resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ which-typed-array: 1.1.11
+ dev: true
+
+ /is-unicode-supported@0.1.0:
+ resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /is-weakref@1.0.2:
+ resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ dependencies:
+ call-bind: 1.0.2
+ dev: true
+
+ /isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /jackspeak@2.2.2:
+ resolution: {integrity: sha512-mgNtVv4vUuaKA97yxUHoA3+FkuhtxkjdXEWOyB/N76fjy0FjezEt34oy3epBtvCvS+7DyKwqCFWx/oJLV5+kCg==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+ dev: true
+
+ /joycon@3.1.1:
+ resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ /js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /jsesc@2.5.2:
+ resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ dev: true
+
+ /json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ dev: true
+
+ /json5@1.0.2:
+ resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+ hasBin: true
+ dependencies:
+ minimist: 1.2.8
+ dev: true
+
+ /json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+ dev: true
+
+ /jsonc-parser@3.2.0:
+ resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
+ dev: true
+
+ /levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /lilconfig@2.1.0:
+ resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ dev: true
+
+ /lint-staged@13.2.3:
+ resolution: {integrity: sha512-zVVEXLuQIhr1Y7R7YAWx4TZLdvuzk7DnmrsTNL0fax6Z3jrpFcas+vKbzxhhvp6TA55m1SQuWkpzI1qbfDZbAg==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ chalk: 5.2.0
+ cli-truncate: 3.1.0
+ commander: 10.0.1
+ debug: 4.3.4(supports-color@8.1.1)
+ execa: 7.2.0
+ lilconfig: 2.1.0
+ listr2: 5.0.8
+ micromatch: 4.0.5
+ normalize-path: 3.0.0
+ object-inspect: 1.12.3
+ pidtree: 0.6.0
+ string-argv: 0.3.2
+ yaml: 2.3.1
+ transitivePeerDependencies:
+ - enquirer
+ - supports-color
+ dev: true
+
+ /listr2@5.0.8:
+ resolution: {integrity: sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+ peerDependencies:
+ enquirer: '>= 2.3.0 < 3'
+ peerDependenciesMeta:
+ enquirer:
+ optional: true
+ dependencies:
+ cli-truncate: 2.1.0
+ colorette: 2.0.20
+ log-update: 4.0.0
+ p-map: 4.0.0
+ rfdc: 1.3.0
+ rxjs: 7.8.1
+ through: 2.3.8
+ wrap-ansi: 7.0.0
+ dev: true
+
+ /load-tsconfig@0.2.5:
+ resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
+ /local-pkg@0.4.3:
+ resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ dev: true
+
+ /lodash.sortby@4.7.0:
+ resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
+ dev: true
+
+ /log-symbols@4.1.0:
+ resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
+ engines: {node: '>=10'}
+ dependencies:
+ chalk: 4.1.2
+ is-unicode-supported: 0.1.0
+ dev: true
+
+ /log-update@4.0.0:
+ resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-escapes: 4.3.2
+ cli-cursor: 3.1.0
+ slice-ansi: 4.0.0
+ wrap-ansi: 6.2.0
+ dev: true
+
+ /loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+ dependencies:
+ js-tokens: 4.0.0
+ dev: false
+
+ /loupe@2.3.6:
+ resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
+ dependencies:
+ get-func-name: 2.0.0
+ dev: true
+
+ /lru-cache@10.0.0:
+ resolution: {integrity: sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==}
+ engines: {node: 14 || >=16.14}
+ dev: true
+
+ /lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ dependencies:
+ yallist: 3.1.1
+ dev: true
+
+ /lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /magic-string@0.30.2:
+ resolution: {integrity: sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+ dev: true
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /mimic-fn@4.0.0:
+ resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch@5.0.1:
+ resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==}
+ engines: {node: '>=10'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
+ /minimatch@9.0.3:
+ resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
+ /minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ dev: true
+
+ /minipass@7.0.2:
+ resolution: {integrity: sha512-eL79dXrE1q9dBbDCLg7xfn/vl7MS4F1gvJAgjJrQli/jbQWdUttuVawphqpffoIYfRdq78LHx6GP4bU/EQ2ATA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dev: true
+
+ /mlly@1.4.0:
+ resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==}
+ dependencies:
+ acorn: 8.9.0
+ pathe: 1.1.1
+ pkg-types: 1.0.3
+ ufo: 1.1.2
+ dev: true
+
+ /mocha@10.2.0:
+ resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==}
+ engines: {node: '>= 14.0.0'}
+ hasBin: true
+ dependencies:
+ ansi-colors: 4.1.1
+ browser-stdout: 1.3.1
+ chokidar: 3.5.3
+ debug: 4.3.4(supports-color@8.1.1)
+ diff: 5.0.0
+ escape-string-regexp: 4.0.0
+ find-up: 5.0.0
+ glob: 7.2.0
+ he: 1.2.0
+ js-yaml: 4.1.0
+ log-symbols: 4.1.0
+ minimatch: 5.0.1
+ ms: 2.1.3
+ nanoid: 3.3.3
+ serialize-javascript: 6.0.0
+ strip-json-comments: 3.1.1
+ supports-color: 8.1.1
+ workerpool: 6.2.1
+ yargs: 16.2.0
+ yargs-parser: 20.2.4
+ yargs-unparser: 2.0.0
+ dev: true
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ dev: true
+
+ /mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+ dev: true
+
+ /nanoid@3.3.3:
+ resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /nanoid@3.3.6:
+ resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /natural-compare-lite@1.4.0:
+ resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
+ dev: true
+
+ /natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ dev: true
+
+ /node-releases@2.0.13:
+ resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==}
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-key: 3.1.1
+ dev: true
+
+ /npm-run-path@5.1.0:
+ resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ path-key: 4.0.0
+ dev: true
+
+ /object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /object-inspect@1.12.3:
+ resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign@4.1.4:
+ resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ has-symbols: 1.0.3
+ object-keys: 1.1.1
+ dev: true
+
+ /object.fromentries@2.0.6:
+ resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ dev: true
+
+ /object.groupby@1.0.0:
+ resolution: {integrity: sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /object.values@1.1.6:
+ resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ dev: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+ dependencies:
+ mimic-fn: 2.1.0
+ dev: true
+
+ /onetime@6.0.0:
+ resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ mimic-fn: 4.0.0
+ dev: true
+
+ /optionator@0.9.3:
+ resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ '@aashutoshrathi/word-wrap': 1.2.6
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-limit@4.0.0:
+ resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ yocto-queue: 1.0.0
+ dev: true
+
+ /p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /p-map@4.0.0:
+ resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ aggregate-error: 3.1.0
+ dev: true
+
+ /parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-key@4.0.0:
+ resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /path-scurry@1.10.1:
+ resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ lru-cache: 10.0.0
+ minipass: 7.0.2
+ dev: true
+
+ /path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /pathe@1.1.1:
+ resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==}
+ dev: true
+
+ /pathval@1.1.1:
+ resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
+ dev: true
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ dev: true
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /pidtree@0.6.0:
+ resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
+ engines: {node: '>=0.10'}
+ hasBin: true
+ dev: true
+
+ /pirates@4.0.6:
+ resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /pkg-types@1.0.3:
+ resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==}
+ dependencies:
+ jsonc-parser: 3.2.0
+ mlly: 1.4.0
+ pathe: 1.1.1
+ dev: true
+
+ /postcss-load-config@4.0.1:
+ resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ dependencies:
+ lilconfig: 2.1.0
+ yaml: 2.3.1
+ dev: true
+
+ /postcss@8.4.27:
+ resolution: {integrity: sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.6
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+ dev: true
+
+ /pretty-format@29.6.2:
+ resolution: {integrity: sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@jest/schemas': 29.6.0
+ ansi-styles: 5.2.0
+ react-is: 18.2.0
+ dev: true
+
+ /punycode@2.3.0:
+ resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /randombytes@2.1.0:
+ resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+ dependencies:
+ safe-buffer: 5.2.1
+ dev: true
+
+ /react-dom@18.2.0(react@18.2.0):
+ resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
+ peerDependencies:
+ react: ^18.2.0
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.2.0
+ scheduler: 0.23.0
+ dev: false
+
+ /react-is@18.2.0:
+ resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
+ dev: true
+
+ /react-refresh@0.14.0:
+ resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /react@18.2.0:
+ resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /regexp.prototype.flags@1.5.0:
+ resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ functions-have-names: 1.2.3
+ dev: true
+
+ /require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve-from@5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /resolve@1.22.4:
+ resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.0
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /restore-cursor@3.1.0:
+ resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
+ engines: {node: '>=8'}
+ dependencies:
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ dev: true
+
+ /reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rfdc@1.3.0:
+ resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
+ dev: true
+
+ /rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.0
+ dev: true
+
+ /rimraf@5.0.1:
+ resolution: {integrity: sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==}
+ engines: {node: '>=14'}
+ hasBin: true
+ dependencies:
+ glob: 10.3.3
+ dev: true
+
+ /rollup@3.25.3:
+ resolution: {integrity: sha512-ZT279hx8gszBj9uy5FfhoG4bZx8c+0A1sbqtr7Q3KNWIizpTdDEPZbV2xcbvHsnFp4MavCQYZyzApJ+virB8Yw==}
+ engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /rollup@3.28.0:
+ resolution: {integrity: sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==}
+ engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /rxjs@7.8.1:
+ resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
+ dependencies:
+ tslib: 2.6.1
+ dev: true
+
+ /safe-array-concat@1.0.0:
+ resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==}
+ engines: {node: '>=0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ has-symbols: 1.0.3
+ isarray: 2.0.5
+ dev: true
+
+ /safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+ dev: true
+
+ /safe-regex-test@1.0.0:
+ resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ is-regex: 1.1.4
+ dev: true
+
+ /scheduler@0.23.0:
+ resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+ dev: true
+
+ /semver@7.5.4:
+ resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /serialize-javascript@6.0.0:
+ resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==}
+ dependencies:
+ randombytes: 2.1.0
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /side-channel@1.0.4:
+ resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ object-inspect: 1.12.3
+ dev: true
+
+ /siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+ dev: true
+
+ /signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+ dev: true
+
+ /signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /simple-git-hooks@2.9.0:
+ resolution: {integrity: sha512-waSQ5paUQtyGC0ZxlHmcMmD9I1rRXauikBwX31bX58l5vTOhCEcBC5Bi+ZDkPXTjDnZAF8TbCqKBY+9+sVPScw==}
+ hasBin: true
+ requiresBuild: true
+ dev: true
+
+ /slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /slice-ansi@3.0.0:
+ resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-styles: 4.3.0
+ astral-regex: 2.0.0
+ is-fullwidth-code-point: 3.0.0
+ dev: true
+
+ /slice-ansi@4.0.0:
+ resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ astral-regex: 2.0.0
+ is-fullwidth-code-point: 3.0.0
+ dev: true
+
+ /slice-ansi@5.0.0:
+ resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.1
+ is-fullwidth-code-point: 4.0.0
+ dev: true
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map@0.8.0-beta.0:
+ resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
+ engines: {node: '>= 8'}
+ dependencies:
+ whatwg-url: 7.1.0
+ dev: true
+
+ /stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+ dev: true
+
+ /std-env@3.3.3:
+ resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
+ dev: true
+
+ /string-argv@0.3.2:
+ resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
+ engines: {node: '>=0.6.19'}
+ dev: true
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+ dev: true
+
+ /string.prototype.trim@1.2.7:
+ resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ dev: true
+
+ /string.prototype.trimend@1.0.6:
+ resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ dev: true
+
+ /string.prototype.trimstart@1.0.6:
+ resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ es-abstract: 1.22.1
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-regex: 6.0.1
+ dev: true
+
+ /strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /strip-final-newline@3.0.0:
+ resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /strip-literal@1.0.1:
+ resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==}
+ dependencies:
+ acorn: 8.9.0
+ dev: true
+
+ /sucrase@3.34.0:
+ resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ commander: 4.1.1
+ glob: 7.1.6
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.6
+ ts-interface-checker: 0.1.13
+ dev: true
+
+ /supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+ dependencies:
+ has-flag: 3.0.0
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-color@8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ dev: true
+
+ /thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ thenify: 3.3.1
+ dev: true
+
+ /thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ dependencies:
+ any-promise: 1.3.0
+ dev: true
+
+ /through@2.3.8:
+ resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+ dev: true
+
+ /tinybench@2.5.0:
+ resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==}
+ dev: true
+
+ /tinypool@0.7.0:
+ resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==}
+ engines: {node: '>=14.0.0'}
+ dev: true
+
+ /tinyspy@2.1.1:
+ resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==}
+ engines: {node: '>=14.0.0'}
+ dev: true
+
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /tr46@1.0.1:
+ resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
+ dependencies:
+ punycode: 2.3.0
+ dev: true
+
+ /tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+ dev: true
+
+ /ts-api-utils@1.0.1(typescript@5.1.6):
+ resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==}
+ engines: {node: '>=16.13.0'}
+ peerDependencies:
+ typescript: '>=4.2.0'
+ dependencies:
+ typescript: 5.1.6
+ dev: true
+
+ /ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+ dev: true
+
+ /tsconfig-paths@3.14.2:
+ resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==}
+ dependencies:
+ '@types/json5': 0.0.29
+ json5: 1.0.2
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+ dev: true
+
+ /tslib@2.6.1:
+ resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==}
+ dev: true
+
+ /tsup@7.2.0(typescript@5.1.6):
+ resolution: {integrity: sha512-vDHlczXbgUvY3rWvqFEbSqmC1L7woozbzngMqTtL2PGBODTtWlRwGDDawhvWzr5c1QjKe4OAKqJGfE1xeXUvtQ==}
+ engines: {node: '>=16.14'}
+ hasBin: true
+ peerDependencies:
+ '@swc/core': ^1
+ postcss: ^8.4.12
+ typescript: '>=4.1.0'
+ peerDependenciesMeta:
+ '@swc/core':
+ optional: true
+ postcss:
+ optional: true
+ typescript:
+ optional: true
+ dependencies:
+ bundle-require: 4.0.1(esbuild@0.18.20)
+ cac: 6.7.14
+ chokidar: 3.5.3
+ debug: 4.3.4(supports-color@8.1.1)
+ esbuild: 0.18.20
+ execa: 5.1.1
+ globby: 11.1.0
+ joycon: 3.1.1
+ postcss-load-config: 4.0.1
+ resolve-from: 5.0.0
+ rollup: 3.25.3
+ source-map: 0.8.0-beta.0
+ sucrase: 3.34.0
+ tree-kill: 1.2.2
+ typescript: 5.1.6
+ transitivePeerDependencies:
+ - supports-color
+ - ts-node
+ dev: true
+
+ /type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ dev: true
+
+ /type-detect@4.0.8:
+ resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /type-fest@0.21.3:
+ resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /typed-array-buffer@1.0.0:
+ resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-length@1.0.0:
+ resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-offset@1.0.0:
+ resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.2
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-length@1.0.4:
+ resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
+ dependencies:
+ call-bind: 1.0.2
+ for-each: 0.3.3
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typescript@5.1.6:
+ resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+ dev: true
+
+ /ufo@1.1.2:
+ resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
+ dev: true
+
+ /unbox-primitive@1.0.2:
+ resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ dependencies:
+ call-bind: 1.0.2
+ has-bigints: 1.0.2
+ has-symbols: 1.0.3
+ which-boxed-primitive: 1.0.2
+ dev: true
+
+ /update-browserslist-db@1.0.11(browserslist@4.21.10):
+ resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.21.10
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.3.0
+ dev: true
+
+ /vite-node@0.34.1(@types/node@20.4.9):
+ resolution: {integrity: sha512-odAZAL9xFMuAg8aWd7nSPT+hU8u2r9gU3LRm9QKjxBEF2rRdWpMuqkrkjvyVQEdNFiBctqr2Gg4uJYizm5Le6w==}
+ engines: {node: '>=v14.18.0'}
+ hasBin: true
+ dependencies:
+ cac: 6.7.14
+ debug: 4.3.4(supports-color@8.1.1)
+ mlly: 1.4.0
+ pathe: 1.1.1
+ picocolors: 1.0.0
+ vite: 4.4.9(@types/node@20.4.9)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ dev: true
+
+ /vite@4.4.9(@types/node@20.4.9):
+ resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': '>= 14'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ '@types/node': 20.4.9
+ esbuild: 0.18.20
+ postcss: 8.4.27
+ rollup: 3.28.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /vitest@0.34.1:
+ resolution: {integrity: sha512-G1PzuBEq9A75XSU88yO5G4vPT20UovbC/2osB2KEuV/FisSIIsw7m5y2xMdB7RsAGHAfg2lPmp2qKr3KWliVlQ==}
+ engines: {node: '>=v14.18.0'}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@vitest/browser': '*'
+ '@vitest/ui': '*'
+ happy-dom: '*'
+ jsdom: '*'
+ playwright: '*'
+ safaridriver: '*'
+ webdriverio: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+ playwright:
+ optional: true
+ safaridriver:
+ optional: true
+ webdriverio:
+ optional: true
+ dependencies:
+ '@types/chai': 4.3.5
+ '@types/chai-subset': 1.3.3
+ '@types/node': 20.4.9
+ '@vitest/expect': 0.34.1
+ '@vitest/runner': 0.34.1
+ '@vitest/snapshot': 0.34.1
+ '@vitest/spy': 0.34.1
+ '@vitest/utils': 0.34.1
+ acorn: 8.9.0
+ acorn-walk: 8.2.0
+ cac: 6.7.14
+ chai: 4.3.7
+ debug: 4.3.4(supports-color@8.1.1)
+ local-pkg: 0.4.3
+ magic-string: 0.30.2
+ pathe: 1.1.1
+ picocolors: 1.0.0
+ std-env: 3.3.3
+ strip-literal: 1.0.1
+ tinybench: 2.5.0
+ tinypool: 0.7.0
+ vite: 4.4.9(@types/node@20.4.9)
+ vite-node: 0.34.1(@types/node@20.4.9)
+ why-is-node-running: 2.2.2
+ transitivePeerDependencies:
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ dev: true
+
+ /webidl-conversions@4.0.2:
+ resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
+ dev: true
+
+ /whatwg-url@7.1.0:
+ resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
+ dependencies:
+ lodash.sortby: 4.7.0
+ tr46: 1.0.1
+ webidl-conversions: 4.0.2
+ dev: true
+
+ /which-boxed-primitive@1.0.2:
+ resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ dependencies:
+ is-bigint: 1.0.4
+ is-boolean-object: 1.1.2
+ is-number-object: 1.0.7
+ is-string: 1.0.7
+ is-symbol: 1.0.4
+ dev: true
+
+ /which-typed-array@1.1.11:
+ resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.2
+ for-each: 0.3.3
+ gopd: 1.0.1
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /why-is-node-running@2.2.2:
+ resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+ dev: true
+
+ /workerpool@6.2.1:
+ resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==}
+ dev: true
+
+ /wrap-ansi@6.2.0:
+ resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+ dev: true
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ dev: true
+
+ /yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ dev: true
+
+ /yaml@2.3.1:
+ resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==}
+ engines: {node: '>= 14'}
+ dev: true
+
+ /yargs-parser@20.2.4:
+ resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yargs-unparser@2.0.0:
+ resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
+ engines: {node: '>=10'}
+ dependencies:
+ camelcase: 6.3.0
+ decamelize: 4.0.0
+ flat: 5.0.2
+ is-plain-obj: 2.1.0
+ dev: true
+
+ /yargs@16.2.0:
+ resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
+ engines: {node: '>=10'}
+ dependencies:
+ cliui: 7.0.4
+ escalade: 3.1.1
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 20.2.4
+ dev: true
+
+ /yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yocto-queue@1.0.0:
+ resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
+ engines: {node: '>=12.20'}
+ dev: true
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..83bb632
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+packages:
+ - 'playground/*'
+ - '.'
\ No newline at end of file
diff --git a/src/client.ts b/src/client.ts
new file mode 100644
index 0000000..6068bd3
--- /dev/null
+++ b/src/client.ts
@@ -0,0 +1 @@
+export * from './hb'
\ No newline at end of file
diff --git a/src/hb.ts b/src/hb.ts
new file mode 100644
index 0000000..ac3e301
--- /dev/null
+++ b/src/hb.ts
@@ -0,0 +1,386 @@
+import type { Exports, GlyphFlag } from '~/schema/export'
+import type { BlobInstace } from '~/schema/blob'
+import type { FaceInstance } from '~/schema/face'
+import type { FontInstance } from '~/schema/font'
+import type { BufferInstance } from '~/schema/buffer'
+import { buffer_flag, hb_tag, hb_untag } from '~/utils/index'
+
+const HB_MEMORY_MODE_WRITABLE = 2
+const HB_SET_VALUE_INVALID = -1
+
+export function hb(instance: WebAssembly.Instance) {
+ const exports = instance.exports as unknown as Exports
+ const memory = exports.memory
+ const heapu8 = new Uint8Array(memory.buffer)
+ const heapu32 = new Uint32Array(memory.buffer)
+ const heapi32 = new Int32Array(memory.buffer)
+ const heapf32 = new Float32Array(memory.buffer)
+ const utf8Decoder = new TextDecoder('utf8')
+
+ /**
+ * Create an object representing a Harfbuzz blob.
+ * @param blob A blob of binary data (usually the contents of a font file).
+ */
+ function createBlob(blob: ArrayBuffer) {
+ const blobPtr = exports.malloc(blob.byteLength)
+ heapu8.set(new Uint8Array(blob), blobPtr)
+ const ptr = exports.hb_blob_create(blobPtr, blob.byteLength, HB_MEMORY_MODE_WRITABLE, blobPtr, exports.free_ptr())
+
+ return {
+ ptr,
+ destory() {
+ exports.hb_blob_destroy(ptr)
+ }
+ }
+ }
+
+ /**
+ * Create an object representing a Harfbuzz face.
+ * @param {BlobInstace} blob An object returned from `createBlob`.
+ * @param {number} index The index of the font in the blob. (0 for most files,
+ * or a 0-indexed font number if the `blob` came form a TTC/OTC file.)
+ **/
+ function createFace(blob: BlobInstace, index: number) {
+ const ptr = exports.hb_face_create(blob.ptr, index)
+ const upem = exports.hb_face_get_upem(ptr)
+
+ return {
+ ptr,
+ upem,
+ /**
+ * Return the binary contents of an OpenType table.
+ * @param table Table name
+ * @returns
+ */
+ reference_table(table: string) {
+ const blob = exports.hb_face_reference_table(ptr, hb_tag(table))
+ const length = exports.hb_blob_get_length(blob)
+ if (!length) return
+
+ const blobPtr = exports.hb_blob_get_data(blob, null)
+ return heapu8.subarray(blobPtr)
+ },
+ getAxisInfos() {
+ const axis = exports.malloc(64 * 32)
+ const c = exports.malloc(4)
+ heapu32[c / 4] = 64
+ exports.hb_ot_var_get_axis_infos(ptr, 0, c, axis)
+ const result: { [p: string]: { min: number; default: number; max: number }} = {}
+ Array.from({ length: heapu32[c / 4] }).forEach((_, i) => {
+ result[hb_untag(heapu32[axis / 4 + i * 8 + 1])] = {
+ min: heapf32[axis / 4 + i * 8 + 4],
+ default: heapf32[axis / 4 + i * 8 + 5],
+ max: heapf32[axis / 4 + i * 8 + 6]
+ }
+ })
+ exports.free(c)
+ exports.free(axis)
+
+ return result
+ },
+ collectUnicodes() {
+ const unicodeSetPtr = exports.hb_set_create()
+ exports.hb_face_collect_unicodes(ptr, unicodeSetPtr)
+ const result = resolveTypedArrayFromSet(unicodeSetPtr, 'u32') as Uint32Array
+ exports.hb_set_destroy(unicodeSetPtr)
+ return result
+ },
+ destory() {
+ exports.hb_face_destroy(ptr)
+ }
+ }
+ }
+
+ const pathBufferSize = 65536; // should be enough for most glyphs
+ const pathBuffer = exports.malloc(pathBufferSize); // permanently allocated
+
+ const nameBufferSize = 256; // should be enough for most glyphs
+ const nameBuffer = exports.malloc(nameBufferSize); // permanently allocated
+
+ function createFont(face: FaceInstance) {
+ const ptr = exports.hb_font_create(face.ptr)
+
+ /**
+ * Return a glyph as an SVG path string.
+ * @param {number} glyphId ID of the requested glyph in the font.
+ **/
+ function glyphToPath(glyphId: number) {
+ const length = exports.hbjs_glyph_svg(ptr, glyphId, pathBuffer, pathBufferSize)
+ return length > 0 ? utf8Decoder.decode(heapu8.subarray(pathBuffer, pathBuffer + length)) : ''
+ }
+
+ /**
+ * Return glyph name.
+ * @param {number} glyphId ID of the requested glyph in the font.
+ **/
+ function glyphName(glyphId: number) {
+ exports.hb_font_glyph_to_string(ptr, glyphId, nameBuffer, nameBufferSize)
+ const array = heapu8.subarray(nameBuffer, nameBuffer + nameBufferSize)
+ return utf8Decoder.decode(array.slice(0, array.indexOf(0)))
+ }
+
+ return {
+ ptr,
+ glyphName,
+ glyphToPath,
+ /**
+ * Return a glyph as a JSON path string
+ * based on format described on https://svgwg.org/specs/paths/#InterfaceSVGPathSegment
+ * @param {number} glyphId ID of the requested glyph in the font.
+ **/
+ glyphToJson(glyphId: number) {
+ const path = glyphToPath(glyphId)
+ return path.replace(/([MLQCZ])/g, '|$1 ')
+ .split('|')
+ .filter(v => v.length)
+ .map(v => {
+ const row = v.split(/[ ,]/g)
+ return {
+ type: row[0],
+ values: row.slice(1).filter(v => v.length).map(Number)
+ }
+ })
+ },
+ /**
+ * Set the font's scale factor, affecting the position values returned from
+ * shaping.
+ * @param {number} xScale Units to scale in the X dimension.
+ * @param {number} yScale Units to scale in the Y dimension.
+ **/
+ setScale(xScale: number, yScale: number) {
+ exports.hb_font_set_scale(ptr, xScale, yScale)
+ },
+ /**
+ * Set the font's variations.
+ * @param {object} variations Dictionary of variations to set
+ **/
+ setVariations (variations: Record) {
+ const entries = Object.entries(variations)
+ const vars = exports.malloc(8 * entries.length)
+ entries.forEach((entry, i) => {
+ heapu32[vars / 4 + i * 2 + 0] = hb_tag(entry[0]);
+ heapf32[vars / 4 + i * 2 + 1] = entry[1];
+ });
+ exports.hb_font_set_variations(ptr, vars, entries.length)
+ exports.free(vars)
+ },
+ destroy() {
+ exports.hb_font_destroy(ptr)
+ }
+ }
+ }
+
+ function createBuffer() {
+ const ptr = exports.hb_buffer_create()
+
+ return {
+ ptr,
+ /**
+ * Add text to the buffer.
+ * @param {string} text Text to be added to the buffer.
+ **/
+ addText(text: string) {
+ const str = createJsString(text)
+ exports.hb_buffer_add_utf16(ptr, str.ptr, str.length, 0, str.length)
+ str.free()
+ },
+ /**
+ * Set buffer script, language and direction.
+ *
+ * This needs to be done before shaping.
+ **/
+ guessSegmentProperties() {
+ return exports.hb_buffer_guess_segment_properties(ptr)
+ },
+ /**
+ * Set buffer direction explicitly.
+ * @param {string} direction: One of "ltr", "rtl", "ttb" or "btt"
+ */
+ setDirection(dir: 'ltr' | 'rtl' | 'ttb' | 'btt') {
+ exports.hb_buffer_set_direction(ptr, {
+ ltr: 4,
+ rtl: 5,
+ ttb: 6,
+ btt: 7
+ }[dir] || 0)
+ },
+ /**
+ * Set buffer flags explicitly.
+ * @param {string[]} flags: A list of strings which may be either:
+ */
+ setFlags(flags: Array<'BOT' | 'EOT' | 'PRESERVE_DEFAULT_IGNORABLES' | 'REMOVE_DEFAULT_IGNORABLES' | 'DO_NOT_INSERT_DOTTED_CIRCLE' | 'PRODUCE_UNSAFE_TO_CONCAT'>) {
+ const flag = flags.reduce((res, item) => res |= buffer_flag(item), 0)
+
+ exports.hb_buffer_set_flags(ptr, flag)
+ },
+ /**
+ * Set buffer language explicitly.
+ * @param {string} language: The buffer language
+ */
+ setLanguage(language: string) {
+ const str = createAsciiString(language)
+ exports.hb_buffer_set_language(ptr, exports.hb_language_from_string(str.ptr, -1))
+ str.free()
+ },
+ /**
+ * Set buffer script explicitly.
+ * @param {string} script: The buffer script
+ */
+ setScript (script: string) {
+ const str = createAsciiString(script)
+ exports.hb_buffer_set_script(ptr, exports.hb_script_from_string(str.ptr, -1))
+ str.free()
+ },
+ /**
+ * Set the Harfbuzz clustering level.
+ *
+ * Affects the cluster values returned from shaping.
+ * @param {number} level: Clustering level. See the Harfbuzz manual chapter
+ * on Clusters.
+ **/
+ setClusterLevel (level: number) {
+ exports.hb_buffer_set_cluster_level(ptr, level)
+ },
+ /**
+ * Return the buffer contents as a JSON object.
+ *
+ * After shaping, this function will return an array of glyph information
+ * objects. Each object will have the following attributes:
+ *
+ * - g: The glyph ID
+ * - cl: The cluster ID
+ * - ax: Advance width (width to advance after this glyph is painted)
+ * - ay: Advance height (height to advance after this glyph is painted)
+ * - dx: X displacement (adjustment in X dimension when painting this glyph)
+ * - dy: Y displacement (adjustment in Y dimension when painting this glyph)
+ * - flags: Glyph flags like `HB_GLYPH_FLAG_UNSAFE_TO_BREAK` (0x1)
+ **/
+ json() {
+ const length = exports.hb_buffer_get_length(ptr)
+ const infosPtr = exports.hb_buffer_get_glyph_infos(ptr, 0)
+ const infosPtr32 = infosPtr / 4
+ const positionsPtr32 = exports.hb_buffer_get_glyph_positions(ptr, 0) / 4
+ const infos = heapu32.subarray(infosPtr32, infosPtr32 + 5 * length)
+ const positions = heapi32.subarray(positionsPtr32, positionsPtr32 + 5 * length)
+ const result: Array<{
+ g: number
+ cl: number
+ ax: number
+ ay: number
+ dx: number
+ dy: number
+ flags: GlyphFlag
+ }> = []
+ for (let i = 0; i < length; ++i) {
+ result.push({
+ g: infos[i * 5 + 0],
+ cl: infos[i * 5 + 2],
+ ax: positions[i * 5 + 0],
+ ay: positions[i * 5 + 1],
+ dx: positions[i * 5 + 2],
+ dy: positions[i * 5 + 3],
+ flags: exports.hb_glyph_info_get_glyph_flags(infosPtr + i * 20)
+ });
+ }
+ return result
+ },
+ destroy() { exports.hb_buffer_destroy(ptr) }
+ }
+ }
+
+ function shape(font: FontInstance, buffer: BufferInstance) {
+ exports.hb_shape(font.ptr, buffer.ptr, 0, 0)
+ }
+
+ function resolveTypedArrayFromSet(ptr: number, type: 'u8' | 'u32' | 'i32' | 'f32') {
+ const heap: Uint8Array | Uint32Array | Int32Array | Float32Array = type === 'u32'
+ ? heapu32
+ : type === 'i32'
+ ? heapi32
+ : type === 'f32'
+ ? heapf32
+ : heapu8
+
+ const bytesPerElment = type === 'u32'
+ ? Uint32Array.BYTES_PER_ELEMENT
+ : type === 'i32'
+ ? Int32Array.BYTES_PER_ELEMENT
+ : type === 'f32'
+ ? Float32Array.BYTES_PER_ELEMENT
+ : Uint8Array.BYTES_PER_ELEMENT
+
+ const setCount = exports.hb_set_get_population(ptr)
+ const arrayPtr = exports.malloc(setCount * bytesPerElment)
+ const arrayOffset = arrayPtr / bytesPerElment
+ const array = heap.subarray(arrayOffset, arrayOffset + setCount)
+ heap.set(array, arrayOffset)
+ exports.hb_set_next_many(
+ ptr,
+ HB_SET_VALUE_INVALID,
+ arrayPtr,
+ setCount
+ )
+ return array
+ }
+
+ function createJsString(text: string) {
+ const ptr = exports.malloc(text.length * 2)
+ const words = new Uint16Array(exports.memory.buffer, ptr, text.length)
+ for (let i = 0; i < words.length; ++i) words[i] = text.charCodeAt(i)
+ return {
+ ptr,
+ length: words.length,
+ free() { exports.free(ptr) }
+ }
+ }
+
+ /**
+ * Use when you know the input range should be ASCII.
+ * Faster than encoding to UTF-8
+ **/
+ function createAsciiString(text: string) {
+ const length = text.length
+ const ptr = exports.malloc(length + 1)
+ for (let i = 0; i < length; ++i) {
+ const char = text.charCodeAt(i)
+ if (char > 127) throw new Error('Expected ASCII text')
+ heapu8[ptr + i] = char
+ }
+ heapu8[ptr + length] = 0
+
+ return {
+ ptr,
+ length,
+ free() { exports.free(ptr) }
+ }
+ }
+
+ function shapeWithTrace(
+ font: FontInstance,
+ buffer: BufferInstance,
+ features: string,
+ stop_at: number,
+ stop_phase: 0 | 1 | 2
+ ) {
+ const length = 1024 * 1024
+ const traceBuffer = exports.malloc(length)
+ const featureStr = createAsciiString(features)
+ const traceLength = exports.hbjs_shape_with_trace(font.ptr, buffer.ptr, featureStr.ptr, stop_at, stop_phase, traceBuffer, length)
+ featureStr.free()
+ const trace = utf8Decoder.decode(heapu8.subarray(traceBuffer, traceBuffer + traceLength - 1))
+ exports.free(traceBuffer)
+
+ return JSON.parse(trace)
+ }
+
+ return {
+ createBlob,
+ createFace,
+ createFont,
+ createBuffer,
+ shape,
+ shapeWithTrace
+ }
+}
+
+export * from './schema/export'
\ No newline at end of file
diff --git a/src/node.ts b/src/node.ts
new file mode 100644
index 0000000..65766d0
--- /dev/null
+++ b/src/node.ts
@@ -0,0 +1,13 @@
+import { resolve } from 'path'
+import { readFile } from 'fs/promises'
+import { hb } from './hb'
+
+export async function initHB() {
+ const data = await readFile(resolve(__dirname, '../hb.wasm'))
+
+ const wasm = await WebAssembly.instantiate(data)
+
+ return hb(wasm.instance)
+}
+
+export * from './hb'
\ No newline at end of file
diff --git a/src/schema/blob.ts b/src/schema/blob.ts
new file mode 100644
index 0000000..7a25321
--- /dev/null
+++ b/src/schema/blob.ts
@@ -0,0 +1,6 @@
+import type { Pointer } from "./export"
+
+export interface BlobInstace {
+ ptr: Pointer
+ destory(): void
+}
\ No newline at end of file
diff --git a/src/schema/buffer.ts b/src/schema/buffer.ts
new file mode 100644
index 0000000..c4d4d81
--- /dev/null
+++ b/src/schema/buffer.ts
@@ -0,0 +1,21 @@
+import type { GlyphFlag } from "./export"
+
+export interface BufferInstance {
+ ptr: number
+ addText(text: string): void
+ guessSegmentProperties(): void
+ setDirection(dir: 'ltr' | 'rtl' | 'ttb' | 'btt'): void
+ setFlags(flags: Array<'BOT' | 'EOT' | 'PRESERVE_DEFAULT_IGNORABLES' | 'REMOVE_DEFAULT_IGNORABLES' | 'DO_NOT_INSERT_DOTTED_CIRCLE' | 'PRODUCE_UNSAFE_TO_CONCAT'>): void
+ setLanguage(language: string): void
+ setScript(script: string): void
+ setClusterLevel(level: number): void
+ json(): Array<{
+ g: number
+ cl: number
+ ax: number
+ ay: number
+ dx: number
+ dy: number
+ flags: GlyphFlag
+ }>
+}
\ No newline at end of file
diff --git a/src/schema/export.ts b/src/schema/export.ts
new file mode 100644
index 0000000..2a212fd
--- /dev/null
+++ b/src/schema/export.ts
@@ -0,0 +1,83 @@
+export type Pointer = number
+type BCP47LanguageTag = string
+
+export enum BufferFlag {
+ HB_BUFFER_FLAG_DEFAULT = 0x0,
+ HB_BUFFER_FLAG_BOT = 0x1, /* Beginning-of-text */
+ HB_BUFFER_FLAG_EOT = 0x2, /* End-of-text */
+ HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x4,
+ HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x8,
+ HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x10,
+ HB_BUFFER_FLAG_VERIFY = 0x20,
+ HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x40,
+ HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL = 0x80,
+ HB_BUFFER_FLAG_DEFINED = 0xFF
+}
+
+export enum ClusterLevel {
+ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0,
+ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1,
+ HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2
+}
+
+export enum GlyphFlag {
+ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x1,
+ HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x2,
+ HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL = 0x4,
+ HB_GLYPH_FLAG_DEFINED = 0x7
+}
+
+export interface Exports {
+ memory: WebAssembly.Memory
+ malloc: (length: number) => Pointer
+ free: (ptr: Pointer) => void
+ free_ptr: () => Pointer
+ hb_blob_create: (data: Pointer, length: number, memoryMode: number, useData: Pointer, destroyFunction: Pointer) => Pointer
+ hb_blob_destroy: (ptr: Pointer) => void
+ hb_blob_get_length: (blob: Blob) => number
+ hb_blob_get_data: (blob: Blob, length: number | null) => Pointer
+
+ hb_face_create: (blobPtr: Pointer, index: number) => Pointer
+ hb_face_get_upem: (facePtr: Pointer) => number
+ hb_face_destroy: (ptr: Pointer) => void
+ hb_face_reference_table: (ptr: Pointer, tag: number) => Blob
+ hb_face_collect_unicodes: (facePtr: Pointer, setPtr: Pointer) => void
+ hb_font_set_variations: (font: Pointer, variations: Pointer, variations_length: number) => void
+ hb_ot_var_get_axis_infos: (ptr: Pointer, start_offset: number, axes_count: Pointer, axes_array: Pointer) => number
+
+ hb_set_create: () => Pointer
+ hb_set_destroy: (setPtr: Pointer) => void
+ hb_set_get_population: (setPtr: Pointer) => number
+ hb_set_next_many: (
+ setPtr: Pointer,
+ greaterThanUnicodePtr: Pointer,
+ outputU32ArrayPtr: Pointer,
+ size: number,
+ ) => number
+
+ hb_font_create: (facePtr: Pointer) => Pointer
+ hb_font_set_scale: (fontPtr: Pointer, xScale: number, yScale: number) => void
+ hb_font_glyph_to_string: (facePtr: Pointer, glyph: number, s: number, size: number) => void
+ hb_font_destroy: (ptr: Pointer) => void
+ hb_buffer_create: () => Pointer
+ hb_buffer_add_utf8: (bufferPtr: Pointer, stringPtr: Pointer, stringLength: number, itemOffset: number, itemLength: number) => void
+ hb_buffer_add_utf16: (bufferPtr: Pointer, stringPtr: Pointer, stringLength: number, itemOffset: number, itemLength: number) => void
+ hb_buffer_guess_segment_properties: (bufferPtr: Pointer) => void
+ hb_buffer_set_direction: (bufferPtr: Pointer, direction: number) => void
+ hb_shape: (fontPtr: Pointer, bufferPtr: Pointer, features: any, numFeatures: number) => void
+ hb_buffer_get_length: (bufferPtr: Pointer) => number
+ hb_buffer_get_glyph_infos: (bufferPtr: Pointer, length: number) => any
+ hb_buffer_get_glyph_positions: (bufferPtr: Pointer, length: number) => any
+ hb_buffer_destroy: (bufferPtr: Pointer) => void
+ hb_buffer_set_flags: (bufferPtr: Pointer, bufferFlag: BufferFlag) => void
+ hb_buffer_set_language: (bufferPtr: Pointer, language: string) => void
+ hb_buffer_set_script: (bufferPtr: Pointer, script: string) => void
+ hb_buffer_set_cluster_level: (bufferPtr: Pointer, cluster_level: ClusterLevel) => void
+ hb_glyph_info_get_glyph_flags: (bufferPtr: Pointer) => GlyphFlag
+ hbjs_glyph_svg: (font: Pointer, glyphId: number, pathBuffer: number, size: number) => number
+ hbjs_shape_with_trace: (font: Pointer, buffer: Pointer, features: Pointer, stop_at: number, stop_phase: number, outbuf: Pointer, buf_size: number) => number
+
+ hb_language_from_string: (ptr: Pointer, len: number) => BCP47LanguageTag
+
+ hb_script_from_string: (ptr: Pointer, len: number) => string
+}
\ No newline at end of file
diff --git a/src/schema/face.ts b/src/schema/face.ts
new file mode 100644
index 0000000..e4d3ae8
--- /dev/null
+++ b/src/schema/face.ts
@@ -0,0 +1,16 @@
+import type { Pointer } from "./export";
+
+export interface FaceInstance {
+ ptr: Pointer
+ upem: Pointer
+ reference_table(table: string): Uint8Array | undefined
+ getAxisInfos(): {
+ [p: string]: {
+ min: number
+ default: number
+ max: number
+ }
+ }
+ collectUnicodes(): Uint32Array
+ destory(): void
+}
\ No newline at end of file
diff --git a/src/schema/font.ts b/src/schema/font.ts
new file mode 100644
index 0000000..deb9713
--- /dev/null
+++ b/src/schema/font.ts
@@ -0,0 +1,12 @@
+export interface FontInstance {
+ ptr: number
+ glyphToPath(id: number): string
+ glyphName(id: number): string
+ glyphToJson(id: number): Array<{
+ type: string
+ values: number[]
+ }>
+ setScale(x: number, y: number): void
+ setVariations (variations: Record): void
+ destroy(): void
+}
\ No newline at end of file
diff --git a/src/utils/index.ts b/src/utils/index.ts
new file mode 100644
index 0000000..b4f8f80
--- /dev/null
+++ b/src/utils/index.ts
@@ -0,0 +1,27 @@
+export function hb_tag(s: string) {
+ return (
+ (s.charCodeAt(0) & 0xFF) << 24 |
+ (s.charCodeAt(1) & 0xFF) << 16 |
+ (s.charCodeAt(2) & 0xFF) << 8 |
+ (s.charCodeAt(3) & 0xFF) << 0
+ )
+}
+
+export function hb_untag(tag: number) {
+ return [
+ String.fromCharCode((tag >> 24) & 0xFF),
+ String.fromCharCode((tag >> 16) & 0xFF),
+ String.fromCharCode((tag >> 8) & 0xFF),
+ String.fromCharCode((tag >> 0) & 0xFF)
+ ].join('')
+}
+
+export function buffer_flag(s: string) {
+ if (s == "BOT") { return 0x1 }
+ if (s == "EOT") { return 0x2 }
+ if (s == "PRESERVE_DEFAULT_IGNORABLES") { return 0x4 }
+ if (s == "REMOVE_DEFAULT_IGNORABLES") { return 0x8 }
+ if (s == "DO_NOT_INSERT_DOTTED_CIRCLE") { return 0x10 }
+ if (s == "PRODUCE_UNSAFE_TO_CONCAT") { return 0x40 }
+ return 0x0
+}
\ No newline at end of file
diff --git a/test/index.js b/test/index.js
deleted file mode 100644
index 0976650..0000000
--- a/test/index.js
+++ /dev/null
@@ -1,185 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-const {expect} = require('chai');
-let hb;
-
-before(async function () {
- hb = await require('..');
-});
-
-afterEach(function () {
- if (this.blob) this.blob.destroy();
- if (this.face) this.face.destroy();
- if (this.font) this.font.destroy();
- if (this.buffer) this.buffer.destroy();
- this.blob = this.face = this.font = this.buffer = null;
-});
-
-describe('Face', function () {
- it('collectUnicodes reflects codepoints supported by the font', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- const codepoints = [...this.face.collectUnicodes()];
- expect(codepoints).to.include('a'.codePointAt(0));
- expect(codepoints).not.to.include('ا'.codePointAt(0));
- });
-
- it('exposes upem', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- expect(this.face.upem).to.equal(1000);
- });
-
- it('getAxisInfos returns details of a variable font', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSansArabic-Variable.ttf')));
- this.face = hb.createFace(this.blob);
- expect(this.face.getAxisInfos()).to.deep.equal({
- wght: {min: 100, default: 400, max: 900},
- wdth: {min: 62.5, default: 100, max: 100}
- });
- });
-
- it('getAxisInfos returns an empty object for a non-variable font', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- expect(Object.keys(this.face.getAxisInfos())).to.have.lengthOf(0);
- });
-});
-
-describe('Font', function () {
- it('glyphName returns names for glyph ids', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- expect(this.font.glyphName(20)).to.equal('one');
- });
-
- it('setScale affects advances', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.buffer = hb.createBuffer();
- this.buffer.addText('a');
- this.buffer.guessSegmentProperties();
- this.font.setScale(1000 * 2, 1000 * 2);
- hb.shape(this.font, this.buffer)
- const glyphs = this.buffer.json();
- expect(glyphs[0].ax).to.equal(561 * 2);
- });
-
- it('setVariations affects advances', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSansArabic-Variable.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.font.setVariations({'wght': 789});
- this.buffer = hb.createBuffer();
- this.buffer.addText('آلو');
- this.buffer.guessSegmentProperties();
- hb.shape(this.font, this.buffer)
- const glyphs = this.buffer.json();
- expect(glyphs[0].ax).to.equal(526);
- });
-});
-
-describe('Buffer', function () {
- it('setDirection controls direction of glyphs', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.buffer = hb.createBuffer();
- this.buffer.addText('rtl');
- this.buffer.setDirection('rtl');
- hb.shape(this.font, this.buffer)
- const glyphs = this.buffer.json();
- expect(glyphs[0].g).to.equal(79); // l
- expect(glyphs[1].g).to.equal(87); // t
- expect(glyphs[2].g).to.equal(85); // r
- });
-
- it('setClusterLevel affects cluster merging', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.buffer = hb.createBuffer();
- this.buffer.setClusterLevel(1);
- this.buffer.addText('x́');
- this.buffer.guessSegmentProperties();
- hb.shape(this.font, this.buffer)
- const glyphs = this.buffer.json();
- expect(glyphs[0].cl).to.equal(0);
- expect(glyphs[1].cl).to.equal(1);
- });
-
- it('setFlags with PRESERVE_DEFAULT_IGNORABLES affects glyph ids', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.buffer = hb.createBuffer();
- this.buffer.addText('\u200dhi');
- this.buffer.setFlags(['PRESERVE_DEFAULT_IGNORABLES']);
- this.buffer.guessSegmentProperties();
- hb.shape(this.font, this.buffer)
- const glyphs = this.buffer.json();
- expect(glyphs[0].g).not.to.equal(3 /* space */);
- });
-});
-
-describe('shape', function () {
- it('shape Latin string', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.buffer = hb.createBuffer();
- this.buffer.addText('abc');
- this.buffer.guessSegmentProperties();
- hb.shape(this.font, this.buffer)
- const glyphs = this.buffer.json();
- expect(glyphs[0]).to.deep.equal({cl: 0, g: 68, ax: 561, ay: 0, dx: 0, dy: 0, flags: 0} /* a */);
- expect(glyphs[1]).to.deep.equal({cl: 1, g: 69, ax: 615, ay: 0, dx: 0, dy: 0, flags: 0} /* b */);
- expect(glyphs[2]).to.deep.equal({cl: 2, g: 70, ax: 480, ay: 0, dx: 0, dy: 0, flags: 0} /* c */);
- });
-
- it('shape Arabic string', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSansArabic-Variable.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.buffer = hb.createBuffer();
- this.buffer.addText('أبجد');
- this.buffer.guessSegmentProperties();
- hb.shape(this.font, this.buffer)
- const glyphs = this.buffer.json();
- expect(glyphs[0]).to.deep.equal({cl: 3, g: 213, ax: 532, ay: 0, dx: 0, dy: 0, flags: 1} /* د */);
- expect(glyphs[1]).to.deep.equal({cl: 2, g: 529, ax: 637, ay: 0, dx: 0, dy: 0, flags: 1} /* ج */);
- expect(glyphs[2]).to.deep.equal({cl: 1, g: 101, ax: 269, ay: 0, dx: 0, dy: 0, flags: 0} /* ب */);
- expect(glyphs[3]).to.deep.equal({cl: 0, g: 50, ax: 235, ay: 0, dx: 0, dy: 0, flags: 0} /* أ */);
- });
-
- it('shape with tracing', function () {
- this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
- this.face = hb.createFace(this.blob);
- this.font = hb.createFont(this.face);
- this.buffer = hb.createBuffer();
- this.buffer.addText('abc');
- this.buffer.guessSegmentProperties();
- const result = hb.shapeWithTrace(this.font, this.buffer, 0, 0)
- expect(result).to.have.lengthOf(42);
- expect(result[0]).to.deep.equal({
- "m": "start table GSUB script tag 'latn'",
- "glyphs": true,
- "t": [
- {cl: 0, g: 68},
- {cl: 1, g: 69},
- {cl: 2, g: 70},
- ],
- });
- expect(result[41]).to.deep.equal({
- "m": "end table GPOS script tag 'latn'",
- "glyphs": true,
- "t": [
- {cl: 0, g: 68, ax: 561, ay: 0, dx: 0, dy: 0},
- {cl: 1, g: 69, ax: 615, ay: 0, dx: 0, dy: 0},
- {cl: 2, g: 70, ax: 480, ay: 0, dx: 0, dy: 0},
- ],
- });
- });
-});
diff --git a/tests/buffer.spec.ts b/tests/buffer.spec.ts
new file mode 100644
index 0000000..e2c8183
--- /dev/null
+++ b/tests/buffer.spec.ts
@@ -0,0 +1,70 @@
+import * as path from 'path'
+import * as fs from 'fs'
+import { afterEach, beforeEach, describe, expect, it } from 'vitest'
+import type { hb as hbjs } from '~/node'
+import { initHB } from '~/node'
+
+type HB = ReturnType
+type Nullable = T | undefined | null
+declare global {
+ var blob: Nullable>
+ var face: Nullable>
+ var font: Nullable>
+ var buffer: Nullable>
+}
+let hb: HB
+beforeEach(async () => {
+ hb = await initHB()
+})
+
+afterEach(() => {
+ if (globalThis.buffer) globalThis.buffer.destroy()
+ if (globalThis.font) globalThis.font.destroy()
+ if (globalThis.face) globalThis.face.destory()
+ if (globalThis.blob) globalThis.blob.destory()
+ globalThis.blob = globalThis.face = globalThis.font = globalThis.buffer = null
+})
+
+describe('Buffer', () => {
+ it('setDirection controls direction of glyphs', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.addText('rtl')
+ globalThis.buffer.setDirection('rtl')
+ hb.shape(globalThis.font, globalThis.buffer)
+ const glyphs = globalThis.buffer.json()
+
+ expect(glyphs[0].g).to.equal(79) // l
+ expect(glyphs[1].g).to.equal(87) // t
+ expect(glyphs[2].g).to.equal(85) // r
+ })
+
+ it('setClusterLevel affects cluster merging', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.setClusterLevel(1)
+ globalThis.buffer.addText('x́')
+ globalThis.buffer.guessSegmentProperties()
+ hb.shape(globalThis.font, globalThis.buffer)
+ const glyphs = globalThis.buffer.json()
+ expect(glyphs[0].cl).to.equal(0)
+ expect(glyphs[1].cl).to.equal(1)
+ })
+
+ it('setFlags with PRESERVE_DEFAULT_IGNORABLES affects glyph ids', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.addText('\u200dhi')
+ globalThis.buffer.setFlags(['REMOVE_DEFAULT_IGNORABLES'])
+ globalThis.buffer.guessSegmentProperties()
+ hb.shape(globalThis.font, globalThis.buffer)
+ const glyphs = globalThis.buffer.json()
+ expect(glyphs[0].g).not.to.equal(3 /* space */)
+ })
+})
\ No newline at end of file
diff --git a/tests/face.spec.ts b/tests/face.spec.ts
new file mode 100644
index 0000000..1fc4825
--- /dev/null
+++ b/tests/face.spec.ts
@@ -0,0 +1,55 @@
+import * as path from 'path'
+import * as fs from 'fs'
+import { afterEach, beforeEach, describe, expect, it } from 'vitest'
+import type { hb as hbjs } from '~/node';
+import { initHB } from '~/node'
+
+type HB = ReturnType
+type Nullable = T | undefined | null
+declare global {
+ var blob: Nullable>
+ var face: Nullable>
+}
+let hb: HB
+beforeEach(async () => {
+ hb = await initHB()
+})
+
+afterEach(() => {
+ if (globalThis.blob) globalThis.blob.destory()
+ if (globalThis.face) globalThis.face.destory()
+ globalThis.blob = globalThis.face = null
+})
+
+describe('Face', () => {
+ it('collectUnicodes reflects codepoints supported by the font', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ const codepoints = [
+ ...globalThis.face.collectUnicodes()
+ ]
+ expect(codepoints).to.include('a'.codePointAt(0))
+ expect(codepoints).to.not.include('ا'.codePointAt(0))
+ })
+
+ it('expose upem', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ expect(globalThis.face.upem).to.equal(1000)
+ })
+
+ it('getAxisInfos returns details of a variable font', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSansArabic-Variable.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ expect(globalThis.face.getAxisInfos()).to.deep.equal({
+ wght: { min: 100, default: 400, max: 900 },
+ wdth: { min: 62.5, default: 100, max: 100 }
+ })
+ })
+
+ it('getAxisInfos returns an empty object for a non-variable font', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ expect(Object.keys(globalThis.face.getAxisInfos())).to.have.length(0)
+ })
+})
\ No newline at end of file
diff --git a/tests/font.spec.ts b/tests/font.spec.ts
new file mode 100644
index 0000000..3526048
--- /dev/null
+++ b/tests/font.spec.ts
@@ -0,0 +1,60 @@
+import { describe, it, expect, beforeEach, afterEach } from 'vitest'
+import * as path from 'path'
+import * as fs from 'fs'
+import { initHB, hb as hbjs } from '~/node'
+
+type HB = ReturnType
+type Nullable = T | undefined | null
+declare global {
+ var blob: Nullable>
+ var face: Nullable>
+ var font: Nullable>
+ var buffer: Nullable>
+}
+let hb: HB
+beforeEach(async () => {
+ hb = await initHB()
+})
+
+afterEach(() => {
+ if (globalThis.buffer) globalThis.buffer.destroy()
+ if (globalThis.font) globalThis.font.destroy()
+ if (globalThis.face) globalThis.face.destory()
+ if (globalThis.blob) globalThis.blob.destory()
+ globalThis.blob = globalThis.face = globalThis.font = globalThis.buffer = null
+})
+
+describe('Font', () => {
+ it('glyphName returns names for glyph ids', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ expect(globalThis.font.glyphName(20)).to.equal('one')
+ })
+
+ it('setScale affects advances', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.addText('a')
+ globalThis.buffer.guessSegmentProperties()
+ globalThis.font.setScale(1000 * 2, 1000 * 2)
+ hb.shape(globalThis.font, globalThis.buffer)
+ const glyphs = globalThis.buffer.json()
+ expect(glyphs[0].ax).to.equal(561 * 2)
+ })
+
+ it('setVariations affects advances', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSansArabic-Variable.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.font.setVariations({ wght: 789 })
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.addText('آلو')
+ globalThis.buffer.guessSegmentProperties()
+ hb.shape(globalThis.font, globalThis.buffer)
+ const glyphs = globalThis.buffer.json()
+ expect(glyphs[0].ax).to.equal(526)
+ })
+})
\ No newline at end of file
diff --git a/tests/fonts/noto/NotoSans-Regular.ttf b/tests/fonts/noto/NotoSans-Regular.ttf
new file mode 100644
index 0000000..973bc2e
Binary files /dev/null and b/tests/fonts/noto/NotoSans-Regular.ttf differ
diff --git a/test/fonts/noto/NotoSansArabic-Variable.ttf b/tests/fonts/noto/NotoSansArabic-Variable.ttf
similarity index 100%
rename from test/fonts/noto/NotoSansArabic-Variable.ttf
rename to tests/fonts/noto/NotoSansArabic-Variable.ttf
diff --git a/test/fonts/noto/OFL.txt b/tests/fonts/noto/OFL.txt
similarity index 100%
rename from test/fonts/noto/OFL.txt
rename to tests/fonts/noto/OFL.txt
diff --git a/tests/shape.spec.ts b/tests/shape.spec.ts
new file mode 100644
index 0000000..df4057d
--- /dev/null
+++ b/tests/shape.spec.ts
@@ -0,0 +1,85 @@
+import { describe, it, expect, beforeEach, afterEach } from 'vitest'
+import * as path from 'path'
+import * as fs from 'fs'
+import { initHB, hb as hbjs } from '~/node'
+
+type HB = ReturnType
+type Nullable = T | undefined | null
+declare global {
+ var blob: Nullable>
+ var face: Nullable>
+ var font: Nullable>
+ var buffer: Nullable>
+}
+let hb: HB
+beforeEach(async () => {
+ hb = await initHB()
+})
+
+afterEach(() => {
+ if (globalThis.buffer) globalThis.buffer.destroy()
+ if (globalThis.font) globalThis.font.destroy()
+ if (globalThis.face) globalThis.face.destory()
+ if (globalThis.blob) globalThis.blob.destory()
+ globalThis.blob = globalThis.face = globalThis.font = globalThis.buffer = null
+})
+
+describe('shape', () => {
+ it('shape Latin string', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.addText('abc')
+ globalThis.buffer.guessSegmentProperties()
+ hb.shape(globalThis.font, globalThis.buffer)
+ const glyphs = globalThis.buffer.json()
+ expect(glyphs[0]).to.deep.equal({cl: 0, g: 68, ax: 561, ay: 0, dx: 0, dy: 0, flags: 0} /* a */);
+ expect(glyphs[1]).to.deep.equal({cl: 1, g: 69, ax: 615, ay: 0, dx: 0, dy: 0, flags: 0} /* b */);
+ expect(glyphs[2]).to.deep.equal({cl: 2, g: 70, ax: 480, ay: 0, dx: 0, dy: 0, flags: 0} /* c */);
+ })
+
+ it('shape Arabic string', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSansArabic-Variable.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.addText('أبجد')
+ globalThis.buffer.guessSegmentProperties()
+ hb.shape(globalThis.font, globalThis.buffer)
+ const glyphs = globalThis.buffer.json()
+ expect(glyphs[0]).to.deep.equal({cl: 3, g: 213, ax: 532, ay: 0, dx: 0, dy: 0, flags: 1} /* د */)
+ expect(glyphs[1]).to.deep.equal({cl: 2, g: 529, ax: 637, ay: 0, dx: 0, dy: 0, flags: 1} /* ج */)
+ expect(glyphs[2]).to.deep.equal({cl: 1, g: 101, ax: 269, ay: 0, dx: 0, dy: 0, flags: 0} /* ب */)
+ expect(glyphs[3]).to.deep.equal({cl: 0, g: 50, ax: 235, ay: 0, dx: 0, dy: 0, flags: 0} /* أ */)
+ })
+
+ it('shape with tracing', () => {
+ globalThis.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')))
+ globalThis.face = hb.createFace(globalThis.blob, 0)
+ globalThis.font = hb.createFont(globalThis.face)
+ globalThis.buffer = hb.createBuffer()
+ globalThis.buffer.addText('abc')
+ globalThis.buffer.guessSegmentProperties()
+ const result = hb.shapeWithTrace(globalThis.font, globalThis.buffer, '', 0, 0)
+ expect(result).to.have.lengthOf(42)
+ expect(result[0]).to.deep.equal({
+ "m": "start table GSUB script tag 'latn'",
+ "glyphs": true,
+ "t": [
+ {cl: 0, g: 68},
+ {cl: 1, g: 69},
+ {cl: 2, g: 70},
+ ],
+ })
+ expect(result[41]).to.deep.equal({
+ "m": "end table GPOS script tag 'latn'",
+ "glyphs": true,
+ "t": [
+ {cl: 0, g: 68, ax: 561, ay: 0, dx: 0, dy: 0},
+ {cl: 1, g: 69, ax: 615, ay: 0, dx: 0, dy: 0},
+ {cl: 2, g: 70, ax: 480, ay: 0, dx: 0, dy: 0},
+ ],
+ })
+ })
+})
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 4e2c2e2..941bd93 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,17 +1,22 @@
{
"compileOnSave": true,
"compilerOptions": {
- "module": "es6",
- "target": "es6",
+ "module": "ES6",
+ "target": "ES6",
"sourceMap": true,
"alwaysStrict": true,
"noImplicitThis": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"strictNullChecks": true,
+ "moduleResolution": "Node",
"skipLibCheck": true,
- "strictPropertyInitialization": true
+ "strictPropertyInitialization": true,
+ "paths": {
+ "~/*": ["./src/*"]
+ }
},
+ "include": ["./src/**/*.ts", "./tests/**/*.ts", "vitest.config.ts"],
"exclude": [
"node_modules"
]
diff --git a/tsup.config.ts b/tsup.config.ts
new file mode 100644
index 0000000..87a9f5a
--- /dev/null
+++ b/tsup.config.ts
@@ -0,0 +1,21 @@
+import { defineConfig } from 'tsup'
+
+export default defineConfig([{
+ entry: ['src/client.ts'],
+ outDir: 'dist/client',
+ minify: true,
+ splitting: false,
+ sourcemap: true,
+ target: 'es2015',
+ dts: true,
+ format: ['esm', 'iife']
+}, {
+ entry: ['src/node.ts'],
+ outDir: 'dist/node',
+ minify: true,
+ splitting: false,
+ sourcemap: true,
+ target: 'node16',
+ dts: true,
+ format: ['esm', 'cjs']
+}])
\ No newline at end of file
diff --git a/vitest.config.ts b/vitest.config.ts
new file mode 100644
index 0000000..7cb5566
--- /dev/null
+++ b/vitest.config.ts
@@ -0,0 +1,10 @@
+import { resolve } from 'path'
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ resolve: {
+ alias: [
+ { find: '~', replacement: resolve(__dirname, './src') }
+ ]
+ }
+})
\ No newline at end of file