{"id":20929670,"url":"https://github.com/swiftech/swiftmarker","last_synced_at":"2026-01-31T02:31:59.384Z","repository":{"id":39960799,"uuid":"159165244","full_name":"swiftech/swiftmarker","owner":"swiftech","description":"a lightweight template engine. 一个轻量级的模板引擎","archived":false,"fork":false,"pushed_at":"2025-08-01T15:52:43.000Z","size":262,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-01T17:30:50.489Z","etag":null,"topics":["engine","java","lightweight","template"],"latest_commit_sha":null,"homepage":"","language":"Java","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/swiftech.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","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":"2018-11-26T12:22:11.000Z","updated_at":"2025-08-01T15:00:51.000Z","dependencies_parsed_at":"2025-01-19T18:44:50.042Z","dependency_job_id":"c70ec1be-6f8f-4a2c-bf06-ed5cb54f66de","html_url":"https://github.com/swiftech/swiftmarker","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/swiftech/swiftmarker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftech%2Fswiftmarker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftech%2Fswiftmarker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftech%2Fswiftmarker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftech%2Fswiftmarker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swiftech","download_url":"https://codeload.github.com/swiftech/swiftmarker/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swiftech%2Fswiftmarker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28927166,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T22:32:35.345Z","status":"online","status_checked_at":"2026-01-31T02:00:09.179Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["engine","java","lightweight","template"],"created_at":"2024-11-18T21:22:44.065Z","updated_at":"2026-01-31T02:31:59.366Z","avatar_url":"https://github.com/swiftech.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SwiftMarker\n\nSwiftMarker is a lightweight template engine.\n\nSwiftMarker是一个轻量级的模板引擎\n\n\n### Features\n* Lightweight and few dependencies.\n* Simple and easy to use but flexible. \n* Supports loop expression, logical expression and nested expression.\n* You can simply use dotted name like ```foo.bar``` to select params in data model.\n* Multiple types are supported to composite data model: array, ```List```, ```JsonArray```, ```Map```, ```JsonObject``` and even plain Bean object. you can combine them freely.\n\n### Dependencies\n* JDK 8+\n\n### Tutorial\n\n##### Quick Start\n\n```java\nString strTemplate = \"......\";\ncom.google.gson.JsonObject model = ...;\nSwiftMarker swiftMarker = new SwiftMarker();\nswiftMarker.prepare(strTemplate);\nString result = swiftMarker.render(model);\n```\n\n##### Basic Usage\n\nUse ```${}``` to select params from data model.\n\n* Template\n```\nFear leads to ${yoda.word1},\n${yoda.word1} leads to ${yoda.word2},\n${yoda.word2} leads to suffering.\n```\n\n* Data Model\n```json\n{\n    \"yoda\": {\n        \"word1\": \"anger\",\n        \"word2\": \"hate\"\n    }\n}\n```\n\n* Result\n```\nFear leads to anger,\nanger leads to hate,\nhate leads to suffering.\n```\n\n###### Loop Expression\n\nUse ```$[var]...$[]``` pair to select listable object(includes array/JsonArray/List) in data model and loop them. \nIf no any elements selected, anything between them will NOT be rendered.\n\nIf the elements are key-value object, use ```${}``` expression starts with `.` to select param value.\n\n\u003e expression starts without `.` will select params from the global data model.\n\nIf the elements are primitive object (like String, Integer etc.), just use ```${.}```` to output this element directly.\n\n* Template\n```\n${question.title}\n$[question.options]${.index}: ${.option}$[]\n\nMy choice is: $[answers]${.}$[]\nHer choice is: ${question.options.1.index}\n```\n\n\u003e Notice: loop expression must ends with ```$[]```.\n\n* Data Model\n```json\n{\n\t\"question\": {\n\t\t\"title\": \"What's your favorite colors?\",\n\t\t\"options\": [\n\t\t\t{\"index\": \"A\", \"option\": \"Red\"},\n\t\t\t{\"index\": \"B\", \"option\": \"Green\"},\n\t\t\t{\"index\": \"C\", \"option\": \"Blue\"}\n\t\t]\n\t},\n    \"answers\": [\n      \"A\", \"C\"\n    ]\n}\n```\n\n* Result\n```\nWhat's your favorite colors?\nA: Red\nB: Green\nC: Blue\n\nMy choice is: AC\nHer choice is: B\n```\n\n\u003e Notice: The line only contains the ```$[]``` placeholder will not output a new line.\n\n\n* Loop expression with array/JsonArray/List element\n\nIf the array selected contains array/JsonArray/List, use ```${.0}```, ```${.1}```... to select params in the elements.\n\n* Template\n```\n${question.title}\n$[question.options]${.0}: ${.1}$[]\n```\n\n* Data Model\n```java\nMap dataMode = new HashMap() {\n\t{\n\t\tput(\"question\", new HashMap() {\n\t\t\t{\n\t\t\t\tput(\"title\", \"What's your favorite color?\");\n\t\t\t\tput(\"options\": new ArrayList(){\n\t\t\t\t\tadd(new String[]{\"A\", \"Red\"});\n\t\t\t\t\tadd(new String[]{\"B\", \"Green\"});\n\t\t\t\t\tadd(new String[]{\"C\", \"Blue\"});\n\t\t\t\t});\n\t\t\t}\n\t\t})\n\t}\n};\n```\n\n* Result\n```\nWhat's your favorite color?\nA: Red\nB: Green\nC: Blue\n```\n\n##### Logical Expression\n\nLogical expression is used to decide whether display content in it, you can have any layer nested logical expression. Only the expression condition determined to logic true\n\n* Template:\n```\n?{logic1}\n${say}\n?{}\n?{logic2}\n${think}\n?{}\n\n?{logic1}\n${say}\n    ?{logic2}\n${think}\n    ?{}\n?{}\n```\n\n* Data Model:\n```json\n{\n    \"logic1\": true,\n    \"say\": \"hello github\",\n    \"logic2\": false,\n    \"think\": \"goodbye\"\n}\n```\n\n* Result:\n```\nhello github\nhello github\n```\n\n* Logical condition judgement for object types:\n\nLogic|String|Number|Boolean|Date|Calendar|JsonPrimitive|Collection|JsonArray|Map|JsonObject|Array\n-|-|-|-|-|-|-|-|-|-|-|-\nLogic true|Y/y/YES/yes/Yes/non-empty text|\u003e0|true|\u003e0|\u003e0|true/\u003e0|size()\u003e0|size()\u003e0|size()\u003e0|size()\u003e0|length\u003e0\nLogic false|N/n/NO/no/No/empty text|\u003c=0|true|=0|=0|true/\u003c=0|size()=0|size()=0|size()=0|size()=0|length=0\n\n* Use \"!\" in logical expression to perform logic negation, for example:\n```\n?{!foo.bar}\n?{}\n```\nor\n```\n$[collection]\n?{!.foo.bar}\n?{}\n$[]\n```\n\n* Logical expression also supports single or compound operation, eg:\n  * `str = 'foo'` `str != 'foo'`\n  * `num = 9` `num \u003e 9` `num \u003c 9` `num \u003e= 9` `num \u003c= 9`\n  * `num \u003e 9 \u0026 num \u003c 99` `str = 'foo' | str = 'bar'` `num \u003e 9 | str = 'foo' | logic_exp`\n\n\n##### Other supported data model object types\n\n* Map\n```java\nMap m = new HashMap() {\n\t{\n\t\tput(\"yoda\", new HashMap() {\n\t\t\t{\n\t\t\t\tput(\"word1\", \"anger\");\n\t\t\t\tput(\"word2\", \"hate\");\n\t\t\t}\n\t\t})\n\t}\n};\nswiftMarker.render(m);\n```\n\n* Plain Bean Object\n```java\npublic class Yoda{\n\tYodaWords yoda;\n}\npublic class YodaWords {\n\tString word1 = \"anger\";\n\tString word2 = \"hate\";\n}\nYoda yoda = new Yoda();\n......\nswiftMarker.render(yoda);\n```\n\n\u003e Of course, you can have all these data objects nested in any way.\n\n##### Escaping\n\nIf the template contains text like `${xxx}` which is not expression but the engine would recognize as expression, you can use the escaping symbol `\\` to let the engine ignore them, for example:\n\n```\n$\\{xxx}\n$\\[xxx] $\\[]\n?\\{xxx} ?\\{}\n```\n\nThe engine will recognize them as text instead of expression.\n\n##### Config\n\n* You can customize SwiftMarker by providing a ```Config``` object to it.\n```java\n...\nSwiftMarker swiftMarker = new SwiftMarker();\nConfig config = new Config();\nlog.setLevel(Logger.LEVEL_DEBUG);\nswiftMarker.prepare(strTemplate, config);\n...\n```\n\n* Options to config SwiftMarker:\n\nname|description|default\n-|-|-\ndebug|true to output debug logs|false\ninputLineBreaker|line breaker of input|\\\\n\noutputLineBreaker|line breaker of output|\\\\n\nrenderExpressionIfValueIsBlank| set false to avoid render expression if no value provided | true\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.github.swiftech\u003c/groupId\u003e\n\t\u003cartifactId\u003eswiftmarker\u003c/artifactId\u003e\n\t\u003cversion\u003e3.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n\n### Release Update\nsee [changelog](changelog.md)\n\n\n### Coming Soon\n* Supports comment in the template.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftech%2Fswiftmarker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswiftech%2Fswiftmarker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswiftech%2Fswiftmarker/lists"}