Repository: teleporthq/teleport-code-generators
Pull request #218 (2019-05-10 13:36:49)

feat(component-gen): A Generic component generatorby splitting post processing.
Addresses #217 

teleport-component-runner is just a temporary project I will remove when it's all done

codecov[bot]: # [Codecov](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218?src=pr&el=h1) Report
> Merging [#218](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218?src=pr&el=desc) into [master](https://codecov.io/gh/teleporthq/teleport-code-generators/commit/aa1fa099d9c9e5c9904719b31866ca70394e697a?src=pr&el=desc) will **decrease** coverage by `4.03%`.
> The diff coverage is `27.88%`.

[![Impacted file tree graph](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/graphs/tree.svg?width=650&token=LI2WPEFm1R&height=150&src=pr)](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #218      +/-   ##
==========================================
- Coverage   36.45%   32.41%   -4.04%     
==========================================
  Files          56       59       +3     
  Lines        1934     1956      +22     
  Branches      218      216       -2     
==========================================
- Hits          705      634      -71     
- Misses       1222     1316      +94     
+ Partials        7        6       -1
```


| [Impacted Files](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/teleport-plugin-vue-css/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtcGx1Z2luLXZ1ZS1jc3Mvc3JjL2luZGV4LnRz) | `0% <0%> (ø)` | :arrow_up: |
| [...es/teleport-postprocessor-prettier-js/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtcG9zdHByb2Nlc3Nvci1wcmV0dGllci1qcy9zcmMvaW5kZXgudHM=) | `0% <0%> (ø)` | |
| [...ges/teleport-plugin-react-css-modules/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtcGx1Z2luLXJlYWN0LWNzcy1tb2R1bGVzL3NyYy9pbmRleC50cw==) | `0% <0%> (ø)` | :arrow_up: |
| [...ges/teleport-plugin-import-statements/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtcGx1Z2luLWltcG9ydC1zdGF0ZW1lbnRzL3NyYy9pbmRleC50cw==) | `0% <0%> (ø)` | :arrow_up: |
| [...-generator-shared/src/generators/js-ast-to-code.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtZ2VuZXJhdG9yLXNoYXJlZC9zcmMvZ2VuZXJhdG9ycy9qcy1hc3QtdG8tY29kZS50cw==) | `0% <0%> (ø)` | :arrow_up: |
| [.../teleport-postprocessor-prettier-html/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtcG9zdHByb2Nlc3Nvci1wcmV0dGllci1odG1sL3NyYy9pbmRleC50cw==) | `0% <0%> (ø)` | |
| [...-generator-shared/src/generators/html-to-string.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtZ2VuZXJhdG9yLXNoYXJlZC9zcmMvZ2VuZXJhdG9ycy9odG1sLXRvLXN0cmluZy50cw==) | `0% <0%> (ø)` | :arrow_up: |
| [packages/teleport-component-generator/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtY29tcG9uZW50LWdlbmVyYXRvci9zcmMvaW5kZXgudHM=) | `0% <0%> (ø)` | |
| [...es/teleport-plugin-vue-base-component/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtcGx1Z2luLXZ1ZS1iYXNlLWNvbXBvbmVudC9zcmMvaW5kZXgudHM=) | `0% <0%> (ø)` | :arrow_up: |
| [...kages/teleport-postprocessor-vue-file/src/index.ts](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree#diff-cGFja2FnZXMvdGVsZXBvcnQtcG9zdHByb2Nlc3Nvci12dWUtZmlsZS9zcmMvaW5kZXgudHM=) | `0% <0%> (ø)` | |
| ... and [10 more](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218?src=pr&el=footer). Last update [aa1fa09...c1bd922](https://codecov.io/gh/teleporthq/teleport-code-generators/pull/218?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

JayaKrishnaNamburu: Hey, @alexnm the idea looks interesting, so we will pass the style plugins too in the same fashion right? Because I don't see any input for styles in the component generator as of now, please correct me if I got it wrong 
alexnm: > Hey, @alexnm the idea looks interesting, so we will pass the style plugins too in the same fashion right? Because I don't see any input for styles in the component generator as of now, please correct me if I got it wrong

yes, the component generator will not know anything about the specific style plugin, that will be added later

Patch:
diff --git a/package.json b/package.json
index 8b3da9c2..5ea90837 100755
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
   "scripts": {
     "lint": "tslint -p ./",
     "build": "lerna run build",
+    "dev": "lerna run --parallel build:watch",
     "test": "jest",
     "test:perf": "jest __tests__/performance",
     "test:coverage": "npm run test -- --coverage --no-cache",
diff --git a/packages/teleport-component-generator-react/package.json b/packages/teleport-component-generator-react/package.json
index 7eb9874e..d889cfa5 100644
--- a/packages/teleport-component-generator-react/package.json
+++ b/packages/teleport-component-generator-react/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@teleporthq/teleport-component-generator-react",
   "version": "0.6.0",
-  "description": "Component generator capable of creating React components with a number of different style flavors",
+  "description": "Component generator customization, capable of creating React components with a number of different style flavors",
   "author": "teleportHQ",
   "license": "MIT",
   "homepage": "https://teleporthq.io/",
@@ -18,9 +18,11 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
+    "@teleporthq/teleport-component-generator": "^0.6.0",
     "@teleporthq/teleport-plugin-react-app-routing": "^0.6.0",
     "@teleporthq/teleport-plugin-react-base-component": "^0.6.0",
     "@teleporthq/teleport-plugin-import-statements": "^0.6.0",
@@ -30,7 +32,7 @@
     "@teleporthq/teleport-plugin-react-styled-components": "^0.6.0",
     "@teleporthq/teleport-plugin-react-styled-jsx": "^0.6.0",
     "@teleporthq/teleport-plugin-react-proptypes": "^0.6.0",
-    "@teleporthq/teleport-generator-shared": "^0.6.0",
-    "@teleporthq/teleport-generator-core": "^0.6.0"
+    "@teleporthq/teleport-postprocessor-prettier-js": "^0.6.0",
+    "@teleporthq/teleport-generator-shared": "^0.6.0"
   }
 }
diff --git a/packages/teleport-component-generator-react/src/index.ts b/packages/teleport-component-generator-react/src/index.ts
index fe2459dc..a7146cfc 100644
--- a/packages/teleport-component-generator-react/src/index.ts
+++ b/packages/teleport-component-generator-react/src/index.ts
@@ -1,2 +1,50 @@
-export { default as createReactComponentGenerator } from './react-component'
-export { default as createReactRouterComponentGenerator } from './react-router'
+import reactComponentPlugin from '@teleporthq/teleport-plugin-react-base-component'
+import reactInlineStylesPlugin from '@teleporthq/teleport-plugin-react-inline-styles'
+import reactJSSPlugin from '@teleporthq/teleport-plugin-react-jss'
+import reactCSSModulesPlugin from '@teleporthq/teleport-plugin-react-css-modules'
+import reactStyledComponentsPlugin from '@teleporthq/teleport-plugin-react-styled-components'
+import reactStyledJSXPlugin from '@teleporthq/teleport-plugin-react-styled-jsx'
+import reactPropTypesPlugin from '@teleporthq/teleport-plugin-react-proptypes'
+import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
+
+import prettierJS from '@teleporthq/teleport-postprocessor-prettier-js'
+
+import { createGenerator } from '@teleporthq/teleport-component-generator'
+
+import reactMapping from './react-mapping.json'
+
+import {
+  ComponentGenerator,
+  GeneratorOptions,
+} from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+const stylePlugins = {
+  InlineStyles: reactInlineStylesPlugin,
+  StyledComponents: reactStyledComponentsPlugin,
+  StyledJSX: reactStyledJSXPlugin,
+  CSSModules: reactCSSModulesPlugin,
+  JSS: reactJSSPlugin,
+}
+
+export const createReactComponentGenerator = (
+  variation: string = 'InlineStyles',
+  { mapping }: GeneratorOptions = { mapping }
+): ComponentGenerator => {
+  const stylePlugin = stylePlugins[variation] || reactInlineStylesPlugin
+
+  const generator = createGenerator()
+
+  generator.addMapping(reactMapping)
+  generator.addMapping(mapping)
+
+  generator.addPlugin(reactComponentPlugin)
+  generator.addPlugin(stylePlugin)
+  generator.addPlugin(reactPropTypesPlugin)
+  generator.addPlugin(importStatementsPlugin)
+
+  generator.addPostProcessor(prettierJS)
+
+  return generator
+}
+
+export default createReactComponentGenerator
diff --git a/packages/teleport-component-generator-react/src/react-component.ts b/packages/teleport-component-generator-react/src/react-component.ts
deleted file mode 100644
index 73278ce5..00000000
--- a/packages/teleport-component-generator-react/src/react-component.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import {
-  AssemblyLine,
-  Builder,
-  Resolver,
-  Validator,
-  Parser,
-} from '@teleporthq/teleport-generator-core'
-
-import reactComponentPlugin from '@teleporthq/teleport-plugin-react-base-component'
-import reactInlineStylesPlugin from '@teleporthq/teleport-plugin-react-inline-styles'
-import reactJSSPlugin from '@teleporthq/teleport-plugin-react-jss'
-import reactCSSModulesPlugin from '@teleporthq/teleport-plugin-react-css-modules'
-import reactStyledComponentsPlugin from '@teleporthq/teleport-plugin-react-styled-components'
-import reactStyledJSXPlugin from '@teleporthq/teleport-plugin-react-styled-jsx'
-import reactPropTypesPlugin from '@teleporthq/teleport-plugin-react-proptypes'
-import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
-
-import { createFile } from '@teleporthq/teleport-generator-shared/lib/utils/project-utils'
-import { sanitizeVariableName } from '@teleporthq/teleport-generator-shared/lib/utils/string-utils'
-import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
-
-import htmlMapping from './html-mapping.json'
-import reactMapping from './react-mapping.json'
-
-import {
-  ComponentGenerator,
-  CompiledComponent,
-  GeneratedFile,
-  GenerateComponentFunction,
-} from '@teleporthq/teleport-generator-shared/lib/typings/generators'
-
-import { Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
-
-const stylePlugins = {
-  InlineStyles: reactInlineStylesPlugin,
-  StyledComponents: reactStyledComponentsPlugin,
-  StyledJSX: reactStyledJSXPlugin,
-  CSSModules: reactCSSModulesPlugin,
-  JSS: reactJSSPlugin,
-}
-
-export interface ReactGeneratorFactoryParams {
-  variation?: string
-  customMapping?: Mapping
-}
-
-const createReactGenerator = (params: ReactGeneratorFactoryParams = {}): ComponentGenerator => {
-  const { variation, customMapping } = params
-  const stylePlugin = stylePlugins[variation] || reactInlineStylesPlugin
-  const validator = new Validator()
-
-  const resolver = new Resolver()
-  resolver.addMapping(htmlMapping as Mapping)
-  resolver.addMapping(reactMapping as Mapping)
-  resolver.addMapping(customMapping)
-
-  const assemblyLine = new AssemblyLine()
-  assemblyLine.addPlugin(reactComponentPlugin)
-  assemblyLine.addPlugin(stylePlugin)
-  assemblyLine.addPlugin(reactPropTypesPlugin)
-  assemblyLine.addPlugin(importStatementsPlugin)
-
-  const chunksLinker = new Builder()
-
-  const generateComponent: GenerateComponentFunction = async (
-    input,
-    options = {}
-  ): Promise<CompiledComponent> => {
-    if (!options.skipValidation) {
-      const validationResult = validator.validateComponent(input)
-      if (!validationResult.valid) {
-        throw new Error(validationResult.errorMsg)
-      }
-    }
-    const uidl = Parser.parseComponentJSON(input)
-
-    const files: GeneratedFile[] = []
-    // For page components, for some frameworks the filename will be the one set in the meta property
-    let fileName = uidl.meta && uidl.meta.fileName ? uidl.meta.fileName : uidl.name
-    fileName = sanitizeVariableName(fileName)
-
-    const resolvedUIDL = resolver.resolveUIDL(uidl, options)
-    const { chunks, externalDependencies } = await assemblyLine.run(resolvedUIDL)
-
-    const jsCode = chunksLinker.link(chunks.default)
-    const cssCode = chunksLinker.link(chunks.cssmodule)
-
-    files.push(createFile(fileName, FILE_TYPE.JS, jsCode))
-
-    if (cssCode) {
-      files.push(createFile(fileName, FILE_TYPE.CSS, cssCode))
-    }
-
-    return {
-      files,
-      dependencies: externalDependencies,
-    }
-  }
-
-  return {
-    generateComponent,
-    resolveElement: resolver.resolveElement.bind(resolver),
-    addMapping: resolver.addMapping.bind(resolver),
-    addPlugin: assemblyLine.addPlugin.bind(assemblyLine),
-  }
-}
-
-export default createReactGenerator
diff --git a/packages/teleport-component-generator-react/src/react-router.ts b/packages/teleport-component-generator-react/src/react-router.ts
deleted file mode 100644
index 5eeff081..00000000
--- a/packages/teleport-component-generator-react/src/react-router.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
-import reactAppRoutingPlugin from '@teleporthq/teleport-plugin-react-app-routing'
-import { AssemblyLine, Builder, Resolver, Parser } from '@teleporthq/teleport-generator-core'
-
-import htmlMapping from './html-mapping.json'
-import reactMapping from './react-mapping.json'
-
-import { Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
-
-const createRouterComponentGenerator = () => {
-  const resolver = new Resolver([htmlMapping as Mapping, reactMapping as Mapping])
-
-  const assemblyLine = new AssemblyLine([reactAppRoutingPlugin, importStatementsPlugin])
-  const chunksLinker = new Builder()
-
-  // TODO change to respect the same output as normal component?
-  // TODO validate UIDL in here as well?
-  const generateComponent = async (input: Record<string, unknown>) => {
-    const uidl = Parser.parseComponentJSON(input)
-    const resolvedUIDL = resolver.resolveUIDL(uidl)
-    const { chunks, externalDependencies } = await assemblyLine.run(resolvedUIDL)
-
-    return {
-      code: chunksLinker.link(chunks.default),
-      externalDependencies,
-    }
-  }
-
-  return {
-    generateComponent,
-  }
-}
-
-export default createRouterComponentGenerator
diff --git a/packages/teleport-component-generator-vue/package.json b/packages/teleport-component-generator-vue/package.json
index a6381bb4..94b6e613 100644
--- a/packages/teleport-component-generator-vue/package.json
+++ b/packages/teleport-component-generator-vue/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@teleporthq/teleport-component-generator-vue",
   "version": "0.6.0",
-  "description": "Component generator capable of creating Vue components",
+  "description": "Component generator customization, capable of creating Vue components",
   "author": "teleportHQ",
   "license": "MIT",
   "homepage": "https://teleporthq.io/",
@@ -18,14 +18,18 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-plugin-import-statements": "^0.6.0",
     "@teleporthq/teleport-generator-shared": "^0.6.0",
-    "@teleporthq/teleport-generator-core": "^0.6.0",
+    "@teleporthq/teleport-component-generator": "^0.6.0",
     "@teleporthq/teleport-plugin-vue-app-routing": "^0.6.0",
     "@teleporthq/teleport-plugin-vue-base-component": "^0.6.0",
-    "@teleporthq/teleport-plugin-vue-css": "^0.6.0"
+    "@teleporthq/teleport-plugin-vue-css": "^0.6.0",
+    "@teleporthq/teleport-postprocessor-prettier-js": "^0.6.0",
+    "@teleporthq/teleport-postprocessor-prettier-html": "^0.6.0",
+    "@teleporthq/teleport-postprocessor-vue-file": "^0.6.0"
   }
 }
diff --git a/packages/teleport-component-generator-vue/src/html-mapping.json b/packages/teleport-component-generator-vue/src/html-mapping.json
deleted file mode 100644
index c8fe6e4a..00000000
--- a/packages/teleport-component-generator-vue/src/html-mapping.json
+++ /dev/null
@@ -1,214 +0,0 @@
-{
-  "elements": {
-    "container": {
-      "elementType": "div"
-    },
-    "group": {
-      "elementType": "div"
-    },
-    "main": {
-      "elementType": "main"
-    },
-    "header": {
-      "elementType": "header"
-    },
-    "nav": {
-      "elementType": "nav"
-    },
-    "section": {
-      "elementType": "section"
-    },
-    "article": {
-      "elementType": "article"
-    },
-    "aside": {
-      "elementType": "aside"
-    },
-    "footer": {
-      "elementType": "footer"
-    },
-    "text": {
-      "elementType": "span"
-    },
-    "textblock": {
-      "elementType": "p"
-    },
-    "strongtext": {
-      "elementType": "strong"
-    },
-    "formattedtext": {
-      "elementType": "pre"
-    },
-    "label": {
-      "elementType": "label"
-    },
-    "heading1": {
-      "elementType": "h1"
-    },
-    "heading2": {
-      "elementType": "h2"
-    },
-    "heading3": {
-      "elementType": "h3"
-    },
-    "heading4": {
-      "elementType": "h4"
-    },
-    "heading5": {
-      "elementType": "h5"
-    },
-    "heading6": {
-      "elementType": "h6"
-    },
-    "image": {
-      "elementType": "img",
-      "attrs": {
-        "src": { "type": "dynamic", "content": { "referenceType": "attr", "id": "url" } }
-      }
-    },
-    "textinput": {
-      "elementType": "input",
-      "attrs": {
-        "type": { "type": "static", "content": "text" }
-      }
-    },
-    "passwordinput": {
-      "elementType": "input",
-      "attrs": {
-        "type":  { "type":"static", "content": "password"}
-      }
-    },
-    "numberinput": {
-      "elementType": "input",
-      "attrs": {
-        "type": { "type": "static", "content": "number" }
-      }
-    },
-    "checkbox": {
-      "elementType": "input",
-      "attrs": {
-        "type": { "type": "static", "content": "checkbox" }
-      }
-    },
-    "radiobutton": {
-      "elementType": "input",
-      "attrs": {
-        "type": { "type": "static", "content": "radio" }
-      }
-    },
-    "textarea": {
-      "elementType": "textarea"
-    },
-    "link": {
-      "elementType": "a",
-      "attrs": {
-        "href": {
-          "type": "dynamic",
-          "content": { "referenceType": "attr", "id": "url" }
-        },
-        "target": {
-          "type": "static",
-          "content": "_blank"
-        }
-      }
-    },
-    "button": {
-      "elementType": "button"
-    },
-    "form": {
-      "elementType": "form",
-      "attrs": {
-        "method": { "type": "dynamic", "content": { "referenceType": "attr", "id": "type" } },
-        "action": { "type": "dynamic", "content": { "referenceType": "attr", "id": "url" } }
-      }
-    },
-    "list": {
-      "elementType": "ul",
-      "children": [{
-        "type": "repeat",
-        "content": {
-          "node": {
-            "type": "element",
-            "content": {
-              "elementType": "li",
-              "name": "item",
-              "children": [{
-                "type": "dynamic",
-                "content": {
-                  "referenceType": "local",
-                  "id": "item"
-                }
-              }]
-            }
-          },
-          "dataSource": { "type": "dynamic", "content": { "referenceType": "attr", "id": "items" } },
-          "meta": {
-            "useIndex": true
-          }
-        }
-      }]
-    },
-    "dropdown": {
-      "elementType": "select",
-      "children": [{
-        "type": "repeat",
-        "content": {
-          "node": {
-            "type": "element",
-            "content": {
-              "elementType": "option",
-              "name": "option",
-              "children": [{
-                "type": "dynamic",
-                "content": {
-                  "referenceType": "local",
-                  "id": "item"
-                }
-              }]
-            }
-          },
-          "dataSource": { "type": "dynamic", "content": { "referenceType": "attr", "id": "options" } },
-          "meta": {
-            "useIndex": true
-          }
-        }
-      }]
-    },
-    "video": {
-      "elementType": "video",
-      "children": [
-        { "type": "dynamic", "content": { "referenceType": "children", "id": "children" } },
-        { "type": "static", "content": "This browser does not support the video formats given" }
-      ]
-    },
-    "audio": {
-      "elementType": "audio",
-      "children": [
-        { "type": "dynamic", "content": { "referenceType": "children", "id": "children" } },
-        { "type": "static", "content": "This browser does not support the audio formats given" }
-      ]
-    },
-    "picture": {
-      "elementType": "picture",
-      "children": [
-        { "type": "dynamic", "content": { "referenceType": "children", "id": "children" } },
-        { "type": "static", "content": "This browser does not support the image formats given" }
-      ]
-    },
-    "source": {
-      "elementType": "source",
-      "attrs": {
-        "src": { "type": "dynamic", "content": { "referenceType": "attr", "id": "url" } }
-      }
-    },
-    "svg": {
-      "elementType": "svg"
-    },
-    "line": {
-      "elementType": "hr"
-    }
-  },
-  "events": {
-    "click": "onclick"
-  }
-}
\ No newline at end of file
diff --git a/packages/teleport-component-generator-vue/src/index.ts b/packages/teleport-component-generator-vue/src/index.ts
index 767e2373..fc775e90 100644
--- a/packages/teleport-component-generator-vue/src/index.ts
+++ b/packages/teleport-component-generator-vue/src/index.ts
@@ -1,2 +1,37 @@
-export { default as createVueComponentGenerator } from './vue-component'
-export { default as createVueRouterComponentGenerator } from './vue-router'
+import { createGenerator } from '@teleporthq/teleport-component-generator'
+
+import vueComponentPlugin from '@teleporthq/teleport-plugin-vue-base-component'
+import vueStylePlugin from '@teleporthq/teleport-plugin-vue-css'
+import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
+
+import prettierJS from '@teleporthq/teleport-postprocessor-prettier-js'
+import prettierHTML from '@teleporthq/teleport-postprocessor-prettier-html'
+import vueFile from '@teleporthq/teleport-postprocessor-vue-file'
+
+import vueMapping from './vue-mapping.json'
+
+import {
+  GeneratorOptions,
+  ComponentGenerator,
+} from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+export const createVueComponentGenerator = (
+  { mapping }: GeneratorOptions = { mapping }
+): ComponentGenerator => {
+  const generator = createGenerator()
+
+  generator.addMapping(vueMapping)
+  generator.addMapping(mapping)
+
+  generator.addPlugin(vueComponentPlugin)
+  generator.addPlugin(vueStylePlugin)
+  generator.addPlugin(importStatementsPlugin)
+
+  generator.addPostProcessor(prettierJS)
+  generator.addPostProcessor(prettierHTML)
+  generator.addPostProcessor(vueFile)
+
+  return generator
+}
+
+export default createVueComponentGenerator
diff --git a/packages/teleport-component-generator-vue/src/utils.ts b/packages/teleport-component-generator-vue/src/utils.ts
deleted file mode 100644
index a963526e..00000000
--- a/packages/teleport-component-generator-vue/src/utils.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-export const buildVueFile = (htmlCode, jsCode, cssCode) => {
-  let code = `<template>
-${htmlCode}
-</template>
-
-<script>
-${jsCode}
-</script>
-`
-
-  if (cssCode) {
-    code += `
-<style>
-${cssCode}
-</style>
-`
-  }
-
-  return code
-}
diff --git a/packages/teleport-component-generator-vue/src/vue-component.ts b/packages/teleport-component-generator-vue/src/vue-component.ts
deleted file mode 100644
index 3c34950d..00000000
--- a/packages/teleport-component-generator-vue/src/vue-component.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import {
-  AssemblyLine,
-  Builder,
-  Resolver,
-  Validator,
-  Parser,
-} from '@teleporthq/teleport-generator-core'
-
-import vueComponentPlugin from '@teleporthq/teleport-plugin-vue-base-component'
-import vueStylePlugin from '@teleporthq/teleport-plugin-vue-css'
-import { createPlugin as createImportStatementsPlugin } from '@teleporthq/teleport-plugin-import-statements'
-
-import htmlMapping from './html-mapping.json'
-import vueMapping from './vue-mapping.json'
-
-import { createFile } from '@teleporthq/teleport-generator-shared/lib/utils/project-utils'
-import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
-import {
-  addSpacesToEachLine,
-  removeLastEmptyLine,
-  sanitizeVariableName,
-} from '@teleporthq/teleport-generator-shared/lib/utils/string-utils'
-
-import { buildVueFile } from './utils'
-
-import {
-  GeneratorOptions,
-  ComponentGenerator,
-  CompiledComponent,
-  GenerateComponentFunction,
-  GeneratedFile,
-} from '@teleporthq/teleport-generator-shared/lib/typings/generators'
-import { Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
-
-const createVueGenerator = ({ mapping }: GeneratorOptions = { mapping }): ComponentGenerator => {
-  const validator = new Validator()
-  const resolver = new Resolver([htmlMapping as Mapping, vueMapping as Mapping, mapping])
-  const assemblyLine = new AssemblyLine([
-    vueComponentPlugin,
-    vueStylePlugin,
-    createImportStatementsPlugin({ fileId: 'vuejs' }),
-  ])
-
-  const chunksLinker = new Builder()
-
-  const generateComponent: GenerateComponentFunction = async (
-    input,
-    options = {}
-  ): Promise<CompiledComponent> => {
-    if (!options.skipValidation) {
-      const validationResult = validator.validateComponent(input)
-      if (!validationResult.valid) {
-        throw new Error(validationResult.errorMsg)
-      }
-    }
-    const uidl = Parser.parseComponentJSON(input)
-
-    const files: GeneratedFile[] = []
-    // For page components, for some frameworks the filename will be the one set in the meta property
-    let fileName = uidl.meta && uidl.meta.fileName ? uidl.meta.fileName : uidl.name
-    fileName = sanitizeVariableName(fileName)
-
-    const resolvedUIDL = resolver.resolveUIDL(uidl, options)
-    const { chunks, externalDependencies } = await assemblyLine.run(resolvedUIDL)
-
-    const jsCode = removeLastEmptyLine(chunksLinker.link(chunks.vuejs))
-    const cssCode = removeLastEmptyLine(chunksLinker.link(chunks.vuecss))
-    const htmlCode = removeLastEmptyLine(chunksLinker.link(chunks.vuehtml))
-
-    const formattedHTMLCode = addSpacesToEachLine(' '.repeat(2), htmlCode)
-    const vueCode = buildVueFile(formattedHTMLCode, jsCode, cssCode)
-
-    files.push(createFile(fileName, FILE_TYPE.VUE, vueCode))
-
-    return {
-      files,
-      dependencies: externalDependencies,
-    }
-  }
-
-  return {
-    generateComponent,
-    resolveElement: resolver.resolveElement.bind(resolver),
-    addMapping: resolver.addMapping.bind(resolver),
-    addPlugin: assemblyLine.addPlugin.bind(assemblyLine),
-  }
-}
-
-export default createVueGenerator
diff --git a/packages/teleport-component-generator-vue/src/vue-mapping.json b/packages/teleport-component-generator-vue/src/vue-mapping.json
index 7a133028..0c365fbe 100644
--- a/packages/teleport-component-generator-vue/src/vue-mapping.json
+++ b/packages/teleport-component-generator-vue/src/vue-mapping.json
@@ -1,7 +1,7 @@
 {
   "elements": {
-    "container": {
-      "elementType": "div"
+    "group": {
+      "elementType": "template"
     }
   },
   "events": {
diff --git a/packages/teleport-component-generator-vue/src/vue-router.ts b/packages/teleport-component-generator-vue/src/vue-router.ts
deleted file mode 100644
index d1f9bec9..00000000
--- a/packages/teleport-component-generator-vue/src/vue-router.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { AssemblyLine, Builder, Resolver, Parser } from '@teleporthq/teleport-generator-core'
-
-import vueRoutingPlugin from '@teleporthq/teleport-plugin-vue-app-routing'
-import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
-
-import htmlMapping from './html-mapping.json'
-import vueMapping from './vue-mapping.json'
-
-import { GeneratorOptions } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
-import { Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
-
-const createVuePipeline = ({ mapping }: GeneratorOptions = {}) => {
-  const resolver = new Resolver([htmlMapping as Mapping, vueMapping as Mapping, mapping])
-  const assemblyLine = new AssemblyLine([vueRoutingPlugin, importStatementsPlugin])
-
-  const chunksLinker = new Builder()
-
-  const generateComponent = async (
-    input: Record<string, unknown>,
-    options: GeneratorOptions = {}
-  ) => {
-    const uidl = Parser.parseComponentJSON(input)
-    const resolvedUIDL = resolver.resolveUIDL(uidl, options)
-    const { chunks, externalDependencies } = await assemblyLine.run(resolvedUIDL)
-    const code = chunksLinker.link(chunks.default)
-
-    return {
-      code,
-      externalDependencies,
-    }
-  }
-
-  return {
-    generateComponent,
-  }
-}
-
-export default createVuePipeline
diff --git a/packages/teleport-component-generator/README.md b/packages/teleport-component-generator/README.md
new file mode 100644
index 00000000..e46e1167
--- /dev/null
+++ b/packages/teleport-component-generator/README.md
@@ -0,0 +1,11 @@
+# `teleport-component-generator`
+
+> TODO: description
+
+## Usage
+
+```
+const teleportComponentGenerator = require('teleport-component-generator');
+
+// TODO: DEMONSTRATE API
+```
diff --git a/packages/teleport-component-generator/package.json b/packages/teleport-component-generator/package.json
new file mode 100644
index 00000000..47037a36
--- /dev/null
+++ b/packages/teleport-component-generator/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "@teleporthq/teleport-component-generator",
+  "version": "0.6.0",
+  "description": "Generic component generator that can be used together with plugins, mappings and post processing functions",
+  "author": "teleportHQ",
+  "license": "MIT",
+  "homepage": "https://teleporthq.io/",
+  "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/teleporthq/teleport-code-generators.git"
+  },
+  "bugs": {
+    "url": "https://github.com/teleporthq/teleport-code-generators/issues"
+  },
+  "publishConfig": {
+    "access": "public"
+  },
+  "scripts": {
+    "build": "tsc",
+    "build:watch": "tsc -w"
+  },
+  "dependencies": {
+    "@teleporthq/teleport-generator-shared": "^0.6.0",
+    "@teleporthq/teleport-generator-core": "^0.6.0"
+  }
+}
diff --git a/packages/teleport-component-generator-react/src/html-mapping.json b/packages/teleport-component-generator/src/html-mapping.json
similarity index 100%
rename from packages/teleport-component-generator-react/src/html-mapping.json
rename to packages/teleport-component-generator/src/html-mapping.json
diff --git a/packages/teleport-component-generator/src/index.ts b/packages/teleport-component-generator/src/index.ts
new file mode 100644
index 00000000..6b16a16a
--- /dev/null
+++ b/packages/teleport-component-generator/src/index.ts
@@ -0,0 +1,97 @@
+import {
+  AssemblyLine,
+  Builder,
+  Resolver,
+  Validator,
+  Parser,
+} from '@teleporthq/teleport-generator-core'
+
+import { createFile } from '@teleporthq/teleport-generator-shared/lib/utils/project-utils'
+import { sanitizeVariableName } from '@teleporthq/teleport-generator-shared/lib/utils/string-utils'
+
+import {
+  ComponentGenerator,
+  CompiledComponent,
+  GenerateComponentFunction,
+  ComponentPlugin,
+  PostProcessingFunction,
+} from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+import { Mapping, ComponentUIDL } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
+
+import htmlMapping from './html-mapping.json'
+
+export interface GeneratorFactoryParams {
+  mappings?: Mapping[]
+  plugins?: ComponentPlugin[]
+  postprocessors?: PostProcessingFunction[]
+}
+
+export const createGenerator = (
+  params: GeneratorFactoryParams = { mappings: [], plugins: [], postprocessors: [] }
+): ComponentGenerator => {
+  const { mappings, plugins, postprocessors } = params
+
+  const validator = new Validator()
+  const resolver = new Resolver([htmlMapping as Mapping, ...mappings])
+  const assemblyLine = new AssemblyLine(plugins)
+  const chunksLinker = new Builder()
+  const processors: PostProcessingFunction[] = postprocessors
+
+  const generateComponent: GenerateComponentFunction = async (
+    input,
+    options = {}
+  ): Promise<CompiledComponent> => {
+    if (!options.skipValidation) {
+      const validationResult = validator.validateComponent(input)
+      if (!validationResult.valid) {
+        throw new Error(validationResult.errorMsg)
+      }
+    }
+
+    const uidl = Parser.parseComponentJSON(input)
+
+    const resolvedUIDL = resolver.resolveUIDL(uidl, options)
+    const { chunks, externalDependencies } = await assemblyLine.run(resolvedUIDL)
+
+    let codeChunks: Record<string, string> = {}
+
+    Object.keys(chunks).forEach((fileId) => {
+      codeChunks[fileId] = chunksLinker.link(chunks[fileId])
+    })
+
+    processors.forEach((processor) => {
+      codeChunks = processor(codeChunks)
+    })
+
+    const files = fileBundler(uidl, codeChunks)
+
+    return {
+      files,
+      dependencies: externalDependencies,
+    }
+  }
+
+  const addPostProcessor = (fn: PostProcessingFunction) => {
+    processors.push(fn)
+  }
+
+  return {
+    generateComponent,
+    resolveElement: resolver.resolveElement.bind(resolver),
+    addMapping: resolver.addMapping.bind(resolver),
+    addPlugin: assemblyLine.addPlugin.bind(assemblyLine),
+    addPostProcessor,
+  }
+}
+
+export default createGenerator()
+
+const fileBundler = (uidl: ComponentUIDL, codeChunks: any) => {
+  let fileName = uidl.meta && uidl.meta.fileName ? uidl.meta.fileName : uidl.name
+  fileName = sanitizeVariableName(fileName)
+
+  return Object.keys(codeChunks).map((fileId) => {
+    return createFile(fileName, fileId, codeChunks[fileId])
+  })
+}
diff --git a/packages/teleport-component-generator/tsconfig.json b/packages/teleport-component-generator/tsconfig.json
new file mode 100755
index 00000000..c882c11f
--- /dev/null
+++ b/packages/teleport-component-generator/tsconfig.json
@@ -0,0 +1,9 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "lib"
+  },
+  "include": [
+    "src"
+  ]
+}
\ No newline at end of file
diff --git a/packages/teleport-generator-core/package.json b/packages/teleport-generator-core/package.json
index ad1fea5f..83a87ded 100644
--- a/packages/teleport-generator-core/package.json
+++ b/packages/teleport-generator-core/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0",
diff --git a/packages/teleport-generator-core/src/assembly-line/utils.ts b/packages/teleport-generator-core/src/assembly-line/utils.ts
index 64c141a5..bffb1ee2 100644
--- a/packages/teleport-generator-core/src/assembly-line/utils.ts
+++ b/packages/teleport-generator-core/src/assembly-line/utils.ts
@@ -1,5 +1,6 @@
 import { ComponentDependency } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
 import { ChunkDefinition } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
 
 export const extractExternalDependencies = (
   dependencies: Record<string, ComponentDependency>
@@ -22,7 +23,7 @@ export const groupChunksByFileId = (
   chunks: ChunkDefinition[]
 ): Record<string, ChunkDefinition[]> => {
   return chunks.reduce((chunksByFileId: Record<string, ChunkDefinition[]>, chunk) => {
-    const fileId = (chunk.meta && chunk.meta.fileId) || 'default'
+    const fileId = (chunk.meta && chunk.meta.fileId) || FILE_TYPE.JS
     if (!chunksByFileId[fileId]) {
       chunksByFileId[fileId] = []
     }
diff --git a/packages/teleport-generator-core/src/builder/index.ts b/packages/teleport-generator-core/src/builder/index.ts
index 72f5649f..6e379395 100644
--- a/packages/teleport-generator-core/src/builder/index.ts
+++ b/packages/teleport-generator-core/src/builder/index.ts
@@ -57,7 +57,7 @@ export default class Builder {
       const { type, content, name } = unprocessedChunks[indexToRemove]
       const compiledContent = this.generateByType(type, content)
       if (compiledContent) {
-        resultingString.push(compiledContent)
+        resultingString.push(compiledContent + '\n')
       }
 
       unprocessedChunks.splice(indexToRemove, 1)
@@ -75,7 +75,7 @@ export default class Builder {
       return ''
     }
     if (Array.isArray(content)) {
-      return content.map((contentItem) => this.generateByType(type, contentItem)).join('')
+      return content.map((contentItem) => this.generateByType(type, contentItem)).join('\n')
     }
 
     if (!this.generators[type]) {
diff --git a/packages/teleport-generator-core/src/uidl-schemas/component.json b/packages/teleport-generator-core/src/uidl-schemas/component.json
index 1b6dd309..85def68d 100644
--- a/packages/teleport-generator-core/src/uidl-schemas/component.json
+++ b/packages/teleport-generator-core/src/uidl-schemas/component.json
@@ -54,7 +54,24 @@
               "type": "string",
               "enum": ["string", "boolean", "number", "array", "func", "object", "children"]
             },
-            "defaultValue": {},
+            "defaultValue": {
+              "oneOf": [
+                { "type": "number" },
+                { "type": "boolean" },
+                { "type": "string" },
+                { "type": "object" }, 
+                {
+                  "type": "array",
+                  "items": {
+                    "oneOf": [
+                      { "type": "number" },
+                      { "type": "string" },
+                      { "type": "object" }
+                    ]
+                  }
+                }
+              ]
+            },
             "meta": {"type": "object"}
           }
         }
diff --git a/packages/teleport-generator-shared/package.json b/packages/teleport-generator-shared/package.json
index 8ef11f1f..2955f85e 100644
--- a/packages/teleport-generator-shared/package.json
+++ b/packages/teleport-generator-shared/package.json
@@ -18,14 +18,14 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/generator": "^7.4.0",
     "@babel/types": "^7.3.3",
     "jss": "^9.8.7",
     "jss-preset-default": "^4.5.0",
-    "@starptech/prettyhtml-hast-to-html": "^0.8.17",
-    "prettier": "^1.17.0"
+    "@starptech/prettyhtml-hast-to-html": "^0.8.17"
   }
 }
diff --git a/packages/teleport-generator-shared/src/generators/html-to-string.ts b/packages/teleport-generator-shared/src/generators/html-to-string.ts
index 9945c371..77bbdfe3 100644
--- a/packages/teleport-generator-shared/src/generators/html-to-string.ts
+++ b/packages/teleport-generator-shared/src/generators/html-to-string.ts
@@ -1,20 +1,6 @@
-import { format } from 'prettier/standalone'
-
-import parserHTML from 'prettier/parser-html'
-import parserPostCSS from 'prettier/parser-postcss'
-
 import toHTML from '@starptech/prettyhtml-hast-to-html'
-import { PRETTIER_CONFIG } from '../constants'
 import { CodeGeneratorFunction, HastNode } from '../typings/generators'
 
 export const generator: CodeGeneratorFunction<HastNode> = (htmlObject) => {
-  const unformatedString = toHTML(htmlObject)
-
-  const formatted = format(unformatedString, {
-    ...PRETTIER_CONFIG,
-    htmlWhitespaceSensitivity: 'ignore',
-    plugins: [parserHTML, parserPostCSS],
-    parser: 'html',
-  })
-  return formatted
+  return toHTML(htmlObject)
 }
diff --git a/packages/teleport-generator-shared/src/generators/js-ast-to-code.ts b/packages/teleport-generator-shared/src/generators/js-ast-to-code.ts
index f9ff07f4..0916ef6a 100644
--- a/packages/teleport-generator-shared/src/generators/js-ast-to-code.ts
+++ b/packages/teleport-generator-shared/src/generators/js-ast-to-code.ts
@@ -1,24 +1,8 @@
-// @ts-ignore
 import babelGenerator from '@babel/generator'
 import * as types from '@babel/types'
-// @ts-ignore
-import { format } from 'prettier/standalone'
 
-// @ts-ignore
-import parserBabylon from 'prettier/parser-babylon'
-import parserPostCSS from 'prettier/parser-postcss'
-
-import { PRETTIER_CONFIG } from '../constants'
 import { CodeGeneratorFunction } from '../typings/generators'
 
 export const generator: CodeGeneratorFunction<types.Node> = (ast) => {
-  const code = babelGenerator(ast).code
-
-  const formatted = format(code, {
-    ...PRETTIER_CONFIG,
-    plugins: [parserBabylon, parserPostCSS],
-    parser: 'babel',
-  })
-
-  return formatted
+  return babelGenerator(ast).code
 }
diff --git a/packages/teleport-generator-shared/src/typings/generators.ts b/packages/teleport-generator-shared/src/typings/generators.ts
index 34596947..8e51537f 100644
--- a/packages/teleport-generator-shared/src/typings/generators.ts
+++ b/packages/teleport-generator-shared/src/typings/generators.ts
@@ -48,11 +48,14 @@ export interface CompiledComponent {
   dependencies: Record<string, string>
 }
 
+export type PostProcessingFunction = (codeChunks: Record<string, string>) => Record<string, string>
+
 export interface ComponentGenerator {
   generateComponent: GenerateComponentFunction
   resolveElement: (node: UIDLElement, options?: GeneratorOptions) => UIDLElement
   addPlugin: (plugin: ComponentPlugin) => void
   addMapping: (mapping: Mapping) => void
+  addPostProcessor: (fn: PostProcessingFunction) => void
 }
 
 export interface GeneratorOptions {
diff --git a/packages/teleport-plugin-import-statements/package.json b/packages/teleport-plugin-import-statements/package.json
index e7f14bcd..f04201d6 100644
--- a/packages/teleport-plugin-import-statements/package.json
+++ b/packages/teleport-plugin-import-statements/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0"
diff --git a/packages/teleport-plugin-import-statements/src/index.ts b/packages/teleport-plugin-import-statements/src/index.ts
index bbb1a1ce..78e1718c 100644
--- a/packages/teleport-plugin-import-statements/src/index.ts
+++ b/packages/teleport-plugin-import-statements/src/index.ts
@@ -5,6 +5,7 @@ import {
   ChunkDefinition,
 } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
 import { ComponentDependency } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
+import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
 
 interface ImportPluginConfig {
   importLibsChunkName?: string
@@ -17,7 +18,7 @@ export const createPlugin: ComponentPluginFactory<ImportPluginConfig> = (config)
     importLibsChunkName = 'import-lib',
     importPackagesChunkName = 'import-pack',
     importLocalsChunkName = 'import-local',
-    fileId = null,
+    fileId = FILE_TYPE.JS,
   } = config || {}
 
   const importPlugin: ComponentPlugin = async (structure) => {
diff --git a/packages/teleport-plugin-react-app-routing/package.json b/packages/teleport-plugin-react-app-routing/package.json
index 6ce204c3..99e35cae 100644
--- a/packages/teleport-plugin-react-app-routing/package.json
+++ b/packages/teleport-plugin-react-app-routing/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/types": "^7.3.3",
diff --git a/packages/teleport-plugin-react-base-component/package.json b/packages/teleport-plugin-react-base-component/package.json
index f2ff4d6f..320b208e 100644
--- a/packages/teleport-plugin-react-base-component/package.json
+++ b/packages/teleport-plugin-react-base-component/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/types": "^7.3.3",
diff --git a/packages/teleport-plugin-react-css-modules/package.json b/packages/teleport-plugin-react-css-modules/package.json
index b9c60d11..81be213e 100644
--- a/packages/teleport-plugin-react-css-modules/package.json
+++ b/packages/teleport-plugin-react-css-modules/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0",
diff --git a/packages/teleport-plugin-react-css-modules/src/index.ts b/packages/teleport-plugin-react-css-modules/src/index.ts
index f3655cae..aada0dc2 100644
--- a/packages/teleport-plugin-react-css-modules/src/index.ts
+++ b/packages/teleport-plugin-react-css-modules/src/index.ts
@@ -19,6 +19,7 @@ import {
   ComponentPluginFactory,
   ComponentPlugin,
 } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
 
 interface ReactCSSModulesConfig {
   componentChunkName: string
@@ -32,7 +33,7 @@ const defaultConfigProps = {
   componentChunkName: 'react-component',
   styleChunkName: 'css-modules',
   styleObjectImportName: 'styles',
-  fileId: 'cssmodule',
+  fileId: FILE_TYPE.CSS,
   camelCaseClassNames: true,
 }
 
diff --git a/packages/teleport-plugin-react-inline-styles/package.json b/packages/teleport-plugin-react-inline-styles/package.json
index 39e66a60..043a237f 100644
--- a/packages/teleport-plugin-react-inline-styles/package.json
+++ b/packages/teleport-plugin-react-inline-styles/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/types": "^7.3.3",
diff --git a/packages/teleport-plugin-react-jss/package.json b/packages/teleport-plugin-react-jss/package.json
index 386a61e4..9552fb57 100644
--- a/packages/teleport-plugin-react-jss/package.json
+++ b/packages/teleport-plugin-react-jss/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0",
diff --git a/packages/teleport-plugin-react-proptypes/package.json b/packages/teleport-plugin-react-proptypes/package.json
index 581afd65..9db4aa15 100644
--- a/packages/teleport-plugin-react-proptypes/package.json
+++ b/packages/teleport-plugin-react-proptypes/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/types": "^7.3.3",
diff --git a/packages/teleport-plugin-react-styled-components/package.json b/packages/teleport-plugin-react-styled-components/package.json
index e0690750..8eaadc8d 100644
--- a/packages/teleport-plugin-react-styled-components/package.json
+++ b/packages/teleport-plugin-react-styled-components/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0",
diff --git a/packages/teleport-plugin-react-styled-jsx/package.json b/packages/teleport-plugin-react-styled-jsx/package.json
index 1a99ac85..034bf5f6 100644
--- a/packages/teleport-plugin-react-styled-jsx/package.json
+++ b/packages/teleport-plugin-react-styled-jsx/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0"
diff --git a/packages/teleport-plugin-vue-app-routing/package.json b/packages/teleport-plugin-vue-app-routing/package.json
index d962c775..7c338ba8 100644
--- a/packages/teleport-plugin-vue-app-routing/package.json
+++ b/packages/teleport-plugin-vue-app-routing/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/types": "^7.3.3",
diff --git a/packages/teleport-plugin-vue-base-component/package.json b/packages/teleport-plugin-vue-base-component/package.json
index 983b4c3f..c43664f1 100644
--- a/packages/teleport-plugin-vue-base-component/package.json
+++ b/packages/teleport-plugin-vue-base-component/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/types": "^7.3.3",
diff --git a/packages/teleport-plugin-vue-base-component/src/index.ts b/packages/teleport-plugin-vue-base-component/src/index.ts
index 863e1f18..c78e155f 100644
--- a/packages/teleport-plugin-vue-base-component/src/index.ts
+++ b/packages/teleport-plugin-vue-base-component/src/index.ts
@@ -3,6 +3,7 @@ import {
   ComponentPluginFactory,
   ComponentPlugin,
 } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
 
 interface VueComponentConfig {
   vueTemplateChunkName: string
@@ -18,8 +19,8 @@ export const createPlugin: ComponentPluginFactory<VueComponentConfig> = (config)
   const {
     vueTemplateChunkName = 'vue-template-chunk',
     vueJSChunkName = 'vue-js-chunk',
-    htmlFileId = 'vuehtml',
-    jsFileId = 'vuejs',
+    htmlFileId = FILE_TYPE.HTML,
+    jsFileId = FILE_TYPE.JS,
     jsFileAfter = ['import-lib', 'import-pack', 'import-local'],
   } = config || {}
 
diff --git a/packages/teleport-plugin-vue-css/package.json b/packages/teleport-plugin-vue-css/package.json
index 039b0996..36dce7d9 100644
--- a/packages/teleport-plugin-vue-css/package.json
+++ b/packages/teleport-plugin-vue-css/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0"
diff --git a/packages/teleport-plugin-vue-css/src/index.ts b/packages/teleport-plugin-vue-css/src/index.ts
index 5ad4f64d..d88aa280 100644
--- a/packages/teleport-plugin-vue-css/src/index.ts
+++ b/packages/teleport-plugin-vue-css/src/index.ts
@@ -14,6 +14,7 @@ import {
   ComponentPluginFactory,
   ComponentPlugin,
 } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
 
 interface VueStyleChunkConfig {
   chunkName: string
@@ -26,7 +27,7 @@ export const createPlugin: ComponentPluginFactory<VueStyleChunkConfig> = (config
   const {
     chunkName = 'vue-style-chunk',
     vueTemplateChunk = 'vue-template-chunk',
-    styleFileId = 'vuecss',
+    styleFileId = FILE_TYPE.CSS,
   } = config || {}
 
   const vueComponentStyleChunkPlugin: ComponentPlugin = async (structure) => {
diff --git a/packages/teleport-postprocessor-prettier-html/README.md b/packages/teleport-postprocessor-prettier-html/README.md
new file mode 100644
index 00000000..6e93d20c
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-html/README.md
@@ -0,0 +1,11 @@
+# `teleport-postprocessor-prettier-html`
+
+> TODO: description
+
+## Usage
+
+```
+const teleportPostprocessorPrettierHtml = require('teleport-postprocessor-prettier-html');
+
+// TODO: DEMONSTRATE API
+```
diff --git a/packages/teleport-postprocessor-prettier-html/package.json b/packages/teleport-postprocessor-prettier-html/package.json
new file mode 100644
index 00000000..ac61ead1
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-html/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "@teleporthq/teleport-postprocessor-prettier-html",
+  "version": "0.6.0",
+  "description": "A post-processing function that formats html code chunks using prettier and the prettier-html plugin",
+  "author": "teleportHQ",
+  "license": "MIT",
+  "homepage": "https://teleporthq.io/",
+  "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/teleporthq/teleport-code-generators.git"
+  },
+  "bugs": {
+    "url": "https://github.com/teleporthq/teleport-code-generators/issues"
+  },
+  "publishConfig": {
+    "access": "public"
+  },
+  "scripts": {
+    "build": "tsc",
+    "build:watch": "tsc -w"
+  },
+  "dependencies": {
+    "@teleporthq/teleport-generator-shared": "^0.6.0",
+    "prettier": "^1.17.0"
+  }
+}
diff --git a/packages/teleport-postprocessor-prettier-html/src/index.ts b/packages/teleport-postprocessor-prettier-html/src/index.ts
new file mode 100644
index 00000000..26b471a8
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-html/src/index.ts
@@ -0,0 +1,24 @@
+import { format } from 'prettier/standalone'
+
+import parserHTML from 'prettier/parser-html'
+import parserPostCSS from 'prettier/parser-postcss'
+
+import { PRETTIER_CONFIG, FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
+import { PostProcessingFunction } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+const processor: PostProcessingFunction = (codeChunks) => {
+  if (codeChunks[FILE_TYPE.HTML]) {
+    codeChunks[FILE_TYPE.HTML] = format(codeChunks[FILE_TYPE.HTML], {
+      ...PRETTIER_CONFIG,
+      htmlWhitespaceSensitivity: 'ignore',
+      plugins: [parserHTML, parserPostCSS],
+      parser: 'html',
+    })
+  } else {
+    console.warn('No code chunk of type HTML found, prettier-html did not perform any operation')
+  }
+
+  return codeChunks
+}
+
+export default processor
diff --git a/packages/teleport-postprocessor-prettier-html/tsconfig.json b/packages/teleport-postprocessor-prettier-html/tsconfig.json
new file mode 100755
index 00000000..a8225141
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-html/tsconfig.json
@@ -0,0 +1,9 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "lib"
+  },
+  "include": [
+    "./src"
+  ]
+}
\ No newline at end of file
diff --git a/packages/teleport-postprocessor-prettier-js/README.md b/packages/teleport-postprocessor-prettier-js/README.md
new file mode 100644
index 00000000..b398c8e6
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-js/README.md
@@ -0,0 +1,11 @@
+# `teleport-postprocessor-prettier-js`
+
+> TODO: description
+
+## Usage
+
+```
+const teleportPostprocessorPrettierJs = require('teleport-postprocessor-prettier-js');
+
+// TODO: DEMONSTRATE API
+```
diff --git a/packages/teleport-postprocessor-prettier-js/package.json b/packages/teleport-postprocessor-prettier-js/package.json
new file mode 100644
index 00000000..269844d7
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-js/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "@teleporthq/teleport-postprocessor-prettier-js",
+  "version": "0.6.0",
+  "description": "A post-processing function that formats js code chunks using prettier and the prettier-js plugin",
+  "author": "teleportHQ",
+  "license": "MIT",
+  "homepage": "https://teleporthq.io/",
+  "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/teleporthq/teleport-code-generators.git"
+  },
+  "bugs": {
+    "url": "https://github.com/teleporthq/teleport-code-generators/issues"
+  },
+  "publishConfig": {
+    "access": "public"
+  },
+  "scripts": {
+    "build": "tsc",
+    "build:watch": "tsc -w"
+  },
+  "dependencies": {
+    "@teleporthq/teleport-generator-shared": "^0.6.0",
+    "prettier": "^1.17.0"
+  }
+}
diff --git a/packages/teleport-postprocessor-prettier-js/src/index.ts b/packages/teleport-postprocessor-prettier-js/src/index.ts
new file mode 100644
index 00000000..475697cd
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-js/src/index.ts
@@ -0,0 +1,23 @@
+import { format } from 'prettier/standalone'
+
+import parserBabylon from 'prettier/parser-babylon'
+import parserPostCSS from 'prettier/parser-postcss'
+
+import { PRETTIER_CONFIG, FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
+import { PostProcessingFunction } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+const processor: PostProcessingFunction = (codeChunks) => {
+  if (codeChunks[FILE_TYPE.JS]) {
+    codeChunks[FILE_TYPE.JS] = format(codeChunks[FILE_TYPE.JS], {
+      ...PRETTIER_CONFIG,
+      plugins: [parserBabylon, parserPostCSS],
+      parser: 'babel',
+    })
+  } else {
+    console.warn('No code chunk of type JS found, prettier-js did not perform any operation')
+  }
+
+  return codeChunks
+}
+
+export default processor
diff --git a/packages/teleport-postprocessor-prettier-js/tsconfig.json b/packages/teleport-postprocessor-prettier-js/tsconfig.json
new file mode 100755
index 00000000..a8225141
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-js/tsconfig.json
@@ -0,0 +1,9 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "lib"
+  },
+  "include": [
+    "./src"
+  ]
+}
\ No newline at end of file
diff --git a/packages/teleport-postprocessor-vue-file/README.md b/packages/teleport-postprocessor-vue-file/README.md
new file mode 100644
index 00000000..aa74c821
--- /dev/null
+++ b/packages/teleport-postprocessor-vue-file/README.md
@@ -0,0 +1,11 @@
+# `teleport-postprocessor-vue-file`
+
+> TODO: description
+
+## Usage
+
+```
+const teleportPostprocessorVueFile = require('teleport-postprocessor-vue-file');
+
+// TODO: DEMONSTRATE API
+```
diff --git a/packages/teleport-postprocessor-vue-file/package.json b/packages/teleport-postprocessor-vue-file/package.json
new file mode 100644
index 00000000..55411563
--- /dev/null
+++ b/packages/teleport-postprocessor-vue-file/package.json
@@ -0,0 +1,27 @@
+{
+  "name": "@teleporthq/teleport-postprocessor-vue-file",
+  "version": "0.6.0",
+  "description": "A post-processing function that concatenates html/js/css code chunks into a single code chunk of type vue",
+  "author": "teleportHQ",
+  "license": "MIT",
+  "homepage": "https://teleporthq.io/",
+  "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/teleporthq/teleport-code-generators.git"
+  },
+  "bugs": {
+    "url": "https://github.com/teleporthq/teleport-code-generators/issues"
+  },
+  "publishConfig": {
+    "access": "public"
+  },
+  "scripts": {
+    "build": "tsc",
+    "build:watch": "tsc -w"
+  },
+  "dependencies": {
+    "@teleporthq/teleport-generator-shared": "^0.6.0"
+  }
+}
diff --git a/packages/teleport-postprocessor-vue-file/src/index.ts b/packages/teleport-postprocessor-vue-file/src/index.ts
new file mode 100644
index 00000000..1ffabeab
--- /dev/null
+++ b/packages/teleport-postprocessor-vue-file/src/index.ts
@@ -0,0 +1,59 @@
+import { PostProcessingFunction } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+import {
+  removeLastEmptyLine,
+  addSpacesToEachLine,
+} from '@teleporthq/teleport-generator-shared/lib/utils/string-utils'
+import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
+
+const processor: PostProcessingFunction = (codeChunks) => {
+  let jsCode
+  let cssCode
+  let htmlCode
+
+  if (codeChunks[FILE_TYPE.HTML]) {
+    htmlCode = removeLastEmptyLine(codeChunks[FILE_TYPE.HTML])
+  } else {
+    throw new Error('No code chunk of type HTML found, vue file concatenation aborded')
+  }
+
+  if (codeChunks[FILE_TYPE.JS]) {
+    jsCode = removeLastEmptyLine(codeChunks[FILE_TYPE.JS])
+  } else {
+    throw new Error('No code chunk of type JS found, vue file concatenation aborded')
+  }
+
+  // if no CSS, skip the <style></style>
+  if (codeChunks[FILE_TYPE.CSS]) {
+    cssCode = removeLastEmptyLine(codeChunks[FILE_TYPE.CSS])
+  }
+
+  const formattedHTMLCode = addSpacesToEachLine(' '.repeat(2), htmlCode)
+  const vueCode = buildVueFile(formattedHTMLCode, jsCode, cssCode)
+
+  return {
+    [FILE_TYPE.VUE]: vueCode,
+  }
+}
+
+export default processor
+
+export const buildVueFile = (htmlCode: string, jsCode: string, cssCode: string) => {
+  let code = `<template>
+${htmlCode}
+</template>
+
+<script>
+${jsCode}
+</script>
+`
+
+  if (cssCode) {
+    code += `
+<style>
+${cssCode}
+</style>
+`
+  }
+
+  return code
+}
diff --git a/packages/teleport-postprocessor-vue-file/tsconfig.json b/packages/teleport-postprocessor-vue-file/tsconfig.json
new file mode 100755
index 00000000..a8225141
--- /dev/null
+++ b/packages/teleport-postprocessor-vue-file/tsconfig.json
@@ -0,0 +1,9 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "lib"
+  },
+  "include": [
+    "./src"
+  ]
+}
\ No newline at end of file
diff --git a/packages/teleport-project-generator-react-basic/package.json b/packages/teleport-project-generator-react-basic/package.json
index 06549be0..ea69d4dc 100644
--- a/packages/teleport-project-generator-react-basic/package.json
+++ b/packages/teleport-project-generator-react-basic/package.json
@@ -18,11 +18,16 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0",
     "@teleporthq/teleport-generator-core": "^0.6.0",
-    "@teleporthq/teleport-component-generator-react": "^0.6.0"
+    "@teleporthq/teleport-component-generator": "^0.6.0",
+    "@teleporthq/teleport-component-generator-react": "^0.6.0",
+    "@teleporthq/teleport-postprocessor-prettier-js": "^0.6.0",
+    "@teleporthq/teleport-plugin-import-statements": "^0.6.0",
+    "@teleporthq/teleport-plugin-react-app-routing": "^0.6.0"
   }
 }
diff --git a/packages/teleport-project-generator-react-basic/src/component-generators/router-component.ts b/packages/teleport-project-generator-react-basic/src/component-generators/router-component.ts
new file mode 100644
index 00000000..d09c1dc3
--- /dev/null
+++ b/packages/teleport-project-generator-react-basic/src/component-generators/router-component.ts
@@ -0,0 +1,21 @@
+import reactAppRoutingPlugin from '@teleporthq/teleport-plugin-react-app-routing'
+import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
+
+import prettierJS from '@teleporthq/teleport-postprocessor-prettier-js'
+
+import { createGenerator } from '@teleporthq/teleport-component-generator'
+
+import { ComponentGenerator } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+export const createReactRouterGenerator = (): ComponentGenerator => {
+  const generator = createGenerator()
+
+  generator.addPlugin(reactAppRoutingPlugin)
+  generator.addPlugin(importStatementsPlugin)
+
+  generator.addPostProcessor(prettierJS)
+
+  return generator
+}
+
+export default createReactRouterGenerator
diff --git a/packages/teleport-project-generator-react-basic/src/index.ts b/packages/teleport-project-generator-react-basic/src/index.ts
index a4c569a2..0b381eea 100644
--- a/packages/teleport-project-generator-react-basic/src/index.ts
+++ b/packages/teleport-project-generator-react-basic/src/index.ts
@@ -32,9 +32,7 @@ import {
 import { ComponentUIDL, Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
 
 const initGenerator = (options: ProjectGeneratorOptions): ComponentGenerator => {
-  const reactGenerator = createReactComponentGenerator({
-    variation: 'CSSModules',
-  })
+  const reactGenerator = createReactComponentGenerator('CSSModules')
 
   reactGenerator.addMapping(reactProjectMapping as Mapping)
   if (options.customMapping) {
@@ -122,14 +120,14 @@ const createReactBasicGenerator = (generatorOptions: ProjectGeneratorOptions = {
     }
 
     // Step 7: Create the routing component (index.js)
-    const { routerFile, externalDependencies } = await createRouterIndexFile(root)
+    const { routerFile, dependencies: routerDependencies } = await createRouterIndexFile(root)
     const htmlIndexFile = createHtmlIndexFile(uidl, { assetsPrefix: ASSETS_PREFIX })
 
     const srcFiles: GeneratedFile[] = [htmlIndexFile, routerFile]
 
     // Step 8: Join all the external dependencies
     const collectedDependencies = {
-      ...externalDependencies,
+      ...routerDependencies,
       ...joinedPageFiles.dependencies,
       ...joinedComponentFiles.dependencies,
     }
diff --git a/packages/teleport-project-generator-react-basic/src/utils.ts b/packages/teleport-project-generator-react-basic/src/utils.ts
index 61c3ced2..d9d1e300 100644
--- a/packages/teleport-project-generator-react-basic/src/utils.ts
+++ b/packages/teleport-project-generator-react-basic/src/utils.ts
@@ -1,10 +1,6 @@
-import { createReactRouterComponentGenerator } from '@teleporthq/teleport-component-generator-react'
+import { createReactRouterGenerator } from './component-generators/router-component'
 
-import {
-  createFolder,
-  createFile,
-} from '@teleporthq/teleport-generator-shared/lib/utils/project-utils'
-import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
+import { createFolder } from '@teleporthq/teleport-generator-shared/lib/utils/project-utils'
 
 import {
   GeneratedFile,
@@ -25,9 +21,14 @@ export const buildFolderStructure = (
 }
 
 export const createRouterIndexFile = async (root: ComponentUIDL) => {
-  const routingComponentGenerator = createReactRouterComponentGenerator()
-  const { code, externalDependencies } = await routingComponentGenerator.generateComponent(root)
-  const routerFile = createFile('index', FILE_TYPE.JS, code)
+  const routingComponentGenerator = createReactRouterGenerator()
+
+  // React router is generated in index.js
+  root.meta = root.meta || {}
+  root.meta.fileName = 'index'
+
+  const { files, dependencies } = await routingComponentGenerator.generateComponent(root)
+  const routerFile = files[0]
 
-  return { routerFile, externalDependencies }
+  return { routerFile, dependencies }
 }
diff --git a/packages/teleport-project-generator-react-next/package.json b/packages/teleport-project-generator-react-next/package.json
index ca639db7..fe8cacef 100644
--- a/packages/teleport-project-generator-react-next/package.json
+++ b/packages/teleport-project-generator-react-next/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@babel/types": "^7.3.3",
diff --git a/packages/teleport-project-generator-react-next/src/index.ts b/packages/teleport-project-generator-react-next/src/index.ts
index 87371a6c..4f001d7f 100644
--- a/packages/teleport-project-generator-react-next/src/index.ts
+++ b/packages/teleport-project-generator-react-next/src/index.ts
@@ -32,9 +32,7 @@ import {
 import { ComponentUIDL, Mapping } from '@teleporthq/teleport-generator-shared/lib/typings/uidl'
 
 const initGenerator = (options: ProjectGeneratorOptions): ComponentGenerator => {
-  const reactGenerator = createReactComponentGenerator({
-    variation: 'StyledJSX',
-  })
+  const reactGenerator = createReactComponentGenerator('StyledJSX')
 
   reactGenerator.addMapping(nextMapping as Mapping)
   if (options.customMapping) {
diff --git a/packages/teleport-project-generator-vue-basic/package.json b/packages/teleport-project-generator-vue-basic/package.json
index fa951986..28c691a1 100644
--- a/packages/teleport-project-generator-vue-basic/package.json
+++ b/packages/teleport-project-generator-vue-basic/package.json
@@ -18,11 +18,16 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0",
     "@teleporthq/teleport-generator-core": "^0.6.0",
-    "@teleporthq/teleport-component-generator-vue": "^0.6.0"
+    "@teleporthq/teleport-component-generator-vue": "^0.6.0",
+    "@teleporthq/teleport-postprocessor-prettier-js": "^0.6.0",
+    "@teleporthq/teleport-plugin-import-statements": "^0.6.0",
+    "@teleporthq/teleport-plugin-vue-app-routing": "^0.6.0",
+    "@teleporthq/teleport-component-generator": "^0.6.0"
   }
 }
diff --git a/packages/teleport-project-generator-vue-basic/src/component-generators/router-component.ts b/packages/teleport-project-generator-vue-basic/src/component-generators/router-component.ts
new file mode 100644
index 00000000..561774fc
--- /dev/null
+++ b/packages/teleport-project-generator-vue-basic/src/component-generators/router-component.ts
@@ -0,0 +1,21 @@
+import { createGenerator } from '@teleporthq/teleport-component-generator'
+
+import vueRoutingPlugin from '@teleporthq/teleport-plugin-vue-app-routing'
+import importStatementsPlugin from '@teleporthq/teleport-plugin-import-statements'
+
+import prettierJS from '@teleporthq/teleport-postprocessor-prettier-js'
+
+import { ComponentGenerator } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+const createVueRouterGenerator = (): ComponentGenerator => {
+  const generator = createGenerator()
+
+  generator.addPlugin(vueRoutingPlugin)
+  generator.addPlugin(importStatementsPlugin)
+
+  generator.addPostProcessor(prettierJS)
+
+  return generator
+}
+
+export default createVueRouterGenerator
diff --git a/packages/teleport-project-generator-vue-basic/src/index.ts b/packages/teleport-project-generator-vue-basic/src/index.ts
index 7f811407..085f7f4d 100644
--- a/packages/teleport-project-generator-vue-basic/src/index.ts
+++ b/packages/teleport-project-generator-vue-basic/src/index.ts
@@ -122,11 +122,11 @@ const createVueBasicGenerator = (generatorOptions: ProjectGeneratorOptions = {})
     publicFiles.push(htmlIndexFile)
 
     // Step 7: Create the routing component (router.js)
-    const { routerFile, externalDependencies } = await createRouterFile(root)
+    const { routerFile, dependencies: routerDependencies } = await createRouterFile(root)
     const srcFiles: GeneratedFile[] = [].concat(routerFile)
 
     const collectedDependencies = {
-      ...externalDependencies,
+      ...routerDependencies,
       ...joinedPageFiles.dependencies,
       ...joinedComponentFiles.dependencies,
     }
diff --git a/packages/teleport-project-generator-vue-basic/src/utils.ts b/packages/teleport-project-generator-vue-basic/src/utils.ts
index 59673798..a508c405 100644
--- a/packages/teleport-project-generator-vue-basic/src/utils.ts
+++ b/packages/teleport-project-generator-vue-basic/src/utils.ts
@@ -1,9 +1,5 @@
-import { createVueRouterComponentGenerator } from '@teleporthq/teleport-component-generator-vue'
-import {
-  createFile,
-  createFolder,
-} from '@teleporthq/teleport-generator-shared/lib/utils/project-utils'
-import { FILE_TYPE } from '@teleporthq/teleport-generator-shared/lib/constants'
+import createVueRouterComponentGenerator from './component-generators/router-component'
+import { createFolder } from '@teleporthq/teleport-generator-shared/lib/utils/project-utils'
 
 import {
   GeneratedFile,
@@ -25,8 +21,13 @@ export const buildFolderStructure = (
 
 export const createRouterFile = async (root: ComponentUIDL) => {
   const vueRouterGenerator = createVueRouterComponentGenerator()
-  const { code, externalDependencies } = await vueRouterGenerator.generateComponent(root)
-  const routerFile = createFile('router', FILE_TYPE.JS, code)
 
-  return { routerFile, externalDependencies }
+  // Routes are defined in router.js
+  root.meta = root.meta || {}
+  root.meta.fileName = 'router'
+
+  const { files, dependencies } = await vueRouterGenerator.generateComponent(root)
+  const routerFile = files[0]
+
+  return { routerFile, dependencies }
 }
diff --git a/packages/teleport-project-generator-vue-nuxt/package.json b/packages/teleport-project-generator-vue-nuxt/package.json
index 07f5f90b..c9b3881d 100644
--- a/packages/teleport-project-generator-vue-nuxt/package.json
+++ b/packages/teleport-project-generator-vue-nuxt/package.json
@@ -18,7 +18,8 @@
     "access": "public"
   },
   "scripts": {
-    "build": "tsc"
+    "build": "tsc",
+    "build:watch": "tsc -w"
   },
   "dependencies": {
     "@teleporthq/teleport-generator-shared": "^0.6.0",
diff --git a/yarn.lock b/yarn.lock
index 96157759..d4570680 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1113,6 +1113,10 @@ are-we-there-yet@~1.1.2:
     delegates "^1.0.0"
     readable-stream "^2.0.6"
 
+arg@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0"
+
 argparse@^1.0.7:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -2016,7 +2020,7 @@ diff-sequences@^24.3.0:
   version "24.3.0"
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975"
 
-diff@^3.2.0:
+diff@^3.1.0, diff@^3.2.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
 
@@ -3948,7 +3952,7 @@ make-dir@^1.0.0, make-dir@^1.3.0:
   dependencies:
     pify "^3.0.0"
 
-make-error@1.x:
+make-error@1.x, make-error@^1.1.1:
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
 
@@ -5843,6 +5847,16 @@ ts-jest@^24.0.2:
     semver "^5.5"
     yargs-parser "10.x"
 
+ts-node@^8.1.0:
+  version "8.1.0"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.1.0.tgz#8c4b37036abd448577db22a061fd7a67d47e658e"
+  dependencies:
+    arg "^4.1.0"
+    diff "^3.1.0"
+    make-error "^1.1.1"
+    source-map-support "^0.5.6"
+    yn "^3.0.0"
+
 tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@@ -6275,3 +6289,7 @@ yargs@^13.1.0:
     which-module "^2.0.0"
     y18n "^4.0.0"
     yargs-parser "^13.0.0"
+
+yn@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.0.tgz#fcbe2db63610361afcc5eb9e0ac91e976d046114"


Test patch:
diff --git a/packages/teleport-component-generator-react/__tests__/end2end/index.ts b/packages/teleport-component-generator-react/__tests__/end2end/index.ts
index 4f7a545e..dfce6bf3 100644
--- a/packages/teleport-component-generator-react/__tests__/end2end/index.ts
+++ b/packages/teleport-component-generator-react/__tests__/end2end/index.ts
@@ -15,9 +15,7 @@ const findFileByType = (files: GeneratedFile[], type: string = JS_FILE) =>
 
 describe('React Component Generator', () => {
   describe('with CSS Modules', () => {
-    const generator = createReactComponentGenerator({
-      variation: 'CSSModules',
-    })
+    const generator = createReactComponentGenerator('CSSModules')
 
     it('should return the files containing the code as string', async () => {
       const result = await generator.generateComponent(uidlSample)
@@ -33,9 +31,7 @@ describe('React Component Generator', () => {
   })
 
   describe('with JSS', () => {
-    const generator = createReactComponentGenerator({
-      variation: 'JSS',
-    })
+    const generator = createReactComponentGenerator('JSS')
 
     it('should return the files containing the code as string', async () => {
       const result = await generator.generateComponent(uidlSample)
@@ -79,10 +75,8 @@ describe('React Component Generator', () => {
   })
 
   describe('with Custom Mapping', () => {
-    const generator = createReactComponentGenerator({
-      variation: 'InlineStyles',
-      customMapping: { elements: { container: { elementType: 'fakediv' } } },
-    })
+    const mapping = { elements: { container: { elementType: 'fakediv' } } }
+    const generator = createReactComponentGenerator('InlineStyles', { mapping })
 
     it('should render <fakediv> tags', async () => {
       const result = await generator.generateComponent(uidlSample)
@@ -97,9 +91,7 @@ describe('React Component Generator', () => {
 })
 
 describe('React Component Validator', () => {
-  const generator = createReactComponentGenerator({
-    variation: 'CSSModules',
-  })
+  const generator = createReactComponentGenerator('CSSModules')
 
   it('works with valid UIDL sample', async () => {
     const result = await generator.generateComponent(uidlSample)
diff --git a/packages/teleport-component-generator-react/__tests__/integration/component-style.ts b/packages/teleport-component-generator-react/__tests__/integration/component-style.ts
index 39a0c5c0..33611ded 100644
--- a/packages/teleport-component-generator-react/__tests__/integration/component-style.ts
+++ b/packages/teleport-component-generator-react/__tests__/integration/component-style.ts
@@ -37,9 +37,7 @@ describe('React Styles in Component', () => {
     })
 
     it('CSSModules should refer state in styles when state is mapped', async () => {
-      const generator = createReactComponentGenerator({
-        variation: 'CSSModules',
-      })
+      const generator = createReactComponentGenerator('CSSModules')
       const result = await generator.generateComponent(ComponentWithStateReference)
       const jsFile = findFileByType(result.files, JS_FILE)
       const cssFile = findFileByType(result.files, CSS_FILE)
@@ -51,11 +49,9 @@ describe('React Styles in Component', () => {
     })
 
     it('JSS should through error when state is refered', async () => {
-      const generator = createReactComponentGenerator({
-        variation: 'JSS',
-      })
+      const generator = createReactComponentGenerator('JSS')
       try {
-        const result = await generator.generateComponent(ComponentWithStateReference)
+        await generator.generateComponent(ComponentWithStateReference)
       } catch (e) {
         expect(e.message).toContain('reactJSSComponentStyleChunksPlugin')
         expect(e.message).toContain('styleValue.content.referenceType value state')
@@ -76,9 +72,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should support object props in styledjsx', async () => {
-      const styledJSXGenerator = createReactComponentGenerator({
-        variation: 'StyledJSX',
-      })
+      const styledJSXGenerator = createReactComponentGenerator('StyledJSX')
       const result = await styledJSXGenerator.generateComponent(ComponentWithValidStyle)
       const jsFile = findFileByType(result.files, JS_FILE)
 
@@ -87,9 +81,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should support nested styles in styledjsx', async () => {
-      const styledJSXGenerator = createReactComponentGenerator({
-        variation: 'StyledJSX',
-      })
+      const styledJSXGenerator = createReactComponentGenerator('StyledJSX')
       const result = await styledJSXGenerator.generateComponent(
         ComponentWithNestedStyles as ComponentUIDL
       )
@@ -104,9 +96,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should throw error when a state is being refered in generated StyledJSX ', async () => {
-      const styledJSXGenerator = createReactComponentGenerator({
-        variation: 'StyledJSX',
-      })
+      const styledJSXGenerator = createReactComponentGenerator('StyledJSX')
       try {
         await styledJSXGenerator.generateComponent(ComponentWithInvalidStateStyles)
         expect(true).toBe(false)
@@ -118,9 +108,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should explicitly send prop if style is using one prop variable', async () => {
-      const styledComponentsGenerator = createReactComponentGenerator({
-        variation: 'StyledComponents',
-      })
+      const styledComponentsGenerator = createReactComponentGenerator('StyledComponents')
       const result = await styledComponentsGenerator.generateComponent(
         ComponentWithValidSingleStlye
       )
@@ -133,9 +121,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should support object props in styled-components', async () => {
-      const styledComponentsGenerator = createReactComponentGenerator({
-        variation: 'StyledComponents',
-      })
+      const styledComponentsGenerator = createReactComponentGenerator('StyledComponents')
       const result = await styledComponentsGenerator.generateComponent(ComponentWithValidStyle)
       const jsFile = findFileByType(result.files, JS_FILE)
 
@@ -144,9 +130,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should support nested styles in styled-components with single prop', async () => {
-      const styledComponentsGenerator = createReactComponentGenerator({
-        variation: 'StyledComponents',
-      })
+      const styledComponentsGenerator = createReactComponentGenerator('StyledComponents')
       const result = await styledComponentsGenerator.generateComponent(
         ComponentWithNestedStyles as ComponentUIDL
       )
@@ -161,9 +145,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should support nested styles in styled-components with multiple prop refs', async () => {
-      const styledComponentsGenerator = createReactComponentGenerator({
-        variation: 'StyledComponents',
-      })
+      const styledComponentsGenerator = createReactComponentGenerator('StyledComponents')
       const result = await styledComponentsGenerator.generateComponent(
         ComponentWithNestedMultiplePropRef as ComponentUIDL
       )
@@ -180,9 +162,7 @@ describe('React Styles in Component', () => {
     })
 
     it('should support nested styles in styled-components with single prop  ref', async () => {
-      const styledComponentsGenerator = createReactComponentGenerator({
-        variation: 'StyledComponents',
-      })
+      const styledComponentsGenerator = createReactComponentGenerator('StyledComponents')
       const result = await styledComponentsGenerator.generateComponent(
         ComponentWithNestedSinglePropRef as ComponentUIDL
       )
@@ -199,18 +179,14 @@ describe('React Styles in Component', () => {
     })
 
     it('should inject props only once for styled components', async () => {
-      const styledJSXGenerator = createReactComponentGenerator({
-        variation: 'StyledComponents',
-      })
+      const styledJSXGenerator = createReactComponentGenerator('StyledComponents')
       const result = await styledJSXGenerator.generateComponent(ComponentWithValidJSON)
       const jsFile = findFileByType(result.files, JS_FILE)
       expect(jsFile.content).toContain('<Container {...props} />')
     })
 
     it('should throw error when a state is being refered in generated StyledComponents ', async () => {
-      const styledJSXGenerator = createReactComponentGenerator({
-        variation: 'StyledComponents',
-      })
+      const styledJSXGenerator = createReactComponentGenerator('StyledComponents')
       try {
         await styledJSXGenerator.generateComponent(ComponentWithInvalidStateStyles)
         expect(true).toBe(false)
@@ -223,9 +199,7 @@ describe('React Styles in Component', () => {
   })
 
   describe('React CSS file using CSS Modules', () => {
-    const generator = createReactComponentGenerator({
-      variation: 'CSSModules',
-    })
+    const generator = createReactComponentGenerator('CSSModules')
 
     it('should return code in an array of files', async () => {
       const result = await generator.generateComponent(ComponentWithValidStyle)
diff --git a/packages/teleport-component-generator-react/__tests__/performance/index.ts b/packages/teleport-component-generator-react/__tests__/performance/index.ts
index 81043ce0..73c802db 100644
--- a/packages/teleport-component-generator-react/__tests__/performance/index.ts
+++ b/packages/teleport-component-generator-react/__tests__/performance/index.ts
@@ -10,9 +10,7 @@ import { ComponentUIDL, UIDLElement } from '@teleporthq/teleport-generator-share
 
 const componentUIDL = componentUIDLJSON as ComponentUIDL
 
-const generator = createReactComponentGenerator({
-  variation: 'StyledJSX',
-})
+const generator = createReactComponentGenerator('StyledJSX')
 
 describe('React Generator Performance Run', () => {
   describe('with realistic component sample', () => {
diff --git a/packages/teleport-component-generator/__tests__/index.ts b/packages/teleport-component-generator/__tests__/index.ts
new file mode 100644
index 00000000..935bf490
--- /dev/null
+++ b/packages/teleport-component-generator/__tests__/index.ts
@@ -0,0 +1,32 @@
+import { GenerateComponentFunction } from '@teleporthq/teleport-generator-shared/lib/typings/generators'
+
+import { createGenerator } from '../src/index'
+import { element } from '@teleporthq/teleport-generator-shared/lib/builders/uidl-builders'
+
+describe('component generator', () => {
+  it('creates a new instance of the generator', () => {
+    const generator = createGenerator()
+    expect(generator.generateComponent).toBeDefined()
+    expect(generator.addMapping).toBeDefined()
+    expect(generator.addPlugin).toBeDefined()
+    expect(generator.addPostProcessor).toBeDefined()
+    expect(generator.resolveElement).toBeDefined()
+  })
+
+  it('resolves a node', () => {
+    const generator = createGenerator()
+
+    generator.addMapping({
+      elements: {
+        container: {
+          elementType: 'div',
+          attrs: { 'data-test': { type: 'static', content: '123' } },
+        },
+      },
+    })
+
+    const result = generator.resolveElement(element('container', {}, []))
+    expect(result.elementType).toBe('div')
+    expect(result.attrs['data-test'].content).toBe('123')
+  })
+})
diff --git a/packages/teleport-postprocessor-prettier-html/__tests__/index.ts b/packages/teleport-postprocessor-prettier-html/__tests__/index.ts
new file mode 100644
index 00000000..34e470a2
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-html/__tests__/index.ts
@@ -0,0 +1,28 @@
+import processor from '../src'
+
+describe('prettier html', () => {
+  it('formats only the html chunk', () => {
+    const inputChunks = {
+      html: `<div><span >Format me!</span> 
+  </div>`,
+      js: `import React from "react"; import {Link} from "react-router"`,
+    }
+
+    const result = processor(inputChunks)
+
+    expect(result.html).toBe('<div><span>Format me!</span></div>\n')
+    expect(result.js).toBe(inputChunks.js)
+  })
+
+  it('skips formatting if no html chunk is found', () => {
+    const inputChunks = {
+      css: '.test { margin: 10px; }',
+      js: `import React from "react"; import {Link} from "react-router"`,
+    }
+
+    const result = processor(inputChunks)
+
+    expect(result.css).toBe(inputChunks.css)
+    expect(result.js).toBe(inputChunks.js)
+  })
+})
diff --git a/packages/teleport-postprocessor-prettier-js/__tests__/index.ts b/packages/teleport-postprocessor-prettier-js/__tests__/index.ts
new file mode 100644
index 00000000..6bf0941c
--- /dev/null
+++ b/packages/teleport-postprocessor-prettier-js/__tests__/index.ts
@@ -0,0 +1,29 @@
+import processor from '../src'
+
+describe('prettier js', () => {
+  it('formats only the js chunk', () => {
+    const inputChunks = {
+      html: `<div><span >Format me!</span>  </div>`,
+      js: `import React from "react"; import {Link} from "react-router"`,
+    }
+
+    const result = processor(inputChunks)
+
+    expect(result.html).toBe(inputChunks.html)
+    expect(result.js).toBe(`import React from 'react'
+import { Link } from 'react-router'
+`)
+  })
+
+  it('skips formatting if no js chunk is found', () => {
+    const inputChunks = {
+      css: '.test { margin: 10px; }',
+      html: `<div><span >Format me!</span>  </div>`,
+    }
+
+    const result = processor(inputChunks)
+
+    expect(result.css).toBe(inputChunks.css)
+    expect(result.html).toBe(inputChunks.html)
+  })
+})
diff --git a/packages/teleport-postprocessor-vue-file/__tests__/index.ts b/packages/teleport-postprocessor-vue-file/__tests__/index.ts
new file mode 100644
index 00000000..2f056dc6
--- /dev/null
+++ b/packages/teleport-postprocessor-vue-file/__tests__/index.ts
@@ -0,0 +1,73 @@
+import processor from '../src'
+
+describe('vue file concat', () => {
+  it('returns a single vue code chunk', () => {
+    const inputChunks = {
+      html: `<div><span>Format me!</span></div>
+`,
+      js: `export default {}
+`,
+      css: `.button { margin: 10px; }
+`,
+    }
+
+    const result = processor(inputChunks)
+
+    expect(result.html).toBeUndefined()
+    expect(result.js).toBeUndefined()
+    expect(result.css).toBeUndefined()
+    expect(result.vue).toBe(`<template>
+  <div><span>Format me!</span></div>
+</template>
+
+<script>
+export default {}
+</script>
+
+<style>
+.button { margin: 10px; }
+</style>
+`)
+  })
+
+  it('skips the style section if it doesn`t exist', () => {
+    const inputChunks = {
+      html: `<div><span>Format me!</span></div>
+`,
+      js: `export default {}
+`,
+    }
+
+    const result = processor(inputChunks)
+
+    expect(result.html).toBeUndefined()
+    expect(result.js).toBeUndefined()
+    expect(result.css).toBeUndefined()
+    expect(result.vue).toBe(`<template>
+  <div><span>Format me!</span></div>
+</template>
+
+<script>
+export default {}
+</script>
+`)
+  })
+
+  it('throws an error if no HTML chunk is provided', () => {
+    const inputChunks = {
+      js: `export default {}
+`,
+    }
+
+    expect(() => processor(inputChunks)).toThrowError('HTML')
+  })
+
+  it('throws an error if no HTML chunk is provided', () => {
+    const inputChunks = {
+      html: `<div><span>Format me!</span></div>
+`,
+    }
+
+    expect(() => processor(inputChunks)).toThrowError('JS')
+  })
+})