{"id":18753508,"url":"https://github.com/xiyuan-fengyu/template-string","last_synced_at":"2025-08-16T08:08:36.938Z","repository":{"id":57724193,"uuid":"180558655","full_name":"xiyuan-fengyu/template-string","owner":"xiyuan-fengyu","description":"raw-string-literals and string-interpolation for java; 在java中实现可插值原字符串","archived":false,"fork":false,"pushed_at":"2019-08-16T08:41:20.000Z","size":71,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-29T00:53:41.189Z","etag":null,"topics":["multiline-strings","raw-string-literals","string-interpolation"],"latest_commit_sha":null,"homepage":"","language":"Java","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/xiyuan-fengyu.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":"2019-04-10T10:29:58.000Z","updated_at":"2021-08-07T08:11:16.000Z","dependencies_parsed_at":"2022-09-02T06:54:43.111Z","dependency_job_id":null,"html_url":"https://github.com/xiyuan-fengyu/template-string","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiyuan-fengyu%2Ftemplate-string","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiyuan-fengyu%2Ftemplate-string/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiyuan-fengyu%2Ftemplate-string/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiyuan-fengyu%2Ftemplate-string/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xiyuan-fengyu","download_url":"https://codeload.github.com/xiyuan-fengyu/template-string/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239644163,"owners_count":19673578,"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":["multiline-strings","raw-string-literals","string-interpolation"],"created_at":"2024-11-07T17:26:04.161Z","updated_at":"2025-02-19T10:43:35.228Z","avatar_url":"https://github.com/xiyuan-fengyu.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# template-string\n\n## 快速开始\n创建一个新项目，通过maven管理jar依赖。    \n在pom.xml中添加依赖  \n```\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.github.xiyuan-fengyu\u003c/groupId\u003e\n        \u003cartifactId\u003etemplate-string\u003c/artifactId\u003e\n        \u003cversion\u003e1.0.3\u003c/version\u003e\n    \u003c/dependency\u003e\n\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.freemarker\u003c/groupId\u003e\n        \u003cartifactId\u003efreemarker\u003c/artifactId\u003e\n        \u003cversion\u003e2.3.28\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n编写一个用于测试的类  \n```\nimport com.xiyuan.templateString.EnableTemplateString;\nimport com.xiyuan.templateString.TemplateString;\n\nimport static com.xiyuan.templateString.TemplateString.S.r;\n\n@EnableTemplateString\npublic class TemplateStringTest {\n\n    public static void main(String[] args) {\n        String templateStr = new TemplateString(\"123\", \"Tom\", 25).$(/*\n        {\n            \"id\": ${_0},\n            \"name\": \"${_1}\",\n            \"age\": ${_2}\n        }\n        */);\n        System.out.println(templateStr);\n\n        String rawStr = r(/*\n        {\n            \"id\": ${_0},\n            \"name\": \"${_1}\",\n            \"age\": ${_2}\n        }\n        */);\n        System.out.println(rawStr);\n    }\n\n}\n```\n输出结果如下  \n```\n{\n    \"id\": 123,\n    \"name\": \"Tom\",\n    \"age\": 25\n}\n{\n    \"id\": ${_0},\n    \"name\": \"${_1}\",\n    \"age\": ${_2}\n}\n```\n\n## 实现说明\n如果一个java文件中有一个类有 @EnableTemplateString 注解，则在编译期间，会扫描这个java文件，将其中满足如下格式的内容(...部分)提取为模板。  \ntypeA  \n```\n    String str = r(/*\n    ...\n    */);\n```\ntypeB  \n```\n    String str = $(/*\n    ...\n    */);\n```\ntypeC  \n```\n    String str = new TemplateString().$(/*\n    ...\n    */);\n```\n\n开始标记行必须以 r(/* 或 $(* 结尾，后面可以有空白字符  \n结束标记行必须以 */) 开始，前面可以有空白字符  \n其间的 ... 为模板内容  \n\n在将...部分提取为模板的过程中，如果模板部分每一个非空(not blank)行和结束行\"*/)\"有相同的空白(blank)前缀，\n，则会从模板内容中每行删除这个相同的空白前缀。  \n例如：  \n```\n    String str = r(/*\n    line 1\n    line 2\n    line 3\n    */);\n```\n解析出来的模板类容为  \n```\nline 1\nline 2\nline 3\n```\n而\n```\n    String str = r(/*\n    line 1\n  line 2\n    line 3\n    */);\n```\n解析出来的模板类容为  \n```\n    line 1\n  line 2\n    line 3\n```\n且在编译期间会提示警告信息\n\n```\n另外，当模板内容中存在\"*/\"这种字符串时，需要替换为\"*\\/\"，直接写作 \"*/\"，在编译过程中会提示错误     \n当 * 和 / 之间有 n 个 \\ 时，解析模板后，将变为 *(n-1)个\\/  \n```\n\n其中 typeA 不经过模板引擎解析，直接返回原内容；typeB，typeC需要模板引擎解析后返回结果，typeC可以设置参数，实现字符串插值。  \ntypeB，typeC 两种方式需要引入额外的模板引擎依赖，目前内置支持 freemarker, velocity, thymeleaf，但在使用的时候需要\n引入对应的包  \n```\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.freemarker\u003c/groupId\u003e\n            \u003cartifactId\u003efreemarker\u003c/artifactId\u003e\n            \u003cversion\u003e2.3.28\u003c/version\u003e\n        \u003c/dependency\u003e\n\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.apache.velocity\u003c/groupId\u003e\n            \u003cartifactId\u003evelocity-engine-core\u003c/artifactId\u003e\n            \u003cversion\u003e2.1\u003c/version\u003e\n        \u003c/dependency\u003e\n\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.thymeleaf\u003c/groupId\u003e\n            \u003cartifactId\u003ethymeleaf\u003c/artifactId\u003e\n            \u003cversion\u003e3.0.11.RELEASE\u003c/version\u003e\n        \u003c/dependency\u003e\n```\n当有两个及以上的模板引擎包存在时，TemplateString启用模板引擎的顺序优先级为：freemarker \u003e velocity \u003e thymeleaf  \n\n通过 typeC 方式声明 TemplateString 时，支持以下方式设置参数，而且可以指定模板引擎  \n```\n    String str = new TemplateString(1, 2, 3)\n            .put(\"someKey\", \"someValue\")\n            .putAll(new HashMap\u003c\u003e())\n            .setTemplateEngine(new VelocityEngine(null))\n            .$(/*\n    {\n        \"id\": ${_0},\n        \"name\": \"${_1}\",\n        \"age\": ${_2}\n    }\n    */);\n    System.out.println(str);\n```  \n构造函数传递的参数将依次解析为 _0, _1, _2, ...  \n通过 put, putAll 设置的参数以key作为参数名  \n\n## 模板引擎语法文档参考  \nfreemarker  \nhttps://freemarker.apache.org/docs/ref.html  \n\nvelocity  \nhttp://velocity.apache.org/engine/devel/user-guide.html  \n\nthymeleaf  \nhttps://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html  \n\n\n\n## 如何开发调试这个项目  \n将 JAVA_HOME/lib/tools.jar 添加到 Java SDK      \n![tools_jar.png](https://i.loli.net/2019/04/09/5cac7479f1571.png)  \n在 src/main/java/com/xiyuan/templateString/EnableTemplateStringProcessor.java 中添加断点    \n![annotation-processor调试.png](https://i.loli.net/2019/04/13/5cb1acc676d02.png)  \n以debug模式运行 src/test/java/com/xiyuan/templateString/ProcessorDebuger.java  \n\n\n\n参考  \nhttps://stackoverflow.com/questions/878573/java-multiline-string/878958  \nhttps://github.com/mageddo/mageddo-projects/tree/master/raw-string-literals  \nhttps://stackoverflow.com/questions/8587096/how-do-you-debug-java-annotation-processors-using-intellij  \n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiyuan-fengyu%2Ftemplate-string","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxiyuan-fengyu%2Ftemplate-string","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiyuan-fengyu%2Ftemplate-string/lists"}