fsprojects / FSharp.Formatting

F# tools for generating documentation (Markdown processor and F# code formatter)
https://fsprojects.github.io/FSharp.Formatting/
Other
464 stars 156 forks source link

Support for templates written in F# #469

Closed kblohm closed 4 years ago

kblohm commented 6 years ago

Hi, in #467 @matthid mentioned his intentions to support rendering with Fulma. @matthid did you actually mean Fulma, as in using Fable and requiring nodejs etc. or did you just want to support another approach besides razor? If you just want rendering in F#, we can maybe use something along the lines of Giraffe's ViewEngine. This would not require Fable and it would also not require to parse fsx files etc. It would however also not allow to write JS in F#. But i do not think that is needed too often for templates.

matthid commented 6 years ago

@MangelMaxime told me that Fulma works on full-framework as well, but I might have misunderstood something.

Can you clarify how Giraffe would be technically different from Fulma? It looks pretty close to me. If we want to have "templates" we still would need to parse fsx files, or how would a user be able to change the template?

matthid commented 6 years ago

To clarify: I'm pretty much open to everything, point is there should be a way to edit templates without the need to re-compile fsf or to use fsf as library (though maybe we should be open to that, fake 5 might help there). Historically, using fsf as library was a very fragile setup (I guess that's why I'm a bit afraid)

kblohm commented 6 years ago

I am not a Fulma/Fable expert so everything i write might be wrong ;) As far as i know Fulma adds support for Bulma with Fable.React. So it renders to React and not directly to HTML and requires Fable. Fable needs nodejs. The Giraffe ViewEngine is just a dsl to create XML/HTML.

So it should be possible to just call MetadataFormat.Generate() use the output and to call one templating function per type, write the output to disc. The function that does this could be in a dll that you import in an fsx file and call from there. So you could create all your templates inside that one fsx file.

kblohm commented 6 years ago

It would probably also be possible to add another renderer to Fulma, so Fulma generates HTML instead of using React. But then you would also be tied to using Bulma.

matthid commented 6 years ago

Honestly, I haven't thought this through. The problem is that I don't really want to maintain RazorEngine anymore just to keep FSharp.Formatting working. In fact upgrading to asp.net.core engine (which I believe now has an API similar to RazorEngine) would work as well.

But if we already switch - switching to something more F# like seems reasonable. Especially considering all the recent developments in fable area. I thought about switching to fable for fsf but there is a lot of churn involved, the most important dependencies (like FSharp.Compiler.Service) are available on fable so I think it is doable.

MangelMaxime commented 6 years ago

Fulma is indeed a wrapper for Bulma on top of Fable.React.

And because Fable.React support Server side rendering by using renderToString then yes Fulma is also working on classic F#.

By using the module Fable.Helpers.ReactServer you don't need neither nodejs neither react.


As a quick note, we should stop having a custom implementation of html DSL in each project. We have one in Suave, Giraffe, Fornax, Fable.React, etc. and think about a common one.

Having a common DSL mean being able to use Fulma everywhere or any equivalent wrapper.


so Fulma generates HTML instead of using React. But then you would also be tied to using Bulma.

Indeed, by using Fulma you need to use Bulma framework, but in every website you need Columns, Notification, etc. and Bulma is really easy to customize. Bulma, give you access to a lot of variable to you can specify custom margin, padding, borders, use/add custom colors, etc.

You can also include custom styles because you can use standard DOM element when needed.

Exampe:

Section.section [ ]
  [ span [ Class "my-custom-element" ]
    [ str "I am a custom element inside a Bulma section ]
kblohm commented 6 years ago

As a quick note, we should stop having a custom implementation of html DSL in each project. We have one in Suave, Giraffe, Fornax, Fable.React, etc. and think about a common one.

YES! :p

Thanks for clarifying!

matthid commented 6 years ago

@MangelMaxime We probably won't add a custom html DSL for FSF, we never even managed to properly finish the markdown spec (we still have a lots of failing tests automatically generated from the spec) ;)

MangelMaxime commented 6 years ago

@matthid I am not saying it should be done inside the FSF but more by the maintainer of the different projects to discuss and merge their DSL.

We did that at the time for Elmish and Fable-Arch for example etc.

Yes, I saw the problem of the Markdown parser and was trying to rewrite one for Fable but I should probably fix the one inside this repo and port it to Fable later. I will probably take a look at it this week-end.

matthid commented 6 years ago

@MangelMaxime feel free to completely rewrite the current implementation. If you manage to get all tests green you probably earned it ;)

cloudRoutine commented 6 years ago

@matthid I still need to merge the alternative rendering approach that doesn't need any js for the tooltips which would let us put (F# snippets with intellisense into more restricted contexts like some epubs and pdfs). I was going to do it yesterday but there ended up being a lot more conflicts than I expected.

@MangelMaxime @kblohm the whole way the pipeline is setup needs to be changed. The way FSF currently integrates with builds is pretty awful and incredibly finicky.

My goal is to make it much easier to integrate FSF into a wider variety of build contexts, whether it's generating a preview window for vscode, rendering .md/.fsx into html for someone's blog or populating a project's doc pages with code snippets. With a little bit of Fable sprinkled into API/doc pages for functionality like search by type signature, we'd have a sweet little setup for all the F# OSS projects.

We could probably package a few different rendering pipelines together to make it easier for people.

cloudRoutine commented 6 years ago

Are there other libraries we should be looking? Each of these seems like they have some big drawbacks.

I'm not sure that people from a bunch of these projects would be able to agree on an approach for an F# html & css library to be shared across them.

I wouldn't mind writing one for FSharp.Formatting as long as it didn't take any dependencies so people could paket-file it and give it a standalone nuget package where the source gets added to the project consuming it.

MangelMaxime commented 6 years ago

@cloudRoutine Fulma have a dependency over npm/yarn only if you want to customize the Bulma framework.

You could use directly Fulma with Bulma from a CDN.

But to be fair, if you use any existing CSS framework you will probably have deps over npm/yarn because otherwise you can't customize it.

cloudRoutine commented 6 years ago

@MangelMaxime i'm liking the idea of us rolling our own EDSLs more and more to enable the baseline functionality. Of course I still want FSharp.Formatting to play nice with whatever other template systems people want to use.

tpetricek commented 6 years ago

Are we thinking mainly about the API doc generation or about the Markdown template processing?

The Markdown template processing is very simple and we could actually just drop that functionality from F# Formatting - we do the Markdown -> HTML part and let someone else do the templating.

For the API doc generation, I guess there is more templating involved, but we could still just return a record/DU domain model that exposes all the information and leave the formatting to other projects.

That would make "F# Formatting" more "F# MetaThing" but I don't think we can pick one templating solution that will make everyone happy - and so maybe that effort should go into scaffold instead...?

MangelMaxime commented 6 years ago

IMO we are speaking about 2 or 3. The markdown parser is another subject.

matthid commented 6 years ago

In an ideal world yes that stuff would be split apart, however we still would need some "integration" solution for the most basic use case: Generate the docs for our open source libraries. I don't want to put several projects together, keeping FSharp.Formatting working is hard enough on its own.

The advantage I see in this very issue is that we remove our hard dependency in the ecosystem on RazorEngine which is kind of without an maintainer at the moment and I have no plans to port it to netcore at all. I don't want to introduce too much churn here - only if somebody else wants to do it all the way to the end ;)

As we already support several backends (latex, razor, simple templates) adding another one (F# templates) shouldn't be too hard. And yes this is mostly about API reference documentation. The markdown parser itself is pretty much good to go already/

cloudRoutine commented 6 years ago

@matthid

I don't want to put several projects together

I wasn't thinking of doing much more than making some samples to show people how to do it. There could be "pipeline" nuget packages that other people could maintain, collects, and streamline assets for.

I don't want to introduce too much churn here - only if somebody else wants to do it all the way to the end ;)

I'm that guy 😉 (I'll try not to disappear for months before I finish)

@tpetricek

Are we thinking mainly about the API doc generation or about the Markdown template processing?

The snippets go in people's blogs, their presentations, they'll be able to go into ebooks now, but API will definitely be the most useful part

I don't think we can pick one templating solution that will make everyone happy - and so maybe that effort should go into scaffold instead...?

It might, but the projectscaffold isn't really modular and it doesn't seem well suited to configuration. FAKE might be the better place for that.

kblohm commented 6 years ago

Although i am not really in favor of a razor solution, it might be nice for some people. There are solutions that use asp.net core razor. For example https://github.com/toddams/RazorLight. That looks pretty active and does not block porting to dotnet core.

dsyme commented 4 years ago

This is outside the remit of this repo, though internally we have moved more to this approach, see https://github.com/fsprojects/FSharp.Formatting/blob/master/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs#L10

For extensible templating over the FSharp.Formatting ApiDocsModel using FSX files please see Fornax and Waypoint by @Krzysztof-Cieslak