Comments (9)
Interesting idea. I think that templ could detect the presence of a .prettierrc and, if present, and the prettier executable is on the path, could call out and format the JS.
If a .prettierrc was found, but there's no prettier executable, then it could be a warning.
from templ.
Hi @jmarais to answer your question of if templ "does" any formatting, it doesn't currently no.
Whether it should is a harder question, there are a lot of differing opinions on how formatting should be done in terms of JS, so my suggestion would be to encourage separate tools that allow users to configure preferences, rather than having these baked in to templ.
from templ.
Thanks. I had some problem formatting the javascript inside a templ file. I don't know of any formatters that will handle this embedded language situation. Since formatters just overwrite the whole file they essentially compete with each other.
Do you currently have a method to handle this? Or is the current suggestion to just keep the 'script' blocks formatted by hand?
from templ.
If you are using Neovim, you can run your formatters with https://github.com/stevearc/conform.nvim, which has injected language support through tree sitter. I use it to run biome on the JavaScript portions of my code.
from templ.
@JonnyLoughlin, Thanks. I will give conform a shot.
edit: @JonnyLoughlin I played around with conform. It doesnt seem to detect the javascript blocks as injected languages in my above example file. I might be messing up the config, do you have a config I can take a look at?
I think I got it with the ["*"] = { "injected" },
config in the `formatters_by_ft``` section. conform can fallback to the lsp and format injected langues.
It still feels weird using external formatters while the templ tool provides a 'fmt' command.
from templ.
return {
"stevearc/conform.nvim",
event = { "BufWritePre" },
cmd = { "ConformInfo" },
opts = {
formatters_by_ft = {
lua = { "stylua" },
go = { "goimports", "gofumpt" },
templ = { "templ", "injected" },
javascript = { "biome" },
typescript = { "biome" },
typescriptreact = { "biome" },
json = { "biome" },
sh = { "beautysh" },
zsh = { "beautysh" },
},
format_on_save = {
lsp_fallback = false,
timeout_ms = 1000,
},
log_level = vim.log.levels.INFO,
notify_on_error = true,
},
}
That is my config. There seems to be a bit of an issue with indenting with this method, but it gets fixed by wrapping the js code. For example:
script graph(data string) {
{
const chart = LightweightCharts.createChart(document.body, { width: 400, height: 300 });
const lineSeries = chart.addLineSeries();
lineSeries.setData(data);
if (true) {
console.log("yes");
} else {
console.log("no");
}
}
}
templ body() {
<script>
{
const chart = LightweightCharts.createChart(document.body, { width: 400, height: 300 });
const lineSeries = chart.addLineSeries();
lineSeries.setData([
{ time: '2019-04-11', value: 80.01 },
{ time: '2019-04-12', value: 96.63 },
{ time: '2019-04-13', value: 76.64 },
{ time: '2019-04-14', value: 81.89 },
{ time: '2019-04-15', value: 74.43 },
{ time: '2019-04-16', value: 80.01 },
{ time: '2019-04-17', value: 96.63 },
{ time: '2019-04-18', value: 76.64 },
{ time: '2019-04-19', value: 81.89 },
{ time: '2019-04-20', value: 74.43 },
]);
}
</script>
<body>
<div>
hello
</div>
</body>
}
formats to
script graph(data string) {
{
const chart = LightweightCharts.createChart(document.body, {
width: 400,
height: 300,
});
const lineSeries = chart.addLineSeries();
lineSeries.setData(data);
if (true) {
console.log("yes");
} else {
console.log("no");
}
}
}
templ body() {
<script>
{
const chart = LightweightCharts.createChart(document.body, {
width: 400,
height: 300,
});
const lineSeries = chart.addLineSeries();
lineSeries.setData([
{ time: "2019-04-11", value: 80.01 },
{ time: "2019-04-12", value: 96.63 },
{ time: "2019-04-13", value: 76.64 },
{ time: "2019-04-14", value: 81.89 },
{ time: "2019-04-15", value: 74.43 },
{ time: "2019-04-16", value: 80.01 },
{ time: "2019-04-17", value: 96.63 },
{ time: "2019-04-18", value: 76.64 },
{ time: "2019-04-19", value: 81.89 },
{ time: "2019-04-20", value: 74.43 },
]);
}</script>
<body>
<div>
hello
</div>
</body>
}
for me with my config. I do intend on figuring out why the extra brackets are needed. I just haven't had time to dive in.
from templ.
Thanks for the reference. The brackets are a neat trick.
Something else I tried was just using the javascript functions in the .templ
file, but defining all the javascript logic in a .js
file. I just run the templ formatter over the .templ
file and can then use the javascript related tools (tsserver lsp and prettier) in the .js
files without worrying about embedded language formatting.
from templ.
I had a play around with this earlier in the week.
I was able to update the parser/v2/raw.go
file to get it to format its content when it writes itself out. There's no popular JS / CSS formatter in Go, so I had to stick with prettier. Since it's in JS, I had to pipe the content over to the prettier command, and pass prettier a file name that's appropriate to the contents of the script or style element (scripts can contain JSON, not JS etc.).
It worked, but then I realised that any HTML LSP that you had would also do the same, and that the prettier formatting and LSP formatting might clash.
I was also concerned about the performance of starting up lots of processes (one per script or style tag in your code).
I noted that if the JS is invalid in some way, prettier bombs out with some log entries on stdout. That gave me the idea of testing the JS early, using the tdewolff
JS parser - that worked really well as a diagnostic, which could be plugged into the templ LSP... but again, what's the point if the design in #498 goes ahead.
func invalidScriptElementContentsDiagnoser(n Node) ([]Diagnostic, error) {
e, ok := n.(RawElement)
if !ok || e.Name != "script" {
return nil, nil
}
_, err := js.Parse(parse.NewInputString(e.Contents), js.Options{})
if err != nil {
pe, isParseError := err.(*parse.Error)
if !isParseError {
return []Diagnostic{{
Message: fmt.Sprintf("invalid content in script element: %v", err),
Range: e.ContentsRange,
}}, nil
}
// Calculate the offset from the start of the script element to the error.
from := e.ContentsRange.From
from.Line += uint32(pe.Line)
from.Col += uint32(pe.Column)
for li, line := range strings.Split(e.Contents, "\n") {
if li == pe.Line {
from.Index += int64(pe.Column)
break
}
from.Index += int64(len(line)) + 1
}
return []Diagnostic{{
Message: fmt.Sprintf("invalid content in script element: %v", pe.Message),
Range: Range{
From: from,
To: from,
},
}}, nil
}
return nil, nil
}
So, basically, I think that we'll get more benefit from implementing #498 than from doing this, so I'm going to pause my experiment on this, and focus on getting multiple LSPs in place.
Then, you can add a prettier LSP into your dev workflow which would handle this. At that point, templ fmt
could also be updated to use 3rd party LSPs to complete formatting work.
from templ.
It worked, but then I realised that any HTML LSP that you had would also do the same, and that the prettier formatting and LSP formatting might clash.
I played around with prettier with the LSPs and ended at the same place.
So, basically, I think that we'll get more benefit from implementing #498 than from doing this, so I'm going to pause my experiment on this, and focus on getting multiple LSPs in place.
Then, you can add a prettier LSP into your dev workflow which would handle this. At that point, templ fmt could also be updated to use 3rd party LSPs to complete formatting work.
That could help.
from templ.
Related Issues (20)
- Binary in`templ_Darwin_arm64.tar.gz` v0.2.697 displays version 0.2.696 HOT 8
- -stdout sends error report to output file HOT 3
- bug: script elements don't render script templates
- lsp: support the organizeImports code action HOT 3
- Wasm support for interacting with the DOM HOT 3
- generator: can't use iterator value in for loop HOT 8
- max retries reached HOT 3
- lsp: panic on codeAction HOT 6
- question: Escape go keywords at the beginning of the line HOT 3
- generator: Duplicate Import Statements in Generated Templates Cause go build Failure HOT 5
- vscode: folded files in tree view seem to not work when rust-analyzer is installed HOT 2
- Issue: Unexpected Script Placement in Generated HTML HOT 3
- fmt: <pre> tags not handled correctly HOT 3
- parser: style attribute of DOM element doesn't accept dynamic styles HOT 1
- proposal: Typed Children for Wrappers HOT 2
- Proposal: Allow spreading List of `templ.Components`, similar to `{ children ... }` HOT 1
- css expression: found unexpected parameters HOT 2
- generator: Add nonce support for style tags
- Abandoned change to not modify files where fmt makes no changes HOT 3
- Proposal: Load file as templ HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from templ.