diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index 3143a0ae43..2ad69b57d5 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -1069,6 +1069,7 @@ export default class Tokenizer extends LocationParser { readString(quote: number): void { let out = "", chunkStart = ++this.state.pos; + const hasJsonStrings = this.hasPlugin("jsonStrings"); for (;;) { if (this.state.pos >= this.input.length) { this.raise(this.state.start, "Unterminated string constant"); @@ -1080,10 +1081,14 @@ export default class Tokenizer extends LocationParser { // $FlowFixMe out += this.readEscapedChar(false); chunkStart = this.state.pos; + } else if ( + hasJsonStrings && + (ch === charCodes.lineSeparator || ch === charCodes.paragraphSeparator) + ) { + ++this.state.pos; + } else if (isNewLine(ch)) { + this.raise(this.state.start, "Unterminated string constant"); } else { - if (isNewLine(ch)) { - this.raise(this.state.start, "Unterminated string constant"); - } ++this.state.pos; } } diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/directive-line-separator/input.js b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-line-separator/input.js new file mode 100644 index 0000000000..979635bbd4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-line-separator/input.js @@ -0,0 +1,2 @@ +"before
after"; +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/directive-line-separator/output.json b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-line-separator/output.json new file mode 100644 index 0000000000..8561f6d687 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-line-separator/output.json @@ -0,0 +1,105 @@ +{ + "type": "File", + "start": 0, + "end": 98, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 82 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 98, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 82 + } + }, + "sourceType": "script", + "body": [], + "directives": [ + { + "type": "Directive", + "start": 0, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "value": { + "type": "DirectiveLiteral", + "start": 0, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "value": "before
after", + "extra": { + "raw": "\"before
after\"", + "rawValue": "before
after" + } + }, + "trailingComments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 16, + "end": 98, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 82 + } + } + } + ] + } + ] + }, + "comments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 16, + "end": 98, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 82 + } + } + } + ] +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/directive-paragraph-separator/input.js b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-paragraph-separator/input.js new file mode 100644 index 0000000000..bbf5551a5f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-paragraph-separator/input.js @@ -0,0 +1,2 @@ +"before
after"; +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/directive-paragraph-separator/output.json b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-paragraph-separator/output.json new file mode 100644 index 0000000000..e9b98e4f6e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/directive-paragraph-separator/output.json @@ -0,0 +1,105 @@ +{ + "type": "File", + "start": 0, + "end": 103, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 87 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 103, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 87 + } + }, + "sourceType": "script", + "body": [], + "directives": [ + { + "type": "Directive", + "start": 0, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "value": { + "type": "DirectiveLiteral", + "start": 0, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "value": "before
after", + "extra": { + "raw": "\"before
after\"", + "rawValue": "before
after" + } + }, + "trailingComments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 16, + "end": 103, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 87 + } + } + } + ] + } + ] + }, + "comments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 16, + "end": 103, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 87 + } + } + } + ] +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/options.json b/packages/babel-parser/test/fixtures/experimental/json-strings/options.json new file mode 100644 index 0000000000..8199686033 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["jsonStrings"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/string-line-separator/input.js b/packages/babel-parser/test/fixtures/experimental/json-strings/string-line-separator/input.js new file mode 100644 index 0000000000..a1735d77e9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/string-line-separator/input.js @@ -0,0 +1,2 @@ +("before
after"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/string-line-separator/output.json b/packages/babel-parser/test/fixtures/experimental/json-strings/string-line-separator/output.json new file mode 100644 index 0000000000..83a66a0ff2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/string-line-separator/output.json @@ -0,0 +1,107 @@ +{ + "type": "File", + "start": 0, + "end": 101, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 83 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 101, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 83 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 17 + } + }, + "expression": { + "type": "StringLiteral", + "start": 1, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "extra": { + "rawValue": "before
after", + "raw": "\"before
after\"", + "parenthesized": true, + "parenStart": 0 + }, + "value": "before
after" + }, + "trailingComments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 18, + "end": 101, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 83 + } + } + } + ] + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 18, + "end": 101, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 83 + } + } + } + ] +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/string-paragraph-separator/input.js b/packages/babel-parser/test/fixtures/experimental/json-strings/string-paragraph-separator/input.js new file mode 100644 index 0000000000..aef14e8525 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/string-paragraph-separator/input.js @@ -0,0 +1,2 @@ +("before
after"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') diff --git a/packages/babel-parser/test/fixtures/experimental/json-strings/string-paragraph-separator/output.json b/packages/babel-parser/test/fixtures/experimental/json-strings/string-paragraph-separator/output.json new file mode 100644 index 0000000000..e91e09b29d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/json-strings/string-paragraph-separator/output.json @@ -0,0 +1,107 @@ +{ + "type": "File", + "start": 0, + "end": 106, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 88 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 106, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 88 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 17 + } + }, + "expression": { + "type": "StringLiteral", + "start": 1, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "extra": { + "rawValue": "before
after", + "raw": "\"before
after\"", + "parenthesized": true, + "parenStart": 0 + }, + "value": "before
after" + }, + "trailingComments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 18, + "end": 106, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 88 + } + } + } + ] + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentLine", + "value": " ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after')", + "start": 18, + "end": 106, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 88 + } + } + } + ] +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-json-strings/.npmignore b/packages/babel-plugin-proposal-json-strings/.npmignore new file mode 100644 index 0000000000..f980694583 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-proposal-json-strings/README.md b/packages/babel-plugin-proposal-json-strings/README.md new file mode 100644 index 0000000000..4fc0a7fc09 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/README.md @@ -0,0 +1,54 @@ +# @babel/plugin-syntax-json-strings + +Allow parsing of the U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR in JS strings + +## Examples + +**In** + +```js +const ex = "before
after"; +// ^ There's a U+2028 char between 'before' and 'after' +``` + +**Out** + +```js +const ex = "before\u2028after"; +// ^ There's a U+2028 char between 'before' and 'after' +``` + +## Installation + +```sh +npm install --save-dev @babel/plugin-proposal-json-strings +``` + +## Usage + +### Via `.babelrc` (Recommended) + +**.babelrc** + +```json +{ + "plugins": ["@babel/plugin-proposal-json-strings"] +} +``` + +### Via CLI + +```sh +babel --plugins @babel/plugin-proposal-json-strings script.js +``` + +### Via Node API + +```javascript +require("@babel/core").transform("code", { + plugins: ["@babel/plugin-proposal-json-strings"] +}); +``` + +## References +- [Proposal: Optional Catch Binding for ECMAScript](https://github.com/babel/proposals/issues/7) diff --git a/packages/babel-plugin-proposal-json-strings/package.json b/packages/babel-plugin-proposal-json-strings/package.json new file mode 100644 index 0000000000..174ec7d63e --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/package.json @@ -0,0 +1,22 @@ +{ + "name": "@babel/plugin-proposal-json-strings", + "version": "7.0.0-beta.47", + "description": "Escape U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR in JS strings", + "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-proposal-json-strings", + "license": "MIT", + "main": "lib/index.js", + "keywords": [ + "babel-plugin" + ], + "dependencies": { + "@babel/helper-plugin-utils": "7.0.0-beta.47", + "@babel/plugin-syntax-json-strings": "7.0.0-beta.47" + }, + "peerDependencies": { + "@babel/core": "7.0.0-beta.47" + }, + "devDependencies": { + "@babel/core": "7.0.0-beta.47", + "@babel/helper-plugin-test-runner": "7.0.0-beta.47" + } +} diff --git a/packages/babel-plugin-proposal-json-strings/src/index.js b/packages/babel-plugin-proposal-json-strings/src/index.js new file mode 100644 index 0000000000..dd555f98d0 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/src/index.js @@ -0,0 +1,29 @@ +import { declare } from "@babel/helper-plugin-utils"; +import syntaxJsonStrings from "@babel/plugin-syntax-json-strings"; + +export default declare(api => { + api.assertVersion(7); + const regex = /(\\*)([\u2028\u2029])/g; + function replace(match, escapes, separator) { + // If there's an odd number, that means the separator itself was escaped. + // "\X" escapes X. + // "\\X" escapes the backslash, so X is unescaped. + const isEscaped = escapes.length % 2 === 1; + if (isEscaped) return match; + + return `${escapes}\\u${separator.charCodeAt(0).toString(16)}`; + } + + return { + inherits: syntaxJsonStrings, + + visitor: { + "DirectiveLiteral|StringLiteral"({ node }) { + const { extra } = node; + if (!extra || !extra.raw) return; + + extra.raw = extra.raw.replace(regex, replace); + }, + }, + }; +}); diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/exec.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/exec.js new file mode 100644 index 0000000000..f15f17bc05 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/exec.js @@ -0,0 +1,5 @@ +"before
after"; +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') +"
"; // Just a U+2028 LINE SEPARATOR +"\
"; // Escaped U+2028 LINE SEPARATOR +"\u2028"; // Escaped U+2028 LINE SEPARATOR diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/input.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/input.js new file mode 100644 index 0000000000..f15f17bc05 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/input.js @@ -0,0 +1,5 @@ +"before
after"; +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') +"
"; // Just a U+2028 LINE SEPARATOR +"\
"; // Escaped U+2028 LINE SEPARATOR +"\u2028"; // Escaped U+2028 LINE SEPARATOR diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/output.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/output.js new file mode 100644 index 0000000000..6ecbb284cd --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-line-separator/output.js @@ -0,0 +1,7 @@ +"before\u2028after"; // ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') + +"\u2028"; // Just a U+2028 LINE SEPARATOR + +"\
"; // Escaped U+2028 LINE SEPARATOR + +"\u2028"; // Escaped U+2028 LINE SEPARATOR diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/exec.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/exec.js new file mode 100644 index 0000000000..481ccfee88 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/exec.js @@ -0,0 +1,5 @@ +"before
after"; +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') +"
"; // Just a U+2029 PARAGRAPH SEPARATOR +"\
"; // Escaped U+2029 PARAGRAPH SEPARATOR +"\u2029"; // Escaped U+2029 PARAGRAPH SEPARATOR diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/input.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/input.js new file mode 100644 index 0000000000..481ccfee88 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/input.js @@ -0,0 +1,5 @@ +"before
after"; +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') +"
"; // Just a U+2029 PARAGRAPH SEPARATOR +"\
"; // Escaped U+2029 PARAGRAPH SEPARATOR +"\u2029"; // Escaped U+2029 PARAGRAPH SEPARATOR diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/output.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/output.js new file mode 100644 index 0000000000..198071423a --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/directive-paragraph-separator/output.js @@ -0,0 +1,7 @@ +"before\u2029after"; // ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') + +"\u2029"; // Just a U+2029 PARAGRAPH SEPARATOR + +"\
"; // Escaped U+2029 PARAGRAPH SEPARATOR + +"\u2029"; // Escaped U+2029 PARAGRAPH SEPARATOR diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/exec.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/exec.js new file mode 100644 index 0000000000..7f689f645f --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/exec.js @@ -0,0 +1,27 @@ +expect("\u2028".length).toBe(1); +expect("\u2028").toBe("\u2028"); + + +expect("before
after".length).toBe(12); +expect("before
after").toBe("before\u2028after"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') + +expect("
".length).toBe(1); +expect("
").toBe("\u2028"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\
".length).toBe(0); +expect("\
").toBe(""); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\
".length).toBe(2); +expect("\\
").toBe("\\\u2028"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\\
".length).toBe(1); +expect("\\\
").toBe("\\"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\\\
".length).toBe(3); +expect("\\\\
").toBe("\\\\\u2028"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/input.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/input.js new file mode 100644 index 0000000000..7f689f645f --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/input.js @@ -0,0 +1,27 @@ +expect("\u2028".length).toBe(1); +expect("\u2028").toBe("\u2028"); + + +expect("before
after".length).toBe(12); +expect("before
after").toBe("before\u2028after"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') + +expect("
".length).toBe(1); +expect("
").toBe("\u2028"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\
".length).toBe(0); +expect("\
").toBe(""); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\
".length).toBe(2); +expect("\\
").toBe("\\\u2028"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\\
".length).toBe(1); +expect("\\\
").toBe("\\"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\\\
".length).toBe(3); +expect("\\\\
").toBe("\\\\\u2028"); +// ^ That's a U+2028 LINE SEPARATOR UTF-16 char diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/output.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/output.js new file mode 100644 index 0000000000..b0e41e9899 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-line-separator/output.js @@ -0,0 +1,19 @@ +expect("\u2028".length).toBe(1); +expect("\u2028").toBe("\u2028"); +expect("before\u2028after".length).toBe(12); +expect("before\u2028after").toBe("before\u2028after"); // ^ That's a U+2028 LINE SEPARATOR UTF-16 char (between 'before' and 'after') + +expect("\u2028".length).toBe(1); +expect("\u2028").toBe("\u2028"); // ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\
".length).toBe(0); +expect("\
").toBe(""); // ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\\u2028".length).toBe(2); +expect("\\\u2028").toBe("\\\u2028"); // ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\\
".length).toBe(1); +expect("\\\
").toBe("\\"); // ^ That's a U+2028 LINE SEPARATOR UTF-16 char + +expect("\\\\\u2028".length).toBe(3); +expect("\\\\\u2028").toBe("\\\\\u2028"); // ^ That's a U+2028 LINE SEPARATOR UTF-16 char diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/exec.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/exec.js new file mode 100644 index 0000000000..9a25519c3d --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/exec.js @@ -0,0 +1,27 @@ +expect("\u2029".length).toBe(1); +expect("\u2029").toBe("\u2029"); + + +expect("before
after".length).toBe(12); +expect("before
after").toBe("before\u2029after"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') + +expect("
".length).toBe(1); +expect("
").toBe("\u2029"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\
".length).toBe(0); +expect("\
").toBe(""); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\
".length).toBe(2); +expect("\\
").toBe("\\\u2029"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\\
".length).toBe(1); +expect("\\\
").toBe("\\"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\\\
".length).toBe(3); +expect("\\\\
").toBe("\\\\\u2029"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/input.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/input.js new file mode 100644 index 0000000000..9a25519c3d --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/input.js @@ -0,0 +1,27 @@ +expect("\u2029".length).toBe(1); +expect("\u2029").toBe("\u2029"); + + +expect("before
after".length).toBe(12); +expect("before
after").toBe("before\u2029after"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') + +expect("
".length).toBe(1); +expect("
").toBe("\u2029"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\
".length).toBe(0); +expect("\
").toBe(""); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\
".length).toBe(2); +expect("\\
").toBe("\\\u2029"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\\
".length).toBe(1); +expect("\\\
").toBe("\\"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\\\
".length).toBe(3); +expect("\\\\
").toBe("\\\\\u2029"); +// ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/output.js b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/output.js new file mode 100644 index 0000000000..01aca610fa --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/json-strings/string-paragraph-separator/output.js @@ -0,0 +1,19 @@ +expect("\u2029".length).toBe(1); +expect("\u2029").toBe("\u2029"); +expect("before\u2029after".length).toBe(12); +expect("before\u2029after").toBe("before\u2029after"); // ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char (between 'before' and 'after') + +expect("\u2029".length).toBe(1); +expect("\u2029").toBe("\u2029"); // ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\
".length).toBe(0); +expect("\
").toBe(""); // ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\\u2029".length).toBe(2); +expect("\\\u2029").toBe("\\\u2029"); // ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\\
".length).toBe(1); +expect("\\\
").toBe("\\"); // ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char + +expect("\\\\\u2029".length).toBe(3); +expect("\\\\\u2029").toBe("\\\\\u2029"); // ^ That's a U+2029 PARAGRAPH SEPARATOR UTF-16 char diff --git a/packages/babel-plugin-proposal-json-strings/test/fixtures/options.json b/packages/babel-plugin-proposal-json-strings/test/fixtures/options.json new file mode 100644 index 0000000000..eaf1a42a37 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/fixtures/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["proposal-json-strings"] +} diff --git a/packages/babel-plugin-proposal-json-strings/test/index.js b/packages/babel-plugin-proposal-json-strings/test/index.js new file mode 100644 index 0000000000..1b534b8fc6 --- /dev/null +++ b/packages/babel-plugin-proposal-json-strings/test/index.js @@ -0,0 +1,3 @@ +import runner from "@babel/helper-plugin-test-runner"; + +runner(__dirname); diff --git a/packages/babel-plugin-syntax-json-strings/.npmignore b/packages/babel-plugin-syntax-json-strings/.npmignore new file mode 100644 index 0000000000..f980694583 --- /dev/null +++ b/packages/babel-plugin-syntax-json-strings/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-syntax-json-strings/README.md b/packages/babel-plugin-syntax-json-strings/README.md new file mode 100644 index 0000000000..ba92be5713 --- /dev/null +++ b/packages/babel-plugin-syntax-json-strings/README.md @@ -0,0 +1,35 @@ +# @babel/plugin-syntax-json-strings + +Allow parsing of the U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR in JS strings + +## Installation + +```sh +npm install --save-dev @babel/plugin-syntax-json-strings +``` + +## Usage + +### Via `.babelrc` (Recommended) + +**.babelrc** + +```json +{ + "plugins": ["@babel/plugin-syntax-json-strings"] +} +``` + +### Via CLI + +```sh +babel --plugins @babel/plugin-syntax-json-strings script.js +``` + +### Via Node API + +```javascript +require("@babel/core").transform("code", { + plugins: ["@babel/plugin-syntax-json-strings"] +}); +``` diff --git a/packages/babel-plugin-syntax-json-strings/package.json b/packages/babel-plugin-syntax-json-strings/package.json new file mode 100644 index 0000000000..4d9f9736bd --- /dev/null +++ b/packages/babel-plugin-syntax-json-strings/package.json @@ -0,0 +1,20 @@ +{ + "name": "@babel/plugin-syntax-json-strings", + "version": "7.0.0-beta.47", + "description": "Allow parsing of the U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR in JS strings", + "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-json-strings", + "license": "MIT", + "main": "lib/index.js", + "keywords": [ + "babel-plugin" + ], + "dependencies": { + "@babel/helper-plugin-utils": "7.0.0-beta.47" + }, + "peerDependencies": { + "@babel/core": "7.0.0-beta.47" + }, + "devDependencies": { + "@babel/core": "7.0.0-beta.47" + } +} diff --git a/packages/babel-plugin-syntax-json-strings/src/index.js b/packages/babel-plugin-syntax-json-strings/src/index.js new file mode 100644 index 0000000000..c6200a4b17 --- /dev/null +++ b/packages/babel-plugin-syntax-json-strings/src/index.js @@ -0,0 +1,11 @@ +import { declare } from "@babel/helper-plugin-utils"; + +export default declare(api => { + api.assertVersion(7); + + return { + manipulateOptions(opts, parserOpts) { + parserOpts.plugins.push("jsonStrings"); + }, + }; +}); diff --git a/packages/babel-preset-stage-3/package.json b/packages/babel-preset-stage-3/package.json index 0cfced9d58..e52474bb76 100644 --- a/packages/babel-preset-stage-3/package.json +++ b/packages/babel-preset-stage-3/package.json @@ -11,6 +11,7 @@ "@babel/helper-plugin-utils": "7.0.0-beta.47", "@babel/plugin-proposal-async-generator-functions": "7.0.0-beta.47", "@babel/plugin-proposal-class-properties": "7.0.0-beta.47", + "@babel/plugin-proposal-json-strings": "7.0.0-beta.47", "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.47", "@babel/plugin-proposal-optional-catch-binding": "7.0.0-beta.47", "@babel/plugin-proposal-unicode-property-regex": "7.0.0-beta.47", diff --git a/packages/babel-preset-stage-3/src/index.js b/packages/babel-preset-stage-3/src/index.js index 439742c957..4562067b4e 100644 --- a/packages/babel-preset-stage-3/src/index.js +++ b/packages/babel-preset-stage-3/src/index.js @@ -3,6 +3,7 @@ import syntaxDynamicImport from "@babel/plugin-syntax-dynamic-import"; import syntaxImportMeta from "@babel/plugin-syntax-import-meta"; import transformAsyncGeneratorFunctions from "@babel/plugin-proposal-async-generator-functions"; import transformClassProperties from "@babel/plugin-proposal-class-properties"; +import transformJsonStrings from "@babel/plugin-proposal-json-strings"; import transformObjectRestSpread from "@babel/plugin-proposal-object-rest-spread"; import transformOptionalCatchBinding from "@babel/plugin-proposal-optional-catch-binding"; import transformUnicodePropertyRegex from "@babel/plugin-proposal-unicode-property-regex"; @@ -33,6 +34,7 @@ export default declare((api, opts) => { syntaxImportMeta, transformAsyncGeneratorFunctions, [transformClassProperties, { loose }], + transformJsonStrings, [transformObjectRestSpread, { loose, useBuiltIns }], transformOptionalCatchBinding, transformUnicodePropertyRegex,