From 54c75eed0ba5871788865357b71666b308a808ec Mon Sep 17 00:00:00 2001 From: Nick Messing <dot.nick.dot.messing@gmail.com> Date: Tue, 8 Jan 2019 12:04:06 +0200 Subject: [PATCH] fix: Trim whitespaces properly, fix #37 --- .../src/index.js | 60 ++++++++++++++----- .../test/snapshot.js | 13 +++- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/packages/babel-plugin-transform-vue-jsx/src/index.js b/packages/babel-plugin-transform-vue-jsx/src/index.js index 424a0a9..787b486 100644 --- a/packages/babel-plugin-transform-vue-jsx/src/index.js +++ b/packages/babel-plugin-transform-vue-jsx/src/index.js @@ -65,9 +65,9 @@ const getTag = (t, path) => { */ const getChildren = (t, paths) => paths - .map((path, index) => { + .map(path => { if (path.isJSXText()) { - return transformJSXText(t, path, index === 0 ? -1 : index === paths.length - 1 ? 1 : 0) + return transformJSXText(t, path) } if (path.isJSXExpressionContainer()) { return transformJSXExpressionContainer(t, path) @@ -374,24 +374,56 @@ const transformJSXMemberExpression = (t, path) => { return t.memberExpression(transformedObject, transformedProperty) } -/** - * Trim text from JSX expressions depending on position - * @param string string - * @param position -1 for left, 0 for middle and 1 for right - * @returns string - */ -const trimText = (string, position) => (position === 0 ? string : string.replace(position === -1 ? /^\s*/ : /\s*$/, '')) - /** * Transform JSXText to StringLiteral * @param t * @param path JSXText - * @param position -1 for left, 0 for middle and 1 for right * @returns StringLiteral */ -const transformJSXText = (t, path, position) => { - const string = trimText(path.get('value').node, position) - return string ? t.stringLiteral(string) : null +const transformJSXText = (t, path) => { + const node = path.node + const lines = node.value.split(/\r\n|\n|\r/) + + let lastNonEmptyLine = 0 + + for (let i = 0; i < lines.length; i++) { + if (lines[i].match(/[^ \t]/)) { + lastNonEmptyLine = i + } + } + + let str = '' + + for (let i = 0; i < lines.length; i++) { + const line = lines[i] + + const isFirstLine = i === 0 + const isLastLine = i === lines.length - 1 + const isLastNonEmptyLine = i === lastNonEmptyLine + + // replace rendered whitespace tabs with spaces + let trimmedLine = line.replace(/\t/g, ' ') + + // trim whitespace touching a newline + if (!isFirstLine) { + trimmedLine = trimmedLine.replace(/^[ ]+/, '') + } + + // trim whitespace touching an endline + if (!isLastLine) { + trimmedLine = trimmedLine.replace(/[ ]+$/, '') + } + + if (trimmedLine) { + if (!isLastNonEmptyLine) { + trimmedLine += ' ' + } + + str += trimmedLine + } + } + + return str !== '' ? t.stringLiteral(str) : null } /** diff --git a/packages/babel-plugin-transform-vue-jsx/test/snapshot.js b/packages/babel-plugin-transform-vue-jsx/test/snapshot.js index 7b6f90b..1738aee 100644 --- a/packages/babel-plugin-transform-vue-jsx/test/snapshot.js +++ b/packages/babel-plugin-transform-vue-jsx/test/snapshot.js @@ -58,8 +58,17 @@ render(h => [h(Alpha, ["test"]), h("Beta", ["test"])]);`, }, { name: 'Combined content', - from: `render(h => <div> test{test} {...test}<br/> </div>)`, - to: `render(h => h("div", ["test", test, " ", ...test, h("br")]));`, + from: `render(h => <div> + test{test} {...test} + <tag1 /> + <tag2 /> + + Some text + goes here + + +</div>)`, + to: `render(h => h("div", ["test", test, " ", ...test, h("tag1"), h("tag2"), "Some text goes here"]));`, }, { name: 'Plain attrs',