From 395e98c48938aa1b34f7914eed820068c154c103 Mon Sep 17 00:00:00 2001
From: Christian Kaisermann <christian@kaisermann.me>
Date: Tue, 14 Jul 2020 11:14:40 -0300
Subject: [PATCH] wip

---
 docs/getting-started.md        |  4 +--
 docs/migration-guide.md        |  6 ++---
 docs/preprocessing.md          | 45 +++++++++++++++++++++++++++++++---
 src/autoProcess.ts             |  1 +
 src/modules/prepareContent.ts  | 22 +++++++++++++++--
 src/processors/babel.ts        |  2 +-
 src/processors/coffeescript.ts |  2 +-
 src/processors/less.ts         |  2 +-
 src/processors/postcss.ts      |  2 +-
 src/processors/pug.ts          |  2 +-
 src/processors/scss.ts         |  2 +-
 src/processors/stylus.ts       |  2 +-
 src/processors/typescript.ts   |  2 +-
 src/transformers/scss.ts       |  2 +-
 src/types/options.ts           | 12 ++++++++-
 15 files changed, 88 insertions(+), 20 deletions(-)

diff --git a/docs/getting-started.md b/docs/getting-started.md
index 969f9d43..c4b0f185 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -213,7 +213,7 @@ Now we're in need of a SCSS file to hold some variables. Let's assume it's creat
 $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!
+As in any SCSS project, we could just `@use './path/to/variables.scss`, but that can also become boring. `svelte-preprocess` [accepts a `additionalData`](/docs/preprocessing.md#preprocessors) for almost every processor. Let's use it to prepend our import!
 
 ```diff
 import svelte from 'rollup-plugin-svelte'
@@ -240,7 +240,7 @@ export default {
 +          // We can use a path relative to the root because
 +          // svelte-preprocess automatically adds it to `includePaths`
 +          // if none is defined.
-+          prependData: `@import 'src/styles/variables.scss';`
++          additionalData: `@import 'src/styles/variables.scss';`
 +        },
          postcss: {
            plugins: [require('autoprefixer')()]
diff --git a/docs/migration-guide.md b/docs/migration-guide.md
index 32a2c159..6a5912b2 100644
--- a/docs/migration-guide.md
+++ b/docs/migration-guide.md
@@ -28,17 +28,17 @@ sveltePreprocess({
 });
 ```
 
-In `v4`, not only `scss`, but every language preprocessor accepts the new `prependData` property. The `data` property is no longer supported.
+In `v4`, not only `scss`, but every language preprocessor accepts the new `additionalData` property. The `data` property is no longer supported.
 
 ```js
 import sveltePreprocess from 'svelte-preprocess';
 
 sveltePreprocess({
   scss: {
-    prependData: '// prepended content for scss',
+    additionalData: '// prepended content for scss',
   },
   typescript: {
-    prependData: '// prepended content for ts',
+    additionalData: '// prepended content for ts',
   },
 });
 ```
diff --git a/docs/preprocessing.md b/docs/preprocessing.md
index 0e8910e8..0dace57c 100644
--- a/docs/preprocessing.md
+++ b/docs/preprocessing.md
@@ -9,6 +9,7 @@
   - [Stand-alone processors](#stand-alone-processors)
   - [Difference between the auto and stand-alone modes](#difference-between-the-auto-and-stand-alone-modes)
 - [Preprocessors](#preprocessors)
+  - [Options](#options)
   - [Babel](#babel)
   - [CoffeeScript](#coffeescript)
   - [Less](#less)
@@ -247,11 +248,49 @@ export default {
 
 ## Preprocessors
 
+### Options
+
 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. |
+| Option                              | Default     | Description                                                                                                                                                                  |
+| ----------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [`additionalData`](#additionalData) | `undefined` | If a `string`, the value will be prepended to every component part that runs through the preprocessor. If a `function`, it expects to return the content to be preprocessed. |
+
+#### `additionalData`
+
+Type: `string | ({ content: string, filename: string }) => string`
+
+If a `string`, the value will be prepended to every component part that runs through the preprocessor. If a `function`, it expects to return the content to be preprocessed.
+
+```js
+import svelte from 'rollup-plugin-svelte';
+
+import autoPreprocess from 'svelte-preprocess';
+
+export default {
+  plugins: [
+    svelte({
+      preprocess: autoPreprocess({
+        typescript: {
+          additionalData: '// prepended content',
+        },
+        scss: {
+          // Passing a function
+          additionalData({ content, filename }) {
+            return [
+              // prepended
+              `// I'm at the top of the file`,
+              content,
+              // appended
+              `// And I'm at the bottom!`,
+            ].join('\n');
+          },
+        },
+      }),
+    }),
+  ],
+};
+```
 
 ### Babel
 
diff --git a/src/autoProcess.ts b/src/autoProcess.ts
index 2eb27865..c2c76c66 100644
--- a/src/autoProcess.ts
+++ b/src/autoProcess.ts
@@ -169,6 +169,7 @@ export function autoPreprocess(
     const transformerOptions = getTransformerOptions(lang, alias);
 
     content = prepareContent({
+      filename,
       options: transformerOptions,
       content,
     });
diff --git a/src/modules/prepareContent.ts b/src/modules/prepareContent.ts
index 578e2505..694a35b9 100644
--- a/src/modules/prepareContent.ts
+++ b/src/modules/prepareContent.ts
@@ -1,11 +1,15 @@
 import stripIndent from 'strip-indent';
 
+import { ContentModifier } from '../types/options';
+
 export function prepareContent({
   options,
   content,
+  filename,
 }: {
-  options: any;
+  options: ContentModifier & unknown;
   content: string;
+  filename: string;
 }) {
   if (typeof options !== 'object') {
     return content;
@@ -14,7 +18,21 @@ export function prepareContent({
   content = stripIndent(content);
 
   if (options.prependData) {
-    content = `${options.prependData}\n${content}`;
+    console.warn(
+      '[svelte-preprocess] 🙊 `options.prependData` is deprecated. Use `options.additionalData` instead.',
+    );
+
+    if (!options.additionalData) {
+      content = `${options.prependData}\n${content}`;
+    }
+  }
+
+  if (options.additionalData) {
+    if (typeof options.additionalData === 'function') {
+      content = options.additionalData({ content, filename });
+    } else {
+      content = `${options.prependData}\n${content}`;
+    }
   }
 
   return content;
diff --git a/src/processors/babel.ts b/src/processors/babel.ts
index 55c84a75..2ddbadcd 100644
--- a/src/processors/babel.ts
+++ b/src/processors/babel.ts
@@ -11,7 +11,7 @@ export default (options?: Options.Babel): PreprocessorGroup => ({
       svelteFile,
     );
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     const transformed = await transformer({
       content,
diff --git a/src/processors/coffeescript.ts b/src/processors/coffeescript.ts
index 85e002d5..ed050ec0 100644
--- a/src/processors/coffeescript.ts
+++ b/src/processors/coffeescript.ts
@@ -15,7 +15,7 @@ export default (options?: Options.Coffeescript): PreprocessorGroup => ({
       dependencies,
     } = await getTagInfo(svelteFile);
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     if (lang !== 'coffeescript') {
       return { code: content };
diff --git a/src/processors/less.ts b/src/processors/less.ts
index ed389126..809bd7b3 100644
--- a/src/processors/less.ts
+++ b/src/processors/less.ts
@@ -14,7 +14,7 @@ export default (options?: Options.Less): PreprocessorGroup => ({
       dependencies,
     } = await getTagInfo(svelteFile);
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     if (lang !== 'less') {
       return { code: content };
diff --git a/src/processors/postcss.ts b/src/processors/postcss.ts
index 5aed99d2..9c068e45 100644
--- a/src/processors/postcss.ts
+++ b/src/processors/postcss.ts
@@ -11,7 +11,7 @@ export default (options?: Options.Postcss): PreprocessorGroup => ({
       svelteFile,
     );
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     /** If manually passed a plugins array, use it as the postcss config */
     const transformed = await transformer({
diff --git a/src/processors/pug.ts b/src/processors/pug.ts
index 6c02785c..f631d98f 100644
--- a/src/processors/pug.ts
+++ b/src/processors/pug.ts
@@ -5,7 +5,7 @@ export default (options?: Options.Pug): PreprocessorGroup => ({
   async markup({ content, filename }) {
     const { transformer } = await import('../transformers/pug');
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     return transformer({ content, filename, options });
   },
diff --git a/src/processors/scss.ts b/src/processors/scss.ts
index a7fc6e22..65ee73b5 100644
--- a/src/processors/scss.ts
+++ b/src/processors/scss.ts
@@ -15,7 +15,7 @@ export default (options?: Options.Sass): PreprocessorGroup => ({
       dependencies,
     } = await getTagInfo(svelteFile);
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     if (lang !== 'scss') {
       return { code: content };
diff --git a/src/processors/stylus.ts b/src/processors/stylus.ts
index 4e975512..2289b62d 100644
--- a/src/processors/stylus.ts
+++ b/src/processors/stylus.ts
@@ -14,7 +14,7 @@ export default (options?: Options.Stylus): PreprocessorGroup => ({
       dependencies,
     } = await getTagInfo(svelteFile);
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     if (lang !== 'stylus') {
       return { code: content };
diff --git a/src/processors/typescript.ts b/src/processors/typescript.ts
index 181baa73..96b63b28 100644
--- a/src/processors/typescript.ts
+++ b/src/processors/typescript.ts
@@ -14,7 +14,7 @@ export default (options?: Options.Typescript): PreprocessorGroup => ({
       dependencies,
     } = await getTagInfo(svelteFile);
 
-    content = prepareContent({ options, content });
+    content = prepareContent({ options, content, filename });
 
     if (lang !== 'typescript') {
       return { code: content };
diff --git a/src/transformers/scss.ts b/src/transformers/scss.ts
index 671dd3ad..77f869eb 100644
--- a/src/transformers/scss.ts
+++ b/src/transformers/scss.ts
@@ -33,7 +33,7 @@ const transformer: Transformer<Options.Sass> = async ({
     implementation = sass = mod.default;
   }
 
-  const { renderSync, prependData, ...restOptions } = {
+  const { renderSync, ...restOptions } = {
     ...options,
     includePaths: getIncludePaths(filename, options.includePaths),
     outFile: `${filename}.css`,
diff --git a/src/types/options.ts b/src/types/options.ts
index 7574adf5..15fbf2ec 100644
--- a/src/types/options.ts
+++ b/src/types/options.ts
@@ -3,8 +3,18 @@ import { Options as SassOptions, render, renderSync } from 'sass';
 import { Options as PugOptions } from 'pug';
 import { TransformOptions as BabelOptions } from '@babel/core';
 
-type ContentModifier = {
+type AdditionalDataMethod = ({
+  content,
+  filename,
+}: {
+  content: string;
+  filename: string;
+}) => string;
+
+export type ContentModifier = {
+  /** @deprecated Use additionalData instead */
   prependData?: string;
+  additionalData?: string | AdditionalDataMethod;
 };
 
 export type Coffeescript = {