From 934f6ca7a22db33d98395c8013b740033a365f58 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Wed, 8 Apr 2020 21:59:54 -0400 Subject: [PATCH 1/2] Upgrade prettier to v2 The previous glob configured in the lint:prettier task (src/**/*) did not match the implementation files directly under src/, only files 1 level down from that (in src/__tests__/). Upgraded prettier to v2 in order to take advantage of the new "prettier --write ." support (https://github.com/prettier/prettier/issues/6085). Also changed to a blacklist strategy using .prettierignore rather than whitelist so that editors configured to run prettier on save only run on files we care about. --- .babelrc | 24 ++--- .prettierignore | 4 + example/index.html | 36 ++++---- example/index.js | 3 +- jest.config.js | 10 +-- package.json | 24 +++-- rollup.config.demo.js | 7 +- rollup.config.js | 7 +- .../react-sane-contenteditable.test.js | 7 +- src/react-sane-contenteditable.js | 87 +++++++++++-------- src/utils.js | 11 +-- yarn.lock | 7 +- 12 files changed, 119 insertions(+), 108 deletions(-) create mode 100644 .prettierignore diff --git a/.babelrc b/.babelrc index 2530918..2698d4f 100644 --- a/.babelrc +++ b/.babelrc @@ -13,29 +13,15 @@ ], "env": { "esm": { - "plugins": [ - ["@babel/transform-runtime"] - ], - "ignore": [ - "**/*.test.js", - "**/__tests__/**", - "**/__mocks__/**" - ] + "plugins": [["@babel/transform-runtime"]], + "ignore": ["**/*.test.js", "**/__tests__/**", "**/__mocks__/**"] }, "cjs": { - "plugins": [ - "transform-es2015-modules-commonjs" - ], - "ignore": [ - "**/*.test.js", - "**/__tests__/**", - "**/__mocks__/**" - ] + "plugins": ["transform-es2015-modules-commonjs"], + "ignore": ["**/*.test.js", "**/__tests__/**", "**/__mocks__/**"] }, "test": { - "plugins": [ - "transform-es2015-modules-commonjs" - ] + "plugins": ["transform-es2015-modules-commonjs"] } }, "plugins": [ diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..9b30b55 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +/coverage/ +/dist/ +/example/index.min.js +/lib/ diff --git a/example/index.html b/example/index.html index 3e9bf13..3fa7394 100644 --- a/example/index.html +++ b/example/index.html @@ -1,21 +1,23 @@ + + + Hello World + + + - - - Hello World - - - - - -
- - - + +
+ + diff --git a/example/index.js b/example/index.js index 63c48cf..9006906 100644 --- a/example/index.js +++ b/example/index.js @@ -42,7 +42,8 @@ class App extends Component {
           {this.state.title}
diff --git a/jest.config.js b/jest.config.js
index 793a72f..67a40fe 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -21,10 +21,10 @@ module.exports = {
   collectCoverage: true,
 
   // An array of glob patterns indicating a set of files for which coverage information should be collected
-  collectCoverageFrom: ["src/*"],
+  collectCoverageFrom: ['src/*'],
 
   // The directory where Jest should output its coverage files
-  coverageDirectory: "coverage",
+  coverageDirectory: 'coverage',
 
   // An array of regexp pattern strings used to skip coverage collection
   // coveragePathIgnorePatterns: [
@@ -118,13 +118,13 @@ module.exports = {
   // setupFiles: [],
 
   // The path to a module that runs some code to configure or set up the testing framework before each test
-  setupTestFrameworkScriptFile: "/jest.setup.js",
+  setupTestFrameworkScriptFile: '/jest.setup.js',
 
   // A list of paths to snapshot serializer modules Jest should use for snapshot testing
   // snapshotSerializers: [],
 
   // The test environment that will be used for testing
-  testEnvironment: "jest-environment-jsdom",
+  testEnvironment: 'jest-environment-jsdom',
 
   // Options that will be passed to the testEnvironment
   // testEnvironmentOptions: {},
@@ -153,7 +153,7 @@ module.exports = {
   // testRunner: "jasmine2",
 
   // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
-  testURL: "http://localhost/",
+  testURL: 'http://localhost/',
 
   // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
   // timers: "real",
diff --git a/package.json b/package.json
index b94bbc3..7805332 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,13 @@
   "name": "react-sane-contenteditable",
   "version": "1.6.1",
   "description": "React component with sane defaults to make any element contentEditable",
-  "keywords": ["content-editable", "contenteditable", "editable", "react", "react-component"],
+  "keywords": [
+    "content-editable",
+    "contenteditable",
+    "editable",
+    "react",
+    "react-component"
+  ],
   "homepage": "https://github.com/ashleyw/react-sane-contenteditable#readme",
   "bugs": {
     "url": "https://github.com/ashleyw/react-sane-contenteditable/issues"
@@ -13,8 +19,16 @@
   },
   "license": "MIT",
   "author": "Ashley Williams ",
-  "contributors": ["Nick Aspinall", "Raphael Silva Cavalcanti", "Jess Telford"],
-  "files": ["lib", "LICENSE", "README.md"],
+  "contributors": [
+    "Nick Aspinall",
+    "Raphael Silva Cavalcanti",
+    "Jess Telford"
+  ],
+  "files": [
+    "lib",
+    "LICENSE",
+    "README.md"
+  ],
   "main": "lib/cjs/react-sane-contenteditable.js",
   "module": "lib/esm/react-sane-contenteditable.js",
   "directories": {
@@ -30,7 +44,7 @@
     "dev": "yarn run demo -w",
     "dev:test": "jest --watch --verbose false",
     "lint": "yarn run lint:prettier",
-    "lint:prettier": "prettier --write src/**/*",
+    "lint:prettier": "prettier --write .",
     "prepublish": "yarn build",
     "test": "jest"
   },
@@ -62,7 +76,7 @@
     "husky": "1.0.0-rc.13",
     "jest": "^23.4.2",
     "jsdom": "^11.12.0",
-    "prettier": "1.14.2",
+    "prettier": "^2.0.4",
     "react": "^16.4.2",
     "react-dom": "^16.3.2",
     "rimraf": "^2.6.2",
diff --git a/rollup.config.demo.js b/rollup.config.demo.js
index ba2dea5..1fd1cd0 100644
--- a/rollup.config.demo.js
+++ b/rollup.config.demo.js
@@ -22,12 +22,7 @@ export default {
       include: common.plugins.commonJs.include,
       exclude: ['node_modules/process-es6/**'],
       namedExports: {
-        'node_modules/react/index.js': [
-          'Children',
-          'Component',
-          'PropTypes',
-          'createElement',
-        ],
+        'node_modules/react/index.js': ['Children', 'Component', 'PropTypes', 'createElement'],
         'node_modules/react-dom/index.js': ['render'],
       },
     }),
diff --git a/rollup.config.js b/rollup.config.js
index e205bbf..011ca6b 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -56,10 +56,7 @@ export default [
       format: 'esm',
       name: common.output.name,
     },
-    external: id => !id.startsWith('\0') && !id.startsWith('.') && !id.startsWith('/'),
-    plugins: [
-      babel(common.plugins.babel),
-      sizeSnapshot(),
-    ],
+    external: (id) => !id.startsWith('\0') && !id.startsWith('.') && !id.startsWith('/'),
+    plugins: [babel(common.plugins.babel), sizeSnapshot()],
   },
 ];
diff --git a/src/__tests__/react-sane-contenteditable.test.js b/src/__tests__/react-sane-contenteditable.test.js
index 3b08b88..1d29685 100644
--- a/src/__tests__/react-sane-contenteditable.test.js
+++ b/src/__tests__/react-sane-contenteditable.test.js
@@ -30,10 +30,7 @@ global.document.createRange = jest.fn(() => mockedRange);
 
 // Helpers
 const focusThenBlur = (wrapper, element = 'div') =>
-  wrapper
-    .find(element)
-    .simulate('focus')
-    .simulate('blur');
+  wrapper.find(element).simulate('focus').simulate('blur');
 
 // Styled components
 const Wrapper = styled.div``;
@@ -295,7 +292,7 @@ describe('Sanitisation', () => {
   it('calls sanitise prop when provided', () => {
     const content = 'foo';
     const nextContent = 'foo bar';
-    const sanitise = jest.fn(value => value);
+    const sanitise = jest.fn((value) => value);
     const wrapper = mount();
 
     wrapper.setProps({ content: nextContent, sanitise });
diff --git a/src/react-sane-contenteditable.js b/src/react-sane-contenteditable.js
index e9fa892..88538ed 100644
--- a/src/react-sane-contenteditable.js
+++ b/src/react-sane-contenteditable.js
@@ -67,23 +67,26 @@ class ContentEditable extends Component {
 
   componentDidUpdate(prevProps, prevState) {
     const { caretPosition, content, focus } = this.props;
-    const updateCaretPosition = prevProps.caretPosition !== caretPosition
-      || prevProps.focus !== focus;
+    const updateCaretPosition =
+      prevProps.caretPosition !== caretPosition || prevProps.focus !== focus;
     const updateContent = prevProps.content !== content;
 
     if (updateCaretPosition || updateContent) {
-      this.setState({
-        caretPosition: updateCaretPosition
-          ? this.getCaretPositionFromProps() : prevState.caretPosition,
-        value: updateContent
-          ? this.sanitiseValue(content) : prevState.value,
-      }, () => {
-        this.setCaretPosition();
-      });
+      this.setState(
+        {
+          caretPosition: updateCaretPosition
+            ? this.getCaretPositionFromProps()
+            : prevState.caretPosition,
+          value: updateContent ? this.sanitiseValue(content) : prevState.value,
+        },
+        () => {
+          this.setCaretPosition();
+        },
+      );
     }
   }
 
-  getRange () {
+  getRange() {
     return this.selection.rangeCount ? this.selection.getRangeAt(0) : document.createRange();
   }
 
@@ -127,7 +130,7 @@ class ContentEditable extends Component {
     const prefix = prevValue.slice(0, startOffset);
     const suffix = prevValue.slice(endOffset);
 
-    return [prefix, valueToInsert, suffix].join('')
+    return [prefix, valueToInsert, suffix].join('');
   };
 
   sanitiseValue(value, props = this.props) {
@@ -155,12 +158,16 @@ class ContentEditable extends Component {
         .replace(/\r|\n{3,}/g, '\n\n')
         // Remove leading & trailing whitespace
         // FIXME This causes an issue when setting caret position
-        .split('\n').map(line => line.trim()).join('\n');
+        .split('\n')
+        .map((line) => line.trim())
+        .join('\n');
     }
 
-    return nextValue
-      // Ensure maxLength not exceeded
-      .substr(0, maxLength);
+    return (
+      nextValue
+        // Ensure maxLength not exceeded
+        .substr(0, maxLength)
+    );
   }
 
   onBlur = (ev) => {
@@ -180,18 +187,21 @@ class ContentEditable extends Component {
       return;
     }
 
-    this.setState({
-      caretPosition: this.getCaret(),
-      value: this.sanitiseValue(innerText),
-    }, () => {
-      const { onChange } = this.props;
+    this.setState(
+      {
+        caretPosition: this.getCaret(),
+        value: this.sanitiseValue(innerText),
+      },
+      () => {
+        const { onChange } = this.props;
 
-      if (isFunction(onChange)) {
-        const { value } = this.state;
+        if (isFunction(onChange)) {
+          const { value } = this.state;
 
-        onChange(ev, value);
-      }
-    });
+          onChange(ev, value);
+        }
+      },
+    );
   };
 
   onKeyDown = (ev) => {
@@ -237,23 +247,26 @@ class ContentEditable extends Component {
     }
   };
 
-  onPaste = ev => {
+  onPaste = (ev) => {
     ev.preventDefault();
 
     const pastedValue = ev.clipboardData.getData('text');
     const value = this.insertAtCaret(this.ref.innerText, pastedValue);
     const { startOffset } = this.getRange();
 
-    this.setState({
-      caretPosition: this.getSafeCaretPosition(startOffset + pastedValue.length, value),
-      value: this.sanitiseValue(value),
-    }, () => {
-      const { onPaste } = this.props;
-
-      if (isFunction(onPaste)) {
-        onPaste(value);
-      }
-    });
+    this.setState(
+      {
+        caretPosition: this.getSafeCaretPosition(startOffset + pastedValue.length, value),
+        value: this.sanitiseValue(value),
+      },
+      () => {
+        const { onPaste } = this.props;
+
+        if (isFunction(onPaste)) {
+          onPaste(value);
+        }
+      },
+    );
   };
 
   setRef = (ref) => {
diff --git a/src/utils.js b/src/utils.js
index 2415bba..b0c3d33 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,7 +1,8 @@
-const reduceTargetKeys = (target, keys, predicate) =>
-  Object.keys(target).reduce(predicate, {});
+const reduceTargetKeys = (target, keys, predicate) => Object.keys(target).reduce(predicate, {});
 
-export const omit = (target = {}, keys = []) => reduceTargetKeys(target, keys, (acc, key) =>
-  keys.some(omitKey => omitKey === key) ? acc : { ...acc, [key]: target[key] });
+export const omit = (target = {}, keys = []) =>
+  reduceTargetKeys(target, keys, (acc, key) =>
+    keys.some((omitKey) => omitKey === key) ? acc : { ...acc, [key]: target[key] },
+  );
 
-export const isFunction = fn => Object.prototype.toString.call(fn) === '[object Function]';
+export const isFunction = (fn) => Object.prototype.toString.call(fn) === '[object Function]';
diff --git a/yarn.lock b/yarn.lock
index 69e976f..2199389 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4547,9 +4547,10 @@ preserve@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
 
-prettier@1.14.2:
-  version "1.14.2"
-  resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.2.tgz#0ac1c6e1a90baa22a62925f41963c841983282f9"
+prettier@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef"
+  integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w==
 
 pretty-format@^23.5.0:
   version "23.5.0"

From faf41dedd34bfd6ddd6dc8145709ed34bdad1fb0 Mon Sep 17 00:00:00 2001
From: Andrew Hutchings 
Date: Wed, 8 Apr 2020 22:06:35 -0400
Subject: [PATCH 2/2] Remove Node 8 from test matrix

Node 8 is no longer maintained, and Prettier dropped support for Node < 10 in v2
---
 .github/workflows/test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0aed07d..2cffead 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -11,7 +11,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        node: [8, 10, 12]
+        node: [10, 12]
 
     steps:
       - name: Clone repository