Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render to key/value pairs #208

Open
polux opened this issue Jun 11, 2020 · 11 comments
Open

Render to key/value pairs #208

polux opened this issue Jun 11, 2020 · 11 comments

Comments

@polux
Copy link

polux commented Jun 11, 2020

It would be great if in addition to rendering to text, clay could also "render" to something more structured. That way it could be used as a DSL for inline CSS in combination with libraries like miso for instance.

@turion
Copy link
Collaborator

turion commented Jun 12, 2020

That's a cool idea. What data structure would you propose clay should render to?

@polux
Copy link
Author

polux commented Jun 12, 2020

In my particular case I'm interested in getting a Map String String that I can pass to miso's style attribute. But to make it generic enough that it's usable with other libs, I'd say any json-like structure that represents the AST of the CSS. Does that make sense?

@turion
Copy link
Collaborator

turion commented Jun 14, 2020

Yep, that makes a lot of sense. You mean https://hackage.haskell.org/package/miso-0.21.2.0/docs/Miso-Html.html#v:style_, right?

Clay itself basically collects a list of Rules (see http://hackage.haskell.org/package/clay-0.13.1/docs/Clay-Stylesheet.html#t:Rule). If you can write a function Rule -> Map String String, then you're halfway done.

I'm not sure this should be part of the clay package, or rather a separate clay-miso package. Either way I'm fine with adding such code to this github repo, even if it's a separate package.

@turion
Copy link
Collaborator

turion commented Jun 14, 2020

But to make it generic enough that it's usable with other libs

That can be a long-term goal, but let's first solve the immediate problem and connect clay to miso. The next step can be refactoring and connecting to other frameworks.

@polux
Copy link
Author

polux commented Jun 15, 2020

Yep, that makes a lot of sense. You mean https://hackage.haskell.org/package/miso-0.21.2.0/docs/Miso-Html.html#v:style_, right?

Yes!

Clay itself basically collects a list of Rules (see http://hackage.haskell.org/package/clay-0.13.1/docs/Clay-Stylesheet.html#t:Rule). If you can write a function Rule -> Map String String, then you're halfway done.

Exactly, I had looked for that in the code of clay but it seems that such an intermediate map doesn't exist: the list of rules is converted to a Builder immediately.

I'm not sure this should be part of the clay package, or rather a separate clay-miso package. Either way I'm fine with adding such code to this github repo, even if it's a separate package.

That would be definitely simpler at first. But don't you think a function of type Rule -> Map String String would make sense in the clay package itself? Another thing I wasn't sure about is that I suppose that some rules don't make sense for an inline style (like keyframes, I don't think you can define them inline?). So that function in clay-miso would have to be partial.

@turion
Copy link
Collaborator

turion commented Jun 15, 2020

Clay itself basically collects a list of Rules (see http://hackage.haskell.org/package/clay-0.13.1/docs/Clay-Stylesheet.html#t:Rule). If you can write a function Rule -> Map String String, then you're halfway done.

Exactly, I had looked for that in the code of clay but it seems that such an intermediate map doesn't exist: the list of rules is converted to a Builder immediately.

No, this map doesn't exist yet, someone needs to implement it. Maybe you? :D

I'm not sure this should be part of the clay package, or rather a separate clay-miso package. Either way I'm fine with adding such code to this github repo, even if it's a separate package.

That would be definitely simpler at first. But don't you think a function of type Rule -> Map String String would make sense in the clay package itself?

It would make more sense if the resulting map is used in some way, but I can't see how the map is sufficient information to recover the whole well-readable rendering that clay produces. clay outputs human-readable CSS, but such a map is too much of a machine format, I think.

But let's start with a small step first, and implement the function. As you suggest, let's add it to Clay.Render. If we notice feature creep, we can still move it to a separate package.

Another thing I wasn't sure about is that I suppose that some rules don't make sense for an inline style (like keyframes, I don't think you can define them inline?). So that function in clay-miso would have to be partial.

Hmm, I think that's best done as a separate endofunction either on Rule oder Map String String that deletes all inapplicable rules. I wouldn't include that at first, but you're welcome to open a separate follow-up issue then.

@polux
Copy link
Author

polux commented Jun 15, 2020

Hmm, I think that's best done as a separate endofunction either on Rule oder Map String String that deletes all inapplicable rules. I wouldn't include that at first, but you're welcome to open a separate follow-up issue then.

Actually I don't think we can do without it: other than Property I'm not sure how to translate other constructors of Rule into entries of a Map String String.

@polux
Copy link
Author

polux commented Jun 15, 2020

Actually, the low-level constructors for attributes are public in Miso, so I guess I could define my own style attribute that takes a Text rendered by clay. It is probably way simpler than re-factoring clay's rendering to output a map.

@polux
Copy link
Author

polux commented Jun 16, 2020

My bad, haddock makes it look like the low-level constructors are exposed but they aren't.

@bsima
Copy link
Contributor

bsima commented Mar 26, 2021

@polux FWIW Here is a hacky way to integration Miso and Clay that I came up with a while back, it worked well enough for a medium-sized project with lots of client-side stuff:

-- | Put 'Clay.Css' into a Miso-compatible style property.
--
-- Allows us to use any amount of CSS written with Clay inlined in HTML or
-- dynamically as JavaScript object properties. The implementation is a bit
-- hacky, but works.
css :: Clay.Css -> Attribute action
css = Miso.style_ . Map.fromList . f . Clay.renderWith Clay.htmlInline []
  where
    f :: L.Text -> [(MisoString, MisoString)]
    f t =
      L.splitOn ";" t
        <&> L.splitOn ":"
        <&> \(x : y) -> (toMisoString x, toMisoString $ L.intercalate ":" y)

Copy link

This issue has not seen any activity in a long time. If no further activity occurs, it will be closed after ten weeks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants