@windpress/oxide-parser 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,157 +1,90 @@
1
- # Setup Guide for @windpress/oxide-parser
1
+ # @windpress/oxide-parser
2
2
 
3
- This guide will help you set up the project and configure GitHub Actions with OIDC trusted publishing.
3
+ WASM-powered [Tailwind CSS's Oxide](https://www.npmjs.com/package/@tailwindcss/oxide) parser for browser and Node.js.
4
4
 
5
- ## Prerequisites
5
+ > [!NOTE]
6
+ >
7
+ > This package is automatically generated from the https://github.com/wind-press/oxide-parser repository.
6
8
 
7
- 1. **Rust and wasm-pack**
8
- ```bash
9
- # Install Rust
10
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
11
-
12
- # Install wasm-pack
13
- cargo install wasm-pack
14
- ```
15
-
16
- 2. **Node.js 18+**
17
- - Download from [nodejs.org](https://nodejs.org/)
18
-
19
- 3. **pnpm** (recommended)
20
- ```bash
21
- npm install -g pnpm
22
- ```
23
-
24
- ## Local Development
25
-
26
- ### 1. Install Dependencies
9
+ ## Installation
27
10
 
28
11
  ```bash
29
- pnpm install
12
+ npm install @windpress/oxide-parser
30
13
  ```
31
14
 
32
- ### 2. Build the Package
33
-
34
- ```bash
35
- # Build WASM module
36
- pnpm run build:wasm
15
+ ## Usage
37
16
 
38
- # Build TypeScript
39
- pnpm run build:ts
17
+ ```typescript
18
+ import { getCandidates } from '@windpress/oxide-parser';
40
19
 
41
- # Copy WASM files to dist
42
- pnpm run copy-wasm
20
+ // Single string
21
+ const candidates = await getCandidates('<div class="flex p-4">');
22
+ // ['flex', 'p-4']
43
23
 
44
- # Or build everything at once
45
- pnpm run build
24
+ // Multiple strings
25
+ const batch = await getCandidates([
26
+ '<div class="flex p-4">',
27
+ '<span class="text-white">',
28
+ ]);
29
+ // ['flex', 'p-4', 'text-white']
46
30
  ```
47
31
 
48
- ### 3. Run Development Server
32
+ ### CDN
49
33
 
50
- ```bash
51
- pnpm run dev
34
+ ```html
35
+ <script type="module">
36
+ import { getCandidates } from 'https://esm.sh/@windpress/oxide-parser';
37
+ const candidates = await getCandidates('<div class="flex p-4">');
38
+ </script>
52
39
  ```
53
40
 
54
- This will start a Vite development server. Open the URL shown in your terminal to test the parser in the browser.
55
-
56
- ## GitHub Actions Setup with OIDC Trusted Publishing
57
-
58
- ### Step 1: Configure Trusted Publisher on npm
41
+ ### Synchronous API
59
42
 
60
- 1. Go to your package page on [npmjs.com](https://www.npmjs.com)
61
- 2. Navigate to **Settings** **Trusted Publisher** section
62
- 3. Click **GitHub Actions** button under "Select your publisher"
63
- 4. Fill in the configuration:
64
- - **Organization or user**: Your GitHub username or organization (e.g., `wind-press`)
65
- - **Repository**: Your repository name (e.g., `oxide-parser`)
66
- - **Workflow filename**: `release.yaml`
67
- - **Environment name**: Leave empty (optional)
43
+ ```typescript
44
+ import { init, getCandidatesSync } from '@windpress/oxide-parser';
68
45
 
69
- 5. Click **Save**
70
-
71
- ![Example of npm Trusted Publisher configuration](https://docs.npmjs.com/packages-and-modules/securing-your-code/trusted-publisher-github-actions.png)
72
-
73
- ### Step 2: Repository Setup
74
-
75
- The GitHub workflows are already configured in `.github/workflows/`:
76
- - `ci.yaml` - Runs on every push/PR to main/develop branches
77
- - `release.yaml` - Publishes to npm when you push a version tag
78
-
79
- **No secrets needed!** The workflows use OpenID Connect (OIDC) for authentication.
80
-
81
- ### Step 3: Publishing a Release
46
+ await init();
47
+ const candidates = getCandidatesSync('<div class="flex">');
48
+ ```
82
49
 
83
- 1. Update version in `package.json` and `Cargo.toml`
84
- 2. Commit your changes
85
- 3. Create and push a git tag:
86
- ```bash
87
- git tag v1.0.0
88
- git push origin v1.0.0
89
- ```
50
+ ### Custom WASM URL
90
51
 
91
- 4. GitHub Actions will automatically:
92
- - Build the WASM module
93
- - Build the TypeScript code
94
- - Publish to npm using OIDC (no token needed!)
95
- - Create a GitHub release with auto-generated notes
96
- - Generate provenance attestations automatically
52
+ ```typescript
53
+ await init('https://cdn.example.com/oxide_parser.wasm');
54
+ ```
97
55
 
98
- ## Security Best Practices
56
+ ## API
99
57
 
100
- ### Restrict Token Access (Recommended)
58
+ ### `getCandidates(input)`
59
+ Extracts Tailwind candidates (auto-initializes WASM).
60
+ - **input**: `string | string[]`
61
+ - **returns**: `Promise<string[]>`
101
62
 
102
- After setting up trusted publishing:
63
+ ### `getCandidatesSync(input)`
64
+ Synchronous version (requires `init()` first).
65
+ - **input**: `string | string[]`
66
+ - **returns**: `string[]`
103
67
 
104
- 1. Go to your package **Settings** → **Publishing access**
105
- 2. Select **"Require two-factor authentication and disallow tokens"**
106
- 3. Click **Update Package Settings**
68
+ ### `init(wasmUrl?)`
69
+ Initializes WASM module.
70
+ - **wasmUrl**: `string` (optional)
71
+ - **returns**: `Promise<void>`
107
72
 
108
- This ensures your package can only be published via:
109
- - Trusted publishers (GitHub Actions with OIDC)
110
- - Manual publishes with 2FA
73
+ ### `isInitialized()`
74
+ Checks if WASM is ready.
75
+ - **returns**: `boolean`
111
76
 
112
- ### What About Private Dependencies?
77
+ ## Development
113
78
 
114
- If your project has private npm dependencies, you can still use a read-only token for `npm ci`:
79
+ ### Prerequisites
80
+ - Rust + wasm-pack: `cargo install wasm-pack`
81
+ - Node.js 18+
82
+ - pnpm: `npm install -g pnpm`
115
83
 
116
- ```yaml
117
- - name: Install dependencies
118
- run: pnpm install
119
- env:
120
- NODE_AUTH_TOKEN: ${{ secrets.NPM_READ_TOKEN }}
84
+ ### Setup
121
85
 
122
- - name: Publish (uses OIDC, no token needed)
123
- run: pnpm publish --access public
86
+ ```bash
87
+ pnpm install
88
+ pnpm run build
89
+ pnpm run dev
124
90
  ```
125
-
126
- ## Troubleshooting
127
-
128
- ### Workflow filename mismatch
129
- - Ensure the workflow filename on npmjs.com matches exactly: `release.yaml` (not `release.yml`)
130
- - Filenames are case-sensitive
131
-
132
- ### OIDC authentication fails
133
- - Verify `id-token: write` permission is set in the workflow
134
- - Confirm you're using GitHub-hosted runners (not self-hosted)
135
- - Check that npm CLI version 11.5.1+ is being used
136
-
137
- ### Build fails
138
- - Ensure Rust and wasm-pack are properly installed in CI
139
- - Check that all build steps complete successfully before publish
140
-
141
- ## Workflow Features
142
-
143
- ### CI Workflow (`ci.yaml`)
144
- - Runs on: Push to main/develop, Pull Requests
145
- - Tests: Node.js 18, 20, 22
146
- - Checks:
147
- - WASM build
148
- - TypeScript build
149
- - Rust formatting (`cargo fmt`)
150
- - Rust linting (`cargo clippy`)
151
-
152
- ### Release Workflow (`release.yaml`)
153
- - Runs on: Version tags (v*)
154
- - Actions:
155
- - Builds WASM and TypeScript
156
- - Publishes to npm with OIDC (automatic provenance)
157
- - Creates GitHub release
package/dist/index.d.mts CHANGED
@@ -1,72 +1,39 @@
1
1
  //#region src/index.d.ts
2
2
  /**
3
3
  * @windpress/oxide-parser
4
- *
5
- * Tailwind CSS Oxide parser WASM package for Vite and CDN usage.
6
- * This package provides a fast, WASM-based parser for extracting
7
- * Tailwind CSS candidates from your code.
4
+ * WASM-powered Tailwind CSS candidate parser.
8
5
  */
9
6
  /**
10
- * Initialize the WASM module
11
- *
12
- * This function must be called before using any parsing functions.
13
- * It loads and initializes the WASM module.
14
- *
15
- * @param wasmUrl - Optional custom URL to the WASM file
16
- * @returns Promise that resolves when initialization is complete
7
+ * Initialize the WASM module.
8
+ * Safe to call multiple times (no-op if already initialized).
17
9
  *
18
- * @example
19
- * ```typescript
20
- * import { init, findTailwindCandidates } from '@windpress/oxide-parser';
21
- *
22
- * await init();
23
- * const candidates = findTailwindCandidates('<div class="flex items-center">');
24
- * ```
10
+ * @param wasmUrl - Optional custom WASM file URL
25
11
  */
26
12
  declare function init(wasmUrl?: string): Promise<void>;
27
13
  /**
28
- * Find Tailwind CSS candidates in the provided input
29
- *
30
- * This function accepts either a single string or an array of strings.
31
- * Always returns unique candidates (duplicates are automatically removed).
32
- * - When given a string, returns unique candidates from that string
33
- * - When given an array, returns unique candidates across all inputs
14
+ * Extract Tailwind CSS candidates from input (auto-initializes WASM).
15
+ * Returns unique candidates only.
34
16
  *
35
- * @param input - Single string or array of strings to parse
17
+ * @param input - String or array of strings to parse
36
18
  * @returns Array of unique candidate strings
37
- *
38
- * @example Single string input
39
- * ```typescript
40
- * const candidates = findTailwindCandidates(`
41
- * <div class="flex flex items-center p-4 bg-blue-500">
42
- * <span class="text-white font-bold p-4">Hello</span>
43
- * </div>
44
- * `);
45
- * // Returns: ['flex', 'items-center', 'p-4', 'bg-blue-500', 'text-white', 'font-bold']
46
- * // Note: duplicates 'flex' and 'p-4' are automatically removed
47
- * ```
48
- *
49
- * @example Array input (batch processing with unique results)
50
- * ```typescript
51
- * const results = findTailwindCandidates([
52
- * '<div class="flex p-4">',
53
- * '<span class="flex text-white">',
54
- * '<button class="p-4 bg-blue-500">',
55
- * ]);
56
- * // Returns: ['flex', 'p-4', 'text-white', 'bg-blue-500']
57
- * // Note: duplicates 'flex' and 'p-4' across inputs are automatically removed
58
- * ```
59
19
  */
60
- declare function findTailwindCandidates(input: string | string[]): string[];
20
+ declare function getCandidates(input: string | string[]): Promise<string[]>;
61
21
  /**
62
- * Check if the WASM module is initialized
22
+ * Extract Tailwind CSS candidates synchronously.
23
+ * Requires init() to be called first.
63
24
  *
64
- * @returns true if initialized, false otherwise
25
+ * @param input - String or array of strings to parse
26
+ * @returns Array of unique candidate strings
27
+ * @throws Error if not initialized
28
+ */
29
+ declare function getCandidatesSync(input: string | string[]): string[];
30
+ /**
31
+ * Check if WASM module is initialized.
65
32
  */
66
33
  declare function isInitialized(): boolean;
67
34
  type TailwindCandidate = string;
68
35
  type ParseResult = TailwindCandidate[];
69
36
  type BatchParseResult = ParseResult[];
70
37
  //#endregion
71
- export { BatchParseResult, ParseResult, TailwindCandidate, init as default, init, findTailwindCandidates, isInitialized };
38
+ export { BatchParseResult, ParseResult, TailwindCandidate, init as default, init, getCandidates, getCandidatesSync, isInitialized };
72
39
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;AA6BA;AA2DA;AAeA;AAKA;AACA;AACA;;;;;;;;;;;;;;;;;;iBAjFsB,IAAA,oBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2D9B,sBAAA;;;;;;iBAeA,aAAA,CAAA;KAKJ,iBAAA;KACA,WAAA,GAAc;KACd,gBAAA,GAAmB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;AAgBA;AA2CA;AAiBA;AAaA;AAKA;AACA;AACA;;;iBAhFsB,IAAA,oBAAwB;;;;;;;;iBA2CxB,aAAA,4BAAyC;;;;;;;;;iBAiB/C,iBAAA;;;;iBAaA,aAAA,CAAA;KAKJ,iBAAA;KACA,WAAA,GAAc;KACd,gBAAA,GAAmB"}
package/dist/index.mjs CHANGED
@@ -1,88 +1,64 @@
1
1
  //#region src/index.ts
2
2
  /**
3
3
  * @windpress/oxide-parser
4
- *
5
- * Tailwind CSS Oxide parser WASM package for Vite and CDN usage.
6
- * This package provides a fast, WASM-based parser for extracting
7
- * Tailwind CSS candidates from your code.
4
+ * WASM-powered Tailwind CSS candidate parser.
8
5
  */
9
6
  let wasmModule = null;
10
7
  let wasmInitialized = false;
8
+ let initPromise = null;
11
9
  /**
12
- * Initialize the WASM module
13
- *
14
- * This function must be called before using any parsing functions.
15
- * It loads and initializes the WASM module.
16
- *
17
- * @param wasmUrl - Optional custom URL to the WASM file
18
- * @returns Promise that resolves when initialization is complete
10
+ * Initialize the WASM module.
11
+ * Safe to call multiple times (no-op if already initialized).
19
12
  *
20
- * @example
21
- * ```typescript
22
- * import { init, findTailwindCandidates } from '@windpress/oxide-parser';
23
- *
24
- * await init();
25
- * const candidates = findTailwindCandidates('<div class="flex items-center">');
26
- * ```
13
+ * @param wasmUrl - Optional custom WASM file URL
27
14
  */
28
15
  async function init(wasmUrl) {
29
16
  if (wasmInitialized) return;
30
- try {
31
- const module = await import("./oxide_parser-C3svwMjw.mjs");
32
- if (wasmUrl) await module.default(wasmUrl);
33
- else await module.default();
34
- wasmModule = module;
35
- wasmInitialized = true;
36
- } catch (error) {
37
- throw new Error(`Failed to initialize WASM module: ${error instanceof Error ? error.message : "Unknown error"}`);
38
- }
17
+ if (initPromise) return initPromise;
18
+ initPromise = (async () => {
19
+ try {
20
+ const module = await import("./oxide_parser-Cpgo0kV5.mjs");
21
+ if (wasmUrl) await module.default(wasmUrl);
22
+ else await module.default();
23
+ wasmModule = module;
24
+ wasmInitialized = true;
25
+ } catch (error) {
26
+ initPromise = null;
27
+ throw new Error(`Failed to initialize WASM module: ${error instanceof Error ? error.message : "Unknown error"}`);
28
+ }
29
+ })();
30
+ return initPromise;
39
31
  }
40
32
  /**
41
- * Find Tailwind CSS candidates in the provided input
42
- *
43
- * This function accepts either a single string or an array of strings.
44
- * Always returns unique candidates (duplicates are automatically removed).
45
- * - When given a string, returns unique candidates from that string
46
- * - When given an array, returns unique candidates across all inputs
33
+ * Extract Tailwind CSS candidates from input (auto-initializes WASM).
34
+ * Returns unique candidates only.
47
35
  *
48
- * @param input - Single string or array of strings to parse
36
+ * @param input - String or array of strings to parse
49
37
  * @returns Array of unique candidate strings
50
- *
51
- * @example Single string input
52
- * ```typescript
53
- * const candidates = findTailwindCandidates(`
54
- * <div class="flex flex items-center p-4 bg-blue-500">
55
- * <span class="text-white font-bold p-4">Hello</span>
56
- * </div>
57
- * `);
58
- * // Returns: ['flex', 'items-center', 'p-4', 'bg-blue-500', 'text-white', 'font-bold']
59
- * // Note: duplicates 'flex' and 'p-4' are automatically removed
60
- * ```
61
- *
62
- * @example Array input (batch processing with unique results)
63
- * ```typescript
64
- * const results = findTailwindCandidates([
65
- * '<div class="flex p-4">',
66
- * '<span class="flex text-white">',
67
- * '<button class="p-4 bg-blue-500">',
68
- * ]);
69
- * // Returns: ['flex', 'p-4', 'text-white', 'bg-blue-500']
70
- * // Note: duplicates 'flex' and 'p-4' across inputs are automatically removed
71
- * ```
72
38
  */
73
- function findTailwindCandidates(input) {
74
- if (!wasmInitialized || !wasmModule) throw new Error("WASM module not initialized. Call init() before using findTailwindCandidates()");
75
- return wasmModule.findTailwindCandidates(input);
39
+ async function getCandidates(input) {
40
+ if (!wasmInitialized) await init();
41
+ return wasmModule.getCandidates(input);
76
42
  }
77
43
  /**
78
- * Check if the WASM module is initialized
44
+ * Extract Tailwind CSS candidates synchronously.
45
+ * Requires init() to be called first.
79
46
  *
80
- * @returns true if initialized, false otherwise
47
+ * @param input - String or array of strings to parse
48
+ * @returns Array of unique candidate strings
49
+ * @throws Error if not initialized
50
+ */
51
+ function getCandidatesSync(input) {
52
+ if (!wasmInitialized || !wasmModule) throw new Error("WASM module not initialized. Call init() and await it before using getCandidatesSync(), or use the async getCandidates() instead.");
53
+ return wasmModule.getCandidates(input);
54
+ }
55
+ /**
56
+ * Check if WASM module is initialized.
81
57
  */
82
58
  function isInitialized() {
83
59
  return wasmInitialized;
84
60
  }
85
61
 
86
62
  //#endregion
87
- export { init as default, init, findTailwindCandidates, isInitialized };
63
+ export { init as default, init, getCandidates, getCandidatesSync, isInitialized };
88
64
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["wasmModule: any"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @windpress/oxide-parser\n * \n * Tailwind CSS Oxide parser WASM package for Vite and CDN usage.\n * This package provides a fast, WASM-based parser for extracting\n * Tailwind CSS candidates from your code.\n */\n\n// Import the WASM module - this will be handled by the bundler or CDN\nlet wasmModule: any = null;\nlet wasmInitialized = false;\n\n/**\n * Initialize the WASM module\n * \n * This function must be called before using any parsing functions.\n * It loads and initializes the WASM module.\n * \n * @param wasmUrl - Optional custom URL to the WASM file\n * @returns Promise that resolves when initialization is complete\n * \n * @example\n * ```typescript\n * import { init, findTailwindCandidates } from '@windpress/oxide-parser';\n * \n * await init();\n * const candidates = findTailwindCandidates('<div class=\"flex items-center\">');\n * ```\n */\nexport async function init(wasmUrl?: string): Promise<void> {\n if (wasmInitialized) {\n return;\n }\n\n try {\n // Try to import from the pkg directory (for local builds)\n const module = await import('../pkg/oxide_parser.js');\n \n if (wasmUrl) {\n // If custom WASM URL provided, use it\n await module.default(wasmUrl);\n } else {\n // Auto-detect WASM location\n await module.default();\n }\n \n wasmModule = module;\n wasmInitialized = true;\n } catch (error) {\n throw new Error(\n `Failed to initialize WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\n/**\n * Find Tailwind CSS candidates in the provided input\n * \n * This function accepts either a single string or an array of strings.\n * Always returns unique candidates (duplicates are automatically removed).\n * - When given a string, returns unique candidates from that string\n * - When given an array, returns unique candidates across all inputs\n * \n * @param input - Single string or array of strings to parse\n * @returns Array of unique candidate strings\n * \n * @example Single string input\n * ```typescript\n * const candidates = findTailwindCandidates(`\n * <div class=\"flex flex items-center p-4 bg-blue-500\">\n * <span class=\"text-white font-bold p-4\">Hello</span>\n * </div>\n * `);\n * // Returns: ['flex', 'items-center', 'p-4', 'bg-blue-500', 'text-white', 'font-bold']\n * // Note: duplicates 'flex' and 'p-4' are automatically removed\n * ```\n * \n * @example Array input (batch processing with unique results)\n * ```typescript\n * const results = findTailwindCandidates([\n * '<div class=\"flex p-4\">',\n * '<span class=\"flex text-white\">',\n * '<button class=\"p-4 bg-blue-500\">',\n * ]);\n * // Returns: ['flex', 'p-4', 'text-white', 'bg-blue-500']\n * // Note: duplicates 'flex' and 'p-4' across inputs are automatically removed\n * ```\n */\nexport function findTailwindCandidates(input: string | string[]): string[] {\n if (!wasmInitialized || !wasmModule) {\n throw new Error(\n 'WASM module not initialized. Call init() before using findTailwindCandidates()'\n );\n }\n\n return wasmModule.findTailwindCandidates(input);\n}\n\n/**\n * Check if the WASM module is initialized\n * \n * @returns true if initialized, false otherwise\n */\nexport function isInitialized(): boolean {\n return wasmInitialized;\n}\n\n// Export types\nexport type TailwindCandidate = string;\nexport type ParseResult = TailwindCandidate[];\nexport type BatchParseResult = ParseResult[];\n\n// Re-export for convenience\nexport { init as default };\n"],"mappings":";;;;;;;;AASA,IAAIA,aAAkB;AACtB,IAAI,kBAAkB;;;;;;;;;;;;;;;;;;AAmBtB,eAAsB,KAAK,SAAiC;AAC1D,KAAI,gBACF;AAGF,KAAI;EAEF,MAAM,SAAS,MAAM,OAAO;AAE5B,MAAI,QAEF,OAAM,OAAO,QAAQ,QAAQ;MAG7B,OAAM,OAAO,SAAS;AAGxB,eAAa;AACb,oBAAkB;UACX,OAAO;AACd,QAAM,IAAI,MACR,qCAAqC,iBAAiB,QAAQ,MAAM,UAAU,kBAC/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCL,SAAgB,uBAAuB,OAAoC;AACzE,KAAI,CAAC,mBAAmB,CAAC,WACvB,OAAM,IAAI,MACR,iFACD;AAGH,QAAO,WAAW,uBAAuB,MAAM;;;;;;;AAQjD,SAAgB,gBAAyB;AACvC,QAAO"}
1
+ {"version":3,"file":"index.mjs","names":["wasmModule: any","initPromise: Promise<void> | null"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @windpress/oxide-parser\n * WASM-powered Tailwind CSS candidate parser.\n */\n\n// Import the WASM module - this will be handled by the bundler or CDN\nlet wasmModule: any = null;\nlet wasmInitialized = false;\nlet initPromise: Promise<void> | null = null;\n\n/**\n * Initialize the WASM module.\n * Safe to call multiple times (no-op if already initialized).\n * \n * @param wasmUrl - Optional custom WASM file URL\n */\nexport async function init(wasmUrl?: string): Promise<void> {\n if (wasmInitialized) {\n return;\n }\n\n // If initialization is already in progress, return the existing promise\n if (initPromise) {\n return initPromise;\n }\n\n initPromise = (async () => {\n try {\n // Try to import from the pkg directory (for local builds)\n const module = await import('../pkg/oxide_parser.js');\n \n if (wasmUrl) {\n // If custom WASM URL provided, use it\n await module.default(wasmUrl);\n } else {\n // Auto-detect WASM location\n await module.default();\n }\n \n wasmModule = module;\n wasmInitialized = true;\n } catch (error) {\n initPromise = null; // Reset so retry is possible\n throw new Error(\n `Failed to initialize WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n })();\n\n return initPromise;\n}\n\n/**\n * Extract Tailwind CSS candidates from input (auto-initializes WASM).\n * Returns unique candidates only.\n * \n * @param input - String or array of strings to parse\n * @returns Array of unique candidate strings\n */\nexport async function getCandidates(input: string | string[]): Promise<string[]> {\n // Auto-initialize if not already initialized\n if (!wasmInitialized) {\n await init();\n }\n\n return wasmModule.getCandidates(input);\n}\n\n/**\n * Extract Tailwind CSS candidates synchronously.\n * Requires init() to be called first.\n * \n * @param input - String or array of strings to parse\n * @returns Array of unique candidate strings\n * @throws Error if not initialized\n */\nexport function getCandidatesSync(input: string | string[]): string[] {\n if (!wasmInitialized || !wasmModule) {\n throw new Error(\n 'WASM module not initialized. Call init() and await it before using getCandidatesSync(), or use the async getCandidates() instead.'\n );\n }\n\n return wasmModule.getCandidates(input);\n}\n\n/**\n * Check if WASM module is initialized.\n */\nexport function isInitialized(): boolean {\n return wasmInitialized;\n}\n\n// Export types\nexport type TailwindCandidate = string;\nexport type ParseResult = TailwindCandidate[];\nexport type BatchParseResult = ParseResult[];\n\n// Re-export for convenience\nexport { init as default };\n"],"mappings":";;;;;AAMA,IAAIA,aAAkB;AACtB,IAAI,kBAAkB;AACtB,IAAIC,cAAoC;;;;;;;AAQxC,eAAsB,KAAK,SAAiC;AAC1D,KAAI,gBACF;AAIF,KAAI,YACF,QAAO;AAGT,gBAAe,YAAY;AACzB,MAAI;GAEF,MAAM,SAAS,MAAM,OAAO;AAE5B,OAAI,QAEF,OAAM,OAAO,QAAQ,QAAQ;OAG7B,OAAM,OAAO,SAAS;AAGxB,gBAAa;AACb,qBAAkB;WACX,OAAO;AACd,iBAAc;AACd,SAAM,IAAI,MACR,qCAAqC,iBAAiB,QAAQ,MAAM,UAAU,kBAC/E;;KAED;AAEJ,QAAO;;;;;;;;;AAUT,eAAsB,cAAc,OAA6C;AAE/E,KAAI,CAAC,gBACH,OAAM,MAAM;AAGd,QAAO,WAAW,cAAc,MAAM;;;;;;;;;;AAWxC,SAAgB,kBAAkB,OAAoC;AACpE,KAAI,CAAC,mBAAmB,CAAC,WACvB,OAAM,IAAI,MACR,oIACD;AAGH,QAAO,WAAW,cAAc,MAAM;;;;;AAMxC,SAAgB,gBAAyB;AACvC,QAAO"}
@@ -98,45 +98,13 @@ function takeObject(idx) {
98
98
  return ret;
99
99
  }
100
100
  /**
101
- * WASM-compatible function for JavaScript/TypeScript
102
- *
103
- * Finds Tailwind CSS candidates in the provided input.
104
- * Accepts either a single string or an array of strings.
105
- * Always returns unique candidates (duplicates are automatically removed).
106
- *
107
- * # Performance
108
- * - Uses direct HashSet insertion to avoid intermediate allocations
109
- * - Pre-allocates JS array for better performance
110
- * - Single-pass extraction for array inputs
111
- *
112
- * # Arguments
113
- * * `input` - Either a string or an array of strings
114
- *
115
- * # Returns
116
- * JavaScript Array containing unique candidate strings, or empty array if input is invalid
117
- *
118
- * # Example (JavaScript)
119
- * ```javascript
120
- * import init, { findTailwindCandidates } from '@windpress/oxide-parser';
121
- *
122
- * await init();
123
- *
124
- * // Single string - returns unique candidates
125
- * const candidates = findTailwindCandidates('<div class="flex flex items-center">');
126
- * console.log(candidates); // ['flex', 'items-center'] (duplicates removed)
127
- *
128
- * // Array of strings - returns unique candidates from all inputs
129
- * const batch = findTailwindCandidates([
130
- * '<div class="flex p-4">',
131
- * '<span class="flex text-white">'
132
- * ]);
133
- * console.log(batch); // ['flex', 'p-4', 'text-white'] (unique only)
134
- * ```
101
+ * Find Tailwind CSS candidates in the input.
102
+ * Accepts a string or array of strings, returns unique candidates.
135
103
  * @param {any} input
136
104
  * @returns {Array<any>}
137
105
  */
138
- function findTailwindCandidates(input) {
139
- return takeObject(wasm.findTailwindCandidates(addHeapObject(input)));
106
+ function getCandidates(input) {
107
+ return takeObject(wasm.getCandidates(addHeapObject(input)));
140
108
  }
141
109
  const EXPECTED_RESPONSE_TYPES = new Set([
142
110
  "basic",
@@ -234,5 +202,5 @@ async function __wbg_init(module_or_path) {
234
202
  var oxide_parser_default = __wbg_init;
235
203
 
236
204
  //#endregion
237
- export { oxide_parser_default as default, findTailwindCandidates, initSync };
238
- //# sourceMappingURL=oxide_parser-C3svwMjw.mjs.map
205
+ export { oxide_parser_default as default, getCandidates, initSync };
206
+ //# sourceMappingURL=oxide_parser-Cpgo0kV5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oxide_parser-Cpgo0kV5.mjs","names":["ptr"],"sources":["../pkg/oxide_parser.js"],"sourcesContent":["let wasm;\n\nlet heap = new Array(128).fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nfunction getObject(idx) { return heap[idx]; }\n\nlet WASM_VECTOR_LEN = 0;\n\nlet cachedUint8ArrayMemory0 = null;\n\nfunction getUint8ArrayMemory0() {\n if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {\n cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);\n }\n return cachedUint8ArrayMemory0;\n}\n\nconst cachedTextEncoder = new TextEncoder();\n\nif (!('encodeInto' in cachedTextEncoder)) {\n cachedTextEncoder.encodeInto = function (arg, view) {\n const buf = cachedTextEncoder.encode(arg);\n view.set(buf);\n return {\n read: arg.length,\n written: buf.length\n };\n }\n}\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n\n if (realloc === undefined) {\n const buf = cachedTextEncoder.encode(arg);\n const ptr = malloc(buf.length, 1) >>> 0;\n getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);\n WASM_VECTOR_LEN = buf.length;\n return ptr;\n }\n\n let len = arg.length;\n let ptr = malloc(len, 1) >>> 0;\n\n const mem = getUint8ArrayMemory0();\n\n let offset = 0;\n\n for (; offset < len; offset++) {\n const code = arg.charCodeAt(offset);\n if (code > 0x7F) break;\n mem[ptr + offset] = code;\n }\n\n if (offset !== len) {\n if (offset !== 0) {\n arg = arg.slice(offset);\n }\n ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;\n const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);\n const ret = cachedTextEncoder.encodeInto(arg, view);\n\n offset += ret.written;\n ptr = realloc(ptr, len, offset, 1) >>> 0;\n }\n\n WASM_VECTOR_LEN = offset;\n return ptr;\n}\n\nfunction isLikeNone(x) {\n return x === undefined || x === null;\n}\n\nlet cachedDataViewMemory0 = null;\n\nfunction getDataViewMemory0() {\n if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {\n cachedDataViewMemory0 = new DataView(wasm.memory.buffer);\n }\n return cachedDataViewMemory0;\n}\n\nlet cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n\ncachedTextDecoder.decode();\n\nconst MAX_SAFARI_DECODE_BYTES = 2146435072;\nlet numBytesDecoded = 0;\nfunction decodeText(ptr, len) {\n numBytesDecoded += len;\n if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {\n cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n cachedTextDecoder.decode();\n numBytesDecoded = len;\n }\n return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));\n}\n\nfunction getStringFromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return decodeText(ptr, len);\n}\n\nlet heap_next = heap.length;\n\nfunction addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n}\n\nfunction dropObject(idx) {\n if (idx < 132) return;\n heap[idx] = heap_next;\n heap_next = idx;\n}\n\nfunction takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n}\n/**\n * Find Tailwind CSS candidates in the input.\n * Accepts a string or array of strings, returns unique candidates.\n * @param {any} input\n * @returns {Array<any>}\n */\nexport function getCandidates(input) {\n const ret = wasm.getCandidates(addHeapObject(input));\n return takeObject(ret);\n}\n\nconst EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']);\n\nasync function __wbg_load(module, imports) {\n if (typeof Response === 'function' && module instanceof Response) {\n if (typeof WebAssembly.instantiateStreaming === 'function') {\n try {\n return await WebAssembly.instantiateStreaming(module, imports);\n\n } catch (e) {\n const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type);\n\n if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {\n console.warn(\"`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n\", e);\n\n } else {\n throw e;\n }\n }\n }\n\n const bytes = await module.arrayBuffer();\n return await WebAssembly.instantiate(bytes, imports);\n\n } else {\n const instance = await WebAssembly.instantiate(module, imports);\n\n if (instance instanceof WebAssembly.Instance) {\n return { instance, module };\n\n } else {\n return instance;\n }\n }\n}\n\nfunction __wbg_get_imports() {\n const imports = {};\n imports.wbg = {};\n imports.wbg.__wbg___wbindgen_string_get_e4f06c90489ad01b = function(arg0, arg1) {\n const obj = getObject(arg1);\n const ret = typeof(obj) === 'string' ? obj : undefined;\n var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);\n var len1 = WASM_VECTOR_LEN;\n getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);\n getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);\n };\n imports.wbg.__wbg___wbindgen_throw_b855445ff6a94295 = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n };\n imports.wbg.__wbg_from_a4ad7cbddd0d7135 = function(arg0) {\n const ret = Array.from(getObject(arg0));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_get_7bed016f185add81 = function(arg0, arg1) {\n const ret = getObject(arg0)[arg1 >>> 0];\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_isArray_96e0af9891d0945d = function(arg0) {\n const ret = Array.isArray(getObject(arg0));\n return ret;\n };\n imports.wbg.__wbg_length_cdd215e10d9dd507 = function(arg0) {\n const ret = getObject(arg0).length;\n return ret;\n };\n imports.wbg.__wbg_new_e17d9f43105b08be = function() {\n const ret = new Array();\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_new_with_length_31d2669cb75c5215 = function(arg0) {\n const ret = new Array(arg0 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_set_c213c871859d6500 = function(arg0, arg1, arg2) {\n getObject(arg0)[arg1 >>> 0] = takeObject(arg2);\n };\n imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {\n // Cast intrinsic for `Ref(String) -> Externref`.\n const ret = getStringFromWasm0(arg0, arg1);\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_object_drop_ref = function(arg0) {\n takeObject(arg0);\n };\n\n return imports;\n}\n\nfunction __wbg_finalize_init(instance, module) {\n wasm = instance.exports;\n __wbg_init.__wbindgen_wasm_module = module;\n cachedDataViewMemory0 = null;\n cachedUint8ArrayMemory0 = null;\n\n\n\n return wasm;\n}\n\nfunction initSync(module) {\n if (wasm !== undefined) return wasm;\n\n\n if (typeof module !== 'undefined') {\n if (Object.getPrototypeOf(module) === Object.prototype) {\n ({module} = module)\n } else {\n console.warn('using deprecated parameters for `initSync()`; pass a single object instead')\n }\n }\n\n const imports = __wbg_get_imports();\n\n if (!(module instanceof WebAssembly.Module)) {\n module = new WebAssembly.Module(module);\n }\n\n const instance = new WebAssembly.Instance(module, imports);\n\n return __wbg_finalize_init(instance, module);\n}\n\nasync function __wbg_init(module_or_path) {\n if (wasm !== undefined) return wasm;\n\n\n if (typeof module_or_path !== 'undefined') {\n if (Object.getPrototypeOf(module_or_path) === Object.prototype) {\n ({module_or_path} = module_or_path)\n } else {\n console.warn('using deprecated parameters for the initialization function; pass a single object instead')\n }\n }\n\n if (typeof module_or_path === 'undefined') {\n module_or_path = new URL('oxide_parser_bg.wasm', import.meta.url);\n }\n const imports = __wbg_get_imports();\n\n if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {\n module_or_path = fetch(module_or_path);\n }\n\n const { instance, module } = await __wbg_load(await module_or_path, imports);\n\n return __wbg_finalize_init(instance, module);\n}\n\nexport { initSync };\nexport default __wbg_init;\n"],"mappings":"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"}
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windpress/oxide-parser",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Tailwind CSS Oxide parser WASM package for Vite and CDN usage",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -16,14 +16,6 @@
16
16
  "README.md",
17
17
  "LICENSE"
18
18
  ],
19
- "scripts": {
20
- "build:wasm": "wasm-pack build --target web --out-dir pkg --release",
21
- "build:ts": "tsdown",
22
- "build": "npm run build:wasm && npm run build:ts && npm run copy-wasm",
23
- "copy-wasm": "node scripts/copy-wasm.js",
24
- "dev": "vite",
25
- "preview": "vite preview"
26
- },
27
19
  "keywords": [
28
20
  "tailwindcss",
29
21
  "oxide",
@@ -46,5 +38,12 @@
46
38
  "type": "git",
47
39
  "url": "https://github.com/wind-press/oxide-parser"
48
40
  },
49
- "packageManager": "pnpm@10.20.0+sha512.cf9998222162dd85864d0a8102e7892e7ba4ceadebbf5a31f9c2fce48dfce317a9c53b9f6464d1ef9042cba2e02ae02a9f7c143a2b438cd93c91840f0192b9dd"
50
- }
41
+ "scripts": {
42
+ "build:wasm": "wasm-pack build --target web --out-dir pkg --release",
43
+ "build:ts": "tsdown",
44
+ "build": "npm run build:wasm && npm run build:ts && npm run copy-wasm",
45
+ "copy-wasm": "node scripts/copy-wasm.js",
46
+ "dev": "vite",
47
+ "preview": "vite preview"
48
+ }
49
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"oxide_parser-C3svwMjw.mjs","names":["ptr"],"sources":["../pkg/oxide_parser.js"],"sourcesContent":["let wasm;\n\nlet heap = new Array(128).fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nfunction getObject(idx) { return heap[idx]; }\n\nlet WASM_VECTOR_LEN = 0;\n\nlet cachedUint8ArrayMemory0 = null;\n\nfunction getUint8ArrayMemory0() {\n if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {\n cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);\n }\n return cachedUint8ArrayMemory0;\n}\n\nconst cachedTextEncoder = new TextEncoder();\n\nif (!('encodeInto' in cachedTextEncoder)) {\n cachedTextEncoder.encodeInto = function (arg, view) {\n const buf = cachedTextEncoder.encode(arg);\n view.set(buf);\n return {\n read: arg.length,\n written: buf.length\n };\n }\n}\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n\n if (realloc === undefined) {\n const buf = cachedTextEncoder.encode(arg);\n const ptr = malloc(buf.length, 1) >>> 0;\n getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);\n WASM_VECTOR_LEN = buf.length;\n return ptr;\n }\n\n let len = arg.length;\n let ptr = malloc(len, 1) >>> 0;\n\n const mem = getUint8ArrayMemory0();\n\n let offset = 0;\n\n for (; offset < len; offset++) {\n const code = arg.charCodeAt(offset);\n if (code > 0x7F) break;\n mem[ptr + offset] = code;\n }\n\n if (offset !== len) {\n if (offset !== 0) {\n arg = arg.slice(offset);\n }\n ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;\n const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);\n const ret = cachedTextEncoder.encodeInto(arg, view);\n\n offset += ret.written;\n ptr = realloc(ptr, len, offset, 1) >>> 0;\n }\n\n WASM_VECTOR_LEN = offset;\n return ptr;\n}\n\nfunction isLikeNone(x) {\n return x === undefined || x === null;\n}\n\nlet cachedDataViewMemory0 = null;\n\nfunction getDataViewMemory0() {\n if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {\n cachedDataViewMemory0 = new DataView(wasm.memory.buffer);\n }\n return cachedDataViewMemory0;\n}\n\nlet cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n\ncachedTextDecoder.decode();\n\nconst MAX_SAFARI_DECODE_BYTES = 2146435072;\nlet numBytesDecoded = 0;\nfunction decodeText(ptr, len) {\n numBytesDecoded += len;\n if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {\n cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n cachedTextDecoder.decode();\n numBytesDecoded = len;\n }\n return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));\n}\n\nfunction getStringFromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return decodeText(ptr, len);\n}\n\nlet heap_next = heap.length;\n\nfunction addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n}\n\nfunction dropObject(idx) {\n if (idx < 132) return;\n heap[idx] = heap_next;\n heap_next = idx;\n}\n\nfunction takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n}\n/**\n * WASM-compatible function for JavaScript/TypeScript\n *\n * Finds Tailwind CSS candidates in the provided input.\n * Accepts either a single string or an array of strings.\n * Always returns unique candidates (duplicates are automatically removed).\n *\n * # Performance\n * - Uses direct HashSet insertion to avoid intermediate allocations\n * - Pre-allocates JS array for better performance\n * - Single-pass extraction for array inputs\n *\n * # Arguments\n * * `input` - Either a string or an array of strings\n *\n * # Returns\n * JavaScript Array containing unique candidate strings, or empty array if input is invalid\n *\n * # Example (JavaScript)\n * ```javascript\n * import init, { findTailwindCandidates } from '@windpress/oxide-parser';\n *\n * await init();\n *\n * // Single string - returns unique candidates\n * const candidates = findTailwindCandidates('<div class=\"flex flex items-center\">');\n * console.log(candidates); // ['flex', 'items-center'] (duplicates removed)\n *\n * // Array of strings - returns unique candidates from all inputs\n * const batch = findTailwindCandidates([\n * '<div class=\"flex p-4\">',\n * '<span class=\"flex text-white\">'\n * ]);\n * console.log(batch); // ['flex', 'p-4', 'text-white'] (unique only)\n * ```\n * @param {any} input\n * @returns {Array<any>}\n */\nexport function findTailwindCandidates(input) {\n const ret = wasm.findTailwindCandidates(addHeapObject(input));\n return takeObject(ret);\n}\n\nconst EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']);\n\nasync function __wbg_load(module, imports) {\n if (typeof Response === 'function' && module instanceof Response) {\n if (typeof WebAssembly.instantiateStreaming === 'function') {\n try {\n return await WebAssembly.instantiateStreaming(module, imports);\n\n } catch (e) {\n const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type);\n\n if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {\n console.warn(\"`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n\", e);\n\n } else {\n throw e;\n }\n }\n }\n\n const bytes = await module.arrayBuffer();\n return await WebAssembly.instantiate(bytes, imports);\n\n } else {\n const instance = await WebAssembly.instantiate(module, imports);\n\n if (instance instanceof WebAssembly.Instance) {\n return { instance, module };\n\n } else {\n return instance;\n }\n }\n}\n\nfunction __wbg_get_imports() {\n const imports = {};\n imports.wbg = {};\n imports.wbg.__wbg___wbindgen_string_get_e4f06c90489ad01b = function(arg0, arg1) {\n const obj = getObject(arg1);\n const ret = typeof(obj) === 'string' ? obj : undefined;\n var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);\n var len1 = WASM_VECTOR_LEN;\n getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);\n getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);\n };\n imports.wbg.__wbg___wbindgen_throw_b855445ff6a94295 = function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n };\n imports.wbg.__wbg_from_a4ad7cbddd0d7135 = function(arg0) {\n const ret = Array.from(getObject(arg0));\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_get_7bed016f185add81 = function(arg0, arg1) {\n const ret = getObject(arg0)[arg1 >>> 0];\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_isArray_96e0af9891d0945d = function(arg0) {\n const ret = Array.isArray(getObject(arg0));\n return ret;\n };\n imports.wbg.__wbg_length_cdd215e10d9dd507 = function(arg0) {\n const ret = getObject(arg0).length;\n return ret;\n };\n imports.wbg.__wbg_new_e17d9f43105b08be = function() {\n const ret = new Array();\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_new_with_length_31d2669cb75c5215 = function(arg0) {\n const ret = new Array(arg0 >>> 0);\n return addHeapObject(ret);\n };\n imports.wbg.__wbg_set_c213c871859d6500 = function(arg0, arg1, arg2) {\n getObject(arg0)[arg1 >>> 0] = takeObject(arg2);\n };\n imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {\n // Cast intrinsic for `Ref(String) -> Externref`.\n const ret = getStringFromWasm0(arg0, arg1);\n return addHeapObject(ret);\n };\n imports.wbg.__wbindgen_object_drop_ref = function(arg0) {\n takeObject(arg0);\n };\n\n return imports;\n}\n\nfunction __wbg_finalize_init(instance, module) {\n wasm = instance.exports;\n __wbg_init.__wbindgen_wasm_module = module;\n cachedDataViewMemory0 = null;\n cachedUint8ArrayMemory0 = null;\n\n\n\n return wasm;\n}\n\nfunction initSync(module) {\n if (wasm !== undefined) return wasm;\n\n\n if (typeof module !== 'undefined') {\n if (Object.getPrototypeOf(module) === Object.prototype) {\n ({module} = module)\n } else {\n console.warn('using deprecated parameters for `initSync()`; pass a single object instead')\n }\n }\n\n const imports = __wbg_get_imports();\n\n if (!(module instanceof WebAssembly.Module)) {\n module = new WebAssembly.Module(module);\n }\n\n const instance = new WebAssembly.Instance(module, imports);\n\n return __wbg_finalize_init(instance, module);\n}\n\nasync function __wbg_init(module_or_path) {\n if (wasm !== undefined) return wasm;\n\n\n if (typeof module_or_path !== 'undefined') {\n if (Object.getPrototypeOf(module_or_path) === Object.prototype) {\n ({module_or_path} = module_or_path)\n } else {\n console.warn('using deprecated parameters for the initialization function; pass a single object instead')\n }\n }\n\n if (typeof module_or_path === 'undefined') {\n module_or_path = new URL('oxide_parser_bg.wasm', import.meta.url);\n }\n const imports = __wbg_get_imports();\n\n if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {\n module_or_path = fetch(module_or_path);\n }\n\n const { instance, module } = await __wbg_load(await module_or_path, imports);\n\n return __wbg_finalize_init(instance, module);\n}\n\nexport { initSync };\nexport default __wbg_init;\n"],"mappings":"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"}