Skip to content

Commit

Permalink
feat(gatsby-plugin-typescript): Supports linting (#18721)
Browse files Browse the repository at this point in the history
Co-authored-by: GatsbyJS Bot <mathews.kyle+gatsbybot@gmail.com>
Co-authored-by: Ward Peeters <ward@coding-tech.com>
  • Loading branch information
3 people committed Mar 2, 2020
1 parent faec9c8 commit d28a0bd
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 4 deletions.
6 changes: 6 additions & 0 deletions packages/gatsby-plugin-typescript/README.md
Expand Up @@ -77,3 +77,9 @@ Visual Studio Code is very good in this regard.

In addition, you can see the instructions in [TypeScript-Babel-Starter](https://github.com/Microsoft/TypeScript-Babel-Starter)
for setting up a `type-check` task.

## ESLint

This plugin supports linting TSX with [typescript-eslint](https://typescript-eslint.io) using [Gatsby's default ESLint config](https://www.gatsbyjs.org/docs/eslint/). To enable linting TSX, install `typescript`.

`npm install typescript`
8 changes: 7 additions & 1 deletion packages/gatsby-plugin-typescript/package.json
Expand Up @@ -33,7 +33,13 @@
"license": "MIT",
"main": "index.js",
"peerDependencies": {
"gatsby": "^2.0.0"
"gatsby": "^2.0.0",
"typescript": "^3.2.1"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
},
"repository": {
"type": "git",
Expand Down
122 changes: 120 additions & 2 deletions packages/gatsby-plugin-typescript/src/__tests__/gatsby-node.js
Expand Up @@ -49,7 +49,22 @@ describe(`gatsby-plugin-typescript`, () => {
const actions = { setWebpackConfig: jest.fn() }
const jsLoader = {}
const loaders = { js: jest.fn(() => jsLoader) }
onCreateWebpackConfig({ actions, loaders })
const stage = `develop`
const eslintLoader = { loader: `eslint-loader` }
const webpackConfig = {
module: {
rules: [
{
enforce: `pre`,
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: [eslintLoader],
},
],
},
}
const getConfig = jest.fn(() => webpackConfig)
onCreateWebpackConfig({ actions, getConfig, loaders, stage })
expect(actions.setWebpackConfig).toHaveBeenCalledWith({
module: {
rules: [
Expand All @@ -60,13 +75,116 @@ describe(`gatsby-plugin-typescript`, () => {
],
},
})
expect(actions.setWebpackConfig).toHaveBeenCalledWith({
module: {
rules: [
{
enforce: `pre`,
test: /\.tsx?$/,
exclude: /(node_modules|bower_components)/,
use: [eslintLoader],
},
],
},
})
})

it(`does not set the webpack config if there isn't a js loader`, () => {
const actions = { setWebpackConfig: jest.fn() }
const loaders = { js: jest.fn() }
onCreateWebpackConfig({ actions, loaders })
const stage = `develop`
const getConfig = jest.fn()
onCreateWebpackConfig({ actions, getConfig, loaders, stage })
expect(actions.setWebpackConfig).not.toHaveBeenCalled()
})

it(`does not set the typescript-eslint webpack config if the built-in eslint-loader isn't set`, () => {
const actions = { setWebpackConfig: jest.fn() }
const jsLoader = {}
const loaders = {
js: jest.fn(() => jsLoader),
}
const stage = `develop`
const webpackConfig = {
module: {
rules: [
{
enforce: `pre`,
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: [],
},
],
},
}
const getConfig = jest.fn(() => webpackConfig)
onCreateWebpackConfig({ actions, getConfig, loaders, stage })
expect(actions.setWebpackConfig).toHaveBeenCalledWith({
module: {
rules: [
{
test: /\.tsx?$/,
use: jsLoader,
},
],
},
})
expect(actions.setWebpackConfig).not.toHaveBeenCalledWith({
module: {
rules: [
{
enforce: `pre`,
test: /\.tsx?$/,
exclude: /(node_modules|bower_components)/,
use: [],
},
],
},
})
})

it(`set the typescript-eslint webpack config only if in develop stage`, () => {
const actions = { setWebpackConfig: jest.fn() }
const jsLoader = {}
const loaders = { js: jest.fn(() => jsLoader) }
const stage = `build-html`
const eslintLoader = { loader: `eslint-loader` }
const webpackConfig = {
module: {
rules: [
{
enforce: `pre`,
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: [eslintLoader],
},
],
},
}
const getConfig = jest.fn(() => webpackConfig)
onCreateWebpackConfig({ actions, getConfig, loaders, stage })
expect(actions.setWebpackConfig).toHaveBeenCalledWith({
module: {
rules: [
{
test: /\.tsx?$/,
use: jsLoader,
},
],
},
})
expect(actions.setWebpackConfig).not.toHaveBeenCalledWith({
module: {
rules: [
{
enforce: `pre`,
test: /\.tsx?$/,
exclude: /(node_modules|bower_components)/,
use: [eslintLoader],
},
],
},
})
})
})
})
40 changes: 39 additions & 1 deletion packages/gatsby-plugin-typescript/src/gatsby-node.js
Expand Up @@ -16,7 +16,13 @@ function onCreateBabelConfig({ actions }, options) {
})
}

function onCreateWebpackConfig({ actions, loaders }) {
function onCreateWebpackConfig({
actions,
getConfig,
loaders,
stage,
reporter,
}) {
const jsLoader = loaders.js()

if (!jsLoader) {
Expand All @@ -33,6 +39,38 @@ function onCreateWebpackConfig({ actions, loaders }) {
],
},
})

if (stage === `develop`) {
let isTypescriptDepAvailable
try {
isTypescriptDepAvailable = require.resolve(`typescript`)
} catch (e) {
reporter.warn(
`"typescript" is not installed. Builtin ESLint won't be working on typescript files.`
)
}

if (isTypescriptDepAvailable) {
const builtInEslintRule = getConfig().module.rules.find(rule => {
if (rule.enforce === `pre`) {
return rule.use.some(use => /eslint-loader/.test(use.loader))
}
return false
})

if (builtInEslintRule) {
const typescriptEslintRule = {
...builtInEslintRule,
test: /\.tsx?$/,
}
actions.setWebpackConfig({
module: {
rules: [typescriptEslintRule],
},
})
}
}
}
}

exports.resolvableExtensions = resolvableExtensions
Expand Down

0 comments on commit d28a0bd

Please sign in to comment.