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(); + } +}