Skip to content

Commit 77a484f

Browse files
committed
(#757) Downdoc as a toolchain
1 parent 1aedf36 commit 77a484f

File tree

23 files changed

+1177
-83
lines changed

23 files changed

+1177
-83
lines changed

docs/modules/ROOT/pages/model5/asciidoctorj/gems.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ plugins {
1313
1414
repositories {
1515
ruby.gems() // <.>
16+
ruby.coop() // <.>
1617
}
1718
1819
dependencies {
@@ -21,6 +22,7 @@ dependencies {
2122
----
2223
<.> Add a repository so that Gradle knows where to resolve GEMs from.
2324
See https://jruby-gradle.ysb33r.org[Simplified JRuby Gradle plugin] for more details.
25+
<.> If you prefer to use `gem.coop` over the original `rubygems.org`, then you can use this instead or `ruby.gems()`.
2426
<.> Add the specific GEM to the toolchain.
2527
The configuration name is of the format `asciidoctorGem<TOOLCHAIN_NAME>`.
2628

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version=5.0.0-alpha.2
1+
version=5.0.0-alpha.2-SNAPSHOT
22
group=org.asciidoctor
33
projectInceptionYear=2013
44
project_description=A Gradle plugin suite that uses Asciidoctor via JRuby/Node.js to process AsciiDoc source files within the project.

gradle/libs.versions.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ asciidoctorjsRevealjs = "5.2.0"
2828
# end::hacking-asciidoctorjs-output-formatter[]
2929
cglib = "3.3.0"
3030
commonsIO = "2.15.1"
31+
downdoc = "1.0.2-stable"
3132
gemHaml = "6.3.0"
3233
gemKroki = "0.10.0"
3334
gemSlim = "5.2.1"
3435
gemTilt= "2.6.1"
35-
grolifant = "5.4.0"
36+
grolifant = "5.5.0-alpha.3"
3637
groovyForGradle9Testing = "4.0.4"
3738
jruby = "9.4.8.0"
3839
jsoup = "1.17.2"
@@ -42,8 +43,8 @@ pluginJRubySimple = "2.0.0"
4243
pluginNodejs = "4.1.0"
4344
pluginPublishPlugin = "1.2.1"
4445
pluginIvypot = "2.0.3"
45-
pluginJavaScript = "4.2.0"
46-
pluginJRuby = "2.1.6"
46+
pluginJavaScript = "5.0.0-alpha.1"
47+
pluginJRuby = "2.2.0"
4748
pluginLicense = "0.16.1"
4849
pluginOS = "2.0.0"
4950
spock = "2.3-groovy-3.0"
@@ -78,8 +79,10 @@ pluginPublishPlugin = { module = "com.gradle.publish:plugin-publish-plugin", ver
7879
pluginNodejs = { module = "org.ysb33r.gradle:nodejs-gradle-plugin", version.ref = "pluginNodejs" }
7980
pluginIvypot = { module = "org.ysb33r.ivypot:ivypot-gradle-plugin", version.ref = "pluginIvypot" }
8081
pluginJavaScript = { module = "org.ysb33r.nodejs.dev.base:org.ysb33r.nodejs.dev.base.gradle.plugin", version.ref = "pluginJavaScript" }
82+
pluginJavaScriptEcosystem = { module = "org.ysb33r.gradle:js-ecosystem-core-plugin", version.ref = "pluginJavaScript" }
8183
pluginJRuby = { module = "org.ysb33r.jruby.resolver:org.ysb33r.jruby.resolver.gradle.plugin", version.ref = "pluginJRuby" }
8284
pluginOS = { module = "org.ysb33r.os:org.ysb33r.os.gradle.plugin", version.ref = "pluginOS" }
85+
pluginPnpm = { module = "org.ysb33r.gradle:js-ecosystem-pnpm-plugin", version.ref = "pluginJavaScript" }
8386
spockCore = { module = "org.spockframework:spock-core", version.ref = "spock" }
8487

8588
[plugins]

model5/downdoc/build.gradle

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
plugins {
2+
id 'org.asciidoctor.internal.model5.gradle.project'
3+
}
4+
5+
agProject {
6+
withIntegrationTests()
7+
configurePlugin(
8+
'org.asciidoctor.downdoc.base',
9+
'Plugin to convert AsciiDoc to Markdown',
10+
'Provides a Downdoc toolchain to convert AsciiDoc to Markdown',
11+
'org.asciidoctor.gradle.model5.downdoc.plugins.DowndocBasePlugin',
12+
['asciidoctor', 'downdoc', 'markdown']
13+
)
14+
configurePlugin(
15+
'org.asciidoctor.downdoc',
16+
'Plugin to convert AsciiDoc to Markdown',
17+
'Provides a Downdoc toolchain to convert AsciiDoc to Markdown',
18+
'org.asciidoctor.gradle.model5.downdoc.plugins.DowndocPlugin',
19+
['asciidoctor', 'downdoc', 'markdown']
20+
)
21+
22+
23+
withVersionSubstitution("${project.name}.properties", [
24+
NODE : versionOf('nodejs'),
25+
VERSION : versionOf('downdoc'),
26+
])
27+
}
28+
29+
dependencies {
30+
api project(':asciidoctor5-core-plugin')
31+
implementation(libs.pluginJavaScriptEcosystem)
32+
implementation(libs.pluginPnpm)
33+
implementation(libs.grolifantApi)
34+
runtimeOnly(libs.grolifantRuntime)
35+
testImplementation project(':testfixtures-jvm')
36+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2013 - 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.asciidoctor.gradle.model5.downdoc.formatters
17+
18+
import org.asciidoctor.gradle.model5.downdoc.internal.formatters.DefaultDowndocMarkdownOutputFormatter
19+
import org.asciidoctor.gradle.model5.downdoc.plugins.DowndocPlugin
20+
import org.asciidoctor.gradle.testfixtures.model5.IntegrationSpecification
21+
22+
import static org.asciidoctor.gradle.model5.core.internal.publications.PublicationUtils.DEFAULT_PUBLICATION
23+
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
24+
25+
class DowndocMarkdownSpec extends IntegrationSpecification {
26+
27+
void 'Markdown formatter will convert files and copy resources'() {
28+
setup:
29+
final taskName = 'asciidoctorMarkdown'
30+
final outputDir = new File(buildDir, 'docs/asciidoc/markdown')
31+
32+
writeBuildFile()
33+
copyTestProject('resources')
34+
35+
configureSourceSetGroovy(DEFAULT_PUBLICATION, """
36+
resources {
37+
include 'images/**'
38+
}
39+
""".stripIndent())
40+
41+
when:
42+
final result = getGradleRunner(IS_GROOVY_DSL, [taskName, '-s', '-i']).build()
43+
44+
then: 'Task completed successfully'
45+
result.task(":${taskName}").outcome == SUCCESS
46+
47+
and: 'Content exists'
48+
fileExists(outputDir, 'simple.md')
49+
fileExists(outputDir, 'images/fake11.txt')
50+
fileExists(outputDir, 'images/fake12.txt')
51+
52+
and: 'Resources in source dir that were not specified, were not copied'
53+
!fileExists(outputDir, 'images2/fake2.txt')
54+
}
55+
56+
void writeBuildFile() {
57+
writeBasicBuildFileGroovy(['org.asciidoctor.downdoc'])
58+
addOutputToSourceSetGroovy(
59+
DowndocPlugin.DEFAULT_TOOLCHAIN,
60+
DefaultDowndocMarkdownOutputFormatter.DEFAULT_NAME,
61+
DEFAULT_PUBLICATION
62+
)
63+
}
64+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
* Copyright 2013 - 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.asciidoctor.gradle.model5.downdoc
17+
18+
import groovy.transform.CompileStatic
19+
import org.asciidoctor.gradle.model5.core.internal.publications.PublicationUtils
20+
import org.asciidoctor.gradle.model5.core.toolchains.AsciidoctorToolchain
21+
import org.asciidoctor.gradle.model5.downdoc.formatters.DowndocMarkdownOutputFormatter
22+
import org.asciidoctor.gradle.model5.downdoc.toolchains.DowndocToolchain
23+
import org.gradle.api.Action
24+
import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer
25+
import org.gradle.api.NamedDomainObjectFactory
26+
import org.gradle.api.model.ObjectFactory
27+
28+
import java.util.function.Function
29+
30+
/**
31+
* Utilities for working with the new Asciidoctor model in an {@code downdoc} context.
32+
*
33+
* @author Schalk W. Cronjé
34+
*
35+
* @since 5.0
36+
*/
37+
@CompileStatic
38+
class DowndocModel {
39+
40+
/**
41+
* The toolchain preparation task name
42+
* @param toolchainName Name of the toolchains
43+
* @return Task name
44+
*/
45+
static String toolchainPrepareTaskName(String toolchainName) {
46+
"${PublicationUtils.TASK_PREFIX}Prepare${toolchainName.capitalize()}Toolchain"
47+
}
48+
49+
/**
50+
* Registers an output formatter on all the {@code downdoc} toolchains.
51+
*
52+
* @param toolchains Toolchain container
53+
* @param formatterClass The formatter class
54+
* @param factoryClass The factory for the formatter.
55+
* @param objectFactory objectFactory
56+
*/
57+
static <T extends DowndocMarkdownOutputFormatter> void registerOutputFormatterFactory(
58+
ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
59+
Class<T> formatterClass,
60+
Class<? extends NamedDomainObjectFactory<T>> factoryClass,
61+
ObjectFactory objectFactory
62+
) {
63+
registerOutputFormatterFactory(toolchains, formatterClass) { DowndocToolchain tc ->
64+
objectFactory.newInstance(factoryClass)
65+
}
66+
}
67+
68+
/**
69+
* Registers an output formatter on all the {@code downdoc} toolchains.
70+
*
71+
* @param toolchains Toolchain container
72+
* @param formatterClass The formatter class
73+
* @param factoryFunction A function that will create a factory given a specific toolchain instance.
74+
*/
75+
static <T extends DowndocMarkdownOutputFormatter> void registerOutputFormatterFactory(
76+
ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
77+
Class<T> formatterClass,
78+
Function<DowndocToolchain, NamedDomainObjectFactory<T>> factoryFunction
79+
) {
80+
toolchains.withType(DowndocToolchain).configureEach { tc ->
81+
tc.registeredOutputFormatters.registerFactory(formatterClass, factoryFunction.apply(tc))
82+
}
83+
}
84+
85+
/**
86+
* Registers a named formatter on each of the {@code downdoc} toolchains
87+
* @param toolchains Toolchains
88+
* @param formatterClass Formatter class
89+
* @param name Name of the formatter
90+
*/
91+
static <T extends DowndocMarkdownOutputFormatter> void registerOutputFormatterOnAllToolchains(
92+
ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
93+
Class<T> formatterClass,
94+
String name
95+
) {
96+
registerOutputFormatterOnAllToolchains(toolchains, formatterClass, name) {
97+
}
98+
}
99+
100+
/**
101+
* Registers a named formatter on each of the {@code downdoc} toolchains.
102+
* @param toolchains Toolchains.
103+
* @param formatterClass Formatter class.
104+
* @param name Name of the .
105+
* @param configurator Configurator of the output formatter.
106+
*/
107+
static <T extends DowndocMarkdownOutputFormatter> void registerOutputFormatterOnAllToolchains(
108+
ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
109+
Class<T> formatterClass,
110+
String name,
111+
Action<T> configurator
112+
) {
113+
toolchains.withType(DowndocToolchain).configureEach { tc ->
114+
final fc = tc.registeredOutputFormatters.register(name, formatterClass)
115+
fc.configure(configurator)
116+
}
117+
}
118+
119+
// /**
120+
// * Registers an extension on all the {@code asciidoctor.js} toolchains.
121+
// *
122+
// * @param toolchains Toolchain container
123+
// * @param extensionClass The extension class
124+
// * @param factoryClass The factory for the extension.
125+
// * @param objectFactory objectFactory
126+
// */
127+
// static <T extends AsciidoctorjsExtension> void registerExtensionFactory(
128+
// ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
129+
// Class<T> extensionClass,
130+
// Class<? extends NamedDomainObjectFactory<T>> factoryClass,
131+
// ObjectFactory objectFactory
132+
// ) {
133+
// registerExtensionFactory(toolchains, extensionClass) { DowndocToolchain tc ->
134+
// objectFactory.newInstance(factoryClass, tc)
135+
// }
136+
// }
137+
//
138+
// /**
139+
// * Registers an extension factory on the {@code asciidoctor.js} toolchains.
140+
// *
141+
// * @param toolchains Toolchain container
142+
// * @param extensionClass The extension class
143+
// * @param factoryFunction A function that will create a factory given a specific toolchain instance.
144+
// */
145+
// static <T extends AsciidoctorjsExtension> void registerExtensionFactory(
146+
// ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
147+
// Class<T> extensionClass,
148+
// Function<DowndocToolchain, NamedDomainObjectFactory<T>> factoryFunction
149+
// ) {
150+
// toolchains.withType(DowndocToolchain).configureEach { tc ->
151+
// tc.asciidocExtensions.registerFactory(extensionClass, factoryFunction.apply(tc))
152+
// }
153+
// }
154+
//
155+
// /**
156+
// * Registers an extension on each of the {@code asciidoctorj} toolchains
157+
// * @param toolchains Toolchains
158+
// * @param extensionClass Extension class
159+
// * @param name Name of the extension
160+
// */
161+
// static <T extends AsciidoctorjsExtension> void registerExtensionOnAllToolchains(
162+
// ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
163+
// Class<T> extensionClass,
164+
// String name
165+
// ) {
166+
// registerExtensionOnAllToolchains(toolchains, extensionClass, name) {
167+
// }
168+
// }
169+
//
170+
// /**
171+
// * Registers an extension on each of the {@code asciidoctor.js} toolchains.
172+
// * @param toolchains Toolchains.
173+
// * @param extensionClass Extension class.
174+
// * @param name Name of the extension.
175+
// * @param configurator Configurator of the extension.
176+
// */
177+
// static <T extends AsciidoctorjsExtension> void registerExtensionOnAllToolchains(
178+
// ExtensiblePolymorphicDomainObjectContainer<AsciidoctorToolchain> toolchains,
179+
// Class<T> extensionClass,
180+
// String name,
181+
// Action<T> configurator
182+
// ) {
183+
// toolchains.withType(DowndocToolchain).configureEach { tc ->
184+
// final fc = tc.asciidocExtensions.register(name, extensionClass)
185+
// fc.configure(configurator)
186+
// }
187+
// }
188+
}

0 commit comments

Comments
 (0)