├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── CHANGELOG.md ├── LICENCE ├── README.md ├── build.js ├── dist └── index.d.ts ├── example-js ├── .gitignore ├── buildscript.js ├── entry.js ├── index.html ├── index.svelte ├── package.json ├── second.svelte └── test.svelte.js ├── example-ts ├── .gitignore ├── buildscript.js ├── entry.ts ├── fun.ts ├── index.html ├── index.svelte ├── package.json ├── second.svelte ├── test.svelte.ts └── tsconfig.json ├── index.ts ├── package-lock.json ├── package.json ├── test ├── cacheTest.mjs ├── commonOptions.js ├── errors.mjs ├── fixtures │ ├── errors │ │ ├── entry.js │ │ ├── error.svelte │ │ └── svelte.config.js │ ├── include │ │ ├── entry.js │ │ └── include.notSvelte │ ├── non-ascii │ │ ├── entry.js │ │ └── non-ascii.svelte │ ├── preprocessing-sourcemaps │ │ ├── pp-sourcemaps.js │ │ ├── pp-sourcemaps.svelte │ │ ├── sourcemapImport.scss │ │ └── svelte.config.js │ ├── resolveDirectory │ │ ├── entry.js │ │ ├── fakeImage.png │ │ └── resDir.svelte │ ├── svelte5 │ │ ├── entry.js │ │ ├── javascript-modules │ │ │ ├── entry.js │ │ │ ├── module.svelte.js │ │ │ └── svelte5.svelte │ │ ├── svelte5.svelte │ │ └── typescript-modules │ │ │ ├── entry.ts │ │ │ ├── module.svelte.ts │ │ │ └── svelte5.svelte │ ├── ts-module-minification │ │ ├── entry.ts │ │ ├── module.svelte.ts │ │ └── svelte5.svelte │ ├── warnings │ │ ├── entry.js │ │ └── missing-declaration.svelte │ └── watch-preprocessing │ │ ├── entry.js │ │ ├── external-styles.svelte │ │ └── external.scss ├── includeOption.mjs ├── non-ascii.mjs ├── resolveDirectoryTest.mjs ├── simpleTest.mjs ├── sourcemapsTest.mjs ├── svelte5.mjs ├── versionTests │ ├── .gitignore │ ├── entry.js │ ├── entry5.js │ ├── index.svelte │ ├── test.js │ └── versionTests.sh ├── warnings.mjs └── watchPreprocessingTest.mjs ├── tsconfig.json └── version.txt /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report something that isn't working correctly 4 | title: "" 5 | labels: bug 6 | assignees: "" 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Have a file with `foo` content 16 | 2. Use a build script that looks like `bar` 17 | 3. See error `invalid foobar` 18 | 19 | If you are able to point to a public repostory that reproduces the issue, please list that as well. 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **Environment (please complete the following information):** 28 | 29 | - esbuild-svelte version: 30 | - esbuild version: 31 | - Svelte version: 32 | - Svelte preprocessors used and their versions (if any): 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: enhancement 6 | assignees: "" 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | - package-ecosystem: "github-actions" 8 | directory: "/" 9 | schedule: 10 | interval: "weekly" 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | needs: lint 13 | 14 | strategy: 15 | matrix: 16 | node-version: [18, 20, 22] 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | cache: "npm" 25 | 26 | # Now install and run tests 27 | - run: npm ci 28 | - run: npm run build 29 | - run: npm test 30 | 31 | # Run lint and version tests as it's own job (also sets up caching of npm packages) 32 | lint: 33 | runs-on: ubuntu-latest 34 | 35 | steps: 36 | - uses: actions/checkout@v4 37 | - name: Use Node.js 20 38 | uses: actions/setup-node@v4 39 | with: 40 | node-version: 20 41 | cache: "npm" 42 | 43 | # Now install packages and lint 44 | - run: npm ci 45 | - run: npm run lint 46 | 47 | # now build and run compatibility tests 48 | - run: npm run build 49 | - run: npm run test:compatibility 50 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: ["v*"] 6 | 7 | permissions: 8 | contents: write 9 | 10 | jobs: 11 | release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v4 16 | 17 | - name: Extract changelog 18 | run: | 19 | CHANGELOG=$(awk -v ver=$(cat version.txt) '/^## / { if (p) { exit }; if ($2 == ver) { p=1; next} } p' CHANGELOG.md) 20 | echo "CHANGELOG<> $GITHUB_ENV 21 | echo "$CHANGELOG" >> $GITHUB_ENV 22 | echo "EOF" >> $GITHUB_ENV 23 | 24 | - name: Create GitHub Release 25 | uses: actions/create-release@v1 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | with: 29 | tag_name: ${{ github.ref }} 30 | release_name: ${{ github.ref }} 31 | body: ${{ env.CHANGELOG }} 32 | draft: false 33 | prerelease: false 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # duh 2 | **node_modules/ 3 | 4 | #should be built by running `node build.js` fresh every time 5 | dist/index.mjs 6 | dist/index.js 7 | 8 | # from example 9 | example/dist/ 10 | example/package-lock.json 11 | 12 | *.log 13 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | package-lock.json 4 | example/package-lock.json 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "overrides": [ 5 | { 6 | "files": ["*.js", "*.mjs", "*.ts"], 7 | "options": { 8 | "tabWidth": 4 9 | } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.9.3 4 | 5 | - Fix regression introduced in 0.9.0 relating to the `include` option ([#306](https://github.com/EMH333/esbuild-svelte/issues/306)) 6 | 7 | ## 0.9.2 8 | 9 | - Fix regression introduced in 0.9.1 related to `*.svelte.ts` files and the `loader` option 10 | - Further restrict options passed to transform `*.svelte.ts` files by default 11 | 12 | ## 0.9.1 13 | 14 | - Fix `*.svelte.ts` transformation issues related to minification and file formats 15 | - Add `esbuildTsTransformOptions` to allow esbuild configuration to be passed directly when transforming `*.svelte.ts` files 16 | 17 | ## 0.9.0 (Breaking) 18 | 19 | This will be the last pre-v1 minor release if all goes according to plan. 20 | 21 | - Add support for `*.svelte.js` and `*.svelte.ts` Svelte modules (Thank you [@ElijahJohnson5 for the contribution!](https://github.com/EMH333/esbuild-svelte/pull/254)) 22 | - Remove support for boolean values for Svelte `css` compile option (use `external` or `injected` instead) 23 | - Bump svelte minimum version to `4.2.1` 24 | - Bump esbuild minimum version to `0.17.0` 25 | - Bump Node minimum version to 18 (lowest supported by Svelte 5) 26 | - Remove `overzealous` cache option (was unusable) 27 | - Remove `fromEntryFile` option (was unusable) 28 | 29 | ## 0.8.2 30 | 31 | - Update Svelte peer dependency version lock to include Svelte 5 pre-release versions ([#235](https://github.com/EMH333/esbuild-svelte/issues/235#issuecomment-2121502360)) 32 | 33 | The version lock will be updated once Svelte 5 is released to remove support for pre-release versions. But for now, this should help prevent needing to use `--force` or `--legacy-peer-deps` when using Svelte 5 pre-releases. 34 | 35 | ## 0.8.1 36 | 37 | - Update Svelte peer dependency version lock to include Svelte 5 38 | 39 | This should have no impact on Svelte 3 or 4 users, but will allow folks to start trying out Svelte 5 if they so please. Any errors or issues should be reported as bugs in order to resolve them before Svelte 5 is offically released. 40 | 41 | **Plugin versions `v0.8.x` will be the last to support Svelte 3 and Svelte 4 below `v4.2.1`** 42 | 43 | ## 0.8.0 (Breaking) 44 | 45 | - **Minorly Breaking** Caching is automatically enabled after two sucessful builds when using the `context` esbuild API 46 | 47 | Previously caching was automatically enabled when using the watch or incremental esbuild options, but those were removed in esbuild `v0.17.0`. This change brings back the automatic cache enabling when using the `context` API which supports the same features as the previous watch and incremental options. esbuild does not provide a way for plugins to determine if the `context` API is being used, so this feature is enabled after two successful builds. This should be a reasonable compromise between not enabling the cache at all and enabling it for every build (which wastes time and space if caching isn't needed). 48 | 49 | If you are using the `context` API and want to disable the cache, you can set the `cache` option to `false` in the plugin options but this isn't recommended (if you do need to disable the cache for some reason, please open an issue to see if your usecase can be fixed). 50 | 51 | - **Minorly Breaking** Add dependency to `@jridgewell/trace-mapping` so error messages are more accurate when using preprocessors ([#83](https://github.com/EMH333/esbuild-svelte/issues/83)) 52 | 53 | If you are using Svelte 4, this doesn't add additional dependencies because that package is already required by Svelte 4. 54 | 55 | - Update development esbuild version to `0.19.0` 56 | 57 | This means that this plugin now supports additional inhancements when using the `context` esbuild `v0.17.0` API as detailed below. 58 | 59 | ## 0.7.4 60 | 61 | - Lock Svelte peerDependency to `>=3.43.0 <5` to protect against breaking changes in future Svelte releases 62 | - Set compilerOptions.css to `external` by default if using Svelte v4 or higher ([#185](https://github.com/EMH333/esbuild-svelte/issues/185)) 63 | - Add compatibility tests for different versions of Svelte and esbuild to prevent regressions 64 | - Switch development version of Svelte to v4 65 | 66 | ## 0.7.3 67 | 68 | - Switch from `.npmignore` to `files` property of `package.json` to prevent accidental file inclusion 69 | 70 | ## 0.7.2 71 | 72 | - Support string values for Svelte compiler option `css` added in Svelte `v3.53.0` ([#109](https://github.com/EMH333/esbuild-svelte/pull/109), [#150](https://github.com/EMH333/esbuild-svelte/pull/150)) 73 | - Update misc dependencies 74 | 75 | ## 0.7.1 76 | 77 | - Fix watch mode if preprocessing failed ([#132](https://github.com/EMH333/esbuild-svelte/pull/132)) 78 | - Remove support for Node 12 79 | 80 | This should probably be another breaking change however Node 12 has reached end of life and is no longer supported. If you are using Node 12, please upgrade to Node 14 in order to continue use of this plugin (or open an issue if you disagree). 81 | 82 | ## 0.7.0 (Breaking) 83 | 84 | - **Breaking** Svelte has been switched to a peer dependency which allows Svelte to be updated independently of this plugin 85 | 86 | Migration is as simple as `npm i --save-dev svelte` if you don't have `svelte` as a dependency already. 87 | 88 | - **Breaking** Remove `compileOptions` since it was deprecated in v0.6.0 89 | 90 | ## 0.6.3 91 | 92 | - Add `filterWarnings` option to filter the Svelte warnings that esbuild-svelte passes to esbuild (Thanks [@Prinzhorn](https://github.com/EMH333/esbuild-svelte/pull/108)) 93 | 94 | See `dist/index.d.ts` for the type definition of the new option. This hope is to replicate `onwarn` from the Svelte Rollup plugin, but in a way that is more conducive to the way esbuild handles things. 95 | 96 | ## 0.6.2 97 | 98 | - Update Svelte to 3.46.2 99 | - (Unstable) Add "overzealous" cache mode that invalidates the cached version of a file if an imported Svelte component has changed ([#102](https://github.com/EMH333/esbuild-svelte/issues/102)) 100 | 101 | As with the standard caching system, this only applies in incremental or watch modes. This shouldn't be used in most situations, but if files aren't rebuilding when they are expected to, then this can be a helpful step before disabling the cache outright. I'm considering this an unstable feature because I'm not set on this way of doing it. This option may change in implementation, name and/or be removed at any time. 102 | 103 | ## 0.6.1 104 | 105 | - Update Svelte to 3.45.0 106 | - Auto create releases 107 | - Rework and improve CI process 108 | 109 | ## 0.6.0 110 | 111 | - **Breaking**: Switch `compileOptions` to `compilerOptions` to better reflect other bundler plugins (Thanks [@tyler-boyd](https://github.com/EMH333/esbuild-svelte/pull/86)) 112 | - Add `include` option so the regex filter that selects compiled files can be changed (Thanks [@tyler-boyd](https://github.com/EMH333/esbuild-svelte/pull/86)) 113 | - Fix "invalid character" error when using preprocessors and non-ASCII characters on NodeJS 15+. Upstream fix in progress (fixes [#84](https://github.com/EMH333/esbuild-svelte/issues/84)) 114 | 115 | ## 0.5.7 116 | 117 | - Handle preprocessors when dealing with sourcemaps 118 | 119 | This should result in more accurate sourcemaps when dealing with one or more preprocessors. Though this was already handled from a purely sourcemap symbols perspective, the sourceContents is now included which should make it easier to understand how the Svelte file was transformed. 120 | 121 | - Update Svelte to 3.44.0 122 | 123 | ## 0.5.6 124 | 125 | - Emergency release to fix errors in distributed files 126 | 127 | ## 0.5.5 128 | 129 | - Return `resolveDir` for created css files so they can import content ([#69](https://github.com/EMH333/esbuild-svelte/issues/69)) 130 | - Update Svelte to 3.42.6 131 | - Add filtering to determine if the file to be processed is directly from esbuild `entryPoints`. 132 | 133 | This is in preparation for a feature that allows a binding to be automatically generated if a .svelte file is set as an entry point. The current configuration defaults to `false` in order to preserve current behavior, however the code is included for future expansion. Most all of my (and others) projects could be simplified once this is added, though I will preserve the current behavior for those that simply want to compile Svelte components using esbuild. 134 | 135 | ## 0.5.4 136 | 137 | - Fix CSS sourcemaps which are now supported with esbuild v0.12.19 ([#63](https://github.com/EMH333/esbuild-svelte/issues/63)) 138 | - Update Svelte to 3.42.1 139 | - Reduce number of development dependencies 140 | 141 | ## 0.5.3 142 | 143 | - Add dependency-aware caching for incremental builds that use a preprocessor ([#59](https://github.com/EMH333/esbuild-svelte/issues/59)) 144 | - Report file dependencies to esbuild when using watch mode 145 | 146 | Likely not something very many people ran into but svelte-esbuild now notifies esbuild of all preprocessor dependecies when watch mode is enabled. This means changes to one of those files will now trigger esbuild to rebuild, improving developer experience. 147 | 148 | ## 0.5.2 149 | 150 | - Disabled cache auto-enabling when using a preprocessor (better fix incoming) 151 | 152 | This is pretty embarrassing and something I should have caught earlier (especially because the esbuild website specifically calls it out). I have a good idea about how to properly fix the issue ([#59](https://github.com/EMH333/esbuild-svelte/issues/59)) but wanted to get a quick and dirty fix out there before others ran into it. This does affect rebuild performance if using preprocessors. 153 | 154 | I don't consider disabling the auto-cache in certain scenarios to be a breaking change. The auto-enable cache feature is a progressive enhancement anyway so worst case performance degrades a bit while I get this fixed. 155 | 156 | - Improve testing (switched to `uvu`) 157 | - Update Svelte to 3.38.3 158 | 159 | ## 0.5.1 160 | 161 | - Update Svelte to 3.38.2 because of bugs in SSR updates 162 | 163 | ## 0.5.0 164 | 165 | - **Breaking**: Require esbuild 0.9.6 or greater to support `initialOptions` property 166 | - **Potentially Breaking**: Auto-enable cache when build is in incremental mode or in watch mode 167 | - **Breaking**: Remove `preprocessor` option, use `preprocess` instead 168 | - Update Svelte to 3.38.0 169 | 170 | ## 0.4.3 171 | 172 | - Update Svelte to 3.35.0 173 | - Update esbuild peer dependency to allow for 0.9.0 version 174 | 175 | ## 0.4.2 176 | 177 | - Add JSDoc deprecation comment to `preprocessor` and add comments for other options 178 | - Fix error arising from esbuid release 0.8.51 and changes to import resolution (Thanks [@AlexxNB](https://github.com/EMH333/esbuild-svelte/pull/34)!) 179 | - Update dependencies 180 | 181 | ## 0.4.1 182 | 183 | - Deprecate `preprocessor` option in favor of `preprocess` 184 | 185 | This is more in line with other bundler plugins which only use the `preprocess` option. This allows common `svelte.config.js` configurations to be used without modification. The `preprocessor` option is now deprecated, and will be removed with the next breaking release. 186 | 187 | - (unstable) Add a cache for incremental and watch builds ([#19](https://github.com/EMH333/esbuild-svelte/issues/19)) 188 | 189 | This should speed up building large projects that use incremental esbuild builds or use the new `--watch` flag for esbuild. It is not required (or recommended) on normal `build` or `transform` calls. To enable this feature, simply set the `cache` option to `true`. This feature should be considered unstable until I get better test coverage. 190 | 191 | - Update and fix example 192 | - Update and add more detail to README 193 | - Update Svelte to 3.32.1 194 | 195 | ## 0.4.0 (**Breaking**) 196 | 197 | - **Breaking** Combine `esbuild-svelte/configurable` and `esbuild-svelte` into one API 198 | 199 | Instead whatever you were importing before, now just import `esbuild-svelte` and call it as a function to get the plugin. 200 | 201 | I've been wanting to do this for a long time (especially since [#12](https://github.com/EMH333/esbuild-svelte/issues/12)) and it seemed like a decent time to sneak this in. I know this breaks builds (sorry about that), I'd rather get it over with now instead of down the line (once this hits `v1.0`). The author of esbuild has some significant code spliting changes incoming in the beginning of 2021, I'll likely bump this to `v1.0` after that. 202 | 203 | - Use TypeScript for development 204 | - Fix example to use `esbuild-svelte` import (`npm link` is a useful command...) 205 | 206 | ## 0.3.2 207 | 208 | - Fix sourcemap generation when exporting external css ([#13](https://github.com/EMH333/esbuild-svelte/issues/13)) 209 | - Update Svelte to 3.31.0 210 | 211 | ## 0.3.1 212 | 213 | - Fix path resolution for Windows when exporting css to external files (Thanks [@markoboy](https://github.com/EMH333/esbuild-svelte/pull/8)) 214 | 215 | This is already covered by tests (when running on Windows) but I'm not going to run CI on Windows. If it continues to be a problem, I will add explict tests but I don't see that becoming the case. 216 | 217 | - Add esbuild as peer dependency 218 | - Update Svelte to 3.29.7 219 | 220 | ## 0.3.0 221 | 222 | - **(Breaking)** Support separate CSS output stream 223 | 224 | No more CSS in JS, yay! If for whatever reason this doesn't work, then just set the `css` compilerOption to `true` and it will revert to the previous behavior. 225 | 226 | In order to implement this, I created a fake file extension loader then set those files to be imported from the js code emited. A map acts as storage between the loaders. I'm not 100% happy with this system because it feels brittle and incomplete but it will work for now. If you have suggestions for how I could do this better, I am all ears! 227 | 228 | ## 0.2.1 229 | 230 | - Fix preprocessor support, currently considered unstable until I test it with some of my personal projects 231 | - Update README because I forgot that I added preprocessor support 232 | 233 | ## 0.2.0 234 | 235 | - Add some simple smoke tests 236 | - Add Github CI 237 | - Add Dependabot 238 | - Fix `configurable` so it actually works now (also add _a bit_ of test coverage so it won't happen again) 239 | - Add typescript types to `configurable` preping for eventual conversion to typescript for development 240 | - Add .npmignore 241 | 242 | ## 0.1.1 243 | 244 | - Format some files 245 | - Update README to reflect the release of the plugin API 246 | 247 | ## 0.1.0 248 | 249 | - Update to esbuild API version 0.8.1 250 | - Add Svelte compiler configuration options 251 | - Fix error/warning reporting from Svelte 252 | 253 | ## 0.0.4 254 | 255 | - Add publishing workflow to reduce mistakes in the future 256 | 257 | ## 0.0.3 258 | 259 | - Update example 260 | - Correct module export 261 | - Update README 262 | 263 | ## 0.0.2 264 | 265 | - Actually export the plugin for use :) 266 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright © 2020 Ethan Hampton 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esbuild-svelte 2 | 3 | [![npm version](https://badge.fury.io/js/esbuild-svelte.svg)](https://badge.fury.io/js/esbuild-svelte) [![npm downloads](http://img.shields.io/npm/dm/esbuild-svelte.svg)](https://www.npmjs.org/package/esbuild-svelte) [![CI](https://github.com/EMH333/esbuild-svelte/actions/workflows/ci.yml/badge.svg)](https://github.com/EMH333/esbuild-svelte/actions/workflows/ci.yml) 4 | 5 | Plugin to compile svelte components for bundling with esbuild. 6 | 7 | ## Install 8 | 9 | Install this plugin, [esbuild](https://github.com/evanw/esbuild) and [Svelte](https://github.com/sveltejs/svelte). 10 | 11 | A simple build script looks like 12 | 13 | ```javascript 14 | import esbuild from "esbuild"; 15 | import sveltePlugin from "esbuild-svelte"; 16 | 17 | esbuild 18 | .build({ 19 | entryPoints: ["app.js"], 20 | mainFields: ["svelte", "browser", "module", "main"], 21 | conditions: ["svelte", "browser"], 22 | bundle: true, 23 | outfile: "out.js", 24 | plugins: [sveltePlugin()], 25 | logLevel: "info", 26 | }) 27 | .catch(() => process.exit(1)); 28 | ``` 29 | 30 | The `example-js` folder of this repository is a great starting off point for a "complete" project. You can quickly get started using [degit](https://github.com/Rich-Harris/degit): 31 | 32 | ```sh 33 | # Clone the JavaScript example to get started 34 | npx degit EMH333/esbuild-svelte/example-js my-svelte-app 35 | 36 | # Clone the TypeScript example to get started 37 | npx degit EMH333/esbuild-svelte/example-ts my-svelte-app 38 | ``` 39 | 40 | ### CSS Output 41 | 42 | By default, `esbuild-svelte` emits external css files from Svelte for `esbuild` to process. If this isn't desired, use a configuration that turns off external css output and instead includes it in the javascript output. For example: `sveltePlugin({compilerOptions: {css: "injected"}})` 43 | 44 | ### Typescript and Other Svelte Preprocessing 45 | 46 | In order to support Typescript and other languages that require preprocessing before being fed into the Svelte compiler, simply add the preprocessor to the `preprocess` option (which accepts both a single preprocessor or an array of them). The example script below is a great place to start, you can also look at the `example-ts` folder for a more complete project. 47 | 48 | ```javascript 49 | import esbuild from "esbuild"; 50 | import esbuildSvelte from "esbuild-svelte"; 51 | import sveltePreprocess from "svelte-preprocess"; 52 | 53 | esbuild 54 | .build({ 55 | entryPoints: ["index.js"], 56 | mainFields: ["svelte", "browser", "module", "main"], 57 | conditions: ["svelte", "browser"], 58 | bundle: true, 59 | outdir: "./dist", 60 | plugins: [ 61 | esbuildSvelte({ 62 | preprocess: sveltePreprocess(), 63 | }), 64 | ], 65 | }) 66 | .catch(() => process.exit(1)); 67 | ``` 68 | 69 | Typescript in `.svelte.ts` files is supported natively. 70 | 71 | ### `svelte` exports condition 72 | 73 | If you are importing a svelte component library, you need to add `"svelte"` to `conditions` in esbuild build options. This lets esbuild use the `svelte` property in svelte component's `exports` conditions in `package.json` . 74 | 75 | ## Advanced 76 | 77 | For incremental or watch build modes, esbuild-svelte will automatically cache files if they haven't changed. This allows esbuild to skip the Svelte compiler for those files altogether, saving time. Setting `cache: false` will disable this file level cache if an issue arises (please report). 78 | 79 | You can see the full API for this plugin [here](https://github.com/EMH333/esbuild-svelte/blob/main/dist/index.d.ts), which includes support for Svelte's compiler options, preprocessing API, and more. 80 | 81 | ## Developing 82 | 83 | Clone, `npm install`, `npm link` and it's good to go! Releases are automated (with the right permissions), just by running `npm version patch|minor|major`. 84 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const { readFile, writeFile } = require("fs"); 3 | const { promisify } = require("util"); 4 | const esbuild = require("esbuild"); 5 | const ts = require("typescript"); 6 | const { rewrite } = require("rewrite-imports"); 7 | 8 | const read = promisify(readFile); 9 | const write = promisify(writeFile); 10 | 11 | const esbuildCommon = { 12 | entryPoints: ["./index.ts"], 13 | platform: "node", 14 | target: ["node18.12.0"], 15 | }; 16 | 17 | (async function () { 18 | //start esbuild process 19 | let result = esbuild.build({ 20 | format: "esm", 21 | outfile: "./dist/index.mjs", 22 | ...esbuildCommon, 23 | }); 24 | 25 | // run .d.ts generation now since it takes a while 26 | const program = ts.createProgram(["index.ts"], { 27 | declaration: true, 28 | emitDeclarationOnly: true, 29 | outDir: "./dist", 30 | }); 31 | program.emit(); 32 | 33 | //wait for esbuild to finish then rewrite imports for cjs version 34 | await result; 35 | let output = await read("./dist/index.mjs", "utf8"); 36 | await write( 37 | "./dist/index.js", 38 | rewrite(output).replace( 39 | /export {.*sveltePlugin as default.*};/s, 40 | "module.exports = sveltePlugin;", 41 | ), 42 | ); 43 | })().catch((err) => { 44 | console.error("ERROR", err.stack || err); 45 | process.exit(1); 46 | }); 47 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import type { CompileOptions, ModuleCompileOptions, CompileResult } from "svelte/compiler"; 2 | import type { PreprocessorGroup } from "svelte/compiler"; 3 | import type { Plugin, TransformOptions } from "esbuild"; 4 | type Warning = CompileResult["warnings"][number]; 5 | interface esbuildSvelteOptions { 6 | /** 7 | * Svelte compiler options 8 | */ 9 | compilerOptions?: CompileOptions; 10 | /** 11 | * Svelte compiler options for module files (*.svelte.js and *.svelte.ts) 12 | */ 13 | moduleCompilerOptions?: ModuleCompileOptions; 14 | /** 15 | * esbuild transform options for ts module files (.svelte.ts) 16 | */ 17 | esbuildTsTransformOptions?: TransformOptions; 18 | /** 19 | * The preprocessor(s) to run the Svelte code through before compiling 20 | */ 21 | preprocess?: PreprocessorGroup | PreprocessorGroup[]; 22 | /** 23 | * Attempts to cache compiled files if the mtime of the file hasn't changed since last run. 24 | * 25 | */ 26 | cache?: boolean; 27 | /** 28 | * The regex filter to use when filtering files to compile 29 | * Defaults to `/\.svelte$/` 30 | */ 31 | include?: RegExp; 32 | /** 33 | * A function to filter out warnings 34 | * Defaults to a constant function that returns `true` 35 | */ 36 | filterWarnings?: (warning: Warning) => boolean; 37 | } 38 | export default function sveltePlugin(options?: esbuildSvelteOptions): Plugin; 39 | export {}; 40 | -------------------------------------------------------------------------------- /example-js/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | *.log 3 | *lock.json 4 | -------------------------------------------------------------------------------- /example-js/buildscript.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const esbuild = require("esbuild"); 3 | const sveltePlugin = require("esbuild-svelte"); 4 | 5 | //make sure the directoy exists before stuff gets put into it 6 | if (!fs.existsSync("./dist/")) { 7 | fs.mkdirSync("./dist/"); 8 | } 9 | 10 | //build the application 11 | esbuild 12 | .build({ 13 | entryPoints: ["./entry.js"], 14 | mainFields: ["svelte", "browser", "module", "main"], 15 | conditions: ["svelte", "browser"], 16 | outdir: "./dist", 17 | format: "esm", 18 | logLevel: "info", 19 | minify: false, //so the resulting code is easier to understand 20 | bundle: true, 21 | splitting: true, 22 | sourcemap: "inline", 23 | plugins: [sveltePlugin()], 24 | }) 25 | .catch((err) => { 26 | console.error(err); 27 | process.exit(1); 28 | }); 29 | 30 | //use a basic html file to test with 31 | fs.copyFile("./index.html", "./dist/index.html", (err) => { 32 | if (err) throw err; 33 | }); 34 | -------------------------------------------------------------------------------- /example-js/entry.js: -------------------------------------------------------------------------------- 1 | import { mount } from "svelte"; 2 | import Test from "./index.svelte"; 3 | 4 | mount(Test, { target: document.body }); 5 | -------------------------------------------------------------------------------- /example-js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | esbuild-svelte Example 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example-js/index.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 25 | 26 |
27 | 29 | 30 |
31 | 32 |
33 | 34 | 35 | 36 | {counter.value} 37 | 38 | 39 |
40 | -------------------------------------------------------------------------------- /example-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "buildscript.js", 3 | "scripts": { 4 | "build": "node buildscript.js" 5 | }, 6 | "dependencies": { 7 | "esbuild": "^0.25.0", 8 | "esbuild-svelte": "^0.8.0", 9 | "svelte": "^5.1.3" 10 | }, 11 | "private": true 12 | } 13 | -------------------------------------------------------------------------------- /example-js/second.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example-js/test.svelte.js: -------------------------------------------------------------------------------- 1 | export default class Counter { 2 | value = $state(0); 3 | } 4 | -------------------------------------------------------------------------------- /example-ts/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | *.log 3 | *lock.json 4 | -------------------------------------------------------------------------------- /example-ts/buildscript.js: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import esbuild from "esbuild"; 3 | import esbuildSvelte from "esbuild-svelte"; 4 | import { sveltePreprocess } from "svelte-preprocess"; 5 | 6 | //make sure the directoy exists before stuff gets put into it 7 | if (!fs.existsSync("./dist/")) { 8 | fs.mkdirSync("./dist/"); 9 | } 10 | esbuild 11 | .build({ 12 | entryPoints: [`./entry.ts`], 13 | bundle: true, 14 | outdir: `./dist`, 15 | mainFields: ["svelte", "browser", "module", "main"], 16 | conditions: ["svelte", "browser"], 17 | // logLevel: `info`, 18 | minify: false, //so the resulting code is easier to understand 19 | sourcemap: "inline", 20 | splitting: true, 21 | write: true, 22 | format: `esm`, 23 | plugins: [ 24 | esbuildSvelte({ 25 | preprocess: sveltePreprocess(), 26 | }), 27 | ], 28 | }) 29 | .catch((error, location) => { 30 | console.warn(`Errors: `, error, location); 31 | process.exit(1); 32 | }); 33 | 34 | //use a basic html file to test with 35 | fs.copyFileSync("./index.html", "./dist/index.html"); 36 | 37 | // maybe incorporate svelte-check or tsc too? 38 | // https://github.com/EMH333/esbuild-svelte/blob/main/build.js 39 | -------------------------------------------------------------------------------- /example-ts/entry.ts: -------------------------------------------------------------------------------- 1 | import Test from "./index.svelte"; 2 | import { haha } from "./fun"; 3 | import { mount } from "svelte"; 4 | 5 | mount(Test, { target: document.body }); 6 | console.log(haha()); 7 | -------------------------------------------------------------------------------- /example-ts/fun.ts: -------------------------------------------------------------------------------- 1 | export function haha(): string { 2 | return `hahahahHA!!`; 3 | } 4 | 5 | export type Joke = { 6 | rating: number; 7 | joke: string; 8 | }; 9 | -------------------------------------------------------------------------------- /example-ts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | esbuild-svelte Typescript Example 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example-ts/index.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | 34 | 35 |
36 | 38 | 39 |
40 | 41 |
42 | 43 | 44 | 45 | {counter.value} 46 |

{haha()}

47 |

{add(1,4)}

48 |

{JSON.stringify(jo)}

49 | 50 |
51 | -------------------------------------------------------------------------------- /example-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "buildscript.js", 3 | "type": "module", 4 | "scripts": { 5 | "build": "node buildscript.js", 6 | "typecheck": "svelte-check --tsconfig tsconfig.json --fail-on-warnings" 7 | }, 8 | "dependencies": { 9 | "@tsconfig/svelte": "^5.0.2", 10 | "esbuild": "^0.25.0", 11 | "esbuild-svelte": "^0.8.0", 12 | "svelte": "^5.1.3", 13 | "svelte-check": "^4.0.5", 14 | "svelte-preprocess": "^6.0.3", 15 | "typescript": "^5.3.3" 16 | }, 17 | "private": true 18 | } 19 | -------------------------------------------------------------------------------- /example-ts/second.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example-ts/test.svelte.ts: -------------------------------------------------------------------------------- 1 | export default class Counter { 2 | value: number = $state(0); 3 | } 4 | -------------------------------------------------------------------------------- /example-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // as recommended by Rick Harris himself 3 | // https://stackoverflow.com/questions/62761623/how-do-you-import-a-svelte-component-in-a-typescript-file 4 | "extends": "@tsconfig/svelte/tsconfig.json", 5 | "compilerOptions": { 6 | /* Visit https://aka.ms/tsconfig to read more about this file */ 7 | 8 | /* Language and Environment */ 9 | "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 10 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 11 | 12 | /* Modules */ 13 | "module": "es2022" /* Specify what module code is generated. */, 14 | // "rootDir": "./", /* Specify the root folder within your source files. */ 15 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 16 | "baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */, 17 | 18 | // And if you want to use $ imports 19 | // "paths": { 20 | // "$": ["."], 21 | // "$*": ["./*"] 22 | // }, /* Specify a set of entries that re-map imports to additional lookup locations. */ 23 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 24 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 25 | "types": [ 26 | // "node", 27 | "svelte" 28 | ] /* Specify type package names to be included without being referenced in a source file. */, 29 | 30 | /* Interop Constraints */ 31 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 32 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 33 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 34 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 35 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 36 | 37 | /* Type Checking */ 38 | "strict": true /* Enable all strict type-checking options. */, 39 | 40 | /* Completeness */ 41 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 42 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 43 | }, 44 | "include": ["entry.ts"], 45 | "exclude": ["node_modules/**", "dist/**"] 46 | } 47 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | //original version from https://github.com/evanw/esbuild/blob/plugins/docs/plugin-examples.md 2 | import { preprocess, compile, VERSION } from "svelte/compiler"; 3 | import { dirname, basename, relative } from "path"; 4 | import { promisify } from "util"; 5 | import { readFile, statSync } from "fs"; 6 | import { originalPositionFor, TraceMap } from "@jridgewell/trace-mapping"; 7 | 8 | import type { CompileOptions, ModuleCompileOptions, CompileResult } from "svelte/compiler"; 9 | import type { PreprocessorGroup } from "svelte/compiler"; 10 | import type { 11 | OnLoadResult, 12 | Plugin, 13 | PluginBuild, 14 | Location, 15 | PartialMessage, 16 | TransformOptions, 17 | } from "esbuild"; 18 | 19 | type Warning = CompileResult["warnings"][number]; 20 | 21 | interface esbuildSvelteOptions { 22 | /** 23 | * Svelte compiler options 24 | */ 25 | compilerOptions?: CompileOptions; 26 | 27 | /** 28 | * Svelte compiler options for module files (*.svelte.js and *.svelte.ts) 29 | */ 30 | moduleCompilerOptions?: ModuleCompileOptions; 31 | 32 | /** 33 | * esbuild transform options for ts module files (.svelte.ts) 34 | */ 35 | esbuildTsTransformOptions?: TransformOptions; 36 | 37 | /** 38 | * The preprocessor(s) to run the Svelte code through before compiling 39 | */ 40 | preprocess?: PreprocessorGroup | PreprocessorGroup[]; 41 | 42 | /** 43 | * Attempts to cache compiled files if the mtime of the file hasn't changed since last run. 44 | * 45 | */ 46 | cache?: boolean; 47 | 48 | /** 49 | * The regex filter to use when filtering files to compile 50 | * Defaults to `/\.svelte$/` 51 | */ 52 | include?: RegExp; 53 | 54 | /** 55 | * A function to filter out warnings 56 | * Defaults to a constant function that returns `true` 57 | */ 58 | filterWarnings?: (warning: Warning) => boolean; 59 | } 60 | 61 | interface CacheData { 62 | data: OnLoadResult; 63 | // path, last modified time 64 | dependencies: Map; 65 | } 66 | 67 | async function convertMessage( 68 | { message, start, end }: Warning, 69 | filename: string, 70 | source: string, 71 | sourcemap: any, 72 | ): Promise { 73 | let location: Partial | undefined; 74 | if (start && end) { 75 | let lineText = source.split(/\r\n|\r|\n/g)[start.line - 1]; 76 | let lineEnd = start.line === end.line ? end.column : lineText.length; 77 | 78 | // Adjust the start and end positions based on what the preprocessors did so the positions are correct 79 | if (sourcemap) { 80 | sourcemap = new TraceMap(sourcemap); 81 | const pos = originalPositionFor(sourcemap, { 82 | line: start.line, 83 | column: start.column, 84 | }); 85 | if (pos.source) { 86 | start.line = pos.line ?? start.line; 87 | start.column = pos.column ?? start.column; 88 | } 89 | } 90 | 91 | location = { 92 | file: filename, 93 | line: start.line, 94 | column: start.column, 95 | length: lineEnd - start.column, 96 | lineText, 97 | }; 98 | } 99 | return { text: message, location }; 100 | } 101 | 102 | //still support old incremental option if possible, but can still be overriden by cache option 103 | const shouldCache = ( 104 | build: PluginBuild & { 105 | initialOptions: { 106 | incremental?: boolean; 107 | watch?: boolean; 108 | }; 109 | }, 110 | ) => build.initialOptions?.incremental || build.initialOptions?.watch; 111 | 112 | const SVELTE_VERSION = VERSION.split(".").map((v) => parseInt(v))[0]; 113 | const SVELTE_JAVASCRIPT_MODULE_FILTER = /\.svelte\.js$/; 114 | const SVELTE_TYPESCRIPT_MODULE_FILTER = /\.svelte\.ts$/; 115 | const SVELTE_MODULE_FILTER = new RegExp( 116 | `(${SVELTE_JAVASCRIPT_MODULE_FILTER.source})|(${SVELTE_TYPESCRIPT_MODULE_FILTER.source})`, 117 | ); 118 | const SVELTE_FILE_FILTER = /\.svelte$/; 119 | const SVELTE_FILTER = 120 | SVELTE_VERSION === 5 121 | ? new RegExp(`(${SVELTE_FILE_FILTER.source})|${SVELTE_MODULE_FILTER.source}`) 122 | : SVELTE_FILE_FILTER; 123 | const FAKE_CSS_FILTER = /\.esbuild-svelte-fake-css$/; 124 | 125 | // This is effectively: esbuild build options - valid transform options 126 | // TODO: there are better ways to do this 127 | const TS_MODULE_DISALLOWED_OPTIONS = [ 128 | "absWorkingDir", 129 | "alias", 130 | "allowOverwrite", 131 | "analyze", 132 | "assetNames", 133 | "banner", 134 | "bundle", 135 | "chunkNames", 136 | "conditions", 137 | "entryNames", 138 | "entryPoints", 139 | "external", 140 | "footer", 141 | "inject", 142 | "mainFields", 143 | "mangeProps", 144 | "mangleQuoted", 145 | "metafile", 146 | "nodePaths", 147 | "outbase", 148 | "outdir", 149 | "outExtension", 150 | "outfile", 151 | "packages", 152 | "plugins", 153 | "preserveSymlinks", 154 | "publicPath", 155 | "resolveExtensions", 156 | "splitting", 157 | "stdin", 158 | "treeShaking", 159 | "tsconfig", 160 | "write", 161 | // minify breaks things 162 | "minify", 163 | // do not need to do any format conversion 164 | // output will go though esbuild again anyway 165 | "format", 166 | // loader has a different type in build vs transform 167 | "loader", 168 | ]; 169 | 170 | export default function sveltePlugin(options?: esbuildSvelteOptions): Plugin { 171 | const svelteFilter = options?.include ?? SVELTE_FILTER; 172 | return { 173 | name: "esbuild-svelte", 174 | setup(build) { 175 | if (!options) { 176 | options = {}; 177 | } 178 | // see if we are incrementally building or watching for changes and enable the cache 179 | // also checks if it has already been defined and ignores this if it has 180 | if (options.cache == undefined && shouldCache(build)) { 181 | options.cache = true; 182 | } 183 | 184 | // by default all warnings are enabled 185 | if (options.filterWarnings == undefined) { 186 | options.filterWarnings = () => true; 187 | } 188 | 189 | // determine valid options for svelte ts module transformation (*.svelte.ts files) 190 | const transformOptions = 191 | options?.esbuildTsTransformOptions ?? 192 | Object.fromEntries( 193 | Object.entries(build.initialOptions).filter( 194 | ([key, val]) => !TS_MODULE_DISALLOWED_OPTIONS.includes(key), 195 | ), 196 | ); 197 | 198 | //Store generated css code for use in fake import 199 | const cssCode = new Map(); 200 | const fileCache = new Map(); 201 | 202 | //main loader 203 | build.onLoad({ filter: svelteFilter }, async (args) => { 204 | let cachedFile = null; 205 | let previousWatchFiles: string[] = []; 206 | 207 | // if told to use the cache, check if it contains the file, 208 | // and if the modified time is not greater than the time when it was cached 209 | // if so, return the cached data 210 | if (options?.cache === true && fileCache.has(args.path)) { 211 | cachedFile = fileCache.get(args.path) || { 212 | dependencies: new Map(), 213 | data: null, 214 | }; // should never hit the null b/c of has check 215 | let cacheValid = true; 216 | 217 | //for each dependency check if the mtime is still valid 218 | //if an exception is generated (file was deleted or something) then cache isn't valid 219 | try { 220 | cachedFile.dependencies.forEach((time, path) => { 221 | if (statSync(path).mtime > time) { 222 | cacheValid = false; 223 | } 224 | }); 225 | } catch { 226 | cacheValid = false; 227 | } 228 | 229 | if (cacheValid) { 230 | return cachedFile.data; 231 | } else { 232 | fileCache.delete(args.path); //can remove from cache if no longer valid 233 | } 234 | } 235 | 236 | //reading files 237 | let originalSource = await promisify(readFile)(args.path, "utf8"); 238 | let filename = relative(process.cwd(), args.path); 239 | let source = originalSource; 240 | 241 | if (SVELTE_TYPESCRIPT_MODULE_FILTER.test(filename)) { 242 | try { 243 | const result = await build.esbuild.transform(originalSource, { 244 | loader: "ts", // first so it can be overrode by esbuildTsTransformOptions 245 | ...transformOptions, 246 | }); 247 | 248 | source = result.code; 249 | } catch (e: any) { 250 | let result: OnLoadResult = {}; 251 | result.errors = [ 252 | await convertMessage( 253 | e, 254 | args.path, 255 | originalSource, 256 | options?.compilerOptions?.sourcemap, 257 | ), 258 | ]; 259 | // only provide if context API is supported or we are caching 260 | if (build.esbuild?.context !== undefined || shouldCache(build)) { 261 | result.watchFiles = previousWatchFiles; 262 | } 263 | return result; 264 | } 265 | } 266 | 267 | //file modification time storage 268 | const dependencyModifcationTimes = new Map(); 269 | dependencyModifcationTimes.set(args.path, statSync(args.path).mtime); // add the target file 270 | 271 | let compilerOptions = { 272 | css: "external" as "external", 273 | ...options?.compilerOptions, 274 | }; 275 | 276 | let moduleCompilerOptions: ModuleCompileOptions = { 277 | ...options?.moduleCompilerOptions, 278 | }; 279 | 280 | //actually compile file 281 | try { 282 | //do preprocessor stuff if it exists 283 | if (options?.preprocess) { 284 | let preprocessResult = null; 285 | 286 | try { 287 | preprocessResult = await preprocess(source, options.preprocess, { 288 | filename, 289 | }); 290 | } catch (e: any) { 291 | // if preprocess failed there are chances that an external dependency caused exception 292 | // to avoid stop watching those files, we keep the previous dependencies if available 293 | if (cachedFile) { 294 | previousWatchFiles = Array.from(cachedFile.dependencies.keys()); 295 | } 296 | throw e; 297 | } 298 | 299 | if (preprocessResult.map) { 300 | // normalize the sourcemap 'source' entrys to all match if they are the same file 301 | // needed because of differing handling of file names in preprocessors 302 | let fixedMap = preprocessResult.map as { sources: Array }; 303 | for (let index = 0; index < fixedMap?.sources.length; index++) { 304 | if (fixedMap.sources[index] == filename) { 305 | fixedMap.sources[index] = basename(filename); 306 | } 307 | } 308 | compilerOptions.sourcemap = fixedMap; 309 | } 310 | source = preprocessResult.code; 311 | 312 | // if caching then we need to store the modifcation times for all dependencies 313 | if (options?.cache === true) { 314 | preprocessResult.dependencies?.forEach((entry) => { 315 | dependencyModifcationTimes.set(entry, statSync(entry).mtime); 316 | }); 317 | } 318 | } 319 | 320 | let { js, css, warnings } = await (async () => { 321 | if (SVELTE_VERSION === 5 && SVELTE_MODULE_FILTER.test(filename)) { 322 | const { compileModule } = await import("svelte/compiler"); 323 | return compileModule(source, { 324 | ...moduleCompilerOptions, 325 | filename, 326 | }); 327 | } 328 | 329 | return compile(source, { 330 | ...compilerOptions, 331 | filename, 332 | }); 333 | })(); 334 | 335 | //esbuild doesn't seem to like sourcemaps without "sourcesContent" which Svelte doesn't provide 336 | //so attempt to populate that array if we can find filename in sources 337 | if (compilerOptions.sourcemap) { 338 | if (js.map.sourcesContent == undefined) { 339 | js.map.sourcesContent = []; 340 | } 341 | 342 | for (let index = 0; index < js.map.sources.length; index++) { 343 | const element = js.map.sources[index]; 344 | if (element == basename(filename)) { 345 | js.map.sourcesContent[index] = originalSource; 346 | index = Infinity; //can break out of loop 347 | } 348 | } 349 | } 350 | 351 | let contents = js.code + `\n//# sourceMappingURL=` + js.map.toUrl(); 352 | 353 | //if svelte emits css seperately, then store it in a map and import it from the js 354 | if (compilerOptions.css === "external" && css?.code) { 355 | let cssPath = args.path 356 | .replace(".svelte", ".esbuild-svelte-fake-css") //TODO append instead of replace to support different svelte filters 357 | .replace(/\\/g, "/"); 358 | cssCode.set( 359 | cssPath, 360 | css.code + `/*# sourceMappingURL=${css.map.toUrl()} */`, 361 | ); 362 | contents = contents + `\nimport "${cssPath}";`; 363 | } 364 | 365 | if (options?.filterWarnings) { 366 | warnings = warnings.filter(options.filterWarnings); 367 | } 368 | 369 | const result: OnLoadResult = { 370 | contents, 371 | warnings: await Promise.all( 372 | warnings.map( 373 | async (e) => 374 | await convertMessage( 375 | e, 376 | args.path, 377 | source, 378 | compilerOptions.sourcemap, 379 | ), 380 | ), 381 | ), 382 | }; 383 | 384 | // if we are told to cache, then cache 385 | if (options?.cache === true) { 386 | fileCache.set(args.path, { 387 | data: result, 388 | dependencies: dependencyModifcationTimes, 389 | }); 390 | } 391 | 392 | // make sure to tell esbuild to watch any additional files used if supported 393 | // only provide if context API is supported or we are caching 394 | if (build.esbuild?.context !== undefined || shouldCache(build)) { 395 | result.watchFiles = Array.from(dependencyModifcationTimes.keys()); 396 | } 397 | 398 | return result; 399 | } catch (e: any) { 400 | let result: OnLoadResult = {}; 401 | result.errors = [ 402 | await convertMessage( 403 | e, 404 | args.path, 405 | originalSource, 406 | compilerOptions.sourcemap, 407 | ), 408 | ]; 409 | // only provide if context API is supported or we are caching 410 | if (build.esbuild?.context !== undefined || shouldCache(build)) { 411 | result.watchFiles = previousWatchFiles; 412 | } 413 | return result; 414 | } 415 | }); 416 | 417 | //if the css exists in our map, then output it with the css loader 418 | build.onResolve({ filter: FAKE_CSS_FILTER }, ({ path }) => { 419 | return { path, namespace: "fakecss" }; 420 | }); 421 | 422 | build.onLoad({ filter: FAKE_CSS_FILTER, namespace: "fakecss" }, ({ path }) => { 423 | const css = cssCode.get(path); 424 | return css ? { contents: css, loader: "css", resolveDir: dirname(path) } : null; 425 | }); 426 | 427 | // this enables the cache at the end of the build. The cache is disabled by default, 428 | // but if this plugin instance is used agian, then the cache will be enabled (because 429 | // we can be confident that the build is incremental or watch). 430 | // This saves enabling caching on every build, which would be a performance hit but 431 | // also makes sure incremental performance is increased. 432 | build.onEnd(() => { 433 | if (!options) { 434 | options = {}; 435 | } 436 | if (options.cache === undefined) { 437 | options.cache = true; 438 | } 439 | }); 440 | }, 441 | }; 442 | } 443 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esbuild-svelte", 3 | "version": "0.9.3", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "esbuild-svelte", 9 | "version": "0.9.3", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@jridgewell/trace-mapping": "^0.3.19" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^18.15.3", 16 | "esbuild": "^0.25.4", 17 | "prettier": "^3.4.0", 18 | "rewrite-imports": "^3.0.0", 19 | "sass": "^1.83.0", 20 | "svelte": "^5.19.0", 21 | "svelte-preprocess-esbuild": "^3.0.0", 22 | "svelte-preprocess-sass": "^2.0.1", 23 | "typescript": "^5.5.2", 24 | "uvu": "^0.5.6" 25 | }, 26 | "engines": { 27 | "node": ">=18" 28 | }, 29 | "peerDependencies": { 30 | "esbuild": ">=0.17.0", 31 | "svelte": ">=4.2.1 <6" 32 | } 33 | }, 34 | "node_modules/@ampproject/remapping": { 35 | "version": "2.3.0", 36 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", 37 | "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", 38 | "dev": true, 39 | "license": "Apache-2.0", 40 | "dependencies": { 41 | "@jridgewell/gen-mapping": "^0.3.5", 42 | "@jridgewell/trace-mapping": "^0.3.24" 43 | }, 44 | "engines": { 45 | "node": ">=6.0.0" 46 | } 47 | }, 48 | "node_modules/@esbuild/aix-ppc64": { 49 | "version": "0.25.4", 50 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", 51 | "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", 52 | "cpu": [ 53 | "ppc64" 54 | ], 55 | "dev": true, 56 | "license": "MIT", 57 | "optional": true, 58 | "os": [ 59 | "aix" 60 | ], 61 | "engines": { 62 | "node": ">=18" 63 | } 64 | }, 65 | "node_modules/@esbuild/android-arm": { 66 | "version": "0.25.4", 67 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", 68 | "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", 69 | "cpu": [ 70 | "arm" 71 | ], 72 | "dev": true, 73 | "license": "MIT", 74 | "optional": true, 75 | "os": [ 76 | "android" 77 | ], 78 | "engines": { 79 | "node": ">=18" 80 | } 81 | }, 82 | "node_modules/@esbuild/android-arm64": { 83 | "version": "0.25.4", 84 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", 85 | "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", 86 | "cpu": [ 87 | "arm64" 88 | ], 89 | "dev": true, 90 | "license": "MIT", 91 | "optional": true, 92 | "os": [ 93 | "android" 94 | ], 95 | "engines": { 96 | "node": ">=18" 97 | } 98 | }, 99 | "node_modules/@esbuild/android-x64": { 100 | "version": "0.25.4", 101 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", 102 | "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", 103 | "cpu": [ 104 | "x64" 105 | ], 106 | "dev": true, 107 | "license": "MIT", 108 | "optional": true, 109 | "os": [ 110 | "android" 111 | ], 112 | "engines": { 113 | "node": ">=18" 114 | } 115 | }, 116 | "node_modules/@esbuild/darwin-arm64": { 117 | "version": "0.25.4", 118 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", 119 | "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", 120 | "cpu": [ 121 | "arm64" 122 | ], 123 | "dev": true, 124 | "license": "MIT", 125 | "optional": true, 126 | "os": [ 127 | "darwin" 128 | ], 129 | "engines": { 130 | "node": ">=18" 131 | } 132 | }, 133 | "node_modules/@esbuild/darwin-x64": { 134 | "version": "0.25.4", 135 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", 136 | "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", 137 | "cpu": [ 138 | "x64" 139 | ], 140 | "dev": true, 141 | "license": "MIT", 142 | "optional": true, 143 | "os": [ 144 | "darwin" 145 | ], 146 | "engines": { 147 | "node": ">=18" 148 | } 149 | }, 150 | "node_modules/@esbuild/freebsd-arm64": { 151 | "version": "0.25.4", 152 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", 153 | "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", 154 | "cpu": [ 155 | "arm64" 156 | ], 157 | "dev": true, 158 | "license": "MIT", 159 | "optional": true, 160 | "os": [ 161 | "freebsd" 162 | ], 163 | "engines": { 164 | "node": ">=18" 165 | } 166 | }, 167 | "node_modules/@esbuild/freebsd-x64": { 168 | "version": "0.25.4", 169 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", 170 | "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", 171 | "cpu": [ 172 | "x64" 173 | ], 174 | "dev": true, 175 | "license": "MIT", 176 | "optional": true, 177 | "os": [ 178 | "freebsd" 179 | ], 180 | "engines": { 181 | "node": ">=18" 182 | } 183 | }, 184 | "node_modules/@esbuild/linux-arm": { 185 | "version": "0.25.4", 186 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", 187 | "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", 188 | "cpu": [ 189 | "arm" 190 | ], 191 | "dev": true, 192 | "license": "MIT", 193 | "optional": true, 194 | "os": [ 195 | "linux" 196 | ], 197 | "engines": { 198 | "node": ">=18" 199 | } 200 | }, 201 | "node_modules/@esbuild/linux-arm64": { 202 | "version": "0.25.4", 203 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", 204 | "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", 205 | "cpu": [ 206 | "arm64" 207 | ], 208 | "dev": true, 209 | "license": "MIT", 210 | "optional": true, 211 | "os": [ 212 | "linux" 213 | ], 214 | "engines": { 215 | "node": ">=18" 216 | } 217 | }, 218 | "node_modules/@esbuild/linux-ia32": { 219 | "version": "0.25.4", 220 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", 221 | "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", 222 | "cpu": [ 223 | "ia32" 224 | ], 225 | "dev": true, 226 | "license": "MIT", 227 | "optional": true, 228 | "os": [ 229 | "linux" 230 | ], 231 | "engines": { 232 | "node": ">=18" 233 | } 234 | }, 235 | "node_modules/@esbuild/linux-loong64": { 236 | "version": "0.25.4", 237 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", 238 | "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", 239 | "cpu": [ 240 | "loong64" 241 | ], 242 | "dev": true, 243 | "license": "MIT", 244 | "optional": true, 245 | "os": [ 246 | "linux" 247 | ], 248 | "engines": { 249 | "node": ">=18" 250 | } 251 | }, 252 | "node_modules/@esbuild/linux-mips64el": { 253 | "version": "0.25.4", 254 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", 255 | "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", 256 | "cpu": [ 257 | "mips64el" 258 | ], 259 | "dev": true, 260 | "license": "MIT", 261 | "optional": true, 262 | "os": [ 263 | "linux" 264 | ], 265 | "engines": { 266 | "node": ">=18" 267 | } 268 | }, 269 | "node_modules/@esbuild/linux-ppc64": { 270 | "version": "0.25.4", 271 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", 272 | "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", 273 | "cpu": [ 274 | "ppc64" 275 | ], 276 | "dev": true, 277 | "license": "MIT", 278 | "optional": true, 279 | "os": [ 280 | "linux" 281 | ], 282 | "engines": { 283 | "node": ">=18" 284 | } 285 | }, 286 | "node_modules/@esbuild/linux-riscv64": { 287 | "version": "0.25.4", 288 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", 289 | "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", 290 | "cpu": [ 291 | "riscv64" 292 | ], 293 | "dev": true, 294 | "license": "MIT", 295 | "optional": true, 296 | "os": [ 297 | "linux" 298 | ], 299 | "engines": { 300 | "node": ">=18" 301 | } 302 | }, 303 | "node_modules/@esbuild/linux-s390x": { 304 | "version": "0.25.4", 305 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", 306 | "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", 307 | "cpu": [ 308 | "s390x" 309 | ], 310 | "dev": true, 311 | "license": "MIT", 312 | "optional": true, 313 | "os": [ 314 | "linux" 315 | ], 316 | "engines": { 317 | "node": ">=18" 318 | } 319 | }, 320 | "node_modules/@esbuild/linux-x64": { 321 | "version": "0.25.4", 322 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", 323 | "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", 324 | "cpu": [ 325 | "x64" 326 | ], 327 | "dev": true, 328 | "license": "MIT", 329 | "optional": true, 330 | "os": [ 331 | "linux" 332 | ], 333 | "engines": { 334 | "node": ">=18" 335 | } 336 | }, 337 | "node_modules/@esbuild/netbsd-arm64": { 338 | "version": "0.25.4", 339 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", 340 | "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", 341 | "cpu": [ 342 | "arm64" 343 | ], 344 | "dev": true, 345 | "license": "MIT", 346 | "optional": true, 347 | "os": [ 348 | "netbsd" 349 | ], 350 | "engines": { 351 | "node": ">=18" 352 | } 353 | }, 354 | "node_modules/@esbuild/netbsd-x64": { 355 | "version": "0.25.4", 356 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", 357 | "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", 358 | "cpu": [ 359 | "x64" 360 | ], 361 | "dev": true, 362 | "license": "MIT", 363 | "optional": true, 364 | "os": [ 365 | "netbsd" 366 | ], 367 | "engines": { 368 | "node": ">=18" 369 | } 370 | }, 371 | "node_modules/@esbuild/openbsd-arm64": { 372 | "version": "0.25.4", 373 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", 374 | "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", 375 | "cpu": [ 376 | "arm64" 377 | ], 378 | "dev": true, 379 | "license": "MIT", 380 | "optional": true, 381 | "os": [ 382 | "openbsd" 383 | ], 384 | "engines": { 385 | "node": ">=18" 386 | } 387 | }, 388 | "node_modules/@esbuild/openbsd-x64": { 389 | "version": "0.25.4", 390 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", 391 | "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", 392 | "cpu": [ 393 | "x64" 394 | ], 395 | "dev": true, 396 | "license": "MIT", 397 | "optional": true, 398 | "os": [ 399 | "openbsd" 400 | ], 401 | "engines": { 402 | "node": ">=18" 403 | } 404 | }, 405 | "node_modules/@esbuild/sunos-x64": { 406 | "version": "0.25.4", 407 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", 408 | "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", 409 | "cpu": [ 410 | "x64" 411 | ], 412 | "dev": true, 413 | "license": "MIT", 414 | "optional": true, 415 | "os": [ 416 | "sunos" 417 | ], 418 | "engines": { 419 | "node": ">=18" 420 | } 421 | }, 422 | "node_modules/@esbuild/win32-arm64": { 423 | "version": "0.25.4", 424 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", 425 | "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", 426 | "cpu": [ 427 | "arm64" 428 | ], 429 | "dev": true, 430 | "license": "MIT", 431 | "optional": true, 432 | "os": [ 433 | "win32" 434 | ], 435 | "engines": { 436 | "node": ">=18" 437 | } 438 | }, 439 | "node_modules/@esbuild/win32-ia32": { 440 | "version": "0.25.4", 441 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", 442 | "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", 443 | "cpu": [ 444 | "ia32" 445 | ], 446 | "dev": true, 447 | "license": "MIT", 448 | "optional": true, 449 | "os": [ 450 | "win32" 451 | ], 452 | "engines": { 453 | "node": ">=18" 454 | } 455 | }, 456 | "node_modules/@esbuild/win32-x64": { 457 | "version": "0.25.4", 458 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", 459 | "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", 460 | "cpu": [ 461 | "x64" 462 | ], 463 | "dev": true, 464 | "license": "MIT", 465 | "optional": true, 466 | "os": [ 467 | "win32" 468 | ], 469 | "engines": { 470 | "node": ">=18" 471 | } 472 | }, 473 | "node_modules/@jridgewell/gen-mapping": { 474 | "version": "0.3.8", 475 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", 476 | "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", 477 | "dev": true, 478 | "license": "MIT", 479 | "dependencies": { 480 | "@jridgewell/set-array": "^1.2.1", 481 | "@jridgewell/sourcemap-codec": "^1.4.10", 482 | "@jridgewell/trace-mapping": "^0.3.24" 483 | }, 484 | "engines": { 485 | "node": ">=6.0.0" 486 | } 487 | }, 488 | "node_modules/@jridgewell/resolve-uri": { 489 | "version": "3.1.2", 490 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 491 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 492 | "license": "MIT", 493 | "engines": { 494 | "node": ">=6.0.0" 495 | } 496 | }, 497 | "node_modules/@jridgewell/set-array": { 498 | "version": "1.2.1", 499 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 500 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 501 | "dev": true, 502 | "license": "MIT", 503 | "engines": { 504 | "node": ">=6.0.0" 505 | } 506 | }, 507 | "node_modules/@jridgewell/sourcemap-codec": { 508 | "version": "1.5.0", 509 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 510 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 511 | "license": "MIT" 512 | }, 513 | "node_modules/@jridgewell/trace-mapping": { 514 | "version": "0.3.25", 515 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 516 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 517 | "license": "MIT", 518 | "dependencies": { 519 | "@jridgewell/resolve-uri": "^3.1.0", 520 | "@jridgewell/sourcemap-codec": "^1.4.14" 521 | } 522 | }, 523 | "node_modules/@parcel/watcher": { 524 | "version": "2.5.0", 525 | "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", 526 | "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", 527 | "dev": true, 528 | "hasInstallScript": true, 529 | "license": "MIT", 530 | "optional": true, 531 | "dependencies": { 532 | "detect-libc": "^1.0.3", 533 | "is-glob": "^4.0.3", 534 | "micromatch": "^4.0.5", 535 | "node-addon-api": "^7.0.0" 536 | }, 537 | "engines": { 538 | "node": ">= 10.0.0" 539 | }, 540 | "funding": { 541 | "type": "opencollective", 542 | "url": "https://opencollective.com/parcel" 543 | }, 544 | "optionalDependencies": { 545 | "@parcel/watcher-android-arm64": "2.5.0", 546 | "@parcel/watcher-darwin-arm64": "2.5.0", 547 | "@parcel/watcher-darwin-x64": "2.5.0", 548 | "@parcel/watcher-freebsd-x64": "2.5.0", 549 | "@parcel/watcher-linux-arm-glibc": "2.5.0", 550 | "@parcel/watcher-linux-arm-musl": "2.5.0", 551 | "@parcel/watcher-linux-arm64-glibc": "2.5.0", 552 | "@parcel/watcher-linux-arm64-musl": "2.5.0", 553 | "@parcel/watcher-linux-x64-glibc": "2.5.0", 554 | "@parcel/watcher-linux-x64-musl": "2.5.0", 555 | "@parcel/watcher-win32-arm64": "2.5.0", 556 | "@parcel/watcher-win32-ia32": "2.5.0", 557 | "@parcel/watcher-win32-x64": "2.5.0" 558 | } 559 | }, 560 | "node_modules/@parcel/watcher-android-arm64": { 561 | "version": "2.5.0", 562 | "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", 563 | "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", 564 | "cpu": [ 565 | "arm64" 566 | ], 567 | "dev": true, 568 | "license": "MIT", 569 | "optional": true, 570 | "os": [ 571 | "android" 572 | ], 573 | "engines": { 574 | "node": ">= 10.0.0" 575 | }, 576 | "funding": { 577 | "type": "opencollective", 578 | "url": "https://opencollective.com/parcel" 579 | } 580 | }, 581 | "node_modules/@parcel/watcher-darwin-arm64": { 582 | "version": "2.5.0", 583 | "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", 584 | "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", 585 | "cpu": [ 586 | "arm64" 587 | ], 588 | "dev": true, 589 | "license": "MIT", 590 | "optional": true, 591 | "os": [ 592 | "darwin" 593 | ], 594 | "engines": { 595 | "node": ">= 10.0.0" 596 | }, 597 | "funding": { 598 | "type": "opencollective", 599 | "url": "https://opencollective.com/parcel" 600 | } 601 | }, 602 | "node_modules/@parcel/watcher-darwin-x64": { 603 | "version": "2.5.0", 604 | "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", 605 | "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", 606 | "cpu": [ 607 | "x64" 608 | ], 609 | "dev": true, 610 | "license": "MIT", 611 | "optional": true, 612 | "os": [ 613 | "darwin" 614 | ], 615 | "engines": { 616 | "node": ">= 10.0.0" 617 | }, 618 | "funding": { 619 | "type": "opencollective", 620 | "url": "https://opencollective.com/parcel" 621 | } 622 | }, 623 | "node_modules/@parcel/watcher-freebsd-x64": { 624 | "version": "2.5.0", 625 | "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", 626 | "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", 627 | "cpu": [ 628 | "x64" 629 | ], 630 | "dev": true, 631 | "license": "MIT", 632 | "optional": true, 633 | "os": [ 634 | "freebsd" 635 | ], 636 | "engines": { 637 | "node": ">= 10.0.0" 638 | }, 639 | "funding": { 640 | "type": "opencollective", 641 | "url": "https://opencollective.com/parcel" 642 | } 643 | }, 644 | "node_modules/@parcel/watcher-linux-arm-glibc": { 645 | "version": "2.5.0", 646 | "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", 647 | "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", 648 | "cpu": [ 649 | "arm" 650 | ], 651 | "dev": true, 652 | "license": "MIT", 653 | "optional": true, 654 | "os": [ 655 | "linux" 656 | ], 657 | "engines": { 658 | "node": ">= 10.0.0" 659 | }, 660 | "funding": { 661 | "type": "opencollective", 662 | "url": "https://opencollective.com/parcel" 663 | } 664 | }, 665 | "node_modules/@parcel/watcher-linux-arm-musl": { 666 | "version": "2.5.0", 667 | "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", 668 | "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", 669 | "cpu": [ 670 | "arm" 671 | ], 672 | "dev": true, 673 | "license": "MIT", 674 | "optional": true, 675 | "os": [ 676 | "linux" 677 | ], 678 | "engines": { 679 | "node": ">= 10.0.0" 680 | }, 681 | "funding": { 682 | "type": "opencollective", 683 | "url": "https://opencollective.com/parcel" 684 | } 685 | }, 686 | "node_modules/@parcel/watcher-linux-arm64-glibc": { 687 | "version": "2.5.0", 688 | "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", 689 | "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", 690 | "cpu": [ 691 | "arm64" 692 | ], 693 | "dev": true, 694 | "license": "MIT", 695 | "optional": true, 696 | "os": [ 697 | "linux" 698 | ], 699 | "engines": { 700 | "node": ">= 10.0.0" 701 | }, 702 | "funding": { 703 | "type": "opencollective", 704 | "url": "https://opencollective.com/parcel" 705 | } 706 | }, 707 | "node_modules/@parcel/watcher-linux-arm64-musl": { 708 | "version": "2.5.0", 709 | "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", 710 | "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", 711 | "cpu": [ 712 | "arm64" 713 | ], 714 | "dev": true, 715 | "license": "MIT", 716 | "optional": true, 717 | "os": [ 718 | "linux" 719 | ], 720 | "engines": { 721 | "node": ">= 10.0.0" 722 | }, 723 | "funding": { 724 | "type": "opencollective", 725 | "url": "https://opencollective.com/parcel" 726 | } 727 | }, 728 | "node_modules/@parcel/watcher-linux-x64-glibc": { 729 | "version": "2.5.0", 730 | "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", 731 | "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", 732 | "cpu": [ 733 | "x64" 734 | ], 735 | "dev": true, 736 | "license": "MIT", 737 | "optional": true, 738 | "os": [ 739 | "linux" 740 | ], 741 | "engines": { 742 | "node": ">= 10.0.0" 743 | }, 744 | "funding": { 745 | "type": "opencollective", 746 | "url": "https://opencollective.com/parcel" 747 | } 748 | }, 749 | "node_modules/@parcel/watcher-linux-x64-musl": { 750 | "version": "2.5.0", 751 | "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", 752 | "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", 753 | "cpu": [ 754 | "x64" 755 | ], 756 | "dev": true, 757 | "license": "MIT", 758 | "optional": true, 759 | "os": [ 760 | "linux" 761 | ], 762 | "engines": { 763 | "node": ">= 10.0.0" 764 | }, 765 | "funding": { 766 | "type": "opencollective", 767 | "url": "https://opencollective.com/parcel" 768 | } 769 | }, 770 | "node_modules/@parcel/watcher-win32-arm64": { 771 | "version": "2.5.0", 772 | "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", 773 | "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", 774 | "cpu": [ 775 | "arm64" 776 | ], 777 | "dev": true, 778 | "license": "MIT", 779 | "optional": true, 780 | "os": [ 781 | "win32" 782 | ], 783 | "engines": { 784 | "node": ">= 10.0.0" 785 | }, 786 | "funding": { 787 | "type": "opencollective", 788 | "url": "https://opencollective.com/parcel" 789 | } 790 | }, 791 | "node_modules/@parcel/watcher-win32-ia32": { 792 | "version": "2.5.0", 793 | "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", 794 | "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", 795 | "cpu": [ 796 | "ia32" 797 | ], 798 | "dev": true, 799 | "license": "MIT", 800 | "optional": true, 801 | "os": [ 802 | "win32" 803 | ], 804 | "engines": { 805 | "node": ">= 10.0.0" 806 | }, 807 | "funding": { 808 | "type": "opencollective", 809 | "url": "https://opencollective.com/parcel" 810 | } 811 | }, 812 | "node_modules/@parcel/watcher-win32-x64": { 813 | "version": "2.5.0", 814 | "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", 815 | "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", 816 | "cpu": [ 817 | "x64" 818 | ], 819 | "dev": true, 820 | "license": "MIT", 821 | "optional": true, 822 | "os": [ 823 | "win32" 824 | ], 825 | "engines": { 826 | "node": ">= 10.0.0" 827 | }, 828 | "funding": { 829 | "type": "opencollective", 830 | "url": "https://opencollective.com/parcel" 831 | } 832 | }, 833 | "node_modules/@sveltejs/acorn-typescript": { 834 | "version": "1.0.5", 835 | "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", 836 | "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", 837 | "dev": true, 838 | "license": "MIT", 839 | "peerDependencies": { 840 | "acorn": "^8.9.0" 841 | } 842 | }, 843 | "node_modules/@types/estree": { 844 | "version": "1.0.6", 845 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 846 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 847 | "dev": true, 848 | "license": "MIT" 849 | }, 850 | "node_modules/@types/node": { 851 | "version": "18.19.71", 852 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.71.tgz", 853 | "integrity": "sha512-evXpcgtZm8FY4jqBSN8+DmOTcVkkvTmAayeo4Wf3m1xAruyVGzGuDh/Fb/WWX2yLItUiho42ozyJjB0dw//Tkw==", 854 | "dev": true, 855 | "license": "MIT", 856 | "dependencies": { 857 | "undici-types": "~5.26.4" 858 | } 859 | }, 860 | "node_modules/acorn": { 861 | "version": "8.14.1", 862 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", 863 | "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", 864 | "dev": true, 865 | "license": "MIT", 866 | "bin": { 867 | "acorn": "bin/acorn" 868 | }, 869 | "engines": { 870 | "node": ">=0.4.0" 871 | } 872 | }, 873 | "node_modules/aria-query": { 874 | "version": "5.3.2", 875 | "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", 876 | "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", 877 | "dev": true, 878 | "license": "Apache-2.0", 879 | "engines": { 880 | "node": ">= 0.4" 881 | } 882 | }, 883 | "node_modules/axobject-query": { 884 | "version": "4.1.0", 885 | "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", 886 | "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", 887 | "dev": true, 888 | "license": "Apache-2.0", 889 | "engines": { 890 | "node": ">= 0.4" 891 | } 892 | }, 893 | "node_modules/braces": { 894 | "version": "3.0.3", 895 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 896 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 897 | "dev": true, 898 | "license": "MIT", 899 | "optional": true, 900 | "dependencies": { 901 | "fill-range": "^7.1.1" 902 | }, 903 | "engines": { 904 | "node": ">=8" 905 | } 906 | }, 907 | "node_modules/chokidar": { 908 | "version": "4.0.3", 909 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", 910 | "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", 911 | "dev": true, 912 | "license": "MIT", 913 | "dependencies": { 914 | "readdirp": "^4.0.1" 915 | }, 916 | "engines": { 917 | "node": ">= 14.16.0" 918 | }, 919 | "funding": { 920 | "url": "https://paulmillr.com/funding/" 921 | } 922 | }, 923 | "node_modules/clsx": { 924 | "version": "2.1.1", 925 | "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", 926 | "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", 927 | "dev": true, 928 | "license": "MIT", 929 | "engines": { 930 | "node": ">=6" 931 | } 932 | }, 933 | "node_modules/dequal": { 934 | "version": "2.0.3", 935 | "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", 936 | "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", 937 | "dev": true, 938 | "license": "MIT", 939 | "engines": { 940 | "node": ">=6" 941 | } 942 | }, 943 | "node_modules/detect-libc": { 944 | "version": "1.0.3", 945 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", 946 | "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", 947 | "dev": true, 948 | "license": "Apache-2.0", 949 | "optional": true, 950 | "bin": { 951 | "detect-libc": "bin/detect-libc.js" 952 | }, 953 | "engines": { 954 | "node": ">=0.10" 955 | } 956 | }, 957 | "node_modules/diff": { 958 | "version": "5.2.0", 959 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", 960 | "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", 961 | "dev": true, 962 | "license": "BSD-3-Clause", 963 | "engines": { 964 | "node": ">=0.3.1" 965 | } 966 | }, 967 | "node_modules/esbuild": { 968 | "version": "0.25.4", 969 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", 970 | "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", 971 | "dev": true, 972 | "hasInstallScript": true, 973 | "license": "MIT", 974 | "bin": { 975 | "esbuild": "bin/esbuild" 976 | }, 977 | "engines": { 978 | "node": ">=18" 979 | }, 980 | "optionalDependencies": { 981 | "@esbuild/aix-ppc64": "0.25.4", 982 | "@esbuild/android-arm": "0.25.4", 983 | "@esbuild/android-arm64": "0.25.4", 984 | "@esbuild/android-x64": "0.25.4", 985 | "@esbuild/darwin-arm64": "0.25.4", 986 | "@esbuild/darwin-x64": "0.25.4", 987 | "@esbuild/freebsd-arm64": "0.25.4", 988 | "@esbuild/freebsd-x64": "0.25.4", 989 | "@esbuild/linux-arm": "0.25.4", 990 | "@esbuild/linux-arm64": "0.25.4", 991 | "@esbuild/linux-ia32": "0.25.4", 992 | "@esbuild/linux-loong64": "0.25.4", 993 | "@esbuild/linux-mips64el": "0.25.4", 994 | "@esbuild/linux-ppc64": "0.25.4", 995 | "@esbuild/linux-riscv64": "0.25.4", 996 | "@esbuild/linux-s390x": "0.25.4", 997 | "@esbuild/linux-x64": "0.25.4", 998 | "@esbuild/netbsd-arm64": "0.25.4", 999 | "@esbuild/netbsd-x64": "0.25.4", 1000 | "@esbuild/openbsd-arm64": "0.25.4", 1001 | "@esbuild/openbsd-x64": "0.25.4", 1002 | "@esbuild/sunos-x64": "0.25.4", 1003 | "@esbuild/win32-arm64": "0.25.4", 1004 | "@esbuild/win32-ia32": "0.25.4", 1005 | "@esbuild/win32-x64": "0.25.4" 1006 | } 1007 | }, 1008 | "node_modules/esm-env": { 1009 | "version": "1.2.2", 1010 | "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", 1011 | "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", 1012 | "dev": true, 1013 | "license": "MIT" 1014 | }, 1015 | "node_modules/esrap": { 1016 | "version": "1.4.6", 1017 | "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.6.tgz", 1018 | "integrity": "sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==", 1019 | "dev": true, 1020 | "license": "MIT", 1021 | "dependencies": { 1022 | "@jridgewell/sourcemap-codec": "^1.4.15" 1023 | } 1024 | }, 1025 | "node_modules/fill-range": { 1026 | "version": "7.1.1", 1027 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1028 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1029 | "dev": true, 1030 | "license": "MIT", 1031 | "optional": true, 1032 | "dependencies": { 1033 | "to-regex-range": "^5.0.1" 1034 | }, 1035 | "engines": { 1036 | "node": ">=8" 1037 | } 1038 | }, 1039 | "node_modules/immutable": { 1040 | "version": "5.0.3", 1041 | "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", 1042 | "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", 1043 | "dev": true, 1044 | "license": "MIT" 1045 | }, 1046 | "node_modules/is-extglob": { 1047 | "version": "2.1.1", 1048 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1049 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1050 | "dev": true, 1051 | "license": "MIT", 1052 | "optional": true, 1053 | "engines": { 1054 | "node": ">=0.10.0" 1055 | } 1056 | }, 1057 | "node_modules/is-glob": { 1058 | "version": "4.0.3", 1059 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1060 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1061 | "dev": true, 1062 | "license": "MIT", 1063 | "optional": true, 1064 | "dependencies": { 1065 | "is-extglob": "^2.1.1" 1066 | }, 1067 | "engines": { 1068 | "node": ">=0.10.0" 1069 | } 1070 | }, 1071 | "node_modules/is-number": { 1072 | "version": "7.0.0", 1073 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1074 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1075 | "dev": true, 1076 | "license": "MIT", 1077 | "optional": true, 1078 | "engines": { 1079 | "node": ">=0.12.0" 1080 | } 1081 | }, 1082 | "node_modules/is-reference": { 1083 | "version": "3.0.3", 1084 | "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", 1085 | "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", 1086 | "dev": true, 1087 | "license": "MIT", 1088 | "dependencies": { 1089 | "@types/estree": "^1.0.6" 1090 | } 1091 | }, 1092 | "node_modules/kleur": { 1093 | "version": "4.1.5", 1094 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", 1095 | "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", 1096 | "dev": true, 1097 | "license": "MIT", 1098 | "engines": { 1099 | "node": ">=6" 1100 | } 1101 | }, 1102 | "node_modules/locate-character": { 1103 | "version": "3.0.0", 1104 | "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", 1105 | "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", 1106 | "dev": true, 1107 | "license": "MIT" 1108 | }, 1109 | "node_modules/magic-string": { 1110 | "version": "0.30.17", 1111 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1112 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1113 | "dev": true, 1114 | "license": "MIT", 1115 | "dependencies": { 1116 | "@jridgewell/sourcemap-codec": "^1.5.0" 1117 | } 1118 | }, 1119 | "node_modules/micromatch": { 1120 | "version": "4.0.8", 1121 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 1122 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 1123 | "dev": true, 1124 | "license": "MIT", 1125 | "optional": true, 1126 | "dependencies": { 1127 | "braces": "^3.0.3", 1128 | "picomatch": "^2.3.1" 1129 | }, 1130 | "engines": { 1131 | "node": ">=8.6" 1132 | } 1133 | }, 1134 | "node_modules/mri": { 1135 | "version": "1.2.0", 1136 | "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", 1137 | "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", 1138 | "dev": true, 1139 | "license": "MIT", 1140 | "engines": { 1141 | "node": ">=4" 1142 | } 1143 | }, 1144 | "node_modules/node-addon-api": { 1145 | "version": "7.1.1", 1146 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", 1147 | "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", 1148 | "dev": true, 1149 | "license": "MIT", 1150 | "optional": true 1151 | }, 1152 | "node_modules/picomatch": { 1153 | "version": "2.3.1", 1154 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1155 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1156 | "dev": true, 1157 | "license": "MIT", 1158 | "optional": true, 1159 | "engines": { 1160 | "node": ">=8.6" 1161 | }, 1162 | "funding": { 1163 | "url": "https://github.com/sponsors/jonschlinkert" 1164 | } 1165 | }, 1166 | "node_modules/prettier": { 1167 | "version": "3.5.3", 1168 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", 1169 | "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", 1170 | "dev": true, 1171 | "license": "MIT", 1172 | "bin": { 1173 | "prettier": "bin/prettier.cjs" 1174 | }, 1175 | "engines": { 1176 | "node": ">=14" 1177 | }, 1178 | "funding": { 1179 | "url": "https://github.com/prettier/prettier?sponsor=1" 1180 | } 1181 | }, 1182 | "node_modules/readdirp": { 1183 | "version": "4.1.1", 1184 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz", 1185 | "integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==", 1186 | "dev": true, 1187 | "license": "MIT", 1188 | "engines": { 1189 | "node": ">= 14.18.0" 1190 | }, 1191 | "funding": { 1192 | "type": "individual", 1193 | "url": "https://paulmillr.com/funding/" 1194 | } 1195 | }, 1196 | "node_modules/rewrite-imports": { 1197 | "version": "3.0.0", 1198 | "resolved": "https://registry.npmjs.org/rewrite-imports/-/rewrite-imports-3.0.0.tgz", 1199 | "integrity": "sha512-RClzg1cUfYLYkQadcrjgih8+CqJDKOP3OIWGkFE+e5n71085QnOwghzLPonEe1gG6iblCVJ8lHGFtd+n8wj3Hg==", 1200 | "dev": true, 1201 | "license": "MIT", 1202 | "engines": { 1203 | "node": ">=6" 1204 | } 1205 | }, 1206 | "node_modules/sade": { 1207 | "version": "1.8.1", 1208 | "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", 1209 | "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", 1210 | "dev": true, 1211 | "license": "MIT", 1212 | "dependencies": { 1213 | "mri": "^1.1.0" 1214 | }, 1215 | "engines": { 1216 | "node": ">=6" 1217 | } 1218 | }, 1219 | "node_modules/sass": { 1220 | "version": "1.83.4", 1221 | "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.4.tgz", 1222 | "integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==", 1223 | "dev": true, 1224 | "license": "MIT", 1225 | "dependencies": { 1226 | "chokidar": "^4.0.0", 1227 | "immutable": "^5.0.2", 1228 | "source-map-js": ">=0.6.2 <2.0.0" 1229 | }, 1230 | "bin": { 1231 | "sass": "sass.js" 1232 | }, 1233 | "engines": { 1234 | "node": ">=14.0.0" 1235 | }, 1236 | "optionalDependencies": { 1237 | "@parcel/watcher": "^2.4.1" 1238 | } 1239 | }, 1240 | "node_modules/source-map-js": { 1241 | "version": "1.2.1", 1242 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1243 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1244 | "dev": true, 1245 | "license": "BSD-3-Clause", 1246 | "engines": { 1247 | "node": ">=0.10.0" 1248 | } 1249 | }, 1250 | "node_modules/svelte": { 1251 | "version": "5.33.1", 1252 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.1.tgz", 1253 | "integrity": "sha512-7znzaaQALL62NBzkdKV04tmYIVla8qjrW+k6GdgFZcKcj8XOb8iEjmfRPo40iaWZlKv3+uiuc0h4iaGgwoORtA==", 1254 | "dev": true, 1255 | "license": "MIT", 1256 | "dependencies": { 1257 | "@ampproject/remapping": "^2.3.0", 1258 | "@jridgewell/sourcemap-codec": "^1.5.0", 1259 | "@sveltejs/acorn-typescript": "^1.0.5", 1260 | "@types/estree": "^1.0.5", 1261 | "acorn": "^8.12.1", 1262 | "aria-query": "^5.3.1", 1263 | "axobject-query": "^4.1.0", 1264 | "clsx": "^2.1.1", 1265 | "esm-env": "^1.2.1", 1266 | "esrap": "^1.4.6", 1267 | "is-reference": "^3.0.3", 1268 | "locate-character": "^3.0.0", 1269 | "magic-string": "^0.30.11", 1270 | "zimmerframe": "^1.1.2" 1271 | }, 1272 | "engines": { 1273 | "node": ">=18" 1274 | } 1275 | }, 1276 | "node_modules/svelte-preprocess-esbuild": { 1277 | "version": "3.0.1", 1278 | "resolved": "https://registry.npmjs.org/svelte-preprocess-esbuild/-/svelte-preprocess-esbuild-3.0.1.tgz", 1279 | "integrity": "sha512-OV4P/onki7hfuzIpYOd92TT0JSm4y67PvkAAM7RigLd869VEvNh2f6J+ewrEqAgTnZzVQcOWzuaU4hPISNPFpA==", 1280 | "dev": true, 1281 | "license": "MIT", 1282 | "engines": { 1283 | "node": ">=10" 1284 | }, 1285 | "peerDependencies": { 1286 | "esbuild": ">=0.14.0", 1287 | "svelte": ">=3.5.0" 1288 | } 1289 | }, 1290 | "node_modules/svelte-preprocess-filter": { 1291 | "version": "1.0.0", 1292 | "resolved": "https://registry.npmjs.org/svelte-preprocess-filter/-/svelte-preprocess-filter-1.0.0.tgz", 1293 | "integrity": "sha512-92innv59nyEx24xbfcSurB5ocwC8qFdDtGli/JVMHzJsxyvV2yjQKIcbUqU9VIV5mKUWO2PoY93nncS2yF4ULQ==", 1294 | "dev": true, 1295 | "license": "MIT" 1296 | }, 1297 | "node_modules/svelte-preprocess-sass": { 1298 | "version": "2.0.1", 1299 | "resolved": "https://registry.npmjs.org/svelte-preprocess-sass/-/svelte-preprocess-sass-2.0.1.tgz", 1300 | "integrity": "sha512-0y4FjRsRWcN7rJeNJnSfZ7LVAz6S7/j9Dg24XFRelr/rjMMjXORdEvXy4r38fUYmyk9Y7yjwlHCiqyGxMHhEbg==", 1301 | "dev": true, 1302 | "license": "MIT", 1303 | "dependencies": { 1304 | "svelte-preprocess-filter": "^1.0.0" 1305 | }, 1306 | "peerDependencies": { 1307 | "sass": "^1.35.2" 1308 | } 1309 | }, 1310 | "node_modules/to-regex-range": { 1311 | "version": "5.0.1", 1312 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1313 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1314 | "dev": true, 1315 | "license": "MIT", 1316 | "optional": true, 1317 | "dependencies": { 1318 | "is-number": "^7.0.0" 1319 | }, 1320 | "engines": { 1321 | "node": ">=8.0" 1322 | } 1323 | }, 1324 | "node_modules/typescript": { 1325 | "version": "5.7.3", 1326 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", 1327 | "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", 1328 | "dev": true, 1329 | "license": "Apache-2.0", 1330 | "bin": { 1331 | "tsc": "bin/tsc", 1332 | "tsserver": "bin/tsserver" 1333 | }, 1334 | "engines": { 1335 | "node": ">=14.17" 1336 | } 1337 | }, 1338 | "node_modules/undici-types": { 1339 | "version": "5.26.5", 1340 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 1341 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 1342 | "dev": true, 1343 | "license": "MIT" 1344 | }, 1345 | "node_modules/uvu": { 1346 | "version": "0.5.6", 1347 | "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", 1348 | "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", 1349 | "dev": true, 1350 | "license": "MIT", 1351 | "dependencies": { 1352 | "dequal": "^2.0.0", 1353 | "diff": "^5.0.0", 1354 | "kleur": "^4.0.3", 1355 | "sade": "^1.7.3" 1356 | }, 1357 | "bin": { 1358 | "uvu": "bin.js" 1359 | }, 1360 | "engines": { 1361 | "node": ">=8" 1362 | } 1363 | }, 1364 | "node_modules/zimmerframe": { 1365 | "version": "1.1.2", 1366 | "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", 1367 | "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", 1368 | "dev": true, 1369 | "license": "MIT" 1370 | } 1371 | } 1372 | } 1373 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esbuild-svelte", 3 | "version": "0.9.3", 4 | "description": "esbuild plugin to resolve .svelte files", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/EMH333/esbuild-svelte.git" 8 | }, 9 | "module": "dist/index.mjs", 10 | "main": "dist/index.js", 11 | "types": "dist/index.d.ts", 12 | "files": [ 13 | "/dist", 14 | "/CHANGELOG.md" 15 | ], 16 | "scripts": { 17 | "prepublishOnly": "git push origin --follow-tags", 18 | "postversion": "npm publish", 19 | "preversion": "npm run lint && npm run build && npm test && npm run test:compatibility", 20 | "pretest": "tsc -p tsconfig.json --noEmit", 21 | "test": "uvu test/ .*\\.mjs", 22 | "test:compatibility": "npm run build && test/versionTests/versionTests.sh", 23 | "build": "node build.js", 24 | "lint": "prettier --check --cache .", 25 | "fix": "prettier --write --cache ." 26 | }, 27 | "keywords": [ 28 | "svelte", 29 | "esbuild", 30 | "plugin" 31 | ], 32 | "author": { 33 | "name": "Ethan Hampton", 34 | "url": "https://www.ethohampton.com" 35 | }, 36 | "license": "MIT", 37 | "peerDependencies": { 38 | "esbuild": ">=0.17.0", 39 | "svelte": ">=4.2.1 <6" 40 | }, 41 | "devDependencies": { 42 | "@types/node": "^18.15.3", 43 | "esbuild": "^0.25.4", 44 | "prettier": "^3.4.0", 45 | "rewrite-imports": "^3.0.0", 46 | "sass": "^1.83.0", 47 | "svelte": "^5.19.0", 48 | "svelte-preprocess-esbuild": "^3.0.0", 49 | "svelte-preprocess-sass": "^2.0.1", 50 | "typescript": "^5.5.2", 51 | "uvu": "^0.5.6" 52 | }, 53 | "engines": { 54 | "node": ">=18" 55 | }, 56 | "dependencies": { 57 | "@jridgewell/trace-mapping": "^0.3.19" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/cacheTest.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { build, context } from "esbuild"; 4 | import { mkdirSync, unlinkSync, writeFileSync } from "fs"; 5 | import { sass } from "svelte-preprocess-sass"; 6 | import sveltePlugin from "../dist/index.mjs"; 7 | import { tmpdir } from "os"; 8 | import { join } from "path"; 9 | import commonOptions from "./commonOptions.js"; 10 | 11 | //with cache enabled 12 | test("Basic cache", async () => { 13 | await build({ 14 | ...commonOptions, 15 | entryPoints: ["./example-js/entry.js"], 16 | outdir: "../example-js/dist", 17 | plugins: [sveltePlugin({ cache: true })], 18 | }); 19 | }); 20 | 21 | async function incrementalTest() { 22 | let result = await context({ 23 | ...commonOptions, 24 | entryPoints: ["./example-js/entry.js"], 25 | outdir: "../example-js/dist", 26 | plugins: [sveltePlugin({ cache: true })], 27 | }); 28 | 29 | // Call "rebuild" as many times as you want 30 | for (let i = 0; i < 5; i++) { 31 | await result.rebuild(); 32 | } 33 | 34 | // Call "dispose" when you're done to free up resources. 35 | result.dispose(); 36 | } 37 | 38 | test("Cache w/ rebuild", async () => { 39 | await incrementalTest(); 40 | }); 41 | 42 | //set up a basic incremental build for use in other tests 43 | async function depsSetup(cacheType) { 44 | if (cacheType == undefined) { 45 | cacheType = true; 46 | } 47 | 48 | const dirname = join(tmpdir(), "esbuild-svelte"); 49 | mkdirSync(dirname, { recursive: true }); 50 | writeFileSync(join(dirname, "/app.js"), 'import x from "./foo.svelte"\nconsole.log(x)'); 51 | writeFileSync( 52 | join(dirname, "/foo.svelte"), 53 | '
foo
', 54 | ); 55 | 56 | // Set color to red 57 | writeFileSync(join(dirname, "/xyz.sass"), ".xyz\n color: red"); 58 | const result = await context({ 59 | ...commonOptions, 60 | entryPoints: [join(dirname, "/app.js")], 61 | outdir: "./dist", 62 | external: ["svelte/internal"], 63 | plugins: [ 64 | sveltePlugin({ 65 | preprocess: { 66 | style: sass(), 67 | }, 68 | cache: cacheType, 69 | }), 70 | ], 71 | logLevel: "silent", 72 | }); 73 | //make sure and build at least once 74 | let firstOut = await result.rebuild(); 75 | return { result, firstOut, dirname }; 76 | } 77 | 78 | test("Preprocess w/ deps basic", async () => { 79 | let { result, firstOut, dirname } = await depsSetup(); 80 | 81 | // Set color to green 82 | writeFileSync(join(dirname, "/xyz.sass"), ".xyz\n color: green"); 83 | const secondOut = await result.rebuild(); 84 | 85 | assert.match(firstOut.outputFiles[1].text, "red"); 86 | assert.match(secondOut.outputFiles[1].text, "green"); 87 | 88 | result.dispose(); 89 | }); 90 | 91 | test("Preprocess w/ deps delete", async () => { 92 | let { result, dirname } = await depsSetup(); 93 | 94 | // remove file 95 | unlinkSync(join(dirname, "/xyz.sass")); 96 | try { 97 | await result.rebuild(); 98 | assert.not.ok(true); 99 | } catch (err) { 100 | assert.ok(err.errors, "Rebuild should generate an exception when file deleted"); 101 | assert.not.match( 102 | err.errors[0].text, 103 | "stat", 104 | "`stat` shouldn't be generating the error message", 105 | ); 106 | assert.ok(err.errors.length == 1, "There should be one error"); 107 | } finally { 108 | result.dispose(); 109 | } 110 | }); 111 | 112 | test("Don't cache errors", async () => { 113 | let { result, dirname } = await depsSetup(); 114 | 115 | // remove file 116 | unlinkSync(join(dirname, "/xyz.sass")); 117 | try { 118 | await result.rebuild(); 119 | assert.not.ok(true); 120 | } catch (err) { 121 | assert.ok(err.errors); //expect to throw from rebuild 122 | } 123 | 124 | // bring it back 125 | // the previous error should go away 126 | writeFileSync(join(dirname, "/xyz.sass"), ".xyz\n color: green"); 127 | try { 128 | await result.rebuild(); 129 | assert.ok(true); 130 | } catch (err) { 131 | assert.not.ok(true); //expect to not to 132 | } finally { 133 | result.dispose(); 134 | } 135 | }); 136 | 137 | test.run(); 138 | -------------------------------------------------------------------------------- /test/commonOptions.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | format: "esm", 3 | minify: true, 4 | bundle: true, 5 | splitting: true, 6 | write: false, //Don't write anywhere 7 | mainFields: ["svelte", "browser", "module", "main"], 8 | conditions: ["svelte", "browser"], 9 | }; 10 | -------------------------------------------------------------------------------- /test/errors.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { build as _build } from "esbuild"; 4 | import { typescript } from "svelte-preprocess-esbuild"; 5 | import sveltePlugin from "../dist/index.mjs"; 6 | 7 | test("Errors (with preprocessors) are in the right spot", async () => { 8 | try { 9 | await _build({ 10 | entryPoints: ["./test/fixtures/errors/entry.js"], 11 | outdir: "../example/dist", 12 | bundle: true, 13 | write: false, //Don't write anywhere 14 | sourcemap: true, 15 | plugins: [ 16 | sveltePlugin({ 17 | preprocess: [typescript()], 18 | compilerOptions: { dev: true }, 19 | }), 20 | ], 21 | logLevel: "silent", 22 | }); 23 | } catch (e) { 24 | assert.equal(e.errors.length, 1, "Should have one error"); 25 | assert.equal(e.warnings.length, 0, "Should not have warnings"); 26 | 27 | const error = e.errors[0]; 28 | 29 | assert.equal( 30 | error.location.file, 31 | "test/fixtures/errors/error.svelte", 32 | "Should have the right file", 33 | ); 34 | assert.equal(error.location.line, 12, "Should have the right line"); 35 | assert.equal(error.location.column, 31, "Should have the right column"); 36 | assert.match( 37 | error.text, 38 | /Expected (value for the attribute|attribute value)/, 39 | "Should have the right error message", 40 | ); 41 | return; 42 | } 43 | 44 | assert.unreachable("Should have thrown an error"); 45 | }); 46 | 47 | test.run(); 48 | -------------------------------------------------------------------------------- /test/fixtures/errors/entry.js: -------------------------------------------------------------------------------- 1 | import Test from "./error.svelte"; 2 | 3 | new Test({ 4 | target: document.body, 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/errors/error.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/fixtures/errors/svelte.config.js: -------------------------------------------------------------------------------- 1 | const { typescript } = require("svelte-preprocess-esbuild"); 2 | const { sass } = require("svelte-preprocess-sass"); 3 | 4 | module.exports = { 5 | preprocess: [{ style: sass() }, typescript()], 6 | }; 7 | -------------------------------------------------------------------------------- /test/fixtures/include/entry.js: -------------------------------------------------------------------------------- 1 | import Test from "./include.notSvelte"; 2 | 3 | new Test({ 4 | target: document.body, 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/include/include.notSvelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 |
13 |

Hello World

14 |
15 | -------------------------------------------------------------------------------- /test/fixtures/non-ascii/entry.js: -------------------------------------------------------------------------------- 1 | import Test from "./non-ascii.svelte"; 2 | 3 | new Test({ 4 | target: document.body, 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/non-ascii/non-ascii.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | 12 |
13 |

Hello World © 2021 {y}

14 |
15 | -------------------------------------------------------------------------------- /test/fixtures/preprocessing-sourcemaps/pp-sourcemaps.js: -------------------------------------------------------------------------------- 1 | import Test from "./pp-sourcemaps.svelte"; 2 | 3 | new Test({ 4 | target: document.body, 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/preprocessing-sourcemaps/pp-sourcemaps.svelte: -------------------------------------------------------------------------------- 1 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 36 | -------------------------------------------------------------------------------- /test/fixtures/preprocessing-sourcemaps/sourcemapImport.scss: -------------------------------------------------------------------------------- 1 | button { 2 | font-size: 1.5rem; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/preprocessing-sourcemaps/svelte.config.js: -------------------------------------------------------------------------------- 1 | const { typescript } = require("svelte-preprocess-esbuild"); 2 | const { sass } = require("svelte-preprocess-sass"); 3 | 4 | module.exports = { 5 | preprocess: [{ style: sass() }, typescript()], 6 | }; 7 | -------------------------------------------------------------------------------- /test/fixtures/resolveDirectory/entry.js: -------------------------------------------------------------------------------- 1 | import Test from "./resDir.svelte"; 2 | 3 | new Test({ 4 | target: document.body, 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/resolveDirectory/fakeImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EMH333/esbuild-svelte/dd2a17b82b91a506a9286ec449a4d53863500a13/test/fixtures/resolveDirectory/fakeImage.png -------------------------------------------------------------------------------- /test/fixtures/resolveDirectory/resDir.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 |
13 |

Hello World

14 |
15 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/entry.js: -------------------------------------------------------------------------------- 1 | import { mount } from "svelte"; 2 | import Test from "./svelte5.svelte"; 3 | 4 | const test = mount(Test, { target: document.body }); 5 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/javascript-modules/entry.js: -------------------------------------------------------------------------------- 1 | import { mount } from "svelte"; 2 | import Test from "./svelte5.svelte"; 3 | 4 | const test = mount(Test, { target: document.body }); 5 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/javascript-modules/module.svelte.js: -------------------------------------------------------------------------------- 1 | export const counter = $state({ 2 | count: 0, 3 | }); 4 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/javascript-modules/svelte5.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/svelte5.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/typescript-modules/entry.ts: -------------------------------------------------------------------------------- 1 | import { mount } from "svelte"; 2 | import Test from "./svelte5.svelte"; 3 | 4 | const test = mount(Test, { target: document.body }); 5 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/typescript-modules/module.svelte.ts: -------------------------------------------------------------------------------- 1 | export const counter: { count: number } = $state({ 2 | count: 0, 3 | }); 4 | -------------------------------------------------------------------------------- /test/fixtures/svelte5/typescript-modules/svelte5.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /test/fixtures/ts-module-minification/entry.ts: -------------------------------------------------------------------------------- 1 | import { mount } from "svelte"; 2 | import Test from "./svelte5.svelte"; 3 | 4 | const test = mount(Test, { target: document.body }); 5 | -------------------------------------------------------------------------------- /test/fixtures/ts-module-minification/module.svelte.ts: -------------------------------------------------------------------------------- 1 | export const a1 = 1; 2 | export const a2 = 1; 3 | export const a3 = 1; 4 | export const a4 = 1; 5 | export const a5 = 1; 6 | export const a6 = 1; 7 | export const a7 = 1; 8 | export const a8 = 1; 9 | export const a9 = 1; 10 | export const a10 = 1; 11 | export const a11 = 1; 12 | export const a12 = 1; 13 | export const a13 = 1; 14 | export const a14 = 1; 15 | export const a15 = 1; 16 | export const a16 = 1; 17 | export const a17 = 1; 18 | export const a18 = 1; 19 | export const a19 = 1; 20 | export const a20 = 1; 21 | export const a21 = 1; 22 | export const a22 = 1; 23 | export const a23 = 1; 24 | export const a24 = 1; 25 | export const a25 = 1; 26 | export const a26 = 1; 27 | export const a27 = 1; 28 | export const a28 = 1; 29 | export const a29 = 1; 30 | export const a30 = 1; 31 | export const a31 = 1; 32 | export const a32 = 1; 33 | export const a33 = 1; 34 | export const a34 = 1; 35 | export const a35 = 1; 36 | export const a36 = 1; 37 | export const a37 = 1; 38 | export const a38 = 1; 39 | export const a39 = 1; 40 | export const a40 = 1; 41 | export const a41 = 1; 42 | export const a42 = 1; 43 | export const a43 = 1; 44 | export const a44 = 1; 45 | export const a45 = 1; 46 | export const a46 = 1; 47 | export const a47 = 1; 48 | export const a48 = 1; 49 | export const a49 = 1; 50 | export const a50 = 1; 51 | export const a51 = 1; 52 | export const a52 = 1; 53 | export const a53 = 1; 54 | export const a54 = 1; 55 | -------------------------------------------------------------------------------- /test/fixtures/ts-module-minification/svelte5.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /test/fixtures/warnings/entry.js: -------------------------------------------------------------------------------- 1 | import Test from "./missing-declaration.svelte"; 2 | 3 | new Test({ 4 | target: document.body, 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/warnings/missing-declaration.svelte: -------------------------------------------------------------------------------- 1 |
2 | 3 | {#if MY_GLOBAL} 4 | {/if} 5 | 6 | 7 | 8 |
9 | -------------------------------------------------------------------------------- /test/fixtures/watch-preprocessing/entry.js: -------------------------------------------------------------------------------- 1 | import Test from "./external-styles.svelte"; 2 | 3 | new Test({ 4 | target: document.body, 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/watch-preprocessing/external-styles.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |

Hello World

7 |

Testing this!

8 |
9 | -------------------------------------------------------------------------------- /test/fixtures/watch-preprocessing/external.scss: -------------------------------------------------------------------------------- 1 | p { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/includeOption.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { build } from "esbuild"; 4 | import sveltePlugin from "../dist/index.mjs"; 5 | import commonOptions from "./commonOptions.js"; 6 | 7 | test("Include option works correctly", async () => { 8 | const results = await build({ 9 | ...commonOptions, 10 | entryPoints: ["./test/fixtures/include/entry.js"], 11 | outdir: "../example/dist", 12 | sourcemap: "inline", 13 | plugins: [ 14 | sveltePlugin({ 15 | include: /\.notSvelte$/, 16 | }), 17 | ], 18 | }); 19 | 20 | assert.equal(results.errors.length, 0, "Expected zero errors"); 21 | assert.equal(results.warnings.length, 0, "Expected zero warnings"); 22 | assert.equal(results.outputFiles.length, 1, "Expected a single output file"); 23 | }); 24 | 25 | test.run(); 26 | -------------------------------------------------------------------------------- /test/non-ascii.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { build as _build } from "esbuild"; 4 | import { typescript } from "svelte-preprocess-esbuild"; 5 | import sveltePlugin from "../dist/index.mjs"; 6 | import commonOptions from "./commonOptions.js"; 7 | 8 | test("Can handle special characters in files", async () => { 9 | try { 10 | const results = await _build({ 11 | ...commonOptions, 12 | entryPoints: ["./test/fixtures/non-ascii/entry.js"], 13 | outdir: "../example/dist", 14 | sourcemap: true, 15 | plugins: [ 16 | sveltePlugin({ 17 | preprocess: typescript(), 18 | compilerOptions: { dev: true }, 19 | }), 20 | ], 21 | logLevel: "silent", 22 | }); 23 | assert.ok(true, "Should not have triggered exception"); 24 | assert.equal(results.warnings.length, 0, "Should not have warnings"); 25 | assert.equal(results.errors.length, 0, "Should not have errors"); 26 | } catch (err) { 27 | console.error(err.errors); 28 | assert.not.ok(err.errors, "Should not error because of invalid characters"); 29 | } 30 | }); 31 | 32 | test.run(); 33 | -------------------------------------------------------------------------------- /test/resolveDirectoryTest.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { build as _build } from "esbuild"; 4 | import { sass } from "svelte-preprocess-sass"; 5 | import sveltePlugin from "../dist/index.mjs"; 6 | import commonOptions from "./commonOptions.js"; 7 | 8 | test("Fake CSS returns correct resolve directory", async () => { 9 | //more advanced 10 | const results = await _build({ 11 | ...commonOptions, 12 | entryPoints: ["./test/fixtures/resolveDirectory/entry.js"], 13 | outdir: "../example/dist", 14 | sourcemap: "inline", 15 | loader: { 16 | ".png": "file", 17 | }, 18 | plugins: [ 19 | sveltePlugin({ 20 | preprocess: { 21 | style: sass(), 22 | }, 23 | }), 24 | ], 25 | }); 26 | 27 | assert.ok(results.errors.length === 0, "Non-zero number of errors"); 28 | assert.ok(results.warnings.length === 0, "Non-zero number of warnings"); 29 | assert.ok(results.outputFiles.length === 3, "Non-expected number of output files"); 30 | }); 31 | 32 | test.run(); 33 | -------------------------------------------------------------------------------- /test/simpleTest.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { build as _build } from "esbuild"; 4 | import sveltePlugin from "../dist/index.mjs"; 5 | import sveltePluginCJS from "../dist/index.js"; 6 | import commonOptions from "./commonOptions.js"; 7 | import { VERSION } from "svelte/compiler"; 8 | 9 | test("Without esbuild", async () => { 10 | let build = {}; 11 | //should have no errors or warnings 12 | build.onLoad = async function onLoad(selection, processor) { 13 | //ignore the css and direct import loaders for now 14 | if ( 15 | selection.filter.test("test.esbuild-svelte-fake-css") || 16 | selection.namespace === "esbuild-svelte-direct-import" 17 | ) { 18 | return; 19 | } 20 | 21 | let failed = false; 22 | let out = await processor({ path: "./example-js/index.svelte" }); 23 | 24 | if (out && out.warnings && out.warnings.length != 0) { 25 | console.error(out.warnings); 26 | failed = true; 27 | } 28 | if (out && out.errors && out.errors.length != 0) { 29 | console.error(out.errors); 30 | failed = true; 31 | } 32 | if (out && out.contents.length < 5) { 33 | console.error("Not the expected length"); 34 | failed = true; 35 | } 36 | 37 | assert.not.ok(failed); 38 | }; 39 | 40 | build.onResolve = async function (selection, processor) {}; 41 | build.onEnd = async function (callback) {}; 42 | build.initialOptions = { incremental: false, watch: false }; 43 | await sveltePlugin().setup(build); 44 | }); 45 | 46 | test("Simple build", async () => { 47 | //Try a simple esbuild build 48 | const results = await _build({ 49 | ...commonOptions, 50 | entryPoints: ["./example-js/entry.js"], 51 | outdir: "../example-js/dist", 52 | plugins: [sveltePlugin()], 53 | }); 54 | 55 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 56 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 57 | assert.equal(results.outputFiles.length, 2, "Non-expected number of output files"); 58 | }); 59 | 60 | test("Simple CommonJS build", async () => { 61 | //Try a simple esbuild build 62 | const results = await _build({ 63 | ...commonOptions, 64 | entryPoints: ["./example-js/entry.js"], 65 | outdir: "../example-js/dist", 66 | plugins: [sveltePluginCJS()], 67 | }); 68 | 69 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 70 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 71 | assert.equal(results.outputFiles.length, 2, "Non-expected number of output files"); 72 | }); 73 | 74 | test("More advanced build", async () => { 75 | //more advanced 76 | const results = await _build({ 77 | ...commonOptions, 78 | entryPoints: ["./example-js/entry.js"], 79 | outdir: "../example-js/dist", 80 | sourcemap: "inline", 81 | plugins: [sveltePlugin({ compilerOptions: { dev: true } })], 82 | }); 83 | 84 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 85 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 86 | assert.equal(results.outputFiles.length, 2, "Non-expected number of output files"); 87 | }); 88 | 89 | test("CSS external boolean", async () => { 90 | // TODO remove for svelte 5 91 | if (VERSION.startsWith("5")) { 92 | return; 93 | } 94 | 95 | //Note this fails on svelte v4 since booleans are deprecated and it has seemingly been broken 96 | //I'm not sure if this is a bug or not, but I'm going to choose to ignore this failure for now, 97 | //since there is an easy workaround (use a string instead of a boolean) 98 | const results = await _build({ 99 | ...commonOptions, 100 | entryPoints: ["./example-js/entry.js"], 101 | outdir: "../example-js/dist", 102 | sourcemap: "inline", 103 | plugins: [sveltePlugin({ compilerOptions: { dev: true, css: false } })], 104 | }); 105 | 106 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 107 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 108 | //assert.equal(results.outputFiles.length, 2, "Non-expected number of output files"); 109 | }); 110 | 111 | test("CSS external string", async () => { 112 | //more advanced 113 | const results = await _build({ 114 | ...commonOptions, 115 | entryPoints: ["./example-js/entry.js"], 116 | outdir: "../example-js/dist", 117 | sourcemap: "inline", 118 | plugins: [sveltePlugin({ compilerOptions: { dev: true, css: "external" } })], 119 | }); 120 | 121 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 122 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 123 | assert.equal(results.outputFiles.length, 2, "Non-expected number of output files"); 124 | }); 125 | 126 | // remove for svelte v5 127 | test("CSS injected boolean", async () => { 128 | // TODO remove for svelte 5 129 | if (VERSION.startsWith("5")) { 130 | return; 131 | } 132 | //TODO this should fail with a warning with svelte v4 133 | const results = await _build({ 134 | ...commonOptions, 135 | entryPoints: ["./example-js/entry.js"], 136 | outdir: "../example-js/dist", 137 | sourcemap: "inline", 138 | plugins: [sveltePlugin({ compilerOptions: { dev: true, css: true } })], 139 | }); 140 | 141 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 142 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 143 | assert.equal(results.outputFiles.length, 1, "Non-expected number of output files"); 144 | }); 145 | 146 | test("CSS injected string", async () => { 147 | //more advanced 148 | const results = await _build({ 149 | ...commonOptions, 150 | entryPoints: ["./example-js/entry.js"], 151 | outdir: "../example-js/dist", 152 | sourcemap: "inline", 153 | plugins: [sveltePlugin({ compilerOptions: { dev: true, css: "injected" } })], 154 | }); 155 | 156 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 157 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 158 | assert.equal(results.outputFiles.length, 1, "Non-expected number of output files"); 159 | }); 160 | 161 | test("CSS none", async () => { 162 | // TODO remove for svelte 5 163 | if (VERSION.startsWith("5")) { 164 | return; 165 | } 166 | 167 | //more advanced 168 | const results = await _build({ 169 | ...commonOptions, 170 | entryPoints: ["./example-js/entry.js"], 171 | outdir: "../example-js/dist", 172 | sourcemap: "inline", 173 | plugins: [sveltePlugin({ compilerOptions: { dev: true, css: "none" } })], 174 | }); 175 | 176 | assert.equal(results.errors.length, 0, "Non-zero number of errors"); 177 | assert.equal(results.warnings.length, 0, "Non-zero number of warnings"); 178 | assert.equal(results.outputFiles.length, 1, "Non-expected number of output files"); 179 | }); 180 | 181 | test.run(); 182 | -------------------------------------------------------------------------------- /test/sourcemapsTest.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { relative } from "path"; 4 | import { build } from "esbuild"; 5 | import { typescript } from "svelte-preprocess-esbuild"; 6 | import { sass } from "svelte-preprocess-sass"; 7 | import sveltePlugin from "../dist/index.mjs"; 8 | import commonOptions from "./commonOptions.js"; 9 | import { writeFileSync } from "fs"; 10 | 11 | test("Preprocessor Sourcemap test", async () => { 12 | const result = await build({ 13 | ...commonOptions, 14 | entryPoints: ["./test/fixtures/preprocessing-sourcemaps/pp-sourcemaps.js"], 15 | outdir: "../example/dist", 16 | sourcemap: "external", 17 | outdir: "out", 18 | plugins: [sveltePlugin({ preprocess: [{ style: sass() }, typescript()] })], 19 | logLevel: "silent", 20 | }); 21 | 22 | assert.equal(result.warnings.length, 1, "Should one warning"); // because of warnings tests 23 | assert.equal(result.errors.length, 0, "Should not have errors"); 24 | 25 | assert.equal(result.outputFiles.length, 4); 26 | 27 | for (let out of result.outputFiles) { 28 | if (relative(process.cwd(), out.path) === "out/pp-sourcemaps.js.map") { 29 | const json = JSON.parse(out.text); 30 | 31 | //console.log(out.text); 32 | assert.match(out.text, / 9 | 10 | 21 | 22 |
23 | 25 | 26 |
27 | 28 |
29 | 30 |

Hello World © 2021 {y}

31 |
32 | -------------------------------------------------------------------------------- /test/versionTests/test.js: -------------------------------------------------------------------------------- 1 | import { existsSync, mkdirSync } from "fs"; 2 | import { build } from "esbuild"; 3 | import sveltePlugin from "./index.mjs"; 4 | 5 | const esbuildVersion = process.argv[2]; 6 | const svelteVersion = process.argv[3]; 7 | 8 | //make sure the directoy exists before stuff gets put into it 9 | if (!existsSync("./dist/")) { 10 | mkdirSync("./dist/"); 11 | } 12 | 13 | //build the application 14 | build({ 15 | entryPoints: [Number(svelteVersion.at(0)) >= 5 ? "./entry5.js" : "./entry.js"], 16 | mainFields: ["svelte", "browser", "module", "main"], 17 | conditions: ["svelte", "browser"], 18 | target: "es2016", 19 | outdir: "./dist", 20 | format: "esm", 21 | logLevel: "info", 22 | minify: false, //so the resulting code is easier to understand 23 | bundle: true, 24 | splitting: true, 25 | sourcemap: "external", 26 | plugins: [sveltePlugin()], 27 | }) 28 | .then((results) => { 29 | if (results.warnings.length > 0) { 30 | console.error( 31 | "Build had warnings with esbuild version " + 32 | esbuildVersion + 33 | " and svelte version " + 34 | svelteVersion, 35 | ); 36 | process.exit(1); 37 | } 38 | }) 39 | .catch((err) => { 40 | console.error(err); 41 | console.error( 42 | "Build failed with esbuild version " + 43 | esbuildVersion + 44 | " and svelte version " + 45 | svelteVersion, 46 | ); 47 | process.exit(1); 48 | }); 49 | -------------------------------------------------------------------------------- /test/versionTests/versionTests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Test esbuild and svelte versions for compability using the example-js project files 4 | 5 | # cd to script directory 6 | cd "$(dirname "$0")" || exit 7 | 8 | # copy esbuild-svelte to destination 9 | cp ../../dist/index.mjs . 10 | 11 | npm init -y || exit 12 | npm pkg set type="module" || exit 13 | 14 | # array of versions 15 | ESBUILD_VERSIONS=("0.17.19" "0.18.10" "0.19.2" "0.21.3" "0.24.0") 16 | SVELTE_VERSIONS=("4.2.1" "5.0.3" "5.1.3") 17 | 18 | # loop through versions 19 | for ESBUILD_VERSION in "${ESBUILD_VERSIONS[@]}" 20 | do 21 | for SVELTE_VERSION in "${SVELTE_VERSIONS[@]}" 22 | do 23 | echo "Testing esbuild@$ESBUILD_VERSION and svelte@$SVELTE_VERSION" 24 | 25 | # install esbuild and svelte versions 26 | npm install esbuild@"$ESBUILD_VERSION" svelte@"$SVELTE_VERSION" || exit 27 | 28 | # run test script 29 | node test.js "$ESBUILD_VERSION" "$SVELTE_VERSION" || exit 30 | done 31 | done 32 | 33 | # remove temp files 34 | rm index.mjs package.json package-lock.json 35 | rm -r dist/ node_modules/ 36 | -------------------------------------------------------------------------------- /test/warnings.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { build as _build } from "esbuild"; 4 | import { typescript } from "svelte-preprocess-esbuild"; 5 | import { sass } from "svelte-preprocess-sass"; 6 | import sveltePlugin from "../dist/index.mjs"; 7 | import commonOptions from "./commonOptions.js"; 8 | 9 | test("Can filter out warnings", async () => { 10 | const resultsWithoutFilter = await _build({ 11 | ...commonOptions, 12 | entryPoints: ["./test/fixtures/warnings/entry.js"], 13 | outdir: "../example/dist", 14 | sourcemap: true, 15 | plugins: [ 16 | sveltePlugin({ 17 | preprocess: typescript(), 18 | compilerOptions: { dev: true }, 19 | }), 20 | ], 21 | logLevel: "silent", 22 | }); 23 | 24 | const resultsWithFilter = await _build({ 25 | ...commonOptions, 26 | entryPoints: ["./test/fixtures/warnings/entry.js"], 27 | outdir: "../example/dist", 28 | sourcemap: true, 29 | plugins: [ 30 | sveltePlugin({ 31 | preprocess: typescript(), 32 | compilerOptions: { dev: true }, 33 | filterWarnings: (warning) => { 34 | // Ignore warning about the empty if block. 35 | if ( 36 | warning.code === "block_empty" && 37 | warning.message.startsWith("Empty block") 38 | ) { 39 | return false; 40 | } 41 | 42 | return true; 43 | }, 44 | }), 45 | ], 46 | logLevel: "silent", 47 | }); 48 | 49 | assert.equal(resultsWithoutFilter.warnings.length, 2, "Should have two warnings"); 50 | assert.equal(resultsWithoutFilter.errors.length, 0, "Should not have errors"); 51 | assert.equal(resultsWithFilter.warnings.length, 1, "Should have one warning"); 52 | assert.equal( 53 | resultsWithFilter.warnings[0].text, 54 | "`` element should have an alt attribute\nhttps://svelte.dev/e/a11y_missing_attribute", 55 | "The not filtered warning is still there", 56 | ); 57 | assert.equal(resultsWithFilter.errors.length, 0, "Should not have errors"); 58 | }); 59 | 60 | test("Warnings are in the right spot", async () => { 61 | const results = await _build({ 62 | entryPoints: ["./test/fixtures/warnings/entry.js"], 63 | outdir: "../example/dist", 64 | bundle: true, 65 | write: false, //Don't write anywhere 66 | sourcemap: true, 67 | plugins: [ 68 | sveltePlugin({ 69 | preprocess: typescript(), 70 | compilerOptions: { dev: true }, 71 | }), 72 | ], 73 | logLevel: "silent", 74 | }); 75 | 76 | assert.equal(results.warnings.length, 2, "Should have two warnings"); 77 | assert.equal(results.errors.length, 0, "Should not have errors"); 78 | assert.equal(results.warnings[0].location.column, 16, "Column is correct"); 79 | assert.equal(results.warnings[0].location.line, 3, "Line is correct"); 80 | assert.equal(results.warnings[0].location.length, 1, "Length is correct"); 81 | assert.equal( 82 | results.warnings[0].location.lineText, 83 | " {#if MY_GLOBAL}", 84 | "Line text is correct", 85 | ); 86 | assert.match(results.warnings[0].text, /Empty block/); 87 | }); 88 | 89 | test("Preprocessor warnings are as expected", async () => { 90 | const results = await _build({ 91 | entryPoints: ["./test/fixtures/preprocessing-sourcemaps/pp-sourcemaps.js"], 92 | outdir: "../example/dist", 93 | format: "esm", 94 | minify: true, 95 | bundle: true, 96 | splitting: true, 97 | write: false, //Don't write anywhere 98 | sourcemap: "external", 99 | outdir: "out", 100 | plugins: [sveltePlugin({ preprocess: [{ style: sass() }, typescript()] })], 101 | logLevel: "silent", 102 | }); 103 | 104 | assert.equal(results.outputFiles.length, 4); 105 | assert.equal(results.warnings.length, 1, "Should have one warnings"); 106 | assert.equal(results.errors.length, 0, "Should not have errors"); 107 | 108 | assert.equal(results.warnings[0].location.column, 0, "Column is correct"); 109 | assert.equal(results.warnings[0].location.line, 25, "Line is correct"); 110 | assert.equal(results.warnings[0].location.length, 21, "Length is correct"); 111 | }); 112 | 113 | test.run(); 114 | -------------------------------------------------------------------------------- /test/watchPreprocessingTest.mjs: -------------------------------------------------------------------------------- 1 | import { test } from "uvu"; 2 | import * as assert from "uvu/assert"; 3 | import { writeFileSync } from "fs"; 4 | import { fileURLToPath } from "url"; 5 | import { dirname } from "path"; 6 | import { context } from "esbuild"; 7 | import { sass } from "svelte-preprocess-sass"; 8 | import sveltePlugin from "../dist/index.mjs"; 9 | import commonOptions from "./commonOptions.js"; 10 | 11 | const __filename = fileURLToPath(import.meta.url); 12 | const __dirname = dirname(__filename); 13 | 14 | test("Watch and build while preprocess of external dependency succeed and fails", async () => { 15 | function _createDeferred() { 16 | let resolve = null; 17 | let reject = null; 18 | const promise = new Promise((_resolve, _reject) => { 19 | resolve = _resolve; 20 | reject = _reject; 21 | }); 22 | promise.forceResolve = resolve; 23 | promise.forceReject = reject; 24 | return promise; 25 | } 26 | 27 | let count = 0; 28 | const firstRebuild = _createDeferred(); 29 | const secondRebuild = _createDeferred(); 30 | 31 | //more advanced 32 | const results = await context({ 33 | ...commonOptions, 34 | entryPoints: ["./test/fixtures/watch-preprocessing/entry.js"], 35 | outdir: "../example/dist", 36 | sourcemap: "inline", 37 | logLevel: "silent", 38 | plugins: [ 39 | sveltePlugin({ 40 | preprocess: { 41 | style: sass(), 42 | }, 43 | }), 44 | { 45 | // this plugin will pass the result back to the promises 46 | name: "watch-preprocessing", 47 | setup(build) { 48 | build.onEnd((result) => { 49 | count++; 50 | if (count === 3) { 51 | firstRebuild.forceResolve(result); 52 | } else if (count === 4) { 53 | secondRebuild.forceResolve(result); 54 | } 55 | }); 56 | }, 57 | }, 58 | ], 59 | }); 60 | 61 | await results.rebuild(); // have to do an initial build to prime everything 62 | await results.rebuild(); // do one more good build to start caching 63 | 64 | // start watching 65 | results.watch().catch((err) => { 66 | console.error(err); 67 | }); 68 | 69 | try { 70 | // write external scss with invalid syntax 71 | writeFileSync( 72 | `${__dirname}/fixtures/watch-preprocessing/external.scss`, 73 | "p { color: red; }!$%^&*()@$%^@@", 74 | ); 75 | const firstRebuildResult = await firstRebuild; 76 | assert.ok(firstRebuildResult.errors.length !== 0, "First build did not fail"); 77 | 78 | // write external scss with valid syntax again 79 | writeFileSync( 80 | `${__dirname}/fixtures/watch-preprocessing/external.scss`, 81 | "p {\n color: red;\n}\n", 82 | ); 83 | const secondRebuildResult = await secondRebuild; 84 | assert.ok(secondRebuildResult.errors.length === 0, "Second build fail"); 85 | } finally { 86 | // stop watching 87 | results.dispose(); 88 | } 89 | }); 90 | 91 | test.run(); 92 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2016", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "declaration": true, 9 | "skipLibCheck": true 10 | }, 11 | "files": ["index.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 0.9.3 2 | --------------------------------------------------------------------------------