Swagger UI is a powerful tool for visualizing and interacting with your API’s resources. While it offers a sleek default design, you might want to personalize its appearance to align with your brand. One effective way to achieve this is by customizing the fonts.
Why Customize Fonts?
Customizing fonts enhances the user experience by making the interface more visually appealing and consistent with your brand identity. Moreover, it can improve readability and accessibility for users with specific needs.
Create Swagger specifications.

Swagger specifications to AsciiDoc.
AsciiDoc is a plain text markup language designed for writing technical content. It includes rich semantic elements and offers features for modularizing and reusing content.

Adds a Maven dependency in “pom.xml”.
<!-- https://mvnrepository.com/artifact/org.openapitools/openapi-generator --> <dependency> <groupId>org.openapitools</groupId> <artifactId>openapi-generator</artifactId> <version>7.3.0</version> </dependency>
Creates a Java class to convert Swagger specifications to AsciiDoc.
import org.openapitools.codegen.DefaultGenerator; import org.openapitools.codegen.config.CodegenConfigurator; import java.io.File; import java.util.HashMap; import java.util.Map; public class OpenApiToAsciidoc { public static void main(String[] args) { OpenApiToAsciidoc asciidoc = new OpenApiToAsciidoc(); asciidoc.jsonToAsciidoc("D:/workspace/document/", "api-docs.json"); } public void jsonToAsciidoc(String swaggerPath, String json) { System.out.println("Converting OpenAPI JSON to AsciiDoc..."); // Input OpenAPI JSON file path String inputFile = swaggerPath + File.separator + json; // Output AsciiDoc file path String outputFile = swaggerPath + File.separator + "asciidoc"; Map<String, Object> options = new HashMap<String, Object>(); options.put("openapi", "3.0.1"); options.put("dateLibrary", "java21"); options.put("enumPropertyNaming", "UPPERCASE"); options.put("hideGenerationTimestamp", true); options.put("version","1.0.0"); options.put("version-label","1.0.0"); options.put("license-id","Apache-2.0"); options.put("developerEmail","admin@example.com"); // Configure CodegenConfigurator CodegenConfigurator configurator = new CodegenConfigurator() .setInputSpec(inputFile) .setOutputDir(outputFile) .setGeneratorName("asciidoc") .setSkipOperationExample(true) .setAdditionalProperties(options) ; // Generate AsciiDoc file DefaultGenerator generator = new DefaultGenerator(); generator.opts(configurator.toClientOptInput()); generator.generate(); System.out.println("Conversion completed. AsciiDoc file generated at: " + outputFile); } }
Executes a Java class to create an AsciiDoc.

In the directory “D:/workspace/document/”, asciidoc
A folder was created.

Swagger specifications to HTML.
Convert to HTML using a Java class with a third-party library called “asciidoctor” or create HTML from the Swagger editor website. Swagger Editor
Convert to HTML5 with a Java class.
Adds a Maven dependency in “pom.xml”.
<!-- https://mvnrepository.com/artifact/org.asciidoctor/asciidoctorj --> <dependency> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctorj</artifactId> <version>2.5.11</version> </dependency>
Creates a Java class to convert Swagger specifications to HTML.
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Options; import org.asciidoctor.SafeMode; import java.io.File; public class AsciidoctorHtml5Generator { final static String swaggerPath = "D:/workspaces/documents/"; public static void main(String[] args) { // Output HTML file path String outputFilePath = swaggerPath + "/asciidoc/index.html"; // Configure Asciidoctor instance try (Asciidoctor asciidoctor = Asciidoctor.Factory.create()) { // Convert AsciiDoc to HTML5 asciidoctor.convertFile(new File(swaggerPath + "/asciidoc/index.adoc"), Options.builder().mkDirs(true) .backend("html5") .toFile(new File(outputFilePath)) .safe(SafeMode.SAFE) //allowed to generate pdf inside this directory only. .build()); System.out.println("HTML file generated successfully!"); } catch (Exception e) { System.out.println(e.getMessage()); } } }
Fix this problem in 2 options.
Jul 30, 2024 3:24:09 PM org.asciidoctor.jruby.internal.JRubyAsciidoctor convertFile SEVERE: (SecurityError) to_dir D:\workspaces\documents\asciidoc\index.html is outside of jail: D:/workspaces/swagger-converter (disallowed in safe mode) org.jruby.exceptions.SecurityError: (SecurityError) to_dir D:\workspaces\documents\asciidoc\index.html is outside of jail: D:/workspaces/swagger-converter (disallowed in safe mode)
1. Recommend moving the asciidoc directory to the project directory.
2. Change the safe mode to UNSAFE.
asciidoctor.convertFile(new File(swaggerPath + "/asciidoc/index.adoc"), Options.builder().mkDirs(true) .backend("html5") .toFile(new File(outputFilePath)) .safe(SafeMode.UNSAFE) .build());
Executes a Java class to create an HTML5.
HTML file generated successfully!

The directory “index.html” was created.

Swagger specifications to PDF.
The developer can convert to PDF using a Java class with a third-party library called “asciidoctor” or create PDF from the Swagger To Pdf website.

Convert to PDF with a Java class.
The developer adds a Maven dependency in “pom.xml”.
<!-- https://mvnrepository.com/artifact/org.asciidoctor/asciidoctorj --> <dependency> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctorj</artifactId> <version>2.5.11</version> </dependency> <dependency> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctorj-pdf</artifactId> <version>2.3.13</version> </dependency>
The developer creates a Java class to convert Swagger specifications to PDF.
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Options; import org.asciidoctor.SafeMode; import org.asciidoctor.jruby.internal.JRubyAsciidoctor; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; public class SwaggerToPDF { final static String swaggerPath = "D:/workspaces/swagger-converter/documents/"; final static String json = "api-docs.json"; public static void main(String[] args) { //create asciidoc file OpenApiToAsciidoc asciidoc = new OpenApiToAsciidoc(); asciidoc.jsonToAsciidoc(swaggerPath, json); // Initialize Asciidoctor instance Asciidoctor asciidoctor = JRubyAsciidoctor.create(); SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); //output path to a pdf file. File pdf = new File(swaggerPath + "/pdf/user-manual-openapi_" + df.format(new Date()) + ".pdf"); System.out.println("Start generating pdf with Asciidoctor: index.adoc to " + pdf.getAbsolutePath()); // Convert AsciiDoc to PDF asciidoctor.convertFile(new File(swaggerPath + "/asciidoc/index.adoc"), Options.builder().mkDirs(true) .backend("pdf") .toFile(pdf) .safe(SafeMode.SAFE) //allowed to generate pdf inside this directory only. .build()); System.out.println("PDF is created!"); } }
The developer executes a Java class to create a PDF.
Converting OpenAPI JSON to AsciiDoc... [main] INFO org.openapitools.codegen.DefaultGenerator - Generating with dryRun=false [main] INFO org.openapitools.codegen.DefaultGenerator - OpenAPI Generator: asciidoc (documentation) [main] INFO org.openapitools.codegen.DefaultGenerator - Generator 'asciidoc' is considered stable. [main] WARN org.openapitools.codegen.languages.AsciidocDocumentationCodegen - base part for include markup lambda not found: null as D:\workspaces\swagger-converter\null [main] WARN org.openapitools.codegen.languages.AsciidocDocumentationCodegen - base part for include markup lambda not found: null as D:\workspaces\swagger-converter\null [main] INFO org.openapitools.codegen.TemplateManager - writing file D:\workspaces\swagger-converter\documents\asciidoc\index.adoc [main] INFO org.openapitools.codegen.TemplateManager - Skipped D:\workspaces\swagger-converter\documents\asciidoc\.openapi-generator-ignore (Skipped by supportingFiles options supplied by user.) [main] INFO org.openapitools.codegen.TemplateManager - writing file D:\workspaces\swagger-converter\documents\asciidoc\.openapi-generator\VERSION [main] INFO org.openapitools.codegen.TemplateManager - writing file D:\workspaces\swagger-converter\documents\asciidoc\.openapi-generator\FILES ################################################################################ # Thanks for using OpenAPI Generator. # # Please consider donation to help us maintain this project 🙏 # # https://opencollective.com/openapi_generator/donate # ################################################################################ Conversion completed. AsciiDoc file generated at: D:/workspaces/swagger-converter/documents/\asciidoc Start generating pdf with Asciidoctor: index.adoc to D:\workspaces\swagger-converter\documents\pdf\user-manual-openapi_20240730.pdf Jul 30, 2024 4:14:47 PM uri:classloader:/gems/asciidoctor-2.0.20/lib/asciidoctor/substitutors.rb sub_macros INFO: possible invalid reference: String PDF is created!


The developer changed the content inside the “api-docs.json” to character UTF-8, which is not supported by the asciidoctor default font.
{ "openapi":"3.0.1", "info":{ "title":"OpenAPI definition", "version":"v0" }, "servers":[ { "url":"http://localhost:8080", "description":"Generated server url" } ], "tags":[ { "name":"สร้างข้อมูลผู้ใช้", "description":"Manage user profile data." } ], "paths":{ "/user":{ "post":{ "tags":[ "บริการสร้างข้อมูลผู้ใช้" ], "summary":"สร้างข้อมูลผู้ใช้งานระบบ", "description":"สร้างข้อมูลผู้ใช้งานระบบและบันทึกลงฐานข้อมูล", "operationId":"create", "requestBody":{ "content":{ "application/json":{ "schema":{ "$ref":"#/components/schemas/UserProfileBean" } } }, "required":true }, ....
When creating a PDF file.

The characters in the PDF file are Unrecognized characters.
The developer must use a custom font that supports UTF-8 characters.
Swagger specifications to PDF with a custom font.
The developer downloads the font and creates a font directory. Create “custom-theme.yml”.
D:/workspaces/swagger-converter/documents └───fonts ├───THSarabun Bold.ttf ├───THSarabun BoldItalic.ttf ├───THSarabun Italic.ttf └───THSarabun.ttf └───themes ├───custom-theme.yml
extends: default base: font_family: THSarabun font: catalog: THSarabun: normal: THSarabun.ttf bold: THSarabun Bold.ttf italic: THSarabun Italic.ttf bold_italic: THSarabun BoldItalic.ttf Noto Serif: normal: GEM_FONTS_DIR/notoserif-regular-subset.ttf bold: GEM_FONTS_DIR/notoserif-bold-subset.ttf italic: GEM_FONTS_DIR/notoserif-italic-subset.ttf bold_italic: GEM_FONTS_DIR/notoserif-bold_italic-subset.ttf # M+ 1mn supports ASCII and the circled numbers used for conums M+ 1mn: normal: GEM_FONTS_DIR/mplus1mn-regular-subset.ttf bold: GEM_FONTS_DIR/mplus1mn-bold-subset.ttf italic: GEM_FONTS_DIR/mplus1mn-italic-subset.ttf bold_italic: GEM_FONTS_DIR/mplus1mn-bold_italic-subset.ttf fallback: - THSarabun
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Attributes; import org.asciidoctor.Options; import org.asciidoctor.SafeMode; import org.asciidoctor.jruby.internal.JRubyAsciidoctor; import java.io.File; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; public class SwaggerToPDFWithCustomFont { final static String swaggerPath = "D:/workspaces/swagger-converter/documents/"; final static String json = "api-docs.json"; public static void main(String[] args) { //create asciidoc file OpenApiToAsciidoc asciidoc = new OpenApiToAsciidoc(); asciidoc.jsonToAsciidoc(swaggerPath, json); // Initialize Asciidoctor instance Asciidoctor asciidoctor = JRubyAsciidoctor.create(); // Set UTF-8 encoding Attributes attributes = Attributes.builder() .attribute("pdf-fontsdir", swaggerPath + File.separator + "fonts;GEM_FONTS_DIR") .attribute("pdf-theme", swaggerPath + File.separator + "themes/custom-theme.yml") .attribute("theme", "custom-theme") .attribute("Encoding", "UTF-8") .attribute("charset", StandardCharsets.UTF_8) .build(); System.out.printf("file.encoding: %s%n", Charset.defaultCharset().displayName()); System.out.printf("defaultCharset: %s%n", Charset.defaultCharset().name()); SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); File pdf = new File(swaggerPath + "/pdf/user-manual-openapi_" + df.format(new Date()) + ".pdf"); System.out.println("Start generating pdf with Asciidoctor: index.adoc to " + pdf.getAbsolutePath()); // Convert AsciiDoc to PDF asciidoctor.convertFile(new File(swaggerPath + "/asciidoc/index.adoc"), Options.builder().mkDirs(true) .backend("pdf") .toFile(pdf) .safe(SafeMode.SAFE) //allowed to generate pdf inside this directory only. .attributes(attributes) .build()); System.out.println("PDF is created!"); } }
The developer executes a Java class to create a PDF with a custom font.

The characters in the PDF file are readable.
Additional Tips
- Fallback Fonts: Always specify fallback fonts to ensure text remains legible if the custom font fails to load.
- Performance Considerations: Using web fonts can impact page load times. Therefore, optimize font loading by selecting only the necessary font weights and styles.
- Accessibility: Choose fonts that are easy to read and consider users with visual impairments.
Finally
Customizing fonts in Swagger UI is a straightforward process that can significantly enhance the look and feel of your API documentation. By following the steps outlined above, you can create a more engaging and accessible user interface.