Skip to content

Commit 6f019e6

Browse files
committed
prepare release 3.4.0
1 parent c0cff02 commit 6f019e6

File tree

2 files changed

+217
-19
lines changed

2 files changed

+217
-19
lines changed

CLAUDE.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Spring-pug4j is a Spring Framework integration library for Pug4J (formerly Jade4J), providing Spring MVC view resolution for Pug templates. The library acts as a bridge between Spring's view resolution mechanism and the Pug templating engine.
8+
9+
**Key Details:**
10+
- Current version: 3.3.2-SNAPSHOT
11+
- Requires Java 17+
12+
- Spring Framework 6.2+ (Jakarta EE with jakarta.servlet-api 6.0)
13+
- Build tool: Maven
14+
- Testing: JUnit 4, Mockito
15+
16+
## Build Commands
17+
18+
```bash
19+
# Compile the project
20+
mvn compile
21+
22+
# Run all tests
23+
mvn test
24+
25+
# Run a specific test class
26+
mvn test -Dtest=SpringTemplateLoaderTest
27+
28+
# Run tests with debug logging
29+
mvn --batch-mode test -D"org.slf4j.simpleLogger.defaultLogLevel"="error" -D"org.slf4j.simpleLogger.log.de.neuland.pug4j"="debug"
30+
31+
# Full build with verification
32+
mvn --batch-mode --update-snapshots verify
33+
34+
# Package the library
35+
mvn package
36+
37+
# Install to local Maven repository
38+
mvn install
39+
```
40+
41+
## Architecture
42+
43+
The library consists of three core components that integrate Spring MVC with Pug4J:
44+
45+
### 1. SpringTemplateLoader (`de.neuland.pug4j.spring.template.SpringTemplateLoader`)
46+
- Implements `TemplateLoader` from pug4j and `ResourceLoaderAware` from Spring
47+
- Responsible for loading Pug template files using Spring's `ResourceLoader` abstraction
48+
- Handles path resolution, including:
49+
- Classpath resources (e.g., `classpath:/templates`)
50+
- File system paths (including Windows paths like `file:C:/templates`)
51+
- Relative and absolute paths
52+
- Path normalization (converts Windows backslashes to Unix forward slashes)
53+
- Automatically appends `.pug` suffix to template names if no extension is provided
54+
- Configurable properties:
55+
- `templateLoaderPath`: Base path for template lookup (default: "")
56+
- `basePath`: Additional base path component (default: "")
57+
- `encoding`: Character encoding (default: "UTF-8")
58+
- `suffix`: Template file extension (default: ".pug")
59+
60+
### 2. PugViewResolver (`de.neuland.pug4j.spring.view.PugViewResolver`)
61+
- Extends Spring's `AbstractTemplateViewResolver`
62+
- Registers itself as a view resolver in Spring MVC's view resolution chain
63+
- Creates `PugView` instances for resolved view names
64+
- Configures each view with:
65+
- The shared `PugConfiguration` instance
66+
- Content type (default: "text/html;charset=UTF-8")
67+
- Exception rendering mode for development
68+
69+
### 3. PugView (`de.neuland.pug4j.spring.view.PugView`)
70+
- Extends Spring's `AbstractTemplateView`
71+
- Executes template rendering by:
72+
- Retrieving compiled template from `PugConfiguration`
73+
- Merging Spring MVC model data with the template
74+
- Writing rendered HTML to the HTTP response
75+
- Features a development-friendly exception rendering mode (`renderExceptions`):
76+
- When enabled, catches `PugException` and renders formatted HTML error pages
77+
- When disabled, logs errors and allows Spring's standard error handling
78+
79+
### Component Interaction Flow
80+
81+
1. Spring MVC receives a request and determines a logical view name (e.g., "index")
82+
2. `PugViewResolver.buildView()` creates a `PugView` instance
83+
3. `PugView.renderMergedTemplateModel()` is invoked with the model data
84+
4. `PugView` retrieves the compiled template via `PugConfiguration.getTemplate()`
85+
5. `PugConfiguration` uses `SpringTemplateLoader.getReader()` to load the template source
86+
6. Template is compiled (or retrieved from cache) and rendered with the model
87+
7. Output is written to the HTTP response
88+
89+
## Configuration Patterns
90+
91+
The library supports both XML and Java-based Spring configuration:
92+
93+
**XML Configuration:**
94+
```xml
95+
<bean id="templateLoader" class="de.neuland.pug4j.spring.template.SpringTemplateLoader">
96+
<property name="templateLoaderPath" value="classpath:/templates" />
97+
</bean>
98+
99+
<bean id="pugConfiguration" class="de.neuland.pug4j.PugConfiguration">
100+
<property name="caching" value="false" />
101+
<property name="templateLoader" ref="templateLoader" />
102+
</bean>
103+
104+
<bean id="viewResolver" class="de.neuland.pug4j.spring.view.PugViewResolver">
105+
<property name="configuration" ref="pugConfiguration" />
106+
<property name="renderExceptions" value="true" />
107+
</bean>
108+
```
109+
110+
**Java Configuration:**
111+
```java
112+
@Configuration
113+
public class PugConfig {
114+
@Bean
115+
public SpringTemplateLoader templateLoader() {
116+
SpringTemplateLoader loader = new SpringTemplateLoader();
117+
loader.setTemplateLoaderPath("classpath:/templates");
118+
loader.setEncoding("UTF-8");
119+
loader.setSuffix(".pug");
120+
return loader;
121+
}
122+
123+
@Bean
124+
public PugConfiguration pugConfiguration() {
125+
PugConfiguration config = new PugConfiguration();
126+
config.setCaching(false);
127+
config.setTemplateLoader(templateLoader());
128+
return config;
129+
}
130+
131+
@Bean
132+
public ViewResolver viewResolver() {
133+
PugViewResolver resolver = new PugViewResolver();
134+
resolver.setConfiguration(pugConfiguration());
135+
return resolver;
136+
}
137+
}
138+
```
139+
140+
## Release Process
141+
142+
This project uses the Maven Release Plugin for releases:
143+
144+
```bash
145+
# Prepare release (updates versions, creates tag)
146+
mvn release:prepare
147+
148+
# Perform release (builds and deploys to repository)
149+
mvn release:perform
150+
```
151+
152+
Releases are signed with GPG when the `performRelease` property is set, and deployed to Sonatype OSS repository.
153+
154+
## Testing Notes
155+
156+
- Tests use JUnit 4 and Mockito for mocking
157+
- `SpringTemplateLoaderTest` focuses on path resolution edge cases:
158+
- Windows path handling (backslash to forward slash conversion)
159+
- Relative paths with `..` navigation
160+
- Empty template loader paths
161+
- Various combinations of `templateLoaderPath`, `basePath`, and template names
162+
- CI runs on both Ubuntu and Windows to ensure cross-platform compatibility
163+
- Timezone is set to "Europe/Berlin" in CI environment
164+
165+
## Important Implementation Details
166+
167+
- **Path Normalization**: All file paths are converted to Unix-style (forward slashes) using `FilenameUtils.separatorsToUnix()` to ensure cross-platform compatibility
168+
- **Extension Handling**: The `SpringTemplateLoader.getExtension()` method returns the suffix without the leading dot (e.g., "pug" not ".pug")
169+
- **Resource Loading**: Uses Spring's `ResourceLoader` abstraction, supporting classpath, file system, and URL-based resources
170+
- **Error Handling**: In development mode (`renderExceptions=true`), template compilation errors are rendered as formatted HTML pages; in production mode, errors are logged and handled by Spring's error handling

pom.xml

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,10 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>de.neuland-bfi</groupId>
55
<artifactId>spring-pug4j</artifactId>
6-
<version>3.3.2-SNAPSHOT</version>
6+
<version>3.4.0-SNAPSHOT</version>
77
<packaging>jar</packaging>
88
<name>spring-pug4j</name>
99
<description>Spring interface to the Pug4J compiler (formerly known as spring-jade4j)</description>
10-
<parent>
11-
<groupId>org.sonatype.oss</groupId>
12-
<artifactId>oss-parent</artifactId>
13-
<version>9</version>
14-
</parent>
15-
1610
<url>https://github.com/neuland/spring-pug4j</url>
1711

1812
<issueManagement>
@@ -58,6 +52,27 @@
5852
</developer>
5953
</developers>
6054

55+
<distributionManagement>
56+
<snapshotRepository>
57+
<id>central</id>
58+
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
59+
</snapshotRepository>
60+
<repository>
61+
<id>central</id>
62+
<url>https://central.sonatype.com</url>
63+
</repository>
64+
</distributionManagement>
65+
66+
<repositories>
67+
<repository>
68+
<id>central-portal-snapshots</id>
69+
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
70+
<snapshots>
71+
<enabled>true</enabled>
72+
</snapshots>
73+
</repository>
74+
</repositories>
75+
6176
<properties>
6277
<org.springframework.version>6.2.1</org.springframework.version>
6378
<servlet-api-version>6.0.0</servlet-api-version>
@@ -68,14 +83,18 @@
6883
<commons-io.version>2.18.0</commons-io.version>
6984
<junit.version>4.13.2</junit.version>
7085
<mockito-core.version>5.6.0</mockito-core.version>
71-
<pug4j.version>2.3.1</pug4j.version>
72-
<maven-gpg-plugin.version>3.1.0</maven-gpg-plugin.version>
73-
<maven-release-plugin.version>3.0.1</maven-release-plugin.version>
74-
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
75-
<maven-surefire-plugin.version>3.0.0</maven-surefire-plugin.version>
76-
<maven-source-plugin.version>3.3.0</maven-source-plugin.version>
77-
<maven-javadoc-plugin.version>3.6.0</maven-javadoc-plugin.version>
78-
<maven-deploy-plugin.version>3.1.3</maven-deploy-plugin.version>
86+
<pug4j.version>2.4.0</pug4j.version>
87+
<maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version>
88+
<maven-release-plugin.version>3.1.1</maven-release-plugin.version>
89+
<maven-compiler-plugin.version>3.14.1</maven-compiler-plugin.version>
90+
<maven-surefire-plugin.version>3.5.4</maven-surefire-plugin.version>
91+
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
92+
<maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version>
93+
<maven-deploy-plugin.version>3.1.4</maven-deploy-plugin.version>
94+
<maven-clean-plugin.version>3.5.0</maven-clean-plugin.version>
95+
<maven-install-plugin.version>3.1.4</maven-install-plugin.version>
96+
<maven-enforcer-plugin.version>3.6.2</maven-enforcer-plugin.version>
97+
<central-publishing-maven-plugin.version>0.9.0</central-publishing-maven-plugin.version>
7998
</properties>
8099

81100
<profiles>
@@ -118,7 +137,7 @@
118137
<configuration>
119138
<mavenExecutorId>forked-path</mavenExecutorId>
120139
<useReleaseProfile>false</useReleaseProfile>
121-
<arguments>${arguments} -Psonatype-oss-release</arguments>
140+
<arguments>${arguments} -Prelease-sign-artifacts</arguments>
122141
</configuration>
123142
</plugin>
124143
</plugins>
@@ -169,7 +188,7 @@
169188
<plugin>
170189
<groupId>org.apache.maven.plugins</groupId>
171190
<artifactId>maven-enforcer-plugin</artifactId>
172-
<version>3.4.1</version>
191+
<version>${maven-enforcer-plugin.version}</version>
173192
<executions>
174193
<execution>
175194
<id>enforce-maven</id>
@@ -203,11 +222,20 @@
203222
</plugin>
204223
<plugin>
205224
<artifactId>maven-clean-plugin</artifactId>
206-
<version>3.3.2</version>
225+
<version>${maven-clean-plugin.version}</version>
207226
</plugin>
208227
<plugin>
209228
<artifactId>maven-install-plugin</artifactId>
210-
<version>3.1.3</version>
229+
<version>${maven-install-plugin.version}</version>
230+
</plugin>
231+
<plugin>
232+
<groupId>org.sonatype.central</groupId>
233+
<artifactId>central-publishing-maven-plugin</artifactId>
234+
<version>${central-publishing-maven-plugin.version}</version>
235+
<extensions>true</extensions>
236+
<configuration>
237+
<publishingServerId>central</publishingServerId>
238+
</configuration>
211239
</plugin>
212240
<!-- <plugin>-->
213241
<!-- <groupId>org.apache.maven.plugins</groupId>-->

0 commit comments

Comments
 (0)