playwright-clipboard-testing 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,7 @@ Testing the Clipboard API in Playwright usually requires boilerplate code to man
15
15
  **playwright-clipboard-testing** simplifies this with:
16
16
  - 🔌 **Zero configuration** — Chromium permissions are granted automatically under the hood (Firefox requires a 1-line config setup).
17
17
  - 🔄 **Built-in Auto-retries & Polling** — Uses Playwright's native `expect` polling to wait until the clipboard updates asynchronously.
18
- - 📦 **TypeScript Ready** — Full type safety for JSON objects with `readJSON<T>()`.
18
+ - 📦 **TypeScript Ready** — Full type safety for JSON objects with `readJSON<T>()` and `writeJSON<T>()`.
19
19
 
20
20
  ## Table of Contents
21
21
  - [Why?](#why)
@@ -24,11 +24,16 @@ Testing the Clipboard API in Playwright usually requires boilerplate code to man
24
24
  - [Usage](#usage)
25
25
  - [Direct Usage](#direct-usage)
26
26
  - [Extended Usage](#extended-usage)
27
+ - [Subpath Exports](#subpath-exports)
27
28
  - [API](#api)
28
- - [Clipboard Fixtures](#clipboard-fixtures)
29
+ - [Fixtures](#fixtures)
30
+ - [ClipboardHandler](#clipboardhandler)
31
+ - [toBeBlank Matcher](#tobeblank-matcher)
32
+ - [toHaveContentLength Matcher](#tohavecontentlength-matcher)
29
33
  - [toHaveTextContent Matcher](#tohavetextcontent-matcher)
30
34
  - [toHaveJSONContent Matcher](#tohavejsoncontent-matcher)
31
- - [toHaveData Matcher](#tohavedata-matcher)
35
+ - [toMatchJSONContent Matcher](#tomatchjsoncontent-matcher)
36
+ - [PATTERNS](#patterns)
32
37
  - [Author](#author)
33
38
  - [License](#license)
34
39
 
@@ -56,7 +61,7 @@ test('should copy text to clipboard', async ({ page, clipboard, browserName }) =
56
61
  If your Playwright setup runs tests in Firefox, manually configure `firefoxUserPrefs` in your Playwright config:
57
62
  ```ts
58
63
  import { defineConfig, devices } from '@playwright/test';
59
- import { firefoxClipboardPrefs } from 'playwright-clipboard-testing';
64
+ import { firefoxClipboardPrefs } from 'playwright-clipboard-testing/constants';
60
65
 
61
66
  export default defineConfig({
62
67
  projects: [
@@ -93,42 +98,97 @@ test('should copy text to clipboard', async ({ page, clipboard }) => {
93
98
  If you already have a custom test fixture file, extend Playwright's `test` and `expect` with `clipboardFixtures` and `clipboardMatchers`:
94
99
  ```ts
95
100
  import { expect as baseExpect, test as baseTest } from '@playwright/test';
96
- import {
97
- type ClipboardHandler,
98
- clipboardFixtures,
99
- clipboardMatchers,
100
- } from 'playwright-clipboard-testing';
101
+ import { type ClipboardHandler, clipboardFixtures } from 'playwright-clipboard-testing/fixtures';
102
+ import { clipboardMatchers } from 'playwright-clipboard-testing/matchers';
101
103
 
102
104
  export const test = baseTest.extend<{ clipboard: ClipboardHandler }>(clipboardFixtures);
103
105
 
104
106
  export const expect = baseExpect.extend(clipboardMatchers);
107
+
105
108
  ```
106
109
 
110
+ ## Subpath Exports
111
+
112
+ The package provides dedicated subpath exports to import specific utilities when extending Playwright:
113
+
114
+ | Import Path | Exports | Description |
115
+ |:-----------------------------------------|:------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------|
116
+ | `playwright-clipboard-testing` | `test`, `expect` | Ready-to-use Playwright `test` runner and `expect` assertion function with built-in clipboard support. |
117
+ | `playwright-clipboard-testing/constants` | `firefoxClipboardPrefs`, `PATTERNS` | Firefox browser preferences for clipboard permissions and regex patterns for clipboard assertions. |
118
+ | `playwright-clipboard-testing/fixtures` | `clipboardFixtures`, `clipboardFixture`, `contextFixture`, `ClipboardHandler` | Playwright test fixtures and `ClipboardHandler` class for extending custom test setups. |
119
+ | `playwright-clipboard-testing/matchers` | `clipboardMatchers` | Custom Playwright matchers for extending custom `expect`. |
120
+
107
121
  ## API
108
- ### Clipboard Fixtures
109
- The package exports `clipboardFixtures` (containing `context` and `clipboard` fixtures) as well as individual fixtures `clipboardFixture` and `contextFixture`:
110
122
 
111
- - `clipboardFixtures` — Object containing both `context` and `clipboard` fixtures for simple fixture extension.
112
- - `contextFixture` (`context`) — Automatically grants `clipboard-read` and `clipboard-write` permissions to Chromium browser contexts.
113
- - `clipboardFixture` (`clipboard`) — Provides direct access to the `ClipboardHandler` instance during tests:
114
- - `clipboard.read(): Promise<string>` — reads the current plain text content from the clipboard.
115
- - `clipboard.readJSON<T>(): Promise<T>` — reads the current clipboard content and parses it as a JSON object of type `T`. Throws an error if the content is not valid JSON.
123
+ ### Fixtures
124
+ The package exports the following fixtures for Playwright test configuration:
125
+
126
+ - `clipboardFixtures` — Object containing both `context` and `clipboard` fixtures. Recommended for extending test fixtures.
127
+ - `contextFixture` (`context`) — Playwright context fixture that automatically grants `clipboard-read` and `clipboard-write` permissions in Chromium.
128
+ - `clipboardFixture` (`clipboard`) — Playwright test fixture that provides access to the `ClipboardHandler` instance in your tests.
129
+
130
+ ### ClipboardHandler
131
+ The `clipboard` fixture provides direct access to the `ClipboardHandler` instance for managing clipboard state:
132
+
133
+ | Method | Return Type | Description |
134
+ |:---------------------|:------------------|:-------------------------------------------------------------------------------------------------------------------------|
135
+ | `read()` | `Promise<string>` | Reads plain text content from the clipboard. |
136
+ | `write(text)` | `Promise<void>` | Writes the specified plain text to the clipboard. |
137
+ | `readJSON<T>()` | `Promise<T>` | Reads clipboard content and parses it as a JSON object of type `T`. Throws an error if invalid JSON. |
138
+ | `writeJSON<T>(data)` | `Promise<void>` | Serializes an object of type `T` to JSON and writes it to the clipboard. Throws an error if object cannot be serialized. |
139
+ | `clear()` | `Promise<void>` | Clears all clipboard content. |
116
140
 
117
141
  ![NOTE](https://img.shields.io/badge/NOTE-For%20your%20tests%20we%20recommend%20using%20existing%20matchers%20to%20assert%20clipboard%20content-yellow)
118
142
 
143
+ ### toBeBlank Matcher
144
+ `expect(clipboard).toBeBlank(options?)`
145
+ Asserts that the clipboard is empty. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
146
+ - `options.timeout: number (optional, default: 10000ms)`
147
+ - `options.trim: boolean (optional, default: false)` — Trims whitespace from the clipboard content before checking if it's blank.
148
+ ```ts
149
+ // assert that the clipboard is empty
150
+ await expect(clipboard).toBeBlank();
151
+ ```
152
+ ```ts
153
+ // assert that the clipboard is not empty with a custom timeout
154
+ await expect(clipboard).not.toBeBlank({ timeout: 5000 });
155
+ ```
156
+
157
+ ### toHaveContentLength Matcher
158
+ `expect(clipboard).toHaveContentLength(expected, options?)`
159
+
160
+ Asserts that the clipboard content has the expected length. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
161
+ - `expected: number` — Expected length of the clipboard content.
162
+ - `options.timeout: number (optional, default: 10000ms)` — Time in milliseconds to wait for the clipboard content to match.
163
+ - `options.trim: boolean (optional, default: false)` — Trims whitespace from the clipboard content before checking its length.
164
+ ```ts
165
+ // assert that the clipboard content has the expected length
166
+ await expect(clipboard).toHaveContentLength(13);
167
+ ```
168
+ ```ts
169
+ // assert that the clipboard content does not have the expected length with trim option
170
+ await expect(clipboard).not.toHaveContentLength(10, { trim: true });
171
+ ```
172
+
119
173
  ### toHaveTextContent Matcher
120
174
  `expect(clipboard).toHaveTextContent(expected, options?)`
121
175
 
122
- Asserts that the clipboard content matches the expected string. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
123
- - `expected: string` — Expected text to compare against.
176
+ Asserts that the clipboard content matches the expected string or regular expression. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
177
+ - `expected: string | RegExp` — Expected text string or regular expression to match against.
124
178
  - `options.timeout: number (optional, default: 10000ms)` — Time in milliseconds to wait for the clipboard content to match.
179
+ - `options.ignoreCase: boolean (optional, default: false)` — Ignores case when comparing strings or matching regular expressions.
180
+ - `options.trim: boolean (optional, default: false)` — Trims whitespace from both expected and actual string before comparison.
125
181
  ```ts
126
182
  // assert that the clipboard contains the expected text
127
183
  await expect(clipboard).toHaveTextContent('Hello, World!');
128
184
  ```
129
185
  ```ts
130
- // Custom timeout
131
- await expect(clipboard).toHaveTextContent('Async copied value', { timeout: 5000 });
186
+ // assert that the clipboard text matches a regular expression
187
+ await expect(clipboard).toHaveTextContent(/Hello, World!/i);
188
+ ```
189
+ ```ts
190
+ // assert that the clipboard is not containing the expected text with a custom timeout
191
+ await expect(clipboard).not.toHaveTextContent('Async copied value', { timeout: 5000 });
132
192
  ```
133
193
 
134
194
  ### toHaveJSONContent Matcher
@@ -141,29 +201,50 @@ Asserts that the clipboard content matches the expected JSON value. Uses Playwri
141
201
  await expect(clipboard).toHaveJSONContent({ message: 'Hello, World!' });
142
202
  ```
143
203
  ```ts
144
- // Custom timeout
145
- await expect(clipboard).toHaveJSONContent({ message: 'Async copied value' }, { timeout: 5000 });
204
+ // assert that the clipboard is not containing the expected JSON data with a custom timeout
205
+ await expect(clipboard).not.toHaveJSONContent({ message: 'Async copied value' }, { timeout: 5000 });
146
206
  ```
147
207
 
148
- ### toHaveData Matcher
149
- ![NOTE](https://img.shields.io/badge/NOTE-Matcher%20is%20deprecated%20in%20favor%20of%20toHaveTextContent%20and%20toHaveJSONContent-yellow)
150
-
151
- `expect(clipboard).toHaveData(expected, options?)`
152
-
153
- Asserts that the clipboard content matches the expected string or JSON object. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
154
- - `expected: unknown` — Expected text or object to compare against.
155
- - `options.timeout: number (optional, default: 10000ms)` — Time in milliseconds to wait for the clipboard data to match.
208
+ ### toMatchJSONContent Matcher
209
+ `expect(clipboard).toMatchJSONContent(expected, options?)`
210
+ Asserts that the expected JSON object is a subset of the clipboard content. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
211
+ - `expected: unknown` — Expected JSON subset object to compare against.
212
+ - `options.timeout: number (optional, default: 10000ms)` — Time in milliseconds to wait for the clipboard content to match.
156
213
  ```ts
157
- // assert that the clipboard contains the expected text
158
- await expect(clipboard).toHaveData('Hello, World!');
214
+ // assert that the clipboard contains a subset of the expected JSON data
215
+ await expect(clipboard).toMatchJSONContent({ status: 'success' });
159
216
  ```
160
217
  ```ts
161
- // assert that the clipboard contains the expected JSON data
162
- await expect(clipboard).toHaveData({ message: 'Hello, World!' });
218
+ // assert that the clipboard is not containing a subset of the expected JSON data with a custom timeout
219
+ await expect(clipboard).not.toMatchJSONContent({ status: 'failed' }, { timeout: 5000 });
163
220
  ```
221
+
222
+ ### PATTERNS
223
+ The package exports pre-defined regular expression patterns for common data formats (`PATTERNS`), which can be passed directly to `toHaveTextContent`:
224
+
225
+ | Pattern | Description | Example Match |
226
+ |:------------|:-------------------------------------|:------------------------------------------|
227
+ | `UUID` | UUID v1–v5 format | `123e4567-e89b-12d3-a456-426614174000` |
228
+ | `EMAIL` | Email address format | `user@example.com` |
229
+ | `PHONE` | Phone number in E.164 format | `+1234567890` |
230
+ | `JWT` | JWT token format | `header.payload.signature` |
231
+ | `BEARER` | Bearer authentication token format | `Bearer token123` |
232
+ | `HEX_COLOR` | HEX color format | `#FFF`, `#FFFFFF`, `#FFFFFFFF` |
233
+ | `IP.V4` | IPv4 address format | `192.168.1.1` |
234
+ | `IP.V6` | IPv6 address format | `2001:0db8:85a3:0000:0000:8a2e:0370:7334` |
235
+ | `IP.ANY` | Any IP address format (IPv4 or IPv6) | `192.168.1.1` or `2001:db8::1` |
236
+
237
+ To use a pattern in your test, import `PATTERNS` and pass the desired pattern to `toHaveTextContent`:
164
238
  ```ts
165
- // Custom timeout
166
- await expect(clipboard).toHaveData('Async copied value', { timeout: 5000 });
239
+ import { expect, test } from 'playwright-clipboard-testing';
240
+ import { PATTERNS } from 'playwright-clipboard-testing/constants';
241
+
242
+ test('should copy UUID to clipboard', async ({ page, clipboard }) => {
243
+ await page.goto('https://example.com');
244
+ await page.locator('#copy-uuid-button').click();
245
+
246
+ await expect(clipboard).toHaveTextContent(PATTERNS.UUID);
247
+ });
167
248
  ```
168
249
 
169
250
  ## Author
@@ -0,0 +1,51 @@
1
+ import { Page } from '@playwright/test';
2
+
3
+ /**
4
+ * Playwright-compatible Clipboard utilities.
5
+ *
6
+ * Core functions for interacting with the browser clipboard within Playwright tests.
7
+ * Provides wrappers for reading plain text and JSON.
8
+ *
9
+ * @remarks
10
+ * These utilities require 'clipboard-read' and 'clipboard-write' permissions
11
+ * to be granted in the browser context.
12
+ */
13
+
14
+ declare class ClipboardHandler {
15
+ private readonly page;
16
+ constructor(page: Page);
17
+ /**
18
+ * Reads the current text content from the browser clipboard.
19
+ * If the content is a JSON-encoded string (e.g., has extra quotes),
20
+ * it will be returned as is. Use readJSON for automatic parsing.
21
+ *
22
+ * @returns A promise that resolves to the clipboard string content.
23
+ */
24
+ read(): Promise<string>;
25
+ /**
26
+ * Reads the clipboard content and parses it as JSON.
27
+ * If the content is a string literal (e.g., '"value"'), it returns the unwrapped string ('value').
28
+ *
29
+ * @template T - The expected type of the parsed JSON object.
30
+ * @returns A promise that resolves to the parsed JSON object of type T.
31
+ * @throws {Error} If the clipboard content is not a valid JSON string.
32
+ */
33
+ readJSON<T = unknown>(): Promise<T>;
34
+ /**
35
+ * Writes the provided string data to the browser clipboard.
36
+ * @param data The data to write to the clipboard.
37
+ */
38
+ write(data: string): Promise<void>;
39
+ /**
40
+ * Writes the provided data to the browser clipboard as a JSON string.
41
+ * @param data The data to write to the clipboard. It will be stringified as JSON.
42
+ */
43
+ writeJSON<T = unknown>(data: T): Promise<void>;
44
+ /**
45
+ * Clears the browser clipboard by writing an empty string to it.
46
+ * This effectively removes any existing content from the clipboard.
47
+ */
48
+ clear(): Promise<void>;
49
+ }
50
+
51
+ export { ClipboardHandler as C };
@@ -0,0 +1,51 @@
1
+ import { Page } from '@playwright/test';
2
+
3
+ /**
4
+ * Playwright-compatible Clipboard utilities.
5
+ *
6
+ * Core functions for interacting with the browser clipboard within Playwright tests.
7
+ * Provides wrappers for reading plain text and JSON.
8
+ *
9
+ * @remarks
10
+ * These utilities require 'clipboard-read' and 'clipboard-write' permissions
11
+ * to be granted in the browser context.
12
+ */
13
+
14
+ declare class ClipboardHandler {
15
+ private readonly page;
16
+ constructor(page: Page);
17
+ /**
18
+ * Reads the current text content from the browser clipboard.
19
+ * If the content is a JSON-encoded string (e.g., has extra quotes),
20
+ * it will be returned as is. Use readJSON for automatic parsing.
21
+ *
22
+ * @returns A promise that resolves to the clipboard string content.
23
+ */
24
+ read(): Promise<string>;
25
+ /**
26
+ * Reads the clipboard content and parses it as JSON.
27
+ * If the content is a string literal (e.g., '"value"'), it returns the unwrapped string ('value').
28
+ *
29
+ * @template T - The expected type of the parsed JSON object.
30
+ * @returns A promise that resolves to the parsed JSON object of type T.
31
+ * @throws {Error} If the clipboard content is not a valid JSON string.
32
+ */
33
+ readJSON<T = unknown>(): Promise<T>;
34
+ /**
35
+ * Writes the provided string data to the browser clipboard.
36
+ * @param data The data to write to the clipboard.
37
+ */
38
+ write(data: string): Promise<void>;
39
+ /**
40
+ * Writes the provided data to the browser clipboard as a JSON string.
41
+ * @param data The data to write to the clipboard. It will be stringified as JSON.
42
+ */
43
+ writeJSON<T = unknown>(data: T): Promise<void>;
44
+ /**
45
+ * Clears the browser clipboard by writing an empty string to it.
46
+ * This effectively removes any existing content from the clipboard.
47
+ */
48
+ clear(): Promise<void>;
49
+ }
50
+
51
+ export { ClipboardHandler as C };
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/constants/index.ts
21
+ var constants_exports = {};
22
+ __export(constants_exports, {
23
+ PATTERNS: () => PATTERNS,
24
+ firefoxClipboardPrefs: () => firefoxClipboardPrefs
25
+ });
26
+ module.exports = __toCommonJS(constants_exports);
27
+
28
+ // src/constants/constants.ts
29
+ var firefoxClipboardPrefs = {
30
+ "dom.events.testing.asyncClipboard": true,
31
+ "dom.events.asyncClipboard.readText": true,
32
+ "dom.events.asyncClipboard.writeText": true,
33
+ "permissions.default.clipboard-read": 1,
34
+ "permissions.default.clipboard-write": 1
35
+ };
36
+
37
+ // src/constants/patterns.ts
38
+ var PATTERNS = {
39
+ /**
40
+ * UUID v1-v5 (example: 123e4567-e89b-12d3-a456-426614174000).
41
+ */
42
+ UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
43
+ /**
44
+ * Email addresses (example: user@example.com).
45
+ */
46
+ EMAIL: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
47
+ /**
48
+ * Phone numbers in E.164 format (example: +1234567890).
49
+ */
50
+ PHONE: /^\+[1-9]\d{1,14}$/,
51
+ /**
52
+ * JWT tokens (example: header.payload.signature).
53
+ */
54
+ JWT: /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/,
55
+ /**
56
+ * Authorization Bearer tokens (example: Bearer <token>).
57
+ */
58
+ BEARER: /^Bearer\s+[a-zA-Z0-9._~+/-]+=*$/i,
59
+ /**
60
+ * HEX-colors (example: #FFF, #FFFFFF, #FFFFFFFF).
61
+ */
62
+ HEX_COLOR: /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i,
63
+ /**
64
+ * IP (IPv4, IPv6 or any).
65
+ */
66
+ IP: {
67
+ /** IPv4 (example: 192.168.1.1 or 127.0.0.1) */
68
+ V4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
69
+ /** IPv6 (example: 2001:0db8:85a3:0000:0000:8a2e:0370:7334) */
70
+ V6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,
71
+ /** Any IP address (IPv4 or IPv6) */
72
+ ANY: /^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))$/
73
+ }
74
+ };
75
+ // Annotate the CommonJS export names for ESM import in node:
76
+ 0 && (module.exports = {
77
+ PATTERNS,
78
+ firefoxClipboardPrefs
79
+ });
80
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/constants/index.ts","../../src/constants/constants.ts","../../src/constants/patterns.ts"],"sourcesContent":["import { firefoxClipboardPrefs } from './constants.ts';\nimport { PATTERNS } from './patterns.ts';\n\nexport { firefoxClipboardPrefs, PATTERNS };\n","export const firefoxClipboardPrefs = {\n 'dom.events.testing.asyncClipboard': true,\n 'dom.events.asyncClipboard.readText': true,\n 'dom.events.asyncClipboard.writeText': true,\n 'permissions.default.clipboard-read': 1,\n 'permissions.default.clipboard-write': 1,\n};\n","/**\n * This module contains regular expression patterns for various common formats.\n * These patterns can be used for validation purposes in applications.\n */\nexport const PATTERNS = {\n /**\n * UUID v1-v5 (example: 123e4567-e89b-12d3-a456-426614174000).\n */\n UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n\n /**\n * Email addresses (example: user@example.com).\n */\n EMAIL: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/,\n\n /**\n * Phone numbers in E.164 format (example: +1234567890).\n */\n PHONE: /^\\+[1-9]\\d{1,14}$/,\n\n /**\n * JWT tokens (example: header.payload.signature).\n */\n JWT: /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/,\n\n /**\n * Authorization Bearer tokens (example: Bearer <token>).\n */\n BEARER: /^Bearer\\s+[a-zA-Z0-9._~+/-]+=*$/i,\n\n /**\n * HEX-colors (example: #FFF, #FFFFFF, #FFFFFFFF).\n */\n HEX_COLOR: /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i,\n\n /**\n * IP (IPv4, IPv6 or any).\n */\n IP: {\n /** IPv4 (example: 192.168.1.1 or 127.0.0.1) */\n V4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,\n\n /** IPv6 (example: 2001:0db8:85a3:0000:0000:8a2e:0370:7334) */\n V6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,\n\n /** Any IP address (IPv4 or IPv6) */\n ANY: /^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))$/,\n },\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,wBAAwB;AAAA,EACnC,qCAAqC;AAAA,EACrC,sCAAsC;AAAA,EACtC,uCAAuC;AAAA,EACvC,sCAAsC;AAAA,EACtC,uCAAuC;AACzC;;;ACFO,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA,EAItB,MAAM;AAAA;AAAA;AAAA;AAAA,EAKN,OAAO;AAAA;AAAA;AAAA;AAAA,EAKP,OAAO;AAAA;AAAA;AAAA;AAAA,EAKP,KAAK;AAAA;AAAA;AAAA;AAAA,EAKL,QAAQ;AAAA;AAAA;AAAA;AAAA,EAKR,WAAW;AAAA;AAAA;AAAA;AAAA,EAKX,IAAI;AAAA;AAAA,IAEF,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,KAAK;AAAA,EACP;AACF;","names":[]}
@@ -0,0 +1,51 @@
1
+ declare const firefoxClipboardPrefs: {
2
+ 'dom.events.testing.asyncClipboard': boolean;
3
+ 'dom.events.asyncClipboard.readText': boolean;
4
+ 'dom.events.asyncClipboard.writeText': boolean;
5
+ 'permissions.default.clipboard-read': number;
6
+ 'permissions.default.clipboard-write': number;
7
+ };
8
+
9
+ /**
10
+ * This module contains regular expression patterns for various common formats.
11
+ * These patterns can be used for validation purposes in applications.
12
+ */
13
+ declare const PATTERNS: {
14
+ /**
15
+ * UUID v1-v5 (example: 123e4567-e89b-12d3-a456-426614174000).
16
+ */
17
+ readonly UUID: RegExp;
18
+ /**
19
+ * Email addresses (example: user@example.com).
20
+ */
21
+ readonly EMAIL: RegExp;
22
+ /**
23
+ * Phone numbers in E.164 format (example: +1234567890).
24
+ */
25
+ readonly PHONE: RegExp;
26
+ /**
27
+ * JWT tokens (example: header.payload.signature).
28
+ */
29
+ readonly JWT: RegExp;
30
+ /**
31
+ * Authorization Bearer tokens (example: Bearer <token>).
32
+ */
33
+ readonly BEARER: RegExp;
34
+ /**
35
+ * HEX-colors (example: #FFF, #FFFFFF, #FFFFFFFF).
36
+ */
37
+ readonly HEX_COLOR: RegExp;
38
+ /**
39
+ * IP (IPv4, IPv6 or any).
40
+ */
41
+ readonly IP: {
42
+ /** IPv4 (example: 192.168.1.1 or 127.0.0.1) */
43
+ readonly V4: RegExp;
44
+ /** IPv6 (example: 2001:0db8:85a3:0000:0000:8a2e:0370:7334) */
45
+ readonly V6: RegExp;
46
+ /** Any IP address (IPv4 or IPv6) */
47
+ readonly ANY: RegExp;
48
+ };
49
+ };
50
+
51
+ export { PATTERNS, firefoxClipboardPrefs };
@@ -0,0 +1,51 @@
1
+ declare const firefoxClipboardPrefs: {
2
+ 'dom.events.testing.asyncClipboard': boolean;
3
+ 'dom.events.asyncClipboard.readText': boolean;
4
+ 'dom.events.asyncClipboard.writeText': boolean;
5
+ 'permissions.default.clipboard-read': number;
6
+ 'permissions.default.clipboard-write': number;
7
+ };
8
+
9
+ /**
10
+ * This module contains regular expression patterns for various common formats.
11
+ * These patterns can be used for validation purposes in applications.
12
+ */
13
+ declare const PATTERNS: {
14
+ /**
15
+ * UUID v1-v5 (example: 123e4567-e89b-12d3-a456-426614174000).
16
+ */
17
+ readonly UUID: RegExp;
18
+ /**
19
+ * Email addresses (example: user@example.com).
20
+ */
21
+ readonly EMAIL: RegExp;
22
+ /**
23
+ * Phone numbers in E.164 format (example: +1234567890).
24
+ */
25
+ readonly PHONE: RegExp;
26
+ /**
27
+ * JWT tokens (example: header.payload.signature).
28
+ */
29
+ readonly JWT: RegExp;
30
+ /**
31
+ * Authorization Bearer tokens (example: Bearer <token>).
32
+ */
33
+ readonly BEARER: RegExp;
34
+ /**
35
+ * HEX-colors (example: #FFF, #FFFFFF, #FFFFFFFF).
36
+ */
37
+ readonly HEX_COLOR: RegExp;
38
+ /**
39
+ * IP (IPv4, IPv6 or any).
40
+ */
41
+ readonly IP: {
42
+ /** IPv4 (example: 192.168.1.1 or 127.0.0.1) */
43
+ readonly V4: RegExp;
44
+ /** IPv6 (example: 2001:0db8:85a3:0000:0000:8a2e:0370:7334) */
45
+ readonly V6: RegExp;
46
+ /** Any IP address (IPv4 or IPv6) */
47
+ readonly ANY: RegExp;
48
+ };
49
+ };
50
+
51
+ export { PATTERNS, firefoxClipboardPrefs };
@@ -0,0 +1,52 @@
1
+ // src/constants/constants.ts
2
+ var firefoxClipboardPrefs = {
3
+ "dom.events.testing.asyncClipboard": true,
4
+ "dom.events.asyncClipboard.readText": true,
5
+ "dom.events.asyncClipboard.writeText": true,
6
+ "permissions.default.clipboard-read": 1,
7
+ "permissions.default.clipboard-write": 1
8
+ };
9
+
10
+ // src/constants/patterns.ts
11
+ var PATTERNS = {
12
+ /**
13
+ * UUID v1-v5 (example: 123e4567-e89b-12d3-a456-426614174000).
14
+ */
15
+ UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
16
+ /**
17
+ * Email addresses (example: user@example.com).
18
+ */
19
+ EMAIL: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
20
+ /**
21
+ * Phone numbers in E.164 format (example: +1234567890).
22
+ */
23
+ PHONE: /^\+[1-9]\d{1,14}$/,
24
+ /**
25
+ * JWT tokens (example: header.payload.signature).
26
+ */
27
+ JWT: /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/,
28
+ /**
29
+ * Authorization Bearer tokens (example: Bearer <token>).
30
+ */
31
+ BEARER: /^Bearer\s+[a-zA-Z0-9._~+/-]+=*$/i,
32
+ /**
33
+ * HEX-colors (example: #FFF, #FFFFFF, #FFFFFFFF).
34
+ */
35
+ HEX_COLOR: /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i,
36
+ /**
37
+ * IP (IPv4, IPv6 or any).
38
+ */
39
+ IP: {
40
+ /** IPv4 (example: 192.168.1.1 or 127.0.0.1) */
41
+ V4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
42
+ /** IPv6 (example: 2001:0db8:85a3:0000:0000:8a2e:0370:7334) */
43
+ V6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,
44
+ /** Any IP address (IPv4 or IPv6) */
45
+ ANY: /^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))$/
46
+ }
47
+ };
48
+ export {
49
+ PATTERNS,
50
+ firefoxClipboardPrefs
51
+ };
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/constants/constants.ts","../../src/constants/patterns.ts"],"sourcesContent":["export const firefoxClipboardPrefs = {\n 'dom.events.testing.asyncClipboard': true,\n 'dom.events.asyncClipboard.readText': true,\n 'dom.events.asyncClipboard.writeText': true,\n 'permissions.default.clipboard-read': 1,\n 'permissions.default.clipboard-write': 1,\n};\n","/**\n * This module contains regular expression patterns for various common formats.\n * These patterns can be used for validation purposes in applications.\n */\nexport const PATTERNS = {\n /**\n * UUID v1-v5 (example: 123e4567-e89b-12d3-a456-426614174000).\n */\n UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n\n /**\n * Email addresses (example: user@example.com).\n */\n EMAIL: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/,\n\n /**\n * Phone numbers in E.164 format (example: +1234567890).\n */\n PHONE: /^\\+[1-9]\\d{1,14}$/,\n\n /**\n * JWT tokens (example: header.payload.signature).\n */\n JWT: /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/,\n\n /**\n * Authorization Bearer tokens (example: Bearer <token>).\n */\n BEARER: /^Bearer\\s+[a-zA-Z0-9._~+/-]+=*$/i,\n\n /**\n * HEX-colors (example: #FFF, #FFFFFF, #FFFFFFFF).\n */\n HEX_COLOR: /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i,\n\n /**\n * IP (IPv4, IPv6 or any).\n */\n IP: {\n /** IPv4 (example: 192.168.1.1 or 127.0.0.1) */\n V4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,\n\n /** IPv6 (example: 2001:0db8:85a3:0000:0000:8a2e:0370:7334) */\n V6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,\n\n /** Any IP address (IPv4 or IPv6) */\n ANY: /^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))$/,\n },\n} as const;\n"],"mappings":";AAAO,IAAM,wBAAwB;AAAA,EACnC,qCAAqC;AAAA,EACrC,sCAAsC;AAAA,EACtC,uCAAuC;AAAA,EACvC,sCAAsC;AAAA,EACtC,uCAAuC;AACzC;;;ACFO,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA,EAItB,MAAM;AAAA;AAAA;AAAA;AAAA,EAKN,OAAO;AAAA;AAAA;AAAA;AAAA,EAKP,OAAO;AAAA;AAAA;AAAA;AAAA,EAKP,KAAK;AAAA;AAAA;AAAA;AAAA,EAKL,QAAQ;AAAA;AAAA;AAAA;AAAA,EAKR,WAAW;AAAA;AAAA;AAAA;AAAA,EAKX,IAAI;AAAA;AAAA,IAEF,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,KAAK;AAAA,EACP;AACF;","names":[]}