Pomax / svg-path-reverse

This is a JavaScript SVG path to "something" converter, turning a path into hookable graphics instructions for arbitrary conversion
59 stars 15 forks source link

Returns NaNs for certain inputs #8

Closed odub closed 2 years ago

odub commented 3 years ago

Hi, thanks for your work on this library

I noticed that reversing this particular path produces bad output:

> require('svg-path-reverse').reverse('M20.888 43.504c.027.07.074.119.139.144.067.028.131.037.191.026.07-.014.104-.041.104-.082V36.92c-.004-.024-.027-.062-.07-.114a.658.658 0 0 0-.173-.15c-.245-.153-.53-.185-.858-.098-.086.023-.17.051-.25.086a1.906 1.906 0 0 0-.546.364 1.923 1.923 0 0 0-.248.307c-.08.124-.15.261-.207.411a2.894 2.894 0 0 0-.14.53 4.011 4.011 0 0 0-.028 1.064c.018.133.037.256.06.37.022.112.057.234.103.367.048.133.09.245.127.338.036.093.09.206.16.339.072.132.13.238.17.315.044.076.108.183.194.32l.194.3.204.305c.155.233.271.41.349.53.078.12.169.276.274.467.107.193.19.37.25.533z')
'M NaN NaN C NaN NaN NaN NaN NaN NaN L NaN NaN C NaN NaN NaN NaN NaN NaN A 4.011 0 0 0 0 NaN NaN A 2.894 2.894 0 0 1 NaN NaN C NaN NaN NaN NaN NaN NaN A 1.923 0 0 0 0 NaN NaN A 1.906 1.906 0 0 1 NaN NaN C NaN NaN NaN 36.388000000000005 NaN 36.55800000000001 C NaN 36.471000000000004 NaN 36.50300000000001 NaN 36.656000000000006 A 0.658 0 0 0 0 NaN 36.806000000000004 C NaN 36.858000000000004 NaN 36.896 NaN 36.92 L NaN NaN C 20.847 43.422 20.915000000000003 43.489999999999995 20.888 43.504 Z'

I suspect could it be the - values? My other inputs up to this point have all worked great

Pomax commented 3 years ago

Hm, let me dig through the spec for path string parsing to figure out what your path string's even supposed to parse as. In all the years I've worked with SVG, this is literally the first time I'm seeing what you're showing. What produced it?

(the spec has this paragraph, which seems useful here: Similarly, for the string "M 0.6.5", the first coordinate of the "moveto" consumes the characters "0.6" and stops upon encountering the second decimal point because the production of a "coordinate" only allows one decimal point. The result is that the first coordinate will be "0.6" and the second coordinate will be ".5".)

odub commented 3 years ago

The input path was passed through svgo

After finding similar broken output from a bunch of other SVG parsers I only found one workaround in the end which was pretty nasty.

I used svgo's internal parser and some hacks on top of their serializer to get the path back into a less condensed form. I then used the expanded path that produced as input to this lib successfully.

https://github.com/svg/svgo/blob/master/lib/path.js#L135

I'm now left wondering whether these inputs should even have been supported in the first place. I don't have enough experience of the area to make that call, honestly. What do you think?

On Mon, 21 Jun 2021, 16:12 Pomax, @.***> wrote:

Hm, let me dig through the spec to figure out what your path string's even supposed to parse as. In all the years I've worked with SVG, this is literally the first time I'm seeing what you're showing. What produced it?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Pomax/svg-path-reverse/issues/8#issuecomment-865114038, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALVRPG3G2A2CEXTF57GK2TTT5JEFANCNFSM467KKO2Q .

Pomax commented 3 years ago

It's technically legal syntax, SVG path strings follow a kind of weird "parse a number until the next character can't be part of that number, and start a new on", which is super stupid if you want efficient value parsing (without forcing folks to roll their own DFA just for splitting values), but it's in the spec, so having tools support it would be useful.