{"id":13770074,"url":"https://github.com/chasefleming/elem-go","last_synced_at":"2025-04-08T12:09:12.372Z","repository":{"id":198765794,"uuid":"701461609","full_name":"chasefleming/elem-go","owner":"chasefleming","description":"Type-safe Go library for creating and manipulating HTML elements (with htmx helpers).","archived":false,"fork":false,"pushed_at":"2024-11-06T00:15:34.000Z","size":564,"stargazers_count":322,"open_issues_count":3,"forks_count":27,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-01-08T23:41:55.632Z","etag":null,"topics":["go","golang","html","htmx"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chasefleming.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-06T17:24:15.000Z","updated_at":"2024-12-29T21:13:32.000Z","dependencies_parsed_at":"2023-10-14T14:06:02.401Z","dependency_job_id":"8d7f80eb-9dcd-41ff-857d-26c7cacc8b52","html_url":"https://github.com/chasefleming/elem-go","commit_stats":{"total_commits":226,"total_committers":25,"mean_commits":9.04,"dds":"0.24778761061946908","last_synced_commit":"e134535b8a28ff02e26c62e6d88ff2dbdd799229"},"previous_names":["chasefleming/elem-go"],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chasefleming%2Felem-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chasefleming%2Felem-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chasefleming%2Felem-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chasefleming%2Felem-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chasefleming","download_url":"https://codeload.github.com/chasefleming/elem-go/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247838444,"owners_count":21004580,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","html","htmx"],"created_at":"2024-08-03T17:00:34.025Z","updated_at":"2025-04-08T12:09:12.351Z","avatar_url":"https://github.com/chasefleming.png","language":"Go","funding_links":[],"categories":["Tools"],"sub_categories":[],"readme":"![elem-go logo](./logo.png)\n\n`elem` is a lightweight Go library for creating HTML elements programmatically. Utilizing the strong typing features of Go, `elem` ensures type safety in defining and manipulating HTML elements, minimizing potential runtime errors. It simplifies the generation of HTML views by providing a simple and intuitive way to create elements and set their attributes, properties, and content.\n\n## Features\n\n- Easily create HTML elements with Go code.\n- Type-safe definition and manipulation of elements, attributes, and properties.\n- Supports common HTML elements and attributes.\n- Utilities for simplified element generation and manipulation.\n- Advanced CSS styling capabilities with the [styles](styles/README.md) subpackage.\n- Use the [`StyleManager`](styles/STYLEMANAGER.md) for advanced CSS features like pseudo-classes, animations, and media queries.\n\n## Installation\n\nTo install `elem`, use `go get`:\n\n```bash\ngo get github.com/chasefleming/elem-go\n```\n\n## Usage\n\nImport the `elem` package in your Go code:\n\n```go\nimport (\n    \"github.com/chasefleming/elem-go\"\n    \"github.com/chasefleming/elem-go/attrs\"\n    \"github.com/chasefleming/elem-go/styles\"\n)\n```\n\n### Creating Elements\n\nHere's an example of creating a `\u003cdiv\u003e` element with nested `\u003ch1\u003e`, `\u003ch2\u003e`, and `\u003cp\u003e` elements using elem:\n\n```go\ncontent := elem.Div(attrs.Props{\n    attrs.ID:    \"container\",\n    attrs.Class: \"my-class\",\n},\n    elem.H1(nil, elem.Text(\"Hello, Elem!\")),\n    elem.H2(nil, elem.Text(\"Subheading\")),\n    elem.P(nil, elem.Text(\"This is a paragraph.\")),\n)\n```\n\nWhen the above Go code is executed and the `.Render()` method is called, it produces the following HTML:\n\n```html\n\u003cdiv id=\"container\" class=\"my-class\"\u003e\n    \u003ch1\u003eHello, Elem!\u003c/h1\u003e\n    \u003ch2\u003eSubheading\u003c/h2\u003e\n    \u003cp\u003eThis is a paragraph.\u003c/p\u003e\n\u003c/div\u003e\n```\n\n### Attributes and Styles\n\nThe [`attrs`](attrs/README.md) subpackage provides type-safe attribute functions that ensure you're setting valid attributes for your elements. This helps eliminate potential issues at runtime due to misspelled or unsupported attribute names.\n\nFor boolean attributes like `checked` and `selected`, you can simply assign them the value `\"true\"` or `\"false\"`. When set to `\"true\"`, the library will correctly render these attributes without needing an explicit value. For instance:\n\n```go\n// Using boolean attributes\ncheckbox := elem.Input(attrs.Props{\n    attrs.Type:    \"checkbox\",\n    attrs.Checked: \"true\",  // This will render as \u003cinput type=\"checkbox\" checked\u003e\n})\n```\n\nFor setting styles, the [`styles`](styles/README.md) subpackage enables you to create style objects and convert them to inline CSS strings:\n\n```go\n// Define a style\nbuttonStyle := styles.Props{\n    styles.BackgroundColor: \"blue\",\n    styles.Color:           \"white\",\n}\n\n// Convert style to inline CSS and apply it\nbutton := elem.Button(\n    attrs.Props{\n        attrs.Style: buttonStyle.ToInline(),\n    },\n    elem.Text(\"Click Me\"),\n)\n```\n\nSee the complete list of supported attributes in [the `attrs` package](./attrs/attrs.go), and for a full overview of style properties and information on using the `styles` subpackage, see the [styles README](styles/README.md).\n\n### Rendering Elements\n\nThe `.Render()` method is used to convert the structured Go elements into HTML strings. This method is essential for generating the final HTML output that can be served to a web browser or integrated into templates.\n\n```go\nhtml := content.Render()\n```\n\nIn this example, `content` refers to an `elem` element structure. When the `.Render()` method is called on content, it generates the HTML representation of the constructed elements.\n\n\u003e NOTE: When using an \u003chtml\u003e element, this method automatically includes a \u003c!DOCTYPE html\u003e preamble in the rendered HTML, ensuring compliance with modern web standards.\n\n#### Custom Rendering Options\n\nFor more control over the rendering process, such as disabling the HTML preamble, use the `RenderWithOptions` method. This method accepts a `RenderOptions` struct, allowing you to specify various rendering preferences.\n\n```go\noptions := RenderOptions{DisableHtmlPreamble: true}\nhtmlString := myHtmlElement.RenderWithOptions(options)\n```\n\nThis flexibility is particularly useful in scenarios where default rendering behaviors need to be overridden or customized.\n\n### Generating Lists of Elements with `TransformEach`\n\nWith `elem`, you can easily generate lists of elements from slices of data using the `TransformEach` function. This function abstracts the repetitive task of iterating over a slice and transforming its items into elements.\n\n```go\nitems := []string{\"Item 1\", \"Item 2\", \"Item 3\"}\n\nliElements := elem.TransformEach(items, func(item string) elem.Node {\n    return elem.Li(nil, elem.Text(item))\n})\n\nulElement := elem.Ul(nil, liElements)\n```\n\nIn this example, we transformed a slice of strings into a list of `li` elements and then wrapped them in a `ul` element.\n\n### Conditional Rendering with `If`\n\n`elem` provides a utility function `If` for conditional rendering of elements.\n\n```go\nisAdmin := true\nadminLink := elem.A(attrs.Props{attrs.Href: \"/admin\"}, elem.Text(\"Admin Panel\"))\nguestLink := elem.A(attrs.Props{attrs.Href: \"/login\"}, elem.Text(\"Login\"))\n\ncontent := elem.Div(nil,\n    elem.H1(nil, elem.Text(\"Dashboard\")),\n    elem.If(isAdmin, adminLink, guestLink),\n)\n```\n\nIn this example, if `isAdmin` is `true`, the `Admin Panel` link is rendered. Otherwise, the `Login` link is rendered.\n\n#### `None` in Conditional Rendering\n\n`elem` provides a specialized node `None` that implements the `Node` interface but does not produce any visible output. It's particularly useful in scenarios where rendering nothing for a specific condition is required.\n\n```go\nshowWelcomeMessage := false\nwelcomeMessage := elem.Div(nil, elem.Text(\"Welcome to our website!\"))\n\ncontent := elem.Div(nil,\n    elem.If[elem.Node](showWelcomeMessage, welcomeMessage, elem.None()),\n)\n```\n\nIn this example, `welcomeMessage` is rendered only if `showWelcomeMessage` is `true`. If it's `false`, `None` is rendered instead, which produces no visible output.\n\nAdditionally, `None` can be used to create an empty element, as in `elem.Div(nil, elem.None())`, which results in `\u003cdiv\u003e\u003c/div\u003e`. This can be handy for creating placeholders or structuring your HTML document without adding additional content.\n\n### Supported Elements\n\n`elem` provides utility functions for creating HTML elements:\n\n- **Document Structure**: `Html`, `Head`, `Body`, `Title`, `Link`, `Meta`, `Style`, `Base`\n- **Text Content**: `H1`, `H2`, `H3`, `H4`, `H5`, `H6`, `P`, `Blockquote`, `Pre`, `Code`, `I`, `Br`, `Hr`, `Small`, `Q`, `Cite`, `Abbr`, `Data`, `Time`, `Var`, `Samp`, `Kbd`\n- **Sectioning \u0026 Semantic Layout**: `Article`, `Aside`, `FigCaption`, `Figure`, `Footer`, `Header`, `Hgroup`, `Main`, `Mark`, `Nav`, `Section`\n- **Form Elements**: `Form`, `Input`, `Textarea`, `Button`, `Select`, `Optgroup`, `Option`, `Label`, `Fieldset`, `Legend`, `Datalist`, `Meter`, `Output`, `Progress`\n- **Interactive Elements**: `Details`, `Dialog`, `Menu`, `Summary`\n- **Grouping Content**: `Div`, `Span`, `Li`, `Ul`, `Ol`, `Dl`, `Dt`, `Dd`\n- **Tables**: `Table`, `Tr`, `Td`, `Th`, `TBody`, `THead`, `TFoot`\n- **Hyperlinks and Multimedia**: `Img`, `Map`, `Area`\n- **Embedded Content**: `Audio`, `Iframe`, `Source`, `Video`\n- **Script-supporting Elements**: `Script`, `Noscript`\n- **Inline Semantic**: `A`, `Strong`, `Em`, `Code`, `I`, `B`, `U`, `Sub`, `Sup`, `Ruby`, `Rt`, `Rp`\n\n### Raw HTML Insertion\n\nThe `Raw` function allows for the direct inclusion of raw HTML content within your document structure. This function can be used to insert HTML strings, which will be rendered as part of the final HTML output.\n\n```go\nrawHTML := `\u003cdiv class=\"custom-html\"\u003e\u003cp\u003eCustom HTML content\u003c/p\u003e\u003c/div\u003e`\ncontent := elem.Div(nil,\n    elem.H1(nil, elem.Text(\"Welcome to Elem-Go\")),\n    elem.Raw(rawHTML), // Inserting the raw HTML\n    elem.P(nil, elem.Text(\"More content here...\")), \n)\n\nhtmlOutput := content.Render()\n// Output: \u003cdiv\u003e\u003ch1\u003eWelcome to Elem-Go\u003c/h1\u003e\u003cdiv class=\"custom-html\"\u003e\u003cp\u003eCustom HTML content\u003c/p\u003e\u003c/div\u003e\u003cp\u003eMore content here...\u003c/p\u003e\u003c/div\u003e\n```\n\u003e **NOTE**: If you are passing HTML from an untrusted source, make sure to sanitize it to prevent potential security risks such as Cross-Site Scripting (XSS) attacks.\n\n### HTML Comments\n\nApart from standard elements, `elem-go` also allows you to insert HTML comments using the `Comment` function:\n\n```go\ncomment := elem.Comment(\"Section: Main Content Start\")\n// Generates: \u003c!-- Section: Main Content Start --\u003e\n```\n\n### Grouping Elements with Fragment\n\nThe `Fragment` function allows you to group multiple elements together without adding an extra wrapper element to the DOM. This is particularly useful when you want to merge multiple nodes into the same parent element without any additional structure.\n\n```go\nnodes := []elem.Node{\n    elem.P(nil, elem.Text(\"1\")),\n    elem.P(nil, elem.Text(\"2\")),\n}\n\ncontent := elem.Div(nil,\n    elem.P(nil, elem.Text(\"0\")),\n    elem.Fragment(nodes...),\n    elem.P(nil, elem.Text(\"3\")),\n)\n```\n\nIn this example, the Fragment function is used to insert the nodes into the parent div without introducing any additional wrapper elements. This keeps the HTML output clean and simple.\n\n### Handling JSON Strings and Special Characters in Attributes\n\nWhen using attributes that require JSON strings or special characters (like quotes), make sure to wrap these strings in single quotes. This prevents the library from adding extra quotes around your value. For example:\n\n```go\ncontent := elem.Div(attrs.Props{\n    attrs.ID:    \"my-div\",\n    attrs.Class: \"special 'class'\",\n    attrs.Data:  `'{\"key\": \"value\"}'`,\n}, elem.Text(\"Content\"))\n```\n\n## Advanced CSS Styling with `StyleManager`\n\nFor projects requiring advanced CSS styling capabilities, including support for animations, pseudo-classes, and responsive design via media queries, the `stylemanager` subpackage offers a powerful solution. Integrated seamlessly with `elem-go`, it allows developers to programmatically create and manage complex CSS styles within the type-safe environment of Go.\n\nExplore the [`stylemanager` subpackage](stylemanager/README.md) to leverage advanced styling features in your web applications.\n\n## HTMX Integration\n\nWe provide a subpackage for htmx integration. [Read more about htmx integration here](htmx/README.md).\n\n## Examples\n\nFor hands-on examples showcasing the usage of `elem`, you can find sample implementations in the `examples/` folder of the repository. Dive into the examples to get a deeper understanding of how to leverage the library in various scenarios.\n\n[Check out the examples here.](./examples)\n\n## Tutorials \u0026 Guides\n\nDive deeper into the capabilities of `elem` and learn best practices through our collection of tutorials and guides:\n\n- [Building a Counter App with htmx, Go Fiber, and elem-go](https://dev.to/chasefleming/building-a-counter-app-with-htmx-go-fiber-and-elem-go-9jd/)\n- [Building a Go Static Site Generator Using elem-go](https://dev.to/chasefleming/building-a-go-static-site-generator-using-elem-go-3fhh)\n\nStay tuned for more tutorials and guides in the future!\n\n## Contributing\n\nContributions are welcome! If you have ideas for improvements or new features, please open an issue or submit a pull request.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchasefleming%2Felem-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchasefleming%2Felem-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchasefleming%2Felem-go/lists"}