elm-css icon indicating copy to clipboard operation
elm-css copied to clipboard

No hash collision handling

Open robinheghan opened this issue 7 years ago • 8 comments

So, if I read the following right, in the rare occurance that you get a hash collision (two different pieces of text giving the same hash) the behaviour of elm-css would be... wonky? Might be worth adding a counter to every classname, just in case.

https://github.com/rtfeldman/elm-css/blob/1026935356eaecee09c1fd14e4da90df3532f08a/src/Html/Styled/Internal.elm#L59

robinheghan avatar Nov 14 '17 19:11 robinheghan

A counter? Can you clarify what you mean by that? 🤔

rtfeldman avatar Nov 15 '17 03:11 rtfeldman

Well. .hashString could, in theory, result in the same hash for { display: inline-block; } and { display: block; } (probably not, but two different pieces of text could result in the same hash). Adding a counter to the end of classnames, like s0m3hash01 and s0m3hash02 would avoid this in the cases where it is an issue.

Of course, me being me, I forgot this is Elm and so it's not as straight forward as I made it sound due to pureness.

robinheghan avatar Nov 16 '17 10:11 robinheghan

A reasonable alternative to a counter that I've used for problems like this in the past is to add the length of the original string. Not perfect but considerably less likely to collide. You can take it further by doing something like a product of {count of certain letters in the string}

eeue56 avatar Nov 16 '17 12:11 eeue56

The main problem I see with the counter approach is duplication.

Suppose I write this:

viewListItem item =
    li [ css [ backgroundColor aliceblue ] ] [ text item.caption ]

view model =
    ul [] (List.map viewListItem model.items)

With the counter approach, I'm now getting N redundant class definitions outputted to my <style> and I'm probably not realizing it. That would be a nasty perf surprise I think.

The length approach doesn't have that problem, of course.

rtfeldman avatar Nov 16 '17 21:11 rtfeldman

I'm curious about doing something like what Atomic CSS does - that is, using shorthand string concatenation instead of hashing, e.g.

button
    [ css [ backgroundColor (hex "f00"), color (rgb 250 250 12), padding (px 20) ] ]
    [ text "Hi!" ]

would compile to:

<button class="Bgc(#f00)C(rgb(250_250_12)P(20px)">Hi!</button>

Besides removing the possibility for collisions, one upside of this approach would be that this would presumably run faster than computing a hash would.

One downside would be that when doing server-side rendering, this would generate significantly larger classnames for the browser to download and parse.

rtfeldman avatar Dec 04 '17 18:12 rtfeldman

I can think of a few more negatives.

  1. Longer class names clutters the browsers html debug view (minor inconvenience, admittedly )
  2. Code size for the final .js file would increase (I'm assuming this would take a relative large case...of statement to translate into shorthand strings).

I think @eeue56 suggestion is a good one. Appending the length of the CSS string, that is.

robinheghan avatar Dec 04 '17 19:12 robinheghan

Adding the length of a string is basically adding a very weak second hash algorithm. Isn't this the same as concatenating two hash algorithm results or using one but with longer result values?

andys8 avatar Dec 12 '17 17:12 andys8

It's a essentially a very weak salt. It's probably worth doing some maths to see how helpful it is for sure.

eeue56 avatar Dec 12 '17 23:12 eeue56