Mc-Zen / tidy

A documentation generator for Typst in Typst.
https://typst.app/universe/package/tidy
MIT License
55 stars 2 forks source link

Remove `show-example` default #27

Open TimeTravelPenguin opened 3 weeks ago

TimeTravelPenguin commented 3 weeks ago

Hi, I am working on the package Catppuccin and I am currently writing up the documentation, where I am using the theme that the library provides.

Currently, Tidy makes it very difficult to render examples that adhere to theming. For example, this line makes it impossible to set the preview theme, even if using the preamble argument in parse-module.

Could you please revise this function and remove any such defaults? I do not feel that explicitly setting the fill to white is necessary.

Thanks :)

TimeTravelPenguin commented 3 weeks ago

Perhaps you could allow a dict argument as a solution. I also noticed that here, here, and here are some other rather rigid configurations.

If you require that I make a pull request, please let me know and I would be happy to, based on your preference as to how to solve this.

Mc-Zen commented 3 weeks ago

Hi @TimeTravelPenguin

It is true that the provided themes are not very customizable, that is why you can make your own themes too. Especially the example rendering has proven to be a little tricky. There have been plans to redesign how themes and customization work in tidy but they require the long-awaited custom types in Typst and I don't want to break everything twice.

This is just for the background, however - for show-example we can totally find a good solution for now. Let me look at the issue.

PS: Nice color themes by the way :)

Mc-Zen commented 3 weeks ago

Okay, so the thing is that we could of course add parameters for all these hard-coded values to show-example() but then you'd sortof have to provide these arguments every time you call example in the documentation. This can be overcome by adding some #example = example.with(...) to the preamble argument in parse-module() but that's all not very clean and satisfying.

Again, ideally example would be a type so one can do set and show rules like

#set tidy.example(fill: black, spacing: 1em)

or similar. Unfortunately, they're not there yet.

One thing you can do now is copying the default theme and insert your own modified implementation of show-example. As you pointed out, there are so many hard-coded details of the implementation of show-example that in the end you might want to change even more.

Modifying a theme does not actually require copying everything, you can write

#import "/src/styles/default.typ"

#let show-example(..args) = {} // your own implementation of show-example

#let my-theme = dictionary(default)
#{my-theme.show-example = show-example}

#show-module(docs, style: styles.default, colors: styles.default.colors-dark)

because styles also accepts a dictionary and since recently it is possible to turn a module into a dictionary.

Still, if you can think of another (elegant) solution to solve this issue, let me know!

TimeTravelPenguin commented 3 weeks ago

PS: Nice color themes by the way :)

Haha thanks, but I can't take credit for the Catppuccin themes. I am just a random community member implementing it in Typst to save my poor eyes from a white screen!

Okay, so the thing is that we could of course add parameters for all these hard-coded values to show-example() but then you'd sortof have to provide these arguments every time you call example in the documentation.

There are a few ways to get around this. Or at least, to make it a bit easier to work with, as I will shortly discuss.

There have been plans to redesign how themes and customization work in tidy but they require the long-awaited custom types in Typst and I don't want to break everything twice.

Yes, I am very excited about custom types. For a temporary workaround, I personally like using the Valkyrie package for schema validation.

What I am doing in my project is having some

#import "@preview/valkyrie:0.2.1" as z

#let config-schema = z.dictionary(( ... ))

#let my-func(config: (:)) = {
    let config-defaults = (...)
    config = config-defaults + config
    let valid-config = z.parse(config, config-schema)
}

You don't need Valkyrie for the main point here, but it shows how it can be used. So, the approach I take is that the default user-provided config is empty. I then use the + behaviour on dictionaries to update the functions local default (e.g., setting the fill to white). Then, if the user provides a fill entry, it overwrites your function's defaults.

Then, Valkyrie is helpful because you can assert that the provided dictionary configuration contains only the expected values for the thing you're plugging it into. But like I said, it isn't the necessary part of this. I just wanted to mention it as I am a personal fan.

Ultimately, a redesign is certainly looking like the way to go, but depending on how you want to go about it, the complexity can greatly differ.

Just off the top of my head, I would probably take a kind of functional approach, seeing as there are no object/types. The tidy show-module function would need to be dependent on the remaining other functions. Either these are given as arguments, found through introspection/parsing of a module, or be the result of another function who, itself, if provided the required components to build show-module.

One other approach, which would be much harder to implement and would require some big planning would be to work with functions that give and take contexts (not the typst context), similar to how CeTZ does.

This is just some spitballing of ideas I had while studying your library :)

Mc-Zen commented 3 weeks ago

Haha thanks, but I can't take credit for the Catppuccin themes. I am just a random community member implementing it in Typst to save my poor eyes from a white screen!

Ah okay haha. Still good work porting it to Typst 👍

You don't need Valkyrie for the main point here, but it shows how it can be used. So, the approach I take is that the default user-provided config is empty. I then use the + behaviour on dictionaries to update the functions local default (e.g., setting the fill to white). Then, if the user provides a fill entry, it overwrites your function's defaults.

Yes, I use the same approach in other packages as well.

Just off the top of my head, I would probably take a kind of functional approach, seeing as there are no object/types. The tidy show-module function would need to be dependent on the remaining other functions. Either these are given as arguments, found through introspection/parsing of a module, or be the result of another function who, itself, if provided the required components to build show-module.

Indeed, the dependance is one of the main issues. For example implementations of show-function call show-type etc. Another issue is passing lots of data and settings down to the different styling functions. I really want to go for user-defined types in the long run because they allow for composable, flexible rules. Additionally, methods on types will allow outsourcing common transformations/preprocessing of the content.

Alas, the different ways that other packages currently deal with this problem are all a bit clunky and have disadvantages of their own. For me it does not make too much sense rebuilding the framework now and then changing it up yet again so I will wait for custom types since everything is possible (I think/I hope) now by building your own themes.

I would still keep this issue open so we can check that this is treated with the needed care once the time has come :)

If you need help defining or modifying a style/theme come back to me.

TimeTravelPenguin commented 3 weeks ago

Ah okay haha. Still good work porting it to Typst 👍

I have so much to do still, but the package is slowly coming together.

For me it does not make too much sense rebuilding the framework now and then changing it up yet again so I will wait for custom types since everything is possible (I think/I hope) now by building your own themes.

That's perfectly valid. There is a lot of potential opportunity depending on what kinds of features get added in the future. Any changes you do now should probably only complement the future, in the event you don't start from the ground up.

If you need help defining or modifying a style/theme come back to me.

Thanks! I have been having some issues with a slightly hacked version of the default show-example, but it is partly due to my own package's configuration and styling. I need to chip away at yours some more when I have the time. I will certainly reach out if I need help.

TimeTravelPenguin commented 3 weeks ago

One thing that I do want to mention is that one place to perhaps introduce where the user may be able to configure their docs would be by making this code an external dependency.

Just wanted to leave this here as a future consideration. A builder pattern would be very useful.

Mc-Zen commented 3 weeks ago

Yes, this will definitely be customizable at some point!