-
Notifications
You must be signed in to change notification settings - Fork 790
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
Allow nested triple-quote interpolation strings #14535
Comments
I've updated the description to state that more than one level of nesting of triple-quote interpolation strings is optional. The thinking was that first I do not currently have a use case for nesting more than once and second I suppose that it is quite likely that implementing single level nesting is much simpler than unlimited nesting. I think supporting a single level nesting is simpler because it is already supported to nest single-quote interpolation strings in a triple-quote string and, my assumption is, it cannot be much different to support to nest triple-quote interpolation strings in a a triple-quote string. |
Might somewhat be related to https://github.com/orgs/dotnet/projects/126/views/31?pane=item&itemId=11881590 |
I feel like this is encouraging complexity in an undesirable way. F# already allows arbitrary expressions in interpolated strings so rather than nesting you can keep the structure more flat with an extra function call. open Fable.Core
let innerJsx x = JSX.jsx $"""<div>{x}</div>"""
[<JSX.Component>]
let JsxInJsx () =
JSX.jsx $"""
<div> { [ for x in 0..2 -> innerJsx x ] } </div>
""" |
@roboz0r for me complexity increases if I need to mentally map between how the code is written and what it does. When I write JSX, I think how it will be rendered. When child components are defined inline, I do not need any mental mapping because they will be rendered where I defined the code. However if the child component is defined above, I will need to find where it is defined and imagine how it is rendered at another place. The blog post that writes about the JSX syntax has an example that actually uses nesting. It only works because the outer markup is not defined using JSX but using the F# syntax. So if you would like to replace the F# syntax with JSX it would not compile. Here the code from the blog post. Code from: https://fable.io/blog/2022/2022-10-12-react-jsx.html [<ReactComponent>]
let QrCode() =
let value, setValue = Hooks.useState("https://fable.io/") |> asTuple
React.fragment [
Html.input [
prop.className "input mb-5"
prop.type' "text"
prop.autoFocus true
prop.value (value)
prop.onTextChange setValue
]
Html.div [
toReact <| JSX.jsx $"""
import {{ SlQrCode }} from "@shoelace-style/shoelace/dist/react"
<SlQrCode value={value} radius="0.5"></SlQrCode>
"""
]
] When I look at other JSX code that uses TypeScript, I often see JSX created within JSX. For example the following code from https://github.com/adrianhajdin/project_chat_application/blob/master/client/src/components/TextContainer/TextContainer.js const TextContainer = ({ users }) => (
<div className="textContainer">
<div>
<h1>Realtime Chat Application <span role="img" aria-label="emoji">💬</span></h1>
<h2>Created with React, Express, Node and Socket.IO <span role="img" aria-label="emoji">❤️</span></h2>
<h2>Try it out right now! <span role="img" aria-label="emoji">⬅️</span></h2>
</div>
{
users
? (
<div>
<h1>People currently chatting:</h1>
<div className="activeContainer">
<h2>
{users.map(({name}) => (
<div key={name} className="activeItem">
{name}
<img alt="Online Icon" src={onlineIcon}/>
</div>
))}
</h2>
</div>
</div>
)
: null
}
</div>
); |
I would like more people to be interested in this issue. Maybe some commenters from the pull request that introduced string interpolation #8907 are interested? @dbrattli, @Swoorup, @0x53A, @realvictorprm, @MikaelUmaN |
Update: My need for this feature was because I wanted to use my favourite programming language F# to write a web application that uses the javascript material-ui library. With the new fable feature to embed JSX in interpolated strings that is now possible. However for me it is not close enough to writing JSX or TSX in a separate file. That is why I created this issue. Seeing not much discussion here made me look for alternatives that allow me to use the material-ui library with a better language than TypeScript. Now I found that Kotlin has a DSL to create markup and that there is a kotlin-wrapper for the MUI library. Concluding, I think F# is a much better language than Kotlin and F# would be much better for web development than any other language, however, in web development, there is a constant need for change and currently (without having tried it yet) there seems to be more support for web development with JetBrains Kotlin. |
Please create a language suggestion for this. |
Is your feature request related to a problem? Please describe.
The problem is described here: fable-compiler/Fable#3319
In short, a new feature in the F# Fable compiler allows using JSX syntax in triple-quote interpolation strings (see https://fable.io/blog/2022/2022-10-12-react-jsx.html), however nesting JSX is not possible.
If nesting triple-quote interpolation strings would be supported by the F# compiler then it would be possible to create complex UIs using the JSX syntax and F# for inline event handlers and for all other code. Without nested strings the new JSX feature has limited use for me.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
See above.
Describe the solution you'd like
All 3 examples below should compile, or at least examples 1 and 3.
Example 1
Example 2 (currently I have no use case for nesting twice but it would be nice for consistency if it would also work)
Example 3
A triple-quote interpolation string should be treated as any other expression within a triple-quote interpolation string and just be compiled.
Describe alternatives you've considered
Alternative 1
Use non triple-quoted strings inside a triple-quote interpolation string. --> Disadvantages: 1. It is only a solution for nesting one level because it is not allowed to nest a single-quote interpolation string within another. 2. There is unfortunately no syntax highlight by the VsCode extension mentioned in the article https://fable.io/blog/2022/2022-10-12-react-jsx.html in that case.
Alternative 2
Concat strings. This seems to work but requires to join strings to make the example work, which will make the UI code ugly. Additionally, there is only syntax highlight for one part of the string.
Alternative 3
Introduce a new filetype similar to
.tsx
as.fsjsx
that allows defining JSX code next to F# code. This would be even better than the proposed change. The advantages to the proposed change are first, no need to start JSX code withJSX.jsx $"""
and second, no need to escape{
and}
characters.There is an in interesting argument in this link from facebook why it is not good to embed JSX in a template, the text says "Unfortunately the syntax noise is substantial when you exit in and out of embedded arbitrary ECMAScript expressions with identifiers in scope".
Additional context
If the issue is about:
String interpolation. See https://github.com/fsharp/fslang-design/blob/main/FSharp-5.0/FS-1001-StringInterpolation.md
The text was updated successfully, but these errors were encountered: