Procházet zdrojové kódy

Support React 18 in @uppy/react (#3680)

* Support React 18
* Remove unit tests
* Create e2e tests

Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
Merlijn Vos před 3 roky
rodič
revize
d42badf995

+ 0 - 19
e2e/clients/dashboard-react/App.jsx

@@ -1,19 +0,0 @@
-/* eslint-disable react/react-in-jsx-scope */
-import Uppy from '@uppy/core'
-// eslint-disable-next-line no-unused-vars
-import React from 'react'
-import { Dashboard } from '@uppy/react'
-
-import '@uppy/core/dist/style.css'
-import '@uppy/dashboard/dist/style.css'
-
-export default App
-
-function App () {
-  // Ideally we test with the `useUppy` hook,
-  // as that's how it should be used.
-  // But that results in breaking the rules of hooks errors?
-  const uppy = new Uppy()
-
-  return <Dashboard uppy={uppy} />
-}

+ 0 - 5
e2e/clients/dashboard-react/index.jsx

@@ -1,5 +0,0 @@
-/* eslint-disable react/react-in-jsx-scope */
-import ReactDOM from 'react-dom'
-import App from './App.jsx'
-
-ReactDOM.render(<App />, document.getElementById('app'))

+ 1 - 1
e2e/clients/index.html

@@ -9,7 +9,7 @@
     <nav>
       <ul>
 				<li><a href="dashboard-compressor/index.html">dashboard-compressor</a></li>
-				<li><a href="dashboard-react/index.html">dashboard-react</a></li>
+				<li><a href="react/index.html">react</a></li>
         <li><a href="dashboard-transloadit/index.html">dashboard-transloadit</a></li>
         <li><a href="dashboard-tus/index.html">dashboard-tus</a></li>
 				<li><a href="dashboard-ui/index.html">dashboard-ui</a></li>

+ 32 - 0
e2e/clients/react/App.jsx

@@ -0,0 +1,32 @@
+/* eslint-disable react/react-in-jsx-scope */
+import Uppy from '@uppy/core'
+/* eslint-disable-next-line no-unused-vars */
+import React, { useState } from 'react'
+import { Dashboard, DashboardModal, DragDrop } from '@uppy/react'
+import ThumbnailGenerator from '@uppy/thumbnail-generator'
+
+import '@uppy/core/dist/style.css'
+import '@uppy/dashboard/dist/style.css'
+import '@uppy/drag-drop/dist/style.css'
+
+export default function App () {
+  const uppyDashboard = new Uppy({ id: 'dashboard' })
+  const uppyModal = new Uppy({ id: 'modal' })
+  const uppyDragDrop = new Uppy({ id: 'drag-drop' }).use(ThumbnailGenerator)
+  const [open, setOpen] = useState(false)
+
+  // drag-drop has no visual output so we test it via the uppy instance
+  window.uppy = uppyDragDrop
+
+  return (
+    <div style={{ maxWidth: '30em', margin: '5em 0', display: 'grid', gridGap: '2em' }}>
+      <button type="button" id="open" onClick={() => setOpen(!open)}>
+        Open Modal
+      </button>
+
+      <Dashboard id="dashboard" uppy={uppyDashboard} />
+      <DashboardModal id="modal" open={open} uppy={uppyModal} />
+      <DragDrop id="drag-drop" uppy={uppyDragDrop} />
+    </div>
+  )
+}

+ 0 - 0
e2e/clients/dashboard-react/index.html → e2e/clients/react/index.html


+ 8 - 0
e2e/clients/react/index.jsx

@@ -0,0 +1,8 @@
+/* eslint-disable react/react-in-jsx-scope */
+import { createRoot } from 'react-dom/client'
+import App from './App.jsx'
+
+const container = document.getElementById('app')
+const root = createRoot(container)
+
+root.render(<App />)

+ 0 - 13
e2e/cypress/integration/dashboard-react.spec.ts

@@ -1,13 +0,0 @@
-describe('dashboard-react', () => {
-  beforeEach(() => {
-    cy.visit('/dashboard-react')
-    cy.get('.uppy-Dashboard-input').as('file-input')
-  })
-
-  it('should render in React and show thumbnails', () => {
-    cy.get('@file-input').attachFile(['images/cat.jpg', 'images/traffic.jpg'])
-    cy.get('.uppy-Dashboard-Item-previewImg')
-      .should('have.length', 2)
-      .each((element) => expect(element).attr('src').to.include('blob:'))
-  })
-})

+ 33 - 0
e2e/cypress/integration/react.spec.ts

@@ -0,0 +1,33 @@
+describe('@uppy/react', () => {
+  beforeEach(() => {
+    cy.visit('/react')
+    cy.get('#dashboard .uppy-Dashboard-input').as('dashboard-input')
+    cy.get('#modal .uppy-Dashboard-input').as('modal-input')
+    cy.get('#drag-drop .uppy-DragDrop-input').as('dragdrop-input')
+  })
+
+  it('should render Dashboard in React and show thumbnails', () => {
+    cy.get('@dashboard-input').attachFile(['images/cat.jpg', 'images/traffic.jpg'])
+    cy.get('#dashboard .uppy-Dashboard-Item-previewImg')
+      .should('have.length', 2)
+      .each((element) => expect(element).attr('src').to.include('blob:'))
+  })
+
+  it('should render Modal in React and show thumbnails', () => {
+    cy.get('#open').click()
+    cy.get('@modal-input').attachFile(['images/cat.jpg', 'images/traffic.jpg'])
+    cy.get('#modal .uppy-Dashboard-Item-previewImg')
+      .should('have.length', 2)
+      .each((element) => expect(element).attr('src').to.include('blob:'))
+  })
+
+  it('should render Drag & Drop in React and create a thumbail with @uppy/thumbnail-generator', () => {
+    const spy = cy.spy()
+
+    cy.window().then(({ uppy }) => uppy.on('thumbnail:generated', spy))
+    cy.get('@dragdrop-input').attachFile(['images/cat.jpg', 'images/traffic.jpg'])
+    // not sure how I can accurately wait for the thumbnail
+    // eslint-disable-next-line cypress/no-unnecessary-waiting
+    cy.wait(1000).then(() => expect(spy).to.be.called)
+  })
+})

+ 2 - 2
e2e/package.json

@@ -50,8 +50,8 @@
     "deep-freeze": "^0.0.1",
     "parcel": "^2.0.1",
     "prompts": "^2.4.2",
-    "react": "^17.0.2",
-    "react-dom": "^17.0.2",
+    "react": "^18.1.0",
+    "react-dom": "^18.1.0",
     "typescript": "^4.5.4",
     "vue": "next"
   }

+ 1 - 1
packages/@uppy/react-native/package.json

@@ -29,7 +29,7 @@
     "expo-document-picker": ">=6.0.0",
     "expo-image-picker": ">=6.0.0",
     "expo-permissions": ">=6.0.0",
-    "react": "^16.0.0 || ^17.0.0",
+    "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
     "react-native": "*"
   }
 }

+ 3 - 6
packages/@uppy/react/package.json

@@ -31,14 +31,11 @@
     "prop-types": "^15.6.1"
   },
   "devDependencies": {
-    "@types/react": "^17.0.13",
-    "enzyme": "3.11.0",
-    "enzyme-adapter-react-16": "1.15.2",
-    "react": "^16.8.6",
-    "react-dom": "^16.8.6"
+    "@types/react": "^18.0.8",
+    "react": "^18.1.0"
   },
   "peerDependencies": {
     "@uppy/core": "workspace:^",
-    "react": "^16.0.0 || ^17.0.0"
+    "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
   }
 }

+ 0 - 53
packages/@uppy/react/src/Dashboard.test.js

@@ -1,53 +0,0 @@
-const h = require('react').createElement
-const { mount, configure } = require('enzyme')
-const ReactAdapter = require('enzyme-adapter-react-16')
-const Uppy = require('@uppy/core')
-
-beforeAll(() => {
-  configure({ adapter: new ReactAdapter() })
-})
-
-jest.mock('@uppy/dashboard', () => require('./__mocks__/DashboardPlugin'))
-
-const Dashboard = require('./Dashboard')
-
-describe('react <Dashboard />', () => {
-  it('can be mounted and unmounted', () => {
-    const oninstall = jest.fn()
-    const onuninstall = jest.fn()
-    const uppy = new Uppy()
-    const dash = mount((
-      <Dashboard
-        uppy={uppy}
-        onInstall={oninstall}
-        onUninstall={onuninstall}
-      />
-    ))
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).not.toHaveBeenCalled()
-
-    dash.unmount()
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).toHaveBeenCalled()
-  })
-
-  it('react on HTMLDivElement props update', async () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <Dashboard
-        uppy={uppy}
-        hidden
-      />
-    ))
-
-    expect(dash.getDOMNode().hidden).toBeTruthy()
-
-    dash.setProps({ hidden: false })
-
-    expect(dash.getDOMNode().hidden).toBeFalsy()
-
-    dash.unmount()
-  })
-})

+ 0 - 118
packages/@uppy/react/src/DashboardModal.test.js

@@ -1,118 +0,0 @@
-const h = require('react').createElement
-const { mount, configure } = require('enzyme')
-const ReactAdapter = require('enzyme-adapter-react-16')
-const Uppy = require('@uppy/core')
-
-jest.mock('@uppy/dashboard', () => require('./__mocks__/DashboardPlugin'))
-
-const DashboardModal = require('./DashboardModal')
-
-beforeAll(() => {
-  configure({ adapter: new ReactAdapter() })
-})
-
-beforeEach(() => {
-  Object.assign(require('@uppy/dashboard').prototype, {
-    openModal: jest.fn(),
-    closeModal: jest.fn(),
-  })
-})
-
-describe('react <DashboardModal />', () => {
-  it('can be mounted and unmounted', () => {
-    const oninstall = jest.fn()
-    const onuninstall = jest.fn()
-    const uppy = new Uppy()
-    const dash = mount((
-      <DashboardModal
-        uppy={uppy}
-        onInstall={oninstall}
-        onUninstall={onuninstall}
-      />
-    ))
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).not.toHaveBeenCalled()
-
-    dash.unmount()
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).toHaveBeenCalled()
-  })
-
-  it('opens the modal using the `open={true}` prop', () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <DashboardModal
-        uppy={uppy}
-        open={false}
-      />
-    ))
-    const { plugin } = dash.instance()
-
-    expect(plugin.openModal).not.toHaveBeenCalled()
-
-    dash.setProps({ open: true })
-
-    expect(plugin.openModal).toHaveBeenCalled()
-
-    dash.unmount()
-  })
-
-  it('closes the modal using the `open={false}` prop', () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <DashboardModal
-        uppy={uppy}
-        open
-      />
-    ))
-    const { plugin } = dash.instance()
-
-    expect(plugin.openModal).toHaveBeenCalled()
-    expect(plugin.closeModal).not.toHaveBeenCalled()
-
-    dash.setProps({ open: false })
-
-    expect(plugin.closeModal).toHaveBeenCalled()
-
-    dash.unmount()
-  })
-
-  it('react on HTMLDivElement props update', async () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <DashboardModal
-        uppy={uppy}
-        hidden
-      />
-    ))
-
-    expect(dash.getDOMNode().hidden).toBeTruthy()
-
-    dash.setProps({ hidden: false })
-
-    expect(dash.getDOMNode().hidden).toBeFalsy()
-
-    dash.unmount()
-  })
-
-  it('react on @uppy/dashboard props update', async () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <DashboardModal
-        uppy={uppy}
-        theme="dark"
-      />
-    ))
-
-    const { plugin } = dash.instance()
-
-    expect(plugin.opts.theme).toBe('dark')
-
-    dash.setProps({ theme: 'light' })
-    expect(plugin.opts.theme).toBe('light')
-
-    dash.unmount()
-  })
-})

+ 0 - 53
packages/@uppy/react/src/DragDrop.test.js

@@ -1,53 +0,0 @@
-const h = require('react').createElement
-const { mount, configure } = require('enzyme')
-const ReactAdapter = require('enzyme-adapter-react-16')
-const Uppy = require('@uppy/core')
-
-beforeAll(() => {
-  configure({ adapter: new ReactAdapter() })
-})
-
-jest.mock('@uppy/drag-drop', () => require('./__mocks__/DragDropPlugin'))
-
-const DragDrop = require('./DragDrop')
-
-describe('react <DragDrop />', () => {
-  it('can be mounted and unmounted', () => {
-    const oninstall = jest.fn()
-    const onuninstall = jest.fn()
-    const uppy = new Uppy()
-    const dash = mount((
-      <DragDrop
-        uppy={uppy}
-        onInstall={oninstall}
-        onUninstall={onuninstall}
-      />
-    ))
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).not.toHaveBeenCalled()
-
-    dash.unmount()
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).toHaveBeenCalled()
-  })
-
-  it('react on HTMLDivElement props update', async () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <DragDrop
-        uppy={uppy}
-        hidden
-      />
-    ))
-
-    expect(dash.getDOMNode().hidden).toBeTruthy()
-
-    dash.setProps({ hidden: false })
-
-    expect(dash.getDOMNode().hidden).toBeFalsy()
-
-    dash.unmount()
-  })
-})

+ 0 - 35
packages/@uppy/react/src/FileInput.test.js

@@ -1,35 +0,0 @@
-const h = require('react').createElement
-const { mount, configure } = require('enzyme')
-const ReactAdapter = require('enzyme-adapter-react-16')
-const Uppy = require('@uppy/core')
-
-beforeAll(() => {
-  configure({ adapter: new ReactAdapter() })
-})
-
-jest.mock('@uppy/file-input', () => require('./__mocks__/FileInputPlugin'))
-
-const FileInput = require('./FileInput')
-
-describe('react <FileInput />', () => {
-  it('can be mounted and unmounted', () => {
-    const oninstall = jest.fn()
-    const onuninstall = jest.fn()
-    const uppy = new Uppy()
-    const input = mount((
-      <FileInput
-        uppy={uppy}
-        onInstall={oninstall}
-        onUninstall={onuninstall}
-      />
-    ))
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).not.toHaveBeenCalled()
-
-    input.unmount()
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).toHaveBeenCalled()
-  })
-})

+ 0 - 55
packages/@uppy/react/src/ProgressBar.test.js

@@ -1,55 +0,0 @@
-const h = require('react').createElement
-const { mount, configure } = require('enzyme')
-const ReactAdapter = require('enzyme-adapter-react-16')
-const Uppy = require('@uppy/core')
-
-beforeAll(() => {
-  configure({ adapter: new ReactAdapter() })
-})
-
-jest.mock('@uppy/progress-bar', () => require('./__mocks__/ProgressBarPlugin'))
-
-const ProgressBar = require('./ProgressBar')
-
-describe('react <ProgressBar />', () => {
-  it('can be mounted and unmounted', () => {
-    const oninstall = jest.fn()
-    const onuninstall = jest.fn()
-    const uppy = new Uppy()
-    const dash = mount((
-      <ProgressBar
-        uppy={uppy}
-        onInstall={oninstall}
-        onUninstall={onuninstall}
-      />
-    ))
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).not.toHaveBeenCalled()
-
-    dash.unmount()
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).toHaveBeenCalled()
-  })
-
-  it('react on HTMLDivElement props update', async () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <ProgressBar
-        uppy={uppy}
-        onInstall={Function.prototype}
-        onUninstall={Function.prototype}
-        hidden
-      />
-    ))
-
-    expect(dash.getDOMNode().hidden).toBeTruthy()
-
-    dash.setProps({ hidden: false })
-
-    expect(dash.getDOMNode().hidden).toBeFalsy()
-
-    dash.unmount()
-  })
-})

+ 0 - 55
packages/@uppy/react/src/StatusBar.test.js

@@ -1,55 +0,0 @@
-const h = require('react').createElement
-const { mount, configure } = require('enzyme')
-const ReactAdapter = require('enzyme-adapter-react-16')
-const Uppy = require('@uppy/core')
-
-beforeAll(() => {
-  configure({ adapter: new ReactAdapter() })
-})
-
-jest.mock('@uppy/status-bar', () => require('./__mocks__/StatusBarPlugin'))
-
-const StatusBar = require('./StatusBar')
-
-describe('react <StatusBar />', () => {
-  it('can be mounted and unmounted', () => {
-    const oninstall = jest.fn()
-    const onuninstall = jest.fn()
-    const uppy = new Uppy()
-    const dash = mount((
-      <StatusBar
-        uppy={uppy}
-        onInstall={oninstall}
-        onUninstall={onuninstall}
-      />
-    ))
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).not.toHaveBeenCalled()
-
-    dash.unmount()
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).toHaveBeenCalled()
-  })
-
-  it('react on HTMLDivElement props update', async () => {
-    const uppy = new Uppy()
-    const dash = mount((
-      <StatusBar
-        uppy={uppy}
-        onInstall={Function.prototype}
-        onUninstall={Function.prototype}
-        hidden
-      />
-    ))
-
-    expect(dash.getDOMNode().hidden).toBeTruthy()
-
-    dash.setProps({ hidden: false })
-
-    expect(dash.getDOMNode().hidden).toBeFalsy()
-
-    dash.unmount()
-  })
-})

+ 0 - 18
packages/@uppy/react/src/__mocks__/DashboardPlugin.js

@@ -1,18 +0,0 @@
-const { UIPlugin } = require('@uppy/core')
-
-module.exports = class Dashboard extends UIPlugin {
-  constructor (uppy, opts) {
-    super(uppy, opts)
-
-    this.id = this.opts.id
-    this.type = 'orchestrator'
-  }
-
-  install () {
-    if (this.opts.onInstall) this.opts.onInstall()
-  }
-
-  uninstall () {
-    if (this.opts.onUninstall) this.opts.onUninstall()
-  }
-}

+ 0 - 18
packages/@uppy/react/src/__mocks__/DragDropPlugin.js

@@ -1,18 +0,0 @@
-const { UIPlugin } = require('@uppy/core')
-
-module.exports = class DragDrop extends UIPlugin {
-  constructor (uppy, opts) {
-    super(uppy, opts)
-
-    this.id = this.opts.id
-    this.type = 'acquirer'
-  }
-
-  install () {
-    if (this.opts.onInstall) this.opts.onInstall()
-  }
-
-  uninstall () {
-    if (this.opts.onUninstall) this.opts.onUninstall()
-  }
-}

+ 0 - 18
packages/@uppy/react/src/__mocks__/FileInputPlugin.js

@@ -1,18 +0,0 @@
-const { UIPlugin } = require('@uppy/core')
-
-module.exports = class FileInput extends UIPlugin {
-  constructor (uppy, opts) {
-    super(uppy, opts)
-
-    this.id = this.opts.id
-    this.type = 'acquirer'
-  }
-
-  install () {
-    if (this.opts.onInstall) this.opts.onInstall()
-  }
-
-  uninstall () {
-    if (this.opts.onUninstall) this.opts.onUninstall()
-  }
-}

+ 0 - 18
packages/@uppy/react/src/__mocks__/ProgressBarPlugin.js

@@ -1,18 +0,0 @@
-const { UIPlugin } = require('@uppy/core')
-
-module.exports = class ProgressBar extends UIPlugin {
-  constructor (uppy, opts) {
-    super(uppy, opts)
-
-    this.id = this.opts.id
-    this.type = 'progressindicator'
-  }
-
-  install () {
-    this.opts.onInstall()
-  }
-
-  uninstall () {
-    this.opts.onUninstall()
-  }
-}

+ 0 - 18
packages/@uppy/react/src/__mocks__/StatusBarPlugin.js

@@ -1,18 +0,0 @@
-const { UIPlugin } = require('@uppy/core')
-
-module.exports = class StatusBar extends UIPlugin {
-  constructor (uppy, opts) {
-    super(uppy, opts)
-
-    this.id = this.opts.id
-    this.type = 'progressindicator'
-  }
-
-  install () {
-    this.opts.onInstall()
-  }
-
-  uninstall () {
-    this.opts.onUninstall()
-  }
-}

+ 0 - 61
packages/@uppy/react/src/useUppy.test.js

@@ -1,61 +0,0 @@
-const h = require('react').createElement
-const { mount, configure } = require('enzyme')
-const ReactAdapter = require('enzyme-adapter-react-16')
-const Uppy = require('@uppy/core')
-
-beforeAll(() => {
-  configure({ adapter: new ReactAdapter() })
-})
-
-const useUppy = require('./useUppy')
-
-describe('useUppy()', () => {
-  it('is created and deleted according to component lifecycle', () => {
-    const oninstall = jest.fn()
-    const onuninstall = jest.fn()
-
-    function JustInstance () {
-      const uppy = useUppy(() => {
-        oninstall()
-        return new Uppy()
-          .on('cancel-all', onuninstall)
-      })
-
-      return <div x={uppy} />
-    }
-
-    const el = mount(<JustInstance />)
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).not.toHaveBeenCalled()
-
-    el.unmount()
-
-    expect(oninstall).toHaveBeenCalled()
-    expect(onuninstall).toHaveBeenCalled()
-  })
-
-  it('checks types', () => {
-    function NullUppy () {
-      const uppy = useUppy(() => null)
-
-      return <div x={uppy} />
-    }
-
-    expect(() => {
-      mount(<NullUppy />)
-    }).toThrow('factory function must return an Uppy instance')
-
-    function GarbageUppy () {
-      const uppy = useUppy(() => ({
-        garbage: 'lala',
-      }))
-
-      return <div x={uppy} />
-    }
-
-    expect(() => {
-      mount(<GarbageUppy />)
-    }).toThrow('factory function must return an Uppy instance')
-  })
-})

+ 37 - 295
yarn.lock

@@ -10023,7 +10023,7 @@ __metadata:
     expo-document-picker: ">=6.0.0"
     expo-image-picker: ">=6.0.0"
     expo-permissions: ">=6.0.0"
-    react: ^16.0.0 || ^17.0.0
+    react: ^16.0.0 || ^17.0.0 || ^18.0.0
     react-native: "*"
   languageName: unknown
   linkType: soft
@@ -10032,21 +10032,18 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "@uppy/react@workspace:packages/@uppy/react"
   dependencies:
-    "@types/react": ^17.0.13
+    "@types/react": ^18.0.8
     "@uppy/dashboard": "workspace:^"
     "@uppy/drag-drop": "workspace:^"
     "@uppy/file-input": "workspace:^"
     "@uppy/progress-bar": "workspace:^"
     "@uppy/status-bar": "workspace:^"
     "@uppy/utils": "workspace:^"
-    enzyme: 3.11.0
-    enzyme-adapter-react-16: 1.15.2
     prop-types: ^15.6.1
-    react: ^16.8.6
-    react-dom: ^16.8.6
+    react: ^18.1.0
   peerDependencies:
     "@uppy/core": "workspace:^"
-    react: ^16.0.0 || ^17.0.0
+    react: ^16.0.0 || ^17.0.0 || ^18.0.0
   languageName: unknown
   linkType: soft
 
@@ -11617,25 +11614,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"airbnb-prop-types@npm:^2.16.0":
-  version: 2.16.0
-  resolution: "airbnb-prop-types@npm:2.16.0"
-  dependencies:
-    array.prototype.find: ^2.1.1
-    function.prototype.name: ^1.1.2
-    is-regex: ^1.1.0
-    object-is: ^1.1.2
-    object.assign: ^4.1.0
-    object.entries: ^1.1.2
-    prop-types: ^15.7.2
-    prop-types-exact: ^1.2.0
-    react-is: ^16.13.1
-  peerDependencies:
-    react: ^0.14 || ^15.0.0 || ^16.0.0-alpha
-  checksum: 393a5988b99f122c4b935296a6b8c8cbd10345418d67d547cdbcd71d57636cb9abdf9d6556940f70d0b76c3f83448627376557a75b5faf570fb8d262ed4a472f
-  languageName: node
-  linkType: hard
-
 "ajax-request@npm:^1.2.0":
   version: 1.2.3
   resolution: "ajax-request@npm:1.2.3"
@@ -12388,31 +12366,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"array.prototype.filter@npm:^1.0.0":
-  version: 1.0.1
-  resolution: "array.prototype.filter@npm:1.0.1"
-  dependencies:
-    call-bind: ^1.0.2
-    define-properties: ^1.1.3
-    es-abstract: ^1.19.0
-    es-array-method-boxes-properly: ^1.0.0
-    is-string: ^1.0.7
-  checksum: 574b52dcebf2def7bedb05449b60e5e3819093fa77f88c3f87a9611361d2745c7aacde01cd3ed7accafd632ee1e0340b655dd26dc7c060429cb4566058e63134
-  languageName: node
-  linkType: hard
-
-"array.prototype.find@npm:^2.1.1":
-  version: 2.1.2
-  resolution: "array.prototype.find@npm:2.1.2"
-  dependencies:
-    call-bind: ^1.0.2
-    define-properties: ^1.1.3
-    es-abstract: ^1.19.0
-  checksum: fd3f56a9e075ede7bd1b4515b92b8a2f11e39dd612caf7ae8d097d21d293a6d680be2d7ac25a0a26f5dd44904ceb591630efde599ff95b76a8e29c4c299ed5a8
-  languageName: node
-  linkType: hard
-
-"array.prototype.flat@npm:^1.2.1, array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.2.5":
+"array.prototype.flat@npm:^1.2.1, array.prototype.flat@npm:^1.2.5":
   version: 1.2.5
   resolution: "array.prototype.flat@npm:1.2.5"
   dependencies:
@@ -14706,7 +14660,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"cheerio@npm:^1.0.0-rc.10, cheerio@npm:^1.0.0-rc.3":
+"cheerio@npm:^1.0.0-rc.10":
   version: 1.0.0-rc.10
   resolution: "cheerio@npm:1.0.0-rc.10"
   dependencies:
@@ -17430,13 +17384,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"discontinuous-range@npm:1.0.0":
-  version: 1.0.0
-  resolution: "discontinuous-range@npm:1.0.0"
-  checksum: 8ee88d7082445b6eadc7c03bebe6dc978f96760c45e9f65d16ca66174d9e086a9e3855ee16acf65625e1a07a846a17de674f02a5964a6aebe5963662baf8b5c8
-  languageName: node
-  linkType: hard
-
 "dlv@npm:^1.1.3":
   version: 1.1.3
   resolution: "dlv@npm:1.1.3"
@@ -17808,8 +17755,8 @@ __metadata:
     deep-freeze: ^0.0.1
     parcel: ^2.0.1
     prompts: ^2.4.2
-    react: ^17.0.2
-    react-dom: ^17.0.2
+    react: ^18.1.0
+    react-dom: ^18.1.0
     typescript: ^4.5.4
     vue: next
   languageName: unknown
@@ -18188,84 +18135,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"enzyme-adapter-react-16@npm:1.15.2":
-  version: 1.15.2
-  resolution: "enzyme-adapter-react-16@npm:1.15.2"
-  dependencies:
-    enzyme-adapter-utils: ^1.13.0
-    enzyme-shallow-equal: ^1.0.1
-    has: ^1.0.3
-    object.assign: ^4.1.0
-    object.values: ^1.1.1
-    prop-types: ^15.7.2
-    react-is: ^16.12.0
-    react-test-renderer: ^16.0.0-0
-    semver: ^5.7.0
-  peerDependencies:
-    enzyme: ^3.0.0
-    react: ^16.0.0-0
-    react-dom: ^16.0.0-0
-  checksum: a6e620b0b352dfdfd370e070687a7138cfd3ff92e339f83ef11ce3c10bf139b77f03982fea935e30226bc2ebc2f010fff9e9513ebb9c16a6630989b918c18b50
-  languageName: node
-  linkType: hard
-
-"enzyme-adapter-utils@npm:^1.13.0":
-  version: 1.14.0
-  resolution: "enzyme-adapter-utils@npm:1.14.0"
-  dependencies:
-    airbnb-prop-types: ^2.16.0
-    function.prototype.name: ^1.1.3
-    has: ^1.0.3
-    object.assign: ^4.1.2
-    object.fromentries: ^2.0.3
-    prop-types: ^15.7.2
-    semver: ^5.7.1
-  peerDependencies:
-    react: 0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0
-  checksum: a96a0a1bdf66417ff751e465c33733f58127b043013ec288429bc9113defa4f8ac23d806be4f3cf399cf23401cd3fdd88383ea146bc1d8f1e4258ecf35611c62
-  languageName: node
-  linkType: hard
-
-"enzyme-shallow-equal@npm:^1.0.1":
-  version: 1.0.4
-  resolution: "enzyme-shallow-equal@npm:1.0.4"
-  dependencies:
-    has: ^1.0.3
-    object-is: ^1.1.2
-  checksum: 54bbad0955683f09252568bfcb9d7e934a27c06634057db9e82b54c0d9f7a27b6160d77643177d973c133b87d404f284cc6aa0481c0a1c81cdff05b072e2bb49
-  languageName: node
-  linkType: hard
-
-"enzyme@npm:3.11.0":
-  version: 3.11.0
-  resolution: "enzyme@npm:3.11.0"
-  dependencies:
-    array.prototype.flat: ^1.2.3
-    cheerio: ^1.0.0-rc.3
-    enzyme-shallow-equal: ^1.0.1
-    function.prototype.name: ^1.1.2
-    has: ^1.0.3
-    html-element-map: ^1.2.0
-    is-boolean-object: ^1.0.1
-    is-callable: ^1.1.5
-    is-number-object: ^1.0.4
-    is-regex: ^1.0.5
-    is-string: ^1.0.5
-    is-subset: ^0.1.1
-    lodash.escape: ^4.0.1
-    lodash.isequal: ^4.5.0
-    object-inspect: ^1.7.0
-    object-is: ^1.0.2
-    object.assign: ^4.1.0
-    object.entries: ^1.1.1
-    object.values: ^1.1.1
-    raf: ^3.4.1
-    rst-selector-parser: ^2.2.3
-    string.prototype.trim: ^1.2.1
-  checksum: 69ae80049c3f405122b8e619f1cf8b04f32b3cc2b6134c29ed8c0f05e87a0b15080f1121096ec211954a710f4787300af9157078c863012de87eee16e98e64ea
-  languageName: node
-  linkType: hard
-
 "err-code@npm:^2.0.2":
   version: 2.0.3
   resolution: "err-code@npm:2.0.3"
@@ -21649,7 +21518,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"function.prototype.name@npm:^1.1.0, function.prototype.name@npm:^1.1.2, function.prototype.name@npm:^1.1.3":
+"function.prototype.name@npm:^1.1.0":
   version: 1.1.5
   resolution: "function.prototype.name@npm:1.1.5"
   dependencies:
@@ -23068,16 +22937,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"html-element-map@npm:^1.2.0":
-  version: 1.3.1
-  resolution: "html-element-map@npm:1.3.1"
-  dependencies:
-    array.prototype.filter: ^1.0.0
-    call-bind: ^1.0.2
-  checksum: 7408da008d37bfa76b597e298ae0ed530258065deb29fbd73d40f7cbd123b654d1022a7a8cfbe713e57d90c5bef844399f5c8a46cde7d55c91d305024c921d08
-  languageName: node
-  linkType: hard
-
 "html-encoding-sniffer@npm:^1.0.2":
   version: 1.0.2
   resolution: "html-encoding-sniffer@npm:1.0.2"
@@ -24299,7 +24158,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"is-boolean-object@npm:^1.0.1, is-boolean-object@npm:^1.1.0":
+"is-boolean-object@npm:^1.1.0":
   version: 1.1.2
   resolution: "is-boolean-object@npm:1.1.2"
   dependencies:
@@ -24323,7 +24182,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"is-callable@npm:^1.1.4, is-callable@npm:^1.1.5, is-callable@npm:^1.2.4":
+"is-callable@npm:^1.1.4, is-callable@npm:^1.2.4":
   version: 1.2.4
   resolution: "is-callable@npm:1.2.4"
   checksum: 1a28d57dc435797dae04b173b65d6d1e77d4f16276e9eff973f994eadcfdc30a017e6a597f092752a083c1103cceb56c91e3dadc6692fedb9898dfaba701575f
@@ -24838,7 +24697,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"is-regex@npm:^1.0.4, is-regex@npm:^1.0.5, is-regex@npm:^1.1.0, is-regex@npm:^1.1.2, is-regex@npm:^1.1.4":
+"is-regex@npm:^1.0.4, is-regex@npm:^1.1.2, is-regex@npm:^1.1.4":
   version: 1.1.4
   resolution: "is-regex@npm:1.1.4"
   dependencies:
@@ -24913,13 +24772,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"is-subset@npm:^0.1.1":
-  version: 0.1.1
-  resolution: "is-subset@npm:0.1.1"
-  checksum: 97b8d7852af165269b7495095691a6ce6cf20bdfa1f846f97b4560ee190069686107af4e277fbd93aa0845c4d5db704391460ff6e9014aeb73264ba87893df44
-  languageName: node
-  linkType: hard
-
 "is-supported-regexp-flag@npm:^1.0.0":
   version: 1.0.1
   resolution: "is-supported-regexp-flag@npm:1.0.1"
@@ -27449,20 +27301,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"lodash.escape@npm:^4.0.1":
-  version: 4.0.1
-  resolution: "lodash.escape@npm:4.0.1"
-  checksum: fcb54f457497256964d619d5cccbd80a961916fca60df3fe0fa3e7f052715c2944c0ed5aefb4f9e047d127d44aa2d55555f3350cb42c6549e9e293fb30b41e7f
-  languageName: node
-  linkType: hard
-
-"lodash.flattendeep@npm:^4.4.0":
-  version: 4.4.0
-  resolution: "lodash.flattendeep@npm:4.4.0"
-  checksum: 8521c919acac3d4bcf0aaf040c1ca9cb35d6c617e2d72e9b4d51c9a58b4366622cd6077441a18be626c3f7b28227502b3bf042903d447b056ee7e0b11d45c722
-  languageName: node
-  linkType: hard
-
 "lodash.frompairs@npm:^4.0.1":
   version: 4.0.1
   resolution: "lodash.frompairs@npm:4.0.1"
@@ -29680,13 +29518,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"moo@npm:^0.5.0":
-  version: 0.5.1
-  resolution: "moo@npm:0.5.1"
-  checksum: 2d8c013f1f9aad8e5c7a9d4a03dbb4eecd91b9fe5e9446fbc7561fd38d4d161c742434acff385722542fe7b360fce9c586da62442379e62e4158ad49c7e1a6b7
-  languageName: node
-  linkType: hard
-
 "morgan@npm:1.10.0, morgan@npm:^1.10.0, morgan@npm:^1.9.1, morgan@npm:~1.10.0":
   version: 1.10.0
   resolution: "morgan@npm:1.10.0"
@@ -29960,23 +29791,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"nearley@npm:^2.7.10":
-  version: 2.20.1
-  resolution: "nearley@npm:2.20.1"
-  dependencies:
-    commander: ^2.19.0
-    moo: ^0.5.0
-    railroad-diagrams: ^1.0.0
-    randexp: 0.4.6
-  bin:
-    nearley-railroad: bin/nearley-railroad.js
-    nearley-test: bin/nearley-test.js
-    nearley-unparse: bin/nearley-unparse.js
-    nearleyc: bin/nearleyc.js
-  checksum: 42c2c330c13c7991b48221c5df00f4352c2f8851636ae4d1f8ca3c8e193fc1b7668c78011d1cad88cca4c1c4dc087425420629c19cc286d7598ec15533aaef26
-  languageName: node
-  linkType: hard
-
 "needle@npm:^2.5.2":
   version: 2.9.1
   resolution: "needle@npm:2.9.1"
@@ -30893,7 +30707,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"object-inspect@npm:^1.11.0, object-inspect@npm:^1.7.0, object-inspect@npm:^1.9.0":
+"object-inspect@npm:^1.11.0, object-inspect@npm:^1.9.0":
   version: 1.11.1
   resolution: "object-inspect@npm:1.11.1"
   checksum: 98bc8e1e108b193cfb5d9bfb71b79f0e19d187aca4f9a3f28ea0e946c0011a74f9fc2ada83ecf2216b3e69fe6bf697fda8230ed84a6ca5680887e7bb73cf34ad
@@ -30907,7 +30721,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"object-is@npm:^1.0.1, object-is@npm:^1.0.2, object-is@npm:^1.1.2":
+"object-is@npm:^1.0.1":
   version: 1.1.5
   resolution: "object-is@npm:1.1.5"
   dependencies:
@@ -30945,7 +30759,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"object.entries@npm:^1.1.0, object.entries@npm:^1.1.1, object.entries@npm:^1.1.2, object.entries@npm:^1.1.5":
+"object.entries@npm:^1.1.0, object.entries@npm:^1.1.2, object.entries@npm:^1.1.5":
   version: 1.1.5
   resolution: "object.entries@npm:1.1.5"
   dependencies:
@@ -30956,7 +30770,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"object.fromentries@npm:^2.0.0 || ^1.0.0, object.fromentries@npm:^2.0.3, object.fromentries@npm:^2.0.5":
+"object.fromentries@npm:^2.0.0 || ^1.0.0, object.fromentries@npm:^2.0.5":
   version: 2.0.5
   resolution: "object.fromentries@npm:2.0.5"
   dependencies:
@@ -30997,7 +30811,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"object.values@npm:^1.1.0, object.values@npm:^1.1.1, object.values@npm:^1.1.5":
+"object.values@npm:^1.1.0, object.values@npm:^1.1.5":
   version: 1.1.5
   resolution: "object.values@npm:1.1.5"
   dependencies:
@@ -34531,17 +34345,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"prop-types-exact@npm:^1.2.0":
-  version: 1.2.0
-  resolution: "prop-types-exact@npm:1.2.0"
-  dependencies:
-    has: ^1.0.3
-    object.assign: ^4.1.0
-    reflect.ownkeys: ^0.2.0
-  checksum: 21676a16d5b2623c345ca938554faba7bf29c6ad589eac3f490eda2207bcfd8d25cb3dfda5e5f8e6805239aabd2c6943f7bfbe726a1de708bae2b7a01c03eead
-  languageName: node
-  linkType: hard
-
 "prop-types@npm:^15.0.0":
   version: 15.8.1
   resolution: "prop-types@npm:15.8.1"
@@ -34945,22 +34748,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"raf@npm:^3.4.1":
-  version: 3.4.1
-  resolution: "raf@npm:3.4.1"
-  dependencies:
-    performance-now: ^2.1.0
-  checksum: 50ba284e481c8185dbcf45fc4618ba3aec580bb50c9121385d5698cb6012fe516d2015b1df6dd407a7b7c58d44be8086108236affbce1861edd6b44637c8cd52
-  languageName: node
-  linkType: hard
-
-"railroad-diagrams@npm:^1.0.0":
-  version: 1.0.0
-  resolution: "railroad-diagrams@npm:1.0.0"
-  checksum: 9e312af352b5ed89c2118edc0c06cef2cc039681817f65266719606e4e91ff6ae5374c707cc9033fe29a82c2703edf3c63471664f97f0167c85daf6f93496319
-  languageName: node
-  linkType: hard
-
 "ramda@npm:^0.21.0":
   version: 0.21.0
   resolution: "ramda@npm:0.21.0"
@@ -34968,16 +34755,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"randexp@npm:0.4.6":
-  version: 0.4.6
-  resolution: "randexp@npm:0.4.6"
-  dependencies:
-    discontinuous-range: 1.0.0
-    ret: ~0.1.10
-  checksum: 3c0d440a3f89d6d36844aa4dd57b5cdb0cab938a41956a16da743d3a3578ab32538fc41c16cc0984b6938f2ae4cbc0216967e9829e52191f70e32690d8e3445d
-  languageName: node
-  linkType: hard
-
 "random-bytes@npm:~1.0.0":
   version: 1.0.0
   resolution: "random-bytes@npm:1.0.0"
@@ -35106,16 +34883,15 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"react-dom@npm:^17.0.2":
-  version: 17.0.2
-  resolution: "react-dom@npm:17.0.2"
+"react-dom@npm:^18.1.0":
+  version: 18.1.0
+  resolution: "react-dom@npm:18.1.0"
   dependencies:
     loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-    scheduler: ^0.20.2
+    scheduler: ^0.22.0
   peerDependencies:
-    react: 17.0.2
-  checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c
+    react: ^18.1.0
+  checksum: bb0d48eeb0b297c79c2a03978baa29f5b3ff7ba3d070b21e34c9af1a6e7fdf0ca8b8d73e41f9214d91ad40eeb6d1f3559f884cbbc338713374a51320637c23df
   languageName: node
   linkType: hard
 
@@ -35153,7 +34929,7 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.8.1, react-is@npm:^16.8.4, react-is@npm:^16.8.6":
+"react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.8.1, react-is@npm:^16.8.4":
   version: 16.13.1
   resolution: "react-is@npm:16.13.1"
   checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f
@@ -35233,20 +35009,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"react-test-renderer@npm:^16.0.0-0":
-  version: 16.14.0
-  resolution: "react-test-renderer@npm:16.14.0"
-  dependencies:
-    object-assign: ^4.1.1
-    prop-types: ^15.6.2
-    react-is: ^16.8.6
-    scheduler: ^0.19.1
-  peerDependencies:
-    react: ^16.14.0
-  checksum: 96eb8a2566e67ebd246ef6e1b36d8c8498c68ebfdb94ca8399c19b4e3b73368caf0ffbe44767593e3499f2f58b4b5e57ba0565a47628048d2ab01b23a422724e
-  languageName: node
-  linkType: hard
-
 "react-transform-hmr@npm:^1.0.4":
   version: 1.0.4
   resolution: "react-transform-hmr@npm:1.0.4"
@@ -35278,6 +35040,15 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
+"react@npm:^18.1.0":
+  version: 18.1.0
+  resolution: "react@npm:18.1.0"
+  dependencies:
+    loose-envify: ^1.1.0
+  checksum: 5bb296b561b43ef2220395da4faac86c14a087c8c80e1a7598a5740f01ee605c11eaf249985c1e2000971c4cd32ccb46d40f00479bbd9fb6b1c7cf857393b7d4
+  languageName: node
+  linkType: hard
+
 "read-cache@npm:^1.0.0":
   version: 1.0.0
   resolution: "read-cache@npm:1.0.0"
@@ -35553,13 +35324,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"reflect.ownkeys@npm:^0.2.0":
-  version: 0.2.0
-  resolution: "reflect.ownkeys@npm:0.2.0"
-  checksum: 9530b166569e547c2cf25ade3cdc39c662212feeccf3e0ed46e6d8abf92f5683c82d7857011cee6230bf648eb0b99b6b419a007012b8571dcd4bb4d818d3b88d
-  languageName: node
-  linkType: hard
-
 "regenerate-unicode-properties@npm:^10.0.1":
   version: 10.0.1
   resolution: "regenerate-unicode-properties@npm:10.0.1"
@@ -37014,16 +36778,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"rst-selector-parser@npm:^2.2.3":
-  version: 2.2.3
-  resolution: "rst-selector-parser@npm:2.2.3"
-  dependencies:
-    lodash.flattendeep: ^4.4.0
-    nearley: ^2.7.10
-  checksum: fbfb2f6a7d4c9b3e013ef555ac06e5dba444e0d37dc959b94c507b6c34093ef10fe98141338d9cac58e5ae0f9453a5ef7f85af3d5e6386b237c1b3552debe4a0
-  languageName: node
-  linkType: hard
-
 "rsvp@npm:^4.8.4":
   version: 4.8.5
   resolution: "rsvp@npm:4.8.5"
@@ -37336,13 +37090,12 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"scheduler@npm:^0.20.2":
-  version: 0.20.2
-  resolution: "scheduler@npm:0.20.2"
+"scheduler@npm:^0.22.0":
+  version: 0.22.0
+  resolution: "scheduler@npm:0.22.0"
   dependencies:
     loose-envify: ^1.1.0
-    object-assign: ^4.1.1
-  checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc
+  checksum: a8ef5cab769c020cd6382ad9ecc3f72dbde56a50a36639b3a42ad9c11f7724f03700bcad373044059b8067d4a6365154dc7c0ca8027ef20ff4900cf58a0fc2c5
   languageName: node
   linkType: hard
 
@@ -39105,17 +38858,6 @@ hexo-filter-github-emojis@arturi/hexo-filter-github-emojis:
   languageName: node
   linkType: hard
 
-"string.prototype.trim@npm:^1.2.1":
-  version: 1.2.5
-  resolution: "string.prototype.trim@npm:1.2.5"
-  dependencies:
-    call-bind: ^1.0.2
-    define-properties: ^1.1.3
-    es-abstract: ^1.19.1
-  checksum: d9f748ffca2a3ce722c421f7c2993b6490ec0cf19d9cb0904598c744e9367e54a3f13c7b99c8c0966c8a76484bd656a60281daa5d0534cc222cd72193fd63034
-  languageName: node
-  linkType: hard
-
 "string.prototype.trimend@npm:^1.0.4":
   version: 1.0.4
   resolution: "string.prototype.trimend@npm:1.0.4"