{"id":36418369,"url":"https://github.com/jeffreyolchovy/sbt-fmpp-resolver","last_synced_at":"2026-01-11T17:01:26.223Z","repository":{"id":57720432,"uuid":"98736839","full_name":"jeffreyolchovy/sbt-fmpp-resolver","owner":"jeffreyolchovy","description":"An Apache FreeMarker template resolver for the sbt new command","archived":false,"fork":false,"pushed_at":"2017-08-12T22:00:52.000Z","size":65,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2023-06-30T18:05:12.348Z","etag":null,"topics":["fmpp","freemarker","sbt","sbt-plugin"],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeffreyolchovy.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}},"created_at":"2017-07-29T14:15:05.000Z","updated_at":"2020-10-06T03:51:36.000Z","dependencies_parsed_at":"2022-09-02T13:10:24.203Z","dependency_job_id":null,"html_url":"https://github.com/jeffreyolchovy/sbt-fmpp-resolver","commit_stats":null,"previous_names":[],"tags_count":3,"template":null,"template_full_name":null,"purl":"pkg:github/jeffreyolchovy/sbt-fmpp-resolver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyolchovy%2Fsbt-fmpp-resolver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyolchovy%2Fsbt-fmpp-resolver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyolchovy%2Fsbt-fmpp-resolver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyolchovy%2Fsbt-fmpp-resolver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeffreyolchovy","download_url":"https://codeload.github.com/jeffreyolchovy/sbt-fmpp-resolver/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyolchovy%2Fsbt-fmpp-resolver/sbom","scorecard":{"id":514331,"data":{"date":"2025-08-11","repo":{"name":"github.com/jeffreyolchovy/sbt-fmpp-resolver","commit":"746c441ec645f691004df757c5898fedfbf83899"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'develop'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T01:24:08.245Z","repository_id":57720432,"created_at":"2025-08-20T01:24:08.249Z","updated_at":"2025-08-20T01:24:08.249Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314259,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"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":["fmpp","freemarker","sbt","sbt-plugin"],"created_at":"2026-01-11T17:01:10.845Z","updated_at":"2026-01-11T17:01:26.190Z","avatar_url":"https://github.com/jeffreyolchovy.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sbt-fmpp-resolver\nAn [Apache FreeMarker](http://freemarker.org/) template resolver for the [sbt](http://www.scala-sbt.org/) [new command](http://www.scala-sbt.org/0.13/docs/sbt-new-and-Templates.html).\n\n[FMPP](http://fmpp.sourceforge.net/) is used as the template processing engine.\n\n## Usage\nsbt-fmpp-template is compatible with sbt 0.13.13+ and sbt 1.0.\n\nTo allow a specific project to use the `FmppTemplateResolver`, add the following to `project/plugins.sbt`:\n```\naddSbtPlugin(\"com.github.jeffreyolchovy\" % \"sbt-fmpp-template\" % \"0.1.2\")\n```\n\nTo globally allow sbt to evaluate templates using this resolver, add that same line to `~/.sbt/0.13/plugins/build.sbt`.\n\nOnce the plugin has been installed for a given project (or globally), you can leverage it using `sbt new` or via the `fmpp` input task.\n\nFor example, given the following sbt project structure:\n```\n(root)\n  |-/templates  # a directory containing a structured set of FreeMarker templates and/or static files\n  |-/includes   # a directory containing FreeMarker files that can be used as libraries\n  |-/project\n  |-build.sbt\n```\n\nExecution of the following command will:\n- Evaluate the templates found in the `templates` directory using the data given on the command line (`-D ...`)\n- Allow templates to use any custom macros and instructions defined in the `includes` directory\n- Emit the generated files to the `src` directory\n```\nsbt new -S templates -O src -D \"name:MyProject, organization:com.example\" --freemarker-links includes:includes\n```\n\nIf that invocation seems too intimidating, sweep your specifications into a `config.fmpp` file and invoke:\n```\nsbt new -C config.fmpp\n```\n\nFor the above example, the contents of `config.fmpp` should include:\n```\nsourceRoot: templates\noutputRoot: src\ndata: {\n  name: MyProject,\n  organization: com.example\n}\nfreemarkerLinks: {\n  includes: includes\n}\nmodes: [\n  ignore(config.fmpp)\n]\n```\n\nFile and directory names can be altered using FreeMarker macros. This allows for the interpolation and expansion of template file paths, if desired.\n\nBy default, empty directories will not be copied to the target destination. This behavior is configurable.\n\nFor more information refer to the [FreeMarker manual](http://freemarker.org/docs/index.html) and the [FMPP Command-line tool documentation](http://fmpp.sourceforge.net/commandline.html).\n\nAll of FMPP's command-line options are respected.\n\n### Examples\nA directory of [example sbt project templates](examples) is provided. It includes FreeMarker template versions of popular sbt-giter8 templates.\n\n- [scala-sbt.ftl](examples/scala-sbt.ftl) (inspired by [scala-sbt.g8](https://github.com/typesafehub/scala-sbt.g8))\n- [scala-native.ftl](examples/scala-native.ftl) (inspired by [scala-native.g8](https://github.com/scala-native/scala-native.g8))\n- [sbt-autoplugin.ftl](examples/sbt-autoplugin.ftl) (inspired by [sbt-autoplugin.g8](https://github.com/sbt/sbt-autoplugin.g8))\n\nRefer to the [README.md](examples/README.md) of the examples directory for more details.\n\nAdditional example projects that utilize the `FmppTemplateResolver` also exist in the [plugin/src/sbt-test/sbt-fmpp-template](plugin/src/sbt-test/sbt-fmpp-template) directory.\n\nThese examples include projects that:\n- Evaluate templates that exist on the [local file system](plugin/src/sbt-test/sbt-fmpp-template/local/test)\n- Evaluate templates from a [remote git repository](plugin/src/sbt-test/sbt-fmpp-template/remote/test)\n- Evaluate templates from a [remote git repository, referencing a given branch by name](plugin/src/sbt-test/sbt-fmpp-template/remote/test)\n- Evaluate templates from a [remote git repository, referencing a given tag](plugin/src/sbt-test/sbt-fmpp-template/remote/test)\n- Evaluate templates that need to create [dynamic directory paths and file names](plugin/src/sbt-test/sbt-fmpp-template/dynamic-files-and-dirs/templates/main/scala/${organization}/Bar.scala)\n- Evaluate templates that utilize [custom user-defined macros](plugin/src/sbt-test/sbt-fmpp-template/macros/includes/custom_macros.ftl)\n- Evaluate templates using a [configuration file](plugin/src/sbt-test/sbt-fmpp-template/config-file)\n\n## Motivation\nsbt supports the idea of pluggable template resolvers, however, only one implementation ([Giter8](http://www.foundweekends.org/giter8/)) is provided out of the box. While I have made extensive use of Giter8 for project templates and project archetypes in the past, Giter8 is somewhat lacking in terms of raw features and extensibility. This is not necessarily a bad thing. The simplicity and limited range of Giter8 has actually been quite welcoming for the majority of my use cases, but when more power is required, there's not a whole lot you can do...\n\nI considered forking and extending Giter8 with additional functionality, but since there already exist myriad templating solutions, it would make more sense, in my opinion, to leverage a more robust templating engine and implement any of Giter8's integral features in the new resolver or with the chosen templating solution itself.\n\nAfter surveying the landscape of existing templating engines, I landed on Apache FreeMarker. FreeMarker has much more power than I anticipated -- or even desired -- and its array of features can, at times, be rather dizzying. The thing that's worth noting is how simple integration has been. The FMPP front-end has a well documented feature set and Java API.\n\nsbt's mechanism for adding template resolvers has also proven to be rather simple. The [docs](http://www.scala-sbt.org/0.13/docs/sbt-new-and-Templates.html#Template+Resolver) explain the process clearly.\n\n## Project Structure\n- [plugin](#plugin)\n- [plugin-buildinfo](#plugin-buildinfo)\n- [resolver](#resolver)\n\n### plugin\nAn sbt plugin that adds the [`FmppTemplateResolver`](resolver/src/main/scala/sbtfmppresolver/FmppTemplateResolver.scala) to sbt's `templateResolverInfos` setting.\n\nThis plugin cross builds for sbt 0.13 and sbt 1.0. There is still a bit of noise and hackery in the build.sbt that I can't seem to simplify, notably:\n- https://github.com/sbt/sbt/issues/3392\n- https://github.com/sbt/sbt/issues/3393\n\nSee the build.sbt and the linked issues for more information on the workarounds.\n\n### plugin-buildinfo\n**NOT YET IMPLEMENTED**\n\nAn additional plugin that requires the [sbt-buildinfo](https://github.com/sbt/sbt-buildinfo) plugin, as it allows users to inject contextual project information into the templates at evaluation time.\n\nA `TDD` renderer is provided for exporting `BuildInfoResult`s in a format digestable by FMPP.\n\n### resolver\nThe template resolver implementation.\n\nCurrently, it programmatically invokes the FMPP `CommandLine` front-end via FMPP's Java API.\n\nIt uses logic ported from Giter8 for resolving remote resources.\n\n## Notes\n- Dynamic file and directory names can be obtained by utilizing `pp` directives *inside* templates\n- The `config.fmpp` files in the [example](examples) projects present a method for automatically interpolating variables when present in file names or directory paths\n- FreeMarker does not include built-in string operations for Java-esque string transformations (e.g. to/from UpperCamelCase, lowerCamelCase, snake_case, etc.)\n  - These operations can be defined in custom macros and included as a library (or **namespace**, in FreeMarker lingo)\n\n## Credits\n- The real heavy lifting is done by the underlying templating engine and templating \"front-end\" (FreeMarker and FMPP)\n- For git repository integration, I've reused whatever functionality I could from Giter8\n\nLicensed under the Apache 2.0 license\n\nCopyright Jeffrey Olchovy, 2017\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffreyolchovy%2Fsbt-fmpp-resolver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeffreyolchovy%2Fsbt-fmpp-resolver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffreyolchovy%2Fsbt-fmpp-resolver/lists"}