diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7712e328..17f1995a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,67 +1,72 @@
-## [3.9.12](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.11...v3.9.12) (2020-07-05)
-
+# [4.0.0](https://github.com/sveltejs/svelte-preprocess/compare/v4.0.0-alpha.2...v4.0.0) (2020-07-07)
### Bug Fixes
-* ๐ set bare option to true ([312bbb9](https://github.com/kaisermann/svelte-preprocess/commit/312bbb9bbf2668e1750296dbfc8b83bb39f291e8))
+- ๐ try to use sass before node-sass ([89aba0e](https://github.com/sveltejs/svelte-preprocess/commit/89aba0e6f03208787cdb7e212979634089405c15)), closes [#163](https://github.com/sveltejs/svelte-preprocess/issues/163)
+* ๐ bump minimum node version to 9.11.2 ([0befa7f](https://github.com/sveltejs/svelte-preprocess/commit/0befa7f4ff2aa3ba9f0129c3ed3994dd29fb991b))
+* ๐ prevent globalify to wrongly split escaped selectors ([f461320](https://github.com/sveltejs/svelte-preprocess/commit/f461320ec05a534021afbe20de0fe097d1016871)), closes [#191](https://github.com/sveltejs/svelte-preprocess/issues/191)
+* ๐ rename scss prepend option from `data` to `prependData` ([16b1325](https://github.com/sveltejs/svelte-preprocess/commit/16b13253bdf19073c084cb1590ed527695133836))
+### Code Refactoring
-## [3.9.11](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.10...v3.9.11) (2020-07-01)
-
+- ๐ก remove deprecated autoProcess props ([3dce7e4](https://github.com/sveltejs/svelte-preprocess/commit/3dce7e432fb15fc27914f5e1524b46929d84bd2c))
-### Bug Fixes
-
-* ๐ log a warning if local external file is not found ([774aece](https://github.com/kaisermann/svelte-preprocess/commit/774aece08a5279a51707d3f428836169fc7735de)), closes [#174](https://github.com/kaisermann/svelte-preprocess/issues/174)
+### Features
+- ๐ธ add sourceMap prop to configuration object ([a2505da](https://github.com/sveltejs/svelte-preprocess/commit/a2505da88ba025040d7069fd499c4d759a1fcb72))
+- ๐ธ support defining default languages ([d86122f](https://github.com/sveltejs/svelte-preprocess/commit/d86122f41a5616b7053dce26d7cf7c58ee025e1d)), closes [#189](https://github.com/sveltejs/svelte-preprocess/issues/189)
+- ๐ธ support markup preprocessing with no tags ([290ef98](https://github.com/sveltejs/svelte-preprocess/commit/290ef98aad8a218880f5c511d11ad562e1869b35))
+- ๐ธ support prependData for almost every preprocessor ([ef5272e](https://github.com/sveltejs/svelte-preprocess/commit/ef5272eceae1237af26d18aaf209ec68c6c43c6e))
+### BREAKING CHANGES
-## [3.9.11](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.10...v3.9.11) (2020-07-01)
+- ๐งจ This is a general evolution of the specific `scss.data` property that
+ was used to prepend data to components written in scss.
+ `{preprocessorOptions}.prependData` is now the way to prepend some
+ string to any preprocessor.
+- ๐งจ Node versions below 9.11.2 won't be supported anymore
+- ๐งจ Uses Lookbehind assertions, so Node 9.11.2+ is needed
+- ๐งจ Content passed through the `data` property won't be prepended anymore.
+- ๐งจ `onBefore` and `transformers` were removed
+## [3.9.12](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.11...v3.9.12) (2020-07-05)
### Bug Fixes
-* ๐ log a warning if local external file is not found ([774aece](https://github.com/kaisermann/svelte-preprocess/commit/774aece08a5279a51707d3f428836169fc7735de)), closes [#174](https://github.com/kaisermann/svelte-preprocess/issues/174)
+- ๐ set bare option to true ([312bbb9](https://github.com/kaisermann/svelte-preprocess/commit/312bbb9bbf2668e1750296dbfc8b83bb39f291e8))
+## [3.9.11](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.10...v3.9.11) (2020-07-01)
+### Bug Fixes
-## [3.9.10](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.9...v3.9.10) (2020-06-22)
+- ๐ log a warning if local external file is not found ([774aece](https://github.com/kaisermann/svelte-preprocess/commit/774aece08a5279a51707d3f428836169fc7735de)), closes [#174](https://github.com/kaisermann/svelte-preprocess/issues/174)
+## [3.9.10](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.9...v3.9.10) (2020-06-22)
### Bug Fixes
-* remove extra identation for sass content ([7d0f437](https://github.com/kaisermann/svelte-preprocess/commit/7d0f4376037d1ff6b426e2d6882adb6b08d95464))
-
-
+- remove extra identation for sass content ([7d0f437](https://github.com/kaisermann/svelte-preprocess/commit/7d0f4376037d1ff6b426e2d6882adb6b08d95464))
## [3.9.9](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.7...v3.9.9) (2020-06-19)
-
### Bug Fixes
-* ๐ prevent including external file if content is not empty ([24e90d1](https://github.com/kaisermann/svelte-preprocess/commit/24e90d101103b043d4b9e9789d2d6582ecf31ae8)), closes [#183](https://github.com/kaisermann/svelte-preprocess/issues/183)
-* ๐ throw if type errors are found ([6545a5c](https://github.com/kaisermann/svelte-preprocess/commit/6545a5c13ff81a568714cbd83ae2d6127d4f61a4)), closes [#182](https://github.com/kaisermann/svelte-preprocess/issues/182)
-
-
+- ๐ prevent including external file if content is not empty ([24e90d1](https://github.com/kaisermann/svelte-preprocess/commit/24e90d101103b043d4b9e9789d2d6582ecf31ae8)), closes [#183](https://github.com/kaisermann/svelte-preprocess/issues/183)
+- ๐ throw if type errors are found ([6545a5c](https://github.com/kaisermann/svelte-preprocess/commit/6545a5c13ff81a568714cbd83ae2d6127d4f61a4)), closes [#182](https://github.com/kaisermann/svelte-preprocess/issues/182)
## [3.9.8](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.7...v3.9.8) (2020-06-17)
-
### Bug Fixes
-* ๐ prevent including external file if content is not empty ([fd1b55a](https://github.com/kaisermann/svelte-preprocess/commit/fd1b55a557eb4db43adb4af3a3c8be63584f7288)), closes [#183](https://github.com/kaisermann/svelte-preprocess/issues/183)
-
-
+- ๐ prevent including external file if content is not empty ([fd1b55a](https://github.com/kaisermann/svelte-preprocess/commit/fd1b55a557eb4db43adb4af3a3c8be63584f7288)), closes [#183](https://github.com/kaisermann/svelte-preprocess/issues/183)
## [3.9.7](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.6...v3.9.7) (2020-06-10)
-
### Bug Fixes
-* ๐ attributes not being passed to transformers ([840239d](https://github.com/kaisermann/svelte-preprocess/commit/840239d225f1ef0b7b642830093a8b6745d11ceb)), closes [#175](https://github.com/kaisermann/svelte-preprocess/issues/175)
-* quotes in the release script ([#173](https://github.com/kaisermann/svelte-preprocess/issues/173)) ([5550b3e](https://github.com/kaisermann/svelte-preprocess/commit/5550b3eea390148e9e5683ec214bddae7531a405))
-
-
+- ๐ attributes not being passed to transformers ([840239d](https://github.com/kaisermann/svelte-preprocess/commit/840239d225f1ef0b7b642830093a8b6745d11ceb)), closes [#175](https://github.com/kaisermann/svelte-preprocess/issues/175)
+- quotes in the release script ([#173](https://github.com/kaisermann/svelte-preprocess/issues/173)) ([5550b3e](https://github.com/kaisermann/svelte-preprocess/commit/5550b3eea390148e9e5683ec214bddae7531a405))
## [3.9.6](https://github.com/kaisermann/svelte-preprocess/compare/v3.9.4...v3.9.6) (2020-06-06)
diff --git a/README.md b/README.md
index 3b3facf5..755d3fbd 100644
--- a/README.md
+++ b/README.md
@@ -1,57 +1,55 @@
-
-
# Svelte Preprocess
-> A [Svelte](https://svelte.dev) preprocessor with support for: PostCSS, SCSS, Less, Stylus, Coffeescript, TypeScript and Pug.
+> A [Svelte](https://svelte.dev) preprocessor with sensible defaults and support for: PostCSS, SCSS, Less, Stylus, CoffeeScript, TypeScript, Pug and much more.
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
-- [Installation](#installation)
+- [What is it?](#what-is-it)
+- [Getting Started](docs/getting-started.md)
+- [Usage](docs/usage.md)
+- [Migration Guide](docs/migration-guide.md)
+- [Preprocessing](docs/preprocessing.md)
+ - [Preprocessors](docs/preprocessing.md#preprocessors)
- [Features](#features)
- [Template tag](#template-tag)
- [External files](#external-files)
- [Global style](#global-style)
- - [Global rule](#global-rule)
- - [Preprocessors](#preprocessors)
- - [Modern Javascript syntax](#modern-javascript-syntax)
+ - [Modern JavaScript syntax](#modern-javascript-syntax)
- [Replace values](#replace-values)
-- [Usage](#usage)
- - [With `rollup-plugin-svelte`](#with-rollup-plugin-svelte)
- - [With `svelte-loader`](#with-svelte-loader)
- - [With Sapper](#with-sapper)
- - [With Svelte VS Code](#with-svelte-vs-code)
-- [Preprocessing modes](#preprocessing-modes)
- - [Auto Preprocessing](#auto-preprocessing)
- - [Standalone processors](#standalone-processors)
-- [Options](#options)
-- [Specifics and limitations](#specifics-and-limitations)
- - [`scss`/`sass`](#scsssass)
- - [`typescript`](#typescript)
- - [`pug`](#pug)
- - [`coffeescript`](#coffeescript)
-- [FAQ](#faq)
- - [My VS Code is displaying a lot of errors on my templates when I try to use `x`...](#my-vs-code-is-displaying-a-lot-of-errors-on-my-templates-when-i-try-to-use-x)
- - [My `typescript` compilation is sloooooooow](#my-typescript-compilation-is-sloooooooow)
-
-
-
-## Installation
-
-`npm install -D svelte-preprocess`
-
-The preprocessor module installation is up to the developer.
-
-- `babel`: `npm install -D @babel/core @babel/preset-...`
-- `coffeescript`: `npm install -D coffeescript`
-- `typescript`: `npm install -D typescript`
-- `postcss`: `npm install -D postcss postcss-load-config`
-- `less`: `npm install -D less`
-- `sass`: `npm install -D node-sass` or `npm install -D sass`
-- `pug`: `npm install -D pug`
-- `stylus`: `npm install -D stylus`
-
-_Note: If you want to load your `postcss` configuration from a external file, make sure to also install `postcss-load-config`._
+ - [Built-in support for commonly used languages](#built-in-support-for-commonly-used-languages)
+
+## What is it?
+
+`Svelte`'s own parser understands only JavaScript, CSS and its HTML-like syntax. To make it possible to write components in other languages, such as TypeScript or SCSS, `Svelte` provides the [preprocess API](https://svelte.dev/docs#svelte_preprocess), which allows to easily transform the content of your `markup` and your `style`/`script` tags.
+
+Writing your own preprocessor for, i.e SCSS is easy enough, but it can be cumbersome to have to always configure multiple preprocessors for the languages you'll be using.
+
+`svelte-preprocess` is a custom svelte preprocessor that acts as a facilitator to use other languages with Svelte, providing multiple features, sensible defaults and a less noisy development experience.
+
+```js
+import svelte from 'rollup-plugin-svelte'
+import autoPreprocess from 'svelte-preprocess'
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess({ ... })
+ })
+ ]
+}
+```
## Features
@@ -59,7 +57,7 @@ _Note: If you want to load your `postcss` configuration from a external file, ma
Add _vue-like_ support for defining your markup between a `` tag. The tagname can be customized to something like `markup` for example. See [#options](#options).
-_Note: only for auto preprocessing_
+_**Note:** only for auto preprocessing_
```html
@@ -81,6 +79,8 @@ _Note: only for auto preprocessing_
### Global style
+#### `global` attribute
+
Add a `global` attribute to your `style` tag and instead of scoping the CSS, all of its content will be interpreted as global style.
```html
@@ -91,13 +91,7 @@ Add a `global` attribute to your `style` tag and instead of scoping the CSS, all
```
-_Note1: needs PostCSS to be installed._
-
-_Note2: if you're using it as a standalone processor, it works best if added to the end of the processors array._
-
-_Note3: if you need to have some styles be scoped inside a global style tag, use `:local` in the same way you'd use `:global`._
-
-### Global rule
+#### `:global` rule
Use a `:global` rule to only expose parts of the stylesheet:
@@ -119,43 +113,11 @@ Use a `:global` rule to only expose parts of the stylesheet:
Works best with nesting-enabled CSS preprocessors, but regular CSS selectors like `div :global .global1 .global2` are also supported.
-_Note1: needs PostCSS to be installed._
-
-_Note2: if you're using it as a standalone processor, it works best if added to the end of the processors array._
-
-_Note3: wrapping `@keyframes` inside `:global {}` blocks is not supported. Use the [`-global-` name prefix for global keyframes](https://svelte.dev/docs#style)._
-
-### Preprocessors
-
-Current supported out-of-the-box preprocessors are `SCSS`, `Stylus`, `Less`, `Coffeescript`, `TypeScript`, `Pug`, `PostCSS`, `Babel`.
-
-```html
-
- div Posts
- +each('posts as post')
- a(href="{post.url}") {post.title}
-
-
-
-
-
-
-
+_**Note**: needs PostCSS to be installed._
-
-```
+### Modern JavaScript syntax
-### Modern Javascript syntax
-
-`svelte-preprocess` allows you to run your component code through `babel` before sending it to the compiler, allowing you to use new language features such as optional operators and nullish coalescing. However, note that `babel` should transpile your component code to the javascript version supported by the Svelte compiler, so ES6+.
+`svelte-preprocess` allows you to run your component code through Babel before sending it to the compiler, allowing you to use new language features such as optional operators and nullish coalescing. However, note that Babel should transpile your component code to the javascript version supported by the Svelte compiler, so ES6+.
For example, with `@babel/preset-env` your config could be:
@@ -183,36 +145,29 @@ import preprocess from 'svelte-preprocess'
...
```
-_Note: If you want to transpile your app to be supported in older browsers, you must run babel from the context of your bundler._
+_**Note:** If you want to transpile your app to be supported in older browsers, you must run babel from the context of your bundler._
### Replace values
Replace a set of string patterns in your components markup by passing an array of `[RegExp, ReplaceFn | string]`, the same arguments received by the `String.prototype.replace` method.
-In example, to add `process.env.{prop}` value resolution and a custom `@if/@endif` if-block shorthand, one could do:
+In example, to replace inject the value of `process.env.NODE_ENV`:
```js
-sveltePreprocess({
- replace: [
- [
- /process\.env\.(\w+)/g,
- (_:, prop) => JSON.stringify(process.env[prop]),
- ],
- [/@if\s*\((.*?)\)$/gim, '{#if $1}'],
- [/@endif$/gim, '{/if}'],
- ],
+autoPreprocess({
+ replace: ['process.env.NODE_ENV', JSON.stringify(process.env.NODE_ENV)],
});
```
-Which allows to write your component like:
+Which, in a production environment, would turn
-```html
-@if(process.env.NODE_ENV !== 'development')
-Production environment!
-@endif
+```svelte
+{#if process.env.NODE_ENV !== 'development'}
+ Production environment!
+{/if}
```
-And the result, for a `NODE_ENV = 'production'` would be:
+into
```svelte
{#if "production" !== 'development'}
@@ -220,421 +175,36 @@ And the result, for a `NODE_ENV = 'production'` would be:
{/if}
```
-_Note1: the `replace` transformer is executed before any other transformer._
-
-_Note2: it is **NOT** recommended to modify Svelte's syntax._
-
-## Usage
-
-### With `rollup-plugin-svelte`
-
-```js
-// rollup.config.js
-import svelte from 'rollup-plugin-svelte';
-import autoPreprocess from 'svelte-preprocess'
-import { scss, coffeescript, pug } from 'svelte-preprocess'
-
-export default {
- ...,
- plugins: [
- svelte({
- /**
- * Auto preprocess supported languages with
- * ''/'external src files' support
- **/
- preprocess: autoPreprocess({ /* options */ })
- /**
- * It is also possible to manually enqueue
- * stand-alone processors
- * */
- preprocess: [
- pug({ /* pug options */ }),
- scss({ /* scss options */ }),
- coffeescript({ /* coffeescript options */ })
- ]
- })
- ]
-}
-```
-
-### With `svelte-loader`
-
-```js
- ...
- module: {
- rules: [
- ...
- {
- test: /\.(html|svelte)$/,
- exclude: /node_modules/,
- use: {
- loader: 'svelte-loader',
- options: {
- preprocess: require('svelte-preprocess')({ /* options */ })
- },
- },
- },
- ...
- ]
- }
- ...
-```
-
-### With Sapper
-
-[Sapper](https://sapper.svelte.dev/) has two build configurations, one for the client bundle and one for the server. To use `svelte-preprocess` with Sapper, you need to define it on both configurations.
-
-```js
-// ...
-import sveltePreprocess from 'svelte-preprocess';
-
-const preprocess = sveltePreprocess({
- postcss: true,
- // ...
-});
-
-export default {
- client: {
- plugins: [
- svelte({
- preprocess,
- // ...
- }),
- },
- server: {
- plugins: [
- svelte({
- preprocess,
- // ...
- }),
- ],
- },
-};
-```
-
-### With Svelte VS Code
-
-[svelte-vscode](https://marketplace.visualstudio.com/items?itemName=JamesBirtles.svelte-vscode) needs to know how its (svelte) language server should preprocess your files. This can be achieved by creating a `svelte.config.js` file at the root of your project which exports a svelte options object (similar to `svelte-loader` and `rollup-plugin-svelte`).
-
-**Example**:
-
-```js
-// svelte.config.js
-import sveltePreprocess from 'svelte-preprocess';
-
-module.exports = {
- preprocess: sveltePreprocess({
- // ...svelte-preprocess options
- }),
- // ...other svelte options
-};
-```
-
-_Tip: this file can be imported in your bundle config instead of having multiple svelte configurations lying around._
-
-## Preprocessing modes
-
-`svelte-preprocess` can be used in two ways: _auto preprocessing_ and with _stand-alone_ processors.
-
-### Auto Preprocessing
-
-In auto preprocessing mode, `svelte-preprocess` automatically uses the respective preprocessor for your code based on your `type="..."` or `lang="..."` attributes. It also handles the `` tag for markup, external files and global styling. It's as simple as importing the module and executing the default exported method.
-
-```js
-import preprocess from 'svelte-preprocess'
-
-...
- {
- /* svelte options */
- ...,
- preprocess: preprocess({ /* options */ }),
- }
-...
-```
-
-[Svelte v3 has added support for multiple processors](https://svelte.dev/docs#svelte_preprocess), so it's also possible to use `svelte-preprocess` with other preprocessors:
-
-```js
-import preprocess from 'svelte-preprocess'
-import { mdsvex } from 'mdsvex'
-...
- {
- /* svelte options */
- ...,
- preprocess: [
- preprocess({ /* svelte-preprocess options */ }),
- mdsvex({ /* mdsvex options */ })
- ],
- }
-...
-```
-
-### Standalone processors
-
-In case you want to manually configure your preprocessing step, `svelte-preprocess` exports these named processors:
-
-- `pug`
-- `coffeescript`
-- `typescript`
-- `less`
-- `scss` or `sass`
-- `stylus`
-- `postcss`
-- `babel`
-- `globalStyle` - transform `
```
-### `coffeescript`
+---
-#### Safety wrapper
+### [Getting started](/docs/getting-started.md)
-Since `coffeescript` transpiles variables to `var` definitions, it uses a safety mechanism to prevent variables from bleeding to outside contexts. This mechanism consists of wrapping your `coffeescript` code inside an IIFE which, unfortunately, prevents `svelte` from finding your variables. To bypass this behavior, `svelte-preprocess` sets the [`bare` coffeescript compiler option](https://coffeescript.org/#lexical-scope) to `true`.
+### [Preprocessing documentation](/docs/preprocessing.md)
-## FAQ
+### [Usage documentation](/docs/usage.md)
-### My VS Code is displaying a lot of errors on my templates when I try to use `x`...
+### [Migration Guide](/docs/migration-guide.md)
-
+---
-If you have configured `svelte-preprocess` to use some kind of preprocessor and `svelte-vscode` is displaying errors like it's ignoring your preprocess configuration, that's happening because `svelte-vscode` needs to know how to preprocess your components. `svelte-vscode` works by having a svelte compiler running on the background and you can configure it by [creating a `svelte.config.js`](#with-svelte-vs-code) file on your project's root. Please check this document [With Svelte VS Code](#with-svelte-vs-code) section.
-
-### My `typescript` compilation is sloooooooow
-
-If you have a medium-to-big project, the typescript processor might start to get slow. If you already have an IDE type checking your code, you can speed up the transpilation process by setting `transpileOnly` to `true`:
-
-```js
-import preprocess from 'svelte-preprocess'
-...
-{
- ...svelteOptions,
- preprocess: preprocess({
- typescript: {
- // skips type checking
- transpileOnly: true,
- compilerOptions: {
- ...
- },
- },
- })
-}
-...
-```
+## License
-Warning: If you do this, you can't import types or interfaces into your svelte component without using the new TS 3.8 `type` import modifier: `import type { SomeInterface } from './MyModule.ts'` otherwise Rollup (and possibly others) will complain that the name is not exported by `MyModule`)
+[MIT](LICENSE)
diff --git a/docs/getting-started.md b/docs/getting-started.md
new file mode 100644
index 00000000..3c352011
--- /dev/null
+++ b/docs/getting-started.md
@@ -0,0 +1,278 @@
+# Getting Started
+
+
+
+
+
+- [1. Installation](#1-installation)
+- [2. Adding `svelte-preprocess` to our build workflow](#2-adding-svelte-preprocess-to-our-build-workflow)
+- [3. Configuring preprocessors](#3-configuring-preprocessors)
+ - [3.1. Setting default languages](#31-setting-default-languages)
+ - [3.2 Prepending content](#32-prepending-content)
+
+
+
+_Note: The examples below are going to be using a hypothetical `rollup.config.js` as if we were configuring a simple Svelte application, but `svelte-preprocess` can be used in various setups. See "[Usage](docs/usage.md)"._
+
+## 1. Installation
+
+First things first, let's create a new Svelte app project and add `svelte-preprocess`.
+
+```shell
+$ npx degit sveltejs/template my-svelte-app
+$ cd my-svelte-app
+$ npm install -D svelte-preprocess
+```
+
+`svelte-preprocess` doesn't have any language specific dependency, so it's up to us to install the rest of tools we are going to use:
+
+- Babel: `npm install -D @babel/core @babel/preset-...`
+- CoffeeScript: `npm install -D coffeescript`
+- TypeScript: `npm install -D typescript`
+- PostCSS: `npm install -D postcss postcss-load-config`
+- Less: `npm install -D less`
+- Sass: `npm install -D node-sass` or `npm install -D sass`
+- Pug: `npm install -D pug`
+- Stylus: `npm install -D stylus`
+
+For now, let's just install the main library.
+
+## 2. Adding `svelte-preprocess` to our build workflow
+
+Let's use `svelte-preprocess` in [auto-preprocessing mode](/docs/preprocessing##auto-preprocessing) and add it to our `rollup.config.js`:
+
+```diff
+import svelte from 'rollup-plugin-svelte'
++ import autoPreprocess from 'svelte-preprocess';
+
+const production = !process.env.ROLLUP_WATCH
+
+export default {
+ input: 'src/main.js',
+ output: {
+ sourcemap: true,
+ format: 'iife',
+ name: 'app',
+ file: 'public/bundle.js',
+ },
+ plugins: [
+ svelte({
++ preprocess: autoPreprocess(),
+ // enable run-time checks when not in production
+ dev: !production,
+ // we'll extract any component CSS out into
+ // a separate file โ better for performance
+ css: css => {
+ css.write('public/bundle.css')
+ },
+ }),
+ ],
+}
+```
+
+Now our app's code can be written in any of the syntaxes supported by `svelte-preprocess`: Sass, Stylus, Less, CoffeeScript, TypeScript, Pug, PostCSS, Babel.
+
+_**Note:** If you use VS Code, check [its usage guide](/docs/usage.md#with-svelte-vs-code) to make the Svelte VS Code extension understand the content of your components._
+
+## 3. Configuring preprocessors
+
+Now let's assume our app markup is going to be written in Pug, our scripts in TypeScript, and our styles in Sass. We also want our styles to be auto-prefixed, so we're also going to need PostCSS. Let's install these dependencies:
+
+**Important:** `svelte-preprocess` only handles content passed to it by `svelte-loader`, `rollup-plugin-svelte` and similar tools. If our TypeScript component import a TypeScript file, the bundler will be the one responsible for handling it. We must make sure it knows how to handle it!
+
+```shell
+$ npm i -D typescript sass postcss autoprefixer pug @rollup/plugin-typescript
+```
+
+After the installation is complete, we still need to configure our PostCSS options and add `@rollup/plugin-typescript` to our config.
+
+```diff
+import svelte from 'rollup-plugin-svelte'
+import autoPreprocess from 'svelte-preprocess';
++ import typescript from '@rollup/plugin-typescript';
+
+const production = !process.env.ROLLUP_WATCH
+
+export default {
+ input: 'src/main.js',
+ output: {
+ sourcemap: true,
+ format: 'iife',
+ name: 'app',
+ file: 'public/bundle.js',
+ },
+ plugins: [
+ svelte({
++ preprocess: autoPreprocess({
++ sourceMap: !production,
++ postcss: {
++ plugins: [require('autoprefixer')()]
++ }
++ }),
++ // teach rollup how to handle typescript imports
++ typescript({ sourceMap: !production }),
+ // enable run-time checks when not in production
+ dev: !production,
+ // we'll extract any component CSS out into
+ // a separate file โ better for performance
+ css: css => {
+ css.write('public/bundle.css')
+ },
+ }),
+ ],
+}
+```
+
+And we're done! Our components can now be written as:
+
+```html
+
+ h1 {world}
+
+
+
+
+
+```
+
+### 3.1. Setting default languages
+
+Ok, we now can write our entire app with Pug, TypeScript and SCSS, but typing `lang="..."` in every file can become an obnoxious process. In [auto-preprocessing mode](/docs/preprocessing.md#auto-preprocessing), `svelte-preprocess` [lets us define the default languages](/docs/preprocessing.md#auto-preprocessing-options) of our components. It's setted by default to HTML, JavaScript and CSS. Let's change that so we don't need those `lang` attributes.
+
+_**Disclaimer**: The Svelte VS Code extension uses the `lang` or `type` attribute to correctly highlight your code. At the time of writing, the extension doesn't support default languages. Doing this can lead to errors on your IDE._
+
+```diff
+import svelte from 'rollup-plugin-svelte'
+import autoPreprocess from 'svelte-preprocess';
+
+export default {
+ input: 'src/main.js',
+ output: {
+ sourcemap: true,
+ format: 'iife',
+ name: 'app',
+ file: 'public/bundle.js',
+ },
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess({
+ sourceMap: !production,
++ defaults: {
++ markup: 'pug',
++ script: 'typescript',
++ style: 'scss'
++ },
+ postcss: {
+ plugins: [require('autoprefixer')()]
+ }
+ }),
+ // enable run-time checks when not in production
+ dev: !production,
+ // we'll extract any component CSS out into
+ // a separate file โ better for performance
+ css: css => {
+ css.write('public/bundle.css')
+ },
+ }),
+ ],
+}
+```
+
+Now our components are a bit leaner!
+
+```html
+
+ h1 {world}
+
+
+
+
+
+```
+
+_**Note**: If the `` tag is not found and the default language is not HTML, `svelte-preprocess` expects the whole markup to be written in that language. In example, for Pug, this means the `script` and `style` tags must be written following pug's syntax._
+
+### 3.2 Prepending content
+
+Now we're in need of a SCSS file to hold some variables. Let's assume it's created at `src/styles/variables.scss`.
+
+```scss
+// src/styles/variables.scss
+$primary-color: red;
+```
+
+As in any SCSS project, we could just `@use './path/to/variables.scss`, but that can also become boring. `svelte-preprocess` [accepts a `prependData`](/docs/preprocessing.md#preprocessors) for almost every processor. Let's use it to prepend our import!
+
+```diff
++ import path from 'path'
+import svelte from 'rollup-plugin-svelte'
+import autoPreprocess from 'svelte-preprocess';
+
+export default {
+ input: 'src/main.js',
+ output: {
+ sourcemap: true,
+ format: 'iife',
+ name: 'app',
+ file: 'public/bundle.js',
+ },
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess({
+ sourceMap: !production,
+ defaults: {
+ markup: 'pug',
+ script: 'typescript',
+ style: 'scss'
+ },
++ scss: {
++ // we use path.resolve because we need a absolute path
++ // because every component style is preprocessed from its directory
++ // so relative paths won't work.
++ prependData: `@use '${path.resolve(process.cwd(), 'src/styles/variables.scss')}';`
++ },
+ postcss: {
+ plugins: [require('autoprefixer')()]
+ }
+ }),
+ // enable run-time checks when not in production
+ dev: !production,
+ // we'll extract any component CSS out into
+ // a separate file โ better for performance
+ css: css => {
+ css.write('public/bundle.css')
+ },
+ }),
+ ],
+}
+```
+
+Voila! We can now reference a variable from our file without having to explicitly import it.
+
+```html
+
+ h1 {world}
+
+
+
+
+
+```
diff --git a/docs/migration-guide.md b/docs/migration-guide.md
new file mode 100644
index 00000000..32a2c159
--- /dev/null
+++ b/docs/migration-guide.md
@@ -0,0 +1,92 @@
+# Migration Guide
+
+
+
+
+
+- [From `v3` to `v4`](#from-v3-to-v4)
+ - [Prepending content to `scss`](#prepending-content-to-scss)
+ - [Executing some function before preprocessing](#executing-some-function-before-preprocessing)
+ - [Defining preprocessor properties](#defining-preprocessor-properties)
+ - [Type-checking components](#type-checking-components)
+
+
+
+## From `v3` to `v4`
+
+### Prepending content to `scss`
+
+In `v3`, it was possible to prepend some content for the `scss` language through the `data` property.
+
+```js
+import sveltePreprocess from 'svelte-preprocess';
+
+sveltePreprocess({
+ scss: {
+ data: '// prepended content',
+ },
+});
+```
+
+In `v4`, not only `scss`, but every language preprocessor accepts the new `prependData` property. The `data` property is no longer supported.
+
+```js
+import sveltePreprocess from 'svelte-preprocess';
+
+sveltePreprocess({
+ scss: {
+ prependData: '// prepended content for scss',
+ },
+ typescript: {
+ prependData: '// prepended content for ts',
+ },
+});
+```
+
+### Executing some function before preprocessing
+
+The previously `onBefore` property was removed. Instead, enqueue a custom preprocessor before `svelte-preprocess`.
+
+```js
+// v3
+
+{
+ preprocess: sveltePreprocess({
+ onBefore({ content, filename }) {
+ return content.replace('foo', 'bar');
+ },
+ });
+}
+
+// v4
+const myPreprocessor = {
+ markup({ content }) {
+ return { code: content.replace('foo', 'bar') };
+ },
+};
+
+// later in your config
+{
+ preprocess: [myPreprocessor, sveltePreprocess()];
+}
+```
+
+### Defining preprocessor properties
+
+The previously `transformers` property was removed. Instead, define your preprocessor options in the root object of `svelte-preprocess` auto-preprocessor.
+
+```diff
+import sveltePreprocess from 'svelte-preprocess';
+
+sveltePreprocess({
+- transformers: {
+ scss: { ... }
+- }
+});
+```
+
+### Type-checking components
+
+In `v3`, `svelte-preprocess` was able to type-check Svelte components. However, giving the specifics of the structure of a Svelte component and how the `script` and `markup` contents are related, type-checking was sub-optimal.
+
+In `v4`, your TypeScript code will only be transpiled into JavaScript, with no type-checking whatsoever. We're moving the responsibility of type-checking to tools better fit to handle it, such as [`svelte-check`](https://www.npmjs.com/package/svelte-check), for CLI and CI usage, and the [VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) extension, for type-checking while developing.
diff --git a/docs/preprocessing.md b/docs/preprocessing.md
new file mode 100644
index 00000000..0e8910e8
--- /dev/null
+++ b/docs/preprocessing.md
@@ -0,0 +1,450 @@
+# Preprocessing
+
+
+
+
+
+- [Preprocessor Modes](#preprocessor-modes)
+ - [Auto Preprocessing](#auto-preprocessing)
+ - [Stand-alone processors](#stand-alone-processors)
+ - [Difference between the auto and stand-alone modes](#difference-between-the-auto-and-stand-alone-modes)
+- [Preprocessors](#preprocessors)
+ - [Babel](#babel)
+ - [CoffeeScript](#coffeescript)
+ - [Less](#less)
+ - [PostCSS](#postcss)
+ - [Pug](#pug)
+ - [scss / sass](#scss-sass)
+ - [Stylus](#stylus)
+ - [TypeScript](#typescript)
+ - [`globalStyle`](#globalstyle)
+ - [`replace`](#replace)
+
+
+
+`svelte-preprocess` can be used in two ways: _auto-preprocessing_ and with _stand-alone_ processors.
+
+The examples below are going to be using a hypothetical `rollup.config.js`, but `svelte-preprocess` can be used in multiple scenarios, see "[Usage](docs/usage.md)".
+
+## Preprocessor Modes
+
+### Auto Preprocessing
+
+In auto preprocessing mode, `svelte-preprocess` automatically uses the respective preprocessor for your code based on a tag's `src`, `lang` or `type` attribute. It also handles the `` tag for markup, external files and global styling.
+
+```js
+import svelte from 'rollup-plugin-svelte'
+import autoPreprocess from 'svelte-preprocess'
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess({ ... })
+ })
+ ]
+}
+```
+
+As `svelte-preprocess` is just a Svelte preprocessor like any oter, it's also possible to use it alongside other preprocessors:
+
+```js
+import preprocess from 'svelte-preprocess'
+import { mdsvex } from 'mdsvex'
+...
+ {
+ /* svelte options */
+ preprocess: [
+ preprocess({ ... }),
+ mdsvex({ ... })
+ ],
+ }
+...
+```
+
+#### Auto preprocessing options
+
+The following options can be passed to the preprocessor. None are required:
+
+| Option | Default | Description |
+| --------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `markupTagName` | `"template"` | `string` that sets the name of the tag `svelte-preprocess` looks for markup in custom languages.
i.e `markup` makes it possible to write your markup between `` tag. |
+| `aliases` | `null` | A list of tuples `[alias: string, language: string]` that correlates an `alias` to a `language`
i.e `['cst', 'customLanguage']` means
`<... src="./file.cst">`
`<... lang="cst">`
`<... type="text/customLanguage">`
`<... type="application/customLanguage">`
are treated as `customLanguage`. |
+| preserve | `[]` | A `string` list of languages/aliases that shouldn't pass through the preprocessor. (i.e `ld+json`) |
+| `defaults` | `{ markup: 'html', script: 'javascript', style: 'css' }` | An `object` that defines the default languages of your components.
i.e: `{ script: 'typescript' }` makes TypeScript the default language, removing the need of adding `lang="ts"` to `script` tags. |
+| `sourceMap` | `true` | If `true`, `svelte-preprocess` generates sourcemap for every language that supports it. |
+
+##### Configuring preprocessors
+
+Alongside the options above, you can also configure options of specific preprocessors:
+
+```js
+import svelte from 'rollup-plugin-svelte';
+import autoPreprocess from 'svelte-preprocess';
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess({
+ globalStyle: { ... },
+ replace: { ... },
+ typescript: { ... },
+ scss: { ... },
+ sass: { ... },
+ less: { ... },
+ stylus: { ... },
+ postcss: { ... },
+ coffeescript: { ... },
+ pug: { ... },
+ }),
+ }),
+ ],
+};
+```
+
+See the section below for options for each preprocessor.
+
+##### Custom preprocessors
+
+It's also possible to create custom preprocessors, taking advantage of the automatic language detection of `svelte-preprocess`:
+
+```js
+import svelte from 'rollup-plugin-svelte';
+import autoPreprocess from 'svelte-preprocess';
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess({
+ aliases: [
+ ['potato', 'potatoLanguage'],
+ ['pot', 'potatoLanguage'],
+ ],
+ /** Add a custom language preprocessor */
+ potatoLanguage({ content, filename, attributes }) {
+ const { code, map } = require('potato-language').render(content);
+
+ return { code, map };
+ },
+ }),
+ }),
+ ],
+};
+```
+
+Now `svelte-preprocess` will use the `potatoLanguage` preprocessor whenever it finds a tag with `lang="potato"`, `type="text/potatoLanguage"` or `src="./index.pot"`.
+
+These methods receive the same arguments and act exactly like a [common svelte preprocessor](https://svelte.dev/docs#svelte_preprocess), but the concept of `markup`/`style`/`script` is abstracted as they are executed whenever `svelte-preprocess` find the aforementioned attributes.
+
+##### Overriding preprocessors
+
+We've seen that we can easily create custom preprocessors within `svelte-preprocess`, but wait, there's more! Using the same mechanism, it's possible to override the default preprocessor for a language!
+
+Let's use TypeScript as an example. The `tsc` compiler is fast enough at the beginning, but as a project grows, it can really become cumbersome. `esbuild` is a JavaScript bundler written in Go and can transpile TypeScript [much faster](https://github.com/evanw/esbuild#benchmarks) than our good and old `tsc`.
+
+To integrate `esbuild` with `svelte-preprocss` we can override the default TypeScript preprocessor as follows:
+
+```js
+import svelte from 'rollup-plugin-svelte';
+import autoPreprocess from 'svelte-preprocess';
+import { transformSync } from 'esbuild';
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess({
+ typescript({ content, filename }) {
+ const { js: code } = transformSync(content, {
+ loader: 'ts',
+ });
+
+ return { code };
+ },
+ }),
+ }),
+ ],
+};
+```
+
+### Stand-alone processors
+
+In case you want to manually configure your preprocessing step while taking advantage of `svelte-preprocess` features, such as language detection and external file support, the following preprocessors are available: Pug, CoffeeScript, TypeScript, Less, SCSS, Sass, Stylus, PostCSS, Babel, `globalStyle` `replace`.
+
+Every processor accepts an option object which is passed to its respective underlying tool. See the section below for options for each preprocessor.
+
+```js
+import { scss, postcss } from 'svelte-preprocess';
+
+svelte.preprocess(input, [
+ scss(),
+ postcss({
+ plugins: [
+ require('autoprefixer')({
+ browsers: 'last 2 versions',
+ }),
+ ],
+ }),
+]);
+```
+
+Stand-alone markup preprocessors such as Pug are executed over the whole markup and not only inside a custom tag.
+
+The preprocessors are language aware, which means you can enqueue multiple ones and you won't have SCSS and Stylus conflicting over the same content.
+
+### Difference between the auto and stand-alone modes
+
+The auto preprocessing mode is the recommended way of using `svelte-preprocess` as it's the least verbose and most straightforward way of supporting multiple language preprocessors.
+
+`svelte-preprocess` was built in a way that the underlying transpilers and compilers are only required/imported if a portion of your component matches its language. With that said, the auto-preprocessing mode is roughly equivalent to using all the stand-alone preprocessors in the following order:
+
+```js
+import svelte from 'rollup-plugin-svelte';
+import {
+ pug,
+ coffeescript,
+ typescript,
+ less,
+ scss,
+ sass,
+ stylus,
+ postcss,
+ globalStyle,
+ babel,
+ replace,
+} from 'svelte-preprocess';
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: [
+ replace(),
+ pug(),
+ coffeescript(),
+ typescript(),
+ less(),
+ scss(),
+ sass(),
+ stylus(),
+ babel(),
+ postcss(),
+ globalStyle(),
+ ],
+ }),
+ ],
+};
+
+// vs
+import svelte from 'rollup-plugin-svelte';
+import autoPreprocess from 'svelte-preprocess';
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: autoPreprocess(),
+ }),
+ ],
+};
+```
+
+## Preprocessors
+
+Besides the options of each preprocessors, `svelte-preprocess` also supports these custom options:
+
+| Option | Default | Description |
+| ------------- | ------- | -------------------------------------------------------------------------------------- |
+| `prependData` | `''` | `string` will be prepended to every component part that runs through the preprocessor. |
+
+### Babel
+
+The Babel preprocessor accepts an option object which is passed onto the babel runtime. You can check the [Babel API reference](https://babeljs.io/docs/en/options#primary-options) for specific options.
+
+**Note**: `Svelte` expects your JavaScript to be in at least ES6 format, so make sure to set your Babel configuration accordingly.
+
+_Note: If you want to transpile your app to be supported in older browsers, you must run babel from the context of your bundler._
+
+### CoffeeScript
+
+The CoffeeScript processor accepts no extra options and only transpiles CoffeeScript code down to esm compliant JavaScript code.
+
+### Less
+
+You can check the [Less API reference](http://lesscss.org/usage/#less-options) for Less specific options.
+
+### PostCSS
+
+The PostCSS preprocessor accepts three options:
+
+| Option | Default | Description |
+| --------- | ----------- | ------------------------------------------------ |
+| `plugins` | `undefined` | a list of `postcss plugins`. |
+| `parser` | `undefined` | the name of the module to be used as the parser. |
+| `syntax` | `undefined` | the syntax to be used. |
+
+**Note**: In auto-preprocessing mode, you can set `postcss: true` if `postcss-load-config` is installed and `svelte-preprocess` will look for a PostCSS config file in your project.
+
+You can check the [PostCSS API reference](https://api.postcss.org/) for PostCSS specific options.
+
+### Pug
+
+You can check the [Pug API reference](https://pugjs.org/api/reference.html) for more options. The only overriden property is `doctype`, which is set to HTML.
+
+**Template blocks:**
+
+Some of Svelte's template syntax is invalid in Pug. `svelte-preprocess` provides some pug mixins to represent svelte's `{#...}{/...}` blocks: `+if()`, `+else()`, `+elseif()`, `+each()`, `+await()`, `+then()`, `+catch()`, `+debug()`.
+
+```pug
+ul
+ +if('posts && posts.length > 1')
+ +each('posts as post')
+ li
+ a(rel="prefetch" href="blog/{post.slug}") {post.title}
+ +else()
+ span No posts :c
+```
+
+**Element attributes:**
+
+Pug encodes everything inside an element attribute to html entities, so `attr="{foo && bar}"` becomes `attr="foo && bar"`. To prevent this from happening, instead of using the `=` operator use `!=` which won't encode your attribute value:
+
+```pug
+button(disabled!="{foo && bar}")
+```
+
+**Svelte Element directives:**
+
+Syntax for use Svelte Element directives with Pug
+
+```pug
+input(bind:value="{foo}")
+input(on:input="{bar}")
+```
+
+### scss / sass
+
+The `scss/sass` preprocessor accepts the default sass options alongside two other props:
+
+| Option | Default | Description |
+| ---------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------ |
+| `renderSync` | `false` | if `true`, use the sync render method which is faster for dart sass. |
+| `implementation` | `undefined` | pass the module to use to compile sass, if unspecified, `svelte-preprocess` will first look for `node-sass` and then for Sass. |
+
+You can check the [Sass API reference](https://sass-lang.com/documentation/js-api) for specific Sass options. The `file` and `data` properties are not supported.
+
+**Note**: When `svelte-preprocess` detects the language as Sass, it automatically sets `indentedSyntax` to `true.
+
+### Stylus
+
+You can check the [Stylus API reference](https://stylus-lang.com/docs/js.html) for specific Stylus options. The `filename` property is overriden.
+
+### TypeScript
+
+| Option | Default | Description |
+| ------------------- | ----------- | ----------------------------------------------------------------------------------------------------------- |
+| `tsconfigDirectory` | `undefined` | optional `string` that specifies from where to load the tsconfig from.
i.e `'./configs'` |
+| `tsconfigFile` | `undefined` | optional `string` pointing torwards a `tsconfig` file.
i.e `'./tsconfig.app.json'` |
+| `compilerOptions` | `undefined` | optional compiler options configuration. These will be merged with options from the tsconfig file if found. |
+
+You can check the [`compilerOptions` reference](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) for specific TypeScript options.
+
+Since `v4`, `svelte-preprocess` doesn't type-check your component, its only concern is to transpile it into valid JavaScript for the compiler. If you want to have your components type-checked, you can use [svelte-check](https://github.com/sveltejs/language-tools/blob/master/packages/svelte-check/README.md).
+
+As we're only transpiling, it's not possible to import types or interfaces into your svelte component without using the new TS 3.8 `type` import modifier: `import type { SomeInterface } from './MyModule'` otherwise bundlers will complain that the name is not exported by `MyModule`.
+
+### `globalStyle`
+
+The `globalStyle` preprocessor extends the functionalities of Svelte's `:global` pseudo selector.
+
+**`global` attribute:**
+
+Add a `global` attribute to your `style` tag and instead of scoping the CSS, all of its content will be interpreted as global style.
+
+```html
+
+```
+
+**`:global` rule:**
+
+Use a `:global` rule to only expose parts of the stylesheet:
+
+```html
+
+```
+
+Works best with nesting-enabled CSS preprocessors, but regular CSS selectors like `div :global .global1 .global2` are also supported.
+
+_Note1: needs PostCSS to be installed._
+
+_Note2: if you're using it as a standalone processor, it works best if added to the end of the processors array._
+
+_Note3: wrapping `@keyframes` inside `:global {}` blocks is not supported. Use the [`-global-` name prefix for global keyframes](https://svelte.dev/docs#style)._
+
+_Note4: if you need to have some styles be scoped inside a global style tag, use `:local` in the same way you'd use `:global`._
+
+### `replace`
+
+The `replace` preprocessor replaces a set of string patterns in your components markup defined by an array of `[RegExp, ReplaceFn | string]` tuples, the same arguments received by the `String.prototype.replace` method.
+
+For example, to add a `process.env.{prop}` value resolution and a custom `@if/@endif` if-block shorthand, one could do:
+
+```js
+import svelte from 'rollup-plugin-svelte'
+
+import { replace } from 'svelte-preprocess'
+
+export default {
+ plugins: [
+ svelte({
+ preprocess: [replace([
+ [
+ /process\.env\.(\w+)/g,
+ (_:, prop) => JSON.stringify(process.env[prop]),
+ ],
+ // Example of supporting a blade-like syntax:
+ [/@if\s*\((.*?)\)$/gim, '{#if $1}'],
+ [/@elseif\s*\((.*?)\)$/gim, '{:else if $1}'],
+ [/@else$/gim, '{:else}'],
+ [/@endif$/gim, '{/if}'],
+ [/@each\s*\((.*?)\)$/gim, '{#each $1}'],
+ [/@endeach$/gim, '{/each}'],
+ [/@await\s*\((.*?)\)$/gim, '{#await $1}'],
+ [/@then\s*(?:\((.*?)\))?$/gim, '{:then $1}'],
+ [/@catch\s*(?:\((.*?)\))?$/gim, '{:catch $1}'],
+ [/@endawait$/gim, '{/await}'],
+ [/@debug\s*\((.*?)\)$/gim, '{@debug $1}'],
+ [/@html\s*\((.*?)\)$/gim, '{@html $1}'],
+ ])]
+ })
+ ]
+}
+```
+
+Allowing to write your component like:
+
+```
+@if(process.env.NODE_ENV !== 'development')
+ Production environment!
+@endif
+```
+
+And the result, with a `NODE_ENV = 'production'` would be:
+
+```svelte
+{#if "production" !== 'development'}
+ Production environment!
+{/if}
+```
diff --git a/docs/usage.md b/docs/usage.md
new file mode 100644
index 00000000..72b7c6c0
--- /dev/null
+++ b/docs/usage.md
@@ -0,0 +1,120 @@
+# Usage
+
+
+
+
+
+- [With `rollup-plugin-svelte`](#with-rollup-plugin-svelte)
+- [With `svelte-loader`](#with-svelte-loader)
+- [With Sapper](#with-sapper)
+- [With Svelte VS Code](#with-svelte-vs-code)
+
+
+
+## With `rollup-plugin-svelte`
+
+```js
+// rollup.config.js
+import svelte from 'rollup-plugin-svelte';
+import autoPreprocess from 'svelte-preprocess'
+import { scss, coffeescript, pug } from 'svelte-preprocess'
+
+export default {
+ ...,
+ plugins: [
+ svelte({
+ /**
+ * Auto preprocess supported languages with
+ * ''/'external src files' support
+ **/
+ preprocess: autoPreprocess({ /* options */ })
+ /**
+ * It is also possible to manually enqueue
+ * stand-alone processors
+ * */
+ preprocess: [
+ pug({ /* pug options */ }),
+ scss({ /* scss options */ }),
+ coffeescript({ /* coffeescript options */ })
+ ]
+ })
+ ]
+}
+```
+
+## With `svelte-loader`
+
+```js
+ ...
+ module: {
+ rules: [
+ ...
+ {
+ test: /\.(html|svelte)$/,
+ exclude: /node_modules/,
+ use: {
+ loader: 'svelte-loader',
+ options: {
+ preprocess: require('svelte-preprocess')({
+ /* options */
+ })
+ },
+ },
+ },
+ ...
+ ]
+ }
+ ...
+```
+
+## With Sapper
+
+[Sapper](https://sapper.svelte.dev/) has two build configurations, one for the client bundle and one for the server. To use `svelte-preprocess` with Sapper, you need to define it on both configurations.
+
+```js
+// ...
+import autoPreprocess from 'svelte-preprocess';
+
+const preprocess = autoPreprocess({
+ postcss: true,
+ // ...
+});
+
+export default {
+ client: {
+ plugins: [
+ svelte({
+ preprocess,
+ // ...
+ }),
+ },
+ server: {
+ plugins: [
+ svelte({
+ preprocess,
+ // ...
+ }),
+ ],
+ },
+};
+```
+
+## With Svelte VS Code
+
+[svelte-vscode](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) needs to know how its (svelte) language server should preprocess your files. This can be achieved by creating a `svelte.config.js` file at the root of your project which exports a svelte options object (similar to `svelte-loader` and `rollup-plugin-svelte`).
+
+**Example**:
+
+```js
+// svelte.config.js
+import autoPreprocess from 'svelte-preprocess';
+
+module.exports = {
+ preprocess: autoPreprocess({
+ // ...svelte-preprocess options
+ }),
+ // ...other svelte options
+};
+```
+
+_Tip: this file can be imported in your bundle config instead of having multiple svelte configurations lying around._
diff --git a/examples/svelte-rollup/rollup.config.js b/examples/svelte-rollup/rollup.config.js
index 2f769f51..a7eb719e 100644
--- a/examples/svelte-rollup/rollup.config.js
+++ b/examples/svelte-rollup/rollup.config.js
@@ -20,10 +20,8 @@ export default {
plugins: [
svelte({
preprocess: autoPreprocess({
- transformers: {
- postcss: {
- plugins: [require('postcss-import')],
- },
+ postcss: {
+ plugins: [require('postcss-import')],
},
}),
// enable run-time checks when not in production
diff --git a/examples/svelte-rollup/yarn.lock b/examples/svelte-rollup/yarn.lock
new file mode 100644
index 00000000..71766788
--- /dev/null
+++ b/examples/svelte-rollup/yarn.lock
@@ -0,0 +1,1271 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.5.5":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
+ integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
+ dependencies:
+ "@babel/highlight" "^7.10.4"
+
+"@babel/helper-validator-identifier@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
+ integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
+
+"@babel/highlight@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
+ integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.10.4"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
+"@polka/url@^0.5.0":
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/@polka/url/-/url-0.5.0.tgz#b21510597fd601e5d7c95008b76bf0d254ebfd31"
+ integrity sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==
+
+"@types/babel-types@*", "@types/babel-types@^7.0.0":
+ version "7.0.7"
+ resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.7.tgz#667eb1640e8039436028055737d2b9986ee336e3"
+ integrity sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ==
+
+"@types/babylon@^6.16.2":
+ version "6.16.5"
+ resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.5.tgz#1c5641db69eb8cdf378edd25b4be7754beeb48b4"
+ integrity sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==
+ dependencies:
+ "@types/babel-types" "*"
+
+"@types/estree@*":
+ version "0.0.45"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
+ integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
+
+"@types/node@*":
+ version "14.0.14"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce"
+ integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==
+
+"@types/pug@^2.0.4":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.4.tgz#8772fcd0418e3cd2cc171555d73007415051f4b2"
+ integrity sha1-h3L80EGOPNLMFxVV1zAHQVBR9LI=
+
+"@types/resolve@0.0.8":
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194"
+ integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/sass@^1.16.0":
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/@types/sass/-/sass-1.16.0.tgz#b41ac1c17fa68ffb57d43e2360486ef526b3d57d"
+ integrity sha512-2XZovu4NwcqmtZtsBR5XYLw18T8cBCnU2USFHTnYLLHz9fkhnoEMoDsqShJIOFsFhn5aJHjweiUUdTrDGujegA==
+ dependencies:
+ "@types/node" "*"
+
+acorn-globals@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf"
+ integrity sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=
+ dependencies:
+ acorn "^4.0.4"
+
+acorn@^3.1.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+ integrity sha1-ReN/s56No/JbruP/U2niu18iAXo=
+
+acorn@^4.0.4, acorn@~4.0.2:
+ version "4.0.13"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
+ integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=
+
+acorn@^7.1.0:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd"
+ integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==
+
+align-text@^0.1.1, align-text@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
+ integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=
+ dependencies:
+ kind-of "^3.0.2"
+ longest "^1.0.1"
+ repeat-string "^1.5.2"
+
+ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+anymatch@~3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
+ integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+asap@~2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
+
+async-limiter@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
+ integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
+
+babel-runtime@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+ integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.11.0"
+
+babel-types@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+ integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
+ dependencies:
+ babel-runtime "^6.26.0"
+ esutils "^2.0.2"
+ lodash "^4.17.4"
+ to-fast-properties "^1.0.3"
+
+babylon@^6.18.0:
+ version "6.18.0"
+ resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+ integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+ integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
+binary-extensions@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
+ integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+
+builtin-modules@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484"
+ integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==
+
+camelcase@^1.0.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
+ integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=
+
+center-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
+ integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60=
+ dependencies:
+ align-text "^0.1.3"
+ lazy-cache "^1.0.3"
+
+chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+character-parser@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0"
+ integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A=
+ dependencies:
+ is-regex "^1.0.3"
+
+chokidar@^3.3.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
+ integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==
+ dependencies:
+ anymatch "~3.1.1"
+ braces "~3.0.2"
+ glob-parent "~5.1.0"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.4.0"
+ optionalDependencies:
+ fsevents "~2.1.2"
+
+clean-css@^4.1.11:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
+ integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==
+ dependencies:
+ source-map "~0.6.0"
+
+cliui@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
+ integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=
+ dependencies:
+ center-align "^0.1.1"
+ right-align "^0.1.1"
+ wordwrap "0.0.2"
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+console-clear@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/console-clear/-/console-clear-1.1.1.tgz#995e20cbfbf14dd792b672cde387bd128d674bf7"
+ integrity sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==
+
+constantinople@^3.0.1, constantinople@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647"
+ integrity sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==
+ dependencies:
+ "@types/babel-types" "^7.0.0"
+ "@types/babylon" "^6.16.2"
+ babel-types "^6.26.0"
+ babylon "^6.18.0"
+
+core-js@^2.4.0:
+ version "2.6.11"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
+ integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
+
+cross-spawn@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+ integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+ dependencies:
+ nice-try "^1.0.4"
+ path-key "^2.0.1"
+ semver "^5.5.0"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+decamelize@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
+define-properties@^1.1.2, define-properties@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+ integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
+ dependencies:
+ object-keys "^1.0.12"
+
+detect-indent@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd"
+ integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==
+
+doctypes@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9"
+ integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+es-abstract@^1.17.0-next.1, es-abstract@^1.17.5:
+ version "1.17.6"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a"
+ integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==
+ dependencies:
+ es-to-primitive "^1.2.1"
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.1"
+ is-callable "^1.2.0"
+ is-regex "^1.1.0"
+ object-inspect "^1.7.0"
+ object-keys "^1.1.1"
+ object.assign "^4.1.0"
+ string.prototype.trimend "^1.0.1"
+ string.prototype.trimstart "^1.0.1"
+
+es-to-primitive@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+ dependencies:
+ is-callable "^1.1.4"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.2"
+
+escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+estree-walker@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
+ integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+fsevents@~2.1.2:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
+ integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+get-port@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
+ integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=
+
+glob-parent@~5.1.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
+ integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
+ dependencies:
+ is-glob "^4.0.1"
+
+graceful-fs@^4.1.2:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
+ integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+
+has-symbols@^1.0.0, has-symbols@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
+ integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+hosted-git-info@^2.1.4:
+ version "2.8.8"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
+ integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-buffer@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+ integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+
+is-callable@^1.1.4, is-callable@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
+ integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
+
+is-date-object@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
+ integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
+
+is-expression@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f"
+ integrity sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=
+ dependencies:
+ acorn "~4.0.2"
+ object-assign "^4.0.1"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
+
+is-glob@^4.0.1, is-glob@~4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
+ integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
+ integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-promise@^2.0.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
+ integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
+
+is-reference@^1.1.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
+ integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==
+ dependencies:
+ "@types/estree" "*"
+
+is-regex@^1.0.3, is-regex@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff"
+ integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==
+ dependencies:
+ has-symbols "^1.0.1"
+
+is-symbol@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
+ integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
+ dependencies:
+ has-symbols "^1.0.1"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+
+jest-worker@^24.9.0:
+ version "24.9.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5"
+ integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==
+ dependencies:
+ merge-stream "^2.0.0"
+ supports-color "^6.1.0"
+
+js-stringify@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
+ integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds=
+
+js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+json-parse-better-errors@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+ integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+
+jstransformer@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3"
+ integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=
+ dependencies:
+ is-promise "^2.0.0"
+ promise "^7.0.1"
+
+kind-of@^3.0.2:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+ integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
+ dependencies:
+ is-buffer "^1.1.5"
+
+kleur@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
+
+lazy-cache@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
+ integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4=
+
+livereload-js@^3.1.0:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.2.3.tgz#64beff07ce5b2a74485d1a08c2ec04ac68e021bc"
+ integrity sha512-dXL/WgTGI2K3oeYX/z1lngFXSKtjCB2j7n9WSSluoU6/6+N4LWNoMiCBFNgn8dh3luBn4JBajVSvM5I7Xn6SLA==
+
+livereload@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/livereload/-/livereload-0.9.1.tgz#65125dabdf2db4fd3f1169e953fe56e3bcc6f477"
+ integrity sha512-9g7sua11kkyZNo2hLRCG3LuZZwqexoyEyecSlV8cAsfAVVCZqLzVir6XDqmH0r+Vzgnd5LrdHDMyjtFnJQLAYw==
+ dependencies:
+ chokidar "^3.3.0"
+ livereload-js "^3.1.0"
+ opts ">= 1.2.0"
+ ws "^6.2.1"
+
+load-json-file@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+ integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^4.0.0"
+ pify "^3.0.0"
+ strip-bom "^3.0.0"
+
+local-access@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.0.1.tgz#5121258146d64e869046c642ea4f1dd39ff942bb"
+ integrity sha512-ykt2pgN0aqIy6KQC1CqdWTWkmUwNgaOS6dcpHVjyBJONA+Xi7AtSB1vuxC/U/0tjIP3wcRudwQk1YYzUvzk2bA==
+
+lodash@^4.17.4:
+ version "4.17.15"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+ integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
+longest@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+ integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=
+
+magic-string@^0.25.2:
+ version "0.25.7"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
+ integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
+ dependencies:
+ sourcemap-codec "^1.4.4"
+
+memorystream@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
+ integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI=
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+mime@^2.3.1:
+ version "2.4.6"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
+ integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
+
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
+minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+mri@^1.1.0:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.5.tgz#ce21dba2c69f74a9b7cf8a1ec62307e089e223e0"
+ integrity sha512-d2RKzMD4JNyHMbnbWnznPaa8vbdlq/4pNZ3IgdaGrVbBhebBsGUUE/6qorTMYNS6TwuH3ilfOlD2bf4Igh8CKg==
+
+nice-try@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+ integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+normalize-package-data@^2.3.2:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+ dependencies:
+ hosted-git-info "^2.1.4"
+ resolve "^1.10.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+npm-run-all@^4.1.5:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
+ integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ chalk "^2.4.1"
+ cross-spawn "^6.0.5"
+ memorystream "^0.3.1"
+ minimatch "^3.0.4"
+ pidtree "^0.3.0"
+ read-pkg "^3.0.0"
+ shell-quote "^1.6.1"
+ string.prototype.padend "^3.0.0"
+
+object-assign@^4.0.1, object-assign@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
+
+object-inspect@^1.7.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
+ integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
+
+object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object.assign@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
+ integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
+ dependencies:
+ define-properties "^1.1.2"
+ function-bind "^1.1.1"
+ has-symbols "^1.0.0"
+ object-keys "^1.0.11"
+
+"opts@>= 1.2.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.0.tgz#c0b2cebdf53eaeafc21ed844e34773758dcf41e2"
+ integrity sha512-rPleeyX48sBEc4aj7rAok5dCbvRdYpdbIdSRR4gnIK98a7Rvd4l3wlv4YHQr2mwPQTpKQiw8uipi/WoyItDINg==
+
+parse-json@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+ integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
+ dependencies:
+ error-ex "^1.3.1"
+ json-parse-better-errors "^1.0.1"
+
+path-key@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+ integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
+
+path-parse@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+ integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+
+path-type@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+ integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+ dependencies:
+ pify "^3.0.0"
+
+picomatch@^2.0.4, picomatch@^2.2.1:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
+ integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
+
+pidtree@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
+ integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==
+
+pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
+
+pify@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+ integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
+
+postcss-import@^12.0.1:
+ version "12.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153"
+ integrity sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==
+ dependencies:
+ postcss "^7.0.1"
+ postcss-value-parser "^3.2.3"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-value-parser@^3.2.3:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
+ integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
+
+postcss@^7.0.1, postcss@^7.0.21:
+ version "7.0.32"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
+ integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==
+ dependencies:
+ chalk "^2.4.2"
+ source-map "^0.6.1"
+ supports-color "^6.1.0"
+
+promise@^7.0.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+ integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
+ dependencies:
+ asap "~2.0.3"
+
+pug-attrs@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.4.tgz#b2f44c439e4eb4ad5d4ef25cac20d18ad28cc336"
+ integrity sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==
+ dependencies:
+ constantinople "^3.0.1"
+ js-stringify "^1.0.1"
+ pug-runtime "^2.0.5"
+
+pug-code-gen@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.2.tgz#ad0967162aea077dcf787838d94ed14acb0217c2"
+ integrity sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw==
+ dependencies:
+ constantinople "^3.1.2"
+ doctypes "^1.1.0"
+ js-stringify "^1.0.1"
+ pug-attrs "^2.0.4"
+ pug-error "^1.3.3"
+ pug-runtime "^2.0.5"
+ void-elements "^2.0.1"
+ with "^5.0.0"
+
+pug-error@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.3.tgz#f342fb008752d58034c185de03602dd9ffe15fa6"
+ integrity sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==
+
+pug-filters@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-3.1.1.tgz#ab2cc82db9eeccf578bda89130e252a0db026aa7"
+ integrity sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==
+ dependencies:
+ clean-css "^4.1.11"
+ constantinople "^3.0.1"
+ jstransformer "1.0.0"
+ pug-error "^1.3.3"
+ pug-walk "^1.1.8"
+ resolve "^1.1.6"
+ uglify-js "^2.6.1"
+
+pug-lexer@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-4.1.0.tgz#531cde48c7c0b1fcbbc2b85485c8665e31489cfd"
+ integrity sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==
+ dependencies:
+ character-parser "^2.1.1"
+ is-expression "^3.0.0"
+ pug-error "^1.3.3"
+
+pug-linker@^3.0.6:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.6.tgz#f5bf218b0efd65ce6670f7afc51658d0f82989fb"
+ integrity sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==
+ dependencies:
+ pug-error "^1.3.3"
+ pug-walk "^1.1.8"
+
+pug-load@^2.0.12:
+ version "2.0.12"
+ resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.12.tgz#d38c85eb85f6e2f704dea14dcca94144d35d3e7b"
+ integrity sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==
+ dependencies:
+ object-assign "^4.1.0"
+ pug-walk "^1.1.8"
+
+pug-parser@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-5.0.1.tgz#03e7ada48b6840bd3822f867d7d90f842d0ffdc9"
+ integrity sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==
+ dependencies:
+ pug-error "^1.3.3"
+ token-stream "0.0.1"
+
+pug-runtime@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.5.tgz#6da7976c36bf22f68e733c359240d8ae7a32953a"
+ integrity sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==
+
+pug-strip-comments@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz#cc1b6de1f6e8f5931cf02ec66cdffd3f50eaf8a8"
+ integrity sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==
+ dependencies:
+ pug-error "^1.3.3"
+
+pug-walk@^1.1.8:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.8.tgz#b408f67f27912f8c21da2f45b7230c4bd2a5ea7a"
+ integrity sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA==
+
+pug@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.4.tgz#ee7682ec0a60494b38d48a88f05f3b0ac931377d"
+ integrity sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==
+ dependencies:
+ pug-code-gen "^2.0.2"
+ pug-filters "^3.1.1"
+ pug-lexer "^4.1.0"
+ pug-linker "^3.0.6"
+ pug-load "^2.0.12"
+ pug-parser "^5.0.1"
+ pug-runtime "^2.0.5"
+ pug-strip-comments "^1.0.4"
+
+read-cache@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
+ integrity sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=
+ dependencies:
+ pify "^2.3.0"
+
+read-pkg@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+ integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
+ dependencies:
+ load-json-file "^4.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^3.0.0"
+
+readdirp@~3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
+ integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==
+ dependencies:
+ picomatch "^2.2.1"
+
+regenerator-runtime@^0.11.0:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+ integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
+repeat-string@^1.5.2:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+ integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
+
+require-relative@^0.8.7:
+ version "0.8.7"
+ resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
+ integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
+
+resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.11.1:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
+ integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
+ dependencies:
+ path-parse "^1.0.6"
+
+right-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
+ integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8=
+ dependencies:
+ align-text "^0.1.1"
+
+rollup-plugin-commonjs@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz#417af3b54503878e084d127adf4d1caf8beb86fb"
+ integrity sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==
+ dependencies:
+ estree-walker "^0.6.1"
+ is-reference "^1.1.2"
+ magic-string "^0.25.2"
+ resolve "^1.11.0"
+ rollup-pluginutils "^2.8.1"
+
+rollup-plugin-livereload@^1.0.4:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-livereload/-/rollup-plugin-livereload-1.3.0.tgz#8da90df13df6502b9d982997d6ac871092f15fdd"
+ integrity sha512-abyqXaB21+nFHo+vJULBqfzNx6zXABC19UyvqgDfdoxR/8pFAd041GO+GIUe8ZYC2DbuMUmioh1Lvbk14YLZgw==
+ dependencies:
+ livereload "^0.9.1"
+
+rollup-plugin-node-resolve@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz#730f93d10ed202473b1fb54a5997a7db8c6d8523"
+ integrity sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==
+ dependencies:
+ "@types/resolve" "0.0.8"
+ builtin-modules "^3.1.0"
+ is-module "^1.0.0"
+ resolve "^1.11.1"
+ rollup-pluginutils "^2.8.1"
+
+rollup-plugin-svelte@^5.1.0:
+ version "5.2.3"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-svelte/-/rollup-plugin-svelte-5.2.3.tgz#efdc15e3e3fdd9b9f1100fdc14a8532b4e587bc8"
+ integrity sha512-513vOht9A93OV7fvmpIq8mD1JFgTZ5LidmpULKM2Od9P1l8oI5KwvO32fwCnASuVJS1EkRfvCnS7vKQ8DF4srg==
+ dependencies:
+ require-relative "^0.8.7"
+ rollup-pluginutils "^2.8.2"
+ sourcemap-codec "^1.4.8"
+
+rollup-plugin-terser@^5.1.2:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz#9c0dd33d5771df9630cd027d6a2559187f65885e"
+ integrity sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g==
+ dependencies:
+ "@babel/code-frame" "^7.5.5"
+ jest-worker "^24.9.0"
+ rollup-pluginutils "^2.8.2"
+ serialize-javascript "^2.1.2"
+ terser "^4.6.2"
+
+rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2:
+ version "2.8.2"
+ resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
+ integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
+ dependencies:
+ estree-walker "^0.6.1"
+
+rollup@^1.26.0:
+ version "1.32.1"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.32.1.tgz#4480e52d9d9e2ae4b46ba0d9ddeaf3163940f9c4"
+ integrity sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A==
+ dependencies:
+ "@types/estree" "*"
+ "@types/node" "*"
+ acorn "^7.1.0"
+
+sade@^1.4.0:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.3.tgz#a217ccc4fb4abb2d271648bf48f6628b2636fa1b"
+ integrity sha512-m4BctppMvJ60W1dXnHq7jMmFe3hPJZDAH85kQ3ACTo7XZNVUuTItCQ+2HfyaMeV5cKrbw7l4vD/6We3GBxvdJw==
+ dependencies:
+ mri "^1.1.0"
+
+"semver@2 || 3 || 4 || 5", semver@^5.5.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+ integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+serialize-javascript@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
+ integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
+
+shebang-command@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+ integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
+ dependencies:
+ shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+ integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+
+shell-quote@^1.6.1:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
+ integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
+
+sirv-cli@^0.4.5:
+ version "0.4.6"
+ resolved "https://registry.yarnpkg.com/sirv-cli/-/sirv-cli-0.4.6.tgz#c28ab20deb3b34637f5a60863dc350f055abca04"
+ integrity sha512-/Vj85/kBvPL+n9ibgX6FicLE8VjidC1BhlX67PYPBfbBAphzR6i0k0HtU5c2arejfU3uzq8l3SYPCwl1x7z6Ww==
+ dependencies:
+ console-clear "^1.1.0"
+ get-port "^3.2.0"
+ kleur "^3.0.0"
+ local-access "^1.0.1"
+ sade "^1.4.0"
+ sirv "^0.4.6"
+ tinydate "^1.0.0"
+
+sirv@^0.4.6:
+ version "0.4.6"
+ resolved "https://registry.yarnpkg.com/sirv/-/sirv-0.4.6.tgz#185e44eb93d24009dd183b7494285c5180b81f22"
+ integrity sha512-rYpOXlNbpHiY4nVXxuDf4mXPvKz1reZGap/LkWp9TvcZ84qD/nPBjjH/6GZsgIjVMbOslnY8YYULAyP8jMn1GQ==
+ dependencies:
+ "@polka/url" "^0.5.0"
+ mime "^2.3.1"
+
+source-map-support@~0.5.12:
+ version "0.5.19"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
+ integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+source-map@~0.5.1:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
+
+sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8:
+ version "1.4.8"
+ resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
+ integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+
+spdx-correct@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
+ integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
+ dependencies:
+ spdx-expression-parse "^3.0.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+ integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
+
+spdx-expression-parse@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
+ integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
+
+string.prototype.padend@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz#dc08f57a8010dc5c153550318f67e13adbb72ac3"
+ integrity sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.0-next.1"
+
+string.prototype.trimend@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913"
+ integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.5"
+
+string.prototype.trimstart@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54"
+ integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.5"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
+
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+ integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+ dependencies:
+ has-flag "^3.0.0"
+
+svelte-preprocess@^4.0.0-alpha.1:
+ version "4.0.0-alpha.1"
+ resolved "https://registry.yarnpkg.com/svelte-preprocess/-/svelte-preprocess-4.0.0-alpha.1.tgz#4dfdaa90cc75feeb5e4481eba484f3ca285bf027"
+ integrity sha512-6I/VOTSVa6JT/Mol7+GdvCFGyIhmfOG12BhSPsGk8mAlEGMsUdQVW97GLMqsitpNlYhn3OTa2zdmgHgOCwPtSw==
+ dependencies:
+ "@types/pug" "^2.0.4"
+ "@types/sass" "^1.16.0"
+ detect-indent "^6.0.0"
+ strip-indent "^3.0.0"
+
+svelte@^3.12.1:
+ version "3.23.2"
+ resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.23.2.tgz#f3e500384261a2e77b29681ee744c3c790fbcdc3"
+ integrity sha512-hE8GeTM83YVR4GY6/6PeDEcGct4JS5aCi+IYbCAa76oaPSfuF7L85DQYULQxlTK/KPWzw3L1GRGmC3oPG/PQoA==
+
+terser@^4.6.2:
+ version "4.8.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17"
+ integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==
+ dependencies:
+ commander "^2.20.0"
+ source-map "~0.6.1"
+ source-map-support "~0.5.12"
+
+tinydate@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/tinydate/-/tinydate-1.3.0.tgz#e6ca8e5a22b51bb4ea1c3a2a4fd1352dbd4c57fb"
+ integrity sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==
+
+to-fast-properties@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+ integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+token-stream@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a"
+ integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=
+
+uglify-js@^2.6.1:
+ version "2.8.29"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+ integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0=
+ dependencies:
+ source-map "~0.5.1"
+ yargs "~3.10.0"
+ optionalDependencies:
+ uglify-to-browserify "~1.0.0"
+
+uglify-to-browserify@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+ integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc=
+
+validate-npm-package-license@^3.0.1:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+ dependencies:
+ spdx-correct "^3.0.0"
+ spdx-expression-parse "^3.0.0"
+
+void-elements@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
+ integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
+
+which@^1.2.9:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+ integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+ dependencies:
+ isexe "^2.0.0"
+
+window-size@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
+ integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=
+
+with@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe"
+ integrity sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=
+ dependencies:
+ acorn "^3.1.0"
+ acorn-globals "^3.0.0"
+
+wordwrap@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+ integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=
+
+ws@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
+ integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
+ dependencies:
+ async-limiter "~1.0.0"
+
+yargs@~3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+ integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=
+ dependencies:
+ camelcase "^1.0.2"
+ cliui "^2.1.0"
+ decamelize "^1.0.0"
+ window-size "0.1.0"
diff --git a/package.json b/package.json
index cbfdb79d..4f3ba247 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,12 @@
{
"name": "svelte-preprocess",
- "version": "3.9.12",
+ "version": "4.0.0",
"license": "MIT",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"description": "A Svelte preprocessor wrapper with baked in support for common used preprocessors",
"author": "Christian Kaisermann ",
- "repository": "https://github.com/kaisermann/svelte-preprocess",
+ "repository": "https://github.com/sveltejs/svelte-preprocess",
"keywords": [
"svelte",
"preprocess",
@@ -18,7 +18,7 @@
"coffeescript"
],
"engines": {
- "node": ">= 7.6.0"
+ "node": ">= 9.11.2"
},
"files": [
"dist/"
@@ -36,13 +36,13 @@
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1 && git add CHANGELOG.md",
"tag": "git tag -a v$npm_package_version -m \"Release v$npm_package_version\"",
"release": "npm run version && yarn && git add package.json yarn.lock && git commit -m \"chore(release): v$npm_package_version :tada:\"",
- "minify": "babel-minify dist -d dist",
- "prepublishOnly": "npm run test -- --no-cache && npm run build && npm run minify && npm run release && npm run tag"
+ "prepublishOnly": "npm run test -- --no-cache && npm run build && npm run release && npm run tag"
},
"jest": {
"collectCoverage": true,
"collectCoverageFrom": [
- "/src/**/*.ts"
+ "/src/**/*.ts",
+ "!/src/types/**/*.ts"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
diff --git a/src/autoProcess.ts b/src/autoProcess.ts
index 7a2b8ecf..e54df727 100644
--- a/src/autoProcess.ts
+++ b/src/autoProcess.ts
@@ -1,58 +1,53 @@
-import stripIndent from 'strip-indent';
-import { version } from 'svelte/package.json';
-
import {
PreprocessorGroup,
- TransformerOptions,
Preprocessor,
- Options,
Processed,
+ TransformerArgs,
+ TransformerOptions,
+ Transformers,
+ Options,
} from './types';
-import { hasPostCssInstalled } from './modules/hasPostcssInstalled';
+import { hasDepInstalled } from './modules/hasDepInstalled';
import { concat } from './modules/concat';
-import { parseFile } from './modules/parseFile';
-import { addLanguageAlias } from './modules/language';
-import { runTransformer } from './modules/transformers';
-import { throwUnsupportedError } from './modules/errors';
-
-interface Transformers {
- typescript?: TransformerOptions;
- scss?: TransformerOptions;
- sass?: TransformerOptions;
- less?: TransformerOptions;
- stylus?: TransformerOptions;
- postcss?: TransformerOptions;
- coffeescript?: TransformerOptions;
- pug?: TransformerOptions;
- globalStyle?: Options.GlobalStyle;
- replace?: Options.Replace;
- [languageName: string]: TransformerOptions;
-}
+import { getTagInfo } from './modules/tagInfo';
+import {
+ addLanguageAlias,
+ getLanguageFromAlias,
+ SOURCE_MAP_PROP_MAP,
+} from './modules/language';
+import { prepareContent } from './modules/prepareContent';
+
+type AutoPreprocessGroup = PreprocessorGroup & {
+ defaultLanguages: Readonly<{
+ markup: string;
+ style: string;
+ script: string;
+ }>;
+};
type AutoPreprocessOptions = {
- /** @deprecated for svelte v3 use instead a array of processors */
- onBefore?: ({
- content,
- filename,
- }: {
- content: string;
- filename: string;
- }) => Promise | string;
markupTagName?: string;
- /** @deprecated add transformer config directly to svelte-preprocess options object */
- transformers?: Transformers;
aliases?: Array<[string, string]>;
preserve?: string[];
+ defaults?: {
+ markup?: string;
+ style?: string;
+ script?: string;
+ };
+ sourceMap?: boolean;
+
+ // transformers
typescript?: TransformerOptions;
scss?: TransformerOptions;
sass?: TransformerOptions;
less?: TransformerOptions;
stylus?: TransformerOptions;
postcss?: TransformerOptions;
- babel?: TransformerOptions;
coffeescript?: TransformerOptions;
pug?: TransformerOptions;
- globalStyle?: Options.GlobalStyle;
+ globalStyle?: Options.GlobalStyle | boolean;
+ replace?: Options.Replace;
+
// workaround while we don't have this
// https://github.com/microsoft/TypeScript/issues/17867
[languageName: string]:
@@ -63,26 +58,56 @@ type AutoPreprocessOptions = {
| TransformerOptions;
};
-const SVELTE_MAJOR_VERSION = +version[0];
const ALIAS_OPTION_OVERRIDES: Record = {
sass: {
indentedSyntax: true,
},
};
+export const runTransformer = async (
+ name: string,
+ options: TransformerOptions,
+ { content, map, filename, attributes }: TransformerArgs,
+): Promise => {
+ if (options === false) {
+ return { code: content };
+ }
+
+ if (typeof options === 'function') {
+ return options({ content, map, filename, attributes });
+ }
+
+ const { transformer } = await import(`./transformers/${name}`);
+
+ return transformer({
+ content,
+ filename,
+ map,
+ attributes,
+ options: typeof options === 'boolean' ? null : options,
+ });
+};
+
export function autoPreprocess(
{
- onBefore,
aliases,
markupTagName = 'template',
preserve = [],
+ defaults,
+ sourceMap = false,
...rest
- }: AutoPreprocessOptions = {} as AutoPreprocessOptions,
-): PreprocessorGroup {
+ } = {} as AutoPreprocessOptions,
+): AutoPreprocessGroup {
markupTagName = markupTagName.toLocaleLowerCase();
- const optionsCache: Record = {};
- const transformers = rest.transformers || (rest as Transformers);
+ const defaultLanguages = Object.freeze({
+ markup: 'html',
+ style: 'css',
+ script: 'javascript',
+ ...defaults,
+ });
+
+ const transformers = rest as Transformers;
const markupPattern = new RegExp(
`<${markupTagName}([\\s\\S]*?)(?:>([\\s\\S]*)<\\/${markupTagName}>|/>)`,
);
@@ -92,59 +117,76 @@ export function autoPreprocess(
}
const getTransformerOptions = (
- lang: string,
- alias: string,
+ name: string,
+ alias?: string,
): TransformerOptions => {
- if (typeof transformers[alias] === 'function') return transformers[alias];
- if (typeof transformers[lang] === 'function') return transformers[lang];
- if (optionsCache[alias] != null) return optionsCache[alias];
+ const { [name]: nameOpts, [alias]: aliasOpts } = transformers;
+
+ if (typeof aliasOpts === 'function') return aliasOpts;
+ if (typeof nameOpts === 'function') return nameOpts;
+ if (aliasOpts === false || nameOpts === false) return false;
const opts: TransformerOptions = {};
- if (typeof transformers[lang] === 'object') {
- Object.assign(opts, transformers[lang]);
+ if (typeof nameOpts === 'object') {
+ Object.assign(opts, nameOpts);
}
- if (lang !== alias) {
+ if (name !== alias) {
Object.assign(opts, ALIAS_OPTION_OVERRIDES[alias] || null);
- if (typeof transformers[alias] === 'object') {
- Object.assign(opts, transformers[alias]);
+ if (typeof aliasOpts === 'object') {
+ Object.assign(opts, aliasOpts);
}
}
- return (optionsCache[alias] = opts);
+ if (sourceMap && name in SOURCE_MAP_PROP_MAP) {
+ const [propName, value] = SOURCE_MAP_PROP_MAP[name];
+
+ opts[propName] = value;
+ }
+
+ return opts;
};
- const getTransformerTo = (targetLanguage: string): Preprocessor => async (
- svelteFile,
- ) => {
- const {
+ const getTransformerTo = (
+ type: 'markup' | 'script' | 'style',
+ targetLanguage: string,
+ ): Preprocessor => async (svelteFile) => {
+ let {
content,
filename,
lang,
alias,
dependencies,
attributes,
- } = await parseFile(svelteFile, targetLanguage);
+ } = await getTagInfo(svelteFile);
+
+ if (lang == null || alias == null) {
+ alias = defaultLanguages[type];
+ lang = getLanguageFromAlias(alias);
+ }
if (preserve.includes(lang) || preserve.includes(alias)) {
- return;
+ return { code: content };
}
+ const transformerOptions = getTransformerOptions(lang, alias);
+
+ content = prepareContent({
+ options: transformerOptions,
+ content,
+ });
+
if (lang === targetLanguage) {
return { code: content, dependencies };
}
- if (transformers[lang] === false || transformers[alias] === false) {
- throwUnsupportedError(alias, filename);
- }
-
- const transformed = await runTransformer(
- lang,
- getTransformerOptions(lang, alias),
- { content: stripIndent(content), filename, attributes },
- );
+ const transformed = await runTransformer(lang, transformerOptions, {
+ content,
+ filename,
+ attributes,
+ });
return {
...transformed,
@@ -152,111 +194,111 @@ export function autoPreprocess(
};
};
- const scriptTransformer = getTransformerTo('javascript');
- const cssTransformer = getTransformerTo('css');
- const markupTransformer = getTransformerTo('html');
+ const scriptTransformer = getTransformerTo('script', 'javascript');
+ const cssTransformer = getTransformerTo('style', 'css');
+ const markupTransformer = getTransformerTo('markup', 'html');
- return {
- async markup({ content, filename }) {
- if (typeof onBefore === 'function') {
- // istanbul ignore next
- if (SVELTE_MAJOR_VERSION >= 3) {
- console.warn(
- '[svelte-preprocess] For svelte >= v3, instead of onBefore(), prefer to prepend a preprocess object to your array of preprocessors',
- );
- }
-
- content = await onBefore({ content, filename });
- }
-
- if (transformers.replace) {
- const transformed = await runTransformer(
- 'replace',
- transformers.replace,
- { content, filename },
- );
+ const markup: PreprocessorGroup['markup'] = async ({ content, filename }) => {
+ if (transformers.replace) {
+ const transformed = await runTransformer(
+ 'replace',
+ transformers.replace,
+ { content, filename },
+ );
- content = transformed.code;
- }
+ content = transformed.code;
+ }
- const templateMatch = content.match(markupPattern);
+ const templateMatch = content.match(markupPattern);
- /** If no was found, just return the original markup */
- if (!templateMatch) {
- return { code: content };
- }
+ /** If no was found, just return the original markup */
+ if (!templateMatch) {
+ return markupTransformer({ content, attributes: {}, filename });
+ }
- const [fullMatch, attributesStr, templateCode] = templateMatch;
+ const [fullMatch, attributesStr, templateCode] = templateMatch;
- /** Transform an attribute string into a key-value object */
- const attributes = attributesStr
- .split(/\s+/)
- .filter(Boolean)
- .reduce((acc: Record, attr) => {
- const [name, value] = attr.split('=');
+ /** Transform an attribute string into a key-value object */
+ const attributes = attributesStr
+ .split(/\s+/)
+ .filter(Boolean)
+ .reduce((acc: Record, attr) => {
+ const [name, value] = attr.split('=');
- // istanbul ignore next
- acc[name] = value ? value.replace(/['"]/g, '') : true;
+ // istanbul ignore next
+ acc[name] = value ? value.replace(/['"]/g, '') : true;
- return acc;
- }, {});
+ return acc;
+ }, {});
- /** Transform the found template code */
- let { code, map, dependencies } = await markupTransformer({
- content: templateCode,
- attributes,
- filename,
- });
+ /** Transform the found template code */
+ let { code, map, dependencies } = await markupTransformer({
+ content: templateCode,
+ attributes,
+ filename,
+ });
- code =
- content.slice(0, templateMatch.index) +
- code +
- content.slice(templateMatch.index + fullMatch.length);
+ code =
+ content.slice(0, templateMatch.index) +
+ code +
+ content.slice(templateMatch.index + fullMatch.length);
- return { code, map, dependencies };
- },
- async script({ content, attributes, filename }) {
- const transformResult: Processed = await scriptTransformer({
- content,
- attributes,
- filename,
- });
+ return { code, map, dependencies };
+ };
- if (transformResult == null) return;
+ const script: PreprocessorGroup['script'] = async ({
+ content,
+ attributes,
+ filename,
+ }) => {
+ const transformResult: Processed = await scriptTransformer({
+ content,
+ attributes,
+ filename,
+ });
- let { code, map, dependencies, diagnostics } = transformResult;
+ let { code, map, dependencies, diagnostics } = transformResult;
- if (transformers.babel) {
- const transformed = await runTransformer('babel', transformers.babel, {
+ if (transformers.babel) {
+ const transformed = await runTransformer(
+ 'babel',
+ getTransformerOptions('babel'),
+ {
content: code,
map,
filename,
attributes,
- });
+ },
+ );
- code = transformed.code;
- map = transformed.map;
- dependencies = concat(dependencies, transformed.dependencies);
- diagnostics = concat(diagnostics, transformed.diagnostics);
- }
+ code = transformed.code;
+ map = transformed.map;
+ dependencies = concat(dependencies, transformed.dependencies);
+ diagnostics = concat(diagnostics, transformed.diagnostics);
+ }
- return { code, map, dependencies, diagnostics };
- },
- async style({ content, attributes, filename }) {
- const transformResult = await cssTransformer({
- content,
- attributes,
- filename,
- });
+ return { code, map, dependencies, diagnostics };
+ };
- if (transformResult == null) return;
+ const style: PreprocessorGroup['style'] = async ({
+ content,
+ attributes,
+ filename,
+ }) => {
+ const transformResult = await cssTransformer({
+ content,
+ attributes,
+ filename,
+ });
- let { code, map, dependencies } = transformResult;
+ let { code, map, dependencies } = transformResult;
+ // istanbul ignore else
+ if (await hasDepInstalled('postcss')) {
if (transformers.postcss) {
const transformed = await runTransformer(
'postcss',
- transformers.postcss,
+ getTransformerOptions('postcss'),
{ content: code, map, filename, attributes },
);
@@ -265,23 +307,23 @@ export function autoPreprocess(
dependencies = concat(dependencies, transformed.dependencies);
}
- if (await hasPostCssInstalled()) {
- const transformed = await runTransformer(
- 'globalStyle',
- transformers?.globalStyle,
- {
- content: code,
- map,
- filename,
- attributes,
- },
- );
+ const transformed = await runTransformer(
+ 'globalStyle',
+ getTransformerOptions('globalStyle'),
+ { content: code, map, filename, attributes },
+ );
- code = transformed.code;
- map = transformed.map;
- }
+ code = transformed.code;
+ map = transformed.map;
+ }
- return { code, map, dependencies };
- },
+ return { code, map, dependencies };
+ };
+
+ return {
+ defaultLanguages,
+ markup,
+ script,
+ style,
};
}
diff --git a/src/modules/errors.ts b/src/modules/errors.ts
index d47bc3e6..c7336019 100644
--- a/src/modules/errors.ts
+++ b/src/modules/errors.ts
@@ -2,9 +2,6 @@ export const throwError = (msg: string) => {
throw new Error(`[svelte-preprocess] ${msg}`);
};
-export const throwUnsupportedError = (lang: string, filename: string) =>
- throwError(`Unsupported script language '${lang}' in file '${filename}'`);
-
export const throwTypescriptError = () => {
throwError(`Encountered type error`);
};
diff --git a/src/modules/globalifySelector.ts b/src/modules/globalifySelector.ts
index cdd54188..ef54ed95 100644
--- a/src/modules/globalifySelector.ts
+++ b/src/modules/globalifySelector.ts
@@ -1,9 +1,14 @@
-const combinatorPattern = /(\s*[ >+~,]\s*)(?![^[]+\])/g;
+/*
+ * Split a selector string (ex: div > foo ~ .potato) by
+ * separators: space, >, +, ~ and comma (maybe not needed)
+ * We use a negative lookbehind assertion to prevent matching
+ * escaped combinators like `\~`.
+ */
+const combinatorPattern = /(?+~,]\s*)(?![^[]+\])/g;
export function globalifySelector(selector: string) {
- return selector
- .trim()
- .split(combinatorPattern)
+ const parts = selector.trim().split(combinatorPattern);
+ const modifiedSelector = parts
.map((selectorPart: string, index: number) => {
// if this is the separator
if (index % 2 !== 0) {
@@ -25,4 +30,6 @@ export function globalifySelector(selector: string) {
return `:global(${selectorPart})`;
})
.join('');
+
+ return modifiedSelector;
}
diff --git a/src/modules/hasDepInstalled.ts b/src/modules/hasDepInstalled.ts
new file mode 100644
index 00000000..c503d68d
--- /dev/null
+++ b/src/modules/hasDepInstalled.ts
@@ -0,0 +1,18 @@
+const cachedResult: Record = {};
+
+export async function hasDepInstalled(dep: string) {
+ if (cachedResult[dep] != null) {
+ return cachedResult;
+ }
+
+ let result = false;
+
+ try {
+ await import(dep);
+ result = true;
+ } catch (e) {
+ result = false;
+ }
+
+ return (cachedResult[dep] = result);
+}
diff --git a/src/modules/hasPostcssInstalled.ts b/src/modules/hasPostcssInstalled.ts
deleted file mode 100644
index fe4f976b..00000000
--- a/src/modules/hasPostcssInstalled.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-let cachedResult: boolean;
-
-export async function hasPostCssInstalled() {
- if (cachedResult != null) {
- return cachedResult;
- }
-
- let result = false;
-
- try {
- await import('postcss');
- result = true;
- } catch (e) {
- result = false;
- }
-
- return (cachedResult = result);
-}
diff --git a/src/modules/language.ts b/src/modules/language.ts
index a1f1b1f8..4ba87350 100644
--- a/src/modules/language.ts
+++ b/src/modules/language.ts
@@ -2,6 +2,17 @@ import { basename } from 'path';
import { PreprocessorArgs } from '../types';
+export const SOURCE_MAP_PROP_MAP: Record = {
+ babel: ['sourceMaps', true],
+ typescript: ['sourceMap', true],
+ scss: ['sourceMap', true],
+ less: ['sourceMap', {}],
+ stylus: ['sourcemap', true],
+ postcss: ['map', true],
+ coffeescript: ['sourceMap', true],
+ globalStyle: ['sourceMap', true],
+};
+
export const ALIAS_MAP = new Map([
['pcss', 'css'],
['postcss', 'css'],
@@ -15,11 +26,12 @@ export const ALIAS_MAP = new Map([
export const addLanguageAlias = (entries: Array<[string, string]>) =>
entries.forEach((entry) => ALIAS_MAP.set(...entry));
-export const getLanguage = (
- attributes: PreprocessorArgs['attributes'],
- defaultLang: string,
-) => {
- let lang = defaultLang;
+export const getLanguageFromAlias = (alias: string | null) => {
+ return ALIAS_MAP.get(alias) || alias;
+};
+
+export const getLanguage = (attributes: PreprocessorArgs['attributes']) => {
+ let alias = null;
if (attributes.lang) {
// istanbul ignore if
@@ -27,14 +39,14 @@ export const getLanguage = (
throw new Error('lang attribute must be string');
}
- lang = attributes.lang;
+ alias = attributes.lang;
} else if (attributes.type) {
// istanbul ignore if
if (typeof attributes.type !== 'string') {
throw new Error('type attribute must be string');
}
- lang = attributes.type.replace(/^(text|application)\/(.*)$/, '$2');
+ alias = attributes.type.replace(/^(text|application)\/(.*)$/, '$2');
} else if (attributes.src) {
// istanbul ignore if
if (typeof attributes.src !== 'string') {
@@ -43,11 +55,13 @@ export const getLanguage = (
const parts = basename(attributes.src).split('.');
- lang = parts.length > 1 ? parts.pop() : defaultLang;
+ if (parts.length > 1) {
+ alias = parts.pop();
+ }
}
return {
- lang: ALIAS_MAP.get(lang) || lang,
- alias: lang,
+ lang: getLanguageFromAlias(alias),
+ alias,
};
};
diff --git a/src/modules/prepareContent.ts b/src/modules/prepareContent.ts
new file mode 100644
index 00000000..578e2505
--- /dev/null
+++ b/src/modules/prepareContent.ts
@@ -0,0 +1,21 @@
+import stripIndent from 'strip-indent';
+
+export function prepareContent({
+ options,
+ content,
+}: {
+ options: any;
+ content: string;
+}) {
+ if (typeof options !== 'object') {
+ return content;
+ }
+
+ content = stripIndent(content);
+
+ if (options.prependData) {
+ content = `${options.prependData}\n${content}`;
+ }
+
+ return content;
+}
diff --git a/src/modules/parseFile.ts b/src/modules/tagInfo.ts
similarity index 81%
rename from src/modules/parseFile.ts
rename to src/modules/tagInfo.ts
index c76eb5a7..49639d20 100644
--- a/src/modules/parseFile.ts
+++ b/src/modules/tagInfo.ts
@@ -4,10 +4,10 @@ import { resolve, dirname } from 'path';
import { PreprocessorArgs } from '../types';
import { getLanguage } from './language';
-export const resolveSrc = (importerFile: string, srcPath: string) =>
+const resolveSrc = (importerFile: string, srcPath: string) =>
resolve(dirname(importerFile), srcPath);
-export const getSrcContent = (file: string): Promise => {
+const getSrcContent = (file: string): Promise => {
return new Promise((resolve, reject) => {
readFile(file, (error: Error, data: unknown) => {
// istanbul ignore if
@@ -21,10 +21,11 @@ async function doesFileExist(file: string) {
return new Promise((resolve) => access(file, 0, (err) => resolve(!err)));
}
-export const parseFile = async (
- { attributes, filename, content }: PreprocessorArgs,
- language: string,
-) => {
+export const getTagInfo = async ({
+ attributes,
+ filename,
+ content,
+}: PreprocessorArgs) => {
const dependencies = [];
/** only include src file if content of tag is empty */
@@ -48,7 +49,7 @@ export const parseFile = async (
}
}
- const { lang, alias } = getLanguage(attributes, language);
+ const { lang, alias } = getLanguage(attributes);
return {
filename,
diff --git a/src/modules/transformers.ts b/src/modules/transformers.ts
deleted file mode 100644
index 044abc6e..00000000
--- a/src/modules/transformers.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import stripIndent from 'strip-indent';
-
-import { Transformer, TransformerArgs, TransformerOptions } from '../types';
-import { throwError } from './errors';
-
-const TRANSFORMERS = {} as {
- [key: string]: Transformer;
-};
-
-export const runTransformer = async (
- name: string,
- options: TransformerOptions,
- { content, map, filename, attributes }: TransformerArgs,
-): Promise>> => {
- // remove any unnecessary indentation (useful for coffee, pug and sugarss)
- content = stripIndent(content);
-
- if (typeof options === 'function') {
- return options({ content, map, filename, attributes });
- }
-
- try {
- if (!TRANSFORMERS[name]) {
- await import(`../transformers/${name}`).then((mod) => {
- // istanbul ignore else
- TRANSFORMERS[name] = mod.default;
- });
- }
-
- return TRANSFORMERS[name]({
- content,
- filename,
- map,
- attributes,
- options: typeof options === 'boolean' ? null : options,
- });
- } catch (e) {
- throwError(
- `Error transforming '${name}'.\n\nMessage:\n${e.message}\n\nStack:\n${e.stack}`,
- );
- }
-};
diff --git a/src/processors/babel.ts b/src/processors/babel.ts
index 0699a1ba..a7a6cfe8 100644
--- a/src/processors/babel.ts
+++ b/src/processors/babel.ts
@@ -1,16 +1,18 @@
import { PreprocessorGroup, Options } from '../types';
import { concat } from '../modules/concat';
-import { parseFile } from '../modules/parseFile';
+import { getTagInfo } from '../modules/tagInfo';
+import { prepareContent } from '../modules/prepareContent';
export default (options?: Options.Babel): PreprocessorGroup => ({
async script(svelteFile) {
- const { default: transformer } = await import('../transformers/babel');
+ const { transformer } = await import('../transformers/babel');
- const { content, filename, dependencies, attributes } = await parseFile(
+ let { content, filename, dependencies, attributes } = await getTagInfo(
svelteFile,
- 'javascript',
);
+ content = prepareContent({ options, content });
+
const transformed = await transformer({
content,
filename,
diff --git a/src/processors/coffeescript.ts b/src/processors/coffeescript.ts
index 27456276..a01cbe57 100644
--- a/src/processors/coffeescript.ts
+++ b/src/processors/coffeescript.ts
@@ -1,20 +1,21 @@
import { PreprocessorGroup, Options } from '../types';
-import { parseFile } from '../modules/parseFile';
+import { getTagInfo } from '../modules/tagInfo';
import { concat } from '../modules/concat';
+import { prepareContent } from '../modules/prepareContent';
export default (options?: Options.Coffeescript): PreprocessorGroup => ({
async script(svelteFile) {
- const { default: transformer } = await import(
- '../transformers/coffeescript'
- );
+ const { transformer } = await import('../transformers/coffeescript');
- const {
+ let {
content,
filename,
attributes,
lang,
dependencies,
- } = await parseFile(svelteFile, 'javascript');
+ } = await getTagInfo(svelteFile);
+
+ content = prepareContent({ options, content });
if (lang !== 'coffeescript') {
return { code: content };
diff --git a/src/processors/globalStyle.ts b/src/processors/globalStyle.ts
index 6dd1666c..f1a86bd8 100644
--- a/src/processors/globalStyle.ts
+++ b/src/processors/globalStyle.ts
@@ -3,9 +3,7 @@ import { PreprocessorGroup } from '../types';
export default (): PreprocessorGroup => {
return {
async style({ content, attributes, filename }) {
- const { default: transformer } = await import(
- '../transformers/globalStyle'
- );
+ const { transformer } = await import('../transformers/globalStyle');
if (!attributes.global) {
return { code: content };
diff --git a/src/processors/less.ts b/src/processors/less.ts
index 7b9a0613..f087193b 100644
--- a/src/processors/less.ts
+++ b/src/processors/less.ts
@@ -1,17 +1,20 @@
import { PreprocessorGroup, Options } from '../types';
-import { parseFile } from '../modules/parseFile';
+import { getTagInfo } from '../modules/tagInfo';
import { concat } from '../modules/concat';
+import { prepareContent } from '../modules/prepareContent';
export default (options?: Options.Less): PreprocessorGroup => ({
async style(svelteFile) {
- const { default: transformer } = await import('../transformers/less');
- const {
+ const { transformer } = await import('../transformers/less');
+ let {
content,
filename,
attributes,
lang,
dependencies,
- } = await parseFile(svelteFile, 'css');
+ } = await getTagInfo(svelteFile);
+
+ content = prepareContent({ options, content });
if (lang !== 'less') {
return { code: content };
diff --git a/src/processors/postcss.ts b/src/processors/postcss.ts
index 657fcaa1..e9c44aa4 100644
--- a/src/processors/postcss.ts
+++ b/src/processors/postcss.ts
@@ -1,16 +1,18 @@
-import { parseFile } from '../modules/parseFile';
import { PreprocessorGroup, Options } from '../types';
+import { getTagInfo } from '../modules/tagInfo';
import { concat } from '../modules/concat';
+import { prepareContent } from '../modules/prepareContent';
/** Adapted from https://github.com/TehShrike/svelte-preprocess-postcss */
export default (options?: Options.Postcss): PreprocessorGroup => ({
async style(svelteFile) {
- const { default: transformer } = await import('../transformers/postcss');
- const { content, filename, attributes, dependencies } = await parseFile(
+ const { transformer } = await import('../transformers/postcss');
+ let { content, filename, attributes, dependencies } = await getTagInfo(
svelteFile,
- 'css',
);
+ content = prepareContent({ options, content });
+
/** If manually passed a plugins array, use it as the postcss config */
const transformed = await transformer({
content,
diff --git a/src/processors/pug.ts b/src/processors/pug.ts
index db0341e0..6c02785c 100644
--- a/src/processors/pug.ts
+++ b/src/processors/pug.ts
@@ -1,12 +1,11 @@
-import stripIndent from 'strip-indent';
-
import { Options, PreprocessorGroup } from '../types';
+import { prepareContent } from '../modules/prepareContent';
export default (options?: Options.Pug): PreprocessorGroup => ({
async markup({ content, filename }) {
- const { default: transformer } = await import('../transformers/pug');
+ const { transformer } = await import('../transformers/pug');
- content = stripIndent(content);
+ content = prepareContent({ options, content });
return transformer({ content, filename, options });
},
diff --git a/src/processors/replace.ts b/src/processors/replace.ts
index 8cde52d0..e05b6f86 100644
--- a/src/processors/replace.ts
+++ b/src/processors/replace.ts
@@ -2,7 +2,7 @@ import { PreprocessorGroup, Options } from '../types';
export default (options: Options.Replace): PreprocessorGroup => ({
async markup({ content, filename }) {
- const { default: transformer } = await import('../transformers/replace');
+ const { transformer } = await import('../transformers/replace');
return transformer({ content, filename, options });
},
diff --git a/src/processors/scss.ts b/src/processors/scss.ts
index 2af985bf..e818c2ad 100644
--- a/src/processors/scss.ts
+++ b/src/processors/scss.ts
@@ -1,12 +1,11 @@
-import stripIndent from 'strip-indent';
-
-import { parseFile } from '../modules/parseFile';
import { PreprocessorGroup, Options } from '../types';
+import { getTagInfo } from '../modules/tagInfo';
import { concat } from '../modules/concat';
+import { prepareContent } from '../modules/prepareContent';
export default (options?: Options.Sass): PreprocessorGroup => ({
async style(svelteFile) {
- const { default: transformer } = await import('../transformers/scss');
+ const { transformer } = await import('../transformers/scss');
let {
content,
filename,
@@ -14,7 +13,9 @@ export default (options?: Options.Sass): PreprocessorGroup => ({
lang,
alias,
dependencies,
- } = await parseFile(svelteFile, 'css');
+ } = await getTagInfo(svelteFile);
+
+ content = prepareContent({ options, content });
if (lang !== 'scss') {
return { code: content };
@@ -25,8 +26,6 @@ export default (options?: Options.Sass): PreprocessorGroup => ({
...options,
indentedSyntax: true,
};
-
- content = stripIndent(content);
}
const transformed = await transformer({
diff --git a/src/processors/stylus.ts b/src/processors/stylus.ts
index 5d62efdf..2bcfde83 100644
--- a/src/processors/stylus.ts
+++ b/src/processors/stylus.ts
@@ -1,17 +1,20 @@
-import { parseFile } from '../modules/parseFile';
import { Options, PreprocessorGroup } from '../types';
+import { getTagInfo } from '../modules/tagInfo';
import { concat } from '../modules/concat';
+import { prepareContent } from '../modules/prepareContent';
export default (options?: Options.Stylus): PreprocessorGroup => ({
async style(svelteFile) {
- const { default: transformer } = await import('../transformers/stylus');
- const {
+ const { transformer } = await import('../transformers/stylus');
+ let {
content,
filename,
attributes,
lang,
dependencies,
- } = await parseFile(svelteFile, 'css');
+ } = await getTagInfo(svelteFile);
+
+ content = prepareContent({ options, content });
if (lang !== 'stylus') {
return { code: content };
diff --git a/src/processors/typescript.ts b/src/processors/typescript.ts
index 7902c918..59c135ea 100644
--- a/src/processors/typescript.ts
+++ b/src/processors/typescript.ts
@@ -1,17 +1,20 @@
import { Options, PreprocessorGroup } from '../types';
-import { parseFile } from '../modules/parseFile';
+import { getTagInfo } from '../modules/tagInfo';
import { concat } from '../modules/concat';
+import { prepareContent } from '../modules/prepareContent';
export default (options?: Options.Typescript): PreprocessorGroup => ({
async script(svelteFile) {
- const { default: transformer } = await import('../transformers/typescript');
- const {
+ const { transformer } = await import('../transformers/typescript');
+ let {
content,
filename,
attributes,
lang,
dependencies,
- } = await parseFile(svelteFile, 'javascript');
+ } = await getTagInfo(svelteFile);
+
+ content = prepareContent({ options, content });
if (lang !== 'typescript') {
return { code: content };
diff --git a/src/transformers/babel.ts b/src/transformers/babel.ts
index 4825fc69..e51378db 100644
--- a/src/transformers/babel.ts
+++ b/src/transformers/babel.ts
@@ -8,10 +8,6 @@ const transformer: Transformer = async ({
options,
map = undefined,
}) => {
- if (!options) {
- return { code: content, map };
- }
-
const { code, map: sourcemap } = await transformAsync(content, {
...options,
inputSourceMap: map as any,
@@ -30,4 +26,4 @@ const transformer: Transformer = async ({
};
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/coffeescript.ts b/src/transformers/coffeescript.ts
index 55f78c2a..e6b4b0cc 100644
--- a/src/transformers/coffeescript.ts
+++ b/src/transformers/coffeescript.ts
@@ -7,14 +7,27 @@ const transformer: Transformer = ({
filename,
options,
}) => {
- const { js: code, sourceMap: map } = coffeescript.compile(content, {
+ const coffeeOptions = {
filename,
- sourceMap: true,
+ /*
+ * Since `coffeescript` transpiles variables to `var` definitions, it uses a safety mechanism to prevent variables from bleeding to outside contexts. This mechanism consists of wrapping your `coffeescript` code inside an IIFE which, unfortunately, prevents `svelte` from finding your variables. To bypass this behavior, `svelte-preprocess` sets the [`bare` coffeescript compiler option](https://coffeescript.org/#lexical-scope) to `true`.
+ */
bare: true,
...options,
- });
+ };
- return { code, map };
+ if (coffeeOptions.sourceMap) {
+ const { js: code, sourceMap: map } = coffeescript.compile(
+ content,
+ coffeeOptions,
+ );
+
+ return { code, map };
+ }
+
+ const code = coffeescript.compile(content, coffeeOptions);
+
+ return { code };
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/globalStyle.ts b/src/transformers/globalStyle.ts
index dd57202f..ad20aac6 100644
--- a/src/transformers/globalStyle.ts
+++ b/src/transformers/globalStyle.ts
@@ -78,4 +78,4 @@ const transformer: Transformer = async ({
return { code: css, map: newMap };
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/less.ts b/src/transformers/less.ts
index 7564a0c4..74c0186d 100644
--- a/src/transformers/less.ts
+++ b/src/transformers/less.ts
@@ -26,4 +26,4 @@ const transformer: Transformer = async ({
};
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/postcss.ts b/src/transformers/postcss.ts
index 8972c518..957a8640 100644
--- a/src/transformers/postcss.ts
+++ b/src/transformers/postcss.ts
@@ -32,7 +32,7 @@ const transformer: Transformer = async ({
content,
filename,
options,
- map = undefined,
+ map,
}) => {
if (options && Array.isArray(options.plugins)) {
return process(options, content, filename, map);
@@ -68,4 +68,4 @@ const transformer: Transformer = async ({
return process(options, content, filename, map);
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/pug.ts b/src/transformers/pug.ts
index 8c38b385..8355e6d1 100644
--- a/src/transformers/pug.ts
+++ b/src/transformers/pug.ts
@@ -68,4 +68,4 @@ const transformer: Transformer = async ({
};
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/replace.ts b/src/transformers/replace.ts
index 75a16f31..b538ac23 100644
--- a/src/transformers/replace.ts
+++ b/src/transformers/replace.ts
@@ -7,7 +7,7 @@ const transformer: Transformer = async ({
let newContent = content;
for (const [regex, replacer] of options) {
- newContent = newContent.replace(regex, replacer);
+ newContent = newContent.replace(regex, replacer as any);
}
return {
@@ -15,4 +15,4 @@ const transformer: Transformer = async ({
};
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/scss.ts b/src/transformers/scss.ts
index 26ffef1c..2f58df7b 100644
--- a/src/transformers/scss.ts
+++ b/src/transformers/scss.ts
@@ -28,20 +28,22 @@ const transformer: Transformer = async ({
let implementation = options?.implementation ?? sass;
if (implementation == null) {
- const mod = await importAny('node-sass', 'sass');
+ const mod = await importAny('sass', 'node-sass');
// eslint-disable-next-line no-multi-assign
implementation = sass = mod.default;
}
- const { renderSync, ...sassOptions }: Options.Sass = {
- sourceMap: true,
+ const { renderSync, prependData, ...restOptions } = {
...options,
includePaths: getIncludePaths(filename, options.includePaths),
outFile: `${filename}.css`,
};
- sassOptions.data = options.data ? options.data + content : content;
+ const sassOptions = {
+ ...restOptions,
+ data: prependData ? `${prependData}${content}` : content,
+ };
// scss errors if passed an empty string
if (sassOptions.data.length === 0) {
@@ -61,4 +63,4 @@ const transformer: Transformer = async ({
});
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/stylus.ts b/src/transformers/stylus.ts
index 7d0f3d05..159dd82a 100644
--- a/src/transformers/stylus.ts
+++ b/src/transformers/stylus.ts
@@ -3,7 +3,7 @@ import path from 'path';
import stylus from 'stylus';
import { getIncludePaths } from '../modules/getIncludePaths';
-import { Processed, Transformer, Options } from '../types';
+import { Transformer, Options } from '../types';
const transformer: Transformer = ({
content,
@@ -15,7 +15,7 @@ const transformer: Transformer = ({
...options,
};
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, reject) => {
const style = stylus(content, {
filename,
...options,
@@ -37,4 +37,4 @@ const transformer: Transformer = ({
});
};
-export default transformer;
+export { transformer };
diff --git a/src/transformers/typescript.ts b/src/transformers/typescript.ts
index b00ca51e..91709ca9 100644
--- a/src/transformers/typescript.ts
+++ b/src/transformers/typescript.ts
@@ -1,10 +1,9 @@
-import { existsSync } from 'fs';
-import { dirname, basename, resolve } from 'path';
+import { dirname } from 'path';
import ts from 'typescript';
-import { Transformer, Options } from '../types';
import { throwTypescriptError } from '../modules/errors';
+import type { Transformer, Options } from '../types';
type CompilerOptions = Options.Typescript['compilerOptions'];
@@ -33,45 +32,6 @@ function formatDiagnostics(
);
}
-function getFilenameExtension(filename: string) {
- filename = basename(filename);
- const lastDotIndex = filename.lastIndexOf('.');
-
- if (lastDotIndex <= 0) return '';
-
- return filename.substr(lastDotIndex + 1);
-}
-
-function isSvelteFile(filename: string) {
- const importExtension = getFilenameExtension(filename);
-
- return importExtension === 'svelte' || importExtension === 'html';
-}
-
-const IMPORTEE_PATTERN = /['"](.*?)['"]/;
-
-function isValidSvelteImportDiagnostic(filename: string, diagnostic: any) {
- // TS2307: 'cannot find module'
- if (diagnostic.code !== 2307) return true;
-
- const importeeMatch = diagnostic.messageText.match(IMPORTEE_PATTERN);
-
- // istanbul ignore if
- if (!importeeMatch) return true;
-
- let [, importeePath] = importeeMatch;
-
- /** if we're not dealing with a relative path, assume the file exists */
- if (importeePath[0] !== '.') return false;
-
- /** if the importee is not a svelte file, do nothing */
- if (!isSvelteFile(importeePath)) return true;
-
- importeePath = resolve(dirname(filename), importeePath);
-
- return existsSync(importeePath) === false;
-}
-
const importTransformer: ts.TransformerFactory = (context) => {
const visit: ts.Visitor = (node) => {
if (ts.isImportDeclaration(node)) {
@@ -93,200 +53,6 @@ const importTransformer: ts.TransformerFactory = (context) => {
return (node) => ts.visitNode(node, visit);
};
-const TS_TRANSFORMERS = {
- before: [importTransformer],
-};
-
-const TS2552_REGEX = /Cannot find name '\$([a-zA-Z0-9_]+)'. Did you mean '([a-zA-Z0-9_]+)'\?/i;
-
-function isValidSvelteReactiveValueDiagnostic(
- filename: string,
- diagnostic: any,
-): boolean {
- if (diagnostic.code !== 2552) return true;
-
- /** if the importee is not a svelte file, do nothing */
- if (!isSvelteFile(filename)) return true;
-
- /** if error message doesn't contain a reactive value, do nothing */
- if (!diagnostic.messageText.includes('$')) return true;
-
- const [, usedVar, proposedVar] =
- diagnostic.messageText.match(TS2552_REGEX) || [];
-
- return !(usedVar && proposedVar && usedVar === proposedVar);
-}
-
-function createImportTransformerFromProgram(program: ts.Program) {
- const checker = program.getTypeChecker();
-
- const importedTypeRemoverTransformer: ts.TransformerFactory = (
- context,
- ) => {
- const visit: ts.Visitor = (node) => {
- if (!ts.isImportDeclaration(node)) {
- return ts.visitEachChild(node, (child) => visit(child), context);
- }
-
- let newImportClause: ts.ImportClause = node.importClause;
-
- if (node.importClause) {
- // import type {...} from './blah'
- if (node.importClause?.isTypeOnly) {
- return ts.createEmptyStatement();
- }
-
- // import Blah, { blah } from './blah'
- newImportClause = ts.getMutableClone(node.importClause);
-
- // types can't be default exports, so we just worry about { blah } and { blah as name } exports
- if (
- newImportClause.namedBindings &&
- ts.isNamedImports(newImportClause.namedBindings)
- ) {
- const newBindings = ts.getMutableClone(newImportClause.namedBindings);
- const newElements = [];
-
- newImportClause.namedBindings = undefined;
-
- for (const spec of newBindings.elements) {
- const ident = spec.name;
-
- const symbol = checker.getSymbolAtLocation(ident);
- const aliased = checker.getAliasedSymbol(symbol);
-
- if (aliased) {
- if (
- (aliased.flags &
- (ts.SymbolFlags.TypeAlias | ts.SymbolFlags.Interface)) >
- 0
- ) {
- // We found an imported type, don't add to our new import clause
- continue;
- }
- }
-
- newElements.push(spec);
- }
-
- if (newElements.length > 0) {
- newBindings.elements = ts.createNodeArray(
- newElements,
- newBindings.elements.hasTrailingComma,
- );
- newImportClause.namedBindings = newBindings;
- }
- }
-
- // we ended up removing all named bindings and we didn't have a name? nothing left to import.
- if (
- newImportClause.namedBindings == null &&
- newImportClause.name == null
- ) {
- return ts.createEmptyStatement();
- }
- }
-
- return ts.createImportDeclaration(
- node.decorators,
- node.modifiers,
- newImportClause,
- node.moduleSpecifier,
- );
- };
-
- return (node) => ts.visitNode(node, visit);
- };
-
- return importedTypeRemoverTransformer;
-}
-
-export function compileFileFromMemory(
- compilerOptions: CompilerOptions,
- { filename, content }: { filename: string; content: string },
-) {
- let code = content;
- let map;
-
- const realHost = ts.createCompilerHost(compilerOptions, true);
- const dummyFileName = ts.sys.resolvePath(filename);
-
- const isDummyFile = (fileName: string) =>
- ts.sys.resolvePath(fileName) === dummyFileName;
-
- const host: ts.CompilerHost = {
- fileExists: (fileName) =>
- isDummyFile(fileName) || realHost.fileExists(fileName),
- getCanonicalFileName: (fileName) =>
- isDummyFile(fileName)
- ? ts.sys.useCaseSensitiveFileNames
- ? fileName
- : fileName.toLowerCase()
- : realHost.getCanonicalFileName(fileName),
- getSourceFile: (
- fileName,
- languageVersion,
- onError,
- shouldCreateNewSourceFile,
- // eslint-disable-next-line max-params
- ) =>
- isDummyFile(fileName)
- ? ts.createSourceFile(dummyFileName, code, languageVersion)
- : realHost.getSourceFile(
- fileName,
- languageVersion,
- onError,
- shouldCreateNewSourceFile,
- ),
- readFile: (fileName) =>
- isDummyFile(fileName) ? content : realHost.readFile(fileName),
- writeFile: (fileName, data) => {
- if (fileName.endsWith('.map')) {
- map = data;
- } else {
- code = data;
- }
- },
- directoryExists:
- realHost.directoryExists && realHost.directoryExists.bind(realHost),
- getCurrentDirectory: realHost.getCurrentDirectory.bind(realHost),
- getDirectories: realHost.getDirectories.bind(realHost),
- getNewLine: realHost.getNewLine.bind(realHost),
- getDefaultLibFileName: realHost.getDefaultLibFileName.bind(realHost),
- resolveModuleNames:
- realHost.resolveModuleNames && realHost.resolveModuleNames.bind(realHost),
- useCaseSensitiveFileNames: realHost.useCaseSensitiveFileNames.bind(
- realHost,
- ),
- };
-
- const program = ts.createProgram([dummyFileName], compilerOptions, host);
-
- const transformers = {
- before: [createImportTransformerFromProgram(program)],
- };
-
- const emitResult = program.emit(
- program.getSourceFile(dummyFileName),
- undefined,
- undefined,
- undefined,
- transformers,
- );
-
- // collect diagnostics without svelte import errors
- const diagnostics = [
- ...emitResult.diagnostics,
- ...ts.getPreEmitDiagnostics(program),
- ].filter(
- (diagnostic) =>
- isValidSvelteImportDiagnostic(filename, diagnostic) &&
- isValidSvelteReactiveValueDiagnostic(filename, diagnostic),
- );
-
- return { code, map, diagnostics };
-}
-
const transformer: Transformer = ({
content,
filename,
@@ -349,26 +115,18 @@ const transformer: Transformer = ({
);
}
- let code;
- let map;
- let diagnostics: ts.Diagnostic[];
-
- if (options.transpileOnly || compilerOptions.transpileOnly) {
- ({ outputText: code, sourceMapText: map, diagnostics } = ts.transpileModule(
- content,
- {
- fileName: filename,
- compilerOptions,
- reportDiagnostics: options.reportDiagnostics !== false,
- transformers: TS_TRANSFORMERS,
- },
- ));
- } else {
- ({ code, map, diagnostics } = compileFileFromMemory(compilerOptions, {
- filename,
- content,
- }));
- }
+ const {
+ outputText: code,
+ sourceMapText: map,
+ diagnostics,
+ } = ts.transpileModule(content, {
+ fileName: filename,
+ compilerOptions,
+ reportDiagnostics: options.reportDiagnostics !== false,
+ transformers: {
+ before: [importTransformer],
+ },
+ });
if (diagnostics.length > 0) {
// could this be handled elsewhere?
@@ -389,8 +147,7 @@ const transformer: Transformer = ({
code,
map,
diagnostics,
- dependencies: [] as string[],
};
};
-export default transformer;
+export { transformer };
diff --git a/src/types/index.ts b/src/types/index.ts
index 9988ed76..03e58748 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -17,14 +17,14 @@ export type PreprocessorArgs = Preprocessor extends (options: infer T) => any
? T
: never;
-export interface TransformerArgs {
+export type TransformerArgs = {
content: string;
filename: string;
attributes?: Record;
map?: string | object;
dianostics?: unknown[];
options?: T;
-}
+};
export type Processed = SvelteProcessed & {
diagnostics?: any[];
@@ -38,3 +38,17 @@ export type TransformerOptions =
| boolean
| Record
| Transformer;
+
+export interface Transformers {
+ typescript?: TransformerOptions;
+ scss?: TransformerOptions;
+ sass?: TransformerOptions;
+ less?: TransformerOptions;
+ stylus?: TransformerOptions;
+ postcss?: TransformerOptions;
+ coffeescript?: TransformerOptions;
+ pug?: TransformerOptions;
+ globalStyle?: Options.GlobalStyle;
+ replace?: Options.Replace;
+ [language: string]: TransformerOptions;
+}
diff --git a/src/types/options.ts b/src/types/options.ts
index 9bc437bc..cdc1c386 100644
--- a/src/types/options.ts
+++ b/src/types/options.ts
@@ -1,44 +1,45 @@
import postcss from 'postcss';
import { Options as SassOptions, render, renderSync } from 'sass';
import { Options as PugOptions } from 'pug';
-import { CompilerOptions } from 'typescript';
import { TransformOptions as BabelOptions } from '@babel/core';
-export type Replace = Array<
- [RegExp, (substring: string, ...args: any[]) => string | string]
->;
+type ContentModifier = {
+ prependData?: string;
+};
-export interface Coffeescript {
- inlineMap?: boolean;
- filename?: string;
- bare?: boolean;
- header?: boolean;
- transpile?: any;
-}
+export type Coffeescript = {
+ sourceMap?: boolean;
+ filename?: never;
+ bare?: never;
+} & ContentModifier;
-export interface Postcss extends postcss.ProcessOptions {
+export type Postcss = postcss.ProcessOptions & {
plugins: postcss.AcceptedPlugin[];
+ // custom
configFilePath?: string;
-}
+} & ContentModifier;
-export interface Babel extends BabelOptions {
+export type Babel = BabelOptions & {
sourceType?: 'module';
minified?: false;
ast?: false;
code?: true;
sourceMaps?: boolean;
-}
+} & ContentModifier;
-export type Pug = PugOptions;
-export type Sass = Omit & {
+export type Pug = PugOptions & ContentModifier;
+
+export type Sass = Omit & {
+ // custom
implementation?: {
render?: typeof render;
renderSync?: typeof renderSync;
};
renderSync?: boolean;
-};
+} & ContentModifier;
+
// from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/less/index.d.ts#L80
-export interface Less {
+export type Less = {
paths?: string[];
plugins?: any[];
strictImports?: boolean;
@@ -48,26 +49,30 @@ export interface Less {
strictUnits?: boolean;
globalVars?: Record;
modifyVars?: Record;
-}
+} & ContentModifier;
// from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/stylus/index.d.ts#L1410
-export interface Stylus {
+export type Stylus = {
globals?: Record;
functions?: Record;
imports?: string[];
paths?: string[];
// custom
sourcemap?: boolean;
-}
+} & ContentModifier;
-export interface Typescript {
- compilerOptions?: CompilerOptions & { transpileOnly?: boolean };
+export type Typescript = {
+ compilerOptions?: any;
+ // custom
tsconfigFile?: string | boolean;
tsconfigDirectory?: string | boolean;
- transpileOnly?: boolean;
reportDiagnostics?: boolean;
-}
+} & ContentModifier;
export interface GlobalStyle {
sourceMap: boolean;
}
+
+export type Replace = Array<
+ [RegExp, string] | [RegExp, (substring: string, ...args: any[]) => string]
+>;
diff --git a/test/autoProcess/autoProcess.test.ts b/test/autoProcess/autoProcess.test.ts
index ae8884b4..1441fd9e 100644
--- a/test/autoProcess/autoProcess.test.ts
+++ b/test/autoProcess/autoProcess.test.ts
@@ -1,4 +1,4 @@
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import {
preprocess,
getFixtureContent,
@@ -13,7 +13,6 @@ describe('detect - mimetype', () => {
{ type: 'text/some-other', targetLanguage: 'some-other' },
{ lang: 'stylus', targetLanguage: 'stylus' },
{ src: '../foo.js', targetLanguage: 'javascript' },
- { src: '../foo', targetLanguage: 'javascript' },
{
src: '../foo.custom',
lang: 'customLanguage',
@@ -25,7 +24,7 @@ describe('detect - mimetype', () => {
it(`should detect '${
src || type || lang
}' as '${targetLanguage}'`, async () => {
- const language = getLanguage({ type, lang, src }, targetLanguage);
+ const language = getLanguage({ type, lang, src });
expect(language).toMatchObject({ lang: targetLanguage });
});
@@ -38,7 +37,7 @@ describe('options', () => {
'template.custom',
)}`;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
customTransformer({ content }) {
content = content.replace('foo', 'bar').toString().trim();
@@ -55,7 +54,7 @@ describe('options', () => {
const input = ``;
const preprocessed = await preprocess(
input,
- getAutoPreprocess({
+ autoPreprocess({
scss: {
sourceMap: false,
includedPaths: ['node_modules'],
@@ -66,22 +65,9 @@ describe('options', () => {
expect(preprocessed.toString()).toMatch(CSS_PATTERN);
});
- it('should execute a onBefore method before transforming markup', async () => {
- const input = `UPPERCASE?`;
- const opts = getAutoPreprocess({
- async onBefore({ content }) {
- return content.toLowerCase();
- },
- });
-
- const preprocessed = await preprocess(input, opts);
-
- expect(preprocessed.toString()).toBe(input.toLowerCase());
- });
-
it('should append aliases to the language alias dictionary', async () => {
const input = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
aliases: [['cl', 'javascript']],
});
@@ -90,7 +76,7 @@ describe('options', () => {
it('should allow to pass a method as an language alias transformer', async () => {
const input = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
aliases: [['cl', 'customLanguage']],
cl() {
return { code: 'div{}' };
@@ -106,7 +92,7 @@ describe('options', () => {
it('should allow to pass a method as an language transformer', async () => {
const input = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
aliases: [['cl', 'customLanguage']],
customLanguage() {
return { code: 'div{}' };
@@ -122,7 +108,7 @@ describe('options', () => {
it('should NOT preprocess preserved languages', async () => {
const input = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
preserve: ['ld+json'],
aliases: [['ld+json', 'structuredData']],
structuredData() {
@@ -142,7 +128,7 @@ describe('options', () => {
'style.sass',
)}`;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
sass: {
indentedSyntax: false,
},
@@ -151,16 +137,70 @@ describe('options', () => {
expect(await doesCompileThrow(input, opts)).toBe(true);
});
- it('should support the old `transformers` option', async () => {
- const input = ``;
- const opts = getAutoPreprocess({
- transformers: {
- mock: () => ({ code: 'mock' }),
+ it('should accept other languages as default', async () => {
+ const input = `markup`;
+
+ const opts = autoPreprocess({
+ defaults: {
+ markup: 'customMarkup',
+ script: 'customScript',
+ style: 'customStyle',
+ },
+ globalStyle: false,
+ customMarkup({ content }) {
+ return { code: content.replace('markup', 'potato') };
+ },
+ customScript({ content }) {
+ return { code: content.replace('script', 'potato') };
+ },
+ customStyle({ content }) {
+ return { code: content.replace('style', 'potato') };
+ },
+ });
+
+ const preprocessed = await preprocess(input, opts);
+
+ expect(preprocessed.toString()).toContain(
+ 'potato',
+ );
+ });
+
+ it('should respect lang/type attributes even if another default language is set', async () => {
+ const input = ``;
+
+ const opts = autoPreprocess({
+ defaults: {
+ script: 'potatoScript',
+ },
+ potatoScript({ content }) {
+ return { code: content.replace('script', 'potato') };
+ },
+ tomatoScript({ content }) {
+ return { code: content.replace('script', 'tomato') };
+ },
+ });
+
+ const preprocessed = await preprocess(input, opts);
+
+ expect(preprocessed.toString()).toContain(
+ '',
+ );
+ });
+
+ it('should be able to use default markup language with template tags', async () => {
+ const input = `potato`;
+
+ const opts = autoPreprocess({
+ defaults: {
+ markup: 'potatoScript',
+ },
+ potatoScript({ content }) {
+ return { code: content.replace('potato', 'french-fries') };
},
});
const preprocessed = await preprocess(input, opts);
- expect(preprocessed.toString()).toBe(``);
+ expect(preprocessed.toString()).toContain('french-fries');
});
});
diff --git a/test/autoProcess/externalFiles.test.ts b/test/autoProcess/externalFiles.test.ts
index 695de4eb..3c682a57 100644
--- a/test/autoProcess/externalFiles.test.ts
+++ b/test/autoProcess/externalFiles.test.ts
@@ -1,14 +1,21 @@
import { resolve } from 'path';
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { Processed } from '../../src/types';
-import { preprocess, getFixtureContent, getFixturePath } from '../utils';
+import {
+ preprocess,
+ getFixtureContent,
+ getFixturePath,
+ spyConsole,
+} from '../utils';
+
+const { warnSpy } = spyConsole();
const {
markup: markupProcessor,
script: scriptProcessor,
style: styleProcessor,
-} = getAutoPreprocess();
+} = autoPreprocess();
const REMOTE_JS = [
'https://www.example.com/some/externally/delivered/content.js',
@@ -58,7 +65,7 @@ describe('external files', () => {
it(`should not attempt to locally resolve ${url}`, async () => {
const input = ``;
- const preprocessed = await preprocess(input, getAutoPreprocess());
+ const preprocessed = await preprocess(input, autoPreprocess());
expect(preprocessed.toString()).toContain(input);
expect(preprocessed.dependencies).toHaveLength(0);
@@ -66,13 +73,12 @@ describe('external files', () => {
});
it("should warn if local file don't exist", async () => {
- const spy = jest.spyOn(console, 'warn');
const input = ``;
- await preprocess(input, getAutoPreprocess());
-
- expect(spy).toHaveBeenCalledWith(expect.stringContaining('was not found'));
+ await preprocess(input, autoPreprocess());
- spy.mockRestore();
+ expect(warnSpy).toHaveBeenCalledWith(
+ expect.stringContaining('was not found'),
+ );
});
});
diff --git a/test/autoProcess/markup.test.ts b/test/autoProcess/markup.test.ts
index 4338ba08..82fb2e4a 100644
--- a/test/autoProcess/markup.test.ts
+++ b/test/autoProcess/markup.test.ts
@@ -1,4 +1,4 @@
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { preprocess, getFixtureContent, doesCompileThrow } from '../utils';
const EXPECTED_MARKUP = getFixtureContent('template.html');
@@ -6,7 +6,7 @@ const MARKUP_LANGS: Array<[string, string]> = [['pug', 'pug']];
test('should transform HTML between ', async () => {
const input = `Hey
`;
- const preprocessed = await preprocess(input, getAutoPreprocess());
+ const preprocessed = await preprocess(input, autoPreprocess());
expect(preprocessed.toString()).toBe(
`${EXPECTED_MARKUP}`,
@@ -17,7 +17,7 @@ test('should transform HTML between custom tag ', async () => {
const input = `Hey
`;
const preprocessed = await preprocess(
input,
- getAutoPreprocess({ markupTagName: 'markup' }),
+ autoPreprocess({ markupTagName: 'markup' }),
);
expect(preprocessed.toString()).toBe(
@@ -29,7 +29,7 @@ test('should transform a custom language between Hey
`;
const preprocessed = await preprocess(
input,
- getAutoPreprocess({
+ autoPreprocess({
test() {
return { code: '' };
},
@@ -45,14 +45,14 @@ MARKUP_LANGS.forEach(([lang, ext]) => {
`template.${ext}`,
)}`;
- it(`should throw parsing ${lang} when { ${lang}: false }`, async () => {
- const opts = getAutoPreprocess({ pug: false });
+ it(`should NOT throw parsing ${lang} when { ${lang}: false }`, async () => {
+ const opts = autoPreprocess({ pug: false });
- expect(await doesCompileThrow(template, opts)).toBe(true);
+ expect(await doesCompileThrow(template, opts)).toBe(false);
});
it(`should parse ${lang}`, async () => {
- const preprocessed = (await preprocess(template, getAutoPreprocess()))
+ const preprocessed = (await preprocess(template, autoPreprocess()))
.toString()
.trim();
diff --git a/test/autoProcess/script.test.ts b/test/autoProcess/script.test.ts
index 878aa3bf..53ed5978 100644
--- a/test/autoProcess/script.test.ts
+++ b/test/autoProcess/script.test.ts
@@ -1,5 +1,5 @@
-import getAutoPreprocess from '../../src';
-import { preprocess, getFixtureContent, doesCompileThrow } from '../utils';
+import autoPreprocess from '../../src';
+import { preprocess, getFixtureContent } from '../utils';
const SCRIPT_LANGS: Array<[string, string, object?]> = [
['coffeescript', 'coffee'],
@@ -18,21 +18,8 @@ SCRIPT_LANGS.forEach(([lang, ext, langOptions]) => {
`script.${ext}`,
)}`;
- it(`should throw parsing ${lang} when { ${lang}: false }`, async () => {
- const input = `
-
-
- `;
-
- const opts = getAutoPreprocess({
- [lang]: false,
- });
-
- expect(await doesCompileThrow(input, opts)).toBe(true);
- });
-
it(`should parse ${lang}`, async () => {
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
[lang]: langOptions,
});
diff --git a/test/autoProcess/sourceMaps.test.ts b/test/autoProcess/sourceMaps.test.ts
new file mode 100644
index 00000000..0352801c
--- /dev/null
+++ b/test/autoProcess/sourceMaps.test.ts
@@ -0,0 +1,97 @@
+import autoPreprocess from '../../src';
+import { preprocess } from '../utils';
+import { transformer as babelTransformer } from '../../src/transformers/babel';
+import { transformer as coffeeTransformer } from '../../src/transformers/coffeescript';
+import { transformer as globalStyleTransformer } from '../../src/transformers/globalStyle';
+import { transformer as lessTransformer } from '../../src/transformers/less';
+import { transformer as postcssTransformer } from '../../src/transformers/postcss';
+import { transformer as scssTransformer } from '../../src/transformers/scss';
+import { transformer as stylusTransformer } from '../../src/transformers/stylus';
+import { transformer as typescriptTransformer } from '../../src/transformers/typescript';
+import { SOURCE_MAP_PROP_MAP } from '../../src/modules/language';
+
+const TRANSFORMERS: Record = {
+ babel: {
+ transformer: babelTransformer,
+ template: ``,
+ },
+ typescript: {
+ transformer: typescriptTransformer,
+ template: ``,
+ },
+ coffeescript: {
+ transformer: coffeeTransformer,
+ template: ``,
+ },
+ scss: {
+ transformer: scssTransformer,
+ template: ``,
+ },
+ less: {
+ transformer: lessTransformer,
+ template: ``,
+ },
+ stylus: {
+ transformer: stylusTransformer,
+ template: ``,
+ },
+ postcss: {
+ transformer: postcssTransformer,
+ template: ``,
+ },
+ globalStyle: {
+ transformer: globalStyleTransformer,
+ template: ``,
+ },
+};
+
+// todo: is there a better way to do this?
+jest.mock(`../../src/transformers/babel`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+jest.mock(`../../src/transformers/typescript`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+jest.mock(`../../src/transformers/coffeescript`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+jest.mock(`../../src/transformers/scss`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+jest.mock(`../../src/transformers/less`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+jest.mock(`../../src/transformers/stylus`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+jest.mock(`../../src/transformers/postcss`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+jest.mock(`../../src/transformers/globalStyle`, () => ({
+ transformer: jest.fn(() => ({ code: '' })),
+}));
+
+afterAll(() => {
+ jest.resetAllMocks();
+});
+
+describe(`sourcemap generation`, () => {
+ Object.entries(TRANSFORMERS).forEach(
+ ([transformerName, { transformer, template }]) => {
+ it(`${transformerName} - pass the appropriate source map option downwards to the transformer`, async () => {
+ const opts = autoPreprocess({
+ sourceMap: true,
+ [transformerName]: true,
+ });
+
+ const [key, val] = SOURCE_MAP_PROP_MAP[transformerName];
+
+ await preprocess(template, opts);
+
+ expect(transformer).toHaveBeenCalledWith(
+ expect.objectContaining({ options: { [key]: val } }),
+ );
+ });
+ },
+ );
+});
diff --git a/test/autoProcess/style.test.ts b/test/autoProcess/style.test.ts
index e484a620..9e22cf30 100644
--- a/test/autoProcess/style.test.ts
+++ b/test/autoProcess/style.test.ts
@@ -1,10 +1,5 @@
-import getAutoPreprocess from '../../src';
-import {
- preprocess,
- getFixtureContent,
- doesCompileThrow,
- CSS_PATTERN,
-} from '../utils';
+import autoPreprocess from '../../src';
+import { preprocess, getFixtureContent, CSS_PATTERN } from '../utils';
const STYLE_LANGS: Array<[string, string]> = [
['sass', 'sass'],
@@ -15,24 +10,12 @@ const STYLE_LANGS: Array<[string, string]> = [
STYLE_LANGS.forEach(([lang, ext]) => {
describe(`style - preprocessor - ${lang}`, () => {
- it(`should throw parsing ${lang} when { ${lang}: false }`, async () => {
- const template = ``;
-
- const opts = getAutoPreprocess({
- [lang]: false,
- });
-
- expect(await doesCompileThrow(template, opts)).toBe(true);
- });
-
it(`should parse ${lang}`, async () => {
const template = ``;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(template, opts);
expect(preprocessed.toString()).toMatch(CSS_PATTERN);
@@ -40,7 +23,7 @@ STYLE_LANGS.forEach(([lang, ext]) => {
it(`should parse external ${lang}`, async () => {
const templateExternal = ``;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(templateExternal, opts);
expect(preprocessed.toString()).toMatch(CSS_PATTERN);
@@ -48,7 +31,7 @@ STYLE_LANGS.forEach(([lang, ext]) => {
it(`should parse external ${lang}`, async () => {
const templateExternal = ``;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(templateExternal, opts);
expect(preprocessed.toString()).toMatch(CSS_PATTERN);
@@ -56,7 +39,7 @@ STYLE_LANGS.forEach(([lang, ext]) => {
it(`should return empty if content is empty`, async () => {
const templateExternal = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
[lang]: {
sourceMap: false,
sourcemap: false,
diff --git a/test/fixtures/types.ts b/test/fixtures/types.ts
index c25ea1d9..cbfedfd9 100644
--- a/test/fixtures/types.ts
+++ b/test/fixtures/types.ts
@@ -1,7 +1,7 @@
-export type AType = "test1" | "test2"
+export type AType = 'test1' | 'test2';
export interface AInterface {
- test: string
+ test: string;
}
-export const AValue: string = "test"
+export const AValue: string = 'test';
-export default "String"
\ No newline at end of file
+export default 'String';
diff --git a/test/modules.test.ts b/test/modules.test.ts
index c5039043..c09cc516 100644
--- a/test/modules.test.ts
+++ b/test/modules.test.ts
@@ -1,10 +1,11 @@
import { resolve } from 'path';
import { getTestAppFilename, getFixtureContent } from './utils';
-import { parseFile } from '../src/modules/parseFile';
+import { getTagInfo } from '../src/modules/tagInfo';
import { importAny } from '../src/modules/importAny';
import { getIncludePaths } from '../src/modules/getIncludePaths';
import { globalifySelector } from '../src/modules/globalifySelector';
+import { hasDepInstalled } from '../src/modules/hasDepInstalled';
describe('importAny', () => {
it('should throw error when none exist', () => {
@@ -71,29 +72,41 @@ describe('globalifySelector', () => {
);
expect(globalifySelector(selector2)).toEqual(':global(div), :global(span)');
});
+
+ it('correctly treats selectors with escaped combinator characters', async () => {
+ const selector1 = '.\\~positive.\\!normal ~ .\\+foo';
+
+ expect(globalifySelector(selector1)).toEqual(
+ ':global(.\\~positive.\\!normal) ~ :global(.\\+foo)',
+ );
+ });
});
-describe(`parse svelte file`, () => {
+describe(`get tag information`, () => {
it('should only include src files if content is empty', async () => {
- let parsedFile = await parseFile(
- {
- content: '',
- attributes: { src: './fixtures/style.scss' },
- filename: getTestAppFilename(),
- },
- 'css',
- );
+ let parsedFile = await getTagInfo({
+ content: '',
+ attributes: { src: './fixtures/style.scss' },
+ filename: getTestAppFilename(),
+ });
expect(parsedFile.content).toEqual(getFixtureContent('style.scss'));
- parsedFile = await parseFile(
- {
- ...parsedFile,
- attributes: { src: './fixtures/style.css' },
- },
- 'css',
- );
+ parsedFile = await getTagInfo({
+ ...parsedFile,
+ attributes: { src: './fixtures/style.css' },
+ });
expect(parsedFile.content).toEqual(getFixtureContent('style.scss'));
});
});
+
+describe('has dependency installed', () => {
+ it('should return true if dependency is installed', async () => {
+ expect(await hasDepInstalled('svelte')).toBe(true);
+ });
+
+ it('should return false if dependency is installed', async () => {
+ expect(await hasDepInstalled('potatonator')).toBe(false);
+ });
+});
diff --git a/test/processors.test.ts b/test/processors.test.ts
deleted file mode 100644
index c3f0bd71..00000000
--- a/test/processors.test.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import {
- scss,
- sass,
- less,
- stylus,
- postcss,
- coffeescript,
- typescript,
- pug,
- babel,
-} from '../src';
-import { CSS_PATTERN, getFixtureContent, preprocess } from './utils';
-
-const EXPECTED_SCRIPT = getFixtureContent('script.js');
-
-type ProcessorEntries = Array<[string, string, (...args: any) => any, any?]>;
-
-const STYLE_LANGS: ProcessorEntries = [
- ['sass', 'sass', sass],
- ['scss', 'scss', scss],
- ['less', 'less', less],
- ['stylus', 'styl', stylus],
- ['postcss', 'css', postcss],
-];
-
-const SCRIPT_LANGS: ProcessorEntries = [
- ['coffeescript', 'coffee', coffeescript],
- [
- 'typescript',
- 'ts',
- typescript,
- { tsconfigFile: false, compilerOptions: { module: 'es2015' } },
- ],
-];
-
-const MARKUP_LANGS: ProcessorEntries = [['pug', 'pug', pug]];
-
-STYLE_LANGS.forEach(([lang, ext, processor, options]) => {
- describe(`processor - ${lang}`, () => {
- it('should support external src files', async () => {
- const template = ``;
- const preprocessed = await preprocess(template, [processor(options)]);
-
- expect(preprocessed.toString()).toMatch(CSS_PATTERN);
- });
- });
-});
-
-SCRIPT_LANGS.forEach(([lang, ext, processor, options]) => {
- describe(`processor - ${lang}`, () => {
- it('should support external src files', async () => {
- const template = ``;
- const preprocessed = await preprocess(template, [processor(options)]);
-
- expect(preprocessed.toString()).toContain(EXPECTED_SCRIPT);
- });
- });
-});
-
-MARKUP_LANGS.forEach(([lang, _, processor, options]) => {
- const EXPECTED_TEMPLATE = getFixtureContent('template.html');
-
- describe(`processor - ${lang}`, () => {
- it('should preprocess the whole file', async () => {
- const template = getFixtureContent('template.pug');
- const preprocessed = await preprocess(template, [processor(options)]);
-
- expect(preprocessed.toString()).toContain(EXPECTED_TEMPLATE);
- });
- });
-});
-
-describe(`processor - babel`, () => {
- it('should support external src files', async () => {
- const template = ``;
- const preprocessed = await preprocess(template, [
- babel({
- presets: [
- [
- '@babel/preset-env',
- {
- loose: true,
- modules: false,
- targets: {
- esmodules: true,
- },
- },
- ],
- ],
- }),
- ]);
-
- expect(preprocessed.toString()).toMatchInlineSnapshot(`
- ""
- `);
- });
-});
diff --git a/test/processors/babel.test.ts b/test/processors/babel.test.ts
new file mode 100644
index 00000000..73d1da2b
--- /dev/null
+++ b/test/processors/babel.test.ts
@@ -0,0 +1,29 @@
+import { babel } from '../../src';
+import { preprocess } from '../utils';
+
+describe(`processor - babel`, () => {
+ it('should support external src files', async () => {
+ const template = ``;
+ const preprocessed = await preprocess(template, [
+ babel({
+ presets: [
+ [
+ '@babel/preset-env',
+ {
+ loose: true,
+ modules: false,
+ targets: {
+ esmodules: true,
+ },
+ },
+ ],
+ ],
+ }),
+ ]);
+
+ expect(preprocessed.toString()).toMatchInlineSnapshot(`
+ ""
+ `);
+ });
+});
diff --git a/test/processors/coffeescript.test.ts b/test/processors/coffeescript.test.ts
new file mode 100644
index 00000000..70ff97b0
--- /dev/null
+++ b/test/processors/coffeescript.test.ts
@@ -0,0 +1,35 @@
+import { coffeescript } from '../../src';
+import { getFixtureContent, preprocess } from '../utils';
+
+const EXPECTED_SCRIPT = getFixtureContent('script.js');
+
+describe(`processor - coffeescript`, () => {
+ it('should ignore other languages', async () => {
+ const template = ``;
+ const options = {};
+
+ const preprocessed = await preprocess(template, [coffeescript(options)]);
+
+ expect(preprocessed.toString()).toBe(template);
+ });
+
+ it('should support external src files', async () => {
+ const template = ``;
+ const options = {};
+
+ const preprocessed = await preprocess(template, [coffeescript(options)]);
+
+ expect(preprocessed.toString()).toContain(EXPECTED_SCRIPT);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = {
+ prependData: '### potato ###',
+ };
+
+ const preprocessed = await preprocess(template, [coffeescript(options)]);
+
+ expect(preprocessed.toString()).toContain('/* potato */');
+ });
+});
diff --git a/test/processors/less.test.ts b/test/processors/less.test.ts
new file mode 100644
index 00000000..56812e6c
--- /dev/null
+++ b/test/processors/less.test.ts
@@ -0,0 +1,28 @@
+import { less } from '../../src';
+import { CSS_PATTERN, preprocess } from '../utils';
+
+describe(`processor - less`, () => {
+ it('should ignore other languages', async () => {
+ const template = ``;
+ const options = {};
+
+ const preprocessed = await preprocess(template, [less(options)]);
+
+ expect(preprocessed.toString()).toBe(template);
+ });
+
+ it('should support external src files', async () => {
+ const template = ``;
+ const preprocessed = await preprocess(template, [less()]);
+
+ expect(preprocessed.toString()).toMatch(CSS_PATTERN);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = { prependData: '/* potato */' };
+ const preprocessed = await preprocess(template, [less(options)]);
+
+ expect(preprocessed.toString()).toContain('/* potato */');
+ });
+});
diff --git a/test/processors/postcss.test.ts b/test/processors/postcss.test.ts
new file mode 100644
index 00000000..e8589af0
--- /dev/null
+++ b/test/processors/postcss.test.ts
@@ -0,0 +1,21 @@
+import { postcss } from '../../src';
+import { CSS_PATTERN, preprocess, spyConsole } from '../utils';
+
+spyConsole();
+
+describe(`processor - postcss`, () => {
+ it('should support external src files', async () => {
+ const template = ``;
+ const preprocessed = await preprocess(template, [postcss()]);
+
+ expect(preprocessed.toString()).toMatch(CSS_PATTERN);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = { prependData: '/* potato */' };
+ const preprocessed = await preprocess(template, [postcss(options as any)]);
+
+ expect(preprocessed.toString()).toContain('/* potato */');
+ });
+});
diff --git a/test/processors/pug.test.ts b/test/processors/pug.test.ts
new file mode 100644
index 00000000..51f0d762
--- /dev/null
+++ b/test/processors/pug.test.ts
@@ -0,0 +1,21 @@
+import { pug } from '../../src';
+import { getFixtureContent, preprocess } from '../utils';
+
+const EXPECTED_TEMPLATE = getFixtureContent('template.html');
+
+describe(`processor - pug`, () => {
+ it('should preprocess the whole file', async () => {
+ const template = getFixtureContent('template.pug');
+ const preprocessed = await preprocess(template, [pug()]);
+
+ expect(preprocessed.toString()).toContain(EXPECTED_TEMPLATE);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = { prependData: `// potato` };
+ const preprocessed = await preprocess(template, [pug(options)]);
+
+ expect(preprocessed.toString()).toContain(``);
+ });
+});
diff --git a/test/processors/scss.test.ts b/test/processors/scss.test.ts
new file mode 100644
index 00000000..f3164d2d
--- /dev/null
+++ b/test/processors/scss.test.ts
@@ -0,0 +1,54 @@
+import { scss, sass } from '../../src';
+import { CSS_PATTERN, preprocess } from '../utils';
+
+describe(`processor - sass`, () => {
+ it('should ignore other languages', async () => {
+ const template = ``;
+ const options = {};
+
+ const preprocessed = await preprocess(template, [sass(options)]);
+
+ expect(preprocessed.toString()).toBe(template);
+ });
+
+ it('should support external src files', async () => {
+ const template = ``;
+ const preprocessed = await preprocess(template, [sass()]);
+
+ expect(preprocessed.toString()).toMatch(CSS_PATTERN);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = { prependData: '/* potato */' };
+ const preprocessed = await preprocess(template, [sass(options)]);
+
+ expect(preprocessed.toString()).toContain('/* potato');
+ });
+});
+
+describe(`processor - scss`, () => {
+ it('should ignore other languages', async () => {
+ const template = ``;
+ const options = {};
+
+ const preprocessed = await preprocess(template, [scss(options)]);
+
+ expect(preprocessed.toString()).toBe(template);
+ });
+
+ it('should support external src files', async () => {
+ const template = ``;
+ const preprocessed = await preprocess(template, [scss()]);
+
+ expect(preprocessed.toString()).toMatch(CSS_PATTERN);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = { prependData: '/* potato */' };
+ const preprocessed = await preprocess(template, [scss(options)]);
+
+ expect(preprocessed.toString()).toContain('/* potato */');
+ });
+});
diff --git a/test/processors/stylus.test.ts b/test/processors/stylus.test.ts
new file mode 100644
index 00000000..49881cf9
--- /dev/null
+++ b/test/processors/stylus.test.ts
@@ -0,0 +1,28 @@
+import { stylus } from '../../src';
+import { CSS_PATTERN, preprocess } from '../utils';
+
+describe(`processor - stylus`, () => {
+ it('should ignore other languages', async () => {
+ const template = ``;
+ const options = {};
+
+ const preprocessed = await preprocess(template, [stylus(options)]);
+
+ expect(preprocessed.toString()).toBe(template);
+ });
+
+ it('should support external src files', async () => {
+ const template = ``;
+ const preprocessed = await preprocess(template, [stylus()]);
+
+ expect(preprocessed.toString()).toMatch(CSS_PATTERN);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = { prependData: '/* potato */' };
+ const preprocessed = await preprocess(template, [stylus(options)]);
+
+ expect(preprocessed.toString()).toContain('/* potato */');
+ });
+});
diff --git a/test/processors/typescript.test.ts b/test/processors/typescript.test.ts
new file mode 100644
index 00000000..44892230
--- /dev/null
+++ b/test/processors/typescript.test.ts
@@ -0,0 +1,41 @@
+import { typescript } from '../../src';
+import { getFixtureContent, preprocess } from '../utils';
+
+const EXPECTED_SCRIPT = getFixtureContent('script.js');
+
+describe(`processor - typescript`, () => {
+ it('should ignore other languages', async () => {
+ const template = ``;
+ const options = {};
+
+ const preprocessed = await preprocess(template, [typescript(options)]);
+
+ expect(preprocessed.toString()).toBe(template);
+ });
+
+ it('should support external src files', async () => {
+ const template = ``;
+ const options = {
+ tsconfigFile: false,
+ compilerOptions: { module: 'es2015' },
+ prependData: '// potato',
+ };
+
+ const preprocessed = await preprocess(template, [typescript(options)]);
+
+ expect(preprocessed.toString()).toContain(EXPECTED_SCRIPT);
+ });
+
+ it('should support prepended data', async () => {
+ const template = ``;
+ const options = {
+ tsconfigFile: false,
+ compilerOptions: { module: 'es2015' },
+ prependData: '// potato',
+ };
+
+ const preprocessed = await preprocess(template, [typescript(options)]);
+
+ expect(preprocessed.toString()).toContain('// potato');
+ });
+});
diff --git a/test/transformers/babel.test.ts b/test/transformers/babel.test.ts
index d729e737..f3e16e47 100644
--- a/test/transformers/babel.test.ts
+++ b/test/transformers/babel.test.ts
@@ -1,4 +1,4 @@
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { preprocess } from '../utils';
const BABEL_CONFIG = {
@@ -19,11 +19,11 @@ const BABEL_CONFIG = {
describe('transformer - babel', () => {
it('transpiles with babel', async () => {
const template = ``;
+let foo = {}
+$: bar = foo?.b ?? 120
+`;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
babel: BABEL_CONFIG,
});
diff --git a/test/transformers/globalStyle.test.ts b/test/transformers/globalStyle.test.ts
index 39a7c009..ad53b30a 100644
--- a/test/transformers/globalStyle.test.ts
+++ b/test/transformers/globalStyle.test.ts
@@ -78,115 +78,113 @@ describe('transformer - globalStyle', () => {
});
describe('global selector', () => {
- describe('transformer - globalRule', () => {
- it('adds sourceMap with { sourceMap: true }', async () => {
- const template = ``;
- const opts = autoProcess({
- globalStyle: {
- sourceMap: true,
- },
- });
-
- const preprocessed = await preprocess(template, opts);
-
- expect(preprocessed.toString()).toContain(`sourceMappingURL`);
+ it('adds sourceMap with { sourceMap: true }', async () => {
+ const template = ``;
+ const opts = autoProcess({
+ globalStyle: {
+ sourceMap: true,
+ },
});
- it('wraps selector in :global(...) modifier', async () => {
- const template = ``;
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toContain(
- `:global(div){color:red}:global(.test){}`,
- );
- });
+ expect(preprocessed.toString()).toContain(`sourceMappingURL`);
+ });
- it('wraps selector in :global(...) only if needed', async () => {
- const template = ``;
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ it('wraps selector in :global(...) modifier', async () => {
+ const template = ``;
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toContain(
- `:global(.test){}:global(.foo){}`,
- );
- });
+ expect(preprocessed.toString()).toContain(
+ `:global(div){color:red}:global(.test){}`,
+ );
+ });
- it('wraps selector in :global(...) on multiple levels', async () => {
- const template = '';
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ it('wraps selector in :global(...) only if needed', async () => {
+ const template = ``;
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toMatch(
- // either be :global(div .cls){}
- // or :global(div) :global(.cls){}
- /(:global\(div .cls\)\{\}|:global\(div\) :global\(\.cls\)\{\})/,
- );
- });
+ expect(preprocessed.toString()).toContain(
+ `:global(.test){}:global(.foo){}`,
+ );
+ });
- it('wraps selector in :global(...) on multiple levels when in the middle', async () => {
- const template = '';
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ it('wraps selector in :global(...) on multiple levels', async () => {
+ const template = '';
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toMatch(
- // either be div div :global(span .cls) {}
- // or div div :global(span) :global(.cls) {}
- /div div (:global\(span .cls\)\{\}|:global\(span\) :global\(\.cls\)\{\})/,
- );
- });
+ expect(preprocessed.toString()).toMatch(
+ // either be :global(div .cls){}
+ // or :global(div) :global(.cls){}
+ /(:global\(div .cls\)\{\}|:global\(div\) :global\(\.cls\)\{\})/,
+ );
+ });
- it('does not break when at the end', async () => {
- const template = '';
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ it('wraps selector in :global(...) on multiple levels when in the middle', async () => {
+ const template = '';
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toContain('span{}');
- });
+ expect(preprocessed.toString()).toMatch(
+ // either be div div :global(span .cls) {}
+ // or div div :global(span) :global(.cls) {}
+ /div div (:global\(span .cls\)\{\}|:global\(span\) :global\(\.cls\)\{\})/,
+ );
+ });
- it('works with collapsed nesting several times', async () => {
- const template = '';
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ it('does not break when at the end', async () => {
+ const template = '';
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toMatch(
- // either be div :global(span .cls) {}
- // or div :global(span) :global(.cls) {}
- /div (:global\(span .cls\)\{\}|:global\(span\) :global\(\.cls\)\{\})/,
- );
- });
+ expect(preprocessed.toString()).toContain('span{}');
+ });
- it('does not interfere with the :global(...) syntax', async () => {
- const template = '';
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ it('works with collapsed nesting several times', async () => {
+ const template = '';
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toContain('div :global(span){}');
- });
+ expect(preprocessed.toString()).toMatch(
+ // either be div :global(span .cls) {}
+ // or div :global(span) :global(.cls) {}
+ /div (:global\(span .cls\)\{\}|:global\(span\) :global\(\.cls\)\{\})/,
+ );
+ });
- it('allows mixing with the :global(...) syntax', async () => {
- const template = '';
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ it('does not interfere with the :global(...) syntax', async () => {
+ const template = '';
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toMatch(
- // either be div :global(span .cls) {}
- // or div :global(span) :global(.cls) {}
- /div (:global\(span .cls\)\{\}|:global\(span\) :global\(\.cls\)\{\})/,
- );
- });
+ expect(preprocessed.toString()).toContain('div :global(span){}');
+ });
+
+ it('allows mixing with the :global(...) syntax', async () => {
+ const template = '';
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
+
+ expect(preprocessed.toString()).toMatch(
+ // either be div :global(span .cls) {}
+ // or div :global(span) :global(.cls) {}
+ /div (:global\(span .cls\)\{\}|:global\(span\) :global\(\.cls\)\{\})/,
+ );
+ });
- it('removes rules with only :global as its selector', async () => {
- const template =
- '';
+ it('removes rules with only :global as its selector', async () => {
+ const template =
+ '';
- const opts = autoProcess();
- const preprocessed = await preprocess(template, opts);
+ const opts = autoProcess();
+ const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toContain(
- '',
- );
- });
+ expect(preprocessed.toString()).toContain(
+ '',
+ );
});
});
});
diff --git a/test/transformers/less.test.ts b/test/transformers/less.test.ts
index c7987465..f206e312 100644
--- a/test/transformers/less.test.ts
+++ b/test/transformers/less.test.ts
@@ -1,12 +1,12 @@
import { resolve } from 'path';
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { preprocess } from '../utils';
describe('transformer - less', () => {
it('should return @imported files as dependencies', async () => {
const template = ``;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(template, opts);
expect(preprocessed.dependencies).toContain(
diff --git a/test/transformers/postcss.test.ts b/test/transformers/postcss.test.ts
index 6992b0f4..c9f66a91 100644
--- a/test/transformers/postcss.test.ts
+++ b/test/transformers/postcss.test.ts
@@ -3,13 +3,15 @@
/* eslint-disable @typescript-eslint/no-require-imports */
import { resolve } from 'path';
-import getAutoPreprocess from '../../src';
-import { preprocess } from '../utils';
+import autoPreprocess from '../../src';
+import { preprocess, spyConsole } from '../utils';
+
+spyConsole();
describe('transformer - postcss', () => {
it('should not transform plain css with postcss if { postcss: falsy }', async () => {
const template = ``;
- const preprocessed = await preprocess(template, getAutoPreprocess());
+ const preprocessed = await preprocess(template, autoPreprocess());
expect(preprocessed.toString()).not.toMatch(/-webkit-/);
});
@@ -18,7 +20,7 @@ describe('transformer - postcss', () => {
const template = ``;
const preprocessed = await preprocess(
template,
- getAutoPreprocess({
+ autoPreprocess({
postcss: true,
}),
);
@@ -28,7 +30,7 @@ describe('transformer - postcss', () => {
it('should transform plain css with postcss if { postcss: { plugins... } }', async () => {
const template = ``;
- const optsWithoutConfigFile = getAutoPreprocess({
+ const optsWithoutConfigFile = autoPreprocess({
postcss: {
plugins: [
require('autoprefixer')({
@@ -45,7 +47,7 @@ describe('transformer - postcss', () => {
it('should transform async preprocessed css with postcss if { postcss: { plugins... } }', async () => {
const templateSass = ``;
- const optsWithoutConfigFile = getAutoPreprocess({
+ const optsWithoutConfigFile = autoPreprocess({
postcss: {
plugins: [
require('autoprefixer')({
@@ -64,7 +66,7 @@ describe('transformer - postcss', () => {
const template = ``;
const preprocessed = await preprocess(
template,
- getAutoPreprocess({
+ autoPreprocess({
postcss: {
configFilePath: './test/fixtures/',
},
@@ -76,7 +78,7 @@ describe('transformer - postcss', () => {
it('should return @imported files as dependencies', async () => {
const template = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
postcss: {
plugins: [require('postcss-easy-import')],
},
@@ -95,7 +97,7 @@ div
color: red
`;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
postcss: {
parser: require('sugarss'),
plugins: [require('postcss-easy-import')],
diff --git a/test/transformers/pug.test.ts b/test/transformers/pug.test.ts
index b889a1f8..ea9896c3 100644
--- a/test/transformers/pug.test.ts
+++ b/test/transformers/pug.test.ts
@@ -1,6 +1,6 @@
import { resolve } from 'path';
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { preprocess } from '../utils';
describe('transformer - pug', () => {
@@ -10,7 +10,7 @@ main
header
h1`;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(template, opts);
expect(preprocessed.code).toBe('');
@@ -22,7 +22,7 @@ main
\theader
\t\th1`;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(template, opts);
expect(preprocessed.code).toBe('');
@@ -30,7 +30,7 @@ main
it('should return included files as dependencies', async () => {
const template = `include ./fixtures/template.pug`;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(template, opts);
expect(preprocessed.dependencies).toContain(
diff --git a/test/transformers/replace.test.ts b/test/transformers/replace.test.ts
index 5c555043..ca3cb4fb 100644
--- a/test/transformers/replace.test.ts
+++ b/test/transformers/replace.test.ts
@@ -1,7 +1,8 @@
import autoProcess from '../../src';
import { preprocess } from '../utils';
+import { Options } from '../../src/types';
-const options = [
+const options: Options.Replace = [
[/@if\s*\((.*?)\)$/gim, '{#if $1}'],
[/@elseif\s*\((.*?)\)$/gim, '{:else if $1}'],
[/@else$/gim, '{:else}'],
@@ -55,7 +56,7 @@ describe('transformer - regex', () => {
expect(preprocessed.toString()).toMatchInlineSnapshot(`
"
{@debug foo}
@@ -82,7 +83,7 @@ describe('transformer - regex', () => {
{:catch }
catch
@endawait
{@debug foo}
@@ -129,9 +130,9 @@ describe('transformer - regex', () => {
const preprocessed = await preprocess(template, opts);
expect(preprocessed.toString()).toMatchInlineSnapshot(`
-""
-`);
+ "
+ `);
});
});
diff --git a/test/transformers/scss.test.ts b/test/transformers/scss.test.ts
index 6e18ccb5..4423583f 100644
--- a/test/transformers/scss.test.ts
+++ b/test/transformers/scss.test.ts
@@ -1,6 +1,9 @@
+/* eslint-disable global-require */
+/* eslint-disable @typescript-eslint/no-require-imports */
+
import { resolve } from 'path';
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { preprocess } from '../utils';
import { Options } from '../../src/types';
@@ -30,22 +33,34 @@ const implementation: Options.Sass['implementation'] = {
};
describe('transformer - scss', () => {
- it('should prepend scss content via `data` option property - via default async render', async () => {
- const template = ``;
- const opts = getAutoPreprocess({
+ it('should return @imported files as dependencies - via default async render', async () => {
+ const template = ``;
+ const opts = autoPreprocess({
scss: {
- data: '$color:red;div{color:$color}',
+ // we force the node-sass implementation here because of
+ // https://github.com/sveltejs/svelte-preprocess/issues/163#issuecomment-639694477
+ implementation: require('node-sass'),
},
});
const preprocessed = await preprocess(template, opts);
- expect(preprocessed.toString()).toContain('red');
+ expect(preprocessed.dependencies).toContain(
+ resolve(__dirname, '..', 'fixtures', 'style.scss').replace(/[\\/]/g, '/'),
+ );
});
- it('should return @imported files as dependencies - via default async render', async () => {
+ it('should return @imported files as dependencies - via renderSync', async () => {
const template = ``;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess({
+ scss: {
+ // we force the node-sass implementation here because of
+ // https://github.com/sveltejs/svelte-preprocess/issues/163#issuecomment-639694477
+ implementation: require('node-sass'),
+ renderSync: true,
+ },
+ });
+
const preprocessed = await preprocess(template, opts);
expect(preprocessed.dependencies).toContain(
@@ -55,7 +70,7 @@ describe('transformer - scss', () => {
it('should use the specified implementation via the `implementation` option property - via default async render', async () => {
const template = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
scss: {
implementation,
},
@@ -68,9 +83,9 @@ describe('transformer - scss', () => {
it('should prepend scss content via `data` option property - via renderSync', async () => {
const template = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
scss: {
- data: '$color:blue;div{color:$color}',
+ prependData: '$color:blue;div{color:$color}',
renderSync: true,
},
});
@@ -80,24 +95,9 @@ describe('transformer - scss', () => {
expect(preprocessed.toString()).toContain('blue');
});
- it('should return @imported files as dependencies - via renderSync', async () => {
- const template = ``;
- const opts = getAutoPreprocess({
- scss: {
- renderSync: true,
- },
- });
-
- const preprocessed = await preprocess(template, opts);
-
- expect(preprocessed.dependencies).toContain(
- resolve(__dirname, '..', 'fixtures', 'style.scss').replace(/[\\/]/g, '/'),
- );
- });
-
it('should use the specified implementation via the `implementation` option property - via renderSync', async () => {
const template = ``;
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
scss: {
implementation,
renderSync: true,
diff --git a/test/transformers/stylus.test.ts b/test/transformers/stylus.test.ts
index 74b74075..96b58443 100644
--- a/test/transformers/stylus.test.ts
+++ b/test/transformers/stylus.test.ts
@@ -1,12 +1,12 @@
import { resolve } from 'path';
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { preprocess } from '../utils';
describe('transformer - stylus', () => {
it('should return @imported files as dependencies', async () => {
const template = ``;
- const opts = getAutoPreprocess();
+ const opts = autoPreprocess();
const preprocessed = await preprocess(template, opts);
expect(preprocessed.dependencies).toContain(
diff --git a/test/transformers/typescript.test.ts b/test/transformers/typescript.test.ts
index 3aaa3bfb..d2a58b05 100644
--- a/test/transformers/typescript.test.ts
+++ b/test/transformers/typescript.test.ts
@@ -2,15 +2,16 @@ import { resolve } from 'path';
import { Diagnostic } from 'typescript';
-import getAutoPreprocess from '../../src';
+import autoPreprocess from '../../src';
import { Processed } from '../../src/types';
-import { preprocess, getFixtureContent } from '../utils';
-import { compileFileFromMemory } from '../../src/transformers/typescript';
+import { preprocess, getFixtureContent, spyConsole } from '../utils';
+
+spyConsole();
const EXPECTED_SCRIPT = getFixtureContent('script.js');
const autoProcessTS = (content: string, compilerOptions?: any) => {
- const opts = getAutoPreprocess({
+ const opts = autoPreprocess({
typescript: {
tsconfigFile: false,
compilerOptions: {
@@ -27,20 +28,6 @@ const autoProcessTS = (content: string, compilerOptions?: any) => {
}) as Processed & { diagnostics: Diagnostic[] };
};
-const compileTS = (content: string, compilerOptions?: any) => {
- return compileFileFromMemory(
- {
- ...compilerOptions,
- skipLibCheck: true,
- allowNonTsExtensions: true,
- },
- {
- content,
- filename: resolve(__dirname, '..', 'App.svelte'),
- },
- ) as Processed & { diagnostics: Diagnostic[] };
-};
-
describe('transformer - typescript', () => {
const template = `