diff --git a/build.gradle b/build.gradle
index c02f13c..e232617 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,103 +1,45 @@
-import org.asciidoctor.gradle.jvm.AsciidoctorTask
import java.text.SimpleDateFormat
plugins {
- id "org.asciidoctor.jvm.base" version "3.3.2"
- id "org.asciidoctor.jvm.convert" version "3.3.2"
- id "org.asciidoctor.jvm.pdf" version "3.3.2"
-}
-repositories {
- mavenCentral()
-}
-
-asciidoctorj {
- version = '2.5.3'
+ id "java"
+ id "application"
}
-ext {
- today = new Date()
- versionDate = new SimpleDateFormat("yyyyMMdd").format(today)
+def group = "org.isaqb"
+def releaseVersion = System.getenv("RELEASE_VERSION")
+def localVersion = "LocalBuild"
+project.version = releaseVersion == null ? localVersion : releaseVersion
+def curriculumFileName = "examination-regulations"
+def criteriaFileName = "examination-criteria"
+def versionDate = new SimpleDateFormat("yyyyMMdd").format(new Date())
+def languages = ["DE", "EN"]
- releaseVersion = System.getenv("RELEASE_VERSION")
- localVersion = "LocalBuild"
- project.version = releaseVersion == null ? localVersion : releaseVersion;
-
- curriculumFileName = "examination-regulations"
- addSuffixToCurriculum = { suffix ->
- for (extension in ["html", "pdf"]) {
- File source = new File("${buildDir}/${curriculumFileName}.${extension}")
- File target = new File("${buildDir}/${curriculumFileName}${suffix}.${extension}")
-
- source.renameTo(target)
- }
- }
+repositories {
+ mavenCentral()
}
-
-
-
-class RenderCurriculumTask extends AsciidoctorTask {
- @Inject
- RenderCurriculumTask(WorkerExecutor we, String curriculumFileName, String versionDate, String language) {
- super(we)
-
- forkOptions {
- jvmArgs "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", "--add-opens", "java.base/java.io=ALL-UNNAMED"
- }
-
-
- sourceDir = new File("./docs/")
- baseDir = new File ("./docs/")
- sources {
- include "index.adoc"
- include "examination-criteria.adoc"
- include "${curriculumFileName}.adoc"
- }
- outputDir = new File("./build/")
- outputOptions {
- separateOutputDirs = false
- backends 'pdf', 'html5'
- }
-
- def fileVersion = project.version.trim() + "-" + language
-
- attributes = [
- 'icons' : 'font',
- 'version-label' : '',
- 'revnumber' : fileVersion,
- 'revdate' : versionDate,
- 'document-version' : fileVersion + "-" + versionDate,
- 'currentDate' : versionDate,
- 'language' : language,
- 'curriculumFileName': curriculumFileName,
- 'debug_adoc' : false,
- 'pdf-stylesdir' : '../pdf-theme/themes',
- 'pdf-fontsdir' : '../pdf-theme/fonts',
- 'pdf-style' : 'isaqb',
- 'stylesheet' : '../html-theme/adoc-github.css',
- 'stylesheet-dir' : '../html-theme'
- ]
- }
+dependencies {
+ implementation("org.asciidoctor:asciidoctorj:2.5.10")
+ implementation("org.asciidoctor:asciidoctorj-pdf:2.3.9")
}
-task buildDocs {
- group 'Documentation'
- description 'Grouping task for generating all languages in several formats'
- dependsOn "renderDE", "renderEN"
+application {
+ mainClass.set("org.isaqb.asciidoc.Main")
+ applicationDefaultJvmArgs = [
+ """-DprojectVersion=${project.version}""",
+ """-DcurriculumFileName=${curriculumFileName}""",
+ """-DcriteriaFileName=${criteriaFileName}""",
+ """-DversionDate=${versionDate}""",
+ """-Dlanguages=${languages.join(',')}""",
+ """--add-opens""", """java.base/sun.nio.ch=ALL-UNNAMED""",
+ """--add-opens""", """java.base/java.io=ALL-UNNAMED"""]
}
-task renderDE(type: RenderCurriculumTask,
- constructorArgs: [curriculumFileName, versionDate, "DE"]) {
- doLast {
- addSuffixToCurriculum("-de")
- }
-}
-task renderEN(type: RenderCurriculumTask,
- constructorArgs: [curriculumFileName, versionDate, "EN"]) {
- doLast {
- addSuffixToCurriculum("-en")
- }
+tasks.register('buildDocs') {
+ description = 'Grouping task for generating all languages in several formats'
+ group = 'documentation'
+ dependsOn "run"
}
defaultTasks "buildDocs"
diff --git a/docs/05-criteria/00-structure.adoc b/docs/05-criteria/00-structure.adoc
index b1525d7..534bbae 100644
--- a/docs/05-criteria/00-structure.adoc
+++ b/docs/05-criteria/00-structure.adoc
@@ -1,9 +1,15 @@
+// we have to adjust the heading levels of all included files, as this structure file
+// is used as the only include for the examination-criteria, and thus requires a different
+// heading structure. Some of the files included below are also included in examination-regulations,
+// which is why they should follow the regular heading style of all the other files.
+// therefore, we also do not need a specific German/English section. To remove warnings, we'll just
+// add empty blocks.
+:leveloffset: -2
+
// tag::DE[]
-== Kriterien
// end::DE[]
// tag::EN[]
-== Criteria
// end::EN[]
include::01-accreditation.adoc[{include_configuration}]
diff --git a/docs/05-criteria/01-accreditation.adoc b/docs/05-criteria/01-accreditation.adoc
index 0612b31..efead9b 100644
--- a/docs/05-criteria/01-accreditation.adoc
+++ b/docs/05-criteria/01-accreditation.adoc
@@ -1,5 +1,4 @@
// tag::DE[]
-=== Akkreditierung
==== Trainingsprovider
Trainingsprovider müssen nachfolgende Kriterien erfüllen, damit sie von iSAQB die Akkreditierung bekommen:
@@ -45,7 +44,10 @@ Zur Akkreditierung muss ein:e Themenmoderator:in folgende Kriterien erfüllen:
// end::DE[]
// tag::EN[]
-=== Accreditation
+==== Training Provider
TODO
+==== Training Facilitators
+
+
// end::EN[]
diff --git a/docs/05-criteria/05-criteria-roadmap.adoc b/docs/05-criteria/05-criteria-roadmap.adoc
index 4290a25..2d40459 100644
--- a/docs/05-criteria/05-criteria-roadmap.adoc
+++ b/docs/05-criteria/05-criteria-roadmap.adoc
@@ -44,7 +44,7 @@
// tag::EN[]
==== Criteria for a Roadmap
-[cols="<3,<1,<7a"]
+[cols="<3,<2,<7a"]
|===
| Criterion | Requirement | Description
diff --git a/docs/05-criteria/06-criteria-formal.adoc b/docs/05-criteria/06-criteria-formal.adoc
index 8ca45c9..5a9d86f 100644
--- a/docs/05-criteria/06-criteria-formal.adoc
+++ b/docs/05-criteria/06-criteria-formal.adoc
@@ -90,7 +90,7 @@
==== Formal Criteria
-[cols="<3,<1,<7a"]
+[cols="<3,<2,<7a"]
|===
| Criterion | Requirement | Description
diff --git a/docs/config/setup.adoc b/docs/config/setup.adoc
index 86cdf25..7802ae3 100644
--- a/docs/config/setup.adoc
+++ b/docs/config/setup.adoc
@@ -2,7 +2,8 @@
:icons: font
:sectnumlevels: 2
:imagesdir: images
-:chapter-label:
+
+:!chapter-signifier:
// ":language:" denotes the language or the target document.
// currently only DE and EN are supported
diff --git a/docs/config/setup_criteria.adoc b/docs/config/setup_criteria.adoc
index cb92da6..f4f65a9 100644
--- a/docs/config/setup_criteria.adoc
+++ b/docs/config/setup_criteria.adoc
@@ -6,7 +6,6 @@ ifeval::["{language}" == "DE"]
endif::[]
ifeval::["{language}" == "EN"]
-:curriculum-name: FULL NAME OF MODULE
:curriculum-header-title: Criteria for the iSAQB® CPSA® Expert Level
:hyphens: en_US
endif::[]
diff --git a/docs/config/setup_regulations.adoc b/docs/config/setup_regulations.adoc
index 8befaf4..6229527 100644
--- a/docs/config/setup_regulations.adoc
+++ b/docs/config/setup_regulations.adoc
@@ -1,14 +1,11 @@
include::setup.adoc[]
-:curriculum-short: MODULKUERZEL
-
ifeval::["{language}" == "DE"]
:curriculum-header-title: Prüfungsordnung iSAQB® CPSA® Expert Level
:hyphens: de
endif::[]
ifeval::["{language}" == "EN"]
-:curriculum-name: FULL NAME OF MODULE
:curriculum-header-title: Examination Regulations iSAQB® CPSA® Expert Level
:hyphens: en_US
endif::[]
diff --git a/docs/examination-criteria.adoc b/docs/examination-criteria.adoc
index 5bc3cde..a2af8b2 100644
--- a/docs/examination-criteria.adoc
+++ b/docs/examination-criteria.adoc
@@ -4,25 +4,19 @@ include::config/setup_criteria.adoc[]
ifeval::["{language}" == "DE"]
= Kriterien für pass:q[
]Certified Professional forpass:q[
]Software Architecture (CPSA)^(R)^pass:q[
]_Expert Level_ pass:q[
]
-:toc-title: Inhaltsverzeichnis
-:toc: left
endif::[]
ifeval::["{language}" == "EN"]
= Criteria for pass:q[
]Certified Professional forpass:q[
]Software Architecture (CPSA)^(R)^pass:q[
]_Expert Level_ pass:q[
]
-:toc: left
endif::[]
// define terms for toc, learning-goals
include::config/i18n-definitions.adoc[tags={language}]
-<<<
:sectnums!:
-include::../license-copyright/copyright.adoc[{include_configuration}]
<<<
-toc::[]
+include::../license-copyright/copyright.adoc[{include_configuration}]
<<<
-:sectnums:
include::05-criteria/00-structure.adoc[{include_configuration}]
diff --git a/docs/index.adoc b/docs/index.adoc
index e182194..1a21fb7 100644
--- a/docs/index.adoc
+++ b/docs/index.adoc
@@ -1,31 +1,29 @@
include::config/setup.adoc[]
= image:isaqb-logo.jpg[width=150]Certified Professional for Software Architecture^(R)^ (CPSA)
-Curriculum {curriculum-name} [{curriculum-short}]
+Expert Level
The international Software Architecture Qualification Board (link:https://isaqb.org[iSAQB]) defines curricula on several levels for software architects.
The terminology used in the iSAQB curricula can be found as a (freely available) ebook, published on https://leanpub.com/isaqbglossary/read[Leanpub].
-== Development versions
+The regulations and criteria of the Expert Level are currently maintained and published in both English (EN) and German (DE).
+Maintainers and volunteer reviewers collaborate on GitHub to improve those documents.
-The Advanced Level Template Curriculum is currently maintained and published in both English (EN) and German (DE).
-Maintainers and volunteer reviewers collaborate on GitHub to improve the curriculum.
-
-[cols="<,^,^"]
+[cols="<,<"]
|===
-| Version | HTML | PDF
+| German | English
+
+| link:examination-regulations-de.pdf[Prüfungsordnung (PDF)]
+| link:examination-regulations-en.pdf[Examination Regulations (PDF)]
-| German
-| link:{curriculumFileName}-de.html[HTML]
-| link:{curriculumFileName}-de.pdf[PDF]
+| link:examination-criteria-de.pdf[Kriterien (PDF)]
+| link:examination-criteria-en.pdf[Examination Criteria (PDF)]
-| English
-| link:{curriculumFileName}-en.html[HTML]
-| link:{curriculumFileName}-en.pdf[PDF]
+| link:iSAQB_CPSA_Expert_Level_Template_Roadmap_DE.docx[Vorlage für eine Roadmap (DOCX)]
+| link:iSAQB_CPSA_Expert_Level_Template_Roadmap_DE.docx[Roadmap Template (DOCX)]
-| Español
-|
-| link:{curriculumFileName}-es.pdf[PDF]
+| link:iSAQB_CPSA_Expert_Level_Field_Report_DE.docx[Erfahrungsbericht zum Expert Level (DOCX)]
+| link:iSAQB_CPSA_Expert_Level_Field_Report_EN.docx[Field Report Expert Level (DOCX)]
|===
diff --git a/docs/index_rc.adoc b/docs/index_rc.adoc
index 3d56769..255f825 100644
--- a/docs/index_rc.adoc
+++ b/docs/index_rc.adoc
@@ -1,32 +1,40 @@
include::config/setup.adoc[]
= image:isaqb-logo.jpg[width=150]Certified Professional for Software Architecture^(R)^ (CPSA)
-- Curriculum {curriculum-name} [{curriculum-short}] – Release Candidate -
+Expert Level
The international Software Architecture Qualification Board (link:https://isaqb.org[iSAQB]) defines curricula on several levels for software architects.
-The **Release Candidates** of the **{curriculum-name} [{curriculum-short}]** advanced level curriculum are currently maintained and published in both English (EN) and German (DE). Maintainers of this curriculum and voluntary reviewers collaborate on https://github.com/isaqb-org[GitHub] to improve the curriculum.
-== Current Release Candidate v2023.1
+The **Release Candidates** of the **Expert Level Regulations and Criteria** are currently maintained and published in both English (EN) and German (DE).
+Maintainers of this curriculum and voluntary reviewers collaborate on https://github.com/isaqb-org[GitHub] to improve the curriculum.
-image:https://img.shields.io/github/last-commit/isaqb-org/advanced-template/main.svg["Last commit"]
-image:https://img.shields.io/github/contributors/isaqb-org/advanced-template.svg["Contributors",link="https://github.com/isaqb-org/advanced-template/graphs/contributors"]
-image:https://img.shields.io/github/issues/isaqb-org/advanced-template.svg["Issues",link="https://github.com/isaqb-org/advanced-template/issues"]
-image:https://img.shields.io/github/issues-closed/isaqb-org/advanced-template.svg["Issues closed",link="https://github.com/isaqb-org/advanced-template/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aclosed+"]
-image:https://img.shields.io/github/commits-since/isaqb-org/advanced-template/latest.svg[]
+== Current Release Candidate {document-version}
+
+image:https://img.shields.io/github/last-commit/isaqb-org/examination-expert/main.svg["Last commit"]
+image:https://img.shields.io/github/contributors/isaqb-org/examination-expert.svg["Contributors",link="https://github.com/isaqb-org/examination-expert/graphs/contributors"]
+image:https://img.shields.io/github/issues/isaqb-org/examination-expert.svg["Issues",link="https://github.com/isaqb-org/examination-expert/issues"]
+image:https://img.shields.io/github/issues-closed/isaqb-org/examination-expert.svg["Issues closed",link="https://github.com/isaqb-org/examination-expert/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aclosed+"]
+image:https://img.shields.io/github/commits-since/isaqb-org/examination-expert/latest.svg[]
+[cols="<,<"]
|===
-| Version | HTML | PDF
+| German | English
+
+| link:examination-regulations-de.pdf[Prüfungsordnung (PDF)]
+| link:examination-regulations-en.pdf[Examination Regulations (PDF)]
-| German
-| link:{curriculumFileName}-de.html[HTML]
-| link:{curriculumFileName}-de.pdf[PDF]
+| link:examination-criteria-de.pdf[Kriterien (PDF)]
+| link:examination-criteria-en.pdf[Examination Criteria (PDF)]
-| English
-| link:{curriculumFileName}-en.html[HTML]
-| link:{curriculumFileName}-en.pdf[PDF]
+| link:iSAQB_CPSA_Expert_Level_Template_Roadmap_DE.docx[Vorlage für eine Roadmap (DOCX)]
+| link:iSAQB_CPSA_Expert_Level_Template_Roadmap_DE.docx[Roadmap Template (DOCX)]
+
+| link:iSAQB_CPSA_Expert_Level_Field_Report_DE.docx[Erfahrungsbericht zum Expert Level (DOCX)]
+| link:iSAQB_CPSA_Expert_Level_Field_Report_EN.docx[Field Report Expert Level (DOCX)]
|===
-== Changes compared to XXX
-- link:https://github.com/isaqb-org/advanced-template/blob/main/CHANGELOG.md[CHANGELOG.md on GitHub]
+
+== Changes compared to the previous version
+- link:https://github.com/isaqb-org/examination-expert/blob/main/CHANGELOG.md[CHANGELOG.md on GitHub]
// - link: [HTML diff to the latest curriculum] T.B.A.
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index afba109..7f93135 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4e86b92..3fa8f86 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 65dcd68..1aa94a4 100755
--- a/gradlew
+++ b/gradlew
@@ -83,10 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -133,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
@@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then
done
fi
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
diff --git a/pdf-theme b/pdf-theme
index ae6b394..50badc7 160000
--- a/pdf-theme
+++ b/pdf-theme
@@ -1 +1 @@
-Subproject commit ae6b39457c8f5cad9be5cdcede26211ec511924d
+Subproject commit 50badc7dc2dd3760eb66821916e7ee76ba421567
diff --git a/src/main/java/org/isaqb/asciidoc/Main.java b/src/main/java/org/isaqb/asciidoc/Main.java
new file mode 100644
index 0000000..698a467
--- /dev/null
+++ b/src/main/java/org/isaqb/asciidoc/Main.java
@@ -0,0 +1,166 @@
+package org.isaqb.asciidoc;
+
+import org.asciidoctor.Asciidoctor;
+import org.asciidoctor.Attributes;
+import org.asciidoctor.Options;
+import org.asciidoctor.SafeMode;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import static org.asciidoctor.Asciidoctor.Factory.create;
+
+public class Main {
+
+ private static final String PROJECT_VERSION = "projectVersion";
+ private static final String CURRICULUM_FILE_NAME = "curriculumFileName";
+ private static final String CRITERIA_FILE_NAME = "criteriaFileName";
+ private static final String INDEX_FILE_NAME = "index";
+ private static final String VERSION_DATE = "versionDate";
+ private static final String LANGUAGES = "languages";
+ private static final String[] FORMATS = {"html", "pdf"};
+
+ private static final String LANGUAGE_SEPERATOR = ",";
+
+ private static final String SOURCE_DIR = "./docs/";
+ private static final String BASE_DIR = SOURCE_DIR;
+ private static final String OUTPUT_DIR = "./build/";
+
+ private static final String ADOC = "adoc";
+ private static final String HTML = "html";
+ private static final String HTML5 = "html5";
+ private static final String PDF = "pdf";
+ private static final String ENGLISH = "EN";
+
+ public static void main(final String[] args) {
+ Objects.requireNonNull(System.getProperty(PROJECT_VERSION));
+ Objects.requireNonNull(System.getProperty(CURRICULUM_FILE_NAME));
+ Objects.requireNonNull(System.getProperty(VERSION_DATE));
+ Objects.requireNonNull(System.getProperty(LANGUAGES));
+
+ final String projectVersion = System.getProperty(PROJECT_VERSION);
+ final String curriculumFileName = System.getProperty(CURRICULUM_FILE_NAME);
+ final String criteriaFileName = System.getProperty(CRITERIA_FILE_NAME);
+ final String versionDate = System.getProperty(VERSION_DATE);
+ final String[] languages = System.getProperty(LANGUAGES).split(LANGUAGE_SEPERATOR);
+
+ Stream.of(languages).forEach(language -> convertInLanguage(
+ language,
+ projectVersion,
+ curriculumFileName,
+ versionDate
+ ));
+
+ Stream.of(languages).forEach(language -> convertInLanguage(
+ language,
+ projectVersion,
+ criteriaFileName,
+ versionDate
+ ));
+
+ convertInLanguage(
+ ENGLISH,
+ projectVersion,
+ INDEX_FILE_NAME,
+ versionDate);
+ }
+
+ private static void convertInLanguage(
+ final String language,
+ final String projectVersion,
+ final String curriculumFileName,
+ final String versionDate) {
+ Stream.of(FORMATS).forEach(format -> convertInFormat(
+ format, projectVersion,
+ curriculumFileName,
+ versionDate,
+ language
+ ));
+ }
+
+ private static void convertInFormat(
+ final String format,
+ final String projectVersion,
+ final String curriculumFileName,
+ final String versionDate,
+ final String language) {
+ try (final Asciidoctor asciidoctor = create()) {
+ final Attributes attributes = toAttributes(
+ projectVersion,
+ curriculumFileName,
+ versionDate,
+ language);
+ asciidoctor.convertDirectory(
+ List.of(new File("%s%s.%s".formatted(
+ SOURCE_DIR,
+ curriculumFileName,
+ ADOC))),
+ Options.builder()
+ .baseDir(new File(BASE_DIR))
+ .backend(toBackend(format))
+ .mkDirs(true)
+ .attributes(attributes)
+ .standalone(true)
+ .toDir(new File(OUTPUT_DIR))
+ .safe(SafeMode.UNSAFE)
+ .build());
+ renameResultAccordingToLanguage(curriculumFileName, format, language);
+ }
+ }
+
+ private static Attributes toAttributes(
+ final String projectVersion,
+ final String curriculumFileName,
+ final String versionDate,
+ final String language) {
+ final String fileVersion = "%s - %s".formatted(projectVersion, language);
+ final String documentVersion = "%s-%s".formatted(fileVersion, versionDate);
+
+ final Map attributes = new HashMap<>() {{
+ put("icons" , "font");
+ put("version-label" , "");
+ put("revnumber" , fileVersion);
+ put("revdate" , versionDate);
+ put("document-version" , documentVersion);
+ put("currentDate" , versionDate);
+ put("language" , language);
+ put("curriculumFileName", curriculumFileName);
+ put("debug_adoc" , false);
+ put("pdf-themesdir" , "../pdf-theme/themes");
+ put("pdf-fontsdir" , "../pdf-theme/fonts");
+ put("pdf-theme" , "isaqb");
+ put("stylesheet" , "../html-theme/adoc-github.css");
+ put("stylesheet-dir" , "../html-theme");
+ put("data-uri" , true);
+ put("allow-uri-read" , true);
+ }};
+
+ return Attributes.builder().attributes(attributes).build();
+ }
+
+ private static String toBackend(final String format) {
+ return switch (format) {
+ case HTML -> HTML5;
+ case PDF -> PDF;
+ default -> throw new IllegalArgumentException("Unknown target format %s".formatted(format));
+ };
+ }
+
+ private static void renameResultAccordingToLanguage(
+ final String fileName,
+ final String format,
+ final String language) {
+ final File original = new File("%s%s.%s".formatted(OUTPUT_DIR, fileName, format));
+ final File renamed = new File("%s%s-%s.%s".formatted(OUTPUT_DIR, fileName, language.toLowerCase(), format));
+ if (!original.exists()) {
+ System.err.printf("Failed to rename result file %s as it does not exist", original.getAbsolutePath());
+ } else if (!original.renameTo(renamed)) {
+ System.err.printf("Failed to rename result file %s to %s%n", original.getName(), renamed.getName());
+ }
+ original.deleteOnExit();
+ }
+}