Repository: maizzle/framework (js)

Issue:
Support defining `build.templates.source` as a function
Would be useful in cases where you have to do some work before figuring out which paths to source templates from.

- [x] must return path(s) as `string` or `array`
  - [x] throw if otherwise
- [x] expose `page` object


Pull request description:
refactor template source
This PR: 

- adds support for defining `templates.source` as a function
- supports defining `templates.source` as either a string or an array

For example, you can now do something like this:

```js
module.exports = {
  build: {
    templates: {
      source: () => ['src/some/templates', 'src/other/templates'],
      // ...
    }
  }
}
```

Closes #560 

Patch:
diff --git a/src/generators/output/to-disk.js b/src/generators/output/to-disk.js
index 3674ffd..7ab8a06 100644
--- a/src/generators/output/to-disk.js
+++ b/src/generators/output/to-disk.js
@@ -31,13 +31,16 @@ module.exports = async (env, spinner, config) => {
     ? config.tailwind.compiled
     : await Tailwind.compile('@tailwind components; @tailwind utilities;', '', {}, config)
 
+  // Parse each template config object
   await asyncForEach(templatesConfig, async templateConfig => {
     const outputDir = get(templateConfig, 'destination.path', `build_${env}`)
 
     await fs.remove(outputDir)
 
+    const source = typeof templateConfig.source === 'function' ? templateConfig.source() : templateConfig.source
+
     await fs
-      .copy(templateConfig.source, outputDir)
+      .copy(source, outputDir)
       .then(async () => {
         const extensions = Array.isArray(templateConfig.filetypes)
           ? templateConfig.filetypes.join('|')


Test patch:
diff --git a/test/test-todisk.js b/test/test-todisk.js
index d4cc644..c1aaf48 100644
--- a/test/test-todisk.js
+++ b/test/test-todisk.js
@@ -416,3 +416,20 @@ test('throws if it cannot spin up local development server', async t => {
     await Maizzle.serve('local', {})
   }, {instanceOf: TypeError})
 })
+
+test('works with templates.source defined as function', async t => {
+  const {files} = await Maizzle.build('production', {
+    build: {
+      fail: 'silent',
+      templates: {
+        source: () => 'test/stubs/templates',
+        destination: {
+          path: t.context.folder
+        }
+      }
+    }
+  })
+
+  t.true(fs.pathExistsSync(t.context.folder))
+  t.is(files.length, 3)
+})