Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printing parenthesized JSX nodes #211

Open
aaronjensen opened this issue Aug 25, 2015 · 3 comments
Open

Printing parenthesized JSX nodes #211

aaronjensen opened this issue Aug 25, 2015 · 3 comments

Comments

@aaronjensen
Copy link

Is it currently possible to print JSX nodes like so:

var x = (
  <div>
    {test}
  </div>
);

They seem to always print like:

var x = (<div>
  {test}
</div>);

http://felix-kling.de/esprima_ast_explorer/#/984sneJJn2

Thanks!

@aaronjensen
Copy link
Author

Probably related: #147

@milahu
Copy link

milahu commented Oct 30, 2022

same here

works for assign
breaks for return

function App(props) {
  //const div = ( // good
  return ( // bad
    <div className="app">
      hello {props.name}
    </div>
  );
  //return div;
}

but only when i transform the AST

good result: assign

function App(props) {
  const div = (
    <div class="app">
      hello {props.name}
    </div>
  );
  return div;
}

bad result: return

function App(props) {
  return (
    (<div class="app">hello{props.name}
    </div>)
  );
}

note: also whitespace in hello {props.name} is lost

demo

const putout = require("putout")

// good: assign
var source = `
function App(props) {
  const div = (
    <div className="app">
      hello {props.name}
    </div>
  );
  return div;
}
`;

// bad: return
var source = `
function App(props) {
  return (
    <div className="app">
      hello {props.name}
    </div>
  );
}
`;

console.log("input:\n" + source)

/* based on
https://github.com/coderaiser/putout/blob/master/packages/plugin-react-router/lib/convert-switch-to-routes/index.js
https://github.com/coderaiser/putout/blob/master/packages/plugin-react-hooks/lib/apply-short-fragment/index.js
*/
const myPlugin = {
  rules: {
    'jsx-classname-to-class': {
        report: () => `Use class instead of className attribute`,
        include: () => [
            'JSXOpeningElement',
        ],
        fix: (path) => {
            const attr = path.node.attributes.find(attr => attr.name.name == "className")
            attr.name.name = "class"
        },
        filter: (path) => {
            const hasClassName = !!path.node.attributes.find(attr => attr.name.name == "className")
            const hasClass = !!path.node.attributes.find(attr => attr.name.name == "class")
            return hasClassName && !hasClass
        },
    },
  }
}

const res = putout(source, {
    isTS: true,
    isJSX: true,
    //sourceFileName: 'input.tsx',
    processors: [
        //'typescript', // @putout/processor-typescript type checking for TypeScript code
    ],
    plugins: [
        //'typescript', // @putout/plugin-typescript transform TypeScript code
        ['my-plugin', myPlugin],
    ],
    rules: {
      // default: all rules are on
      //"my-plugin/jsx-classname-to-class": "on",
    }
});

console.log("output:\n" + res.code)

bug seems to be in

recast/lib/printer.ts

Lines 1305 to 1322 in f41dd8b

const childLines = concat(
path.map(function (childPath: any) {
const child = childPath.getValue();
if (
namedTypes.Literal.check(child) &&
typeof child.value === "string"
) {
if (/\S/.test(child.value)) {
return child.value.replace(/^\s+|\s+$/g, "");
} else if (/\n/.test(child.value)) {
return "\n";
}
}
return print(childPath);
}, "children"),
).indentTail(options.tabWidth);

child.type = "JSXText"
child.value = "\n      hello "
line 1314: "hello"

from

  return (
    <div class="app">
      hello {props.name}
    </div>
  );

the whitespace before </div>

child.value: "\n    "
line 1316: "\n"

return concat([openingLines, childLines, closingLines]);

openingLines = '    <div class="app">'
childLines = "hello{props.name}\n"
closingLines = "</div>"

in the "good" case, this code is not reached
instead, print seems to use the fast path

i guess the slow path is caused by adding parens at return ( ... )
but we already have parens around that expression

when parens are missing

return <div>
  asdf
</div>

then it should create a parens-block, indented by 2 spaces

return (
  <div>
    asdf
  </div>
)

@milahu
Copy link

milahu commented Oct 31, 2022

nevermind. im moving on to eslint as its more popular

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants