diff --git a/src/rules/no-reversed-media-syntax.js b/src/rules/no-reversed-media-syntax.js index 82e00ec8..141beb74 100644 --- a/src/rules/no-reversed-media-syntax.js +++ b/src/rules/no-reversed-media-syntax.js @@ -22,11 +22,11 @@ /** * Matches reversed link/image syntax like `(text)[url]`, ignoring escaped characters like `\(text\)[url]`. - * The nested group is `\([^()]*\)`, not `\([\s\S]*\)`, so that it cannot overlap the + * The nested group is `\((?:\\[\s\S]|[^()\\])*\)`, not `\([\s\S]*\)`, so that it cannot overlap the * other alternatives. Overlapping alternatives cause catastrophic backtracking. */ const reversedPattern = - /(?<=(?(?:\\.|[^()\\]|\([^()]*\))*)\)\[(?(?:\\.|[^\]\\\r\n])*)\](?!\()/gu; + /(?<=(?(?:\\.|[^()\\]|\((?:\\[\s\S]|[^()\\])*\))*)\)\[(?(?:\\.|[^\]\\\r\n])*)\](?!\()/gu; //----------------------------------------------------------------------------- // Rule Definition diff --git a/tests/rules/no-reversed-media-syntax.test.js b/tests/rules/no-reversed-media-syntax.test.js index a084df3d..4988665e 100644 --- a/tests/rules/no-reversed-media-syntax.test.js +++ b/tests/rules/no-reversed-media-syntax.test.js @@ -588,6 +588,137 @@ ruleTester.run("no-reversed-media-syntax", rule, { }, ], }, + // Nested parentheses with escaped characters + { + code: "(a (b \\(c\\)) d)[x]", + output: "[a (b \\(c\\)) d](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 1, + endLine: 1, + endColumn: 19, + }, + ], + }, + { + code: "!(a (b \\(c\\)) d)[x]", + output: "![a (b \\(c\\)) d](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 2, + endLine: 1, + endColumn: 20, + }, + ], + }, + { + code: "(a (b\\( c))[x]", + output: "[a (b\\( c)](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 1, + endLine: 1, + endColumn: 15, + }, + ], + }, + { + code: "!(a (b\\( c))[x]", + output: "![a (b\\( c)](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 2, + endLine: 1, + endColumn: 16, + }, + ], + }, + { + code: "(a (b\\) c))[x]", + output: "[a (b\\) c)](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 1, + endLine: 1, + endColumn: 15, + }, + ], + }, + { + code: "!(a (b\\) c))[x]", + output: "![a (b\\) c)](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 2, + endLine: 1, + endColumn: 16, + }, + ], + }, + { + code: "(a (b\\\\) c)[x]", + output: "[a (b\\\\) c](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 1, + endLine: 1, + endColumn: 15, + }, + ], + }, + { + code: "!(a (b\\\\) c)[x]", + output: "![a (b\\\\) c](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 2, + endLine: 1, + endColumn: 16, + }, + ], + }, + { + code: "(a (b\\\nc))[x]", + output: "[a (b\\\nc)](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 1, + endLine: 2, + endColumn: 7, + }, + ], + }, + { + code: "!(a (b\\\nc))[x]", + output: "![a (b\\\nc)](x)", + errors: [ + { + messageId: "reversedSyntax", + line: 1, + column: 2, + endLine: 2, + endColumn: 7, + }, + ], + }, // Heading { code: "# (ESLint)[https://eslint.org/]",