{"id":19789517,"url":"https://github.com/webfreak001/webconfig","last_synced_at":"2026-03-10T12:31:24.883Z","repository":{"id":146628705,"uuid":"97722610","full_name":"WebFreak001/WebConfig","owner":"WebFreak001","description":"HTML settings generator \u0026 server side validator from any struct","archived":false,"fork":false,"pushed_at":"2019-01-10T11:31:20.000Z","size":156,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-01T01:38:34.705Z","etag":null,"topics":["backend","configuration","css","css3","dlang","frontend","generator","html","html5"],"latest_commit_sha":null,"homepage":"https://webfreak001.github.io/WebConfig/package.html","language":"D","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WebFreak001.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2017-07-19T13:58:56.000Z","updated_at":"2020-09-17T15:09:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"0c158b8e-fc2c-4e61-9087-8c5093026992","html_url":"https://github.com/WebFreak001/WebConfig","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/WebFreak001/WebConfig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2FWebConfig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2FWebConfig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2FWebConfig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2FWebConfig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WebFreak001","download_url":"https://codeload.github.com/WebFreak001/WebConfig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebFreak001%2FWebConfig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30333442,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["backend","configuration","css","css3","dlang","frontend","generator","html","html5"],"created_at":"2024-11-12T06:33:49.230Z","updated_at":"2026-03-10T12:31:24.797Z","avatar_url":"https://github.com/WebFreak001.png","language":"D","funding_links":[],"categories":[],"sub_categories":[],"readme":"# web-config\n\n[![Dub version](https://img.shields.io/dub/v/web-config.svg)](https://code.dlang.org/packages/web-config)\n[![Dub downloads](https://img.shields.io/dub/dt/web-config.svg)](https://code.dlang.org/packages/web-config)\n\nA HTML settings/properties generator using D's Compile Time magic.\n\nBy default there is **no CSS**. Inputs will be ugly because the default generator does not emit any line breaks. You could make a custom generator and call the `DefaultInputGenerator` methods and add a line break but the recommended way is by making the `\u003clabel\u003e` elements simply `display: block`.\n\nYou need to serve the CSS inside your head or add it to your existing stylesheet. Here are some preset styles (all styles are assuming you added class=\"settings\" to any parent element or the form itself):\n\n* [Material Design (Lite)](styles/material.min.css) (small \u0026 simplistic)\n\n_PRs Welcome!_\n\n## Generation\n\nThe default generated output looks like this (but more minified):\n\n```html\n\u003cform action=\"/settings\" method=\"POST\"\u003e \u003c!-- You can change action \u0026 method and even add raw attributes like a class name --\u003e\n\t\u003clabel\u003e\n\t\t\u003c!--\n\t\t\tYou can change this entire construct by\n\t\t\tproviding a custom input generator. But\n\t\t\tchanging the CSS is often enough.\n\t\t--\u003e\n\t\t\u003cspan\u003eMy Setting\u003c/span\u003e\n\t\t\u003cinput type=\"text\" value=\"a tree\"/\u003e\n\t\u003c/label\u003e\n\t...\n\t\u003cinput type=\"submit\" value=\"Save\"/\u003e\n\u003c/form\u003e\n\u003c!-- Everything from here is replacable --\u003e\n\u003cscript id=\"_setting_script_\"\u003e\n...\n\u003c/script\u003e\n```\n\n## Example\n\n```d\nimport webconfig;\n//import webconfig.aliases; // For shorter UDAs\n\nenum FavoriteFood\n{\n\t@settingTranslation(null, \"Fish\")\n\t@settingTranslation(\"de\", \"Fisch\")\n\t@settingTranslation(\"ja\", \"魚\")\n\tfish,\n\n\t@settingTranslation(null, \"Meat\")\n\t@settingTranslation(\"de\", \"Fleisch\")\n\t@settingTranslation(\"ja\", \"肉\")\n\tmeat,\n\n\t@settingTranslation(null, \"Vegetables\")\n\t@settingTranslation(\"de\", \"Gemüse\")\n\t@settingTranslation(\"ja\", \"野菜\")\n\tvegetables,\n\n\t@settingTranslation(null, \"Fruits\")\n\t@settingTranslation(\"de\", \"Obst\")\n\t@settingTranslation(\"ja\", \"フルーツ\")\n\tfruit\n}\n\nenum Country\n{\n\tnone, AF, AX, AL, DZ, AS, AD, AO, AI, AQ, AG, AR, AM, AW, AC, AU, AT, AZ, BS, BH, BD, BB, BY, BE, BZ, BJ, BM,\n\tBT, BO, BA, BW, BR, IO, VG, BN, BG, BF, BI, KH, CM, CA, IC, CV, BQ, KY, CF, EA, TD, CL, CN, CX, CC, CO, KM,\n\tCG, CD, CK, CR, CI, HR, CU, CW, CY, CZ, DK, DG, DJ, DM, DO, EC, EG, SV, GQ, ER, EE, ET, FK, FO, FJ, FI, FR,\n\tGF, PF, TF, GA, GM, GE, DE, GH, GI, GR, GL, GD, GP, GU, GT, GG, GN, GW, GY, HT, HN, HK, HU, IS, IN, ID, IR,\n\tIQ, IE, IM, IL, IT, JM, JP, JE, JO, KZ, KE, KI, XK, KW, KG, LA, LV, LB, LS, LR, LY, LI, LT, LU, MO, MK, MG,\n\tMW, MY, MV, ML, MT, MH, MQ, MR, MU, YT, MX, FM, MD, MC, MN, ME, MS, MA, MZ, MM, NA, NR, NP, NL, NC, NZ, NI,\n\tNE, NG, NU, NF, KP, MP, NO, OM, PK, PW, PS, PA, PG, PY, PE, PH, PN, PL, PT, PR, QA, RE, RO, RU, RW, WS, SM,\n\tST, SA, SN, RS, SC, SL, SG, SX, SK, SI, SB, SO, ZA, GS, KR, SS, ES, LK, BL, SH, KN, LC, MF, PM, VC, SD, SR,\n\tSJ, SZ, SE, CH, SY, TW, TJ, TZ, TH, TL, TG, TK, TO, TT, TA, TN, TR, TM, TC, TV, UM, VI, UG, UA, AE, GB, US,\n\tUY, UZ, VU, VA, VE, VN, WF, EH, YE, ZM, ZW\n}\n\nenum SocialMedia\n{\n\ttwitter = 1 \u003c\u003c 0,\n\tfacebook = 1 \u003c\u003c 1,\n\tmyspace = 1 \u003c\u003c 2,\n}\n\nstruct Config\n{\n\t@requiredSetting // Must be filled out\n\t@nonAutomaticSetting // Don't auto sync when typing\n\t@emailSetting string userEmail;\n\tbool married;\n\t@urlSetting @settingLength(64) string resourceURI;\n\t// OR\n\t@settingLength(64) URL myWebsite;\n\t@multilineSetting @settingLength(1000) string aboutMe;\n\t@rangeSetting @settingRange(0, 10) int rating;\n\t@timeSetting string favoriteTimeOfDay;\n\t// OR\n\tTimeOfDay leastFavoriteTimeOfDay;\n\t@weekSetting string bestWeekYouHad;\n\t@monthSetting string firstMonthOfWork;\n\t// Timezone-less\n\t@datetimeLocalSetting string birthdayTimeAndDate;\n\t// OR\n\tDateTime myChildsBirthdayTimeAndDate;\n\t@dateSetting string myMothersBirthday;\n\t// OR\n\tDate myFathersBirthday;\n\t@colorSetting string favoriteColor;\n\t@disabledSetting string someInformation = \"Just a hint, nothing changable\";\n\tCountry favoriteCountry;\n\t@settingTranslation(\"de\", \"Lieblingsessen\")  // Translation of labels (only in translation contexts inside web interfaces)\n\t@settingTranslation(\"ja\", \"好きな食べ物\")  // translations require at least vibe.d 0.8.1-alpha.3 to work\n\t@optionsSetting FavoriteFood favoriteFood;\n\tBitFlags!SocialMedia usedSocialMedia;\n\t@settingTitle(\"If you don't have any you can still say 1 because you have yourself.\")  // Hover \u0026 validation text\n\t@settingMin(1) int numberOfFriends;\n\t@settingRange(0, 100) @settingStep(0.1) double englishSkillLevelPercentage;\n\t@settingMax(10) ubyte orderedProductCount;\n\t@settingLabel(\"Accept terms of service\") @requiredSetting bool acceptTOS;\n\t@settingPattern(`(ISBN\\s+)?\\d{3}-\\d-\\d{5}-\\d{3}-\\d`) string favoriteBookISBN;\n}\n\nConfig settingsInstance; // You might fetch \u0026 save this per user or have it global like here, web-config only changes the contents of the struct\n\n// Actual vibe.d routes: (GET /settings, POST /settings, POST /api/settings)\nrouter.get(\"/settings\", delegate(scope req, scope res) @safe{\n\tstring settings = renderSettings(settingsInstance);\n\tres.writeBody(html.format(settings), \"text/html\");\n});\nrouter.post(\"/settings\", delegate(scope req, scope res) @safe{\n\t// no-js \u0026 nonautomatic setting route\n\tauto ret = req.processSettings(settingsInstance);\n\tstring settings = renderSettings(settingsInstance, ret);\n\tif (ret)\n\t{\n\t\t// Something changed, you can save here\n\t}\n\tres.render!(\"settings.dt\", settings); // use with `|!= settings` in diet\n});\nrouter.post(\"/api/setting\", delegate(scope req, scope res) @safe{\n\t// js route called for each individual setting\n\tif (req.processSettings(settingsInstance))\n\t{\n\t\t// Save settings\n\t\tres.writeBody(\"\", 204); // Send 200 or 204\n\t}\n\telse\n\t\tres.writeBody(\"\", HTTPStatus.badRequest);\n});\n```\n\n(See unittest in [source/webconfig/package.d](source/webconfig/package.d) for HTML of this example)\n\n![Demo Config](demo.png)\n\n[Documentation](https://webfreak001.github.io/WebConfig/package.html)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfreak001%2Fwebconfig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebfreak001%2Fwebconfig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfreak001%2Fwebconfig/lists"}