diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 94420cea3c3..a267014b3c8 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -31,6 +31,7 @@ const config = { 'prettier', 'react', 'tsdoc', + 'unicorn', ], ignorePatterns: [ '**/etc/*', @@ -112,6 +113,10 @@ const config = { 'no-unused-vars': 'off', 'no-useless-catch': 'warn', 'no-async-promise-executor': 'warn', + 'unicorn/prefer-string-slice': 'error', + 'unicorn/prefer-node-protocol': 'error', + 'unicorn/prefer-keyboard-event-key': 'error', + 'unicorn/custom-error-definition': 'error', }, settings: { 'import/extensions': extensions, diff --git a/package.json b/package.json index fb4d04ceda0..1d2459b3b61 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-simple-import-sort": "^12.0.0", "eslint-plugin-tsdoc": "^0.2.17", + "eslint-plugin-unicorn": "^52.0.0", "eslint-plugin-unused-imports": "^3.1.0", "execa": "^2.0.0", "glob": "^7.2.0", diff --git a/packages/@sanity/block-tools/src/HtmlDeserializer/helpers.ts b/packages/@sanity/block-tools/src/HtmlDeserializer/helpers.ts index 21e6ca76cc3..b026156c033 100644 --- a/packages/@sanity/block-tools/src/HtmlDeserializer/helpers.ts +++ b/packages/@sanity/block-tools/src/HtmlDeserializer/helpers.ts @@ -161,18 +161,18 @@ export function trimWhitespace(blocks: TypedObject[]): TypedObject[] { child.text = child.text.replace(/[^\S\n]+$/g, '') } if ( - /\s/.test(child.text.substring(child.text.length - 1)) && + /\s/.test(child.text.slice(Math.max(0, child.text.length - 1))) && nextChild && isMinimalSpan(nextChild) && - /\s/.test(nextChild.text.substring(0, 1)) + /\s/.test(nextChild.text.slice(0, 1)) ) { child.text = child.text.replace(/[^\S\n]+$/g, '') } if ( - /\s/.test(child.text.substring(0, 1)) && + /\s/.test(child.text.slice(0, 1)) && prevChild && isMinimalSpan(prevChild) && - /\s/.test(prevChild.text.substring(prevChild.text.length - 1)) + /\s/.test(prevChild.text.slice(Math.max(0, prevChild.text.length - 1))) ) { child.text = child.text.replace(/^[^\S\n]+/g, '') } diff --git a/packages/@sanity/block-tools/src/util/randomKey.ts b/packages/@sanity/block-tools/src/util/randomKey.ts index 2011207fe12..68f754403f0 100644 --- a/packages/@sanity/block-tools/src/util/randomKey.ts +++ b/packages/@sanity/block-tools/src/util/randomKey.ts @@ -9,7 +9,7 @@ function whatwgRNG(length = 16) { const byteToHex: string[] = [] for (let i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substring(1) + byteToHex[i] = (i + 0x100).toString(16).slice(1) } /** diff --git a/packages/@sanity/block-tools/test/tests/HtmlDeserializer/index.test.ts b/packages/@sanity/block-tools/test/tests/HtmlDeserializer/index.test.ts index 8c31175bdd9..bacd549e2ca 100644 --- a/packages/@sanity/block-tools/test/tests/HtmlDeserializer/index.test.ts +++ b/packages/@sanity/block-tools/test/tests/HtmlDeserializer/index.test.ts @@ -1,8 +1,8 @@ -import * as fs from 'node:fs' -import * as path from 'node:path' +import assert from 'node:assert' +import fs from 'node:fs' +import path from 'node:path' import {describe, it} from '@jest/globals' -import * as assert from 'assert' import {JSDOM} from 'jsdom' import * as blockTools from '../../../src' diff --git a/packages/@sanity/block-tools/test/tests/util/normalizeBlock.test.ts b/packages/@sanity/block-tools/test/tests/util/normalizeBlock.test.ts index 6193cd713bd..030624b1c5e 100644 --- a/packages/@sanity/block-tools/test/tests/util/normalizeBlock.test.ts +++ b/packages/@sanity/block-tools/test/tests/util/normalizeBlock.test.ts @@ -1,5 +1,6 @@ +import assert from 'node:assert' + import {describe, it} from '@jest/globals' -import * as assert from 'assert' import {normalizeBlock} from '../../../src/util/normalizeBlock' diff --git a/packages/@sanity/cli/codemods/partsTypeDirective.js b/packages/@sanity/cli/codemods/partsTypeDirective.js index 4d8d8b1cd69..609f998bb05 100644 --- a/packages/@sanity/cli/codemods/partsTypeDirective.js +++ b/packages/@sanity/cli/codemods/partsTypeDirective.js @@ -1,4 +1,4 @@ -const path = require('path') +const path = require('node:path') partsTypeDirective.parser = 'tsx' module.exports = partsTypeDirective diff --git a/packages/@sanity/cli/codemods/reactIconsV3.js b/packages/@sanity/cli/codemods/reactIconsV3.js index d77126e6ebc..8e1c328c2ab 100644 --- a/packages/@sanity/cli/codemods/reactIconsV3.js +++ b/packages/@sanity/cli/codemods/reactIconsV3.js @@ -82,7 +82,7 @@ function replace(input, re, value) { function pascalCaseTransform(input) { const firstChar = input.charAt(0) - const lowerChars = input.substr(1).toLowerCase() + const lowerChars = input.slice(1).toLowerCase() return `${firstChar.toUpperCase()}${lowerChars}` } diff --git a/packages/@sanity/cli/test/shared/environment.ts b/packages/@sanity/cli/test/shared/environment.ts index 289b44efdf6..1b6cb4b41fd 100644 --- a/packages/@sanity/cli/test/shared/environment.ts +++ b/packages/@sanity/cli/test/shared/environment.ts @@ -195,6 +195,7 @@ class ExecError extends Error { stderr: string constructor(message: string, code: number, stdout: string, stderr: string) { super(message) + this.name = 'ExecError' this.code = code this.stdout = stdout this.stderr = stderr diff --git a/packages/@sanity/migrate/src/fetch-utils/fetchStream.ts b/packages/@sanity/migrate/src/fetch-utils/fetchStream.ts index bb519e4365b..d0d8ecf421b 100644 --- a/packages/@sanity/migrate/src/fetch-utils/fetchStream.ts +++ b/packages/@sanity/migrate/src/fetch-utils/fetchStream.ts @@ -9,6 +9,7 @@ export class HTTPError extends Error { constructor(statusCode: number, message: string) { super(message) + this.name = 'HTTPError' this.statusCode = statusCode } } diff --git a/packages/@sanity/migrate/src/it-utils/split.ts b/packages/@sanity/migrate/src/it-utils/split.ts index 24dbf8d71d9..bbe538d3ce7 100644 --- a/packages/@sanity/migrate/src/it-utils/split.ts +++ b/packages/@sanity/migrate/src/it-utils/split.ts @@ -7,12 +7,12 @@ export async function* split( buf += chunk if (buf.includes(delimiter)) { const lastIndex = buf.lastIndexOf(delimiter) - const parts = buf.substring(0, lastIndex).split(delimiter) + const parts = buf.slice(0, Math.max(0, lastIndex)).split(delimiter) for (const part of parts) { yield part } - buf = buf.substring(lastIndex + delimiter.length) + buf = buf.slice(Math.max(0, lastIndex + delimiter.length)) } } yield buf diff --git a/packages/@sanity/portable-text-editor/e2e-tests/setup/collaborative.jest.env.ts b/packages/@sanity/portable-text-editor/e2e-tests/setup/collaborative.jest.env.ts index 829c841a7b8..4ebccc2c981 100644 --- a/packages/@sanity/portable-text-editor/e2e-tests/setup/collaborative.jest.env.ts +++ b/packages/@sanity/portable-text-editor/e2e-tests/setup/collaborative.jest.env.ts @@ -89,7 +89,7 @@ export default class CollaborationEnvironment extends NodeEnvironment { } // This will identify this test throughout the web environment - const testId = (Math.random() + 1).toString(36).substring(7) + const testId = (Math.random() + 1).toString(36).slice(7) // Hook up page console and npm debug in the PTE if (DEBUG) { @@ -101,11 +101,11 @@ export default class CollaborationEnvironment extends NodeEnvironment { }, DEBUG) this._pageA.on('console', (message) => // eslint-disable-next-line no-console - console.log(`A:${message.type().substring(0, 3).toUpperCase()} ${message.text()}`), + console.log(`A:${message.type().slice(0, 3).toUpperCase()} ${message.text()}`), ) this._pageB.on('console', (message) => // eslint-disable-next-line no-console - console.log(`B:${message.type().substring(0, 3).toUpperCase()} ${message.text()}`), + console.log(`B:${message.type().slice(0, 3).toUpperCase()} ${message.text()}`), ) } this._pageA.on('pageerror', (err) => { @@ -120,7 +120,7 @@ export default class CollaborationEnvironment extends NodeEnvironment { this.global.setDocumentValue = async ( value: PortableTextBlock[] | undefined, ): Promise => { - const revId = (Math.random() + 1).toString(36).substring(7) + const revId = (Math.random() + 1).toString(36).slice(7) ipc.of.socketServer.emit('payload', JSON.stringify({type: 'value', value, testId, revId})) await this._pageA?.waitForSelector(`code[data-rev-id="${revId}"]`, { timeout: REVISION_TIMEOUT_MS, diff --git a/packages/@sanity/portable-text-editor/e2e-tests/web-server/app.tsx b/packages/@sanity/portable-text-editor/e2e-tests/web-server/app.tsx index 1c1c8e4df84..edde3e1083a 100644 --- a/packages/@sanity/portable-text-editor/e2e-tests/web-server/app.tsx +++ b/packages/@sanity/portable-text-editor/e2e-tests/web-server/app.tsx @@ -23,7 +23,7 @@ export function App() { const {editorId, testId} = useMemo(() => { const params = new URLSearchParams(document.location.search) return { - editorId: params.get('editorId') || (Math.random() + 1).toString(36).substring(7), + editorId: params.get('editorId') || (Math.random() + 1).toString(36).slice(7), testId: params.get('testId') || 'noTestIdGiven', } }, []) diff --git a/packages/@sanity/portable-text-editor/e2e-tests/web-server/components/Editor.tsx b/packages/@sanity/portable-text-editor/e2e-tests/web-server/components/Editor.tsx index 57542b1d898..4f9e50a222a 100644 --- a/packages/@sanity/portable-text-editor/e2e-tests/web-server/components/Editor.tsx +++ b/packages/@sanity/portable-text-editor/e2e-tests/web-server/components/Editor.tsx @@ -71,7 +71,7 @@ export const Editor = ({ const [selectionValue, setSelectionValue] = useState(selection) const selectionString = useMemo(() => JSON.stringify(selectionValue), [selectionValue]) const editor = useRef(null) - const keyGenFn = useMemo(() => createKeyGenerator(editorId.substring(0, 1)), [editorId]) + const keyGenFn = useMemo(() => createKeyGenerator(editorId.slice(0, 1)), [editorId]) const [isOffline, setIsOffline] = useState(!window.navigator.onLine) const [readOnly, setReadOnly] = useState(false) diff --git a/packages/@sanity/portable-text-editor/e2e-tests/ws-server/index.ts b/packages/@sanity/portable-text-editor/e2e-tests/ws-server/index.ts index d699954a059..2d68f1910e9 100644 --- a/packages/@sanity/portable-text-editor/e2e-tests/ws-server/index.ts +++ b/packages/@sanity/portable-text-editor/e2e-tests/ws-server/index.ts @@ -81,7 +81,7 @@ app.ws('/', (s, req) => { } if (mutatedValue !== null) { // Assign revId and store value - const revId = (Math.random() + 1).toString(36).substring(7) + const revId = (Math.random() + 1).toString(36).slice(7) valueMap[testId] = mutatedValue revisionMap[testId] = revId // Broadcast to all diff --git a/packages/@sanity/schema/example/test.js b/packages/@sanity/schema/example/test.js index e9ecf2e635d..71eab9b2f7d 100644 --- a/packages/@sanity/schema/example/test.js +++ b/packages/@sanity/schema/example/test.js @@ -1,4 +1,4 @@ -import assert from 'assert' +import assert from 'node:assert' import {Schema} from '../src/legacy/Schema' import schemaDef from './schema-def' diff --git a/packages/@sanity/util/src/content/randomKey.ts b/packages/@sanity/util/src/content/randomKey.ts index 506e24d40ee..3f318954bb8 100644 --- a/packages/@sanity/util/src/content/randomKey.ts +++ b/packages/@sanity/util/src/content/randomKey.ts @@ -9,7 +9,7 @@ const getByteHexTable = (() => { table = [] for (let i = 0; i < 256; ++i) { - table[i] = (i + 0x100).toString(16).substring(1) + table[i] = (i + 0x100).toString(16).slice(1) } return table } diff --git a/packages/sanity/src/_internal/cli/actions/graphql/SchemaError.ts b/packages/sanity/src/_internal/cli/actions/graphql/SchemaError.ts index b8bc56f1352..f9fac4f3c4d 100644 --- a/packages/sanity/src/_internal/cli/actions/graphql/SchemaError.ts +++ b/packages/sanity/src/_internal/cli/actions/graphql/SchemaError.ts @@ -12,6 +12,7 @@ export class SchemaError extends Error { constructor(problemGroups: SchemaValidationProblemGroup[]) { super('Schema errors encountered') + this.name = 'SchemaError' this.problemGroups = problemGroups } diff --git a/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts b/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts index 1ce553834a7..1ca695844c8 100644 --- a/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts +++ b/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts @@ -724,6 +724,7 @@ class HelpfulError extends Error { constructor(message: string, helpUrl?: string) { super(message) + this.name = 'HelpfulError' this.helpUrl = helpUrl } } diff --git a/packages/sanity/src/_internal/cli/actions/schema/formatSchemaValidation.ts b/packages/sanity/src/_internal/cli/actions/schema/formatSchemaValidation.ts index c9e00fa37d2..ed0c773f64e 100644 --- a/packages/sanity/src/_internal/cli/actions/schema/formatSchemaValidation.ts +++ b/packages/sanity/src/_internal/cli/actions/schema/formatSchemaValidation.ts @@ -25,7 +25,7 @@ function formatPath(pathSegments: SchemaValidationProblemPath) { return `${mode === 'array' ? `[${name}]` : `.${name}`}${format(next)}` } - return format(pathSegments.slice(1)).substring(1) // removes the top-level type and leading `.` + return format(pathSegments.slice(1)).slice(1) // removes the top-level type and leading `.` } export function getAggregatedSeverity( diff --git a/packages/sanity/src/_internal/cli/actions/validation/reporters/prettyReporter/util.ts b/packages/sanity/src/_internal/cli/actions/validation/reporters/prettyReporter/util.ts index ce9517f9640..9e52add4ba3 100644 --- a/packages/sanity/src/_internal/cli/actions/validation/reporters/prettyReporter/util.ts +++ b/packages/sanity/src/_internal/cli/actions/validation/reporters/prettyReporter/util.ts @@ -23,7 +23,7 @@ export const levelValues = {error: 0, warning: 1, info: 2} as const */ export const count = (amount: number, subject: string): string => `${amount.toLocaleString('en-US')} ${ - amount === 1 ? subject.substring(0, subject.length - 1) : subject + amount === 1 ? subject.slice(0, Math.max(0, subject.length - 1)) : subject }` const percentageFormatter = new Intl.NumberFormat('en-US', { diff --git a/packages/sanity/src/_internal/cli/commands/dataset/alias/createAliasHandler.ts b/packages/sanity/src/_internal/cli/commands/dataset/alias/createAliasHandler.ts index 6213dbe67e1..0abf0a0325c 100644 --- a/packages/sanity/src/_internal/cli/commands/dataset/alias/createAliasHandler.ts +++ b/packages/sanity/src/_internal/cli/commands/dataset/alias/createAliasHandler.ts @@ -27,7 +27,7 @@ export const createAliasHandler: CliCommandAction = async (args, context) => { let aliasOutputName = aliasName if (aliasName.startsWith(ALIAS_PREFIX)) { - aliasName = aliasName.substring(1) + aliasName = aliasName.slice(1) } else { aliasOutputName = `${ALIAS_PREFIX}${aliasName}` } diff --git a/packages/sanity/src/_internal/cli/commands/dataset/alias/deleteAliasHandler.ts b/packages/sanity/src/_internal/cli/commands/dataset/alias/deleteAliasHandler.ts index 015b35bf2d0..8f73ffa7f77 100644 --- a/packages/sanity/src/_internal/cli/commands/dataset/alias/deleteAliasHandler.ts +++ b/packages/sanity/src/_internal/cli/commands/dataset/alias/deleteAliasHandler.ts @@ -28,7 +28,7 @@ export const deleteAliasHandler: CliCommandAction = async (arg if (dsError) { throw dsError } - aliasName = aliasName.startsWith(ALIAS_PREFIX) ? aliasName.substring(1) : aliasName + aliasName = aliasName.startsWith(ALIAS_PREFIX) ? aliasName.slice(1) : aliasName const [fetchedAliases] = await Promise.all([aliasClient.listAliases(client)]) const linkedAlias = fetchedAliases.find((elem) => elem.name === aliasName) diff --git a/packages/sanity/src/_internal/cli/commands/dataset/alias/linkAliasHandler.ts b/packages/sanity/src/_internal/cli/commands/dataset/alias/linkAliasHandler.ts index fe8b29f9ef8..57ef789e58d 100644 --- a/packages/sanity/src/_internal/cli/commands/dataset/alias/linkAliasHandler.ts +++ b/packages/sanity/src/_internal/cli/commands/dataset/alias/linkAliasHandler.ts @@ -28,7 +28,7 @@ export const linkAliasHandler: CliCommandAction = async (args, context) => { let aliasOutputName = aliasName if (aliasName.startsWith(ALIAS_PREFIX)) { - aliasName = aliasName.substring(1) + aliasName = aliasName.slice(1) } else { aliasOutputName = `${ALIAS_PREFIX}${aliasName}` } diff --git a/packages/sanity/src/_internal/cli/commands/dataset/alias/unlinkAliasHandler.ts b/packages/sanity/src/_internal/cli/commands/dataset/alias/unlinkAliasHandler.ts index 0c54d80a59b..4a3c4e53346 100644 --- a/packages/sanity/src/_internal/cli/commands/dataset/alias/unlinkAliasHandler.ts +++ b/packages/sanity/src/_internal/cli/commands/dataset/alias/unlinkAliasHandler.ts @@ -32,7 +32,7 @@ export const unlinkAliasHandler: CliCommandAction = async (args, co let aliasOutputName = aliasName if (aliasName.startsWith(ALIAS_PREFIX)) { - aliasName = aliasName.substring(1) + aliasName = aliasName.slice(1) } else { aliasOutputName = `${ALIAS_PREFIX}${aliasName}` } diff --git a/packages/sanity/src/_internal/cli/threads/__tests__/validateDocuments.test.ts b/packages/sanity/src/_internal/cli/threads/__tests__/validateDocuments.test.ts index e8e6e203918..df9018b56fd 100644 --- a/packages/sanity/src/_internal/cli/threads/__tests__/validateDocuments.test.ts +++ b/packages/sanity/src/_internal/cli/threads/__tests__/validateDocuments.test.ts @@ -117,7 +117,7 @@ describe('validateDocuments', () => { .filter((key) => key.startsWith('$')) .reduce>((acc, key) => { const values = searchParams.getAll(key) - acc[key.substring(1)] = values.length === 1 ? values[0] : values + acc[key.slice(1)] = values.length === 1 ? values[0] : values return acc }, {}) diff --git a/packages/sanity/src/_internal/cli/util/getUrlHeaders.ts b/packages/sanity/src/_internal/cli/util/getUrlHeaders.ts index 76b36120fe5..0e7adc63902 100644 --- a/packages/sanity/src/_internal/cli/util/getUrlHeaders.ts +++ b/packages/sanity/src/_internal/cli/util/getUrlHeaders.ts @@ -5,6 +5,11 @@ import {promise} from 'get-it/middleware' const request = getIt([promise()]) export class HttpError extends Error { + constructor(message: string) { + super(message) + this.name = 'HttpError' + } + statusCode?: number } diff --git a/packages/sanity/src/core/comments/components/pte/comment-input/CommentInputProvider.tsx b/packages/sanity/src/core/comments/components/pte/comment-input/CommentInputProvider.tsx index 32fe3c80bf8..15a393f94b3 100644 --- a/packages/sanity/src/core/comments/components/pte/comment-input/CommentInputProvider.tsx +++ b/packages/sanity/src/core/comments/components/pte/comment-input/CommentInputProvider.tsx @@ -97,10 +97,11 @@ export function CommentInputProvider(props: CommentInputProviderProps) { const isDeleteText = event.inputType === 'deleteContentBackward' const isInsertingAtChar = isInsertText && event.data === '@' - const lastIndexOfAt = focusSpan?.text.substring(0, cursorOffset).lastIndexOf('@') || 0 + const lastIndexOfAt = + focusSpan?.text.slice(0, Math.max(0, cursorOffset)).lastIndexOf('@') || 0 const isWhitespaceCharBeforeCursorPosition = - focusSpan?.text.substring(cursorOffset - 1, cursorOffset) === ' ' + focusSpan?.text.slice(cursorOffset - 1, cursorOffset) === ' ' const filterStartsWithSpaceChar = isInsertText && event.data === ' ' && !mentionsSearchTerm @@ -126,14 +127,14 @@ export function CommentInputProvider(props: CommentInputProviderProps) { // Update the search term if (isPortableTextSpan(focusChild)) { // Term starts with the @ char in the value until the cursor offset - let term = focusChild.text.substring(lastIndexOfAt + 1, cursorOffset) + let term = focusChild.text.slice(lastIndexOfAt + 1, cursorOffset) // Add the char to the mentions search term if (isInsertText) { term += event.data } // Exclude the char from the mentions search term if (isDeleteText) { - term = term.substring(0, term.length - 1) + term = term.slice(0, Math.max(0, term.length - 1)) } // Set the updated mentions search term setMentionsSearchTerm(term) diff --git a/packages/sanity/src/core/comments/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts b/packages/sanity/src/core/comments/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts index a31991f8da5..89661f89896 100644 --- a/packages/sanity/src/core/comments/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts +++ b/packages/sanity/src/core/comments/utils/inline-comments/buildRangeDecorationSelectionsFromComments.ts @@ -90,11 +90,11 @@ export function buildRangeDecorationSelectionsFromComments( .replaceAll(COMMENT_INDICATORS[0], '') .indexOf(COMMENT_INDICATORS[1]) const textWithoutCommentTags = diffedText.replaceAll(COMMENT_INDICATORS_REGEX, '') - const oldCommentedText = selectionMember.text.substring( + const oldCommentedText = selectionMember.text.slice( selectionMember.text.indexOf(COMMENT_INDICATORS[0]) + 1, selectionMember.text.indexOf(COMMENT_INDICATORS[1]), ) - const newCommentedText = textWithoutCommentTags.substring(startIndex, endIndex) + const newCommentedText = textWithoutCommentTags.slice(startIndex, endIndex) const {levenshtein} = diffText(newCommentedText, oldCommentedText) const threshold = Math.round(newCommentedText.length + oldCommentedText.length / 2) diff --git a/packages/sanity/src/core/comments/utils/inline-comments/buildTextSelectionFromFragment.ts b/packages/sanity/src/core/comments/utils/inline-comments/buildTextSelectionFromFragment.ts index 376658ede50..c9ea4dc2bb0 100644 --- a/packages/sanity/src/core/comments/utils/inline-comments/buildTextSelectionFromFragment.ts +++ b/packages/sanity/src/core/comments/utils/inline-comments/buildTextSelectionFromFragment.ts @@ -55,7 +55,7 @@ export function buildTextSelectionFromFragment( if (child._key === fragmentStartSpan?._key) { originalTextBeforeSelection += (isPortableTextSpan(child) && - child.text.substring(0, normalizedSelection.anchor.offset)) || + child.text.slice(0, Math.max(0, normalizedSelection.anchor.offset))) || '' break } @@ -68,7 +68,7 @@ export function buildTextSelectionFromFragment( if (child._key === fragmentEndSpan?._key) { originalTextAfterSelection = ((isPortableTextSpan(child) && - child.text.substring(normalizedSelection.focus.offset, child.text.length)) || + child.text.slice(normalizedSelection.focus.offset, child.text.length)) || '') + originalTextAfterSelection break } diff --git a/packages/sanity/src/core/config/ConfigPropertyError.ts b/packages/sanity/src/core/config/ConfigPropertyError.ts index f299fb318d8..cf2482c8dbc 100644 --- a/packages/sanity/src/core/config/ConfigPropertyError.ts +++ b/packages/sanity/src/core/config/ConfigPropertyError.ts @@ -21,6 +21,7 @@ export class ConfigPropertyError extends Error { `An error occurred while resolving \`${propertyName}\` from ${path.join(' > ')}${message}`, ) + this.name = 'ConfigPropertyError' this.propertyName = propertyName this.cause = cause this.path = path diff --git a/packages/sanity/src/core/config/ConfigResolutionError.ts b/packages/sanity/src/core/config/ConfigResolutionError.ts index c83771604a3..f355fc70710 100644 --- a/packages/sanity/src/core/config/ConfigResolutionError.ts +++ b/packages/sanity/src/core/config/ConfigResolutionError.ts @@ -26,6 +26,7 @@ export class ConfigResolutionError extends Error { .join('\n')}\n\n`, ) + // eslint-disable-next-line unicorn/custom-error-definition this.name = name this.causes = causes this.type = type diff --git a/packages/sanity/src/core/config/SchemaError.ts b/packages/sanity/src/core/config/SchemaError.ts index d3a6a66f6a8..432356f2c6b 100644 --- a/packages/sanity/src/core/config/SchemaError.ts +++ b/packages/sanity/src/core/config/SchemaError.ts @@ -5,5 +5,6 @@ import {type Schema} from '@sanity/types' export class SchemaError extends Error { constructor(public schema: Schema) { super('SchemaError') + this.name = 'SchemaError' } } diff --git a/packages/sanity/src/core/field/types/portableText/diff/components/PortableText.tsx b/packages/sanity/src/core/field/types/portableText/diff/components/PortableText.tsx index 2cb0ce00506..4ca44527a20 100644 --- a/packages/sanity/src/core/field/types/portableText/diff/components/PortableText.tsx +++ b/packages/sanity/src/core/field/types/portableText/diff/components/PortableText.tsx @@ -345,11 +345,11 @@ function renderDecorators({ .filter((text) => !!text) .join('') const ptDiffMatchString = ptDiffChildren - const controlString = ptDiffMatchString.substring( + const controlString = ptDiffMatchString.slice( 0, - ptDiffMatchString.indexOf(seg.text) + seg.text.length, + Math.max(0, ptDiffMatchString.indexOf(seg.text) + seg.text.length), ) - const toTest = controlString.substring(0, controlString.indexOf(seg.text)) + const toTest = controlString.slice(0, Math.max(0, controlString.indexOf(seg.text))) const marks: string[] = [] const matches = [...toTest.matchAll(markRegex)] matches.forEach((match) => { diff --git a/packages/sanity/src/core/field/types/portableText/diff/helpers.ts b/packages/sanity/src/core/field/types/portableText/diff/helpers.ts index 25b7350a0a2..12058efc4c4 100644 --- a/packages/sanity/src/core/field/types/portableText/diff/helpers.ts +++ b/packages/sanity/src/core/field/types/portableText/diff/helpers.ts @@ -302,7 +302,7 @@ function buildSegments(fromInput: string, toInput: string): StringDiffSegment[] segments.push({ type: 'stringSegment', action: 'removed', - text: fromInput.substring(fromIdx, fromIdx + text.length), + text: fromInput.slice(fromIdx, fromIdx + text.length), annotation: null, }) fromIdx += text.length @@ -311,7 +311,7 @@ function buildSegments(fromInput: string, toInput: string): StringDiffSegment[] segments.push({ type: 'stringSegment', action: 'added', - text: toInput.substring(toIdx, toIdx + text.length), + text: toInput.slice(toIdx, toIdx + text.length), annotation: null, }) toIdx += text.length @@ -330,11 +330,11 @@ function buildSegments(fromInput: string, toInput: string): StringDiffSegment[] markMatches.forEach((match) => { const index = match.index || 0 if (index > lastIndex) { - newSegments.push({...seg, text: seg.text.substring(lastIndex + 1, index)}) + newSegments.push({...seg, text: seg.text.slice(lastIndex + 1, index)}) newSegments.push({...seg, text: match[0]}) } if (match === markMatches[markMatches.length - 1]) { - newSegments.push({...seg, text: seg.text.substring(index + 1)}) + newSegments.push({...seg, text: seg.text.slice(Math.max(0, index + 1))}) } lastIndex = index }) diff --git a/packages/sanity/src/core/form/inputs/files/ImageInput/utils/image.ts b/packages/sanity/src/core/form/inputs/files/ImageInput/utils/image.ts index c2e6e8d452b..22449b800a2 100644 --- a/packages/sanity/src/core/form/inputs/files/ImageInput/utils/image.ts +++ b/packages/sanity/src/core/form/inputs/files/ImageInput/utils/image.ts @@ -9,7 +9,13 @@ export function urlToFile(url: string, filename?: string): Promise { const reader = new FileReader() reader.onloadend = () => { const string = reader.result?.toString() - const ext = string?.substring('data:image/'.length, string.indexOf(';base64')) + const base64Index = string?.indexOf(';base64') + if (!string || base64Index === -1) { + reject(new Error('Could not convert URL to file')) + return + } + + const ext = string.slice('data:image/'.length, base64Index) if (!ext && !filename) { reject(new Error('Could not find mime type for image')) return @@ -30,7 +36,13 @@ export function urlToFile(url: string, filename?: string): Promise { export function base64ToFile(base64Data: string | ArrayBuffer, filename?: string): Promise { return new Promise((resolve, reject) => { const string = base64Data.toString() - const ext = string.substring('data:image/'.length, string.indexOf(';base64')) + const base64Index = string.indexOf(';base64') + if (!string || base64Index === -1) { + reject(new Error('Could not convert base64 to file')) + return + } + + const ext = string.slice('data:image/'.length, base64Index) if (!ext && !filename) { reject(new Error('Could not find mime type for image')) return diff --git a/packages/sanity/src/core/form/utils/common.tsx b/packages/sanity/src/core/form/utils/common.tsx index df16f428265..25eede33cc8 100644 --- a/packages/sanity/src/core/form/utils/common.tsx +++ b/packages/sanity/src/core/form/utils/common.tsx @@ -78,7 +78,7 @@ export function mappedChildren({children, childProps}: ChildrenWithPropsProps) { if (!Array.isArray(children)) { children = [children] } - return Children.map(children, function (child) { + return Children.map(children, (child) => { if (isValidElement(child)) { return cloneElement(child, childProps) } diff --git a/packages/sanity/src/core/form/utils/randomKey.ts b/packages/sanity/src/core/form/utils/randomKey.ts index 3eabb8ffae2..3955045722d 100644 --- a/packages/sanity/src/core/form/utils/randomKey.ts +++ b/packages/sanity/src/core/form/utils/randomKey.ts @@ -15,7 +15,7 @@ const getByteHexTable = (() => { } table = [] for (let i = 0; i < 256; ++i) { - table[i] = (i + 0x100).toString(16).substring(1) + table[i] = (i + 0x100).toString(16).slice(1) } return table } diff --git a/packages/sanity/src/core/i18n/simpleParser.ts b/packages/sanity/src/core/i18n/simpleParser.ts index d9c9fdd80ee..973634d0d8c 100644 --- a/packages/sanity/src/core/i18n/simpleParser.ts +++ b/packages/sanity/src/core/i18n/simpleParser.ts @@ -78,11 +78,11 @@ export function simpleParser(input: string): Token[] { tokens.push({type: 'tagOpen', name: tagName}) openTag = tagName } - remainder = remainder.substring(match[0].length) + remainder = remainder.slice(match[0].length) } else { // move on to next char text += remainder[0] - remainder = remainder.substring(1) + remainder = remainder.slice(1) } } else if (openTag && remainder[0] === '<' && remainder[1] !== '<') { const match = matchCloseTag(remainder) @@ -104,16 +104,16 @@ export function simpleParser(input: string): Token[] { } tokens.push({type: 'tagClose', name: tagName}) openTag = '' - remainder = remainder.substring(match[0].length) + remainder = remainder.slice(match[0].length) } else { // move on to next char text += remainder[0] - remainder = remainder.substring(1) + remainder = remainder.slice(1) } } else { // move on to next char text += remainder[0] - remainder = remainder.substring(1) + remainder = remainder.slice(1) } } if (openTag) { diff --git a/packages/sanity/src/core/scheduledPublishing/tool/toolCalendar/CalendarMonth.tsx b/packages/sanity/src/core/scheduledPublishing/tool/toolCalendar/CalendarMonth.tsx index f1a393390d2..dac69a4b139 100644 --- a/packages/sanity/src/core/scheduledPublishing/tool/toolCalendar/CalendarMonth.tsx +++ b/packages/sanity/src/core/scheduledPublishing/tool/toolCalendar/CalendarMonth.tsx @@ -37,7 +37,7 @@ export function CalendarMonth(props: CalendarMonthProps) { // tone={isWeekend(date) ? 'transparent' : 'default'} > ) diff --git a/packages/sanity/src/core/store/_legacy/cors/CorsOriginError.ts b/packages/sanity/src/core/store/_legacy/cors/CorsOriginError.ts index 2b2329b1bff..00f8450381e 100644 --- a/packages/sanity/src/core/store/_legacy/cors/CorsOriginError.ts +++ b/packages/sanity/src/core/store/_legacy/cors/CorsOriginError.ts @@ -9,6 +9,7 @@ export class CorsOriginError extends Error { constructor({projectId}: CorsOriginErrorOptions) { super('CorsOriginError') + this.name = 'CorsOriginError' this.projectId = projectId } } diff --git a/packages/sanity/src/core/store/_legacy/debugParams/debugParams.ts b/packages/sanity/src/core/store/_legacy/debugParams/debugParams.ts index cf359e47717..fd464a66cd4 100644 --- a/packages/sanity/src/core/store/_legacy/debugParams/debugParams.ts +++ b/packages/sanity/src/core/store/_legacy/debugParams/debugParams.ts @@ -10,10 +10,10 @@ export const debugParams$ = concat(of(0), hashchange$).pipe( distinctUntilChanged(), map((hash) => hash - .substring(1) + .slice(1) .split(';') .filter((p) => p.toLowerCase().startsWith(DEBUG_PREFIX)) - .map((param) => param.substring(DEBUG_PREFIX.length)), + .map((param) => param.slice(DEBUG_PREFIX.length)), ), ) diff --git a/packages/sanity/src/core/store/_legacy/user/__tests__/userStore.test.ts b/packages/sanity/src/core/store/_legacy/user/__tests__/userStore.test.ts index 795d6783fd7..5d599d495e7 100644 --- a/packages/sanity/src/core/store/_legacy/user/__tests__/userStore.test.ts +++ b/packages/sanity/src/core/store/_legacy/user/__tests__/userStore.test.ts @@ -4,6 +4,11 @@ import {type SanityClient} from '@sanity/client' import {createUserStore} from '../userStore' export class HttpError extends Error { + constructor() { + super() + this.name = 'HttpError' + } + statusCode?: number } diff --git a/packages/sanity/src/core/studio/activeWorkspaceMatcher/__tests__/matchWorkspace.test.ts b/packages/sanity/src/core/studio/activeWorkspaceMatcher/__tests__/matchWorkspace.test.ts index e6a3a2c324e..bb3abc76927 100644 --- a/packages/sanity/src/core/studio/activeWorkspaceMatcher/__tests__/matchWorkspace.test.ts +++ b/packages/sanity/src/core/studio/activeWorkspaceMatcher/__tests__/matchWorkspace.test.ts @@ -1,6 +1,7 @@ -import {describe, expect, it} from '@jest/globals' /* eslint-disable @typescript-eslint/no-explicit-any */ -import assert from 'assert' +import assert from 'node:assert' + +import {describe, expect, it} from '@jest/globals' import {type WorkspaceLike} from '../../workspaces' import {createCommonBasePathRegex} from '../createCommonBasePathRegex' diff --git a/packages/sanity/src/core/studio/activeWorkspaceMatcher/createCommonBasePathRegex.ts b/packages/sanity/src/core/studio/activeWorkspaceMatcher/createCommonBasePathRegex.ts index c86b28ca176..c0604bc3b6f 100644 --- a/packages/sanity/src/core/studio/activeWorkspaceMatcher/createCommonBasePathRegex.ts +++ b/packages/sanity/src/core/studio/activeWorkspaceMatcher/createCommonBasePathRegex.ts @@ -20,7 +20,7 @@ export function createCommonBasePathRegex(workspaces: NormalizedWorkspace[]): Re // gets the segments from the basePath workspace.basePath // removes the leading `/` - .substring(1) + .slice(1) .split('/'), ) diff --git a/packages/sanity/src/core/studio/workspaces/WorkspaceValidationError.ts b/packages/sanity/src/core/studio/workspaces/WorkspaceValidationError.ts index a6a212af693..37c5cd370f2 100644 --- a/packages/sanity/src/core/studio/workspaces/WorkspaceValidationError.ts +++ b/packages/sanity/src/core/studio/workspaces/WorkspaceValidationError.ts @@ -16,6 +16,7 @@ export class WorkspaceValidationError extends Error { constructor(message: string, options?: WorkspaceValidationErrorOptions) { super(message) + this.name = 'WorkspaceValidationError' this.index = options?.index this.identifier = options?.workspace && getWorkspaceIdentifier(options.workspace, options.index) } diff --git a/packages/sanity/src/core/studio/workspaces/validateWorkspaces.ts b/packages/sanity/src/core/studio/workspaces/validateWorkspaces.ts index 9c5afe9eb73..b72a6c193df 100644 --- a/packages/sanity/src/core/studio/workspaces/validateWorkspaces.ts +++ b/packages/sanity/src/core/studio/workspaces/validateWorkspaces.ts @@ -102,14 +102,14 @@ export function validateBasePaths(workspaces: WorkspaceLike[]): void { const [firstWorkspace, ...restOfWorkspaces] = workspaces const firstWorkspaceSegmentCount = (firstWorkspace.basePath || '/') // remove starting slash before splitting - .substring(1) + .slice(1) .split('/') .filter(Boolean).length restOfWorkspaces.forEach((workspace, index) => { const workspaceSegmentCount = (workspace.basePath || '/') // remove starting slash before splitting - .substring(1) + .slice(1) .split('/').length if (firstWorkspaceSegmentCount !== workspaceSegmentCount) { diff --git a/packages/sanity/src/router/_parseRoute.ts b/packages/sanity/src/router/_parseRoute.ts index 5d93fc44497..0b4d4722fa4 100644 --- a/packages/sanity/src/router/_parseRoute.ts +++ b/packages/sanity/src/router/_parseRoute.ts @@ -8,7 +8,7 @@ function createSegment(segment: string): RouteSegment | null { } if (segment.startsWith(':')) { - const paramName = segment.substring(1) + const paramName = segment.slice(1) if (!VALID_PARAM_SEGMENT.test(paramName)) { const addendum = segment.includes('*') diff --git a/packages/sanity/src/structure/structureBuilder/SerializeError.ts b/packages/sanity/src/structure/structureBuilder/SerializeError.ts index b7a0d7c86b5..0dcece58324 100644 --- a/packages/sanity/src/structure/structureBuilder/SerializeError.ts +++ b/packages/sanity/src/structure/structureBuilder/SerializeError.ts @@ -12,6 +12,7 @@ export class SerializeError extends Error { hint?: string, ) { super(message) + this.name = 'SerializeError' const segment = typeof pathSegment === 'undefined' ? '' : `${pathSegment}` this.path = (parentPath || []).concat(hint ? `${segment} (${hint})` : segment) } diff --git a/packages/sanity/src/structure/structureResolvers/PaneResolutionError.ts b/packages/sanity/src/structure/structureResolvers/PaneResolutionError.ts index 48ff8a460de..e864029d3f2 100644 --- a/packages/sanity/src/structure/structureResolvers/PaneResolutionError.ts +++ b/packages/sanity/src/structure/structureResolvers/PaneResolutionError.ts @@ -19,6 +19,7 @@ export class PaneResolutionError extends Error { constructor({message, context, helpId, cause}: PaneResolutionErrorOptions) { super(message) + this.name = 'PaneResolutionError' this.context = context this.helpId = helpId this.cause = cause diff --git a/packages/sanity/test/validation/util/typeString.test.ts b/packages/sanity/test/validation/util/typeString.test.ts index 6051e774abd..c0070427d60 100644 --- a/packages/sanity/test/validation/util/typeString.test.ts +++ b/packages/sanity/test/validation/util/typeString.test.ts @@ -6,7 +6,7 @@ describe('typeString', () => { it('returns the a type string of built in types', () => { expect(typeString({})).toBe('Object') expect( - typeString(function () { + typeString(() => { // intentionally blank }), ).toBe('Function') diff --git a/perf/tests/runner/utils/gitUtils.ts b/perf/tests/runner/utils/gitUtils.ts index 1a665d54af5..c2712022829 100644 --- a/perf/tests/runner/utils/gitUtils.ts +++ b/perf/tests/runner/utils/gitUtils.ts @@ -45,9 +45,7 @@ function stripHead(refs: string) { const ORIGIN_PREFIX = 'origin/' function stripOrigin(branchName: string) { - return branchName.startsWith(ORIGIN_PREFIX) - ? branchName.substring(ORIGIN_PREFIX.length) - : branchName + return branchName.startsWith(ORIGIN_PREFIX) ? branchName.slice(ORIGIN_PREFIX.length) : branchName } export function parseDecoratedRefs(refs: string) { const parsedRefs = stripHead(refs) @@ -56,7 +54,7 @@ export function parseDecoratedRefs(refs: string) { .filter((s) => s) .map((s) => s.startsWith(TAG_PREFIX) - ? {type: 'tag', name: s.substring(TAG_PREFIX.length)} + ? {type: 'tag', name: s.slice(TAG_PREFIX.length)} : {type: 'branch', name: stripOrigin(s)}, ) const [branches, tags] = partition(parsedRefs, (ref) => ref.type === 'branch') diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b19043f2fc9..25b88adbd6d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -145,6 +145,9 @@ importers: eslint-plugin-tsdoc: specifier: ^0.2.17 version: 0.2.17 + eslint-plugin-unicorn: + specifier: ^52.0.0 + version: 52.0.0(eslint@8.57.0) eslint-plugin-unused-imports: specifier: ^3.1.0 version: 3.1.0(@typescript-eslint/eslint-plugin@7.6.0)(eslint@8.57.0) @@ -9005,6 +9008,11 @@ packages: engines: {node: '>=8'} dev: true + /ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} + dev: true + /cjs-module-lexer@1.2.3: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} dev: true @@ -9023,6 +9031,13 @@ packages: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} dev: false + /clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + /clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -10803,6 +10818,33 @@ packages: '@microsoft/tsdoc-config': 0.16.2 dev: true + /eslint-plugin-unicorn@52.0.0(eslint@8.57.0): + resolution: {integrity: sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==} + engines: {node: '>=16'} + peerDependencies: + eslint: '>=8.56.0' + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint/eslintrc': 2.1.4 + ci-info: 4.0.0 + clean-regexp: 1.0.0 + core-js-compat: 3.36.1 + eslint: 8.57.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.6.0 + strip-indent: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /eslint-plugin-unused-imports@3.1.0(@typescript-eslint/eslint-plugin@7.6.0)(eslint@8.57.0): resolution: {integrity: sha512-9l1YFCzXKkw1qtAru1RWUtG2EVDZY0a0eChKXcL+EZ5jitG7qxdctu4RnvhOJHv4xfmUf7h+JJPINlVpGhZMrw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -13816,6 +13858,12 @@ packages: engines: {node: '>=4'} hasBin: true + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true @@ -16029,6 +16077,11 @@ packages: engines: {node: '>=14.0.0'} dev: false + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + /polished@4.3.1: resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} engines: {node: '>=10'} @@ -16762,6 +16815,11 @@ packages: safe-regex: 1.1.0 dev: true + /regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + /regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} @@ -16795,6 +16853,13 @@ packages: dependencies: rc: 1.2.8 + /regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + /regjsparser@0.9.1: resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} hasBin: true