package com.taiwanlife.teamwalk.admin.configuration;
import lombok.extern.slf4j.Slf4j;
import nz.net.ultraq.thymeleaf.layoutdialect.LayoutDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect;
import org.thymeleaf.spring6.SpringTemplateEngine;
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring6.view.ThymeleafViewResolver;
import com.taiwanlife.teamwalk.admin.configuration.dialect.FunctionDialect;
@Slf4j
@Configuration
public class ThymeleafConfig {
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML"); // 注意!6.x 不支援 HTML5
resolver.setCharacterEncoding("UTF-8");
resolver.setCacheable(false);
log.info("[ThymeleafConfig] TemplateResolver configured: prefix={}, suffix={}, mode={}",
resolver.getPrefix(), resolver.getSuffix(), resolver.getTemplateMode());
return resolver;
}
@Bean
public SpringTemplateEngine templateEngine(SpringResourceTemplateResolver templateResolver,
LayoutDialect layoutDialect,
SpringSecurityDialect springSecurityDialect,
FunctionDialect functionDialect) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver);
engine.addDialect(layoutDialect);
engine.addDialect(springSecurityDialect);
engine.addDialect(functionDialect);
log.info("[ThymeleafConfig] TemplateEngine initialized with dialects: {}",
engine.getDialects().keySet());
return engine;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine);
resolver.setCharacterEncoding("UTF-8");
resolver.setOrder(1);
log.info("[ThymeleafConfig] ThymeleafViewResolver registered");
return resolver;
}
@Bean
public SpringSecurityDialect springSecurityDialect() {
log.info("[ThymeleafConfig] SpringSecurityDialect registered");
return new SpringSecurityDialect();
}
@Bean
public LayoutDialect layoutDialect() {
log.info("[ThymeleafConfig] LayoutDialect registered");
return new LayoutDialect();
}
@Bean
public FunctionDialect functionDialect() {
log.info("[ThymeleafConfig] Custom FunctionDialect registered");
return new FunctionDialect();
}
}
cGFja2FnZSBjb20udGFpd2FubGlmZS50ZWFtd2Fsay5hZG1pbi5jb25maWd1cmF0aW9uOwoKCgppbXBvcnQgbG9tYm9rLmV4dGVybi5zbGY0ai5TbGY0ajsKCmltcG9ydCBuei5uZXQudWx0cmFxLnRoeW1lbGVhZi5sYXlvdXRkaWFsZWN0LkxheW91dERpYWxlY3Q7CgppbXBvcnQgb3JnLnNwcmluZ2ZyYW1ld29yay5jb250ZXh0LmFubm90YXRpb24uQmVhbjsKCmltcG9ydCBvcmcuc3ByaW5nZnJhbWV3b3JrLmNvbnRleHQuYW5ub3RhdGlvbi5Db25maWd1cmF0aW9uOwoKaW1wb3J0IG9yZy50aHltZWxlYWYuZXh0cmFzLnNwcmluZ3NlY3VyaXR5Ni5kaWFsZWN0LlNwcmluZ1NlY3VyaXR5RGlhbGVjdDsKCmltcG9ydCBvcmcudGh5bWVsZWFmLnNwcmluZzYuU3ByaW5nVGVtcGxhdGVFbmdpbmU7CgppbXBvcnQgb3JnLnRoeW1lbGVhZi5zcHJpbmc2LnRlbXBsYXRlcmVzb2x2ZXIuU3ByaW5nUmVzb3VyY2VUZW1wbGF0ZVJlc29sdmVyOwoKaW1wb3J0IG9yZy50aHltZWxlYWYuc3ByaW5nNi52aWV3LlRoeW1lbGVhZlZpZXdSZXNvbHZlcjsKCmltcG9ydCBjb20udGFpd2FubGlmZS50ZWFtd2Fsay5hZG1pbi5jb25maWd1cmF0aW9uLmRpYWxlY3QuRnVuY3Rpb25EaWFsZWN0OwoKCgpAU2xmNGoKCkBDb25maWd1cmF0aW9uCgpwdWJsaWMgY2xhc3MgVGh5bWVsZWFmQ29uZmlnIHsKCgoKICAgIEBCZWFuCgogICAgcHVibGljIFNwcmluZ1Jlc291cmNlVGVtcGxhdGVSZXNvbHZlciB0ZW1wbGF0ZVJlc29sdmVyKCkgewoKICAgICAgICBTcHJpbmdSZXNvdXJjZVRlbXBsYXRlUmVzb2x2ZXIgcmVzb2x2ZXIgPSBuZXcgU3ByaW5nUmVzb3VyY2VUZW1wbGF0ZVJlc29sdmVyKCk7CgogICAgICAgIHJlc29sdmVyLnNldFByZWZpeCgiY2xhc3NwYXRoOi90ZW1wbGF0ZXMvIik7CgogICAgICAgIHJlc29sdmVyLnNldFN1ZmZpeCgiLmh0bWwiKTsKCiAgICAgICAgcmVzb2x2ZXIuc2V0VGVtcGxhdGVNb2RlKCJIVE1MIik7ICAvLyDms6jmhI/vvIE2Lngg5LiN5pSv5o+0IEhUTUw1CgogICAgICAgIHJlc29sdmVyLnNldENoYXJhY3RlckVuY29kaW5nKCJVVEYtOCIpOwoKICAgICAgICByZXNvbHZlci5zZXRDYWNoZWFibGUoZmFsc2UpOwoKICAgICAgICBsb2cuaW5mbygiW1RoeW1lbGVhZkNvbmZpZ10gVGVtcGxhdGVSZXNvbHZlciBjb25maWd1cmVkOiBwcmVmaXg9e30sIHN1ZmZpeD17fSwgbW9kZT17fSIsCgogICAgICAgICAgICAgICAgIHJlc29sdmVyLmdldFByZWZpeCgpLCByZXNvbHZlci5nZXRTdWZmaXgoKSwgcmVzb2x2ZXIuZ2V0VGVtcGxhdGVNb2RlKCkpOwoKICAgICAgICByZXR1cm4gcmVzb2x2ZXI7CgogICAgfQoKCgogICAgQEJlYW4KCiAgICBwdWJsaWMgU3ByaW5nVGVtcGxhdGVFbmdpbmUgdGVtcGxhdGVFbmdpbmUoU3ByaW5nUmVzb3VyY2VUZW1wbGF0ZVJlc29sdmVyIHRlbXBsYXRlUmVzb2x2ZXIsCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExheW91dERpYWxlY3QgbGF5b3V0RGlhbGVjdCwKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3ByaW5nU2VjdXJpdHlEaWFsZWN0IHNwcmluZ1NlY3VyaXR5RGlhbGVjdCwKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnVuY3Rpb25EaWFsZWN0IGZ1bmN0aW9uRGlhbGVjdCkgewoKICAgICAgICBTcHJpbmdUZW1wbGF0ZUVuZ2luZSBlbmdpbmUgPSBuZXcgU3ByaW5nVGVtcGxhdGVFbmdpbmUoKTsKCiAgICAgICAgZW5naW5lLnNldFRlbXBsYXRlUmVzb2x2ZXIodGVtcGxhdGVSZXNvbHZlcik7CgogICAgICAgIGVuZ2luZS5hZGREaWFsZWN0KGxheW91dERpYWxlY3QpOwoKICAgICAgICBlbmdpbmUuYWRkRGlhbGVjdChzcHJpbmdTZWN1cml0eURpYWxlY3QpOwoKICAgICAgICBlbmdpbmUuYWRkRGlhbGVjdChmdW5jdGlvbkRpYWxlY3QpOwoKICAgICAgICBsb2cuaW5mbygiW1RoeW1lbGVhZkNvbmZpZ10gVGVtcGxhdGVFbmdpbmUgaW5pdGlhbGl6ZWQgd2l0aCBkaWFsZWN0czoge30iLAoKICAgICAgICAgICAgICAgICBlbmdpbmUuZ2V0RGlhbGVjdHMoKS5rZXlTZXQoKSk7CgogICAgICAgIHJldHVybiBlbmdpbmU7CgogICAgfQoKCgogICAgQEJlYW4KCiAgICBwdWJsaWMgVGh5bWVsZWFmVmlld1Jlc29sdmVyIHRoeW1lbGVhZlZpZXdSZXNvbHZlcihTcHJpbmdUZW1wbGF0ZUVuZ2luZSB0ZW1wbGF0ZUVuZ2luZSkgewoKICAgICAgICBUaHltZWxlYWZWaWV3UmVzb2x2ZXIgcmVzb2x2ZXIgPSBuZXcgVGh5bWVsZWFmVmlld1Jlc29sdmVyKCk7CgogICAgICAgIHJlc29sdmVyLnNldFRlbXBsYXRlRW5naW5lKHRlbXBsYXRlRW5naW5lKTsKCiAgICAgICAgcmVzb2x2ZXIuc2V0Q2hhcmFjdGVyRW5jb2RpbmcoIlVURi04Iik7CgogICAgICAgIHJlc29sdmVyLnNldE9yZGVyKDEpOwoKICAgICAgICBsb2cuaW5mbygiW1RoeW1lbGVhZkNvbmZpZ10gVGh5bWVsZWFmVmlld1Jlc29sdmVyIHJlZ2lzdGVyZWQiKTsKCiAgICAgICAgcmV0dXJuIHJlc29sdmVyOwoKICAgIH0KCgoKICAgIEBCZWFuCgogICAgcHVibGljIFNwcmluZ1NlY3VyaXR5RGlhbGVjdCBzcHJpbmdTZWN1cml0eURpYWxlY3QoKSB7CgogICAgICAgIGxvZy5pbmZvKCJbVGh5bWVsZWFmQ29uZmlnXSBTcHJpbmdTZWN1cml0eURpYWxlY3QgcmVnaXN0ZXJlZCIpOwoKICAgICAgICByZXR1cm4gbmV3IFNwcmluZ1NlY3VyaXR5RGlhbGVjdCgpOwoKICAgIH0KCgoKICAgIEBCZWFuCgogICAgcHVibGljIExheW91dERpYWxlY3QgbGF5b3V0RGlhbGVjdCgpIHsKCiAgICAgICAgbG9nLmluZm8oIltUaHltZWxlYWZDb25maWddIExheW91dERpYWxlY3QgcmVnaXN0ZXJlZCIpOwoKICAgICAgICByZXR1cm4gbmV3IExheW91dERpYWxlY3QoKTsKCiAgICB9CgoKCiAgICBAQmVhbgoKICAgIHB1YmxpYyBGdW5jdGlvbkRpYWxlY3QgZnVuY3Rpb25EaWFsZWN0KCkgewoKICAgICAgICBsb2cuaW5mbygiW1RoeW1lbGVhZkNvbmZpZ10gQ3VzdG9tIEZ1bmN0aW9uRGlhbGVjdCByZWdpc3RlcmVkIik7CgogICAgICAgIHJldHVybiBuZXcgRnVuY3Rpb25EaWFsZWN0KCk7CgogICAgfQoKfQo=