1+ buildscript {
2+ repositories {
3+ mavenCentral()
4+ }
5+ dependencies {
6+ classpath ' net.sf.saxon:Saxon-HE:10.6'
7+ }
8+ }
9+
110plugins {
211 id ' io.github.jyjeanne.dita-ot-gradle' version ' 2.3.2'
3- id ' com.github.eerohele.saxon-gradle' version ' 0.9.0-beta4'
12+ // Removed: 'com.github.eerohele.saxon-gradle' - not Configuration Cache compatible
13+ // Replaced with: inline XsltTransformTask class below
414}
515
6- // Specify Saxon version per https://github.com/eerohele/saxon-gradle/blob/master/README.md
16+ import org.gradle.api.DefaultTask
17+ import org.gradle.api.file.RegularFileProperty
18+ import org.gradle.api.provider.MapProperty
19+ import org.gradle.api.tasks.*
20+ import net.sf.saxon.s9api.Processor
21+ import net.sf.saxon.s9api.QName
22+ import net.sf.saxon.s9api.XdmAtomicValue
23+ import javax.xml.transform.stream.StreamSource
24+
25+ /**
26+ * Gradle 9 compatible XSLT transformation task using Saxon-HE.
27+ * Replaces eerohele/saxon-gradle which is not Configuration Cache compatible.
28+ */
29+ @CacheableTask
30+ abstract class XsltTransformTask extends DefaultTask {
31+
32+ @InputFile
33+ @PathSensitive (PathSensitivity .RELATIVE )
34+ abstract RegularFileProperty getInputFile ()
35+
36+ @InputFile
37+ @PathSensitive (PathSensitivity .RELATIVE )
38+ abstract RegularFileProperty getStylesheetFile ()
39+
40+ @OutputFile
41+ abstract RegularFileProperty getOutputFile ()
42+
43+ @Input
44+ @Optional
45+ abstract MapProperty<String , String > getParameters ()
46+
47+ @TaskAction
48+ void transform () {
49+ def inputPath = inputFile. get(). asFile
50+ def stylesheetPath = stylesheetFile. get(). asFile
51+ def outputPath = outputFile. get(). asFile
52+
53+ try {
54+ outputPath. parentFile?. mkdirs()
55+
56+ def processor = new Processor (false )
57+ def compiler = processor. newXsltCompiler()
58+ def executable = compiler. compile(new StreamSource (stylesheetPath))
59+ def transformer = executable. load30()
60+
61+ def params = parameters. getOrElse([:])
62+ if (! params. isEmpty()) {
63+ params. each { name , value ->
64+ transformer. setStylesheetParameters(
65+ Collections . singletonMap(new QName (name), new XdmAtomicValue (value))
66+ )
67+ }
68+ }
769
8- repositories {
9- mavenCentral()
10- }
70+ transformer. transform(new StreamSource (inputPath), processor. newSerializer(outputPath))
71+ logger. lifecycle(" Generated: ${ outputPath.name} " )
72+ } catch (Exception e) {
73+ throw new GradleException (" XSLT transformation failed: ${ inputPath.name} -> ${ outputPath.name} \n " +
74+ " Stylesheet: ${ stylesheetPath.name} \n " +
75+ " Cause: ${ e.message} " , e)
76+ }
77+ }
1178
12- configurations {
13- saxon
14- }
79+ // DSL methods for backward compatibility with saxon-gradle syntax
80+ // Using layout API for Configuration Cache compatibility
81+ void input (Object path ) {
82+ inputFile. set(project. layout. projectDirectory. file(path. toString()))
83+ }
84+
85+ void output (Object path ) {
86+ outputFile. set(project. layout. projectDirectory. file(path. toString()))
87+ }
1588
16- dependencies {
17- // Use Saxon-HE 10.6 like DITA-OT, instead of the version that comes with `saxon-gradle`
18- saxon ' net.sf.saxon:Saxon-HE:10.6'
89+ void stylesheet (Object path ) {
90+ stylesheetFile. set(project. layout. projectDirectory. file(path. toString()))
91+ }
92+
93+ void parameters (Map<String , String > params ) {
94+ parameters. putAll(params)
95+ }
1996}
2097
2198import com.github.jyjeanne.DitaOtTask
22- import com.github.eerohele.SaxonXsltTask
23- import org.gradle.process.ExecOperations
2499
25100def getPropertyOrDefault (String name , def defaultValue ) {
26101 providers. gradleProperty(name). getOrElse(defaultValue)
@@ -33,29 +108,40 @@ String ditaHome = getPropertyOrDefault('ditaHome', layout.projectDirectory.asFil
33108String ditaHomeSrc = getPropertyOrDefault(' ditaHomeSrc' , ditaHome)
34109String configDir = " ${ ditaHomeSrc} /config"
35110String ditavalFile = " ${ projectDirPath} /platform.ditaval"
36- Boolean toolkitBuild = file(" ${ projectDirPath} /../lib/dost.jar" ). exists()
111+
112+ // Defer file existence check for Configuration Cache compatibility
113+ Boolean toolkitBuild = providers. provider {
114+ file(" ${ projectDirPath} /../lib/dost.jar" ). exists()
115+ }. get()
116+
37117String samplesDir = toolkitBuild ? " ${ ditaHome} /docsrc/samples" : " ${ projectDirPath} /samples"
38118String outputDir = getPropertyOrDefault(' outputDir' , toolkitBuild ? " ${ ditaHome} /doc" : " ${ projectDirPath} /out" )
39119
40120String toURI (String path ) {
41121 file(path). toURI(). toString()
42122}
43123
44- task messages (type : SaxonXsltTask ) {
124+ task messages (type : XsltTransformTask ) {
125+ group = ' generation'
126+ description = ' Generate error messages documentation from DITA-OT config.'
45127 input " ${ configDir} /messages.xml"
46128 output " ${ projectDirPath} /topics/error-messages.xml"
47129 stylesheet " ${ projectDirPath} /resources/messages.xsl"
48130}
49131
50- task params (type : SaxonXsltTask ) {
132+ task params (type : XsltTransformTask ) {
133+ group = ' generation'
134+ description = ' Generate parameters documentation from DITA-OT plugins config.'
51135 input " ${ configDir} /plugins.xml"
52136 output " ${ projectDirPath} /parameters/all-parameters.dita"
53137 stylesheet " ${ projectDirPath} /resources/params.xsl"
54138 parameters(' output-dir.url' : toURI(' parameters' ))
55139 outputs. dir " ${ projectDirPath} /parameters"
56140}
57141
58- task extensionPoints (type : SaxonXsltTask ) {
142+ task extensionPoints (type : XsltTransformTask ) {
143+ group = ' generation'
144+ description = ' Generate extension points documentation from DITA-OT plugins config.'
59145 input " ${ configDir} /plugins.xml"
60146 output " ${ projectDirPath} /extension-points/all-extension-points.dita"
61147 stylesheet " ${ projectDirPath} /resources/extension-points.xsl"
@@ -64,17 +150,16 @@ task extensionPoints(type: SaxonXsltTask) {
64150}
65151
66152task generatePlatformFilter {
153+ group = ' generation'
154+ description = ' Generate platform-specific DITAVAL filter file.'
67155 def outputFile = layout. projectDirectory. file(ditavalFile)
68156 outputs. file(outputFile)
69157
70158 doLast {
71- // Use Gradle's built-in OS detection instead of Ant
72- def platformName = ' unix' // default
73- if (org.gradle.internal.os.OperatingSystem . current(). isWindows()) {
74- platformName = ' windows'
75- } else if (org.gradle.internal.os.OperatingSystem . current(). isMacOsX()) {
76- platformName = ' mac'
77- }
159+ // Use System properties for OS detection (public API)
160+ def osName = System . getProperty(' os.name' ). toLowerCase()
161+ def platformName = osName. contains(' win' ) ? ' windows' :
162+ osName. contains(' mac' ) ? ' mac' : ' unix'
78163
79164 // Generate the ditaval file using modern Gradle file operations
80165 outputFile. asFile. text = """ <?xml version="1.0" encoding="UTF-8"?>
@@ -86,69 +171,75 @@ task generatePlatformFilter {
86171 }
87172}
88173
89- task generatePropertiesTemplate (type : SaxonXsltTask ) {
174+ task generatePropertiesTemplate (type : XsltTransformTask ) {
175+ group = ' generation'
176+ description = ' Generate properties template file from DITA-OT plugins config.'
90177 input " ${ configDir} /plugins.xml"
91178 output " ${ samplesDir} /properties/template.properties"
92179 stylesheet " ${ projectDirPath} /resources/properties-file.xsl"
93180}
94181
95182task autoGenerate (dependsOn : [messages, params, extensionPoints, generatePlatformFilter, generatePropertiesTemplate]) {
183+ group = ' generation'
96184 description = ' Run tasks that generate content from resource files and the build environment.'
97185}
98186
99187task pdf (type : DitaOtTask , dependsOn : autoGenerate) {
188+ group = ' documentation'
189+ description = ' Build PDF documentation.'
100190 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
101191 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
102192 input " ${ projectDirPath} /userguide-book.ditamap"
103193 output outputDir
104194 transtype ' pdf'
105195 filter " ${ projectDirPath} /resources/pdf.ditaval"
106196
107- properties {
108- property(name : ' args.chapter.layout' , value : ' BASIC' )
109- property(name : ' args.gen.task.lbl' , value : ' YES' )
110- property(name : ' include.rellinks' , value : ' #default external' )
111- property(name : ' outputFile.base' , value : ' userguide' )
112- property(name : ' theme' , value : " ${ projectDirPath} /samples/themes/dita-ot-docs-theme.yaml" )
113- }
197+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
198+ ditaProperties. put(' args.chapter.layout' , ' BASIC' )
199+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
200+ ditaProperties. put(' include.rellinks' , ' #default external' )
201+ ditaProperties. put(' outputFile.base' , ' userguide' )
202+ ditaProperties. put(' theme' , " ${ projectDirPath} /samples/themes/dita-ot-docs-theme.yaml" )
114203}
115204
116205task html (type : DitaOtTask , dependsOn : autoGenerate) {
206+ group = ' documentation'
207+ description = ' Build HTML5 documentation.'
117208 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
118209 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
119210 input " ${ projectDirPath} /userguide.ditamap"
120211 output outputDir
121212 transtype ' html5'
122213 filter " ${ projectDirPath} /resources/html.ditaval"
123214
124- properties {
125- property(name : ' args.copycss' , value : ' yes' )
126- property(name : ' args.css' , value : ' dita-ot-doc.css' )
127- property(name : ' args.csspath' , value : ' css' )
128- property(name : ' args.cssroot' , value : " ${ projectDirPath} /resources/" )
129- property(name : ' args.gen.task.lbl' , value : ' YES' )
130- property(name : ' args.hdr' , value : " ${ projectDirPath} /resources/header.xml" )
131- property(name : ' args.rellinks' , value : ' noparent' )
132- property(name : ' html5.toc.generate' , value : ' no' )
133- property(name : ' nav-toc' , value : ' partial' )
134- }
215+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
216+ ditaProperties. put(' args.copycss' , ' yes' )
217+ ditaProperties. put(' args.css' , ' dita-ot-doc.css' )
218+ ditaProperties. put(' args.csspath' , ' css' )
219+ ditaProperties. put(' args.cssroot' , " ${ projectDirPath} /resources/" )
220+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
221+ ditaProperties. put(' args.hdr' , " ${ projectDirPath} /resources/header.xml" )
222+ ditaProperties. put(' args.rellinks' , ' noparent' )
223+ ditaProperties. put(' html5.toc.generate' , ' no' )
224+ ditaProperties. put(' nav-toc' , ' partial' )
135225}
136226
137227task htmlhelp (type : DitaOtTask , dependsOn : autoGenerate) {
228+ group = ' documentation'
229+ description = ' Build HTML Help (.chm) documentation.'
138230 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
139231 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
140232 input " ${ projectDirPath} /userguide.ditamap"
141233 output outputDir
142234 transtype ' htmlhelp'
143235 filter ditavalFile
144236
145- properties {
146- property(name : ' args.copycss' , value : ' yes' )
147- property(name : ' args.css' , value : ' dita-ot-doc.css' )
148- property(name : ' args.csspath' , value : ' css' )
149- property(name : ' args.cssroot' , value : " ${ projectDirPath} /resources/" )
150- property(name : ' args.gen.task.lbl' , value : ' YES' )
151- }
237+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
238+ ditaProperties. put(' args.copycss' , ' yes' )
239+ ditaProperties. put(' args.css' , ' dita-ot-doc.css' )
240+ ditaProperties. put(' args.csspath' , ' css' )
241+ ditaProperties. put(' args.cssroot' , " ${ projectDirPath} /resources/" )
242+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
152243
153244 doLast {
154245 // Move .chm files using modern Gradle file operations
@@ -165,67 +256,66 @@ task htmlhelp(type: DitaOtTask, dependsOn: autoGenerate) {
165256 }
166257}
167258
168- task cleanUp {
259+ task cleanOutput {
260+ group = ' build'
261+ description = ' Delete the output directory.'
169262 doLast {
170263 delete outputDir
171264 }
172265}
173266
174- // Get git commit hash at configuration time for tasks that need it
175- def getGitCommitHash () {
176- try {
177- def result = new ByteArrayOutputStream ()
178- exec {
179- workingDir = layout. projectDirectory. asFile
180- commandLine ' git' , ' rev-parse' , ' HEAD'
181- standardOutput = result
182- ignoreExitValue = true
183- }
184- return result. toString(). trim()
185- } catch (Exception e) {
186- logger. warn(" Could not get git commit hash: ${ e.message} " )
187- return ' unknown'
188- }
189- }
190-
191- // Store git commit for use by tasks
192- def gitCommitHash = getGitCommitHash()
267+ // Get git commit hash using Gradle 9 compatible Provider API
268+ // Uses providers.exec() instead of deprecated project.exec()
269+ def gitCommitHash = providers. exec {
270+ commandLine ' git' , ' rev-parse' , ' HEAD'
271+ ignoreExitValue = true
272+ }. standardOutput. asText. map { it. trim() }. getOrElse(' unknown' )
193273
194274task gitMetadata {
275+ group = ' build'
276+ description = ' Log git commit metadata.'
195277 // This task just logs the git commit for reference
196278 doLast {
197- logger. info (" Git commit: ${ gitCommitHash} " )
279+ logger. lifecycle (" Git commit: ${ gitCommitHash} " )
198280 }
199281
200282 // Mark outputs to help with up-to-date checking
201283 outputs. upToDateWhen { false } // Always run since git commit changes frequently
202284}
203285
204286task site (type : DitaOtTask ) {
287+ group = ' documentation'
288+ description = ' Build website documentation.'
205289 dependsOn ' messages' , ' params' , ' extensionPoints' , ' gitMetadata'
206290
207291 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
208292 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
209293 input file(" ${ projectDirPath} /site.ditamap" )
210- output getPropertyOrDefault(' outputDir' , " ${ buildDir } / site" )
294+ output getPropertyOrDefault(' outputDir' , layout . buildDirectory . dir( " site" ) . get() . asFile . path )
211295 filter " ${ projectDirPath} /resources/site.ditaval"
212296
213297 transtype ' org.dita-ot.html'
214298
215299 // Evaluate the noCommitMeta flag at configuration time
216300 def includeCommitMeta = ! providers. gradleProperty(' noCommitMeta' ). map { Boolean . parseBoolean(it) }. getOrElse(false )
217301
218- properties {
219- property(name : ' args.gen.task.lbl' , value : ' YES' )
220- property(name : ' args.rellinks' , value : ' noparent' )
221- if (includeCommitMeta) {
222- // Use the git commit hash obtained at configuration time
223- property(name : ' commit' , value : gitCommitHash)
224- }
302+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
303+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
304+ ditaProperties. put(' args.rellinks' , ' noparent' )
305+ if (includeCommitMeta) {
306+ // Use the git commit hash obtained at configuration time
307+ ditaProperties. put(' commit' , gitCommitHash)
225308 }
226309}
227310
228- task all (dependsOn : [pdf, html, htmlhelp])
229- task dist (dependsOn : [pdf, html])
311+ task all (dependsOn : [pdf, html, htmlhelp]) {
312+ group = ' documentation'
313+ description = ' Build all documentation formats (PDF, HTML, HTMLHelp).'
314+ }
315+
316+ task dist (dependsOn : [pdf, html]) {
317+ group = ' documentation'
318+ description = ' Build distribution documentation (PDF and HTML).'
319+ }
230320
231321defaultTasks ' dist'
0 commit comments