├── test ├── fixture │ ├── basic │ │ ├── _headers │ │ ├── _redirects │ │ ├── netlify.toml │ │ └── nuxt.config.js │ ├── warn │ │ ├── _headers │ │ └── nuxt.config.js │ ├── disable │ │ ├── _headers │ │ ├── _redirects │ │ ├── netlify.toml │ │ └── nuxt.config.js │ ├── programmatically │ │ ├── _headers │ │ ├── _redirects │ │ └── nuxt.config.js │ ├── programmatically-func │ │ ├── _headers │ │ ├── _redirects │ │ └── nuxt.config.js │ ├── forms-invalid │ │ ├── pages │ │ │ └── index.vue │ │ └── nuxt.config.js │ └── forms │ │ ├── pages │ │ └── index.vue │ │ └── nuxt.config.js ├── forms.test.ts ├── forms-invalid.test.ts ├── basic.test.ts ├── disable.test.ts ├── utils.ts ├── warn.test.ts ├── programmatically.test.ts └── programmatically-func.test.ts ├── renovate.json ├── .eslintignore ├── .eslintrc ├── jest.config.js ├── .gitignore ├── .editorconfig ├── tsconfig.json ├── .github └── workflows │ └── ci.yml ├── LICENSE ├── CHANGELOG.md ├── package.json ├── src └── module.ts └── README.md /test/fixture/basic/_headers: -------------------------------------------------------------------------------- 1 | foobar 2 | -------------------------------------------------------------------------------- /test/fixture/warn/_headers: -------------------------------------------------------------------------------- 1 | foobar 2 | -------------------------------------------------------------------------------- /test/fixture/basic/_redirects: -------------------------------------------------------------------------------- 1 | barfoo 2 | -------------------------------------------------------------------------------- /test/fixture/disable/_headers: -------------------------------------------------------------------------------- 1 | foobar 2 | -------------------------------------------------------------------------------- /test/fixture/disable/_redirects: -------------------------------------------------------------------------------- 1 | barfoo 2 | -------------------------------------------------------------------------------- /test/fixture/programmatically/_headers: -------------------------------------------------------------------------------- 1 | foobar 2 | -------------------------------------------------------------------------------- /test/fixture/programmatically/_redirects: -------------------------------------------------------------------------------- 1 | barfoo 2 | -------------------------------------------------------------------------------- /test/fixture/programmatically-func/_headers: -------------------------------------------------------------------------------- 1 | foobar 2 | -------------------------------------------------------------------------------- /test/fixture/programmatically-func/_redirects: -------------------------------------------------------------------------------- 1 | barfoo 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Common 2 | node_modules 3 | dist 4 | .nuxt 5 | coverage 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs/eslint-config-typescript" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /test/fixture/basic/netlify.toml: -------------------------------------------------------------------------------- 1 | [context.production] 2 | environment = { FOO = "bar" } 3 | -------------------------------------------------------------------------------- /test/fixture/disable/netlify.toml: -------------------------------------------------------------------------------- 1 | [context.production] 2 | environment = { FOO = "bar" } 3 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@nuxt/test-utils', 3 | collectCoverageFrom: ['src/**'] 4 | } 5 | -------------------------------------------------------------------------------- /test/fixture/forms-invalid/pages/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /test/fixture/forms/pages/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | sw.* 11 | .env 12 | -------------------------------------------------------------------------------- /test/fixture/warn/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../../src/module.ts' 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/fixture/basic/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../../src/module.ts' 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/fixture/forms/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../../src/module.ts' 5 | ], 6 | netlifyFiles: { 7 | detectForms: true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixture/disable/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../../src/module.ts' 5 | ], 6 | netlifyFiles: { 7 | copyExistingFiles: false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixture/forms-invalid/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../../src/module.ts' 5 | ], 6 | netlifyFiles: { 7 | detectForms: true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /test/fixture/programmatically/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../../src/module.ts' 5 | ], 6 | netlifyFiles: { 7 | netlifyToml: { 8 | build: { 9 | environment: { 10 | BAR: 'baz' 11 | } 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "resolveJsonModule": true, 7 | "strict": false, 8 | "types": [ 9 | "node", 10 | "jest" 11 | ] 12 | }, 13 | "exclude": [ 14 | "node_modules", 15 | "dist" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /test/fixture/programmatically-func/nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | rootDir: __dirname, 3 | buildModules: [ 4 | '../../../src/module.ts' 5 | ], 6 | netlifyFiles: { 7 | netlifyToml: () => { 8 | return { 9 | build: { 10 | environment: { 11 | BAR: 'baz' 12 | } 13 | } 14 | 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/forms.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs' 2 | import { getNuxt, setupTest } from '@nuxt/test-utils' 3 | import { resolvePaths } from './utils' 4 | 5 | describe('forms', () => { 6 | setupTest({ 7 | generate: true, 8 | fixture: 'fixture/forms' 9 | }) 10 | 11 | test('it generate _netlify-forms.html', () => { 12 | const { formsPath } = resolvePaths(getNuxt()) 13 | 14 | expect(existsSync(formsPath)).toBe(true) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/forms-invalid.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs' 2 | import { getNuxt, setupTest } from '@nuxt/test-utils' 3 | import { resolvePaths } from './utils' 4 | 5 | describe('forms invalid', () => { 6 | setupTest({ 7 | generate: true, 8 | fixture: 'fixture/forms-invalid' 9 | }) 10 | 11 | test('it doesn`t generate _netlify-forms.html', () => { 12 | const { formsPath } = resolvePaths(getNuxt()) 13 | 14 | expect(existsSync(formsPath)).toBe(false) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/basic.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs' 2 | import { getNuxt, setupTest } from '@nuxt/test-utils' 3 | import { resolvePaths } from './utils' 4 | 5 | describe('basic', () => { 6 | setupTest({ 7 | generate: true, 8 | fixture: 'fixture/basic' 9 | }) 10 | 11 | test('it copies netlify files', () => { 12 | const { headersPath, redirectsPath, tomlPath } = resolvePaths(getNuxt()) 13 | 14 | expect(existsSync(headersPath)).toBe(true) 15 | expect(existsSync(redirectsPath)).toBe(true) 16 | expect(existsSync(tomlPath)).toBe(true) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /test/disable.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs' 2 | import { getNuxt, setupTest } from '@nuxt/test-utils' 3 | import { resolvePaths } from './utils' 4 | 5 | describe('disable', () => { 6 | setupTest({ 7 | generate: true, 8 | fixture: 'fixture/disable' 9 | }) 10 | 11 | test('should not copies netlify files', () => { 12 | const { headersPath, redirectsPath, tomlPath } = resolvePaths(getNuxt()) 13 | 14 | expect(existsSync(headersPath)).toBe(false) 15 | expect(existsSync(redirectsPath)).toBe(false) 16 | expect(existsSync(tomlPath)).toBe(false) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /test/utils.ts: -------------------------------------------------------------------------------- 1 | import { join, resolve } from 'path' 2 | import { NuxtOptions } from '@nuxt/types' 3 | 4 | export const resolvePaths = (nuxt: { options: NuxtOptions }) => { 5 | const distBasePath = resolve(nuxt.options.rootDir, nuxt.options.generate.dir) 6 | const headersPath = join(distBasePath, '_headers') 7 | const redirectsPath = join(distBasePath, '_redirects') 8 | const tomlPath = join(distBasePath, 'netlify.toml') 9 | const formsPath = join(distBasePath, '_netlify-forms.html') 10 | 11 | return { 12 | headersPath, 13 | redirectsPath, 14 | tomlPath, 15 | formsPath 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/warn.test.ts: -------------------------------------------------------------------------------- 1 | import { setupTest } from '@nuxt/test-utils' 2 | 3 | const mockReporter = { 4 | warn: jest.fn() 5 | } 6 | 7 | jest.mock('consola', () => ({ 8 | info: jest.fn(), 9 | success: jest.fn(), 10 | debug: jest.fn(), 11 | warn: jest.fn(), 12 | withTag: jest.fn().mockImplementation(() => mockReporter) 13 | })) 14 | 15 | describe('warn', () => { 16 | setupTest({ 17 | generate: true, 18 | fixture: 'fixture/warn' 19 | }) 20 | 21 | test('should warn if not found the netlify files file', () => { 22 | expect(mockReporter.warn).toHaveBeenCalledWith(expect.stringMatching(/^No `(.*)` file found in `(.*)`.$/)) 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /test/programmatically.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync, readFileSync } from 'fs' 2 | import { getNuxt, setupTest } from '@nuxt/test-utils' 3 | import { resolvePaths } from './utils' 4 | 5 | describe('programmatically', () => { 6 | setupTest({ 7 | generate: true, 8 | fixture: 'fixture/programmatically' 9 | }) 10 | 11 | test('it has all files in generate folder', () => { 12 | const { headersPath, redirectsPath, tomlPath } = resolvePaths(getNuxt()) 13 | 14 | expect(existsSync(headersPath)).toBe(true) 15 | expect(existsSync(redirectsPath)).toBe(true) 16 | expect(existsSync(tomlPath)).toBe(true) 17 | }) 18 | 19 | test('it created netlify.toml correctly', () => { 20 | const { tomlPath } = resolvePaths(getNuxt()) 21 | const data = readFileSync(tomlPath, 'utf8') 22 | const dataArr = data.split(/\n/).map(str => str.trim()).filter(Boolean) 23 | 24 | expect(dataArr).toEqual(['[build.environment]', 'BAR = "baz"']) 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /test/programmatically-func.test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync, readFileSync } from 'fs' 2 | import { getNuxt, setupTest } from '@nuxt/test-utils' 3 | import { resolvePaths } from './utils' 4 | 5 | describe('programmatically-func', () => { 6 | setupTest({ 7 | generate: true, 8 | fixture: 'fixture/programmatically-func' 9 | }) 10 | 11 | test('it has all files in generate folder', () => { 12 | const { headersPath, redirectsPath, tomlPath } = resolvePaths(getNuxt()) 13 | 14 | expect(existsSync(headersPath)).toBe(true) 15 | expect(existsSync(redirectsPath)).toBe(true) 16 | expect(existsSync(tomlPath)).toBe(true) 17 | }) 18 | 19 | test('it created netlify.toml correctly', () => { 20 | const { tomlPath } = resolvePaths(getNuxt()) 21 | const data = readFileSync(tomlPath, 'utf8') 22 | const dataArr = data.split(/\n/).map(str => str.trim()).filter(Boolean) 23 | 24 | expect(dataArr).toEqual(['[build.environment]', 'BAR = "baz"']) 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | ci: 13 | runs-on: ${{ matrix.os }} 14 | 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, windows-latest] 18 | node: [12] 19 | 20 | steps: 21 | - uses: actions/setup-node@v2 22 | with: 23 | node-version: ${{ matrix.node }} 24 | 25 | - name: checkout 26 | uses: actions/checkout@master 27 | 28 | - name: cache node_modules 29 | uses: actions/cache@v2 30 | with: 31 | path: node_modules 32 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }} 33 | 34 | - name: Install dependencies 35 | if: steps.cache.outputs.cache-hit != 'true' 36 | run: yarn 37 | 38 | - name: Lint 39 | run: yarn lint 40 | 41 | - name: Test 42 | run: yarn test 43 | 44 | - name: Coverage 45 | uses: codecov/codecov-action@v1 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nuxt Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [1.2.0](https://github.com/nuxt-community/netlify-files-module/compare/v1.0.0...v1.2.0) (2020-05-28) 6 | 7 | 8 | ### Features 9 | 10 | * programmatic netlify.toml support & copying ([#11](https://github.com/nuxt-community/netlify-files-module/issues/11)) ([f9ab430](https://github.com/nuxt-community/netlify-files-module/commit/f9ab430222dcbd026218f6dbd73ea2a6869f335c)) 11 | 12 | ## [1.1.0](https://github.com/nuxt-community/netlify-files-module/compare/v1.0.0...v1.1.0) (2020-04-26) 13 | 14 | * Refactor the module based on `@nuxtjs/module-test-utils` 15 | 16 | 17 | # [1.0.0](https://github.com/nuxt-community/netlify-files-module/compare/v0.0.1...v1.0.0) (2019-07-25) 18 | 19 | 20 | 21 | # Changelog 22 | 23 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 24 | 25 | ### 0.0.1 (2019-07-25) 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxtjs/netlify-files", 3 | "version": "1.2.0", 4 | "description": "Nuxt module to create new _headers, _redirects and netlify.toml files for Netlify or to use existing ones", 5 | "repository": "nuxt-community/netlify-files-module", 6 | "license": "MIT", 7 | "contributors": [ 8 | "Alexander Lichter ", 9 | "Ricardo Gobbo de Souza " 10 | ], 11 | "main": "./dist/module.js", 12 | "types": "./dist/module.d.ts", 13 | "files": [ 14 | "dist" 15 | ], 16 | "scripts": { 17 | "build": "siroc build", 18 | "prepublishOnly": "yarn build", 19 | "lint": "eslint --ext .js,.ts,.vue .", 20 | "release": "yarn test && yarn build && standard-version && git push --follow-tags && npm publish", 21 | "test": "yarn lint && yarn jest" 22 | }, 23 | "dependencies": { 24 | "@iarna/toml": "^2.2.5", 25 | "consola": "^2.15.0", 26 | "defu": "^3.2.2", 27 | "node-html-parser": "^3.0.3" 28 | }, 29 | "devDependencies": { 30 | "@babel/preset-typescript": "latest", 31 | "@nuxt/test-utils": "latest", 32 | "@nuxt/types": "latest", 33 | "@nuxtjs/eslint-config-typescript": "latest", 34 | "@types/jest": "latest", 35 | "@types/node": "latest", 36 | "eslint": "latest", 37 | "jest": "latest", 38 | "nuxt": "latest", 39 | "siroc": "latest", 40 | "standard-version": "latest" 41 | }, 42 | "publishConfig": { 43 | "access": "public" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/module.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path' 2 | import { copyFileSync, existsSync, writeFileSync } from 'fs' 3 | import type { Module } from '@nuxt/types' 4 | import { parse, HTMLElement } from 'node-html-parser' 5 | import { stringify as tomlStringify } from '@iarna/toml' 6 | import consola from 'consola' 7 | import defu from 'defu' 8 | import { name, version } from '../package.json' 9 | 10 | const logger = consola.withTag('nuxt:netlify-files') 11 | 12 | export type NetlifyToml = object 13 | 14 | export interface ModuleOptions { 15 | copyExistingFiles?: boolean, 16 | detectForms?: boolean, 17 | existingFilesDirectory?: string, 18 | netlifyToml?: NetlifyToml | (() => NetlifyToml) 19 | } 20 | 21 | const CONFIG_KEY = 'netlifyFiles' 22 | const HEADERS_FILE_NAME = '_headers' 23 | const REDIRECTS_FILE_NAME = '_redirects' 24 | const TOML_FILE_NAME = 'netlify.toml' 25 | const FILE_NAMES = [HEADERS_FILE_NAME, REDIRECTS_FILE_NAME, TOML_FILE_NAME] 26 | 27 | const nuxtModule: Module = function (moduleOptions) { 28 | const DEFAULTS: ModuleOptions = { 29 | copyExistingFiles: true, 30 | detectForms: false, 31 | existingFilesDirectory: this.options.srcDir, 32 | netlifyToml: undefined 33 | } 34 | 35 | const options: ModuleOptions = defu( 36 | this.options['netlify-files'], 37 | this.options[CONFIG_KEY], 38 | moduleOptions, 39 | DEFAULTS 40 | ) 41 | 42 | const forms: HTMLElement[] = [] 43 | 44 | if (options.detectForms) { 45 | this.nuxt.hook('generate:page', function ({ html }) { 46 | forms.push(...parse(html).querySelectorAll('form').filter((form) => { 47 | return form.getAttribute('netlify') === '' || 48 | form.getAttribute('netlify') === 'true' || 49 | form.getAttribute('data-netlify') === '' || 50 | form.getAttribute('data-netlify') === 'true' 51 | })) 52 | }) 53 | } 54 | 55 | this.nuxt.hook('generate:done', async () => { 56 | // prevent netlify.toml from being copied when it has been generated programmatically 57 | const filesToCopy = options.netlifyToml ? FILE_NAMES.filter(file => file !== TOML_FILE_NAME) : FILE_NAMES 58 | 59 | await programmaticallyCreateToml.bind(this)(options) 60 | copyExistingNetlifyFiles.bind(this)(options, filesToCopy) 61 | generatePageWithForms.bind(this)(options, forms) 62 | }) 63 | } 64 | 65 | async function programmaticallyCreateToml ({ netlifyToml }: ModuleOptions) { 66 | if (!netlifyToml) { 67 | return 68 | } 69 | 70 | const tomlObject = typeof netlifyToml === 'function' ? await netlifyToml() : netlifyToml 71 | 72 | if (typeof tomlObject !== 'object') { 73 | throw new TypeError('`netlifyToml` must be an object, or a function that returns an object') 74 | } 75 | 76 | const toml = tomlStringify(tomlObject) 77 | const destination = resolve(this.options.rootDir, this.options.generate.dir, TOML_FILE_NAME) 78 | writeFileSync(destination, toml) 79 | } 80 | 81 | function copyExistingNetlifyFiles ({ existingFilesDirectory, copyExistingFiles }: ModuleOptions, filesToCopy: string[]) { 82 | if (!copyExistingFiles) { 83 | return 84 | } 85 | 86 | filesToCopy.forEach((name) => { 87 | const origin = resolve(existingFilesDirectory, name) 88 | const destination = resolve(this.options.rootDir, this.options.generate.dir, name) 89 | const isAvailable = existsSync(origin) 90 | 91 | if (!isAvailable) { 92 | logger.warn(`No \`${name}\` file found in \`${existingFilesDirectory}\`.`) 93 | return 94 | } 95 | 96 | copyFileSync(origin, destination) 97 | }) 98 | } 99 | 100 | function generatePageWithForms ({ detectForms }: ModuleOptions, forms: HTMLElement[]) { 101 | if (!detectForms) { 102 | return 103 | } 104 | 105 | const destination = resolve(this.options.rootDir, this.options.generate.dir, '_netlify-forms.html') 106 | const content = forms.map(form => form.toString()).join('').trim() 107 | 108 | if (content) { 109 | writeFileSync(destination, content) 110 | } 111 | } 112 | 113 | ;(nuxtModule as any).meta = { name, version } 114 | 115 | declare module '@nuxt/types' { 116 | interface NuxtConfig { [CONFIG_KEY]?: ModuleOptions } // Nuxt 2.14+ 117 | interface Configuration { [CONFIG_KEY]?: ModuleOptions } // Nuxt 2.9 - 2.13 118 | } 119 | 120 | export default nuxtModule 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @nuxtjs/netlify-files 2 | 3 | [![npm version][npm-version-src]][npm-version-href] 4 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 5 | [![Github Actions CI][github-actions-ci-src]][github-actions-ci-href] 6 | [![Codecov][codecov-src]][codecov-href] 7 | [![License][license-src]][license-href] 8 | 9 | > Nuxt 2 module to create new _headers, _redirects and netlify.toml files for Netlify or to use existing ones 10 | 11 | [📖 **Release Notes**](./CHANGELOG.md) 12 | 13 | ## Setup 14 | 15 | 1. Add `@nuxtjs/netlify-files` dependency to your project 16 | 17 | ```bash 18 | yarn add --dev @nuxtjs/netlify-files # or npm install --save-dev @nuxtjs/netlify-files 19 | ``` 20 | 21 | 2. Add `@nuxtjs/netlify-files` to the `buildModules` section of `nuxt.config.js` 22 | 23 | ```js 24 | export default { 25 | buildModules: [ 26 | // Simple usage 27 | '@nuxtjs/netlify-files', 28 | 29 | // With options 30 | ['@nuxtjs/netlify-files', { /* module options */ }] 31 | ] 32 | } 33 | ``` 34 | 35 | :warning: If you are using Nuxt **< v2.9** you have to install the module as a `dependency` (No `--dev` or `--save-dev` flags) and use `modules` section in `nuxt.config.js` instead of `buildModules`. 36 | 37 | ### Using top level options 38 | 39 | ```js 40 | export default { 41 | buildModules: [ 42 | '@nuxtjs/netlify-files' 43 | ], 44 | netlifyFiles: { 45 | /* module options */ 46 | } 47 | } 48 | ``` 49 | 50 | ## Options 51 | 52 | ### `copyExistingFiles` 53 | 54 | - Type: `Boolean` 55 | - Default: `true` 56 | 57 | Enable/disable copying of existing files. 58 | 59 | ### `detectForms` 60 | 61 | - Type: `Boolean` 62 | - Default: `false` 63 | 64 | Enable/disable forms detection netlify. See https://docs.netlify.com/forms/setup/ 65 | 66 | ### `existingFilesDirectory` 67 | 68 | - Type: `String` 69 | - Default: `srcDir` 70 | 71 | The directory where your _headers, _redirects and netlify.toml files that should be copied are located. 72 | 73 | ### `netlifyToml` 74 | 75 | - Type: `Object` or `Function` (must return `Object`) 76 | - Default: `undefined` 77 | 78 | Object to create a `netlify.toml` from. If set, `netlify.toml` will not be copied, but programmatically created instead. 79 | 80 | ## Usage 81 | 82 | ### Copying 83 | 84 | The module will look for `_headers`, `_redirects` and `netlify.toml` files and will copy them into the generate folder 85 | (default: `dist`) after static generation. If you have them directly in your project folder, you don't have to do anything else. In case the files are somewhere else, you can configure the directory (see below) 86 | 87 | ```js 88 | export default { 89 | netlifyFiles: { 90 | existingFilesDirectory: 'path/to/nuxt/directory', // The directory where your _headers, _redirects and netlify.toml files are located 91 | } 92 | } 93 | ``` 94 | 95 | ### Creating a new `netlify.toml` 96 | 97 | For `netlify.toml`, instead of just copying it, it is also possible to create a new one. This could be useful if certain configurations need to be set dynamically. 98 | Since with `netlify.toml` also redirects and headers can be set, using this option makes it possible to dynamically create those as well, making `_redirects` and `_headers` files redundant. 99 | 100 | Note that if `netlifyToml` is set, the module will create the new toml directly in the destination folder. It will ignore the netlify.toml (if it does exist) in the source folder. 101 | 102 | ```js 103 | export default { 104 | netlifyFiles: { 105 | netlifyToml: { 106 | build: { 107 | environment: { FOO: process.env.FOO } 108 | }, 109 | headers: [ 110 | { 111 | for: '/*', 112 | values: { 'X-XSS-Protection': '1; mode=block' } 113 | } 114 | ], 115 | redirects: [ 116 | { 117 | from: '/old', 118 | to: '/new', 119 | status: 302 120 | } 121 | ] 122 | } 123 | } 124 | } 125 | ``` 126 | 127 | 128 | ## License 129 | 130 | [MIT License](./LICENSE) 131 | 132 | Copyright (c) Nuxt Community 133 | 134 | 135 | [npm-version-src]: https://img.shields.io/npm/v/@nuxtjs/netlify-files/latest.svg 136 | [npm-version-href]: https://npmjs.com/package/@nuxtjs/netlify-files 137 | 138 | [npm-downloads-src]: https://img.shields.io/npm/dt/@nuxtjs/netlify-files.svg 139 | [npm-downloads-href]: https://npmjs.com/package/@nuxtjs/netlify-files 140 | 141 | [github-actions-ci-src]: https://github.com/nuxt-community/netlify-files-module/workflows/ci/badge.svg 142 | [github-actions-ci-href]: https://github.com/nuxt-community/netlify-files-module/actions?query=workflow%3Aci 143 | 144 | [codecov-src]: https://img.shields.io/codecov/c/github/nuxt-community/netlify-files-module.svg 145 | [codecov-href]: https://codecov.io/gh/nuxt-community/netlify-files-module 146 | 147 | [license-src]: https://img.shields.io/npm/l/@nuxtjs/netlify-files.svg 148 | [license-href]: https://npmjs.com/package/@nuxtjs/netlify-files 149 | --------------------------------------------------------------------------------