atom / etch

Builds components using a simple and explicit API around virtual-dom

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Some SVG attributes are stripped before rendering

mnquintana opened this issue · comments

Steps to reproduce:

  1. Try sticking this JSX in a component's render method:

    <svg className='about-logo' width='330px' height='68px' viewBox='0 0 330 68'>
      <g stroke='none' strokeWidth='1' fill='none' fillRule='evenodd'>
        <g transform='translate(2.000000, 1.000000)'>
          <g transform='translate(96.000000, 8.000000)' fill='currentColor'>
            <path d='M185.498,3.399 C185.498,2.417 186.34,1.573 187.324,1.573 L187.674,1.573 C188.447,1.573 189.01,1.995 189.5,2.628 L208.676,30.862 L227.852,2.628 C228.272,1.995 228.905,1.573 229.676,1.573 L230.028,1.573 C231.01,1.573 231.854,2.417 231.854,3.399 L231.854,49.403 C231.854,50.387 231.01,51.231 230.028,51.231 C229.044,51.231 228.202,50.387 228.202,49.403 L228.202,8.246 L210.151,34.515 C209.729,35.148 209.237,35.428 208.606,35.428 C207.973,35.428 207.481,35.148 207.061,34.515 L189.01,8.246 L189.01,49.475 C189.01,50.457 188.237,51.231 187.254,51.231 C186.27,51.231 185.498,50.458 185.498,49.475 L185.498,3.399 L185.498,3.399 Z'></path>
            <path d='M113.086,26.507 L113.086,26.367 C113.086,12.952 122.99,0.941 137.881,0.941 C152.77,0.941 162.533,12.811 162.533,26.225 L162.533,26.367 C162.533,39.782 152.629,51.792 137.74,51.792 C122.85,51.792 113.086,39.923 113.086,26.507 M158.74,26.507 L158.74,26.367 C158.74,14.216 149.89,4.242 137.74,4.242 C125.588,4.242 116.879,14.075 116.879,26.225 L116.879,26.367 C116.879,38.518 125.729,48.491 137.881,48.491 C150.031,48.491 158.74,38.658 158.74,26.507'></path>
            <path d='M76.705,5.155 L60.972,5.155 C60.06,5.155 59.287,4.384 59.287,3.469 C59.287,2.556 60.059,1.783 60.972,1.783 L96.092,1.783 C97.004,1.783 97.778,2.555 97.778,3.469 C97.778,4.383 97.005,5.155 96.092,5.155 L80.358,5.155 L80.358,49.405 C80.358,50.387 79.516,51.231 78.532,51.231 C77.55,51.231 76.706,50.387 76.706,49.405 L76.706,5.155 L76.705,5.155 Z'></path>
            <path d='M0.291,48.562 L21.291,3.05 C21.783,1.995 22.485,1.292 23.75,1.292 L23.891,1.292 C25.155,1.292 25.858,1.995 26.348,3.05 L47.279,48.421 C47.49,48.843 47.56,49.194 47.56,49.546 C47.56,50.458 46.788,51.231 45.803,51.231 C44.961,51.231 44.329,50.599 43.978,49.826 L38.219,37.183 L9.21,37.183 L3.45,49.897 C3.099,50.739 2.538,51.231 1.694,51.231 C0.781,51.231 0.008,50.529 0.008,49.685 C0.009,49.404 0.08,48.983 0.291,48.562 L0.291,48.562 Z M36.673,33.882 L23.749,5.437 L10.755,33.882 L36.673,33.882 L36.673,33.882 Z'></path>
          </g>
          <g>
            <path d='M40.363,32.075 C40.874,34.44 39.371,36.77 37.006,37.282 C34.641,37.793 32.311,36.29 31.799,33.925 C31.289,31.56 32.791,29.23 35.156,28.718 C37.521,28.207 39.851,29.71 40.363,32.075' fill='currentColor'></path>
            <path d='M48.578,28.615 C56.851,45.587 58.558,61.581 52.288,64.778 C45.822,68.076 33.326,56.521 24.375,38.969 C15.424,21.418 13.409,4.518 19.874,1.221 C22.689,-0.216 26.648,1.166 30.959,4.629' stroke='currentColor' strokeWidth='3.08' strokeLinecap='round'></path>
            <path d='M7.64,39.45 C2.806,36.94 -0.009,33.915 0.154,30.79 C0.531,23.542 16.787,18.497 36.462,19.52 C56.137,20.544 71.781,27.249 71.404,34.497 C71.241,37.622 68.127,40.338 63.06,42.333' stroke='currentColor' strokeWidth='3.08' strokeLinecap='round'></path>
            <path d='M28.828,59.354 C23.545,63.168 18.843,64.561 15.902,62.653 C9.814,58.702 13.572,42.102 24.296,25.575 C35.02,9.048 48.649,-1.149 54.736,2.803 C57.566,4.639 58.269,9.208 57.133,15.232' stroke='currentColor' strokeWidth='3.08' strokeLinecap='round'></path>
          </g>
        </g>
      </g>
    </svg>
  2. The fillRule and strokeWidth attributes (and others too, probably) are stripped from the rendered DOM element.

Are they also stripped when using them in the 'style'-attribute?

It's worth noting that virtual-dom's "attributes" are actually assigned as JavaScript properties on the underlying DOM nodes rather than HTML attributes. This is why you have to use the className property instead of class. For HTML elements, all the attributes correspond to properties. I don't think this is the case for SVG, however.

@BinaryMuse and @kuychaco ran into this issue using SVG in etch and came up with a workaround. Interested in their thoughts here.

Yeah virtual-dom's SVG support seems to be a bit weird. #17 added support for tags but did nothing to normalize attributes except for className. Perhaps they should be normalized to use the camelCase format other attributes use? We'd have to have a list of them and do them manually (à la React) to handle them.

Here's an example of an SVG component that we got working; notice the use of stroke-width and stroke-linecap instead of strokeWidth and strokeLinecap

'use babel'
/** @jsx etch.dom */

import etch from 'etch'

import stateless from 'etch-stateless'

export default stateless(etch, () => {
  // Inline SVG so the icon can be styled with CSS
  return (
    <svg className='icon-svg icon-atom' viewBox='0 0 64 64'>
      <g stroke='none' stroke-width={1} fill='none' fillRule='evenodd'>
        <g transform='translate(1.640625 4.170573)'>
          <path stroke='currentColor' stroke-width={3} stroke-linecap='round' d='M41.1546628,24.0016159 C48.1314158,38.3143746 49.5709562,51.8023702 44.283365,54.4984514 C38.8313273,57.2797075 28.2924076,47.5351914 20.7438863,32.7341528 C13.195365,17.9331141 11.4960833,3.6802309 16.9481211,0.899818142 C19.3220556,-0.311183594 22.6607435,0.853435764 26.2962786,3.77468229' />
          <path stroke='currentColor' stroke-width={3} stroke-linecap='round' d='M6.63099349,33.1397878 C2.5552474,31.0222214 0.181312934,28.4720339 0.317930122,25.8366714 C0.635860243,19.7243173 14.3448047,15.4697882 30.9370464,16.3325004 C47.5292882,17.196056 60.7221233,22.8504896 60.4041931,28.9628438 C60.2667326,31.5982062 57.6406467,33.887809 53.3675647,35.5710677' />
          <path stroke='currentColor' stroke-width={3} stroke-linecap='round' d='M24.4991723,49.9251489 C20.043934,53.141556 16.0786623,54.3162951 13.5984701,52.7064049 C8.46436241,49.3753069 11.6335438,35.3762617 20.6772643,21.4379353 C29.7209848,7.50045226 41.2145382,-1.0979974 46.3486458,2.23394401 C48.73523,3.78227214 49.3272378,7.63538281 48.3692309,12.7155182' />
          <path fill='currentColor' d='M34.226822,26.9194891 C34.6577565,28.9139314 33.3902526,30.879701 31.3958103,31.3106354 C29.4013681,31.7415699 27.4355985,30.474066 27.0046641,28.4796237 C26.5745729,26.4851814 27.8412335,24.5194119 29.8356758,24.0884774 C31.8292747,23.657543 33.7950443,24.9250469 34.226822,26.9194891' />
        </g>
      </g>
    </svg>
  )
})

@BinaryMuse So am I understanding correctly that for SVG elements they interpret the attributes as actual attributes rather than DOM node properties?

@nathansobo Yeah that's correct; anything using the svg function (which Etch delegates to automatically based on tag name) uses attributes. See https://github.com/Raynos/virtual-hyperscript/blob/5aac9c75d3e3286755d14901ad717933a07e9f0a/svg.js#L23

I've implemented a PR to normalize attribute names if people wanna take a gander.