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

Convert HTML to Gomponents #178

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

Convert HTML to Gomponents #178

wants to merge 6 commits into from

Conversation

amrojjeh
Copy link
Contributor

@amrojjeh amrojjeh commented Jun 23, 2024

This is my attempt to solve #167. I didn't use x/net/html because... well I forgot to look into it. The XML parser in the standard library seems to work fine though once configured to parse HTML.

The way I decided to format the output was as such:

  • Attributes are on the same line
  • g.Text and other elements take up a new line
  • Whitespace is ignored
  • Tabs are used instead of spaces (as per Go's standard)
  • It's standard to have one "page" per file, so this code outputs an entire new file with the imports and the package (default "ui") rather than outputting a single function

Here's an example:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
</head>
<body>
	<p>How are you doing?</p>
	<unknown required data-crazy="lol">wow</unknown>
	<a aria-hidden="true" data-wow="some field" unrecognized="crazy" anotherunrecognized></a>
	<form action="/test" method="get">
		<input type="text" required>
	</form>
</body>
</html>
package ui

import (
	g "github.com/maragudk/gomponents"
	. "github.com/maragudk/gomponents/html"
)

func Page() g.Node {
	return Doctype(
		HTML(Lang("en"),
			Head(
				Meta(Charset("UTF-8")),
				Meta(Name("viewport"), Content("width=device-width, initial-scale=1.0")),
				TitleEl(
					g.Text("Document"),
				),
			),
			Body(
				P(
					g.Text("How are you doing?"),
				),
				g.El("unknown", Required(), Data("crazy", "lol"),
					g.Text("wow"),
				),
				A(Aria("hidden", "true"), Data("wow", "some field"), g.Attr("unrecognized", "crazy"), g.Attr("anotherunrecognized", "anotherunrecognized")),
				Form(Action("/test"), Method("get"),
					Input(Type("text"), Required()),
				),
			),
		),
	)
}

(Note: the output contains trailing commas, not seen here, but these are easily removed by running go fmt, which is integrated into most editors)

Usage: go run . (-p PACKAGE NAME) [html file]

There is still lots of work left, such as integrating SVG and HTMX, running automated tests, supporting globbing, but I think this lays a good foundation.

Apologize for the older commits as well. I had an older fork of this repo and I didn't know how to squash them excerpt by deleting my fork and starting a new one, and at that point I had already started working on it.

Feel free to move this off of main.

@amrojjeh
Copy link
Contributor Author

amrojjeh commented Jun 23, 2024

Tests are failing because I accidentally used go 1.20 features 💀 (strings.CutPrefix). I'll let you decide if you want to upgrade or if we should stick to go1.18

@markuswustenberg
Copy link
Member

Hey @amrojjeh, thanks for having a go at this! I'll see if I can get around to having a look at it before the start of my summer holidays at the end of this week. 😊

@amrojjeh
Copy link
Contributor Author

Note to self: Go code can be formatted with https://pkg.go.dev/go/format

@markuswustenberg
Copy link
Member

Hi @amrojjeh . Thanks again for having a go at this!

Since then, @PiotrKowalski made an online version at https://htg.piotrkowalski.me, with source available at https://github.com/PiotrKowalski/html-to-gomponents . I think I'm going with pointing to that for now, since it's the least amount of work for me and looks like it's working fine. If I'm adding anything to the core library, I'd have to make sure to understand it and be responsible for maintaining it, and unfortunately I don't want to take that on right now.

But perhaps it would make sense for you to publish this as an independent CLI tool?

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

Successfully merging this pull request may close these issues.

2 participants