{"id":15099892,"url":"https://github.com/bcrist/zkittle","last_synced_at":"2026-01-31T16:03:36.127Z","repository":{"id":239254923,"uuid":"799002074","full_name":"bcrist/zkittle","owner":"bcrist","description":"A little Zig template engine","archived":false,"fork":false,"pushed_at":"2025-02-14T02:34:27.000Z","size":192,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-08T08:03:42.856Z","etag":null,"topics":["file-format","template","template-engine","templates","vscode-extension","zig","zig-library","zig-package","ziglang"],"latest_commit_sha":null,"homepage":"","language":"Zig","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/bcrist.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-05-10T23:40:05.000Z","updated_at":"2025-02-14T02:34:30.000Z","dependencies_parsed_at":"2025-02-14T03:24:02.034Z","dependency_job_id":"e826e215-edbd-4e68-8d1c-71e5348f3911","html_url":"https://github.com/bcrist/zkittle","commit_stats":null,"previous_names":["bcrist/zkittle"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bcrist/zkittle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcrist%2Fzkittle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcrist%2Fzkittle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcrist%2Fzkittle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcrist%2Fzkittle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bcrist","download_url":"https://codeload.github.com/bcrist/zkittle/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcrist%2Fzkittle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28947567,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T14:26:55.697Z","status":"ssl_error","status_checked_at":"2026-01-31T14:26:52.545Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["file-format","template","template-engine","templates","vscode-extension","zig","zig-library","zig-package","ziglang"],"created_at":"2024-09-25T17:40:34.996Z","updated_at":"2026-01-31T16:03:36.110Z","avatar_url":"https://github.com/bcrist.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Zkittle\n\nA basic templating language for Zig programs.\n\nThe name is pronounced like \"skittle,\" not \"zee kittle\".\n\n## Syntax\n\n    A template always starts with \"literal\" text.\n    i.e. text that will just be included in the final document verbatim.\n\n    You can add data to your templates by surrounding a \\\\command block// with double slashes.\n    \n    Whitespace inside command blocks is ignored, and it's legal to have an empty \\\\// command block.\n\n    \\\\ $ If a command block contains a $, then //\n    everything else in that command block is considered a comment.\n    \n    \\\\$ If there is no // to close a block on the same line, it ends at the end of the line.\n    \\\\$ The final newline character is not included in the output document in this case.\n    \\\\$ Since comments end at the end of their containing command block, they are also at most one line.\n\n    Templates are evaluated using a \"data context\", which is usually a struct value.\n    The \\\\identifiers// in the command block reference fields of the data struct.\n    You can reference nested data structures the same way you would in Zig: \\\\ parent_field.child_field //\n\n    Individual elements of \"collections\" (arrays and slices) are accessed with '.': \\\\ some_array.0 //\n    Optionals are treated as a collection of size 0 or 1.\n    The length of a collection can be printed with: \\\\ some_array.# //\n    Accessing an out-of-bounds element is allowed; it becomes a void value (printing it is a no-op).\n\n    Tagged union fields can be accessed the same way as structs, but only the active field will resolve\n    to actual data; inactive fields will resolve to void.\n\n    Values of type void are considered a special 'nil' value.  This includes accessing a struct field\n    that doesn't exist, an enum or union tag that isn't active (or doesn't exist), or a collection index\n    that's out of bounds, as well as data explicitly declared to have a type of `void` or\n    `@TypeOf(undefined)`.  All values have a \\\\value.@exists// pseudo-field which converts the value to\n    a bool, where nil becomes false, and anything else becomes true.\n\n    The special \\\\*// syntax represents the whole data context (similar to the \"this\" or \"self\" pointer in\n    some programming languages).  It can be useful when the current data context is not a struct, union,\n    or collection.\n\n    Identifiers that aren't qualified by '^' can reference a field in the current context, or the first\n    parent context that has a non-nil value for the field.  This is useful because sometimes a template\n    is designed to be imported, but you don't know if it will be inside a \"within\" block.  You can\n    explicitly search only the current context by using \\\\*.field// instead of \\\\field//.\n\n    You can \"push\" a new data context with the ':' operator (a.k.a \"within\").\n    This can be useful if you want to access multiple fields of a deeply nested struct.\n    For example, instead of:\n        First Name: \\\\phonebook.z.ziggleman.0.first//\n        Last Name: \\\\phonebook.z.ziggleman.0.last//\n        Phone Number: \\\\phonebook.z.ziggleman.0.phone//\n    we could instead write:\n    \\\\ phonebook.z.ziggleman.0:\n        First Name: \\\\first//\n        Last Name: \\\\last//\n        Phone Number: \\\\phone//\n    \\\\ ~\n    Note that the sequence does not end at the end of the command block, so that it can include\n    literal text easily.  Instead, the ~ character ends the region.\n\n    When the data selected by a \"within\" block is a collection, the sequence will be evaluated once\n    for each item in the collection.  You can print the current index with the \\\\@index// syntax.  When\n    not inside a \"within\" region, nothing will be output.  You can access the entire collection\n    instead of an individual item with \\\\ ^* //.  You can access the \"outer\" data context with \\\\ ^^* //.\n    (note this also works when the within block isn't a collection)\n    If you have nested \"within\" blocks, the '^' prefixes can be chained as needed.\n\n    The conditional '?' operator only evaluates its subsequent region when its data value is \"truthy,\"\n    but it does not push a new data context:\n    \\\\ should_render_section? // whatever \\\\ ~\n    Boolean false, the number zero, and empty collections (including void-like values) are considered\n    falsey; all other values are truthy.\n\n    Both ':' and '?' regions may contain a ';' before the '~' to create an \"otherwise\" region.\n    This region will only be evaluated if the first region is not evaluated. e.g.\n    \\\\ has_full_name ? full_name ; first_name last_name ~ //\n\n    \\\\x / y// is mostly equivalent to \\\\x? x ; y ~// except that the former can be used as an\n    expression, while the latter always just prints x or y.  Similarly \\\\x | y// is corresponds to\n    \\\\x.@exists? x ; y ~// in the same way.\n\n    Application-specific extensions can be added by adding functions to the data context.  These\n    functions will be passed the writer, escape functions, and the root data context, as well as\n    a list of any parameters from the template.  Calling a function from a template looks like\n    this: \\\\ :my_func param1 param2 param3 //  Note that \":\" is used for both function calls and\n    \"within\" blocks.  In order to be treated as a function call, it must be followed immediately\n    by a non-whitespace character.\n\n    By default all strings will be printed with an HTML escape function.\n    This can be overridden or disabled in code when generating other types of documents.\n    You can also disable it for a specific expression with \\\\ @raw some_value //.\n    An alternative escaping function can be used for specific expressions with \\\\ @url some_value //.\n    By default, this will escape using percent encoding; suitable for embedding arbitrary data in URLs.\n\n    Within command blocks, you can use string literals, wrapped in double quotes, anywhere an\n    expression is expected.  Note that no escape sequences are supported; the string literal simply\n    ends as soon as the next double quote is seen, so string literals can never contain a double\n    quote.  Often string literals are functionally equivalent to closing the command block and\n    opening another immediately after:\n    \\\\ \"Hellorld!\"  //Hellorld!\\\\\n    \\\\ $ but string literals also let you do things like:\n    \\\\ @raw \"\u003ctable\u003e\" $ prevent escaping of HTML tags\n    \\\\ :func \"asdf\" $ pass literals to a function\n\n    String literals can also be used to access fields with names that aren't valid zkittle identifiers.\n    This only works when used after the \".\" or `^` operators:\n    \\\\ something.\"has weird fields\".\"and even recursive ones\"\n    \\\\ *.\"I am in the current context\"\n    \\\\ ^^\"I'm in the parent context\"\n\n    The \\\\ @include \"path/to/template\" // syntax can be used to pull the entire content of another\n    template into the current one.\n    Note that this happens at compile time, not at runtime (the template source is provided to the\n    template parser by a callback).\n\n    The \\\\ @resource \"whatever\" // syntax works similarly to @include, but instead of interpreting\n    the data returned by the callback as template source,\n    it treats it as a raw literal to be printed.\n\n    Sometimes you may want to render only a part of a template in some cases.  To facilitate this,\n    you can define a \\\\ #fragment_name // to refer to part of the template, ending with the \\\\~//\n    operator.  This doesn't affect how the overall template is rendered, but allows you to access\n    the sub-template by name from code.  See https://htmx.org/essays/template-fragments/ for more\n    information about how this technique might be useful.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcrist%2Fzkittle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbcrist%2Fzkittle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcrist%2Fzkittle/lists"}