{"id":23159204,"url":"https://github.com/jogemu/ob_html","last_synced_at":"2025-04-04T18:42:11.858Z","repository":{"id":225057760,"uuid":"764949717","full_name":"jogemu/ob_html","owner":"jogemu","description":"Seamlessly generate HTML with PHP functions. Use named arguments to set attributes, neatly nest tags and allow HTML forms to update PHP variables.","archived":false,"fork":false,"pushed_at":"2025-03-22T14:45:25.000Z","size":36,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-22T15:32:18.031Z","etag":null,"topics":["html-form","html-metadata","keyword-arguments","named-arguments","nested-tags","output-buffering","passing-by-reference","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jogemu.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":"2024-02-29T02:06:29.000Z","updated_at":"2025-03-22T14:45:28.000Z","dependencies_parsed_at":"2024-04-29T02:30:15.518Z","dependency_job_id":"df35e12e-5fb5-4a4e-8ba6-7695b9305ae3","html_url":"https://github.com/jogemu/ob_html","commit_stats":null,"previous_names":["jogemu/ob_html"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jogemu%2Fob_html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jogemu%2Fob_html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jogemu%2Fob_html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jogemu%2Fob_html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jogemu","download_url":"https://codeload.github.com/jogemu/ob_html/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247234844,"owners_count":20905852,"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":["html-form","html-metadata","keyword-arguments","named-arguments","nested-tags","output-buffering","passing-by-reference","php"],"created_at":"2024-12-17T22:32:46.301Z","updated_at":"2025-04-04T18:42:11.850Z","avatar_url":"https://github.com/jogemu.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ob_html.php\nSeamlessly generate HTML with PHP functions. Use named arguments to set attributes, neatly nest tags and allow HTML forms to update PHP variables. Designed to be compact and easy to understand, even in deeply nested scopes. The native control structures of PHP allow maximum flexibility while keeping the barrier to entry low.\n\n## Quick start\nEcho shows the expected output of the previous call.\n\n```php\n\u003c?php require 'ob_html.php';\np('Lorem ipsum', id: 'paragraph');\necho '\u003cp id=\"paragraph\"\u003eLorem ipsum\u003c/p\u003e';\n```\n\nPositional arguments are [content][anatomy] and [named arguments] are [attributes][anatomy]. Some elements allow arrays, where each entry is placed in its own child element like a list item. A more detailed description and further exceptions can be found [here](#special-array-interpretations).\n\n[named arguments]: https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments\n[anatomy]: https://developer.mozilla.org/en-US/docs/Learn_web_development/Getting_started/Your_first_website/Creating_the_content#anatomy_of_an_html_element\n\n```php\n\u003c?php require 'ob_html.php';\nul(['Lorem', 'ipsum']);\necho '\u003cul\u003e\u003cli\u003eLorem\u003c/li\u003e\u003cli\u003eipsum\u003c/li\u003e\u003c/ul\u003e';\ndl(['Lorem'=\u003e'ipsum', 'dolor'=\u003e'sit']);\necho '\u003cdl\u003e\u003cdt\u003eLorem\u003c/dt\u003e\u003cdd\u003eipsum\u003c/dd\u003e\u003cdt\u003edolor\u003c/dt\u003e\u003cdd\u003esit\u003c/dd\u003e\u003c/dl\u003e';\n```\n\nNest tags by using a tag as an argument or provide a function to do loops or exit and re-enter PHP interpretation as needed. Variables from the parent scope can be made accessible with `function() use (...) {}` or [arrow functions](https://www.php.net/manual/en/functions.arrow.php).\n\n```php\n\u003c?php require 'ob_html.php';\ndiv(\n  p('Lorem ipsum', id: 'paragraph'),\n  article(function() {\n    p('Lorem ipsum', id: 'paragraph');\n    ?\u003e\u003cp\u003eLorem ipsum\u003c/p\u003e\u003c?php\n    for($i = 0; $i \u003c 10; $i++) {}\n  })\n);\n```\n\nIf a [combined getter and setter](https://martinfowler.com/bliki/OverloadedGetterSetter.html) is passed as value of a form input, user input will automatically set that value. For this to happen, the `input()`, `select()`, `textarea()` or `button()` must have a `name` and be in a `\u003cform\u003e`. Inputs that are `readonly` or `disabled` do not overwrite their variables. The optional parameter `ob_action` may provide a function that is called on form submission.\n\n```php\n\u003c?php require 'ob_html.php';\nclass User {\n  public function __construct(private string $name, private int $age) {}\n  public function __call($n, $v) { return $v ? $this-\u003e$n = $v[0] : $this-\u003e$n; }\n  public function __get($n) { return fn($v) =\u003e $this-\u003e$n($v); }\n  public function save() { echo 'Validate and save to database/session'; }\n}\n$user = new User('John Doe', 0);\nform(\n  textarea('Name', value: $user-\u003ename, name: 'name'),\n  // echo '\u003clabel\u003e\u003ctextarea name=\"name\"\u003eJohn Doe\u003c/textarea\u003e\u003cspan\u003eName\u003c/span\u003e\u003c/label\u003e';\n  input('Age', value: $user-\u003eage, type: 'number', name: 'age'),\n  // echo '\u003clabel\u003e\u003cinput type=\"number\" name=\"age\" value=\"0\"/\u003e\u003cspan\u003eAge\u003c/span\u003e\u003c/label\u003e';\n  button('Submit', type:'submit', name: 'submit', ob_action: $user-\u003esave),\n  // echo '\u003cbutton type=\"submit\" name=\"submit\"\u003eSubmit\u003c/button\u003e';\n  method: 'post'\n);\n```\n\nUltimately, the essential HTML elements are still missing. Call the return value of `require 'ob_html.php'` to add a `\u003ctitle\u003e`, stylesheets and metadata.\n\n```php\n\u003c?php (require 'ob_html.php')(\n  title: 'title',\n  lang: 'en',\n\n  // optional metas\n  description: 'meta description',\n  keywords: ['Lorem', 'ipsum'],\n  author: 'author',\n  // ...: ...\n\n  base: '.',\n  // common links\n  manifest: 'manifest.json',\n  stylesheets: ['stylesheet.css'],\n  scripts: ['script.js'],\n  translations: ['de'=\u003e'de.php'],\n  // other links\n  links: [\n    ['rel'=\u003e'icon', 'href'=\u003e'favicon.svg']\n  ]\n);\n\np('I am a child of tag body.');\n```\n\n## Functions\nA list of supported functions should not be necessary by design. Assuming familiarity with [HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), simply use the functions of the respective name.\n\n### Intentionally excluded\n* Essentials and metadata (generated via return or `html()`)\n  * `\u003c!DOCTYPE html\u003e`, `\u003chead\u003e`, `\u003cbody\u003e`\n  * `\u003ctitle\u003e`, `\u003cmeta\u003e`, `\u003clink\u003e`, `\u003cbase\u003e`\n* Items and captions (generated via permitted parent)\n  * `\u003cli\u003e`, `\u003cdt\u003e`, `\u003cdd\u003e`\n  * `\u003coption\u003e`, `\u003coptgroup\u003e`\n  * `\u003ccaption\u003e`, `\u003cfigcaption\u003e`, `\u003clegend\u003e`, `\u003csummary\u003e`\n  * `\u003ctr\u003e`, `\u003ctd\u003e`, `\u003cth\u003e`, `\u003ctbody\u003e`, `\u003cthead\u003e`, `\u003ctfoot\u003e` `\u003ccol\u003e`, `\u003ccolgroup\u003e`\n  * `\u003csource\u003e`, `\u003ctrack\u003e`, `\u003carea\u003e`\n* Conflicts with native PHP functions or reserved keywords\n  * `\u003cheader\u003e` =\u003e `intro()`\n  * `\u003cvar\u003e` =\u003e `variable()`\n  * `\u003ctime\u003e` =\u003e `datetime()`\n* Obsolete and deprecated elements\n\n### Special array interpretations\nIn this compact list, the meaning of a string depends on the quotation marks used. The current content of a string is the placeholder and represents a place where content can be placed. For single quotes (`'`) the placeholder is the tag of the element that contains the content. With double quotes (`\"`) the tag must be inferred from the context and has an attribute with the placeholder as the name and the content as the value.\n\n* `ul(['li', ...])`, `ol(['li', ...])`, `menu(['li', ...])`\n* `dl(['dt'=\u003e'dd', ...])`\n* `select('label', options: [\"value\"=\u003e'option', 'optgroup'=\u003e[\"value\"=\u003e'option'], ...])`\n* `datalist(options: [\"value\", ...])`\n* `[\"href\", ...]` for `audio(sources: $, tracks: $)`, `picture(sources: $)`, `video(sources: $, tracks: $)`\n* `ruby([[''=\u003e'rt'], ...], 'rp', 'rp')`\n\n### Limitations\nThe definition of so many functions, some with short names, is likely to cause conflicts. The advantages of simple coding hopefully outweigh the disadvantages. Although some type of injection is prevented, in many places injection prevention would be too restrictive. Therefore, this should happen on a level that is built on top of these functions. The same also applies to validation. In particular, the detection of missing values requires additional logic.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjogemu%2Fob_html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjogemu%2Fob_html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjogemu%2Fob_html/lists"}