formatTreeNode.js.flow 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /* @flow */
  2. import formatReactElementNode from './formatReactElementNode';
  3. import formatReactFragmentNode from './formatReactFragmentNode';
  4. import type { Options } from './../options';
  5. import type { TreeNode } from './../tree';
  6. const jsxStopChars = ['<', '>', '{', '}'];
  7. const shouldBeEscaped = (s: string) =>
  8. jsxStopChars.some(jsxStopChar => s.includes(jsxStopChar));
  9. const escape = (s: string) => {
  10. if (!shouldBeEscaped(s)) {
  11. return s;
  12. }
  13. return `{\`${s}\`}`;
  14. };
  15. const preserveTrailingSpace = (s: string) => {
  16. let result = s;
  17. if (result.endsWith(' ')) {
  18. result = result.replace(/^(.*?)(\s+)$/, "$1{'$2'}");
  19. }
  20. if (result.startsWith(' ')) {
  21. result = result.replace(/^(\s+)(.*)$/, "{'$1'}$2");
  22. }
  23. return result;
  24. };
  25. export default (
  26. node: TreeNode,
  27. inline: boolean,
  28. lvl: number,
  29. options: Options
  30. ): string => {
  31. if (node.type === 'number') {
  32. return String(node.value);
  33. }
  34. if (node.type === 'string') {
  35. return node.value
  36. ? `${preserveTrailingSpace(escape(String(node.value)))}`
  37. : '';
  38. }
  39. if (node.type === 'ReactElement') {
  40. return formatReactElementNode(node, inline, lvl, options);
  41. }
  42. if (node.type === 'ReactFragment') {
  43. return formatReactFragmentNode(node, inline, lvl, options);
  44. }
  45. throw new TypeError(`Unknow format type "${node.type}"`);
  46. };