styled-components / vim-styled-components

Vim bundle for http://styled-components.com based javascript files.
300 stars 24 forks source link

Nested template literals with interpolations breaks highlighting #22

Closed emilgoldsmith closed 6 years ago

emilgoldsmith commented 7 years ago

screenshot from 2017-07-11 13-33-08

The nested interpolation is somehow seen as the closing interpolation for the outside interpolation. I'm assuming it's a problem with this package, thought it could be with YAJS.vim

fleischie commented 7 years ago

Hi, yes this is definitely a problem with this package.

I cannot offer an immediate solution, as these things are really hard to debug. I will keep it in mind though, when I find the time to work on this. 🙂

In the meantime: Try to refactor your functions (less nesting, more testing) 🙂

function retrieveHeightOrGiveMeNothing(props) {
  if (props.height) {
    return `height: ${props.height}`;
  }

  return '';
}

function retrieveWidthOrGiveMeNothing(props) {
  if (props.width) {
    return `width: ${props.width}`;
  }

  return '';
}

const DropdownArrow = styled.img.attrs({
  src: '/static/images/material_dropdown_arrow.svg',
})`
  color: ${props => props.color};
  ${retrieveHeightOrGiveMeNothing};
  ${retrieveWidthOrGiveMeNothing};
`;

Or alternatively:

const DropdownArrow = styled.img.attrs({
  src: '/static/images/material_dropdown_arrows.svg',
})`
  color: ${props => props.color};
  height: ${props => props.height ? props.height : 'auto'};
  width: ${props => props.width ? props.width : 'auto'};
`;

This works as well, as 'auto' is the default value for unset height/width attributes (had to look it up, though 😛 ). I know this is not the answer you hoped for, but I hope this helps you in the immediate problem you are having.

Disclaimer: I wrote both approaches just from the top of my mind and did not test, them.

emilgoldsmith commented 7 years ago

Hi @fleischie no problem :). I understand the troubles of maintaining a package!

Yeah my quick fix was actually exactly doing a refactor ;). Already implemented!

/**
 * Delivers css props to a styled component. It returns a function that when
 * interpolated in a styled component tagged template literal will return
 * `${cssProperty}: ${this.props[propName]};}` note the included semi-colon at the end.
 * If only propName is supplied (or if cssProperty is falsy) it is assumed
 * the prop name coincides with the css property * to be set.
 *
 * If the prop isn't supplied (this.props[propName] is falsy) the delivery function will
 * return ''.
 *
 * @param {string} propName - key of css prop in this.props
 * @param {string} [cssProperty] - The css property the prop value should be assigned to
 */
export const propDeliverer = (propName, cssProperty) => {
  let processedProperty = cssProperty || propName;

  return props => (
    props[propName]
      ? `${processedProperty}: ${props[propName]};`
      : ''
  );
};

And it now looks like this:

const DropdownArrow = styled(ArrowSVG)`
  ${propDeliverer('height')}
  ${propDeliverer('width')}

  > path {
    ${propDeliverer('color', 'fill')}
  }
`;

Much nicer!

(Also changed to inlining the svg :) )

fleischie commented 6 years ago

I am torn, whether to close this issue (as it seems to be resolved) and keeping it open (as it seems to be a still active larger-scale issue).

...

I think I'll close it and maybe re-open, if it re-surfaces. 🤷‍♂️