diff --git a/HISTORY.md b/HISTORY.md index 6ae6e7e91..22cb155c2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,6 +5,7 @@ - Fix #3025: improve handling of matrices and error handling in function `corr` (#3030). Thanks @vrushaket. - Fix #3074: improve error message when using function `max` in `derivative`. +- Fix #3073: fix parsing quotes inside a string. # 2023-09-20, 11.11.1 diff --git a/src/expression/parse.js b/src/expression/parse.js index 54ce64bfd..96aed7a8a 100644 --- a/src/expression/parse.js +++ b/src/expression/parse.js @@ -1466,7 +1466,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ if (currentCharacter(state) === '\\') { // escape character, immediately process the next // character to prevent stopping at a next '\"' - str += currentCharacter(state) + const cNext = nextCharacter(state) + if (cNext !== "'") { + str += currentCharacter(state) + } next(state) } @@ -1517,7 +1520,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ if (currentCharacter(state) === '\\') { // escape character, immediately process the next // character to prevent stopping at a next '\'' - str += currentCharacter(state) + const cNext = nextCharacter(state) + if (cNext !== "'" && cNext !== '"') { + str += currentCharacter(state) + } next(state) } @@ -1531,7 +1537,7 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ } getToken(state) - return JSON.parse('"' + str + '"') // unescape escaped characters + return JSON.parse('"' + str.replace(/"/g, '\\"') + '"') // unescape escaped characters } /** diff --git a/test/unit-tests/expression/parse.test.js b/test/unit-tests/expression/parse.test.js index fb8cca3e5..049ab0386 100644 --- a/test/unit-tests/expression/parse.test.js +++ b/test/unit-tests/expression/parse.test.js @@ -364,6 +364,19 @@ describe('parse', function () { assert.deepStrictEqual(parseAndEval(' "hi" '), 'hi') }) + it('should parse a string containing quotes', function () { + // quote + assert.deepStrictEqual(parseAndEval('"with\'quote"'), "with'quote") + + // escaped quote -> remove escape character + assert.deepStrictEqual(parseAndEval('"with\\"quote"'), 'with"quote') + assert.deepStrictEqual(parseAndEval('"with\\\'quote"'), "with'quote") + + // escaped escape character -> remove two escape characters + assert.deepStrictEqual(parseAndEval('"with\\\\\\"quote"'), 'with\\"quote') + assert.deepStrictEqual(parseAndEval('"with\\\\\'quote"'), "with\\'quote") + }) + it('should parse a with escaped characters', function () { assert.deepStrictEqual(parseAndEval('"line end\\nnext"'), 'line end\nnext') assert.deepStrictEqual(parseAndEval('"line end\\n"'), 'line end\n') @@ -420,7 +433,20 @@ describe('parse', function () { assert.deepStrictEqual(parseAndEval(' \'hi\' '), 'hi') }) - it('should parse a with escaped characters', function () { + it('should parse a string containing quotes', function () { + // quote + assert.deepStrictEqual(parseAndEval("'with\"quote'"), 'with"quote') + + // escaped quote -> remove escape character + assert.deepStrictEqual(parseAndEval("'with\\'quote'"), "with'quote") + assert.deepStrictEqual(parseAndEval("'with\\\"quote'"), 'with"quote') + + // escaped escape character -> remove two escape characters + assert.deepStrictEqual(parseAndEval("'with\\\\\\'quote'"), "with\\'quote") + assert.deepStrictEqual(parseAndEval("'with\\\\\"quote'"), 'with\\"quote') + }) + + it('should parse a string with escaped characters', function () { assert.deepStrictEqual(parseAndEval('\'line end\\nnext\''), 'line end\nnext') assert.deepStrictEqual(parseAndEval('\'line end\\n\''), 'line end\n') assert.deepStrictEqual(parseAndEval('\'tab\\tnext\''), 'tab\tnext')