{"id":13623952,"url":"https://github.com/fizzed/rocker","last_synced_at":"2025-05-14T13:08:42.760Z","repository":{"id":28902413,"uuid":"32427215","full_name":"fizzed/rocker","owner":"fizzed","description":"Java 8 optimized, memory efficient, speedy template engine producing statically typed, plain java objects","archived":false,"fork":false,"pushed_at":"2025-01-23T14:29:53.000Z","size":5737,"stargazers_count":761,"open_issues_count":45,"forks_count":91,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-04-14T22:07:15.883Z","etag":null,"topics":["java","templating","web"],"latest_commit_sha":null,"homepage":"","language":"Java","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/fizzed.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2015-03-17T23:52:08.000Z","updated_at":"2025-03-23T23:37:34.000Z","dependencies_parsed_at":"2024-01-03T01:25:50.697Z","dependency_job_id":"ae904957-85fa-4e6a-bce5-6d8c74ddeef8","html_url":"https://github.com/fizzed/rocker","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fizzed%2Frocker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fizzed%2Frocker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fizzed%2Frocker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fizzed%2Frocker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fizzed","download_url":"https://codeload.github.com/fizzed/rocker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254149974,"owners_count":22022852,"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":["java","templating","web"],"created_at":"2024-08-01T21:01:37.289Z","updated_at":"2025-05-14T13:08:37.746Z","avatar_url":"https://github.com/fizzed.png","language":"Java","readme":"# Rocker Templates by Fizzed\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.fizzed/rocker?color=blue\u0026style=flat-square)](https://mvnrepository.com/artifact/com.fizzed/rocker)\n\n## Automated Testing\n\nThe following Java versions and platforms are tested using GitHub workflows:\n\n[![Java 8](https://img.shields.io/github/actions/workflow/status/fizzed/rocker/java8.yaml?branch=master\u0026label=Java%208\u0026style=flat-square)](https://github.com/fizzed/rocker/actions/workflows/java8.yaml)\n[![Java 11](https://img.shields.io/github/actions/workflow/status/fizzed/rocker/java11.yaml?branch=master\u0026label=Java%2011\u0026style=flat-square)](https://github.com/fizzed/rocker/actions/workflows/java11.yaml)\n[![Java 17](https://img.shields.io/github/actions/workflow/status/fizzed/rocker/java17.yaml?branch=master\u0026label=Java%2017\u0026style=flat-square)](https://github.com/fizzed/rocker/actions/workflows/java17.yaml)\n[![Java 21](https://img.shields.io/github/actions/workflow/status/fizzed/rocker/java21.yaml?branch=master\u0026label=Java%2021\u0026style=flat-square)](https://github.com/fizzed/rocker/actions/workflows/java21.yaml)\n\n[![Linux x64](https://img.shields.io/github/actions/workflow/status/fizzed/rocker/java8.yaml?branch=master\u0026label=Linux%20x64\u0026style=flat-square)](https://github.com/fizzed/rocker/actions/workflows/java8.yaml)\n[![MacOS arm64](https://img.shields.io/github/actions/workflow/status/fizzed/rocker/macos-arm64.yaml?branch=master\u0026label=MacOS%20arm64\u0026style=flat-square)](https://github.com/fizzed/rocker/actions/workflows/macos-arm64.yaml)\n[![Windows x64](https://img.shields.io/github/actions/workflow/status/fizzed/rocker/windows-x64.yaml?branch=master\u0026label=Windows%20x64\u0026style=flat-square)](https://github.com/fizzed/rocker/actions/workflows/windows-x64.yaml)\n\nThe following platforms are tested using the [Fizzed, Inc.](http://fizzed.com) build system:\n\n[![Linux arm64](https://img.shields.io/badge/Linux%20arm64-passing-green)](buildx-results.txt)\n[![Linux riscv64](https://img.shields.io/badge/Linux%20riscv64-passing-green)](buildx-results.txt)\n[![Linux MUSL x64](https://img.shields.io/badge/Linux%20MUSL%20x64-passing-green)](buildx-results.txt)\n[![MacOS x64](https://img.shields.io/badge/MacOS%20x64-passing-green)](buildx-results.txt)\n[![Windows arm64](https://img.shields.io/badge/Windows%20arm64-passing-green)](buildx-results.txt)\n[![FreeBSD x64](https://img.shields.io/badge/FreeBSD%20x64-passing-green)](buildx-results.txt)\n[![OpenBSD x64](https://img.shields.io/badge/OpenBSD%20x64-passing-green)](buildx-results.txt)\n\n## Overview\n\nRocker is a Java 8+ optimized, near zero-copy rendering,\nspeedy template engine that produces statically typed, plain java object templates\nthat are compiled along with the rest of your project.  No more \"warm-up\" time\nin production, slow reflection-based logic, or nasty surprises that should have\nbeen caught during development.\n\nWrite your templates using an [intuitive, **tagless** syntax](docs/SYNTAX.md)\nwith standard Java expressions for logic, iteration, and values.  Use Rocker's\nspecial `?` presence operator for null-safe evaluation. All the heavy\nlifting is done by the Rocker parser during development -- which keeps the runtime\ndependencies down to just a handful of classes.  Rocker will parse your templates\nand generate well-documented Java source files (so you can easily inspect and\nunderstand how it works).\n\nIncludes the following features:\n\n* Templates are runtime compatible with Java 8+ -- using Lambdas and type inference under-the-hood\n* [Near zero-copy rendering](#near-zero-copy-rendering)\n* [Hot reload support in two flavors](#hot-reloading)\n* [Elegant, intuitive, tagless syntax](docs/SYNTAX.md) that infers when your logic ends for control / dynamic\n  content.  All dynamic / control code uses standard Java syntax.\n* A special `?` presence operator extends syntax for simplified handling of\n  null values.\n* Parsed templates become normal POJOs with defined arguments -- allowing you\n  to tap into your IDEs code completion, syntax highlighting, etc.\n* Support for injecting intermediate application-specific super classes during\n  parsing \u0026 generating phase  -- thereby creating your own app-specific template engine\n  where you can make implicit variables/methods available to all templates.\n* Since templates are just Java classes -- your logic / dynamic content can call\n  out to any other Java code. Your templates can be as advanced or as simple as\n  you need. No reflection used.\n* No runtime configuration/engine required -- there isn't any sort of RockerEngine\n  class required to execute templates.  Each compiled template is ready-to-go\n  and knows how to render itself.\n* Templates retain enough information about the original template to throw\n  exceptions at runtime (during render()) that let you track down the problematic line\n  in the original template source file.\n* GraalVM compatability if you leverage the new PlainText strategy of STATIC_BYTE_ARRAYS\n\n## Sponsorship \u0026 Support\n\n![](https://cdn.fizzed.com/github/fizzed-logo-100.png)\n\nProject by [Fizzed, Inc.](http://fizzed.com) (Follow on Twitter: [@fizzed_inc](http://twitter.com/fizzed_inc))\n\n**Developing and maintaining opensource projects requires significant time.** If you find this project useful or need\ncommercial support, we'd love to chat. Drop us an email at [ping@fizzed.com](mailto:ping@fizzed.com)\n\nProject sponsors may include the following benefits:\n\n- Priority support (outside of Github)\n- Feature development \u0026 roadmap\n- Priority bug fixes\n- Privately hosted continuous integration tests for their unique edge or use cases\n\n## Performance\n\nBased on the following [template benchmark](https://github.com/fizzed/template-benchmark),\nRocker is the clear winner.  ~250% faster than Freemarker while also requiring\norders-of-magnitude less memory.\n\n![Template Comparison](docs/benchmark.png)\n\n## Quick Start\n\nMost templates are used for websites, so here is a quick sample showing how\nRocker templates work and can call each other during the rendering process.\nCreate a template containing a common header and footer as well as a placeholder\nfor body content. Create template `src/main/java/views/main.rocker.html`\n\n```html\n@args (String title, RockerBody content)\n\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003e@title\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n    @content\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nThe template we actually plan on showing to a user will render its content\nwithin the context of the common/header footer. In Java terms, it's passing \na block of rendering code to be executed within another template. Create template\n`src/main/java/views/index.rocker.html`\n\n```html\n@args (String message)\n\n@views.main.template(\"Home\") -\u003e {\n    \u003ch1\u003eHello @message!\u003c/h1\u003e\n}\n```\n\nHey, what about the `RockerBody content` argument?  We cover it in more\ndetail in the [syntax readme](docs/SYNTAX.md), but for now just understand that its\nthe only special type of argument and instructs Rocker that a template expects\na \"body\" to be passed to it.\n\nThe Rocker parser will generate a Java source file for each template. They\nwill be `target/generated-sources/rocker/views/main.java` and \n`target/generated-sources/rocker/views/index.java`. In your application, you\ncan render the index template like so.\n\n```java\nstatic public void main(String[] args) {\n\n    String output = views.index.template(\"World\")\n        .render()\n        .toString();\n\n}\n```\n\nThe output will equal:\n\n```html\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eHome\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003ch1\u003eHello World!\u003c/h1\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nOnce you generate the Java sources and peek inside the code, it's simple\nto see how this works. The views.index class creates a views.main template instance\nand hands off rendering to it -- while also passing a block of itself that\nit will render when views.main calls the `@content` variable.  The syntax is \nidentical to how a lambda is defined in Java 8 (implemented with lambdas for Java 8\nand anonymous inner classes for Java 6/7).  Rocker does a number of things behind\nthe scenes to make sure templates that create other templates share the same\nrendering context (output buffer, application-specific context/implicit state).\n\n## Syntax\n\nCheckout the [SYNTAX.md](docs/SYNTAX.md) file for a comprehensive deep dive on\nthe rocker syntax.\n\n## Framework integrations\n\nRocker has a growing list of frameworks that it has been seamlessly integrated with.\nIf you want to link to a new framework added, please file an issue or submit a PR:\n\n * Ninja Framework: https://github.com/fizzed/ninja-rocker\n * Jooby: http://jooby.org/doc/rocker\n * Spark Framework: https://github.com/perwendel/spark-template-engines\n * Micronaut Framework: https://github.com/micronaut-projects/micronaut-views\n\n## Near zero-copy rendering\n\nStatic (plain text) for each Rocker template is (by default) stored internally as\nstatic byte arrays already converted into your target charset (e.g. UTF-8). When\na template is rendered -- the static byte arrays are reused across all requests.\nRocker renders to an optimized output stream that stores a composite (linked list)\nview of the reused byte arrays plus your dynamic content.  Since templates consist\nmostly of static content rendered into the same charset over and over again,\nrather than allocating new memory, copying that content, and then converting it\ninto your target charset for each request -- Rocker simply uses a pointer to it\nover and over again. This technique produces fast and memory efficient\nrenders.\n\nLet's say you have a template consisting of 9000 bytes of plain static text\nand 1000 bytes of dynamic content.  Without this optimization, it \nwould require ~100MB of memory to service 10000 requests (10000 bytes x \n10000 requests).  With this optimization, it would require ~10MB of memory\nto service 10000 requests (1000 bytes x 10000 requests).  Besides lower memory,\nyou also cut out 90MB of memory copies and 90MB of UTF-8 String-\u003ebyte conversions.\nA pretty useful optimization.\n\n## No reflection\n\nEverything is compiled by your project's compiler along with your other Java\nsource code.  Any dynamic code in your template is ultimately converted into\nstandard Java and compiled.  No reflection used.\n\n## Hot reloading\n\nVersion 0.10.0 introduced support for hot reloading templates during\ndevelopment. Hot reloading allows you to modify the template source code,\nsave it, and have the changes active on the next request -- without\nhaving to restart your JVM. Rocker offers two different flavors of hot\nreloading for flexibility.\n\n### Flavor 1: static interface, dynamic rendering\n\nThe major feature of Rocker templates is that your templates are compile-time\nchecked for usage, arguments, logic, etc. by the Java compiler.\n\nIn version 0.10.0 the underlying structure of a template was modified where a\ntemplate generates two underlying classes.  Each template generates a model class\n (its interface) and an implementation class (its renderer). Your application will\nonly interact directly with the model, therefore allowing Rocker to dynamically\nrecompile and reload the implementation class.\n\nThe major benefit of flavor one is that your application code remains the same\nand is compile-time checked by the Java compiler, while the template content can\nbe modified and automatically reloaded at runtime.  Only in the case where you\nactually change the template arguments, will you need to restart your application.\n\n### Flavor 2: dynamic interface, dynamic rendering\n\nIf you prefer the convenience of fully dynamic templates, flavor two supports\nhot reloading of both the template model class (its interface) as well as the\nimplementation class (its renderer).  Your application will lose some of the\ncompile-time checking and a small performance hit, but gain the convenience of\neverything being reloadable. The way your application will use templates is\ndifferent as well.\n\n```java\nimport com.fizzed.rocker.Rocker\n\n...\n\n// dynamic interfaces, dynamic implementation\nString rendered = Rocker.template(\"views/index.rocker.html\")\n    .bind(\"val\", \"ValueA\")\n    .render()\n    .toString();\n```\n\nThe template path and arguments will be runtime-checked. Please note that each\nbindable value must match the name and type declared in your template.\n\nIn case your bindable map may contain more values that than the required ones\na relaxed bind is available. The relaxed alternative will not fail rendering\nif an attribute is extra to the required list. For example:\n\n```\n@args (String name)\nHello ${name}!\n```\n\nWill render in relaxed mode as:\n\n```java\nMap map = new HashMap();\nmap.put(\"name\", \"Joe\");\nmap.put(\"age\", 42);\n\nRocker.template(\"views/hello.rocker.html\")\n    .relaxedBind(map)\n    .render();\n// -\u003e Hello Joe!\n```\n\n### Activate hot reloading\n\nSupport for hot reloading is added to your generated templates by default in\nversion 0.10.0.  If you'd like to disable support, set the configuration/system\nproperty \u003ccode\u003erocker.optimize\u003c/code\u003e to true during your build.  Since the code\nis present in your templates by default, you merely need to turn it on at runtime.\n\n#### Add dependency\n\nThe \u003ccode\u003erocker-compiler\u003c/code\u003e dependency needs to be added to your build. \nThis dependency only needs to be present during development and can be removed\nin production. In Maven, this means you'll want to add the dependency in the\n\u003ccode\u003eprovided\u003c/code\u003e scope.\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.fizzed\u003c/groupId\u003e\n    \u003cartifactId\u003erocker-compiler\u003c/artifactId\u003e\n    \u003cversion\u003e2.2.1\u003c/version\u003e\n    \u003cscope\u003eprovided\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n#### Enable at runtime\n\nActivate hot reloading at runtime. You can activate hot reloading\neither with a system property or programmatically.  For activating\nhot reloading with a system property in maven.\n\n```\nmvn -Drocker.reloading=true ...rest of args...\n```\n\nAlternatively, you can activate hot reloading programmatically.\n\n```java\nimport com.fizzed.rocker.runtime.RockerRuntime\n\n...\n\nRockerRuntime.getInstance().setReloading(true);\n```\n\n### Try out hot reloading\n\nThere is a simple example demonstrating hot reload in action.  This project \nuses [Blaze](https://github.com/fizzed/blaze) to help script tasks. Run the\nfollowing\n\n    java -jar blaze.jar hot_reload\n\nPoint your browser to http://localhost:8080\n\nThen modify \u0026 save \u003ccode\u003erocker-test-reload/src/test/java/views/index.rocker.html\u003c/code\u003e\nand refresh your browser.\n\n## Getting started\n\nRocker consists of two components - the parser/generator and the runtime.  To\nuse Rocker in your project, add the runtime dependency to your application,\nthen enable the parser in your build tool followed by creating your first template.\n\n### Add dependency\n\nRocker is published to Maven central. To add as a dependency in Maven:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.fizzed\u003c/groupId\u003e\n    \u003cartifactId\u003erocker-runtime\u003c/artifactId\u003e\n    \u003cversion\u003e2.2.1\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- for hot-reloading support only during development --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.fizzed\u003c/groupId\u003e\n    \u003cartifactId\u003erocker-compiler\u003c/artifactId\u003e\n    \u003cversion\u003e2.2.1\u003c/version\u003e\n    \u003cscope\u003eprovided\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nTo add as a dependency in Gradle:\n\n```groovy\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    compile group: 'com.fizzed', name: 'rocker-runtime', version: '2.2.1'\n    // add rocker-compiler dependency as needed\n}\n```\n\n### Integrate parser/generator in build tool\n\nRocker supports Maven and Gradle out-of-the box.\n\n#### Maven\n\nAdd the following to your pom\n\n```xml\n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003ecom.fizzed\u003c/groupId\u003e\n            \u003cartifactId\u003erocker-maven-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e2.2.1\u003c/version\u003e\n            \u003cexecutions\u003e\n                \u003cexecution\u003e\n                    \u003cid\u003egenerate-rocker-templates\u003c/id\u003e\n                    \u003cphase\u003egenerate-sources\u003c/phase\u003e\n                    \u003cgoals\u003e\n                        \u003cgoal\u003egenerate\u003c/goal\u003e\n                    \u003c/goals\u003e\n                \u003c/execution\u003e\n            \u003c/executions\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\nBy default, Rocker will recursively process any template files ending with\n`.rocker.html` in `src/main/java`.  The directory the\ntemplate is saved will become the standard Java package the\ngenerated Java classes will be placed into.  The generated Java source files\nwill be saved to `target/generated-sources/rocker`.  The plugin\nwill take care of adding this generated directory to your sources root.\n\nThe following properties are supported:\n\n * `templateDirectory` is the base directory to recursively start from\n    when locating and parsing template files.  The Java `package`\n    a template will be generated to will use this directory as its base.  So\n    if you have `${templateDirectory}/views/mytemplate.rocker.html`\n    then Rocker will generate `${outputDirectory}/views/mytemplate.java`.\n    Defaults to `${project.build.sourceDirectory}`.\n\n * `outputDirectory` is the directory the parser will generate sources\n    for templates.\n    Defaults to `${project.build.directory}/generated-sources/rocker`\n\n * `classDirectory` is the directory the hot reload feature will (re)compile\n    classes to at runtime.\n    Defaults to `${project.build.outputDirectory}`\n\n * `failOnError` determines whether any parsing/generating errors cause Maven\n    to fail.\n    Defaults to true.\n\n * `skip` determines whether execution of the plugin should be skipped.\n    Defaults to false.\n\n * `touchFile` is the file to \"touch\" after successfully generating Java sources.\n    Useful for triggering other workflow.  Many IDEs will not automatically reload\n    generated sources for code completion unless either explicitly told to reload\n    OR if the maven pom.xml file is changed. Thus, this value is by default set\n    to `${basedir}/pom.xml`.  It's usually harmless to keep this enabled.\n\n * `skipTouch` disables touchFile.  Defaults to false.\n\n * `addAsSources` will add the outputDirectory to maven as sources\n    to be compiled.  Defaults to true.\n\n * `addAsTestSources` will adds the outputDirectory to maven as test sources\n    to be compiled.  Defaults to false.  If true, this is evaluated before\n    addAsSources and effectively tells maven to compile your templates as test\n    code.\n\nThe following properties are also supported, but it's important to understand\nthese are essentially passthrough overrides to the parser and they all default\nto Rocker's default value.\n\n * `javaVersion` is the Java version you'd like your templates \n    compile \u0026 runtime compatible with.  Defaults to the Java version of the\n    JVM executing maven (e.g. \"1.8\").\n\n * `optimize` determines if hot reloading support will be removed from the\n    generated templates.  False by default.\n \n * `extendsClass` is the class that all template implementations should extend.\n    Useful for application-specific intermediate classes that you'd like all\n    templates to extend.\n    Defaults to Rocker's default.\n\n * `extendsModelClass` is the class that all template models should extend.\n    Useful for application-specific intermediate classes that you'd like all\n    template models to extend.\n    Defaults to Rocker's default.\n\n * `plainTextStrategy` is the strategy used for embedding plain text as part\n   of templates. Default is STATIC_BYTE_ARRAYS_VIA_UNLOADED_CLASS but if you\n   need GraalVM compatability, you would try STATIC_BYTE_ARRAYS\n\n * `discardLogicWhitespace` determines whether whitespace in templates that is\n    determined to be only a part of logic/control blocks should be discarded.\n    Helps make rendered content look more professional, while still keeping \n    much of your formatting intact.\n    Defaults to Rocker's default.\n \n * `targetCharset` is the target charset for template output.\n    Defaults to Rocker's default.\n   \n * `suffixRegex` is the regular expression to use to find templates to\n    parse.\n    Defaults to Rocker's default.\n\n * `markAsGenerated` adds a @Generated annotation to the generated classes.\n    The Retention is CLASS so that the annotation can be used by tools that\n    only rely on the class files and not on the source code.\n    Defaults to Rocker's default.\n\n#### Gradle\n\nThanks to `@victory` and `@mnlipp` for contributing the gradle plugin. `@etiennestuder`\nalso had an [alternative Gradle plugin](https://github.com/etiennestuder/gradle-rocker-plugin)\nyou may want to consider as well.  Rocker's gradle plugin is published to\ngradle.org. Just add the following to your build script:\n\n```groovy\nplugins {\n  id \"com.fizzed.rocker\" version \"2.2.1\"\n}\n\nsourceSets {\n    main {\n        rocker {\n            srcDir('src/main/java')\n        }\n    }\n}\n\nrocker {\n    // (All settings are shown with their defaults)\n    // \n    // Skips building templates all together\n    skip false\n    // Base directory for generated java sources, actual target is sub directory \n    // with the name of the source set. The value is passed through project.file(). \n    outputBaseDirectory = \"$buildDir/generated-src/rocker\"\n    // Base directory for the directory where the hot reload feature \n    // will (re)compile classes to at runtime (and where `rocker-compiler.conf`\n    // is generated, which is used by RockerRuntime.getInstance().setReloading(true)).\n    // The actual target is a sub directory with the name of the source set. \n    // The value is passed through project.file().\n    classBaseDirectory = \"$buildDir/classes\"\n    failOnError true\n    skipTouch true\n    // must not be empty when skipTouch is equal to false\n    touchFile \"\"\n    javaVersion '1.8'\n    extendsClass null\n    extendsModelClass null\n    optimize null\n    discardLogicWhitespace null\n    targetCharset null\n    suffixRegex null\n    postProcessing null\n    markAsGenerated null\n}\n\n```\n\n### Create first template\n\nThe template syntax is described in detail below, but for now create a new\nfile in `${templateDirectory}/views/HelloWorld.rocker.html`\n\n    @*\n     Example of hello world\n    *@\n    @args (String message)\n\n    Hello @message!\n\n### Use compiled template\n\nTime to compile your project and starting using the template.  You can call it\nfrom java like so:\n\n```java\nstatic public void main(String[] args) {\n\n    String output = views.HelloWorld\n        .template(\"World\")\n        .render()\n        .toString();\n\n}\n```\n\n### Use optimized output\n\nRocker is heavily optimized (by default) to output templates as byte arrays.\nThe default `RockerOutput` a template will render to is of the type\n`com.fizzed.rocker.runtime.ArrayOfByteArraysOutput`.  This is an excellent choice\nfor byte arrays or asynchronous IO. However, the framework has the capability\nfor optimized rendering to Strings (or other custom outputs).\n\nTo efficiently render to a String:\n\n```java\nimport com.fizzed.rocker.runtime.StringBuilderOutput;\n\nstatic public void main(String[] args) {\n\n    StringBuilderOutput output = views.HelloWorld\n        .template(\"World\")\n        .render(StringBuilderOutput.FACTORY);\n\n    String text = output.toString();\n\n}\n```\n\nTo efficiently render to an OutputStream:\n\n```java\nimport com.fizzed.rocker.runtime.OutputStreamOutput;\n\nstatic public void main(String[] args) throws Exception {\n\n    final OutputStream os = new FileOutputStream(new File(\"test\"));\n\n    OutputStreamOutput output = views.HelloWorld\n        .template(\"World\")\n        .render((contentType, charsetName) -\u003e new OutputStreamOutput(contentType, os, charsetName));\n\n}\n```\n\nPlease note that if there is an exception during the render the OutputStream\nwould have a partial template rendered (up to the point of the exception).  In\nmost cases it would be better to render to the default `com.fizzed.rocker.runtime.ArrayOfByteArraysOutput`\nand write its buffer of byte arrays out directly to your OutputStream.\n\n## Other demos?\n\nThere are numerous demos of Rocker in action.  From parsing templates into a\nmodel to asynchronously sending results in an HTTP server.  This project \nuses [Blaze](https://github.com/fizzed/blaze) to help script tasks. Run the\nfollowing for a complete list:\n\n    java -jar blaze.jar -l\n\n## License\n\nCopyright (C) 2025+ Fizzed, Inc.\n\nThis work is licensed under the Apache License, Version 2.0. See LICENSE for details.\n","funding_links":[],"categories":["Java","项目","模板引擎","Projects"],"sub_categories":["模板引擎","Template Engine"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffizzed%2Frocker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffizzed%2Frocker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffizzed%2Frocker/lists"}