{"id":19509557,"url":"https://github.com/raspi/lomake","last_synced_at":"2025-04-26T03:31:56.517Z","repository":{"id":57601714,"uuid":"128199838","full_name":"raspi/lomake","owner":"raspi","description":"HTML Form generator from Go structs","archived":false,"fork":false,"pushed_at":"2018-07-06T01:39:42.000Z","size":20,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T07:23:36.899Z","etag":null,"topics":["form","golang","html","json","reflection"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raspi.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}},"created_at":"2018-04-05T12:00:05.000Z","updated_at":"2021-04-21T10:55:51.000Z","dependencies_parsed_at":"2022-09-26T20:00:38.675Z","dependency_job_id":null,"html_url":"https://github.com/raspi/lomake","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspi%2Flomake","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspi%2Flomake/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspi%2Flomake/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspi%2Flomake/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raspi","download_url":"https://codeload.github.com/raspi/lomake/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250926824,"owners_count":21509044,"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":["form","golang","html","json","reflection"],"created_at":"2024-11-10T23:12:28.196Z","updated_at":"2025-04-26T03:31:56.210Z","avatar_url":"https://github.com/raspi.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lomake\nHTML Form generator from Go structs\n\nWith lomake HTML form for registration:\n```html\n\u003cform id=\"pageform\" action=\"/api/account/register.json\" method=\"post\"\u003e\n    \u003c!-- User --\u003e\n    \u003cdiv class=\"form-group required\"\u003e\u003clabel for=\"Username\"\u003e* User name\u003c/label\u003e\n        \u003cinput class=\"form-control\" type=\"text\"\n               name=\"Username\" id=\"Username\"\n               value=\"\"\n               placeholder=\"Enter your user name\"/\u003e\n    \u003c/div\u003e\n    \n    \u003c!-- Email --\u003e\n    \u003cdiv class=\"form-group required\"\u003e\u003clabel for=\"EmailAddress\"\u003e* E-mail address\u003c/label\u003e\n        \u003cinput class=\"form-control\"\n               type=\"text\"\n               name=\"EmailAddress\"\n               id=\"EmailAddress\" value=\"\"\n               placeholder=\"Enter your e-mail\"/\u003e\n    \u003c/div\u003e\n\n    \u003c!-- Password --\u003e\n    \u003cdiv class=\"form-group required\"\u003e\u003clabel for=\"Password\"\u003e* Password\u003c/label\u003e\n        \u003cinput class=\"form-control\" type=\"password\"\n               name=\"Password\" id=\"Password\"\n               value=\"\"\n               placeholder=\"%mYs3cr37p455w0rd\"/\u003e\n    \u003c/div\u003e\n    \u003c!-- Password (again) --\u003e\n    \u003cdiv class=\"form-group required\"\u003e\u003clabel for=\"Password2\"\u003e* Password (again)\u003c/label\u003e\n        \u003cinput class=\"form-control\"\n               type=\"password\"\n               name=\"Password2\"\n               id=\"Password2\" value=\"\"\n               placeholder=\"%mYs3cr37p455w0rd\"/\u003e\n    \u003c/div\u003e\n\n    \u003c!-- Submit --\u003e\n    \u003cinput id=\"formsubmit\" type=\"submit\" class=\"btn-primary\" value=\"Send\"/\u003e\n\u003c/form\u003e\n```\nBecomes:\n```go\ntype RegisterForm struct {\n\tUsername     string `json:\",\" lomaketype:\"input.text\"`\n\tEmailAddress string `json:\",\" lomaketype:\"input.text\"`\n\tPassword     string `json:\",\" lomaketype:\"input.password\"`\n\tPassword2    string `json:\",\" lomaketype:\"input.password\"`\n}\n```\n\nIt also supports internationalization (i18n) out of the box, so that all field placeholders etc can be translated.\n\n```go\npackage main\n\nimport (\n\t\"html/template\"\n\t\"log\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"bytes\"\n\t\"golang.org/x/text/message\"\n\t\"golang.org/x/text/language\"\n\t\"github.com/raspi/lomake\"\n)\n\ntype RegisterForm struct {\n\tUsername     string `json:\",\" lomaketype:\"input.text\"`\n\tEmailAddress string `json:\",\" lomaketype:\"input.text\"`\n\tPassword     string `json:\",\" lomaketype:\"input.password\"`\n\tPassword2    string `json:\",\" lomaketype:\"input.password\"`\n}\n\nvar pageTemplate = `\n\u003cform id=\"pageform\" action=\"/api/account/register.json\" method=\"post\"\u003e\n\t{{- .Form -}}\n    \u003cinput id=\"formsubmit\" type=\"submit\" class=\"btn-primary\" value=\"{{ T \"form.submit\" }}\" /\u003e\n\u003c/form\u003e\n`\n\n// Get HTML\nfunc (f RegisterForm) HTML() template.HTML {\n\t// TODO cache\n\tout, err := lomake.New(\u0026f)\n\tif err != nil {\n\t\tlog.Fatalf(`error=%v`, err)\n\t\treturn ``\n\t}\n\n\treturn out\n}\n\nfunc main() {\n\n\t// -- Global:\n\ttranslator := message.NewPrinter(language.Finnish)\n\n\tt := template.New(\"\")\n\n\tt = t.Funcs(template.FuncMap{\n\t\t\"T\": func(s string, a ...interface{}) string {\n\t\t\tref := message.Key(s, fmt.Sprintf(`NOT TRANSLATED: '%v'`, s))\n\t\t\treturn translator.Sprintf(ref, a...)\n\t\t},\n\t})\n\n\tt.Parse(pageTemplate)\n\n\tlomake.Translator = translator\n\tlomake.HTMLTemplate = t\n\n\t// -- Page (view):\n\tvar buf bytes.Buffer\n\tpage, err := t.Clone()\n\n\t// Render form\n\tvar form RegisterForm\n\tview := struct {\n\t\tForm template.HTML\n\t}{\n\t\tForm: form.HTML(),\n\t}\n\n\tpage.Execute(\u0026buf, \u0026view)\n\tfmt.Println(buf.String())\n}\n\n// Ignore, used to get the package name\ntype Empty struct{}\n\n// Initialize translations\nfunc init() {\n\tpkgName := reflect.TypeOf(Empty{}).PkgPath()\n\n\tprefix := fmt.Sprintf(`lomake.%v`, pkgName)\n\n\tt := make(map[string]map[language.Tag]string)\n\n\tt[fmt.Sprintf(`%v.Username`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: `User name`,\n\t\tlanguage.Finnish: `Käyttäjätunnus`,\n\t}\n\n\tt[fmt.Sprintf(`%v.Username.placeholder`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: `Enter your user name`,\n\t\tlanguage.Finnish: `Syötä käyttäjätunnuksesi`,\n\t}\n\n\n\tt[fmt.Sprintf(`%v.EmailAddress`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: `E-mail address`,\n\t\tlanguage.Finnish: `Sähköpostiosoite`,\n\t}\n\n\tt[fmt.Sprintf(`%v.EmailAddress.placeholder`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: `Enter your e-mail`,\n\t\tlanguage.Finnish: `Syötä sähköpostiosoitteesi`,\n\t}\n\n\tt[fmt.Sprintf(`%v.Password`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: `Password`,\n\t\tlanguage.Finnish: `Salasana`,\n\t}\n\n\tt[fmt.Sprintf(`%v.Password2`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: `Password (again)`,\n\t\tlanguage.Finnish: `Salasana (uudestaan)`,\n\t}\n\n\tt[fmt.Sprintf(`%v.Password.placeholder`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: `%%mYs3cr37p455w0rd`,\n\t\tlanguage.Finnish: `sAl454N4%%`,\n\t}\n\n\tt[fmt.Sprintf(`%v.Password2.placeholder`, prefix)] = map[language.Tag]string{\n\t\tlanguage.English: t[fmt.Sprintf(`%v.Password.placeholder`, prefix)][language.English],\n\t\tlanguage.Finnish: t[fmt.Sprintf(`%v.Password.placeholder`, prefix)][language.Finnish],\n\t}\n\n\tt[`form.submit`] = map[language.Tag]string{\n\t\tlanguage.English: `Send`,\n\t\tlanguage.Finnish: `Lähetä`,\n\t}\n\n\tfor key,_ := range t {\n\t\tfor lang, v := range t[key] {\n\t\t\tmessage.SetString(lang, key, v )\n\t\t}\n\t}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraspi%2Flomake","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraspi%2Flomake","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraspi%2Flomake/lists"}