diff --git a/.eslintignore b/.eslintignore
index a99bd88c6..20efa3e5f 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,10 +1,14 @@
node_modules
coverage
spec/react_on_rails/dummy-for-generators
-spec/dummy
+spec/dummy/.yalc
+spec/dummy/public
+spec/dummy/vendor
+spec/dummy/tmp
+spec/dummy/app/assets/config/manifest.js
+spec/dummy/client/node_modules
+spec/dummy/client/app/components/HelloWorldReScript.res.js
node_package/lib/
-node_package/tests/node_modules
-node_package/webpack.config.js
**/node_modules/**
**/assets/webpack/**
**/public/webpack/**
diff --git a/.eslintrc b/.eslintrc
index 1d1df612b..cf2ae3191 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -41,14 +41,18 @@ rules:
object-curly-newline: 0
no-restricted-syntax: ["error", "SequenceExpression"]
# https://stackoverflow.com/a/59268871/5241481
- import/extensions: ['error', 'ignorePackages', {"js": 'never',"ts": "never"}]
+ import/extensions: ['error', 'ignorePackages', {"js": 'never', "jsx": 'never', "ts": "never", " ": "never"}]
# https://github.com/benmosher/eslint-plugin-import/issues/340
import/no-extraneous-dependencies: 0
+ react/forbid-prop-types: 0
+ jsx-a11y/anchor-is-valid: 0
+
settings:
import/core-modules:
- react-redux
import/resolver:
+ alias: [ ["Assets", "./spec/dummy/client/app/assets"] ]
node:
- extensions: [".js", ".ts", ".d.ts"]
+ extensions: [".js", ".jsx", ".ts", ".d.ts"]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d455aa93..f49274f4a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,10 @@ Please follow the recommendations outlined at [keepachangelog.com](http://keepac
### [Unreleased]
Changes since the last non-beta release.
+#### Fixed
+
+- Resolved 14.1.1 incompatibility with eslint & made sure that spec/dummy is linted by eslint. [PR 1693](https://github.com/shakacode/react_on_rails/pull/1693) by [judahmeek](https://github.com/judahmeek).
+
### [14.1.1] - 2025-01-15
#### Fixed
diff --git a/package.json b/package.json
index 166616196..b2156ebaf 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,7 @@
"name": "react-on-rails",
"version": "14.1.1",
"description": "react-on-rails JavaScript for react_on_rails Ruby gem",
+ "main": "node_package/lib/ReactOnRails.js",
"exports": {
".": {
"node": "./node_package/lib/ReactOnRails.node.js",
@@ -26,6 +27,7 @@
"eslint": "^7.32.0",
"eslint-config-prettier": "^7.0.0",
"eslint-config-shakacode": "^16.0.1",
+ "eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "^3.4.1",
@@ -42,8 +44,7 @@
"ts-jest": "^29.2.5",
"typescript": "^5.6.2"
},
- "dependencies": {
- },
+ "dependencies": {},
"peerDependencies": {
"react": ">= 16",
"react-dom": ">= 16"
diff --git a/spec/dummy/babel.config.js b/spec/dummy/babel.config.js
index 40e049a1e..6aa1d24be 100644
--- a/spec/dummy/babel.config.js
+++ b/spec/dummy/babel.config.js
@@ -1,5 +1,6 @@
-module.exports = function (api) {
- const defaultConfigFunc = require('shakapacker/package/babel/preset.js');
+const defaultConfigFunc = require('shakapacker/package/babel/preset');
+
+module.exports = function createBabelConfig(api) {
const resultConfig = defaultConfigFunc(api);
const isProductionEnv = api.env('production');
const isDevelopmentEnv = api.env('development');
diff --git a/spec/dummy/client/.eslintignore b/spec/dummy/client/.eslintignore
deleted file mode 100644
index 3c3629e64..000000000
--- a/spec/dummy/client/.eslintignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/spec/dummy/client/.eslintrc b/spec/dummy/client/.eslintrc
deleted file mode 100644
index 8ff607255..000000000
--- a/spec/dummy/client/.eslintrc
+++ /dev/null
@@ -1,12 +0,0 @@
----
-
-extends:
- - eslint-config-shakacode
- - prettier
- - prettier/react
-
-plugins:
- - prettier
-
-rules:
- react/forbid-prop-types: 0
diff --git a/spec/dummy/client/app/components/RouterLayout.jsx b/spec/dummy/client/app/components/RouterLayout.jsx
index d72e58bc9..13c3a122a 100644
--- a/spec/dummy/client/app/components/RouterLayout.jsx
+++ b/spec/dummy/client/app/components/RouterLayout.jsx
@@ -1,10 +1,9 @@
-import PropTypes from 'prop-types';
import React from 'react';
import { Link, Route, Switch } from 'react-router-dom';
import RouterFirstPage from './RouterFirstPage';
import RouterSecondPage from './RouterSecondPage';
-const RouterLayout = ({ children }) => (
+const RouterLayout = () => (
React Router is working!
@@ -29,8 +28,4 @@ const RouterLayout = ({ children }) => (
);
-RouterLayout.propTypes = {
- children: PropTypes.object,
-};
-
export default RouterLayout;
diff --git a/spec/dummy/client/app/packs/rescript-components.js b/spec/dummy/client/app/packs/rescript-components.js
index ae0384cb4..c1b243230 100644
--- a/spec/dummy/client/app/packs/rescript-components.js
+++ b/spec/dummy/client/app/packs/rescript-components.js
@@ -4,4 +4,4 @@
import HelloWorldReScript from '../components/HelloWorldReScript.res.js';
-export { HelloWorldReScript };
+export default HelloWorldReScript;
diff --git a/spec/dummy/client/app/packs/server-bundle.js b/spec/dummy/client/app/packs/server-bundle.js
index 517fe677e..f21eb77ec 100644
--- a/spec/dummy/client/app/packs/server-bundle.js
+++ b/spec/dummy/client/app/packs/server-bundle.js
@@ -1,7 +1,7 @@
-// import statement added by react_on_rails:generate_packs rake task
-import './../generated/server-bundle-generated.js';
// Shows the mapping from the exported object to the name used by the server rendering.
import ReactOnRails from 'react-on-rails';
+// import statement added by react_on_rails:generate_packs rake task
+import './../generated/server-bundle-generated';
// Example of server rendering with no React
import HelloString from '../non_react/HelloString';
diff --git a/spec/dummy/client/app/startup/ContextFunctionReturnInvalidJSX.jsx b/spec/dummy/client/app/startup/ContextFunctionReturnInvalidJSX.jsx
index 444082420..decd79449 100644
--- a/spec/dummy/client/app/startup/ContextFunctionReturnInvalidJSX.jsx
+++ b/spec/dummy/client/app/startup/ContextFunctionReturnInvalidJSX.jsx
@@ -1,5 +1,6 @@
// Example of incorrectly taking two params and returning JSX
-import React, { useState } from 'react';
+import React from 'react';
+import PropTypes from 'prop-types';
import css from '../components/HelloWorld.module.scss';
import RailsContext from '../components/RailsContext';
@@ -11,6 +12,12 @@ const ContextFunctionReturnInvalidJSX = (props, railsContext) => (
>
);
+ContextFunctionReturnInvalidJSX.propTypes = {
+ helloWorldData: PropTypes.shape({
+ name: PropTypes.string,
+ }).isRequired,
+}
+
/* Wrapping in a function would be correct in this case, since two params
are passed to the registered function:
diff --git a/spec/dummy/client/app/startup/HelloTurboStream.jsx b/spec/dummy/client/app/startup/HelloTurboStream.jsx
index 5125044f8..ca32d2c18 100644
--- a/spec/dummy/client/app/startup/HelloTurboStream.jsx
+++ b/spec/dummy/client/app/startup/HelloTurboStream.jsx
@@ -7,7 +7,7 @@ import css from '../components/HelloWorld.module.scss';
const HelloTurboStream = ({ helloTurboStreamData, railsContext }) => {
const [name, setName] = useState(helloTurboStreamData.name);
const nameDomRef = useRef(null);
-
+ // eslint-disable-next-line no-unused-vars
const handleChange = () => {
setName(nameDomRef.current.value);
};
diff --git a/spec/dummy/client/app/startup/HelloWorldHooks.jsx b/spec/dummy/client/app/startup/HelloWorldHooks.jsx
index 23a7414ac..da2aebbe6 100644
--- a/spec/dummy/client/app/startup/HelloWorldHooks.jsx
+++ b/spec/dummy/client/app/startup/HelloWorldHooks.jsx
@@ -1,5 +1,6 @@
// Super simple example of the simplest possible React component
import React, { useState } from 'react';
+import PropTypes from 'prop-types';
import css from '../components/HelloWorld.module.scss';
// TODO: make more like the HelloWorld.jsx
@@ -16,4 +17,10 @@ function HelloWorldHooks(props) {
);
}
+HelloWorldHooks.propTypes = {
+ helloWorldData: PropTypes.shape({
+ name: PropTypes.string,
+ }).isRequired,
+}
+
export default HelloWorldHooks;
diff --git a/spec/dummy/client/app/startup/HelloWorldHooksContext.jsx b/spec/dummy/client/app/startup/HelloWorldHooksContext.jsx
index 332c8a7cc..3fcb9f52b 100644
--- a/spec/dummy/client/app/startup/HelloWorldHooksContext.jsx
+++ b/spec/dummy/client/app/startup/HelloWorldHooksContext.jsx
@@ -1,12 +1,13 @@
// Example of using hooks when taking the props and railsContext
// Note, you need the call the hooks API within the react component stateless function
import React, { useState } from 'react';
+import PropTypes from 'prop-types';
import css from '../components/HelloWorld.module.scss';
import RailsContext from '../components/RailsContext';
-const HelloWorldHooksContext = (props, railsContext) => {
// You could pass props here or use the closure
- return () => {
+const HelloWorldHooksContext = (props, railsContext) => {
+ const Result = () => {
const [name, setName] = useState(props.helloWorldData.name);
return (
<>
@@ -20,6 +21,14 @@ const HelloWorldHooksContext = (props, railsContext) => {
>
);
};
+
+ Result.propTypes = {
+ helloWorldData: PropTypes.shape({
+ name: PropTypes.string,
+ }).isRequired,
+ };
+
+ return Result;
};
export default HelloWorldHooksContext;
diff --git a/spec/dummy/client/app/startup/HelloWorldProps.jsx b/spec/dummy/client/app/startup/HelloWorldProps.jsx
index ef126eb64..a776f9732 100644
--- a/spec/dummy/client/app/startup/HelloWorldProps.jsx
+++ b/spec/dummy/client/app/startup/HelloWorldProps.jsx
@@ -1,7 +1,8 @@
import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
import css from '../components/HelloWorld.module.scss';
-function HelloWorldHooks(props) {
+function HelloWorldProps(props) {
console.log(`HelloWorldProps modification target prop value: ${props.modificationTarget}`);
const [name, setName] = useState(props.helloWorldData.name);
@@ -24,4 +25,11 @@ function HelloWorldHooks(props) {
);
}
-export default HelloWorldHooks;
+HelloWorldProps.propTypes = {
+ helloWorldData: PropTypes.shape({
+ name: PropTypes.string,
+ }).isRequired,
+ modificationTarget: PropTypes.string.isRequired,
+}
+
+export default HelloWorldProps;
diff --git a/spec/dummy/client/app/startup/ImageExample.jsx b/spec/dummy/client/app/startup/ImageExample.jsx
index 2f6c1b9e3..72264a5f4 100644
--- a/spec/dummy/client/app/startup/ImageExample.jsx
+++ b/spec/dummy/client/app/startup/ImageExample.jsx
@@ -1,13 +1,15 @@
import React from 'react';
-import css from '../components/ImageExample/ImageExample.module.scss';
// Note the global alias for images
-import bowerLogo from '../components/ImageExample/bower.png';
-import blueprintIcon from '../components/ImageExample/blueprint_icon.svg';
import logo from 'Assets/images/256egghead.png';
import legoIcon from 'Assets/images/lego_icon.svg';
-const TestComponent = (_props) => (
+import css from '../components/ImageExample/ImageExample.module.scss';
+
+import bowerLogo from '../components/ImageExample/bower.png';
+import blueprintIcon from '../components/ImageExample/blueprint_icon.svg';
+
+const TestComponent = () => (
This is a test of CSS module color red.
diff --git a/spec/dummy/client/app/startup/RouterApp.server.jsx b/spec/dummy/client/app/startup/RouterApp.server.jsx
index 1d832e1b3..2995b42c2 100644
--- a/spec/dummy/client/app/startup/RouterApp.server.jsx
+++ b/spec/dummy/client/app/startup/RouterApp.server.jsx
@@ -3,10 +3,8 @@ import { StaticRouter } from 'react-router-dom';
import routes from '../routes/routes';
-export default (props, railsContext) => {
- return () => (
-
- {routes}
-
- );
-};
+export default (props, railsContext) => () => (
+
+ {routes}
+
+);
diff --git a/spec/dummy/config/webpack/commonWebpackConfig.js b/spec/dummy/config/webpack/commonWebpackConfig.js
index 02a1ec0af..ba523a96b 100644
--- a/spec/dummy/config/webpack/commonWebpackConfig.js
+++ b/spec/dummy/config/webpack/commonWebpackConfig.js
@@ -5,7 +5,7 @@ const baseClientWebpackConfig = generateWebpackConfig();
const webpack = require('webpack');
-const aliasConfig = require('./alias.js');
+const aliasConfig = require('./alias');
const commonOptions = {
resolve: {
@@ -23,7 +23,7 @@ const sassLoaderConfig = {
const scssConfigIndex = baseClientWebpackConfig.module.rules.findIndex((config) =>
'.scss'.match(config.test),
-);
+); // eslint-disable-next-line no-undef
baseClientWebpackConfig.module.rules[scssConfigIndex]?.use.push(sassLoaderConfig);
// add jquery
diff --git a/spec/dummy/config/webpack/serverWebpackConfig.js b/spec/dummy/config/webpack/serverWebpackConfig.js
index b64a616a6..aca7bf7a9 100644
--- a/spec/dummy/config/webpack/serverWebpackConfig.js
+++ b/spec/dummy/config/webpack/serverWebpackConfig.js
@@ -1,4 +1,4 @@
-const { merge, config } = require('shakapacker');
+const { config } = require('shakapacker');
const commonWebpackConfig = require('./commonWebpackConfig');
const webpack = require('webpack');
@@ -28,7 +28,7 @@ const configureServer = () => {
// replace file-loader with null-loader
serverWebpackConfig.module.rules.forEach((loader) => {
if (loader.use && loader.use.filter) {
- loader.use = loader.use.filter(
+ loader.use = loader.use.filter( // eslint-disable-line no-param-reassign
(item) => !(typeof item === 'string' && item.match(/mini-css-extract-plugin/)),
);
}
@@ -65,11 +65,11 @@ const configureServer = () => {
// Remove the mini-css-extract-plugin from the style loaders because
// the client build will handle exporting CSS.
// replace file-loader with null-loader
- const rules = serverWebpackConfig.module.rules;
+ const { rules } = serverWebpackConfig.module;
rules.forEach((rule) => {
if (Array.isArray(rule.use)) {
// remove the mini-css-extract-plugin and style-loader
- rule.use = rule.use.filter((item) => {
+ rule.use = rule.use.filter((item) => { // eslint-disable-line no-param-reassign
let testValue;
if (typeof item === 'string') {
testValue = item;
@@ -95,7 +95,7 @@ const configureServer = () => {
// Skip writing image files during SSR by setting emitFile to false
} else if (rule.use && (rule.use.loader === 'url-loader' || rule.use.loader === 'file-loader')) {
- rule.use.options.emitFile = false;
+ rule.use.options.emitFile = false; // eslint-disable-line no-param-reassign
}
});
diff --git a/spec/dummy/config/webpack/webpack.config.js b/spec/dummy/config/webpack/webpack.config.js
index 34ff0b4d6..d2a3fd8f9 100644
--- a/spec/dummy/config/webpack/webpack.config.js
+++ b/spec/dummy/config/webpack/webpack.config.js
@@ -7,10 +7,10 @@ const envSpecificConfig = () => {
const path = resolve(__dirname, `${env.nodeEnv}.js`);
if (existsSync(path)) {
console.log(`Loading ENV specific webpack configuration file ${path}`);
+ // eslint-disable-next-line import/no-dynamic-require, global-require
return require(path);
- } else {
- return generateWebpackConfig();
}
+ return generateWebpackConfig();
};
module.exports = envSpecificConfig();
diff --git a/yarn.lock b/yarn.lock
index bb59419ba..1ddef02c5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2992,6 +2992,11 @@ eslint-config-shakacode@^16.0.1:
babel-eslint "8.2.2"
eslint-config-airbnb "16.1.0"
+eslint-import-resolver-alias@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz#297062890e31e4d6651eb5eba9534e1f6e68fc97"
+ integrity sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==
+
eslint-import-resolver-node@^0.3.9:
version "0.3.9"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac"