Closed pedrobslisboa closed 7 months ago
The latest updates on your projects. Learn more about Vercel for Git ↗︎
This looks good so far! Though, there's one quirk about the style tag rendering that I misspoke about in the screenshot above. The expected output should actually look like this:
<style data-emotion="css id123-someName" data-s>
.css-id123-someName { }
</style>
Basically, the IDs used in data-emotion
should not have the css-
prefix. Also, to keep consistent with emotion's client-side behaviour maybe data-s
could go second?
To my knowledge, Stylesheet.get_all
already returns names prefixed with css-
, so the only way to extract the IDs is to mechanically chop the prefix, which works, but is a little unsafe. Thoughts, @davesnx?
Probably best to add the prefix where it matters only, and render here without any change.
Do you know why emotion doesn't need the "css-" prefix here?
This looks good so far! Though, there's one quirk about the style tag rendering that I misspoke about in the screenshot above. The expected output should actually look like this:
<style data-emotion="css id123-someName" data-s> .css-id123-someName { } </style>
Basically, the IDs used in
data-emotion
should not have thecss-
prefix. Also, to keep consistent with emotion's client-side behaviour maybedata-s
could go second?To my knowledge,
Stylesheet.get_all
already returns names prefixed withcss-
, so the only way to extract the IDs is to mechanically chop the prefix, which works, but is a little unsafe. Thoughts, @davesnx?
@purefunctor What about the animation-
prefix? Does it need to be removed?
Do you know why emotion doesn't need the "css-" prefix here?
I'm not entirely sure myself, maybe it's just how emotion encodes it? Ultimately it sees the prefix already as the first word under data-emotion
.
What about the animation- prefix? Does it need to be removed?
Not sure as well, it's be good to check but I won't be able to until tomorrow!
Probably best to add the prefix where it matters only, and render here without any change.
Do you know why emotion doesn't need the "css-" prefix here?
Were you talking about something like this?
- let pp_keyframes hash keyframes =
+ let pp_keyframes preffix hash keyframes =
let pp_keyframe (percentage, rules) =
Printf.sprintf "%i%% { %s }" percentage (render_declarations rules)
in
let definition = keyframes |> List.map pp_keyframe |> String.concat " " in
- Printf.sprintf "@keyframes %s { %s }" hash definition
+ Printf.sprintf "@keyframes %s-%s { %s }" preffix hash definition
(* ... *)
(* `resolved_rule` here means to print valid CSS, selectors are nested
and properties aren't autoprefixed. This function transforms into correct CSS. *)
- let pp_rules hash rules =
+ let pp_keyframes preffix hash keyframes =
(* TODO: Refactor with partition or partition_map. List.filter_map is error prone.
Ss might need to respect the order of definition, and this breaks the order *)
let list_of_rules = rules |> resolve_selectors in
let declarations =
list_of_rules
|> List.map Autoprefixer.prefix
|> List.flatten
|> List.filter_map render_declaration
|> String.concat " "
- |> fun all -> Printf.sprintf ".%s { %s }" hash all
+ |> Printf.sprintf "@keyframes %s-%s { %s }" preffix hash definition
in
(* ... *)
- let render_hash prefix hash styles =
+ let render_hash hash styles =
let is_label = function D ("label", value) -> Some value | _ -> None in
match List.find_map is_label styles with
- | None -> Printf.sprintf "%s-%s" prefix hash
- | Some label -> Printf.sprintf "%s-%s-%s" prefix hash label
+ | None -> Printf.sprintf "%s" hash
+ | Some label -> Printf.sprintf "%s-%s" hash label
let style (styles : rule list) =
match styles with
| [] -> ""
| _ ->
+ let type_ = "css"
let hash = Emotion_hash.Hash.default (rules_to_string styles) in
- let className = render_hash "css" hash styles in
+ let className = render_hash hash styles in
Stylesheet.push instance (type_, className, Classnames styles);
- className
+ Printf.sprintf "%s-%s" type_ className
let keyframes (keyframes : (int * rule list) list) =
match keyframes with
| [] -> ""
| _ ->
+ let type_ = "animation"
let hash = Emotion_hash.Hash.default (keyframes_to_string keyframes) in
Stylesheet.push instance (type_, hash, Keyframes keyframes);
- animationName
+ "Printf.sprintf "%s-%s" type_ animationName
let get_style_rules () =
Stylesheet.get_all instance
|> List.fold_left
(fun accumulator (type_, hash, rules) ->
match rules with
| Classnames rules ->
let rules = pp_rules type_ hash rules |> String.trim in
Printf.sprintf "%s %s" hash rules
| Keyframes keyframes ->
let rules = pp_keyframes type_ hash keyframes |> String.trim in
Printf.sprintf "%s %s" hash rules)
""
|> String.trim
Here's an initial fix I came up with, it doesn't account for animations yet: https://github.com/purefunctor/styled-ppx/commit/3032deec06c52be6ab2f6997ddeeda1d40d3f5fd
Okay, so with animations, here's what @emotion/server
emits on my SSR script. They're stuffed under the css-global
namespace with the hashes (as expected):
<style data-emotion="css-global 1acbpvw">
@-webkit-keyframes animation-1acbpvw {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes animation-1acbpvw {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>
I also discovered that for [%styled.global ...]
styles, emotion emits the following, though I'm not entirely sure where it got the hash from.
<style data-emotion="css-global 1dvid4v">
body {
background-color: #1F1F1F;
color: #F5F5F5;
margin: 0;
padding: 0;
}
#root {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
box-sizing: border-box;
padding: 1rem;
min-height: 100vh;
}
#root>main {
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1;
}
@media screen and (min-width: 768px) {
#root {
max-width: 900px;
margin-left: auto;
margin-right: auto;
}
}
</style>
@davesnx I have to issue a mea culpa for not testing it on a project using a reasonml SSR. I'm going to take the @purefunctor details and going to make some changes and test it on a side project. As soon as I have it I'll push to this PR.
⚠️ To my future me ⚠️
It would be nice to have a demo of this feature on styleppx
Why
As mentioned by @purefunctor it would be nice to have full SSR support on styled-ppx:
That way the user doesn't need to create a function to handle it and it will work out of the box by the library.
How
render_style_tag
since it doesn't render a tag but the style rules;get_string_style_rules
based onrender_style_tag
;get_string_style_hashes
to get all hashes;render_style_html_tag
to deliver a full SSR-supported style tag.<style data-s data-emotion="css className1">.css-className1 { display: block; }</style>
Attention, this branch is a extension of this one: https://github.com/davesnx/styled-ppx/pull/468
Screenshot
The screenshot below shows how the emotion handles it well, only creating on client size only client styles the universal styles were not recreated.