{"id":15049311,"url":"https://github.com/vbprojects/exhtml","last_synced_at":"2026-02-04T22:36:05.400Z","repository":{"id":233373970,"uuid":"786231495","full_name":"vbprojects/exhtml","owner":"vbprojects","description":"Simple HTML templating language written in C99","archived":false,"fork":false,"pushed_at":"2024-06-02T21:02:54.000Z","size":29704,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-14T20:41:45.541Z","etag":null,"topics":["c99","html5","preprocessor","template-language"],"latest_commit_sha":null,"homepage":"https://vbprojects.github.io/vpml/","language":"C","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/vbprojects.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":"2024-04-13T20:18:50.000Z","updated_at":"2024-06-02T21:02:57.000Z","dependencies_parsed_at":"2024-04-18T18:42:46.878Z","dependency_job_id":"a9300620-4449-4848-94d7-684037e2161b","html_url":"https://github.com/vbprojects/exhtml","commit_stats":null,"previous_names":["vbprojects/vpml","vbprojects/exhtml"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vbprojects/exhtml","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbprojects%2Fexhtml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbprojects%2Fexhtml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbprojects%2Fexhtml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbprojects%2Fexhtml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vbprojects","download_url":"https://codeload.github.com/vbprojects/exhtml/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbprojects%2Fexhtml/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29098239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T21:05:08.033Z","status":"ssl_error","status_checked_at":"2026-02-04T21:04:53.031Z","response_time":62,"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":["c99","html5","preprocessor","template-language"],"created_at":"2024-09-24T21:19:41.078Z","updated_at":"2026-02-04T22:36:05.372Z","avatar_url":"https://github.com/vbprojects.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Exhtml - Personal Markup Language\n\n\nhttps://vbprojects.github.io/vpml/\n\nThis is a small project meant to make a parser and transpiler/preprocessor from my personal markup language (vpml) to html. The first implementation in VPMLR is written in base julia. The second implementation is written in C99 with only the standard library. The third is implemented in JavaScript. The C99 version is the most basic but smallest and fastest requiring only the standard library. The JavaScript version consists of vpj.js, which exposes a method process_string for compiling js strings into html and vpnj.js, which requires node for file io. vpnj.js can be compiled to a single executable with node js.\n\nvpml is a pythonic-esque way of writing html meant for use with css frameworks like tailwind. What differentiates this from tools like pug, haml, and ember is that the syntax assumes in most cases you are specifying classes. For Example,\n\n```\nhead\n  title\n    VPML - Example\n  link rel=\"stylesheet\" href=\"styles.css\"\nhtml\n# this is a comment\n    body #body bg-black\n        div #content bg-gray-800 #1\n            h1 bg-blue\n                Hello World\n            p\n#           this is a comment\n                raw This is my site\n        div #content bg-gray-800 #2\n            h1 bg-blue\n                Hello World\n\n```\n\nIf the first token of the line is not a valid html tag then the line is considered text. For lines that start with tags, any token that starts with # is considered an id. Any token that has an '=' char in it is considered an attribute. Otherwise, the token is considered a class. Tokens are delimited by ' '. Lines that are all whitespace characters or are empty are ignored. Lines that start with the char '#' are ignored.\n\n\u003c!-- vpc.c has a total non comment lines equal to 216 and an average cyclomatic complexity of 4 and a max of 10. --\u003e\n\u003c!-- gpp (general preprocessor) --\u003e\n\n\n```bash\nclang -O3 vpc.c -o bin/vpc.exe\nclang -O3 gpp.c -o bin/gpp.exe\n\ngpp index.vpml -o index.vpmlp \u0026\u0026 vpc index.vpmlp index.html\n```\n\nYou can build both with whatever C99 compiler you want. The reason the JS version exists is because it seems like even the most space efficient executables for compiling vpc to wasm are still nearly 36kb, the JS version minified is around 4.9kb.\n\nThe JS compiler includes a built in macro system which allows for text substitution in leaf elements of strings, and additional syntax for specifying the text of elements.\n\nMacros can be defined by starting a line as such `:macro !\u003cname_of_macro\u003e`\nThe text of an element can be defined as follows `tag [inside first tag] | \u003ctext\u003e`\n\nMacro names must start with ! and must be invoked by starting a line with `!\u003cmacro_name\u003e`\n\n```\n:macro !hello_world\n  div\n    h1 | @0\n    h2 | @1\n!helllo_world\n  Hello World!\n  div useless_class #useless_id | Also Hello World!\n```\n\n```\ndiv\n  h1\n    Hello World!\n  h2\n    Also Hello World!\n```\n\nMacros are only available to lines processed after their declaration. Raw strings are not tokenized and thus cannot have macro string interpolation\n\n```\n:macro !not_hello_world\n  div\n    h1\n      raw @0\n!not_hello_world\n  Hello World!\n```\n\n```\ndiv\n  h1\n    raw @0\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbprojects%2Fexhtml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvbprojects%2Fexhtml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbprojects%2Fexhtml/lists"}