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
7-
816repositories {
917 mavenCentral()
1018}
1119
12- configurations {
13- saxon
14- }
20+ import org.gradle.api.DefaultTask
21+ import org.gradle.api.file.RegularFileProperty
22+ import org.gradle.api.provider.MapProperty
23+ import org.gradle.api.tasks.*
24+ import net.sf.saxon.s9api.Processor
25+ import net.sf.saxon.s9api.QName
26+ import net.sf.saxon.s9api.XdmAtomicValue
27+ import javax.xml.transform.stream.StreamSource
28+
29+ /**
30+ * Gradle 9 compatible XSLT transformation task using Saxon-HE.
31+ * Replaces eerohele/saxon-gradle which is not Configuration Cache compatible.
32+ */
33+ @CacheableTask
34+ abstract class XsltTransformTask extends DefaultTask {
35+
36+ @InputFile
37+ @PathSensitive (PathSensitivity .RELATIVE )
38+ abstract RegularFileProperty getInputFile ()
39+
40+ @InputFile
41+ @PathSensitive (PathSensitivity .RELATIVE )
42+ abstract RegularFileProperty getStylesheetFile ()
43+
44+ @OutputFile
45+ abstract RegularFileProperty getOutputFile ()
46+
47+ @Input
48+ @Optional
49+ abstract MapProperty<String , String > getParameters ()
50+
51+ @TaskAction
52+ void transform () {
53+ def inputPath = inputFile. get(). asFile
54+ def stylesheetPath = stylesheetFile. get(). asFile
55+ def outputPath = outputFile. get(). asFile
56+
57+ try {
58+ outputPath. parentFile?. mkdirs()
59+
60+ def processor = new Processor (false )
61+ def compiler = processor. newXsltCompiler()
62+ def executable = compiler. compile(new StreamSource (stylesheetPath))
63+ def transformer = executable. load30()
64+
65+ def params = parameters. getOrElse([:])
66+ if (! params. isEmpty()) {
67+ params. each { name , value ->
68+ transformer. setStylesheetParameters(
69+ Collections . singletonMap(new QName (name), new XdmAtomicValue (value))
70+ )
71+ }
72+ }
73+
74+ transformer. transform(new StreamSource (inputPath), processor. newSerializer(outputPath))
75+ logger. lifecycle(" Generated: ${ outputPath.name} " )
76+ } catch (Exception e) {
77+ throw new GradleException (" XSLT transformation failed: ${ inputPath.name} -> ${ outputPath.name} \n " +
78+ " Stylesheet: ${ stylesheetPath.name} \n " +
79+ " Cause: ${ e.message} " , e)
80+ }
81+ }
82+
83+ // DSL methods for backward compatibility with saxon-gradle syntax
84+ // Using layout API for Configuration Cache compatibility
85+ void input (Object path ) {
86+ inputFile. set(project. layout. projectDirectory. file(path. toString()))
87+ }
88+
89+ void output (Object path ) {
90+ outputFile. set(project. layout. projectDirectory. file(path. toString()))
91+ }
92+
93+ void stylesheet (Object path ) {
94+ stylesheetFile. set(project. layout. projectDirectory. file(path. toString()))
95+ }
1596
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 '
97+ void parameters ( Map< String , String > params ) {
98+ parameters . putAll(params)
99+ }
19100}
20101
21102import com.github.jyjeanne.DitaOtTask
22- import com.github.eerohele.SaxonXsltTask
23- import org.gradle.process.ExecOperations
24103
25104def getPropertyOrDefault (String name , def defaultValue ) {
26105 providers. gradleProperty(name). getOrElse(defaultValue)
@@ -33,29 +112,40 @@ String ditaHome = getPropertyOrDefault('ditaHome', layout.projectDirectory.asFil
33112String ditaHomeSrc = getPropertyOrDefault(' ditaHomeSrc' , ditaHome)
34113String configDir = " ${ ditaHomeSrc} /config"
35114String ditavalFile = " ${ projectDirPath} /platform.ditaval"
36- Boolean toolkitBuild = file(" ${ projectDirPath} /../lib/dost.jar" ). exists()
115+
116+ // Defer file existence check for Configuration Cache compatibility
117+ Boolean toolkitBuild = providers. provider {
118+ file(" ${ projectDirPath} /../lib/dost.jar" ). exists()
119+ }. get()
120+
37121String samplesDir = toolkitBuild ? " ${ ditaHome} /docsrc/samples" : " ${ projectDirPath} /samples"
38122String outputDir = getPropertyOrDefault(' outputDir' , toolkitBuild ? " ${ ditaHome} /doc" : " ${ projectDirPath} /out" )
39123
40124String toURI (String path ) {
41125 file(path). toURI(). toString()
42126}
43127
44- task messages (type : SaxonXsltTask ) {
128+ task messages (type : XsltTransformTask ) {
129+ group = ' generation'
130+ description = ' Generate error messages documentation from DITA-OT config.'
45131 input " ${ configDir} /messages.xml"
46132 output " ${ projectDirPath} /topics/error-messages.xml"
47133 stylesheet " ${ projectDirPath} /resources/messages.xsl"
48134}
49135
50- task params (type : SaxonXsltTask ) {
136+ task params (type : XsltTransformTask ) {
137+ group = ' generation'
138+ description = ' Generate parameters documentation from DITA-OT plugins config.'
51139 input " ${ configDir} /plugins.xml"
52140 output " ${ projectDirPath} /parameters/all-parameters.dita"
53141 stylesheet " ${ projectDirPath} /resources/params.xsl"
54142 parameters(' output-dir.url' : toURI(' parameters' ))
55143 outputs. dir " ${ projectDirPath} /parameters"
56144}
57145
58- task extensionPoints (type : SaxonXsltTask ) {
146+ task extensionPoints (type : XsltTransformTask ) {
147+ group = ' generation'
148+ description = ' Generate extension points documentation from DITA-OT plugins config.'
59149 input " ${ configDir} /plugins.xml"
60150 output " ${ projectDirPath} /extension-points/all-extension-points.dita"
61151 stylesheet " ${ projectDirPath} /resources/extension-points.xsl"
@@ -64,17 +154,16 @@ task extensionPoints(type: SaxonXsltTask) {
64154}
65155
66156task generatePlatformFilter {
157+ group = ' generation'
158+ description = ' Generate platform-specific DITAVAL filter file.'
67159 def outputFile = layout. projectDirectory. file(ditavalFile)
68160 outputs. file(outputFile)
69161
70162 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- }
163+ // Use System properties for OS detection (public API)
164+ def osName = System . getProperty(' os.name' ). toLowerCase()
165+ def platformName = osName. contains(' win' ) ? ' windows' :
166+ osName. contains(' mac' ) ? ' mac' : ' unix'
78167
79168 // Generate the ditaval file using modern Gradle file operations
80169 outputFile. asFile. text = """ <?xml version="1.0" encoding="UTF-8"?>
@@ -86,69 +175,75 @@ task generatePlatformFilter {
86175 }
87176}
88177
89- task generatePropertiesTemplate (type : SaxonXsltTask ) {
178+ task generatePropertiesTemplate (type : XsltTransformTask ) {
179+ group = ' generation'
180+ description = ' Generate properties template file from DITA-OT plugins config.'
90181 input " ${ configDir} /plugins.xml"
91182 output " ${ samplesDir} /properties/template.properties"
92183 stylesheet " ${ projectDirPath} /resources/properties-file.xsl"
93184}
94185
95186task autoGenerate (dependsOn : [messages, params, extensionPoints, generatePlatformFilter, generatePropertiesTemplate]) {
187+ group = ' generation'
96188 description = ' Run tasks that generate content from resource files and the build environment.'
97189}
98190
99191task pdf (type : DitaOtTask , dependsOn : autoGenerate) {
192+ group = ' documentation'
193+ description = ' Build PDF documentation.'
100194 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
101195 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
102196 input " ${ projectDirPath} /userguide-book.ditamap"
103197 output outputDir
104198 transtype ' pdf'
105199 filter " ${ projectDirPath} /resources/pdf.ditaval"
106200
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- }
201+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
202+ ditaProperties. put(' args.chapter.layout' , ' BASIC' )
203+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
204+ ditaProperties. put(' include.rellinks' , ' #default external' )
205+ ditaProperties. put(' outputFile.base' , ' userguide' )
206+ ditaProperties. put(' theme' , " ${ projectDirPath} /samples/themes/dita-ot-docs-theme.yaml" )
114207}
115208
116209task html (type : DitaOtTask , dependsOn : autoGenerate) {
210+ group = ' documentation'
211+ description = ' Build HTML5 documentation.'
117212 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
118213 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
119214 input " ${ projectDirPath} /userguide.ditamap"
120215 output outputDir
121216 transtype ' html5'
122217 filter " ${ projectDirPath} /resources/html.ditaval"
123218
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- }
219+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
220+ ditaProperties. put(' args.copycss' , ' yes' )
221+ ditaProperties. put(' args.css' , ' dita-ot-doc.css' )
222+ ditaProperties. put(' args.csspath' , ' css' )
223+ ditaProperties. put(' args.cssroot' , " ${ projectDirPath} /resources/" )
224+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
225+ ditaProperties. put(' args.hdr' , " ${ projectDirPath} /resources/header.xml" )
226+ ditaProperties. put(' args.rellinks' , ' noparent' )
227+ ditaProperties. put(' html5.toc.generate' , ' no' )
228+ ditaProperties. put(' nav-toc' , ' partial' )
135229}
136230
137231task htmlhelp (type : DitaOtTask , dependsOn : autoGenerate) {
232+ group = ' documentation'
233+ description = ' Build HTML Help (.chm) documentation.'
138234 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
139235 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
140236 input " ${ projectDirPath} /userguide.ditamap"
141237 output outputDir
142238 transtype ' htmlhelp'
143239 filter ditavalFile
144240
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- }
241+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
242+ ditaProperties. put(' args.copycss' , ' yes' )
243+ ditaProperties. put(' args.css' , ' dita-ot-doc.css' )
244+ ditaProperties. put(' args.csspath' , ' css' )
245+ ditaProperties. put(' args.cssroot' , " ${ projectDirPath} /resources/" )
246+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
152247
153248 doLast {
154249 // Move .chm files using modern Gradle file operations
@@ -165,67 +260,66 @@ task htmlhelp(type: DitaOtTask, dependsOn: autoGenerate) {
165260 }
166261}
167262
168- task cleanUp {
263+ task cleanOutput {
264+ group = ' build'
265+ description = ' Delete the output directory.'
169266 doLast {
170267 delete outputDir
171268 }
172269}
173270
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()
271+ // Get git commit hash using Gradle 9 compatible Provider API
272+ // Uses providers.exec() instead of deprecated project.exec()
273+ def gitCommitHash = providers. exec {
274+ commandLine ' git' , ' rev-parse' , ' HEAD'
275+ ignoreExitValue = true
276+ }. standardOutput. asText. map { it. trim() }. getOrElse(' unknown' )
193277
194278task gitMetadata {
279+ group = ' build'
280+ description = ' Log git commit metadata.'
195281 // This task just logs the git commit for reference
196282 doLast {
197- logger. info (" Git commit: ${ gitCommitHash} " )
283+ logger. lifecycle (" Git commit: ${ gitCommitHash} " )
198284 }
199285
200286 // Mark outputs to help with up-to-date checking
201287 outputs. upToDateWhen { false } // Always run since git commit changes frequently
202288}
203289
204290task site (type : DitaOtTask ) {
291+ group = ' documentation'
292+ description = ' Build website documentation.'
205293 dependsOn ' messages' , ' params' , ' extensionPoints' , ' gitMetadata'
206294
207295 // Set DITA-OT directory: pass as parameter -PditaHome or fall back to parent when run in core repo.
208296 ditaOt file(findProperty(' ditaHome' ) ?: ditaHome)
209297 input file(" ${ projectDirPath} /site.ditamap" )
210- output getPropertyOrDefault(' outputDir' , " ${ buildDir } / site" )
298+ output getPropertyOrDefault(' outputDir' , layout . buildDirectory . dir( " site" ) . get() . asFile . path )
211299 filter " ${ projectDirPath} /resources/site.ditaval"
212300
213301 transtype ' org.dita-ot.html'
214302
215303 // Evaluate the noCommitMeta flag at configuration time
216304 def includeCommitMeta = ! providers. gradleProperty(' noCommitMeta' ). map { Boolean . parseBoolean(it) }. getOrElse(false )
217305
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- }
306+ // Use ditaProperties MapProperty directly for v2.3.0 compatibility
307+ ditaProperties. put(' args.gen.task.lbl' , ' YES' )
308+ ditaProperties. put(' args.rellinks' , ' noparent' )
309+ if (includeCommitMeta) {
310+ // Use the git commit hash obtained at configuration time
311+ ditaProperties. put(' commit' , gitCommitHash)
225312 }
226313}
227314
228- task all (dependsOn : [pdf, html, htmlhelp])
229- task dist (dependsOn : [pdf, html])
315+ task all (dependsOn : [pdf, html, htmlhelp]) {
316+ group = ' documentation'
317+ description = ' Build all documentation formats (PDF, HTML, HTMLHelp).'
318+ }
319+
320+ task dist (dependsOn : [pdf, html]) {
321+ group = ' documentation'
322+ description = ' Build distribution documentation (PDF and HTML).'
323+ }
230324
231325defaultTasks ' dist'
0 commit comments